eval

eval.txt 适用于 Vim 8.2 版本。 最近更新: 2021年4月 VIM 参考手册 by Bram Moolenaar 译者: Willis 表达式求值 expression expr E15 eval 用户手册第 41 章 usr_41.txt 有使用表达式的介绍。 注意: 表达式求值可以在编译时关闭。如果你这么做,本文档介绍的特性就不复存在。见 +evalno-eval-feature 。 此文件介绍后向兼容的 Vim 脚本。关于执行快很多、支持类型检查还有更多优点的 Vim9 脚本,参见 vim9.txt 。 1. 变量 variables 1.1 变量类型 1.2 函数引用 Funcref 1.3 列表 Lists 1.4 字典 Dictionaries 1.5 blob Blobs 1.6 变量的更多细节 more-variables 2. 表达式语法 expression-syntax 3. 内部变量 internal-variables 4. 内建函数 functions 5. 定义函数 user-functions 6. 花括号名字 curly-braces-names 7. 命令 expression-commands 8. 例外处理 exception-handling 9. 示例 eval-examples 10. Vim 脚本版本 vimscript-version 11. 不包含 +eval 特性 no-eval-feature 12. 沙盘 (sandbox) eval-sandbox 13. 文本锁 textlock 测试支持的文档可见 testing.txt 。 剖视的文档可见 profiling

1. 变量 variables

1.1 变量类型 E712 E896 E897 E899 有十种类型的变量: Number Integer 数值 32 位或 64 位带符号整数。 expr-number 位数可以 v:numbersize 得到。 示例: -123 0x10 0o177 0b1011 浮点数 带小数的数值。 floating-point-format Float {仅当编译时加入 +float 特性才有效} 示例: 123.456 1.15e-6 -1.1e3 E928 字符串 NUL 结尾的 8 位无符号字符 (即字节) 的串。 expr-string 示例: "ab\txx\"--" 'x-z''a,c' 列表 项目的有序的序列,详见 List 。 示例: [1, 2, ['a', 'b']] 字典 关联的无序数组: 每个项目包含一个键和一个值。 Dictionary 示例: {'blue': "#0000ff", 'red': "#ff0000"} #{blue: "#0000ff", red: "#ff0000"} 函数引用 指向一个函数的引用 Funcref 。 示例: function("strlen") 可以绑定到字典或参数上,这样就类似于一个偏函数。 示例: function("Callback", [arg], myDict) 特殊 v:falsev:truev:nonev:null Special 作业 用于作业,见 job_start() Job Jobs 通道 用于通道,见 ch_open() Channel Channels blob 二进制大对象 (Binary Large Object)。存储任意字符序列。详见 Blob 示例: 0zFF00ED015DAF 0z 是空 blob。 数值和字符串类型之间会根据使用的情况自动转换。 数值到字符串的转换使用数值的 ASCII 表示。例如: 数值 123 --> 字符串 "123" 数值 0 --> 字符串 "0" 数值 -1 --> 字符串 "-1" octal 只在老式 Vim 脚本中进行字符串到数值的转换,Vim9 脚本不进行转换。转换时,把字符 串开头的一系列数字位转换成数值。可以识别十六进制 "0xf9"、八进制 "017" 或 "0o17" 和二进制 "0b10" 形式的数值 注意: scriptversion-4 不识别 "0" 开头的八进制。0o 记法需要 8.2.0886 补丁。 如果字符串不以数字开始,则结果为零。 例如: 字符串 "456" --> 数值 456 字符串 "6bar" --> 数值 6 字符串 "foo" --> 数值 0 字符串 "0xf1" --> 数值 241 字符串 "0100" --> 数值 64 字符串 "0b101" --> 数值 5 字符串 "-8" --> 数值 -8 字符串 "+8" --> 数值 0 要强制从字符串转换到数值,给它加零: :echo "0100" + 0 64 要避免开头的零导致八进制的转换,或者想换不同的基底,用 str2nr() TRUE FALSE Boolean 布尔型的操作使用数值类型。零代表假值 (FALSE),非零代表真值 (TRUE)。也可用 v:falsev:true 。Vim9 脚本中可用 falsetrue 。函数返回 TRUE 时相当 于数值一,FALSE 相当于数值零。 注意 在命令: :if "foo" :" _不_ 执行 里,"foo" 被转换成 0,也就是假值。如果字符串以非零数字开始,则代表真值: :if "8foo" :" 执行 要测试字符串非空,应该使用 empty(): :if !empty("foo") falsy truthy 表达式可用作条件,这里忽略类型,而仅仅判断该值是 "某种程序是真的" 或 "某种程度 是假的"。准假值 (falsy) 为: 数值零 空字符串、blob、列表或字典 其它值均为准真值 (truthy)。例如: 0 准假值 1 准真值 -1 准真值 0.0 准假值 0.1 准真值 '' 准假值 'x' 准真值 [] 准假值 [0] 准真值 {} 准假值 #{x: 1} 准真值 0z 准假值 0z00 准真值 non-zero-arg 函数参数和 TRUE 行为通常略有差异: 如果参数存在且其值为非零数值、 v:true 或 非空字符串,则视之为真值。 注意 " " 和 "0" 也是非空字符串,亦应视为真值。列表、字典和浮点数不是数值或字符 串,因而视为假值。 E745 E728 E703 E729 E730 E731 E908 E910 E913 E974 E975 E976 ListDictionaryFuncrefJobChannelBlob 类型不会自动进行转 换。 E805 E806 E808 混合数值和浮点数的计算时,数值转换为浮点数。否则没有自动到浮点数的转换。用 str2float() 可转换字符串到浮点数,printf() 从浮点数到字符串,float2nr() 则从浮 点数到数值。 E891 E892 E893 E894 E907 E911 E914 期待浮点数的地方也可用数值代替,但其它都不行。 no-type-checking 试图改变变量类型不会报错。 1.2 函数引用 Funcref E695 E718 函数引用变量可以通过 function() 函数、 funcref() 函数或者 expr-lambda 匿 名表达式得到。可以在表达式里用它来代替函数名,在围绕参数的括号之前,以调用它引 用的函数。例如: :let Fn = function("MyFunc") :echo Fn() E704 E705 E707 函数引用变量必须以大写字母、"s:"、"w:"、"t:" 或 "b:" 开始。可以用 "g:",但后面 的名字必须以大写开始。函数引用变量不能和任何函数重名。 特例是可以定义函数并直接把它的函数引用赋给字典的一个项目。例如: :function dict.init() dict : let self.val = 0 :endfunction 该字典的键可以用小写字母开始。这里不用实际的函数名。另见 numbered-function 。 函数引用可以用 :call 命令调用: :call Fn() :call dict.init() 所引用的函数的名字可以用 string() 得到, :let func = string(Fn) 你可以用 call() 来调用函数引用并用一个列表变量来传递参数: :let r = call(Fn, mylist) Partial 函数引用可以选择绑定字典和/或参数,也叫偏函数。通过向 function() 或 funcref() 提供字典和/或参数完成。调用函数时,该字典和/或参数被传入函数。例如: let Cb = function('Callback', ['foo'], myDict) call Cb('bar') 这类似于如下方式地调用函数: call myDict.Callback('foo', 'bar') ch_open() 这样传递函数作为参数的情况,这很有用。 注意 把函数作为字典的一个成员时,也会绑定函数到字典: let myDict.myFunction = MyFunction call myDict.myFunction() 这里,调用 "myFunction" 成员时,MyFunction() 会通过 "self" 得到 myDict。如果把 "myFunction" 赋给 otherDict 并调用之,则相应绑定到 otherDict 上: let otherDict.myFunction = myDict.myFunction call otherDict.myFunction() 现在 "self" 变成了 "otherDict"。但字典如果是显式绑定,这不会发生: let myDict.myFunction = function(MyFunction, myDict) let otherDict.myFunction = myDict.myFunction call otherDict.myFunction() 这里 "self" 还是 "myDict",因为是通过显式绑定的。 1.3 列表 list List Lists E686 列表是项目的有序序列。项目可以是任何类型,用索引号可以进行访问。可以在序列的任 何位置上增加或者删除项目。 列表建立 E696 E697 列表用方括号里逗号分隔的项目序列建立。例如: :let mylist = [1, two, 3, "four"] :let emptylist = [] 项目可以是任何表达式。用列表作为项目就能建立列表的列表: :let nestlist = [[11, 12], [21, 22], [31, 32]] 忽略末项之后额外的逗号。 列表索引 list-index E684 在列表之后的方括号中放上索引号可以访问列表项目。索引从零开始,也就是说,第一个 项目的索引值为零。 :let item = mylist[0] " 得到第一个项目: 1 :let item = mylist[2] " 得到第三个项目: 3 如果返回的项目本身是列表,可以重复这样的操作: :let item = nestlist[0][1] " 得到第一个列表的第二个项目: 12 负索引从尾端开始计算。索引 -1 指向列表的最后一个项目,-2 指向倒数第二个项目, 依此类推。 :let last = mylist[-1] " 得到最后一个项目: "four" 要避免非法索引值产生的错误,用 get() 函数。如果项目不存在,它返回零或者你指 定的缺省值: :echo get(mylist, idx) :echo get(mylist, idx, "NONE") 列表连接 list-concatenation 两个列表可以用 "+" 操作符连接: :let longlist = mylist + [5, 6] :let mylist += [7, 8] 要在前面或后面附加项目,在项目外面加上 [] 从而把它变为一个列表。要改变列表内部 的值,见下 list-modification子列表 sublist 列表的一部分可以通过指定首末两个索引获得,方括号内以冒号分隔两者: :let shortlist = mylist[2:-1] " 得到列表 [3, "four"] 首索引的省略类似于用 0。末索引的省略类似于用 -1。 :let endlist = mylist[2:] " 从项目 2 到结束: [3, "four"] :let shortlist = mylist[2:2] " 单个项目的列表: [3] :let otherlist = mylist[:] " 复制列表 注意末索引是闭的。如果希望用开的索引,可用 slice() 方法。 如果首索引在列表末项之后或者末索引小于首索引,返回空列表。没有错误信息。 如果末索引大于等于列表的长度,使用列表长度减一: :let mylist = [0, 1, 2, 3] :echo mylist[2:8] " 返回: [2, 3] 注意: mylist[s:e] 意味着用变量 "s:e" 作为索引。在 ":" 之前用单个字母作为变量要 小心。需要的话加上空格: mylist[s : e]。 列表同一 list-identity 如果变量 "aa" 是列表,把它赋给另一个变量 "bb" 后,两个变量指向同一列表。因此, 对列表 "aa" 的修改也同时修改了 "bb": :let aa = [1, 2, 3] :let bb = aa :call add(aa, 4) :echo bb [1, 2, 3, 4] copy() 函数可以复制列表。如上所述,用 [:] 也可。这种方式建立列表的浅备份: 改 变列表中的列表项目仍然会修改复制列表的相应项目: :let aa = [[1, 'a'], 2, 3] :let bb = copy(aa) :call add(aa, 4) :let aa[0][1] = 'aaa' :echo aa [[1, aaa], 2, 3, 4] :echo bb [[1, aaa], 2, 3] 要建立一个完全独立的列表,用 deepcopy() 。它递归地建立列表值的备份。最深可达 100 层。 可用操作符 "is" 检查两个变量是否指向同一个列表。"isnot" 刚好相反。与此对照, "==" 比较两个列表的值是否相同。 :let alist = [1, 2, 3] :let blist = [1, 2, 3] :echo alist is blist 0 :echo alist == blist 1 比较列表时 注意: 如果长度相同,所有项目用 "==" 的比较的结果也相同,两个列表就 认为相同。有一个例外: 数值和字符串总被认为不相同。这里不进行自动类型转换,而在 变量间直接用 "==" 却不是如此。例如: echo 4 == "4" 1 echo [4] == ["4"] 0 因此可以说,列表的比较比数值和字符串的比较更严格。你同样可以用这种方式比较简单 类型的值,把它们放到列表里就行了: :let a = 5 :let b = "5" :echo a == b 1 :echo [a] == [b] 0 列表解包 要给列表项目解包,即把它们分别存入单独的变量,用方括号把变量括起来,如同把它们 当作列表项目: :let [var1, var2] = mylist 如果变量和列表的项目数量不同,报错。要处理列表中所有额外的项目,加上 ";" 和单 个变量: :let [var1, var2; rest] = mylist 它的工作方式就像: :let var1 = mylist[0] :let var2 = mylist[1] :let rest = mylist[2:] 如果只有两个项目,不会报错。这时 "rest" 成为空表。 列表修改 list-modification 要修改列表的指定项目,用 :let : :let list[4] = "four" :let listlist[0][3] = item 要修改列表的一部分,可以指定要修改的首末项目。提供的值的个数必须不少于该范围内 的项目数: :let list[3:5] = [3, 4, 5] 给列表增加和删除项目可以通过函数完成。一些例子如下: :call insert(list, 'a') " 在最前面插入 'a' :call insert(list, 'a', 3) " 在 list[3] 前插入项目 'a' :call add(list, "new") " 在最后附加字符串项目 :call add(list, [1, 2]) " 在最后附加新的列表项目 :call extend(list, [1, 2]) " 在最后扩展列表,使之多包含两个项目 :let i = remove(list, 3) " 删除项目 3 :unlet list[3] " 同上 :let l = remove(list, 3, -1) " 从项目 3 删除到最后 :unlet list[3 : ] " 同上 :call filter(list, 'v:val !~ "x"') " 删除有 'x' 的项目 改变列表项目的顺序: :call sort(list) " 按字母给列表排序 :call reverse(list) " 反转项目的顺序 :call uniq(sort(list)) " 排序并删除重复项 For 循环 :for 循环为每个列表、字符串或 Blob 中的项目执行命令。一个变量被依次设为每个 列表项目。例如: :for item in mylist : call Doit(item) :endfor 它的工作方式就像: :let index = 0 :while index < len(mylist) : let item = mylist[index] : :call Doit(item) : let index = index + 1 :endwhile 如果你只是想要修改每个列表项目, map() 函数比 for 循环简单得多。 就像 :let 命令, :for 也可以接受变量的列表。这需要参数是列表的列表。 :for [lnum, col] in [[1, 3], [2, 8], [3, 0]] : call Doit(lnum, col) :endfor 这就像对列表的每个项目使用了 :let 命令。重复一次,类型必须相同,否则会报错。 也可以用变量保存列表变量的其余项目: :for [i, j; rest] in listlist : call Doit(i, j) : if !empty(rest) : echo "remainder: " . string(rest) : endif :endfor 对 Blob 而言,每次访问一个字节。 对字符串而言,每次访问一个字符,包含组合字符在内。例如: for c in text echo 'This character is ' .. c endfor 列表的相关函数 E714 可用于列表的函数: :let r = call(funcname, list) " 调用带参数列表的函数 :if empty(list) " 检查 list 是否为空 :let l = len(list) " list 项目的数量 :let big = max(list) " list 项目的最大值 :let small = min(list) " list 项目的最小值 :let xs = count(list, 'x') " 计算 list 里 'x' 出现的次数 :let i = index(list, 'x') " list 第一个 'x' 的位置 :let lines = getline(1, 10) " 得到缓冲区十行文本行 :call append('$', lines) " 附加若干文本行到缓冲区尾部 :let list = split("a b c") " 用字符串中的项目建立列表 :let string = join(list, ', ') " 用 list 项目构造字符串 :let s = string(list) " list 的字符串表示 :call map(list, '">> " . v:val') " 在每个项目前加上 ">> " 不要忘记组合使用不同功能可以简化任务。例如,要计算列表中所有数值的总和: :exe 'let sum = ' . join(nrlist, '+') 1.4 字典 dict Dict Dictionaries Dictionary 字典是关联数组: 每个项目有一个键和一个值。用键可以定位项目,而项目的存储不能确 定任何特定顺序。 字典建立 E720 E721 E722 E723 字典通过花括号里逗号分隔的项目列表建立。每个项目包含以冒号分隔的键和值。一个键 只能出现一次。例如: :let mydict = {1: 'one', 2: 'two', 3: 'three'} :let emptydict = {} E713 E716 E717 键必须是字符串。用数值也可以,但它总被自动转换为字符串。所以字符串 '4' 和数值 4 总会找到相同的项目。注意 字符串 '04' 和数值 04 是不一样的,因为后者被转换成 字符串 '4'。空字符串也可用作键。 literal-Dict #{} 要不想给每个键都围上引号,可以用 #{} 形式。这要求键只包含 ASCII 字母、数位、 '-' 和 '_'。例如: :let mydict = #{zero: 0, one_key: 1, two-key: 2, 333: 3} 注意 这里的 333 代表字符串 "333"。空键用 #{} 是不可能的。 值可以是任何表达式。如果值本身是字典,就可以建立嵌套的字典: :let nestdict = {1: {11: 'a', 12: 'b'}, 2: {21: 'c'}} 忽略末项之后的逗号。 访问项目 常见的访问项目的方式是把键放入方括号: :let val = mydict["one"] :let mydict["four"] = 4 用这种方式可以给已存在的字典增加新项目,这和列表不同。 如果键只包含字母、数字和下划线,可以使用如下形式 expr-entry : :let val = mydict.one :let mydict.four = 4 因为项目可以是包括列表和字典的任何类型,你可以反复使用索引和键进行访问: :echo dict.key[idx].key 字典到列表的转换 你可以循环遍历字典的所有项目。为此,你需要把字典转为列表,然后把它传递给 :for 。 通常,你期望遍历所有的键,用 keys() 函数就可以了: :for key in keys(mydict) : echo key . ': ' . mydict[key] :endfor 键列表没有经过排序。你可能希望先进行排序: :for key in sort(keys(mydict)) 要遍历所有的值,用 values() 函数: :for v in values(mydict) : echo "value: " . v :endfor 如果你想同时得到键和值,用 items() 函数。它返回一个列表,其中每个项目是两个 项目的列表: 键和值: :for [key, value] in items(mydict) : echo key . ': ' . value :endfor 字典同一 dict-identity 就像列表那样,你需要用 copy()deepcopy() 来构造字典的备份。否则,赋值产 生的结果会引用同一个字典: :let onedict = {'a': 1, 'b': 2} :let adict = onedict :let adict['a'] = 11 :echo onedict['a'] 11 如果所有的键-值组对的比较结果相同,两个字典比较的结果也相同。详情见 list-identity字典修改 dict-modification 要修改字典已经存在的项目或者增加新的项目,用 :let : :let dict[4] = "four" :let dict['one'] = item 从字典里删除项目可以通过 remove():unlet 完成。 从 dict 里删除键 "aaa" 的项目有三种方法: :let i = remove(dict, 'aaa') :unlet dict.aaa :unlet dict['aaa'] 两个字典的合并可以用 extend() : :call extend(adict, bdict) 这使得 adict 得到扩展,加入所有的 bdict 项目。对于重复的键,adict 项目被覆盖。 可选的第三个参数可以改变这一点。 注意 这不影响字典项目的顺序,不要希望 ":echo adict" 会先显示原有 adict 项目, 然后再显示 bdict 的项目。 可用 filter() 从字典里删除多个项目: :call filter(dict, 'v:val =~ "x"') 会删除 "dict" 里所有值不匹配 "x" 的项目。 也可这样来删除所有的项目: call filter(dict, 0) 字典函数 Dictionary-function self E725 E862 定义函数时,如果带有 "dict" 属性,可以以一种特殊方式使用字典。例如: :function Mylen() dict : return len(self.data) :endfunction :let mydict = {'data': [0, 1, 2, 3], 'len': function("Mylen")} :echo mydict.len() 这类似于面向对象编程的方法。字典项目用作 Funcref 。局部变量 "self" 引用函数所 在的字典。 字典里也可以加入指向没有 "dict" 属性的函数的函数引用,不过这时无法使用 "self" 变量。 numbered-function anonymous-function 要避免额外的函数名,可以定义时直接赋给字典: :let mydict = {'data': [0, 1, 2, 3]} :function mydict.len() : return len(self.data) :endfunction :echo mydict.len() 该函数会得到一个编号,而 dict.len 的值是指向此函数的 Funcref 。该函数只能通过 Funcref 访问。如果没有任何 Funcref 引用,它会被自动删除。 编号函数不一定要有 "dict" 属性。 如果你的编号函数有错,可以用一个技巧知道它是什么内容。假定函数是 42,命令为: :function {42} 字典相关函数 E715 可以用于字典的函数: :if has_key(dict, 'foo') " 如果 dict 有带 "foo" 键的项目则为真 :if empty(dict) " 如果 dict 为空则为真 :let l = len(dict) " dict 项目的数量 :let big = max(dict) " dict 项目的最大值 :let small = min(dict) " dict 项目的最小值 :let xs = count(dict, 'x') " 统计 dict 里 'x' 出现的数目 :let s = string(dict) " dict 的字符串表示 :call map(dict, '">> " . v:val') " 在每个项目前加上 ">> " 1.5 blob blob Blob Blobs E978 blob 是一个二进制对象。例如,可用来读取文件的映像并通过通道发送。 blob 基本类似于数值的 List ,其中每个数值是个 8 位字节的值,从 0 到 255。 blob 建立 可用 blob-literal 建立 blob: :let b = 0zFF00ED015DAF 字节 (一对十六进制字符) 之间可以插入点号以提高可读性。不改变值本身: :let b = 0zFF00.ED01.5DAF readfile() 可从文件里读取 blob,其中 {type} 参数设为 "B"。例如: :let b = readfile('image.png', 'B') ch_readblob() 函数可从通道读取 blob。 blob 索引 blob-index E979 blob 之后用方括号放上索引可以访问 blob 中的字节。索引从零开始,因而首个字节的 索引为零。 :let myblob = 0z00112233 :let byte = myblob[0] " 读取首个字节: 0x00 :let byte = myblob[2] " 读取第三个字节: 0x22 负数索引从末尾开始计算。索引 -1 引用 blob 最后一个字节,-2 是倒数第二个字节, 等等。 :let last = myblob[-1] " 读取最后一个字节: 0x33 get() 函数可以避免索引值非法的错误,如果索引不可用,返回 -1 或你指定的缺 省值: :echo get(myblob, idx) :echo get(myblob, idx, 999) blob 遍历 :for 循环为 blob 的每个字节执行命令。其中循环变量设为 blob 的每个字节。例如: :for byte in 0z112233 : call Doit(byte) :endfor 会分别用 0x11、0x22 和 0x33 调用 Doit()。 blob 连接 用 "+" 操作符可以连接两个 blob: :let longblob = myblob + 0z4455 :let myblob += 0z6677 要在原位修改 blob,可见下述的 blob-modificationblob 部分 blob 的一部分可用在方括号内指定以冒号分隔的开始处和结束处的索引来获得: :let myblob = 0z00112233 :let shortblob = myblob[1:2] " 返回 0z1122 :let shortblob = myblob[2:-1] " 返回 0z2233 开始索引要是省略相当于零。结束索引要是省略相当于 -1。 :let endblob = myblob[2:] " 从项目 2 到尾: 0z2233 :let shortblob = myblob[2:2] " 一个字节的 blob: 0z22 :let otherblob = myblob[:] " 建立 blob 的备份 如果开始索引超过 blob 的最后字节,或者结束索引在开始索引之前,返回空 blob。不 报错。 如果结束索引等于或大于列表长度,使用长度减一: :echo myblob[2:8] " 返回: 0z2233 blob 修改 blob-modification 要修改 blob 的特定字节,可以这么用 :let : :let blob[4] = 0x44 如果索引是 blob 最后索引加一,附加到尾部。再大的索引会报错。 要改变字节序列,可用 [:] 记法: let blob[1:3] = 0z445566 被替换字节序列的长度必须和提供的值相等。 E972 要修改 blob 的部分,指定要修改的开始和结束字节。新值必须和范围的字节数相同: :let blob[3:5] = 0z334455 也可用 add()remove()insert() 函数。 blob 同一 blob 间可以比较是否值相等: if blob == 0z001122 也可以比较是否同一引用: if blob is otherblob blob-identity E977 当 "aa" 变量是 blob 而把它赋值给另一个变量 "bb" 时,两个变量指向同一个 blob。 因而 "is" 操作符返回真值。 用 [:] 或 copy() 创建备份时值相等,但是不同的引用: :let blob = 0z112233 :let blob2 = blob :echo blob == blob2 1 :echo blob is blob2 1 :let blob3 = blob[:] :echo blob == blob3 1 :echo blob is blob3 0 blob 建立备份可通过 copy() 函数。用 [:] 也可以,已有上述。 1.6 变量的更多细节 more-variables 如果你需要知道变量或表达式的类型,使用 type() 函数。 如果 'viminfo' 选项包含 '!' 标志位,大写开头且不包含小写字母的全局变量被保存在 viminfo 文件里 viminfo-file 。 如果 'sessionoptions' 选项包含 "global",大写开头且包含至少一个小写字母的全局 变量被保存在会话文件里 session-file变量名 可以保存的位置 my_var_6 无 My_Var_6 会话文件 MY_VAR_6 viminfo 文件 可以使用花括号来构造变量名,见 curly-braces-names

2. 表达式语法 expression-syntax

表达式语法小结,优先级从低到高排列: expr1 expr2 expr2 ? expr1 : expr1 if-then-else expr2 expr3 expr3 || expr3 ... 逻辑或 expr3 expr4 expr4 && expr4 ... 逻辑与 expr4 expr5 expr5 == expr5 等于 expr5 != expr5 不等于 expr5 > expr5 大于 expr5 >= expr5 大于等于 expr5 < expr5 小于 expr5 <= expr5 小于等于 expr5 =~ expr5 匹配正规表达式 expr5 !~ expr5 不匹配正规表达式 expr5 ==? expr5 等于,忽略大小写 expr5 ==# expr5 等于,匹配大小写 等等 如上,? 忽略大小写,# 则匹配之 expr5 is expr5 相同的 ListDictionaryBlob 实例 expr5 isnot expr5 不同的 ListDictionaryBlob 实例 expr5 expr6 expr6 + expr6 ... 数值加法、列表或 blob 连接 expr6 - expr6 ... 数值减法 expr6 . expr6 ... 字符串连接 expr6 .. expr6 ... 字符串连接 expr6 expr7 expr7 * expr7 ... 数值乘法 expr7 / expr7 ... 数值除法 expr7 % expr7 ... 数值求余 expr7 expr8 ! expr7 逻辑非 - expr7 一元减法: 取反 + expr7 一元加法: 原值 expr8 expr9 expr8[expr1] 字符串里的字节或者 List 的项目 expr8[expr1 : expr1] 字符串子串或 List 的子列表 expr8.name Dictionary 的项目 expr8(expr1, ...) 使用 Funcref 变量的函数调用 expr8->name(expr1, ...) method 调用 expr9 number 数值常数 "string" 字符串常数,反斜杠有特殊含义 'string' 字符串常数,' 加倍 [expr1, ...] List {expr1: expr1, ...} Dictionary #{key: expr1, ...} Dictionary &option 选项值 (expr1) 嵌套表达式 variable 内部变量 va{ria}ble 带花括号的内部变量 $VAR 环境变量 @r 寄存器 'r' 的值 function(expr1, ...) 函数调用 func{ti}on(expr1, ...) 带花括号的函数调用 {args -> expr1} 匿名函数表达式 "..." 标明这一层上的操作可以连接。比如: &nu || &list && &shell == "csh" 同一层的表达式从左到右进行分析。 expr1 expr1 trinary falsy-operator ?? E109

三元操作符: expr2 ? expr1 : expr1 准假值操作符: expr2 ?? expr1 三元操作符 '?' 之前的表达式作为数值求值。如果结果为 TRUE ,最终的结果是 '?' 和 ':' 之间 的表达式的值,不然最终的结果是 ':' 之后的表达式的值。例如: :echo lnum == 1 ? "top" : lnum 因为第一个表达式是 "expr2",它不能包含另一个 ?:。另外两个表达式则没有这个限 制,从而使得递归使用 ?: 成为可能。例如: :echo lnum == 1 ? "top" : lnum == 1000 ? "last" : lnum 要使之可读,建议使用续行符 line-continuation : :echo lnum == 1 :\ ? "top" :\ : lnum == 1000 :\ ? "last" :\ : lnum 在 ':' 前,你总是应该加上空格,否则它可能被错误用在如 "a:1" 这样的变量里。 准假值操作符 也有人叫作 "空值合并操作符",但太复杂了,所以我们就叫它准假值操作符。 先计算 '??' 之前的表达式,如果值为 truthy ,则把它用作结果。否则,计算 '??' 之后的表达式并用作结果。最常用于为可能为零或空的表达式指定缺省值: echo theList ?? '列表为空' echo GetName() ?? '未知' 以下两者类似,但不完全相同: expr2 ?? expr1 expr2 ? expr2 : expr1 第二行中的 "expr2" 会计算两次。 expr2 和 expr3 expr2 expr3

expr3 || expr3 .. 逻辑或 expr-barbar expr4 && expr4 .. 逻辑与 expr-&& "||" 和 "&&" 操作符左右两边各接受一个参数。参数是 (或转化为) 数值。运算结果是: 输入 输出 n1 n2 n1 || n2 n1 && n2 FALSE FALSE FALSE FALSE FALSE TRUE TRUE FALSE TRUE FALSE TRUE FALSE TRUE TRUE TRUE TRUE 操作符可以连接。比如: &nu || &list && &shell == "csh" 注意 "&&" 比 "||" 优先级高,所以这等价于: &nu || (&list && &shell == "csh") 一旦结果可以确定,表达式使用 "短路" 计算,也就是,不再计算后面的参数,这和 C 的情形类似。比如: let a = 1 echo a || b 这是合法的,即使没有叫 "b" 的变量也是如此。因为 "a" 已经是 TRUE ,结果必然是 TRUE 。下面的情形类似: echo exists("b") && b == "yes" 无论 "b" 定义与否,这是合法的。第二个子句只有在 "b" 定义的时候才会被计算。 expr4 expr4

expr5 {cmp} expr5 比较两个 expr 表达式,如果结果为假,返回 0,如果结果为真,返回 1。 expr-== expr-!= expr-> expr->= expr-< expr-<= expr-=~ expr-!~ expr-==# expr-!=# expr-># expr->=# expr-<# expr-<=# expr-=~# expr-!~# expr-==? expr-!=? expr->? expr->=? expr-<? expr-<=? expr-=~? expr-!~? expr-is expr-isnot expr-is# expr-isnot# expr-is? expr-isnot? 使用 'ignorecase' 匹配大小写 忽略大小写 等于 == ==# ==? 不等于 != !=# !=? 大于 > ># >? 大于等于 >= >=# >=? 小于 < <# <? 小于等于 <= <=# <=? 匹配正规表达式 =~ =~# =~? 不匹配正规表达式 !~ !~# !~? 相同实例 is is# is? 不同实例 isnot isnot# isnot? 示例: "abc" ==# "Abc" 结果为 0 "abc" ==? "Abc" 结果为 1 "abc" == "Abc" 如果置位了 'ignorecase',结果为 1,不然结果为 0 E691 E692 List 只能和 List 比较,而且只能用 "等于"、"不等于"、"is" 和 "isnot"。比较 针对列表的值,递归进行。忽略大小写意味着比较项目的值时忽略大小写。 E735 E736 Dictionary 只能和 Dictionary 比较,而且只能用 "等于"、"不等于"、"is" 和 "isnot"。比较针对 Dictionary 的键/值,递归进行。忽略大小写意味着比较项目的值 时忽略大小写。 E694 Funcref 只能和 Funcref 比较,而且只能用 "等于"、"不等于"、"is" 和 "isnot"。这里永不忽略大小写。参数或字典是否绑定 (即偏函数的情况) 是有关系的。 绑定的字典必须相等 (或 "is" 的情况下,相同实例),参数亦然。 要比较函数引用是否指向相同的函数但忽略绑定的字典和参数,用 get() 来取得函数 名: if get(Part1, 'name') == get(Part2, 'name') " Part1 and Part2 refer to the same function ListDictionaryBlob 用 "is" 或 "isnot" 时,检查表达式是否指向同一个 ListDictionaryBlob 实例。一个 List 的备份和原来的 List 不同。 如果不是 ListDictionaryBlob ,用 "is" 等价于用 "等于",而 "isnot" 等价于 "不等于",有一点区别: 不同的类型总认为有不同的值: echo 4 == '4' 1 echo 4 is '4' 0 echo 0 is [] 0 "is#"/"isnot#" 和 "is?"/"isnot?" 用于强制匹配和忽略大小写。 如果比较字符串和数值,字符串被转化成数值,而比较是在数值之间进行的。这意味 着: echo 0 == 'x' 1 因为 'x' 转化的数值为零。不过: echo [0] == ['x'] 0 在列表或字典里不进行这种转换。 如果比较两个字符串,使用 strcmp() 或 stricmp()。因而,比较的是数学上的差异 (比 较字节码),而不必然是本地语言的字母的差异。 如果操作符后带上 '#',或者 'ignorecase' 关闭时使用无 '#' 的版本时,比较使用 strcmp(): 大小写相关。 如果操作符后带上 '?',或者 'ignorecase' 打开时使用无 '?' 的版本时,比较使用 stricmp(): 大小写无关。 这里 'smartcase' 不适用。 "=~" 和 "!~" 操作符使用右边的参数作为模式来匹配左边的参数。模式的定义见 pattern 。匹配进行时,总是假设置位了 'magic' 并且 'cpoptions' 为空,无论 'magic''cpoptions' 实际的值为何。这使得脚本可移植。要避免在正规表达式里使 用的反斜杠需要加倍的问题,可以使用单引号的字符串,见 literal-string 。 既然字符串假定为单行,多行的模式 (包含 \n,即反斜杠-n) 不会被匹配。不过,按本 义出现的单个 NL 字符可以像普通字符一样匹配。比如: "foo\nbar" =~ "\n" 结果为 1 "foo\nbar" =~ "\\n" 结果为 0 expr5 和 expr6 expr5 expr6

expr6 + expr6 数值加法、 ListBlob 连接 expr-+ expr6 - expr6 数值减法 expr-- expr6 . expr6 字符串连接 expr-. expr6 .. expr6 字符串连接 expr-.. Lists 只能用 "+",而且两个 expr6 必须都是列表。返回两者连接以后的新列表。 字符串连接建议使用 "..",因为 "." 有二义性,也用于 Dict 的成员访问和浮点数。 当 vimscript-version 为 2 或更高时,不允许使用 "."。 expr7 * expr7 数值乘法 expr-star expr7 / expr7 数值除法 expr-/ expr7 % expr7 数值求余 expr-% 除了 "." 和 ".." 以外,这里所有的操作都把字符串转化成数值。 按位操作运算见 and()or()xor()注意 "+" 和 "." 的差异: "123" + "456" = 579 "123" . "456" = "123456" 因为 '.' 和 '+' 与 '-' 的优先级相同,你需要把: 1 . 90 + 90.0 看作: (1 . 90) + 90.0 这没问题,因为字符串 "190" 被自动转换为数值 190,然后和浮点数 90.0 相加。不 过: 1 . 90 * 90.0 应被看作: 1 . (90 * 90.0) 因为 '.' 的优先级比 '*' 低,这 不能 工作,因为它试图连接浮点数和字符串。 数值除以零时,结果取决于该值: 0 / 0 = -0x80000000 (类似于浮点数的 NaN) >0 / 0 = 0x7fffffff (类似于正无穷大) <0 / 0 = -0x7fffffff (类似于负无穷大) (Vim 7.2 之前,总是返回 0x7fffffff) 启用 64-位数值支持时: 0 / 0 = -0x8000000000000000 (类似于浮点数的 NaN) >0 / 0 = 0x7fffffffffffffff (类似于正无穷大) <0 / 0 = -0x7fffffffffffffff (类似于负无穷大) 如果 '%' 的右边为零,结果为 0。 这些操作不适用于 Funcref 。 而 % 也不适用于浮点数。 E804 expr7 expr7

! expr7 逻辑非 expr-! - expr7 一元减法: 取反 expr-unary-- + expr7 一元加法: 原值 expr-unary-+ '!' 把 TRUE 变为 FALSEFALSE 变为 TRUE (一)。 '-' 改变数值的符号。 '+' 保持原值。注意 "++" 没有效果 (译者注: 即,不是增量操作符)。 字符串会先转化为数值。 可以重复和混合这三种运算。例如: !-1 == 0 !!8 == 1 --9 == 9 expr8 expr8

此处表达式或是 expr9 ,或是任意顺序的下面各项之一的序列。例如这些都可以: expr8[expr1].name expr8.name[expr1] expr8(expr1, ...)[expr1].name expr8->(expr1, ...)[expr1] 计算总是从左到右。 expr8[expr1] 字符串或 List 的项目 expr-[] E111 E909 subscript 老式 Vim 脚本里: 如果 expr8 是数值或字符串,结果是字符串,包含 expr8 里第 expr1 个字节。expr8 视作字符串 (数值自动转换为字符串),expr1 视作数值。这里不识别多字节编码,但可 考虑使用 byteidx() ,或用 split() 把字符串变为字符的列表。例如,要得到光标 所在的字节: :let c = getline(line("."))[col(".") - 1] Vim9 脚本里: 如果 expr8 是字符串,结果是字符串,包含 expr8 里第 expr1 个单个字符 (包含任何 的组合字符)。要用字节索引,使用 strpart() 。 索引 0 给出第一个字节。要小心: 文本列号可是从 1 开始的! 如果字符串的长度小于索引值,结果为空字符串。负索引总是给出空字符串 (原因: 反向 兼容)。用 [-1:] 得到最后一个字节或字符。 Vim9 脚本中,负索引的用法同列表中的相同: 由结尾开始反向计算。 如果 expr8 是 List ,返回索引值为 expr1 的项目。可用的索引值见 list-index 。 如果索引越界,产生错误。例如: :let item = mylist[-1] " 得到最后一个项目 一般的,如果 List 索引大于等于 List 的长度,或者比 List 的长度更负,产生 错误。 expr8[expr1a : expr1b] 子字符串或子列表 expr-[:] 如果 expr8 是字符串,结果是子字符串,包含第 expr1a 到第 expr1b (包含) 个 字节或字符。expr8 视作字符串,expr1a 和 expr1b 视作数值。 在老式 Vim 脚本里,索引是字节索引。这里不识别多字节编码,需用 byteidx() 来计 算索引值。如果 expr8 为数值,先转换为字符串。 在 Vim9 脚本里索引为字符索引,包含组合字符。要使用字节索引,可用 strpart() 。 要用字符索引但不带组合字符,可用 strcharpart() 。 索引 expr1b 包含在内,亦即是闭的。要用开的索引值,可用 slice() 函数。 如果省略 expr1a,用零。如果省略 expr1b,用字符串的长度减一。 可以用负数来从字符串尾部开始计算位置。-1 代表最后一个字符,-2 倒数第二个,依此 类推。 如果索引越界,忽略这些字符。如果 expr1b 小于 expr1a,结果是空字符串。 例如: :let c = name[-1:] " 字符串最后一个字节 :let c = name[0:-1] " 整个字符串 :let c = name[-2:-2] " 字符串倒数第二个字节 :let s = line(".")[4:] " 从第五个字节到最后 :let s = s[:-3] " 删除最后两个字节 slice 如果 expr8 是 List ,结果是新的 List ,包含 expr1 和 expr1b 索引指定的项目。 和上面描述的字符串情形类似。另见下面的 sublist 。例如: :let l = mylist[:3] " 前四个项目 :let l = mylist[4:4] " 单个项目的列表 :let l = mylist[:] " 列表的浅备份 如果 expr8 是 Blob ,结果是新的 Blob ,包含从索引 expr1a 到 expr1b 的字节, 闭区间。例如: :let b = 0zDEADBEEF :let bs = b[1:2] " 0zADBE :let bs = b[:] " 0zDEADBEEF 的备份 Funcref 上用 expr8[expr1] 或 expr8[expr1a : expr1b] 出错。 小心命名空间和变量后加冒号的子列表用法引起的混淆: mylist[n:] " 使用变量 n mylist[s:] " 使用命名空间 s:,报错! expr8.name Dictionary 的项目 expr-entry 如果 expr8 是一个 Dictionary 且后跟句号再跟一个名字,该名字用作 Dictionary 的键。这相当于: expr8[name]。 该名字必须由字母数字字符组成。这和变量名一样,不过这里可以用数字开始。但不能用 花括号。 句号前后不能用空白。 例如: :let dict = {"one": 1, 2: "two"} :echo dict.one " 显示 "1" :echo dict.2 " 显示 "two" :echo dict .2 " 因为点号前有空格,报错 注意 句号也用于字符串连接。要避免混淆,用于字符串连接的句号前后加上空白。 expr8(expr1, ...) Funcref 函数调用 如果 expr8 是 Funcref 类型的变量,调用它指向的函数。 expr8->name([args]) 方法调用 method -> expr8->{lambda}([args]) E276 对同时作为全局函数存在的方法而言,这等价于: name(expr8 [, args]) 也有专用于 "expr8" 类型的方法。 可用于链式调用,把一个方法的结果传给下一个方法: mylist->filter(filterexpr)->map(mapexpr)->sort()->join() 使用匿名函数的示例: GetPercentage()->{x -> x * 100}()->printf('%d%%') 使用 -> 时,先应用 expr7 操作符,所以: -1.234->string() 等价于: (-1.234)->string()不是 : -(1.234->string()) E274 "->name(" 内部不能包含空白。"->" 之前和 "(" 之后可有空白,所以可以这样断行: mylist \ ->filter(filterexpr) \ ->map(mapexpr) \ ->sort() \ ->join() 使用匿名函数形式时,} 和 ( 之间不能有空白。 expr9 number

number 数值常数 expr-number 0x hex-number 0o octal-number binary-number 十进制、十六进制 (0x 或 0X 开始)、二进制 (0b 或 0B 开始) 和 八进制 (0、0o 或 0O 开始)。 floating-point-format 浮点数可用两种形式给出: [-+]{N}.{M} [-+]{N}.{M}[eE][-+]{exp} {N}{M} 都是数值。{N}{M} 都必须存在,且只能包含数位。 [-+] 意味着有一个可选的正负号。 {exp} 是指数部分,以 10 为基。 只能接受小数点,逗号不行。这和当前的 locale 无关。 {仅当编译时加入 +float 特性才有效} 示例: 123.456 +0.0001 55.0 -0.123 1.234e03 1.0E-6 -3.1416e+88 下面的形式是 非法的 : 3. {M} 为空 1e40 {M} 为空 理据: 浮点数引入之前,文本 "123.456" 被解释为两个数值 "123" 和 "456",转换为字符串, 然后进行连接而生成字符串 "123456"。这被认为没有意义,也没有找到有意使用此特性 的 Vim 脚本,因此我们采纳了这种普遍的浮点数记法,而接受其后向不兼容性。 float-pi float-e 可以复制-粘贴的一些常用值: :let pi = 3.14159265359 :let e = 2.71828182846 或者,如果不要直接写浮点常量,可用相应的函数,就像这样: :let pi = acos(-1.0) :let e = exp(1.0) floating-point-precision 浮点数的精度和取值范围取决于 Vim 编译时使用的库如何理解 "double"。运行时无法改 变。 浮点数 Float 的显示缺省使用 6 位十进制位,类似于 printf("%g", f)。使用 printf() 函数时可以指定其它位数。例如: :echo printf('%.15e', atan(1)) 7.853981633974483e-01 string string String expr-string E114

"string" 字符串常数 expr-quote 注意 使用的是双引号。 字符串常数接受以下特殊字符: \... 三位八进制数 (例如,"\316") \.. 两位八进制数 (必须后跟非数字) \. 一位八进制数 (必须后跟非数字) \x.. 两位十六进制数指定的字节 (例如,"\x1f") \x. 一位十六进制数指定的字节 (必须后跟非十六进制数字) \X.. 同 \x.. \X. 同 \x. \u.... 四位十六进制指定的字符。根据 'encoding' 的当前值决定的编码进行存贮 (例 如,"\u02a4") \U.... 同 \u 但接受多达 8 位十六进制数。 \b 退格 <BS> \e escape <Esc> \f 换页 <FF> \n 换行 <NL> \r 回车 <CR> \t 制表 <Tab> \\ 反斜杠 \" 双引号 \<xxx> "xxx" 命名的特殊字符,例如 "\<C-W>" 代表 CTRL-W。用于映射,0x80 字节被 转义。 双引号必须转义: "<M-\">"。 不要用 <Char-xxxx> 来得到 utf-8 字符,用上面提到的 \uxxxxx。 \<*xxx> 类似于 \<xxx>,但在之前附加修饰符而不是把它包含到字符里。例如, "\<C-w>" 是单个字符 0x17,而 "\<*C-w>" 是四个字节: CTRL 修饰符对应 3 个,然后是字符 "W"。 注意 "\xff" 保存为字节 255,在某些编码中它是不合法的。使用 "\u00ff" 可以按照 'encoding' 的当前值保存字符 255。 注意 "\000" 和 "\x00" 强制字符串结束。 blob-literal blob-literal E973

0z 或 0Z 开头的十六进制序列,字符数目不限。序列必须是偶数位的十六进制字符。例 如: :let b = 0zFF00ED015DAF literal-string literal-string E115

'string' 字符串常数 expr-' 注意 使用的是单引号。 字符串这里按原义出现。不去掉反斜杠,它也没有特殊含义。唯一的特例是两个单引号代 表一个单引号。 单引号字符串有助于模式的使用,因为反斜杠不再需要加倍。以下两个命令等价: if a =~ "\\s*" if a =~ '\s*' option expr-option E112 E113

&option 选项值,如有存在,使用局部值 &g:option 全局选项值 &l:option 局部选项值 例如: echo "tabstop is " . &tabstop if &insertmode 这里可以使用任何选项值。见 options 。如果指定要使用局部值,但不存在局部于缓冲 区或局部于窗口的选项,则还是使用全局值。 register expr-register @r

@r 寄存器 'r' 的值 结果是命名寄存器的内容,以单个字符串表达。换行符在需要时会被插入。要得到无名寄 存器的内容,使用 @" 或 @@。可用寄存器的相关解释可见 registers 。 如果用 '=' 寄存器,你得到表达式自身,而不是它计算的结果。用 eval() 来进行计 算。 nesting expr-nesting E110

(expr1) 嵌套表达式 environment variable expr-env

$VAR 环境变量 任何环境变量的字符串值。如果该环境变量没有定义,结果为空字符串。 也可用 getenv()setenv() 函数,它们支持非字母数字的环境变量名。 可用 environ() 函数得到包含所有环境变量的字典。 expr-env-expand 注意 直接使用 $VAR 和使用 expand("$VAR") 有区别。直接使用的形式只能扩展当前 Vim 会话所知的环境变量。使用 expand() 会先尝试当前 Vim 会话所知的环境变量,如 果不成功,则使用外壳扩展该变量。这会变慢,但可以用来扩展只有外壳知道的变量。 例如: :echo $shell :echo expand("$shell") 前者可能不会回显任何内容,后者会回显 $shell 变量 (如果你的外壳支持的话)。 internal variable expr-variable

variable 内部变量 见下面的 internal-variables 。 function call expr-function E116 E118 E119 E120

function(expr1, ...) 函数调用 见下面的 functions 。 lambda expression expr-lambda lambda

{args -> expr1} 匿名函数表达式 匿名函数表达式创建一个新的无名函数,返回 expr1 的计算结果。匿名函数表达式和 user-functions 的区别如下: 1. 匿名函数表达式的本体是 expr1 而不是 Ex 命令序列。 2. 前缀 "a:" 不用于参数。例如: :let F = {arg1, arg2 -> arg1 - arg2} :echo F(5, 2) 3 参数可选。例如: :let F = {-> 'error function'} :echo F('ignored') error function 注意 Vim9 脚本中可用另一种匿名函数: vim9-lambda closure 匿名函数表达式可能访问外层变量和参数。这通常被称为闭包。下例中匿名函数可以使用 已存在于函数作用域的 "i" 和 "a:arg"。在函数返回后它们依然有效: :function Foo(arg) : let i = 3 : return {x -> x + i - a:arg} :endfunction :let Bar = Foo(4) :echo Bar(6) 5 注意 变量必须在 lambda 定义之前已存在于外部作用域。另见 :func-closure 。 可以这样来检查匿名函数和闭包的支持: if has('lambda') 示例如何在 sort()map()filter() 中使用匿名函数: :echo map([1, 2, 3], {idx, val -> val + 1}) [2, 3, 4] :echo sort([3,7,2,1,4], {a, b -> a - b}) [1, 2, 3, 4, 7] 匿名函数表达式也可用于通道、作业和定时器中: :let timer = timer_start(500, \ {-> execute("echo 'Handler called'", "")}, \ {'repeat': 3}) Handler called Handler called Handler called 注意 execute() 是如何用来执行 Ex 命令的。这不怎样好看。 在 Vim9 脚本中可用命令块,见 inline-function 。 匿名函数表达式使用的内部名形如 '<lambda>42'。如果有关于某匿名函数的错误,可以 用下述命令查看它的定义: :function <lambda>42 另见: numbered-function

3. 内部变量 internal-variables E461

内部变量的名字由字母、数字和 '_' 组成。但不能由数字开始。可以使用花括号,见 curly-braces-names 。 内部变量通过 ":let" 命令建立 :let 。 内部变量通过 ":unlet" 命令显式删除 :unlet 。 使用非内部变量的名字或引用已经删除的内部变量会产生错误。 variable-scope 变量有不同的命名空间,根据附加的前缀决定: (无) 函数内: 局部于函数;否则: 全局 buffer-variable b: 局部于当前缓冲区。 window-variable w: 局部于当前窗口。 tabpage-variable t: 局部于当前标签页。 global-variable g: 全局。 local-variable l: 局部于函数。 script-variable s: 局部于 :source 的 Vim 脚本。 function-argument a: 函数参数 (只限于函数内使用)。 vim-variable v: Vim 预定义的全局变量。 作用域本身可以用作 Dictionary 。例如,要删除所有局部于脚本的变量: :for k in keys(s:) : unlet s:[k] :endfor 备注: Vim9 脚本此处不同,见 vim9-scopes buffer-variable b:var b: "b:" 开头的变量名局部于当前缓冲区。这样,你可以为每个缓冲区定义不同的 "b:foo" 变量。这种变量在缓冲区被删除时 (:bwipeout 或 :bdelete :bdelete ) 同时被删除。 预定义了如下的缓冲区局部变量: b:changedtick changetick b:changedtick 当前缓冲区的改变次数。每次改变都会递增。撤销命令在此情形下也被 视作一次改变。写入缓冲区后复位 'modified' 也算。 这可用来在缓冲区发生改变时执行一些动作。比如: :if my_changedtick != b:changedtick : let my_changedtick = b:changedtick : call My_Update() :endif 不可改变或删除 b:changedtick 变量。 window-variable w:var w: "w:" 开头的变量名局部于当前窗口。窗口关闭时被删除。 tabpage-variable t:var t: "t" 开始的变量名局部于当前标签页。标签页关闭时,这些变量被删除。 {仅当编译时加入 +windows 特性才有效} global-variable g:var g: 函数内部,全局变量可以通过 "g:" 访问。如果不提供前缀,会使用函数的局部变量。在 其他地方,如果你想的话。也可以使用 "g:"。 local-variable l:var l: 访问函数的局部变量无需任何前缀。但如果你想要,可以使用 "l:"。不过,如果没有 "l:" 前缀,你可能会和保留的变量名冲突。例如 "count"。它本身指代 "v:count"。但 使用了 "l:count" 你就可以使用同名的局部变量。 script-variable s:var Vim 脚本里,可以使用 "s:" 开头的变量。它们不能在脚本之外访问,因而可以称为局部 于脚本的变量。 它们可以用于: - 载入脚本时执行的命令 - 脚本定义的函数 - 脚本定义的自动命令 - 脚本定义的函数和自动命令里定义的函数和自动命令 (递归) - 脚本里定义的用户定义命令 但不能用在: - 该脚本载入的其它脚本 - 映射 - 菜单 - 等等 脚本变量可以用来防止和全局变量名的冲突。看看这个例子: let s:counter = 0 function MyCounter() let s:counter = s:counter + 1 echo s:counter endfunction command Tick call MyCounter() 你可以从任何脚本里启动 "Tick",但那个脚本里的 "s:counter" 变量不会被改变,只有 在 "Tick" 定义所在脚本的 "s:counter" 才会。 另一个完成相同功能的例子: let s:counter = 0 command Tick let s:counter = s:counter + 1 | echo s:counter 如果调用函数或者启动用户定义命令,脚本变量的上下文设置为函数和命令定义所在的脚 本。 脚本变量也可用于脚本里定义的函数里定义的函数。例如: let s:counter = 0 function StartCounting(incr) if a:incr function MyCounter() let s:counter = s:counter + 1 endfunction else function MyCounter() let s:counter = s:counter - 1 endfunction endif endfunction 调用 StartCounting() 时,定义 MyCounter() 函数或者递增或者递减计数器。不管 StartCounting() 在哪里调用,s:counter 变量总可以在 MyCounter() 里访问。 如果相同的脚本多次执行,使用的是同一个脚本变量。只要 Vim 还在运行,就保持有 效。这可以用于维护计数: if !exists("s:counter") let s:counter = 1 echo "脚本首次执行" else let s:counter = s:counter + 1 echo "脚本现在执行了 " . s:counter . " 次" endif 注意 这意味着 filetype 插件不能为每个缓冲区提供不同的脚本变量。这时应使用缓冲 区的局部变量 b:var 。 预定义的 VIM 变量: vim-variable v:var v: E963 有些变量可以被用户设置,但不能改变类型。 v:argv argv-variable v:argv 调用 Vim 时的命令行参数。这是字符串列表。首项是 Vim 命令。 v:beval_col beval_col-variable v:beval_col 鼠标指针所在的列号,即 v:beval_lnum 行中的字节位置。 仅当计算 'balloonexpr' 选项时有效。 v:beval_bufnr beval_bufnr-variable v:beval_bufnr 鼠标指针所在的缓冲区号。仅当计算 'balloonexpr' 选项时有效。 v:beval_lnum beval_lnum-variable v:beval_lnum 鼠标指针所在的行号。仅当计算 'balloonexpr' 选项时有效。 v:beval_text beval_text-variable v:beval_text 鼠标指针所在或之后的文本。通常是一个单词,可用于调试 C 程序。 此处用到 'iskeyword',但也包括此位置之前的句号和 "->"。如果在 ']' 上,使用它之前的文本,包括匹配的 '[' 和它之前的单词。如果 在单行的可视区域上,使用高亮文本。另见 <cexpr> 。 仅当计算 'balloonexpr' 选项时有效。 v:beval_winnr beval_winnr-variable v:beval_winnr 鼠标指针所在的窗口号。仅当计算 'balloonexpr' 选项时有效。首个 窗口的编号为零 (这和多数需要窗口编号的地方不同)。 v:beval_winid beval_winid-variable v:beval_winid 鼠标指针所在的窗口 ID window-ID 。其它类同于 v:beval_winnr。 v:char char-variable v:char 计算 'formatexpr' 时使用的参数和用于带 <expr> 的缩写中输入的字 符 :map-<expr> 。 也用于 InsertCharPreInsertEnter 事件。 v:charconvert_from charconvert_from-variable v:charconvert_from 要转换的文件字符编码名。只在计算 'charconvert' 选项时有效。 v:charconvert_to charconvert_to-variable v:charconvert_to 转换后的文件字符编码名。只在计算 'charconvert' 选项时有效。 v:cmdarg cmdarg-variable v:cmdarg 该变量有两个目的: 1. 文件读写命令的额外参数。目前,它们包括 "++enc=" 和 "++ff="。该变量在文件读写命令的自动命令事件激活之前设置。开 头有一个空格,以便直接把该变量附加到读写命令之后。注意: 这 里不包括 "+cmd" 参数,因为它总要被执行的。 2. 使用 ":hardcopy" 打印 PostScript 文件时,":hardcopy" 命令的 参数。在 'printexpr' 里用得到。 v:cmdbang cmdbang-variable v:cmdbang 文件读写命令时,和 v:cmdarg 设置的时间类似。如果使用了 "!",其 值为 1,不然为 0。注意 它只能用于自动命令。用户命令里可以用 <bang> v:collate collate-variable v:collate 运行时环境当前 locale 设置的排序规则。这使 Vim 脚本可访问当前 locale 的编码。技术上: 这是 LC_COLLATE 的值。没有 locale 时的 值为 "C"。 此变量不能直接设置,请用 :language 命令。 见 multi-lang v:completed_item completed_item-variable v:completed_item 包含 complete-itemsDictionary ,用于得到 CompleteDone 之后的最近补全。如果补全失败, Dictionary 为空。 v:count count-variable v:count 最近的普通模式命令使用的计数。在映射前可用于得到计数。只读。 例如: :map _x :<C-U>echo "计数为 " . v:count<CR> 注意: <C-U> 是必要的,它删除紧跟在计数之后 ':' 所给出的行范 围。 如果有两个计数,如 "3d2w",它们进行相乘,如同命令行实际发生的 那样,等同于 "d6w"。 也用于计算 'formatexpr' 选项。 为了后向兼容,这里也可以用 "count",除非 scriptversion 为 3 或更高。 v:count1 count1-variable v:count1 类似于 "v:count",但没有给出计数时,缺省为 1。 v:ctype ctype-variable v:ctype 运行环境当前的字符 locale 设置。它使得 Vim 脚本能得到当前的 locale 编码。技术细节: 这就是 LC_CTYPE 的值。如果没有使用 locale,其值为 "C"。 该变量不能直接设置,请使用 :language 命令。 见 multi-lang v:dying dying-variable v:dying 通常为零。如果捕获到某个 "致命" 的 signal,设为 1。如果同时捕 获到多个 signal,其值相应增加。在自动命令里可以用来检查 Vim 是否被异常终止。{仅限于 Unix} 例如: :au VimLeave * if v:dying | echo "\nAAAAaaaarrrggghhhh!!!\n" | endif 备注: 如果 v:dying 为一而同时又捕捉到另一个致命的 signal,不执 行 VimLeave 自动命令。 v:exiting exiting-variable v:exiting Vim 退出码。通常为零,非零代表出现某种错误。调用 VimLeavePreVimLeave 自动命令前,此值为 v:null。见 :q:x:cquit 。 示例: :au VimLeave * echo "Exit value is " .. v:exiting v:echospace echospace-variable v:echospace 在屏幕行末行上 :echo 消息不引发 hit-enter-prompt 最多可用 的屏幕单元格数目。取决于 'showcmd''ruler''columns'。需要 检查 'cmdheight' 看看在末行之上是否有全宽的行存在。 v:errmsg errmsg-variable v:errmsg 最近给出的错误信息。该变量可以设置。 例如: :let v:errmsg = "" :silent! next :if v:errmsg != "" : ... handle error 为了后向兼容,这里也可以用 "errmsg",除非 scriptversion 为 3 或更高。 v:errors errors-variable assert-return v:errors assert 函数找到的错误,如 assert_true() 。 是一个字符串列表。 assert 函数在 assert 失败后附加项目。 返回值说明这一点: 如果有项目加入 v:errors,返回一,不然返回 零。 要清空旧的结果: :let v:errors = [] 如果用非列表来设置 v:errors,assert 函数会把它变成空列表。 v:event event-variable v:event 包含当前 autocommand 信息的字典。字典放置的内容参见具体事 件。 autocommand 结束后该字典清空,请参见 dict-identity 来了解 如何取得字典独立的备份。如果你要在事件触发后保留信息,可用 deepcopy() 。例如: au TextYankPost * let g:foo = deepcopy(v:event) v:exception exception-variable v:exception 最近捕获且没有完成的例外的值。见 v:throwpointthrow-variables 。 例如: :try : throw "oops" :catch /.*/ : echo "caught" .. v:exception :endtry 输出: "caught oops"。 v:false false-variable v:false 取值为零的数值。用于在 JSON 里填入 "false"。见 json_encode() 。 用于字符串时会返回 "v:false"。 echo v:false v:false 这样 eval() 可以把该字符串解析回相同的值。只读。 v:fcs_reason fcs_reason-variable v:fcs_reason 激活 FileChangedShell 事件的原因。 可以在自动命令里用来决定该做什么和/或如何设置 v:fcs_choice。可 能的值是: deleted 文件不再存在 conflict 文件内容、模式或修改时间被改变,而缓冲 区同时被修改 changed 文件内容被改变 mode 文件模式被改变 time 文件修改时间被改变 v:fcs_choice fcs_choice-variable v:fcs_choice FileChangedShell 事件激活后该做什么。可以在自动命令里用来告 诉 Vim 如何处理涉及的缓冲区: reload 重新载入缓冲区 (如果文件已删除,不能工 作)。 ask 询问用户该做什么,就像没有自动命令一 样。不过,如果只有修改时间被改变,不做 任何事。 <空> 不做任何事。自动命令应该已经处理完毕。 缺省为空。如果使用别的 (非法的) 值,Vim 的行为就像它为空一样。 不会有警告信息。 v:fname_in fname_in-variable v:fname_in 输入文件名。在计算以下选项时合法: 选项 用于 'charconvert' 要转换的文件 'diffexpr' 原始文件 'patchexpr' 原始文件 'printexpr' 要打印的文件 SwapExists 里设为交换文件名。 v:fname_out fname_out-variable v:fname_out 输出文件名。只有在计算以下选项时才合法: 选项 用于 'charconvert' 生成的转换完成的文件 (*) 'diffexpr' diff 的结果 'patchexpr' 产生的补丁文件 (*) 如果用于为写入命令进行转换 (比如,":w file"),等价于 v:fname_in。如果用于为读入命令进行转换 (比如,":e file"),它是 一个临时文件名,和 v:fname_in 不同。 v:fname_new fname_new-variable v:fname_new 文件新版本的名字。只有在计算 'diffexpr' 的时候才有效。 v:fname_diff fname_diff-variable v:fname_diff 比较结果 (或补丁) 的文件名。只有在计算 'patchexpr' 的时候才有 效。 v:folddashes folddashes-variable v:folddashes 用于 'foldtext': 反映关闭的折叠的折叠级别的连字符。 sandbox 里只读。 fold-foldtext v:foldlevel foldlevel-variable v:foldlevel 用于 'foldtext': 关闭的折叠的折叠级别。 sandbox 里只读。 fold-foldtext v:foldend foldend-variable v:foldend 用于 'foldtext': 关闭的折叠的最后一行。 sandbox 里只读。 fold-foldtext v:foldstart foldstart-variable v:foldstart 用于 'foldtext': 关闭的折叠的第一行。 sandbox 里只读。 fold-foldtext v:hlsearch hlsearch-variable v:hlsearch 用于指定搜索高亮是否打开的变量。只有在启动 'hlsearch' 时它的设 置才有意义,这需要 +extra_search 。设置该变量为零相当 :nohlsearch 命令,设置为一则相当于 let &hlsearch = &hlsearch 备注 函数返回时复原其值。 function-search-undo v:insertmode insertmode-variable v:insertmode 用于 InsertEnterInsertChange 自动命令事件。取值: i 插入模式 r 替换模式 v 虚拟替换模式 v:key key-variable v:key Dictionary 里当前项目的键。只有在 map()filter() 里计 算表达式时有效。 只读。 v:lang lang-variable v:lang 运行环境当前的消息 locale 设置。它使得 Vim 脚本能得到当前使用 的语言。技术细节: 这就是 LC_MESSAGES 的值。该值和系统有关。 该变量不能直接设置,请使用 :language 命令。 它和 v:ctype 不同,因为消息可能使用不同于字符编码的语言。见 multi-lang v:lc_time lc_time-variable v:lc_time 运行环境当前的时间消息 locale 设置。它使得 Vim 脚本能得到当前使用的语言。技术细节: 这就是 LC_TIME 的值。 该变量不能直接设置,请使用 :language 命令。见 multi-lang v:lnum lnum-variable v:lnum 'foldexpr' fold-expr'formatexpr''indentexpr' 表达式中 的行号和 'guitablabel''guitabtooltip' 中的标签页号。只有在 计算这些表达式时才合法。在 sandbox 里时只读。 v:mouse_win mouse_win-variable v:mouse_win 用 getchar() 得到鼠标点击时所在的窗口号。首个窗口的编号为 1 ,就像 winnr() 那样。如果那时没有鼠标点击,该值为零。 v:mouse_winid mouse_winid-variable v:mouse_winid 用 getchar() 得到鼠标点击时所在的窗口 ID。如果那时没有鼠标点 击,该值为零。 v:mouse_lnum mouse_lnum-variable v:mouse_lnum 用 getchar() 得到鼠标点击时所在的行号。这是文本行号,不是屏 幕行号。如果那时没有鼠标点击,该值为零。 v:mouse_col mouse_col-variable v:mouse_col 用 getchar() 得到鼠标点击时所在的列号。这是屏幕列号,就像 virtcol() 那样。如果那时没有鼠标点击,该值为零。 v:none none-variable None v:none 空字符串。用于在 JSON 里填入空项目。见 json_encode() 。 也可用于函数参数,指代缺省值,见 none-function_argument 。 用于数值时返回零。 用于字符串时会返回 "v:none"。 echo v:none v:none 这样 eval() 可以把该字符串解析回相同的值。只读。 v:null null-variable v:null 空字符串。用于在 JSON 里填入 "null"。见 json_encode() 。 用于数值时返回零。 用于字符串时会返回 "v:null"。 echo v:null v:null 这样 eval() 可以把该字符串解析回相同的值。只读。 v:numbermax numbermax-variable v:numbermax 数值的最大值。 v:numbermin numbermin-variable v:numbermin 数值的最小值 (为负数)。 v:numbersize numbersize-variable v:numbersize 数值型的位数。通常为 64,但在某些系统上可能为 32。 v:oldfiles oldfiles-variable v:oldfiles 启动时从 viminfo 文件载入的文件名列表。Vim 记住的位置标记所 在的就是这些文件。列表长度的上限由 'viminfo' 选项的 ' 参数定义 (缺省是 100)。 如果不用 viminfo ,该列表为空。 另见 :oldfilesc_#< 。 此列表可修改,但并不影响之后 viminfo 文件保存什么。同时,如 果使用非字符串的值,会有问题。 {仅当编译时加入 +viminfo 特性才有效} v:option_new v:option_new 选项的新值。执行 OptionSet 自动命令时有效。 v:option_old v:option_old 选项的旧值。执行 OptionSet 自动命令时有效。取决于用来设置的 命令和选项的类型,这可以是旧的局部值,也可以是旧的全局值。 v:option_oldlocal v:option_oldlocal 选项的旧的局部值。执行 OptionSet 自动命令时有效。 v:option_oldglobal v:option_oldglobal 选项的旧的全部值。执行 OptionSet 自动命令时有效。 v:option_type v:option_type 设置命令的作用域。执行 OptionSet 自动命令时有效。可能为 "global" 或 "local" v:option_command v:option_command 用于设置选项的命令。执行 OptionSet 自动命令时有效。 值 选项设置方法 "setlocal" :setlocal 或 ":let l:xxx" "setglobal" :setglobal 或 ":let g:xxx" "set" :set:let "modeline" modeline v:operator operator-variable v:operator 普通模式给出的最近的操作符。除了 <g><z> 开始的命令是两个 字符外,这是单个字符。最好和 v:prevcountv:register 一 起使用。常常,先中止操作符等待模式,然后使用操作符,例如: :omap O <Esc>:call MyMotion(v:operator)<CR> 直到输入下一个操作符之前,该值保持不变。因此不要期待该值会为 空。 :delete:yank 或其它 Ex 命令不改变 v:operator。 只读。 v:prevcount prevcount-variable v:prevcount 倒数第二次的普通模式命令使用的计数,也就是再上一个命令用的 v:count 的值。可以用来先中止可视模式或操作符等待模式,然后使用 计数。 :vmap % <Esc>:call MyFilter(v:prevcount)<CR> 只读。 v:profiling profiling-variable v:profiling 通常为零。开始用 ":profile start" 之后设为一。见 profiling v:progname progname-variable v:progname 包含 Vim 启动时使用的名字 (路径已被去掉)。可以用来为 viewevim 等符号链接到 Vim 的名字提供特殊的设置。 只读。 v:progpath progpath-variable v:progpath 包含 Vim 启动时使用的命令,使用的形式如果传递给外壳的话会保证 和当前进程运行相同的 Vim 可执行程序 (如果 $PATH 没变的话)。可 用于通过 --remote-expr 给 Vim 服务器发消息。 要得到完整路径: echo exepath(v:progpath) 如果命令使用相对路径,这样就会把相对路径扩展为完整路径,从而可 在 :cd 后使用。假定用 "./vim" 启动,返回 "/home/user/path/to/vim/src/vim"。 Linux 和其它系统上总是使用完整路径。 Mac 上可能只是 "vim",如上所述使用 exepath() 可用来得到完整路 径。 MS-Windows 上的可执行文件可能叫做 "vim.exe",但 v:progpath 中 不会带上 ".exe"。 只读。 v:register register-variable v:register 当前的普通模式命令使用的寄存器名字 (不管该命令是否使用寄存 器),也用于当前执行的普通模式的映射 (用于其中的接受寄存器的自 定义命令)。 如果没有特殊指定,使用缺省寄存器 '"'。除非 'clipboard' 包含 "unamed" 或 "unamedplus",此时它为 '*' 或 '+'。 另见 getreg()setreg() v:scrollstart scrollstart-variable v:scrollstart 指示使屏幕上滚的脚本或函数的字符串。只有在原来为空时才设置,因 此只记住第一个原因。如果来自输入的命令,设为 "Unknown"。 可以用来发现你的脚本为什么产生 hit-enter 提示。 v:servername servername-variable v:servername 如果有的话,注册过的 client-server-name 名字。 只读。 v:searchforward v:searchforward searchforward-variable 搜索方向: 正向搜索后为 1,反向搜索后为 0。直接设置最近搜索模式 会复位此值为正向,见 quote/注意 从函数返回时该值被复原 function-search-undo 。 可读写。 v:shell_error shell_error-variable v:shell_error 最近一次外壳命令的返回值。如果非零,最近一次外壳命令有错。如果 为零,则该命令成功返回。这只有在外壳把错误代码返回给 Vim 的时 候才工作。-1 通常用来告知该命令无法执行。只读。 例如: :!mv foo bar :if v:shell_error : echo '不能把 "foo" 换名为 "bar"!' :endif 为了后向兼容,这里也可以用 "shell_error",除非 scriptversion 为 3 或更高。 v:statusmsg statusmsg-variable v:statusmsg 最近给出的状态消息。可以设置该变量。 v:swapname swapname-variable v:swapname 只有在执行 SwapExists 自动命令时才合法: 找到的交换文件名。只 读。 v:swapchoice swapchoice-variable v:swapchoice SwapExists 自动命令可以设置此值,以选择如何处理已有交换文件: 'o' 以只读方式打开 'e' 仍然编辑 'r' 恢复 'd' 删除交换文件 'q' 退出 'a' 中止 该值应是单个字符的字符串。如果为空,用户会被询问,就像没有 SwapExists 自动命令那样。缺省为空。 v:swapcommand swapcommand-variable v:swapcommand 打开文件后执行的普通模式命令。可以用于 SwapExists 自动命令, 用以让另一个 Vim 打开文件并跳转到合适的位置。例如,要跳转到某 标签,用的值是 ":tag tagname\r"。":edit +cmd file" 用的值是 ":cmd\r"。 v:t_TYPE v:t_bool t_bool-variable v:t_bool Boolean 的类型值。只读。见: type() v:t_channel t_channel-variable v:t_channel Channel 的类型值。只读。见: type() v:t_dict t_dict-variable v:t_dict Dictionary 的类型值。只读。见: type() v:t_float t_float-variable v:t_float Float 的类型值。只读。见: type() v:t_func t_func-variable v:t_func Funcref 的类型值。只读。见: type() v:t_job t_job-variable v:t_job Job 的类型值。只读。见: type() v:t_list t_list-variable v:t_list List 的类型值。只读。见: type() v:t_none t_none-variable v:t_none None 的类型值。只读。见: type() v:t_number t_number-variable v:t_number Number 的类型值。只读。见: type() v:t_string t_string-variable v:t_string String 的类型值。只读。见: type() v:t_blob t_blob-variable v:t_blob Blob 的类型值。只读。见: type() v:termresponse termresponse-variable v:termresponse 使用 t_RV termcap 项目返回的终端的转义序列。Vim 收到 ESC [ 或者 CSI 开始,然后是 '>' 或 '?',并以一个 'c' 结束,并且其间 只包含数字和 ';' 的转义序列的时候,会设置该值。 如果设置该选项,会激活 TermResponse 自动命令事件,这样你就可以 对终端的应答做出反应。可用 terminalprops() 来查看 Vim 对终端 了解的情况。 新的 xterm 的应答是: "<Esc>[> Pp ; Pv ; Pc c"。 Pp 是终端类型: 0 代表 vt100,而 1 代表 vt220。 Pv 是补丁号 (因为这是 patch 95 引入的,补丁号应该总是 95 会更高)。Pc 总是零。 {仅当编译时加入 +termresponse 特性才有效} v:termblinkresp v:termblinkresp 终端用于 t_RC termcap 项目的转义序列。用于找出终端光标是否闪 烁。用于 term_getcursor() v:termstyleresp v:termstyleresp 终端用于 t_RS termcap 项目的转义序列。用于找出终端光标的形 状。用于 term_getcursor() v:termrbgresp v:termrbgresp 终端用于 t_RB termcap 项目的转义序列。用于找出终端的背景色, 见 'background' v:termrfgresp v:termrfgresp 终端用于 t_RF termcap 项目的转义序列。用于找出终端的前景色。 v:termu7resp v:termu7resp 终端用于 t_u7 termcap 项目的转义序列。用于找出终端如何处理二 义性宽度字符,见 'ambiwidth' v:testing testing-variable v:testing 必须在 test_garbagecollect_now() 之前设置。 另外,设置时,在 2 秒内不会显示特定的错误信息 (例如 "'dictionary' option is empty") v:this_session this_session-variable v:this_session 最近载入或者保存的会话文件的文件名 :mksession 。可以设置该变 量。如果没有保存过会话文件,该变量为空。 为了后向兼容,这里也可以用 "this_session",除非 scriptversion 为 3 或更高。 v:throwpoint throwpoint-variable v:throwpoint 最近捕获且未完成的例外的抛出位置。输入的命令不会设置此变量。另 见 v:exceptionthrow-variables 。 例如: :try : throw "oops" :catch /.*/ : echo "Exception from" v:throwpoint :endtry 输出: "Exception from test.vim, line 2" v:true true-variable v:true 取值为一的数值。用于在 JSON 里填入 "true"。见 json_encode() 。 用于字符串时会返回 "v:true"。 echo v:true v:true 这样 eval() 可以把该字符串解析回相同的值。只读。 v:val val-variable v:val ListDictionary 当前项目的值。只有在计算 map()filter() 里的表达式时才有效。只读。 v:version version-variable v:version Vim 的版本号: 主版本号乘以 100 加上副版本号。5.0 版本对应的是 500。5.1 版本则是 501。只读。为了后向兼容,这里也可以用 "version",除非 scriptversion 为 3 或者更高。 用 has() 可以检查是否包含某补丁,例如: if has("patch-7.4.123") 注意 补丁号和版本有关,5.0 和 5.1 版本都有补丁号 123,但完全不 同。 v:versionlong versionlong-variable v:versionlong 类似于 v:version,但末四位数字包含补丁号。8.1 版本带补丁 123 的值是 8010123。可以这样用: if v:versionlong >= 8010123 不过,如果包含的补丁列表有空档这样不太完美。比如为了安全原因, 有时旧的版本会打上新近的补丁。用 has() 函数可以确定是否包含某 补丁。 v:vim_did_enter vim_did_enter-variable v:vim_did_enter 直到绝大部分的初始化工作做完之前保持为零。在 VimEnter 自动命 令刚刚激活之前,设为一。 v:warningmsg warningmsg-variable v:warningmsg 最近给出的警告消息。该变量可以设置。 v:windowid windowid-variable v:windowid 运行基于 X11 的任何 GUI,或者在终端运行且 Vim 连接到 X 服务器 ( -X ) 时,给出窗口号。 运行 MS-Windows GUI 时,给出窗口的句柄。 否则该值为零。 注意: Vim 内部的窗口请用 winnr()win_getid() ,见 window-ID

4. 内建函数 functions

function-list 提供了按功能分组的一个函数列表。 (在函数名上使用 CTRL-] 跳转到完整的功能说明。) 用法 结果 描述 abs({expr}) 浮点或数值 {expr} 的绝对值 acos({expr}) 浮点 {expr} 的反余弦值 add({object}, {item}) 列表或 blob 在 {object} 最后附加 {item} and({expr}, {expr}) 数值 按位与 append({lnum}, {text}) 数值 在第 {lnum} 行下附加 {text} appendbufline({expr}, {lnum}, {text}) 数值 在缓冲区 {expr}{lnum} 行下附加 {text} argc([{winid}]) 数值 参数列表的文件数目 argidx() 数值 参数列表的当前索引 arglistid([{winnr} [, {tabnr}]]) 数值 参数列表的 id argv({nr} [, {winid}]) 字符串 参数列表第 {nr} 个参数 asin({expr}) 浮点 {expr} 的反正弦值 argv([-1, {winid}]) 列表 参数列表 assert_beeps({cmd}) 数值 断言 {cmd} 产生铃声 assert_equal({exp}, {act} [, {msg}]) 数值 断言 {exp} 等于 {act} assert_equalfile({fname-one}, {fname-two} [, {msg}]) 数值 断言文件内容相同 assert_exception({error} [, {msg}]) 数值 断言 v:exception 中有 {error} assert_fails({cmd} [, {error} [, {msg} [, {lnum} [, {context}]]]]) 数值 断言 {cmd} 失败 assert_false({actual} [, {msg}]) 数值 断言 {actual} 为假 assert_inrange({lower}, {upper}, {actual} [, {msg}]) 数值 断言 {actual} 在指定范围内 assert_match({pat}, {text} [, {msg}]) 数值 断言 {pat} 匹配 {text} assert_nobeep({cmd}) 数值 断言 {cmd} 不导致响铃 assert_notequal({exp}, {act} [, {msg}]) 数值 断言 {exp} 不等于 {act} assert_notmatch({pat}, {text} [, {msg}]) 数值 断言 {pat} 不匹配 {text} assert_report({msg}) 数值 报告一个测试失败 assert_true({actual} [, {msg}]) 数值 断言 {actual} 为真 atan({expr}) 浮点 {expr} 的反正切值 atan2(`{expr}, {expr}) 浮点 {expr1} / {expr2} 的反正切值 balloon_gettext() 字符串 气泡的当前文本 balloon_show({expr}) 无 在气泡内显示{expr} balloon_split({msg}) 列表 分割用于的 {msg} browse({save}, {title}, {initdir}, {default}) 字符串 启动文件请求窗口 browsedir({title}, {initdir}) 字符串 启动目录请求窗口 bufadd({name}) 数值 在缓冲区列表里加入缓冲区 bufexists({expr}) 数值 如果缓冲区 {expr} 存在则为 TRUE buflisted({expr}) 数值 如果缓冲区 {expr} 在列表内则为 TRUE bufload({expr}) 数值 如果还未载入,载入缓冲区 {expr} bufloaded({expr}) 数值 如果缓冲区 {expr} 被载入则为 TRUE bufname([{expr}]) 字符串 缓冲区 {expr} 的名字 bufnr([{expr} [, {create}]]) 数值 缓冲区 {expr} 的编号 bufwinid({expr}) 数值 缓冲区 {expr} 的窗口 ID bufwinnr({expr}) 数值 缓冲区 {expr} 的窗口号 byte2line({byte}) 数值 第 {byte} 个字节所在的行号 byteidx({expr}, {nr}) 数值 {expr} 里第 {nr} 个字符的字节位置 byteidxcomp({expr}, {nr}) 数值 {expr} 里第 {nr} 个字符的字节位置 call({func}, {arglist} [, {dict}]) 可变 调用函数 {func},使用参数 {arglist} ceil({expr}) 浮点 {expr} 向上取整 ch_canread({handle}) 数值 检查是否有可读的内容 ch_close({handle}) 无 关闭 {handle} ch_close_in({handle}) 无 关闭 {handle} 的 in 部分 ch_evalexpr({handle}, {expr} [, {options}]) 可变 在 JSON {handle} 上执行 {expr} ch_evalraw({handle}, {string} [, {options}]) 可变 在原始 {handle} 上执行 {string} ch_getbufnr({handle}, {what}) 数值 获得 {handle}/{what} 的缓冲区号 ch_getjob({channel}) 作业 获得 {channel} 的相关作业 ch_info({handle}) 字符串 有关通道 {handle} 的信息 ch_log({msg} [, {handle}]) 无 在通道日志文件中写入 {msg} ch_logfile({fname} [, {mode}]) 无 开始记录通道活动 ch_open({address} [, {options}]) 通道 打开到 {address} 的通道 ch_read({handle} [, {options}]) 字符串 从 {handle} 读取 ch_readblob({handle} [, {options}]) blob 从 {handle} 读取 blob ch_readraw({handle} [, {options}]) 字符串 从 {handle} 读取原始格式 ch_sendexpr({handle}, {expr} [, {options}]) 可变 在 JSON {handle} 上发送 {expr} ch_sendraw({handle}, {expr} [, {options}]) 可变 在原始 {handle} 上发送 {expr} ch_setoptions({handle}, {options}) 无 设置 {handle} 的选项 ch_status({handle} [, {options}]) 字符串 通道 {handle} 的状态 changenr() 数值 当前改变号 char2nr({expr} [, {utf8}]) 数值 {expr} 里第一个字符串的 ASCII/UTF8 值 charclass({string}) 数值 {string} 的字符类 charcol({expr}) 数值 光标或位置标记的列号 charidx({string}, {idx} [, {countcc}]) 数值 {string} 中字节 {idx} 对应的字符索引 chdir({dir}) 数值 改变当前目录 cindent({lnum}) 数值 第 {lnum} 行的 C 缩进 clearmatches([{win}]) 无 清除所有的匹配 col({expr}) 数值 光标或位置标记的列字节索引 complete({startcol}, {matches}) 无 设置插入模式补全 complete_add({expr}) 数值 增加补全匹配 complete_check() 数值 补全时检查输入的键 complete_info([{what}]) 字典 获得当前补全信息 confirm({msg} [, {choices} [, {default} [, {type}]]]) 数值 用户选择的序号 copy({expr}) 可变 提供 {expr} 的浅备份 cos({expr}) 浮点 {expr} 的余弦值 cosh({expr}) 浮点 {expr} 的双曲余弦值 count({comp}, {expr} [, {ic} [, {start}]]) 数值 计算 {comp} 里有多少个 {expr} cscope_connection([{num} , {dbpath} [, {prepend}]]) 数值 检查 cscope 连接是否存在 cursor({lnum}, {col} [, {off}]) 数值 移动光标到 {lnum}{col}{off} debugbreak({pid}) 数值 中断待调试的进程 cursor({list}) 数值 移动光标到 {list} 里的位置 deepcopy({expr} [, {noref}]) 可变 提供 {expr} 的完整备份 delete({fname} [, {flags}]) 数值 删除文件或目录 {fname} deletebufline({expr}, {first} [, {last}]) 数值 删除缓冲区 {expr} 的多行 did_filetype() 数值 用过 FileType 自动命令事件则为 TRUE diff_filler({lnum}) 数值 {lnum} 行之上的 diff 填充行数 diff_hlID({lnum}, {col}) 数值 {lnum}/{col} 位置的 diff 高亮 echoraw({expr}) 无 照原样输出 {expr} empty({expr}) 数值 如果 {expr} 为空则为 TRUE environ() 字典 返回所有环境变量 escape({string}, {chars}) 字符串 在 {string} 里用 '\' 转义 {chars} eval({string}) 可变 计算 {string},返回结果 eventhandler() 数值 如果在事件处理中则为 TRUE executable({expr}) 数值 如果可执行文件 {expr} 存在则为 1 execute({command}) 字符串 执行 {command} 并取得输出结果 exepath({expr}) 字符串 命令 {expr} 的完整路径 exists({expr}) 数值 如果 {expr} 存在则为 TRUE exp({expr}) 浮点 {expr} 的指数函数值 (译者注: 以 e 为底) expand({expr} [, {nosuf} [, {list}]]) 可变 扩展 {expr} 里的特殊关键字 expandcmd({expr}) 字符串 像 :edit 那样扩展 {expr} extend({expr1}, {expr2} [, {expr3}]) 列表/字典 把 {expr2} 里的项目插入 {expr1} extendnew({expr1}, {expr2} [, {expr3}]) 列表/字典 和 extend() 类似,但建立新列表或字 典 feedkeys({string} [, {mode}]) 数值 给预输入缓冲区加入键序列 filereadable({file}) 数值 如果 {file} 是个可读文件则为 TRUE filewritable({file}) 数值 如果 {file} 是个可写文件则为 TRUE filter({expr1}, {expr2}) 列表/字典 删除 {expr1}{expr2} 为 0 的项目 finddir({name} [, {path} [, {count}]]) 字符串 在 {path} 里寻找目录 {name} findfile({name} [, {path} [, {count}]]) 字符串 在 {path} 里寻找文件 {name} flatten({list} [, {maxdepth}]) 列表 展平 {list},最多到 {maxdepth} 层 flattennew({list} [, {maxdepth}]) 列表 展平 {list} 的一个备份 float2nr({expr}) 数值 转换浮点数 {expr} 为数值 floor({expr}) 浮点 {expr} 向下取整 fmod({expr1}, {expr2}) 浮点 {expr1} / {expr2} 的浮点余数 fnameescape({fname}) 字符串 转义 {fname} 中的特殊字符 fnamemodify({fname}, {mods}) 字符串 修改文件名 foldclosed({lnum}) 数值 {lnum} 所在折叠的首行,如果是关闭的话 foldclosedend({lnum}) 数值 {lnum} 所在折叠的末行,如果是关闭的话 foldlevel({lnum}) 数值 {lnum} 的折叠级别 foldtext() 字符串 关闭的折叠显示的行 foldtextresult({lnum}) 字符串 {lnum} 所在的关闭的折叠的文本 foreground() 数值 把 Vim 窗口带到前台 fullcommand({name}) 字符串 得到 {name} 的完整命令 funcref({name} [, {arglist}] [, {dict}]) 函数引用 函数 {name} 的引用 function({name} [, {arglist}] [, {dict}]) 函数引用 函数 {name} 的命名引用 garbagecollect([{atexit}]) 无 释放内存,打破循环引用 get({list}, {idx} [, {def}]) 可变 得到 {list}{def} 的项目 {idx} get({dict}, {key} [, {def}]) 可变 得到 {dict}{def} 的项目 {idx} get({func}, {what}) 可变 得到函数引用/偏函数 {func} 的属性 getbufinfo([{expr}]) 列表 缓冲区信息 getbufline({expr}, {lnum} [, {end}]) 列表 缓冲区 {expr}{lnum}{end} 行 getbufvar({expr}, {varname} [, {def}]) 可变 缓冲区 {expr} 的变量 {varname} getchangelist([{expr}]) 列表 改变列表项目的列表 getchar([expr]) 数值 让用户输入一个字符 getcharmod() 数值 最近输入字符的修饰符 getcharpos({expr}) 列表 光标、位置标记等的位置 getcharsearch() 字典 最近字符搜索选项 getcmdline() 字符串 返回当前命令行 getcmdpos() 数值 返回命令行的光标位置 getcmdtype() 字符串 返回当前命令行类型 getcmdwintype() 字符串 返回当前命令行窗口类型 getcompletion({pat}, {type} [, {filtered}]) 列表 命令行补全匹配列表 getcurpos([{winnr}]) 列表 光标位置 getcursorcharpos([{winnr}]) 列表 光标的字符位置 getcwd([{winnr} [, {tabnr}]]) 字符串 当前工作目录 getenv({name}) 字符串 返回环境变量 getfontname([{name}]) 字符串 使用的字体名 getfperm({fname}) 字符串 文件 {fname} 的文件权限 getfsize({fname}) 数值 字节计算的文件 {fname} 大小 getftime({fname}) 数值 文件的最新修改时间 getftype({fname}) 字符串 文件 {fname} 类型的描述 getimstatus() 数值 如果 IME 处于激活状态则为 TRUE getjumplist([{winnr} [, {tabnr}]]) 列表 跳转列表项目的列表 getline({lnum}) 字符串 当前缓冲区的第 {lnum} 行 getline({lnum}, {end}) 列表 当前缓冲区第 {lnum}{end} 行 getloclist({nr}) 列表 位置列表项目的列表 getloclist({nr}, {what}) 字典 获取指定的位置列表项目 getmarklist([{expr}]) 列表 全局/局部位置标记的列表 getmatches([{win}]) 列表 当前匹配的列表 getmousepos() 字典 最近已知的鼠标位置 getpid() 数值 Vim 的进程号 getpos({expr}) 列表 光标、位置标记等的位置 getqflist() 列表 快速修复项目的列表 getqflist([{what}]) 字典 获取指定快速修复列表的项目 getreg([{regname} [, 1 [, {list}]]]) 字符串/列表 某寄存器内容 getreginfo([{regname}]) 字典 关于某寄存器的信息 getregtype([{regname}]) 字符串 某寄存器的类型 gettabinfo([{expr}]) 列表 标签页列表 gettabvar({nr}, {varname} [, {def}]) 可变 {tabnr} 标签页的 {varname} 变量 gettabwinvar({tabnr}, {winnr}, {name} [, {def}]) 可变 {tabnr} 标签页 {winnr} 窗口的 {name} gettagstack([{nr}]) 字典 获取窗口 {nr} 的标签栈 gettext({text}) 字符串 查找 {text} 的翻译 getwininfo([{winid}]) 列表 每个窗口信息的列表 getwinpos([{timeout}]) 列表 Vim 窗口以像素计的 X 和 Y 坐标 getwinposx() 数值 Vim 窗口以像素计的 X 坐标 getwinposy() 数值 Vim 窗口以像素计的 Y 坐标 getwinvar({nr}, {varname} [, {def}]) 可变 窗口 {expr} 的变量 {varname} glob({expr} [, {nosuf} [, {list} [, {alllinks}]]]) 可变 扩展 {expr} 里的文件通配符 glob2regpat({expr}) 字符串 转化 glob 模式为搜索模式 globpath({path}, {expr} [, {nosuf} [, {list} [, {alllinks}]]]) 字符串 在 {path} 所有目录下执行 glob({expr}) has({feature} [, {check}]) 数值 如果支持特性 {feature} 则为 TRUE has_key({dict}, {key}) 数值 如果 {dict} 有项目 {key} 则为 TRUE haslocaldir([{winnr} [, {tabnr}]]) 数值 如果当前窗口执行过 :lcd 则为 TRUE hasmapto({what} [, {mode} [, {abbr}]]) 数值 如果 {what} 的映射存在则为 TRUE histadd({history},{item}) 数值 在历史里增加项目 histdel({history} [, {item}]) 数值 从历史里删除项目 histget({history} [, {index}]) 字符串 得到历史的第 {index} 项 histnr({history}) 数值 历史里最高的项目号 hlID({name}) 数值 高亮组 {name} 的语法 ID hlexists({name}) 数值 如果高亮组 {name} 存在则为 TRUE hostname() 字符串 Vim 运行的机器名字 iconv({expr}, {from}, {to}) 字符串 转换 {expr} 的编码 indent({lnum}) 数值 第 {lnum} 行的缩进 index({object}, {expr} [, {start} [, {ic}]]) 数值 {object} 里出现 {expr} 的项目的索引 input({prompt} [, {text} [, {completion}]]) 字符串 从用户得到输入 inputdialog({prompt} [, {text} [, {completion}]]) 字符串 类似于 input(),但使用 GUI 对话框 inputlist({textlist}) 数值 让用户从选择列表里挑选 inputrestore() 数值 恢复预输入 inputsave() 数值 保存和清除预输入 inputsecret({prompt} [, {text}]) 字符串 类似于 input(),但隐藏文本 insert({object}, {item} [, {idx}]) 列表 在 {object} 里插入 {item} [{idx} 之前] interrupt() 无 中断脚本执行 invert({expr}) 数值 按位取反 isdirectory({directory}) 数值 如果 {directory} 是目录则为 TRUE islocked({expr}) 数值 如果 {expr} 被锁住则为 TRUE isinf({expr}) 数值 决定 {expr} 是否为无限大 (正或负) isnan({expr}) 数值 如果 {expr} 为 NaN 则为 TRUE items({dict}) 列表 {dict} 里的键-值组对 job_getchannel({job}) 通道 获取 {job} 的通道句柄 job_info([{job}]) 字典 获取 {job} 的信息 job_setoptions({job}, {options}) 无 设置 {job} 选项 job_start({command} [, {options}]) 作业 启动作业 job_status({job}) 字符串 获取 {job} 的状态 job_stop({job} [, {how}]) 数值 停止 {job} join({list} [, {sep}]) 字符串 连接 {list} 的项目成为一个字符串 js_decode({string}) 可变 解码 JS 风格的 JSON js_encode({expr}) 字符串 编码 JS 风格的 JSON json_decode({string}) 可变 解码 JSON json_encode({expr}) 字符串 编码 JSON keys({dict}) 列表 {dict} 的所有键 len({expr}) 数值 {expr} 的长度 libcall({lib}, {func}, {arg}) 字符串 调用库 {lib} 的函数 {func},使用参数 {arg} libcallnr({lib}, {func}, {arg}) 数值 同上,但返回数值 line({expr} [, {winid}]) 数值 光标所在、末行或者位置标记所在的行号 line2byte({lnum}) 数值 行 {lnum} 的字节位置 lispindent({lnum}) 数值 行 {lnum} 的 Lisp 缩进 list2str({list} [, {utf8}]) 字符串 把 {list} 中的数值转成字符串 listener_add({callback} [, {buf}]) 数值 增加监听改动的回调 listener_flush([{buf}]) 无 激活监听器回调 listener_remove({id}) 无 删除监听器回调 localtime() 数值 当前时间 log({expr}) 浮点 {expr} 的自然对数 (以 e 为底) log10({expr}) 浮点 {expr} 以 10 为底的对数 luaeval({expr} [, {expr}]) 可变 执行 Lua 表达式 map({expr1}, {expr2}) 列表/字典 {expr1} 的每个项目改变为 {expr2} maparg({name} [, {mode} [, {abbr} [, {dict}]]]) 字符串/字典 模式 {mode} 的映射 {name} 的右手边 mapcheck({name} [, {mode} [, {abbr}]]) 字符串 检查匹配 {name} 的映射 mapnew({expr1}, {expr2}) 列表/字典 类似于 map() 但创建新列表或字典 mapset({mode}, {abbr}, {dict}) 无 从 maparg() 返回值恢复映射 match({expr}, {pat} [, {start} [, {count}]]) 数值 {expr}{pat} 的匹配位置 matchadd({group}, {pattern} [, {priority} [, {id} [, {dict}]]]) 数值 用 {group} 高亮 {pattern} matchaddpos({group}, {pos} [, {priority} [, {id} [, {dict}]]]) 数值 {group} 的高亮位置 matcharg({nr}) 列表 :match 的参数 matchdelete({id} [, {win}]) 数值 删除 {id} 指定的匹配 matchend({expr}, {pat} [, {start} [, {count}]]) 数值 {expr}{pat} 的结束位置 matchfuzzy({list}, {str} [, {dict}]) 列表 在 {list} 中模糊匹配 {str} matchfuzzypos({list}, {str} [, {dict}]) 列表 在 {list} 中模糊匹配 {str} matchlist({expr}, {pat} [, {start} [, {count}]]) 列表 {expr}{pat} 的匹配和子匹配 matchstr({expr}, {pat} [, {start} [, {count}]]) 字符串 {expr}{pat} 的第 {count} 个匹配文 本 matchstrpos({expr}, {pat} [, {start} [, {count}]]) 列表 {expr}{pat} 的第 {count} 个匹配 max({expr}) 数值 {expr} 的项目的最大值 menu_info({name} [, {mode}]) 字典 获取菜单项目信息 min({expr}) 数值 {expr} 的项目的最小值 mkdir({name} [, {path} [, {prot}]]) 数值 建立目录 {name} mode([expr]) 字符串 当前编辑模式 mzeval({expr}) 可变 计算 MzScheme 表达式 nextnonblank({lnum}) 数值 第一个 >= {lnum} 的非空白行的行号 nr2char({expr} [, {utf8}]) 字符串 ASCII/UTF8 值为 {expr} 的单个字符 or({expr}, {expr}) 数值 按位或 pathshorten({expr} [, {len}]) 字符串 缩短路径里的目录名 perleval({expr}) 可变 计算 Perl 表达式 popup_atcursor({what}, {options}) 数值 在光标附近创建弹出窗口 popup_beval({what}, {options}) 数值 为 'ballooneval' 创建弹出窗口 popup_clear() 无 关闭所有弹出窗口 popup_close({id} [, {result}]) 无 关闭弹出窗口 {id} popup_create({what}, {options}) 数值 创建弹出窗口 popup_dialog({what}, {options}) 数值 创建弹出窗口用作对话框 popup_filter_menu({id}, {key}) 数值 菜单弹出窗口的过滤 popup_filter_yesno({id}, {key}) 数值 对话框弹出窗口的过滤 popup_findinfo() 数值 获取信息弹出窗口的窗口 ID popup_findpreview() 数值 获取预览弹出窗口的窗口 ID popup_getoptions({id}) 字典 获取弹出窗口 {id} 的选项 popup_getpos({id}) 字典 获取弹出窗口 {id} 的位置 popup_hide({id}) 无 隐藏弹出窗口 {id} popup_list() 列表 获取所有弹出的窗口 ID 列表 popup_locate({row}, {col}) 数值 获取在给出位置的弹出窗口 ID popup_menu({what}, {options}) 数值 创建弹出窗口用作菜单 popup_move({id}, {options}) 无 设置弹出窗口 {id} 的位置 popup_notification({what}, {options}) 数值 创建通知弹出窗口 popup_setoptions({id}, {options}) 无 设置弹出窗口 {id} 的选项 popup_settext({id}, {text}) 无 设置弹出窗口 {id} 的文本 popup_show({id}) 无 撤销弹出窗口 {id} 的隐藏 pow({x}, {y}) 浮点 {x}{y} 次方 prevnonblank({lnum}) 数值 最后一个 <= {lnum} 的非空白行的行号 printf({fmt}, {expr1}...) 字符串 排版文本 prompt_getprompt({buf}) 字符串 获取提示文本 prompt_setcallback({buf}, {expr}) 无 设置提示回调函数 prompt_setinterrupt({buf}, {text}) 无 设置提示中断函数 prompt_setprompt({buf}, {text}) 无 设置提示文本 prop_add({lnum}, {col}, {props}) 无 新增文本属性 prop_clear({lnum} [, {lnum-end} [, {props}]]) 无 删除所有文本属性 prop_find({props} [, {direction}]) 字典 查找文本属性 prop_list({lnum} [, {props}]) 列表 {lnum} 的文本属性 prop_remove({props} [, {lnum} [, {lnum-end}]]) 数值 删除一个文本属性 prop_type_add({name}, {props}) 无 定义新的文本属性类型 prop_type_change({name}, {props}) 无 改变已有的文本属性类型 prop_type_delete({name} [, {props}]) 无 删除文本属性类型 prop_type_get({name} [, {props}]) 字典 获取文本属性类型的值 prop_type_list([{props}]) 列表 获取文本属性类型的列表 pum_getpos() 字典 如果可见,pum 的位置和大小 pumvisible() 数值 弹出窗口是否可见 py3eval({expr}) 可变 计算 python3 表达式 pyeval({expr}) 可变 计算 Python 表达式 pyxeval({expr}) 可变 计算 python_x 表达式 rand([{expr}]) 数值 得到伪随机数 range({expr} [, {max} [, {stride}]]) 列表 从 {expr}{max} 的序列 readblob({fname}) blob 从 {fname} 读取 Blob readdir({dir} [, {expr} [, {dict}]]) 列表 {dir}{expr} 所选择的文件名 readdirex({dir} [, {expr} [, {dict}]]) 列表 {dir}{expr} 所选择的文件信息 readfile({fname} [, {type} [, {max}]]) 列表 得到文件 {fname} 的行列表 reduce({object}, {func} [, {initial}]) 可变 用 {func} 缩减 {object} reg_executing() 字符串 得到执行中的寄存器名 reg_recording() 字符串 得到记录中寄存器名 reltime([{start} [, {end}]]) 列表 得到时间值 reltimefloat({time}) 浮点数 把时间值转化为浮点数 reltimestr({time}) 字符串 把时间值转化为字符串 remote_expr({server}, {string} [, {idvar} [, {timeout}]]) 字符串 发送表达式 remote_foreground({server}) 数值 把 Vim 服务器带到前台 remote_peek({serverid} [, {retvar}]) 数值 检查应答字符串 remote_read({serverid} [, {timeout}]) 字符串 读入应答字符串 remote_send({server}, {string} [, {idvar}]) 字符串 发送键序列 remote_startserver({name}) 无 成为服务器 {name} remove({list}, {idx} [, {end}]) 可变/列表 从 {list} 里删除项目 {idx}-{end} remove({blob}, {idx} [, {end}]) 可变/blob 从 {blob} 里删除字节 {idx}-{end} remove({dict}, {key}) 可变 从 {dict} 里删除项目 {key} rename({from}, {to}) 数值 换名 (移动) 文件,从 {from}{to} repeat({expr}, {count}) 字符串 重复 {expr} {count} 次 resolve({filename}) 字符串 解析快捷方式对应的文件名 reverse({list}) 列表 反转 {list},直接修改 {list} round({expr}) 浮点 {expr} 四舍五入 rubyeval({expr}) 可变 计算 Ruby 表达式 screenattr({row}, {col}) 数值 当前光标所在的属性 screenchar({row}, {col}) 数值 当前光标所在的字符 screenchars({row}, {col}) 列表 当前光标所在的字符列表 screencol() 数值 当前光标列 screenpos({winid}, {lnum}, {col}) 字典 文本字符的屏幕行与列 screenrow() 数值 当前光标行 screenstring({row}, {col}) 字符串 当前光标所在的字符串 search({pattern} [, {flags} [, {stopline} [, {timeout} [, {skip}]]]]) 数值 搜索 {pattern} searchcount([{options}]) 字典 获取或更新搜索统计数据 searchdecl({name} [, {global} [, {thisblock}]]) 数值 搜索变量声明 searchpair({start}, {middle}, {end} [, {flags} [, {skip} [...]]]) 数值 搜索 start/end 对的另一侧 searchpairpos({start}, {middle}, {end} [, {flags} [, {skip} [...]]]) 列表 搜索 start/end 队的另一侧 searchpos({pattern} [, {flags} [, {stopline} [, {timeout} [, {skip}]]]]) 列表 搜索 {pattern} server2client({clientid}, {string}) 数值 发送应答字符串 serverlist() 字符串 得到可用的服务器列表 setbufline({expr}, {lnum}, {text}) 数值 设置缓冲区 {expr}{lnum} 行为 {text} setbufvar({expr}, {varname}, {val}) 无 设置缓冲区 {expr}{varname}{val} setcellwidths({list}) 无 设置字符单元宽度覆盖 setcharpos({expr}, {list}) 数值 设置 {expr} 的位置为 {list} setcharsearch({dict}) 字典 从 {dict} 设置字符搜索选项 setcmdpos({pos}) 数值 设置命令行的光标位置 setcursorcharpos({list}) 数值 移动光标到 {list} 指定的位置 setenv({name}, {val}) 无 设置环境变量 setfperm({fname}, {mode}) 数值 设置 {fname} 文件权限为 {mode} setline({lnum}, {line}) 数值 设置第 {lnum} 行的内容为 {line} setloclist({nr}, {list} [, {action}]) 数值 用 {list} 修改位置列表 setloclist({nr}, {list} [, {action} [, {what}]]) 数值 修改指定的位置列表项目 setmatches({list} [, {win}]) 数值 还原匹配列表 setpos({expr}, {list}) 数值 设置 {expr} 的位置为 {list} setqflist({list} [, {action}]) 数值 用 {list} 修改快速修复列表 setqflist({list} [, {action} [, {what}]]) 数值 修改指定的快速修复列表项目 setreg({n}, {v} [, {opt}]) 数值 设置寄存器的值和类型 settabvar({nr}, {varname}, {val}) 无 设置标签页 {nr}{varname} 变量为 {val} settabwinvar({tabnr}, {winnr}, {varname}, {val}) 无 设置标签页 {tabnr} 窗口 {winnr}{varname} 变量为 {val} settagstack({nr}, {dict} [, {action}]) 数值 用 {dict} 修改标签栈 setwinvar({nr}, {varname}, {val}) 无 设置窗口 {expr}{varname}{val} sha256({string}) 字符串 {string} 的 SHA256 校验码 shellescape({string} [, {special}]) 字符串 转义 {string} 以便用作外壳命令的参数 shiftwidth([{col}]) 数值 'shiftwidth' 的有效值 sign_define({name} [, {dict}]) 数值 定义或更新标号 sign_define({list}) 列表 定义或更新一列标号 sign_getdefined([{name}]) 列表 得到已定义的标号的列表 sign_getplaced([{expr} [, {dict}]]) 列表 得到已放置的标号的列表 sign_jump({id}, {group}, {expr}) 数值 跳转到标号 sign_place({id}, {group}, {name}, {expr} [, {dict}]) 数值 放置标号 sign_placelist({list}) 列表 放置一列标号 sign_undefine([{name}]) 数值 撤销标号的定义 sign_undefine({list}) 列表 撤销一列标号的定义 sign_unplace({group} [, {dict}]) 数值 撤销标号的放置 sign_unplacelist({list}) 列表 撤销一列标号的放置 simplify({filename}) 字符串 尽可能简化文件名 sin({expr}) 浮点 {expr} 的正弦值 sinh({expr}) 浮点 {expr} 的双曲正弦值 slice({expr}, {start} [, {end}]) 字符串、列表或 blob 字符串、列表或 blob 的切片 sort({list} [, {func} [, {dict}]]) 列表 排序 {list},用比较函数 {func} sound_clear() 无 停止播放所有声音 sound_playevent({name} [, {callback}]) 数值 播放事件声音 sound_playfile({path} [, {callback}]) 数值 播放声音文件 {path} sound_stop({id}) 无 停止播放声音 {id} soundfold({word}) 字符串 按发音折叠 {word} spellbadword() 字符串 光标所在的拼写错误的单词 spellsuggest({word} [, {max} [, {capital}]]) 列表 拼写建议 split({expr} [, {pat} [, {keepempty}]]) 列表 从 {pat} 分割的 {expr} 里构造 List sqrt({expr}) 浮点 {expr} 的平方根 srand([{expr}]) 列表 取得 rand() 的种子 state([{what}]) 字符串 Vim 的当前状态 str2float({expr}) 浮点 转换字符串为浮点数 str2list({expr} [, {utf8}]) 列表 把 {expr} 的每个字符转换为 ASCII/UTF8 值 str2nr({expr} [, {base} [, {quoted}]]) 数值 把字符串转换为数值 strcharlen({expr}) 数值 字符串 {expr} 的字符长度 strcharpart({str}, {start} [, {len} [, {skipcc}]]) 字符串 {str} 从第 {start} 字符开始的 {len} 个 字符 strchars({expr} [, {skipcc}]) 数值 {expr} 字符串的字符计数 strdisplaywidth({expr} [, {col}]) 数值 {expr} 字符串的显示长度 strftime({format} [, {time}]) 字符串 使用指定格式排版时间 strgetchar({str}, {index}) 数值 从 {str} 取得字符 {index} stridx({haystack}, {needle} [, {start}]) 数值 {haystack}{needle} 的位置 string({expr}) 字符串 {expr} 值得字符串表示 strlen({expr}) 数值 字符串 {expr} 的长度 strpart({str}, {start} [, {len} [, {chars}]]) 字符串 {str}{start} 字节开始的 {len} 个字 节/字符 strptime({format}, {timestring}) 数值 把 {timestring} 转换为 unix 时间戳 strridx({haystack}, {needle} [, {start}]) 数值 {haystack} 里最后一个 {needle} 的位置 strtrans({expr}) 字符串 翻译字符串,使之可以显示 strwidth({expr}) 数值 {expr} 字符串的显示单元长度 submatch({nr} [, {list}]) 字符串/列表 ":s" 或 substitute() 的特定匹配 substitute({expr}, {pat}, {sub}, {flags}) 字符串 {expr} 里的所有 {pat}{sub} 替代 swapinfo({fname}) 字典 关于交换文件 {fname} 的信息 swapname({expr}) 字符串 缓冲区 {expr} 的交换文件 synID({lnum}, {col}, {trans}) 数值 {lnum}{col} 列所在的语法 ID synIDattr({synID}, {what} [, {mode}]) 字符串 syntax ID {synID}{what} 属性 synIDtrans({synID}) 数值 {synID} 经过翻译的语法 ID synconcealed({lnum}, {col}) 列表 关于隐藏的信息 synstack({lnum}, {col}) 列表 {lnum}{col} 列所在的语法 ID 堆栈 system({expr} [, {input}]) 字符串 外壳命令/过滤 {expr} 的输出 systemlist({expr} [, {input}]) 列表 外壳命令/过滤 {expr} 的输出 tabpagebuflist([{arg}]) 列表 标签页里的缓冲区号列表 tabpagenr([{arg}]) 数值 当前或最后标签页的编号 tabpagewinnr({tabarg} [, {arg}]) 数值 标签页里当前窗口的编号 tagfiles() 列表 使用的标签文件 taglist({expr} [, {filename}]) 列表 匹配 {expr} 的标签列表 tan({expr}) 浮点 {expr} 的正切值 tanh({expr}) 浮点 {expr} 的双曲正切值 tempname() 字符串 临时文件的文件名 term_dumpdiff({filename}, {filename} [, {options}]) 数值 显示两份截图的差异 term_dumpload({filename} [, {options}]) 数值 显示一份屏幕截图 term_dumpwrite({buf}, {filename} [, {options}]) 无 为终端窗口的内容进行截图 term_getaltscreen({buf}) 数值 取得备用屏幕标志位 term_getansicolors({buf}) 列表 取得 GUI 色彩模式的 ANSI 调色板 term_getattr({attr}, {what}) 数值 取得 {what} 属性的值 term_getcursor({buf}) 列表 取得终端光标位置 term_getjob({buf}) 作业 取得终端关联的作业 term_getline({buf}, {row}) 字符串 从终端取得一行文本行 term_getscrolled({buf}) 数值 取得终端的滚动数目 term_getsize({buf}) 列表 取得终端的大小 term_getstatus({buf}) 字符串 取得终端的状态 term_gettitle({buf}) 字符串 取得终端的标题 term_gettty({buf}, [{input}]) 字符串 取得终端的 tty 名 term_list() 列表 取得终端缓冲区的列表 term_scrape({buf}, {row}) 列表 取得终端屏幕的某行 term_sendkeys({buf}, {keys}) 无 给终端发送键序列 term_setansicolors({buf}, {colors}) 无 设置 GUI 色彩模式的 ANSI 调色板 term_setapi({buf}, {expr}) 无 设置 terminal-api 函数名前缀 term_setkill({buf}, {how}) 无 设置停止终端作业的信号值 term_setrestore({buf}, {command}) 无 设置恢复终端的命令 term_setsize({buf}, {rows}, {cols}) 无 设置终端的大小 term_start({cmd} [, {options}]) 数值 打开终端窗口并执行作业 term_wait({buf} [, {time}]) 数值 等待屏幕刷新 terminalprops() 字典 终端属性 test_alloc_fail({id}, {countdown}, {repeat}) 无 使内存分配失败 test_autochdir() 无 系统启动中启动 'autochdir' test_feedinput({string}) 无 给输入缓冲区增加键序列 test_garbagecollect_now() 无 为测试用,立即释放内存 test_garbagecollect_soon() 无 为测试用,尽快释放内存 test_getvalue({string}) 可变 得到内部变量的值 test_ignore_error({expr}) 无 忽略特定的错误 test_null_blob() blob 用作测试的空值 (null) test_null_channel() 通道 用作测试的空值 (null) test_null_dict() 字典 用作测试的空值 (null) test_null_function() 函数引用 用作测试的空值 (null) test_null_job() 作业 用作测试的空值 (null) test_null_list() 列表 用作测试的空值 (null) test_null_partial() 函数引用 用作测试的空值 (null) test_null_string() 字符串 用作测试的空值 (null) test_option_not_set({name}) 无 复位指示选项已设置的标志位 test_override({expr}, {val}) 无 Vim 内部覆盖用作测试 test_refcount({expr}) 数值 得到 {expr} 的引用计数 test_scrollbar({which}, {value}, {dragging}) 无 为测试用,在 GUI 内滚动 test_setmouse({row}, {col}) 无 为测试用,设置鼠标位置 test_settime({expr}) 无 用作测试的当前时间 test_srand_seed([seed]) 无 为 srand() 测试用,设置种子 test_unknown() 可变 用作测试的未知值 test_void() 可变 且作测试的无值 (void) timer_info([{id}]) 列表 定时器信息 timer_pause({id}, {pause}) 无 暂停或继续定时器 timer_start({time}, {callback} [, {options}]) 数值 新建定时器 timer_stop({timer}) 无 停止定时器 timer_stopall() 无 停止所有定时器 tolower({expr}) 字符串 字符串 {expr} 变为小写 toupper({expr}) 字符串 字符串 {expr} 变为大写 tr({src}, {fromstr}, {tostr}) 字符串 把 {src} 里的 {fromstr} 字符翻译为 {tostr} 字符 trim({text} [, {mask} [, {dir}]]) 字符串 从 {text} 中删除 {mask} 中的字符 trunc({expr}) 浮点 浮点数 {expr} 截断小数点 type({expr}) 数值 值 {expr} 的类型 typename({expr}) 字符串 {expr} 类型的描述 undofile({name}) 字符串 对应 {name} 的撤销文件名 undotree() 列表 撤销文件树 uniq({list} [, {func} [, {dict}]]) 列表 从列表中删除相邻的重复项 values({dict}) 列表 {dict} 的所有值 virtcol({expr}) 数值 光标或位置标记的屏幕列 visualmode([expr]) 字符串 最近使用的可视模式 wildmenumode() 数值 'wildmenu' 模式是否激活 win_execute({id}, {command} [, {silent}]) 字符串 在窗口 {id} 执行 {command} win_findbuf({bufnr}) 列表 寻找包含 {bufnr} 的窗口 win_getid([{win} [, {tab}]]) 数值 得到 {tab}{win} 的窗口 ID win_gettype([{nr}]) 字符串 窗口 {nr} 的类型 win_gotoid({expr}) 数值 转到 ID 为 {expr} 的窗口 win_id2tabwin({expr}) 列表 从窗口 ID 获得标签页与窗口 win_id2win({expr}) 数值 从窗口 ID 获得窗口号 win_screenpos({nr}) 列表 得到窗口 {nr} 的屏幕位置 win_splitmove({nr}, {target} [, {options}]) 数值 移动窗口 {nr} 成为 {target} 的分割窗口 winbufnr({nr}) 数值 窗口 {nr} 的缓冲区号 wincol() 数值 光标所在的窗口列 windowsversion() 字符串 MS-Windows 操作系统版本 winheight({nr}) 数值 窗口 {nr} 的高度 winlayout([{tabnr}]) 列表 标签页 {tabnr} 的窗口布局 winline() 数值 光标所在的窗口行 winnr([{expr}]) 数值 当前窗口的编号 winrestcmd() 字符串 返回恢复窗口大小的命令 winrestview({dict}) 无 恢复当前窗口的视图 winsaveview() 字典 保存当前窗口的视图 winwidth({nr}) 数值 窗口 {nr} 的宽度 wordcount() 字典 字节/字符/单词统计 writefile({object}, {fname} [, {flags}]) 数值 把行的 BlobList 写到文件 {fname} xor({expr}, {expr}) 数值 按位异或 abs({expr}) abs() 返回 {expr} 的绝对值。如果 {expr} 计算结果为浮点数,abs() 返回 浮点数。如果 {expr} 可以转换为数值,abs() 返回数值。否则报错并 返回 -1。 示例: echo abs(1.456) 1.456 echo abs(-5.456) 5.456 echo abs(-4) 4 也可用作 method : Compute()->abs() {仅当编译时加入 +float 特性才有效} acos({expr}) acos() 返回以弧度表示的 {expr} 的反余弦值,返回值为 [0, pi] 区间内的 浮点数。 {expr} 的计算结果必须是 [-1, 1] 区间内的浮点数或数值。 示例: :echo acos(0) 1.570796 :echo acos(-0.5) 2.094395 也可用作 method : Compute()->acos() {仅当编译时加入 +float 特性才有效} add({object}, {expr}) add() ListBlob {object} 最后附加项目 {expr}。返回新产生的 ListBlob 。例如: :let alist = add([1, 2, 3], item) :call add(mylist, "woodstock") 注意 如果 {expr}List ,它被作为单个项目附加进去。 extend() 可以用来连接 List 。 如果 {object}Blob{expr} 必须是个数值。 insert() 可以用来把一个项目加到其它的位置上。 也可用作 method : mylist->add(val1)->add(val2) and({expr}, {expr}) and() 对两个参数进行按位与。参数须转换为数值。列表、字典或浮点数参数 会报错。 示例: :let flag = and(bits, 0x80) 也可用作 method : :let flag = bits->and(0x80) append({lnum}, {text}) append() {text}List : 把每个 List 项目作为文本行,附加到当前 缓冲区第 {lnum} 行之下。 否则,把 {text} 作为单个文本行,附加于当前缓冲区第 {lnum} 行之 下。 接受任何项目,并转换为字符串。 {lnum} 可以为零,用于在第一行前插入一行。如果失败 ({lnum} 越 界),返回 1,成功则返回 0。例如: :let failed = append(line('$'), "# THE END") :let failed = append(0, ["Chapter 1", "the beginning"]) 也可用作列表的 method ,基是作为第二个参数传递的: mylist->append(lnum) appendbufline({expr}, {lnum}, {text}) appendbufline() 类似于 append() ,但在缓冲区 {expr} 中附加文本。 此函数只能用于已载入的缓冲区。有必要的话先调用 bufload(){expr} 的用法可见 bufname(){lnum} 的用法和 append() 类似。注意 使用 line() 会用到当前 缓冲区而不是正在进行附加的那个。 "$" 用来附加于缓冲区的末尾。 成功时返回 0,失败则返回 1。 如果 {expr} 不是合法的缓冲区或 {lnum} 不合法,报错。例如: :let failed = appendbufline(13, 0, "# THE START") 也可用作列表的 method ,基是作为第二个参数传递的: mylist->appendbufline(buf, lnum) argc([{winid}]) argc() 返回参数列表的文件数目。见 arglist 。 如果 {winid} 未给出,使用当前窗口的参数列表。 如果 {winid} 是 -1,使用全局参数列表。 否则,{winid} 指定参数列表所在的窗口: 窗口号或窗口 ID 均可。 如果 {winid} 参数不合法,返回 -1。 argidx() argidx() 返回参数列表的当前索引。0 是第一个文件。argc() - 1 是最后一 个。见 arglist arglistid() arglistid([{winnr} [, {tabnr}]]) 返回参数列表 ID,这是一个用来标识正在使用的参数列表的数值。零 代表全局参数列表。见 arglist 。 如果参数非法,返回 -1。 无参数时,使用当前窗口。 只提供 {winnr} 时,使用当前标签页的指定窗口。 同时提供 {winnr}{tabnr} 时,使用指定标签页的指定窗口。 {winnr} 可以是窗口号或 window-ID argv() argv([{nr} [, {winid}]]) 返回参数列表第 {nr} 个参数。见 arglist 。"argv(0)" 是第一个参 数。例如: :let i = 0 :while i < argc() : let f = escape(fnameescape(argv(i)), '. ') : exe 'amenu Arg.' . f . ' :e ' . f . '<CR>' : let i = i + 1 :endwhile 如果没有 {nr} 参数或 {nr} 为 -1,返回完整的 {arglist}List{winid} 参数指定窗口 ID,见 argc() 。 关于 Vim 的命令行参数,可见 v:argv 。 asin({expr}) asin() 返回以弧度表示的 {expr} 的反正弦值,返回值为 [-pi/2, pi/2] 区 间内的浮点数。 {expr} 的计算结果必须是 [-1, 1] 区间内的浮点数或数值。 示例: :echo asin(0.8) 0.927295 :echo asin(-0.5) -0.523599 也可用作 method : Compute()->asin() {仅当编译时加入 +float 特性才有效} assert_ 函数文档在这里: assert-functions-details atan({expr}) atan() 返回 {expr} 反正切的主值,返回值为 [-pi/2, +pi/2] 区间内的弧度 值浮点数。 {expr} 计算结果必须为浮点数或数值。 示例: :echo atan(100) 1.560797 :echo atan(-4.01) -1.326405 也可用作 method : Compute()->atan() {仅当编译时加入 +float 特性才有效} atan2({expr1}, {expr2}) atan2() 返回 {expr1} / {expr2} 的反正切值,以弧度计算,返回值为 [-pi, +pi] 区间内的浮点数。 {expr1}{expr2} 计算结果必须为浮点数或数值。 示例: :echo atan2(-1, 1) -0.785398 :echo atan2(1, -1) 2.356194 也可用作 method : Compute()->atan(1) (译者注: 原文如此) {仅当编译时加入 +float 特性才有效} balloon_gettext() balloon_gettext() 返回气泡的当前文本。只用于字符串,不用于列表。 balloon_show({expr}) balloon_show() 在气泡中显示 {expr}。GUI 上 {expr} 用作字符串。而终端上 {expr} 可以是多行的列表。如果 {expr} 不是列表,会用 balloon_split() 进行分割。 如果 {expr} 为空,删除任何已存在的气泡。 示例: func GetBalloonContent() " ... 启动内容的获取过程 return '' endfunc set balloonexpr=GetBalloonContent() func BalloonCallback(result) call balloon_show(a:result) endfunc 也可用作 method : GetText()->balloon_show() 期待的用法是从 'balloonexpr' 启动气泡内容的获取过程。它应调用 异步方法,然后在其回调中执行 balloon_show()。'balloonexpr' 自 身可返回空字符串或任何占位符。 如果不能显示气泡,不做任何事,不会报错。 {仅当编译时加入 +balloon_evalballoon_eval_term 特性才 有效} balloon_split({msg}) balloon_split() {msg} 分割为用于气泡中显示的多行。分割依据的是当前窗口大 小,并进行优化以显示调试器的输出。 返回分割后行的 List 。 也可用作 method : GetText()->balloon_split()->balloon_show() {仅当编译时加入 balloon_eval_term 特性才有效} browse() browse({save}, {title}, {initdir}, {default}) 启动文件请求窗口。只有在 "has("browse")" 返回 TRUE 时 (只有 在一些 GUI 版本里) 才可以。 输入的字段包括: {save} TRUE 时,选择要写入的文件 {title} 请求窗口的标题 {initdir} 开始浏览的目录 {default} 缺省文件名 如果按了 "Cancel" 按钮、出错、或者无法浏览,返回空字符串。 browsedir() browsedir({title}, {initdir}) 启动目录请求窗口。只有在 "has("browse")" 返回 TRUE 时 (只有 在一些 GUI 版本里) 才能工作。 有的系统上不支持目录浏览器,这时使用文件浏览器。此时: 选择要用 的目录里的文件。 输入的字段包括: {title} 请求窗口的标题 {initdir} 开始浏览的目录 如果按了 "Cancel" 按钮、出错、或者无法浏览,返回空字符串。 bufadd({name}) bufadd() 在缓冲区列表中加入名为 {name} 的缓冲区。 如果对应文件 {name} 的缓冲区已经存在,返回该缓冲区号。否则返回 新建缓冲区的号。{name} 为空串时,总是建立新缓冲区。 该缓冲区不置位 'buflisted' 也还未载入。要在缓冲区中增加文件: let bufnr = bufadd('someName') call bufload(bufnr) call setbufline(bufnr, 1, ['some', 'text']) 也可用作 method : let bufnr = 'somename'->bufadd() bufexists({expr}) bufexists() 返回数值,如果名为 {expr} 的缓冲区存在的话,返回 TRUE{expr} 参数是数值时,指定缓冲区号。数值零指定当前窗口的轮换缓 冲区。 {expr} 参数是字符串时,必须完全匹配指定缓冲区名。该名可以是: - 相对于当前目录。 - 完整路径。 - 'buftype' 设为 "nofile" 的缓冲区名。 - URL 名。 列表外缓冲区也会被找到。 注意 帮助文件在 :buffers 里列出的是它们的短名字。但 bufexists() 需要它们的长名字才能找到它们。 bufexists() 可能报告缓冲区存在,但要使其名字可用于 :buffer 命令,可能需用到 expand() 。尤其 MS-Windows 8.3 名字可能形 如 "c:\DOCUME~1"。 使用 "bufexists(0)" 可以测试是否存在轮换文件名。 也可用作 method : let exists = 'somename'->bufexists() 已废弃的名字: buffer_exists()。 buffer_exists() buflisted({expr}) buflisted() 返回数值,如果名为 {expr} 的缓冲区在列表内的话 (置位了 'buflisted' 选项),返回 TRUE{expr} 参数用法同 bufexists() 。 也可用作 method : let listed = 'somename'->buflisted() bufload({expr}) bufload() 确保缓冲区 {expr} 已载入。如果缓冲区名指向已存在的文件,读入该 文件。否则缓冲区会为空。如果缓冲区已载入,则没有改变。 如果缓冲区的文件已有交换文件,不会弹出对话框,还是会载入缓冲 区。 {expr} 参数的用法类似于 bufexists() 。 也可用作 method : eval 'somename'->bufload() bufloaded({expr}) bufloaded() 返回数值,如果名为 {expr} 的缓冲区存在且已载入的话 (在窗口显 示,或者至少被隐藏),返回 TRUE{expr} 参数用法同 bufexists() 。 也可用作 method : let loaded = 'somename'->bufloaded() bufname([{expr}]) bufname() 返回缓冲区的名字,如同 ":ls" 命令显示的那样。 如果 {expr} 省略使用当前缓冲区。 如果 {expr} 参数是数值,指定缓冲区号。数值零代表当前窗口的轮换 缓冲区。 如果 {expr} 参数是字符串,它用作 file-pattern 来匹配缓冲区名 字。这里总假设置位 'magic''cpoptions' 为空。如果有超过一个 匹配,返回空字符串。 "" 或 "%" 可用来指定当前缓冲区,"#" 指定轮换缓冲区。 完整的匹配优先,如果没有,也接受在缓冲区名的开始,结束和中间的 匹配。如果你只愿意接受完整的匹配,在模式的开始放上 "^",在结尾 放上 "$"。 先查找列表内缓冲区。如果列出缓冲区有唯一的匹配,返回之。不然, 再查找列表外的缓冲区。 如果 {expr} 是字符串,但你想用作缓冲区号,给它加零可以强制转化 为数值型: :echo bufname("3" + 0) 也可用作 method : echo bufnr->bufname() 如果缓冲区不存在,或者没有名字,返回空字符串。 bufname("#") 轮换缓冲区名 bufname(3) 缓冲区 3 的名字 bufname("%") 当前缓冲区名 bufname("file2") 匹配 "file2" 的缓冲区名。 buffer_name() 已废弃的名字: buffer_name()。 bufnr() bufnr([{expr} [, {create}]]) 返回缓冲区的编号,如同 ":ls" 命令显示的那样。关于 {expr} 的使 用,见上 bufname() 。 如果不存在符合的缓冲区,返回 -1。或者,如果提供了 {create} 参 数而且为 TRUE,建立一个新的列表外缓冲区,并返回其编号。例如: let newbuf = bufnr('Scratch001', 1) 这里空名会使用当前缓冲区。要创建新缓冲区可用 bufadd() 带空 名。 bufnr("$") 是最后一个缓冲区: :let last_buffer = bufnr("$") 返回数值,即最大的已有的缓冲区的编号。注意 较小的编号不一定都 对应存在的缓冲区,因为 ":bwipeout" 可能永久地删除了部分的缓冲 区。用 bufexists() 可以测试缓冲区是否存在。 也可用作 method : echo bufref->bufnr() 已废弃的名字: buffer_number()。 buffer_number() last_buffer_nr() bufnr("$") 已废弃的名字: last_buffer_nr()。 bufwinid({expr}) bufwinid() 返回数值,带缓冲区 {expr} 相关的第一个窗口的 window-ID{expr} 的用法见上述 bufname() 。 如果缓冲区 {expr} 不存在或没 有对应窗口,返回 -1。示例: echo "A window containing buffer 1 is " . (bufwinid(1)) 只处理当前标签页。 也可用作 method : FindBuffer()->bufwinid() bufwinnr({expr}) bufwinnr() bufwinid() 类似,但返回窗口号而不是 window-ID 。 如果缓冲区 {expr} 不存在或者没有对应的窗口,返回 -1。例如: echo "包含缓冲区 1 的窗口是 " . (bufwinnr(1)) 该编号可用于 CTRL-W_w 和 ":wincmd w" :wincmd 。 也可用作 method : FindBuffer()->bufwinnr() byte2line({byte}) byte2line() 返回当前缓冲区第 {byte} 个字节所在的行号。取决于当前缓冲区的 'fileformat' 选项,这可以包括不同的换行符。第一个字符的字节编 号为 1。 另见 line2byte()go:goto 。 也可用作 method : GetOffset()->byte2line() {仅当编译时加入 +byte_offset 特性才有效} byteidx({expr}, {nr}) byteidx() 返回字符串 {expr} 里第 {nr} 个字符的字节位置。零代表第一个字 符,此时返回零。 如果没有多字节字符,返回值总是等于 {nr}。 组合字符不单独计数,其字节长度加到其前导的基础字符上。要将组合 字符分别计数,见下 byteidxcomp() 。例如: echo matchstr(str, ".", byteidx(str, 3)) 显示第四个字符。另一个方法也能达到相同的效果: let s = strpart(str, byteidx(str, 3)) echo strpart(s, 0, byteidx(s, 1)) 另见 strgetchar()strcharpart() 。 如果字符数不足 {nr},返回 -1。 如果刚好 {nr} 个字符,返回字符串的字节长度。 也可用作 method : GetName()->byteidx(idx) byteidxcomp({expr}, {nr}) byteidxcomp() 类似于 byteidx(),但组合字符作为一个单独的字符计算。示例: let s = 'e' . nr2char(0x301) echo byteidx(s, 1) echo byteidxcomp(s, 1) echo byteidxcomp(s, 2) 第一个和第三个 echo 返回 3 ('e' 加上组合字符是 3 个字节),第二 个 echo 返回 1 ('e' 是一个字节)。 仅当 'encoding' 为某 Unicode 编码时,才和 byteidx() 有所不同。 也可用作 method : GetName()->byteidxcomp(idx) call({func}, {arglist} [, {dict}]) call() E699 调用函数 {func},使用 List {arglist} 项目作为参数。 {func} 可以是 Funcref 或函数名。 a:firstline 和 a:lastline 设为当前行。 返回调用的函数的结果。 {dict} 用于为函数指定 "dict" 属性。其目的是设置局部变量 "self"。 Dictionary-function 也可用作 method : GetFunc()->call([arg, arg], dict) ceil({expr}) ceil() 返回浮点数,即大于等于 {expr} 的最小整数 (向上取整)。 {expr} 的计算结果必须是浮点数或数值。 示例: echo ceil(1.456) 2.0 echo ceil(-5.456) -5.0 echo ceil(4.0) 4.0 也可用作 method : Compute()->ceil() {仅当编译时加入 +float 特性才有效} ch_ 函数文档在这里: channel-functions-details changenr() changenr() 返回最近改变的编号。这和 :undolist 显示的编号相同,可用于 :undo 命令。 如果发生了改变,返回的是此改变的编号。在重做以后,返回的是重做 的改变的编号。在撤销以后,返回撤销的改变的编号减一。 char2nr({expr} [, {utf8}]) char2nr() 返回 {expr} 第一个字符的数值结果。例如: char2nr(" ") 返回 32 char2nr("ABC") 返回 65 如果 {utf8} 省略或为零,使用当前的 'encoding'。比如对 "utf-8" 来说: char2nr("á") 返回 225 char2nr("á"[0]) 返回 195 如果 {utf8} 为 TRUE,则总视为 utf-8 字符。 组合字符是一个单独的字符。 nr2char() 是它的逆操作。 要把字符串转换为字符数值的列表: let str = "ABC" let list = map(split(str, '\zs'), {_, val -> char2nr(val)}) 结果是: [65, 66, 67] 也可用作 method : GetChar()->char2nr() charclass({string}) charclass() 返回 {string} 首个字符的字符类。 字符类为以下之一: 0 空白 1 标点 2 单词字符 3 表情符号 其它 特定 Unicode 类 此类用于模式匹配和单词动作。 charcol() charcol({expr}) 同 col() ,但返回 {expr} 给出列的位置字符索引而不是字节索引。 示例: 如果光标在第五行文本 "여보세요" 的 '세' 时: charcol('.') 返回 3 col('.') 返回 7 也可用作 method : GetPos()->col() charidx() charidx({string}, {idx} [, {countcc}]) 返回 {string}{idx} 个字节对应的字符索引。首个字符的索引为 零。 如果没有多字节字符,返回值自然等于 {idx}。 如果 {countcc} 省略或为零,组合字符不单独计算,它们的字节长度 被加入前导的基本字符。 如果 {countcc} 设为 1,组合字符算作单独的字符。 如果参数非法或 {idx} 大于 {string} 末字节的索引,返回 -1。如果 首个参数不是字符串、第二个参数不是数值或第三个参数存在且非零或 一,报错。 关于如何从字符索引来获取字节索引,可见 byteidx()byteidxcomp() 。 示例: echo charidx('áb́ć', 3) 返回 1 echo charidx('áb́ć', 6, 1) 返回 4 echo charidx('áb́ć', 16) 返回 -1 也可用作 method : GetName()->charidx(idx) chdir({dir}) chdir() 切换当前工作目录为 {dir}。目录改变的作用域取决于当前窗口的目 录: - 如果当然窗口有局部于窗口的目录 ( :lcd ),则改变局部 于窗口的目录。 - 否则,如果当前标签页有局部目录 ( :tcd ),则改变局部 于标签页的目录。 - 否则,返回全局目录。 如果成功,返回上次的工作目录。把它传给另一个 chdir() 会恢复上 次目录。 如果失败,返回空串。 示例: let save_dir = chdir(newdir) if save_dir != "" " ... 做点事 call chdir(save_dir) endif 也可用作 method : GetDir()->chdir() cindent({lnum}) cindent() 得到第 {lnum} 行根据 C 缩进规则应有的缩进距离,见 'cindent'。 缩进的计算以空格计,因而和 'tabstop' 的值是有关系的。{lnum} 的 使用方式和 getline() 相同。 如果 {lnum} 非法或者 Vim 编译时不带 +cindent 特性,返回 -1。 见 C-indenting 。 也可用作 method : GetLnum()->cindent() clearmatches([{win}]) clearmatches() 清除之前 matchadd():match 命令为当前窗口定义的匹配。 如果给出 {win},使用指定窗口号或窗口 ID 的窗口而不是当前窗口。 也可用作 method : GetWin()->clearmatches() col() col({expr}) 返回数值,即 {expr} 给定的列位置的字节索引。可接受的位置是: . 光标位置 $ 光标行的行尾 (返回光标行的字节数加 1) 'x 位置标记 x 的位置 (如果该位置标记没有设置,返回 0) v 可视模式下: 可视区域的开始位置 (光标是结束位置)。 如果不在可视模式下,返回当前光标位置。和 '< 不同 的是,会被立即更新。 另外,{expr} 可以是 [lnum, col]: 包含行号和列号的 List 。常用 于指定列号为 "$" 以得到特定行的末列列号。如果 "lnum" 或 "col" 超出范围,col() 返回零。 要得到行号用 line() 。两者都要用 getpos() 。 要得到屏幕列的位置,用 virtcol() 。要得到字符位置,用 charcol()注意 只能使用当前文件的位置标记。 例如: col(".") 光标所在列 col("$") 光标行的长度加 1 col("'t") 位置标记 t 的列号 col("'" . markname) 等于 markname 的位置标记的列号 第一列为 1。0 用来返回错误。 大写位置标记的对应列可能在另一个缓冲区中。 如果激活了 'virtualedit' 并且如果光标在行尾之后的话,计算光标 位置得到的列号比实际的多 1。可用来在插入模式得到列数: :imap <F2> <C-O>:let save_ve = &ve<CR> \<C-O>:set ve=all<CR> \<C-O>:echo col(".") . "\n" <Bar> \let &ve = save_ve<CR> 也可用作 method : GetPos()->col() complete({startcol}, {matches}) complete() E785 设置插入模式补全的匹配。 只能用于插入模式。需要使用 CTRL-R = 的映射 (见 i_CTRL-R )。不 能在 CTRL-O 之后或者在表达式映射里使用。 {startcol} 是行内待补全文本开始的字节偏移。直到光标为止的文本 就是原始的文本,它将要被匹配所替代。用 col('.') 会得到空串。而 "col('.') - 1" 将用匹配替换单个字符。 {matches} 必须是 List 。每个 List 项目是一个匹配。 complete-items 说明可能的项目类型。 注意 调用此函数后,你不应插入任何使补全停止的内容。 用 CTRL-NCTRL-P 选择匹配,就像普通的插入模式补全那样。如果 指定,会出现弹出菜单,见 ins-completion-menu 。 示例: inoremap <F5> <C-R>=ListMonths()<CR> func! ListMonths() call complete(col('.'), ['January', 'February', 'March', \ 'April', 'May', 'June', 'July', 'August', 'September', \ 'October', 'November', 'December']) return '' endfunc 此例并不很有用,但可以说明功能。注意这里返回空串,以免插入零。 也可用作 method ,基是作为第二个参数传递的: GetMatches()->complete(col('.')) complete_add({expr}) complete_add() {expr} 加到匹配的列表里。只能用于 'completefunc' 选项指定的 函数里。 返回 0 代表失败 (空字符串或者内存不足),1 代表加入了匹配,2 代 表匹配已经在列表里。 complete-functions 解释 {expr}。它和 'omnifunc' 应该返回的列 表中单个项目相同。 也可用作 method : GetMoreMatches()->complete_add() complete_info() complete_info([{what}]) 返回关于插入模式补全信息的 Dictionary 。见 ins-completion 。 项目是: mode 当前补全模式名的字符串。 可用值见 complete_info_mode 。 pum_visible 如果弹出菜单可见则为 TRUE 。 见 pumvisible() 。 items 补全匹配的列表。每个项目是包含项目 "word"、 "abbr"、"menu"、"kind"、"info" 和 "user_data" 的字典。 见 complete-items 。 selected 选中项目的索引。首个索引为零。如果没有选中的项 目则索引为 -1 (只显示输入的文本) inserted 插入的字符串。[尚未实现] complete_info_mode mode 值是: "" 不在补全模式中 "keyword" 关键字补全 i_CTRL-X_CTRL-N "ctrl_x" 刚按了 CTRL-X i_CTRL-X "whole_line" 整行 i_CTRL-X_CTRL-L "files" 文件名 i_CTRL-X_CTRL-F "tags" 标签 i_CTRL-X_CTRL-] "path_defines" 定义补全 i_CTRL-X_CTRL-D "path_patterns" 头文件补全 i_CTRL-X_CTRL-I "dictionary" 字典 i_CTRL-X_CTRL-K "thesaurus" 同义词词典 i_CTRL-X_CTRL-T "cmdline" Vim 命令行 i_CTRL-X_CTRL-V "function" 用户定义补全 i_CTRL-X_CTRL-U "omni" 全能补全 i_CTRL-X_CTRL-O "spell" 拼写建议 i_CTRL-X_s "eval" complete() 补全 "unknown" 其它内部模式 如果提供可选的 {what} 列表参数,只返回 {what} 中列出的项目。 {what} 中不支持的项目被安静地跳过。 要得到弹出菜单的位置和大小,可见 pum_getpos() 。也可通过 CompleteChanged 事件中的 v:event 得到。 示例: " 取得所有项目 call complete_info() " 只要 'mode' call complete_info(['mode']) " 只要 'mode' 和 'pum_visible' call complete_info(['mode', 'pum_visible']) 也可用作 method : GetItems()->complete_info() complete_check() complete_check() 寻找补全匹配时,检查输入的键。如果寻找匹配需要一定时间时有用。 如果匹配的搜索被中止,返回 TRUE 。否则返回零。 只能用于 'completefunc' 选项指定的函数里。 confirm() confirm({msg} [, {choices} [, {default} [, {type}]]]) confirm() 提供用户一个对话框,从中可以作出选择。返回选择的序 号。第一个选择为 1。 注意: confirm() 只有在编译时加入对话框支持才存在,见 +dialog_con+dialog_gui 。 在 dialog 里显示 {msg} 消息,并提供可能的选择 {choices}。如 果 {choices} 不存在或者为空,使用 "&OK" (经过翻译)。 {msg} 是字符串,'\n' 用来包含换行符。在有些系统上该字符串在放 不下时被回绕,但并非所有系统都如此。 {choices} 是一个字符串,用 '\n' 分隔各个选择,例如 confirm("Save changes?", "&Yes\n&No\n&Cancel") '&' 之后的字符提供该选择的快捷键。这样,你可以输入 'c' 来选择 "Cancel"。快捷键不一定是第一个字符: confirm("file has been modified", "&Save\nSave &All") 控制台里,每个选择的第一个字符用作缺省的快捷键。忽略大小写。 可选的 {default} 参数是用户按 <CR> 使用的选择号。设定 1 使得第 一个选项成为缺省,如果是 0,则不设定任何缺省。如果不提供 {default},假设为 1。 可选的 {type} 参数指定对话框的类型。只有在 GTK、Mac、Motif 和 Win32 GUI 上才用得上,它用以指定图标。可以取的值是: "Error"、 "Question"、"Info"、"Warning" 或 "Generic"。只有第一个字符是重 要的。如果忽略 {type},使用 "Generic"。 如果用户用 <Esc>CTRL-C 或者别的合法的中断键中止对话框, confirm() 返回 0。 一个例子: :let choice = confirm("你要吃什么?", "&苹果\n&桔子\n&香蕉", 2) :if choice == 0 : echo "快下定决心!" :elseif choice == 3 : echo "好吃" :else : echo "我本人喜欢香蕉。" :endif GUI 的对话框使用按钮。按钮的排放方式取决于 'guioptions' 里的 'v' 标志位。如果包含该标志位,按钮总是竖排的。不然,confirm() 试图把按钮放在一行里。如果放不下,那么还是使用竖排的方式。在有 的系统上,无论如何总是使用横排。 也可用作 method : BuildMessage()->confirm("&Yes\n&No") copy() copy({expr}) 构造 {expr} 的备份。对数值和字符串而言,这和直接使用 {expr} 并无不同。 如果 {expr}List ,建立一个浅备份。这意味着,原来的 List 可以被改变,而不会影响新建的备份。反之亦然。不过,其中的项目只 有一份,所以修改项目同时修改两个 List 的内容。 Dictionary 的复制和 List 类似。 另见 deepcopy() 。 也可用作 method : mylist->copy() cos({expr}) cos() 返回浮点数,即以弧度测量的 {expr} 的余弦值。 {expr} 的计算结果必须是浮点数或数值。 示例: :echo cos(100) 0.862319 :echo cos(-4.01) -0.646043 也可用作 method : Compute()->cos() {仅当编译时加入 +float 特性才有效} cosh({expr}) cosh() 返回 {expr} 的双曲余弦值,返回值为 [1, inf] 区间内的浮点数。 {expr} 的计算结果必须是浮点数或数值。 示例: :echo cosh(0.5) 1.127626 :echo cosh(-0.5) -1.127626 也可用作 method : Compute()->cosh() {仅当编译时加入 +float 特性才有效} count({comp}, {expr} [, {ic} [, {start}]]) count() 返回 StringListDictionary {comp} 里值为 {expr} 的 项目出现的次数。 如果给出 {start},从该索引指定的项目开始。{start} 只能用于 List 。 如果给出 {ic} 并且为 TRUE ,忽略大小写。 {comp} 为字符串时返回 {expr} 不重叠的出现次数。{expr} 为空串时 返回零。 也可用作 method : mylist->count(val) cscope_connection() cscope_connection([{num} , {dbpath} [, {prepend}]]) 检查 cscope 连接是否存在。如果没有参数,则函数返回: 0,如果 cscope 不存在 (编译没有带该特性),或者不存在 cscope 连接; 1,如果至少有一个 cscope 连接。 如果指定了参数,那么 {num} 的值指定如何检查 cscope 连接存在与 否的方式: {num} 存在检查的方式描述 ----- ------------------------------ 0 等同于无参数 (例如,"cscope_connection()")。 1 忽略 {prepend},使用 {dbpath} 的字符串部分匹配。 2 忽略 {prepend},使用 {dbpath} 的字符串完整匹配。 3 使用 {prepend},使用 {dbpath}{prepend} 的字符串部 分匹配。 4 使用 {prepend},使用 {dbpath}{prepend} 的字符串完 整匹配。 注意: 所有的字符串比较都对大小写敏感! 示例。假定我们有如下设置 (":cs show" 的输出): # pid database name prepend path 0 27664 cscope.out /usr/local 启动方式 返回值 ---------- ---------- cscope_connection() 1 cscope_connection(1, "out") 1 cscope_connection(2, "out") 0 cscope_connection(3, "out") 0 cscope_connection(3, "out", "local") 1 cscope_connection(4, "out") 0 cscope_connection(4, "out", "local") 0 cscope_connection(4, "cscope.out", "/usr/local") 1 cursor({lnum}, {col} [, {off}]) cursor() cursor({list}) 把光标定位在第 {lnum} 行的第 {col} 列 (字节计数)。第一列为 1。 如果只有一个参数 {list},它被看作带两个、三个或四个参数的 List : [{lnum}, {col}] [{lnum}, {col}, {off}] [{lnum}, {col}, {off}, {curswant}] 和 getpos()getcurpos() 的返回值类似,但没有第一项。 要用字符计数来定位光标,用 setcursorcharpos() 。 不改变跳转表。 如果 {lnum} 超过缓冲区的行数,光标定位在缓冲区的末行。 如果 {lnum} 为零,光标留在当前行。 如果 {col} 超过该行的字节数,光标定位在该行的最后一个字符上。 如果 {col} 为零,光标留在当前列。 如果 {curswant} 给出,它被用于设置垂直移动的首选列,否则使用 {col}。 如果使用 'virtualedit'{off} 指定从该字符开始以屏幕列计算的偏 移。例如,在制表里或者在最后一个字符之后的某个位置。 如果定位成功,返回 0,否则返回 -1。 也可用作 method : GetCursorPos()->cursor() debugbreak({pid}) debugbreak() 专用于中断待调试的程序。给进程 {uid} 发送 SIGTRAP。其它进程的 行为未指定。见 terminal-debugger{仅适用于 MS-Windows} 也可用作 method : GetPid()->debugbreak() deepcopy({expr} [, {noref}]) deepcopy() E698 构造 {expr} 的备份。对数值和字符串而言,这和直接使用 {expr} 并无不同。 如果 {expr}List ,建立一个完整的备份。这意味着,原来的 List 可以被改变,而不会影响新建的备份。反之亦然。如果某个项 目是 ListDictionary ,递归地建立它的备份。这样,备份里 项目的修改也不会影响到原来 List 的内容。 Dictionary 的复制和 List 类似。 如果省略 {noref} 或为零,包含的 ListDictionary 只复制 一次。所有指向它的引用指向此一备份。如果 {noref} 设为 1,每次 ListDictionary 的出现会导致建立一个新的备份。这意味着 循环引用会使得 deepcopy() 失败。 E724 嵌套可达 100 层。如果有指向较高层的引用,{noref} 为 1 的深备份 会失败。 另见 copy() 。 也可用作 method : GetObject()->deepcopy() delete({fname} [, {flags}]) delete() {flags}{flags} 为空: 删除名为 {fname} 的文件。{fname} 是符号链接也可以。 如果 {flags} 是 "d": 删除名为 {fname} 的目录。如果目录 {fname} 非空会失败。 如果 {flags} 是 "rf": 递归删除名为 {fname} 的目录和其下的所有 文件。 要小心备注: 在 MS-Windows 上不能删除正在使用的目录。 符号链接本身被删除,而不是它链接到的文件。 返回类型为数值。如果成功删除文件,返回 0/false,如果删除失败或 部分失败,返回 -1/御前。 从 List 里删除项目请用 remove() 。 要删除缓冲区的行用 :deletedeletebufline() 。 也可用作 method : GetName()->delete() deletebufline({expr}, {first} [, {last}]) deletebufline() 删除缓冲区 {expr}{first}{last} (闭区间) 的文本行。 如果省略 {last},只删除第 {first} 行。 成功时返回 0,失败时返回 1。 此函数只能用于已载入的缓冲区。有必要的话先调用 bufload(){expr} 的用法见上述的 bufname(){first}{last} 的用法类似于 getline()注意 line() 指定 当前缓冲区。"$" 指定缓冲区 {expr} 的末行。 也可用作 method : GetBuffer()->deletebufline(1) did_filetype() did_filetype() 如果执行自动命令时,激活 FileType 事件至少一次,则返回 TRUE 。可以用于防止在检测文件类型的脚本里再次激活 FileType 事 件。 FileType 如果用过 ":setf FALLBACK",返回 FALSE 。 如果编辑另外一个文件,该计数被复位,因而这只能检查 FileType 事 件是否在当前缓冲区里激活过。它允许开始编辑另一个缓冲区的自动命 令设置 'filetype' 并载入语法文件。 diff_filler({lnum}) diff_filler() 返回第 {lnum} 行之上的填充行的数目。 这些是在另一个进行比较的窗口里在此位置插入的行。这些填充行在屏 幕上显示,但缓冲区里并不存在。 {lnum} 的用法类似于 getline() 。所以 "." 是当前行,"'m" 是位 置标记 m,等等。 如果当前窗口不处于比较模式,返回 0。 也可用作 method : GetLnum()->diff_filler() diff_hlID({lnum}, {col}) diff_hlID() 返回比较模式下行 {lnum} 和列 {col} (字节位置) 所在的高亮 ID。 如果当前行没有差异,返回零。 {lnum} 的用法类似于 getline() 。所以 "." 是当前行,"'m" 是位 置标记 m,等等。 最左列的 {col} 为 1,第一行的 {lnum} 为 1。 高亮 ID 可以用于 synIDattr() ,以得到高亮对应的语法信息。 也可用作 method : GetLnum()->diff_hlID(col) echoraw({expr}) echoraw() 照原样输出 {expr},包括非显示字符。可用于输出终端代码。例如, 要关闭 modifyOtherKeys: call echoraw(&t_TE) 要再次打开之: call echoraw(&t_TI) 使用时要小心,容易把终端搞乱。 empty({expr}) empty() 如果 {expr} 为空,返回数值 1,否则返回 0。 - ListDictionary 没有项目时为空。 - String 的长度为零时为空。 - NumberFloat 的值为零时为空。 - v:falsev:nonev:null 为空, v:true 不是。 - 启动失败的 Job 为空。 - 己关闭的 Channel 为空。 - Blob 的长度为零时为空。 如果 List 很大,这比把长度和零比较要快得多。 也可用作 method : mylist->empty() environ() environ() 返回所有的环境变量构成的字典。可以这样检查某个环境变量是否存 在: :echo has_key(environ(), 'HOME') 注意 变量名可以是驼峰式 (CamelCase) 的,要忽略大小写,可以这 样: :echo index(keys(environ()), 'HOME', 0, 1) != -1 escape({string}, {chars}) escape() {string} 里用反斜杠转义 {chars} 里的字符。例如: :echo escape('c:\program files\vim', ' \') 返回: c:\\program\ files\\vim 另见 shellescape()fnameescape() 。 也可用作 method : GetText()->escape(' \') eval() eval({string}) 计算 {string} 并返回其结果。这对把 string() 的结果转换为原来 的值尤其有用。适用于数值、浮点数、字符串、blob 和它们的复合类 型。也可用于指向已有函数的 Funcref 。 也可用作 method : argv->join()->eval() eventhandler() eventhandler() 如果在事件处理中则返回 1。此时,Vim 在等待用户输入一个字符的时 候被中断,比如,在 Vim 上拖放了一个文件。这也意味着此时不能使 用交互的命令。如果不是,返回零。 executable({expr}) executable() 本函数检查名字由 {expr} 指定的可执行文件存在与否。{expr} 必须 是程序不带任何参数的名字。 executable() 使用 $PATH 的值和/或程序的普通的搜索路径。 PATHEXT MS-Windows 上,可以可选地包含 ".exe"、".bat" 等。为此, $PATHEXT 里的扩展名会被尝试。这样,如果 "foo.exe" 不存在,可能 会找到 "foo.exe.bat"。如果没有设置 $PATHEXT,使用的是 ".com;.exe;.bat;.cmd"。$PATHEXT 里可以使用单独的句号,以尝试没 有扩展名的名字。如果 'shell' 看起来像 Unix 外壳,那么也尝试没 有扩展名的名字。 MS-Windows 上,只检查是否文件存在且不是目录,并不检查它是否真 的可以执行。 MS-Windows 上,和 Vim 在同一目录的可执行文件总能找到。因为这个 目录加到了 $PATH 里,执行应该也没有问题 win32-PATH 。 返回数值: 1 存在 0 不存在 -1 此系统中没有实现 exepath() 可用于获取可执行文件的完整路径。 也可用作 method : GetCommand()->executable() execute({command} [, {silent}]) execute() 执行 Ex 命令或命令序列,返回结果为字符串。 {command} 可以是字符串或列表。如果是列表,逐行执行命令。 等价于: redir => var {command} redir END 可选的 {silent} 参数可取以下的值: "" 不用 :silent "silent" 用 :silent "silent!" 用 :silent! 缺省是 "silent"。注意 用 "silent!" 时,和 :redir 不同,错误 被忽略。使用外部命令时,屏幕可能会搞乱,可用 system() 代替。 E930 {command} 里不可用 :redir 。 要得到行的列表,在结果上用 split() : split(execute('args'), "\n") 要在非当前窗口的其它窗口中执行命令,用 win_execute() 。 递归调用时,内层的输出结果不包含在外层的结果里。 也可用作 method : GetCommand()->execute() exepath({expr}) exepath() 如果 {expr} 是可执行文件并且是绝对路径、相对路径或可在 $PATH 是找到,返回完整路径。 注意 如果 {expr} 以 "./" 开始,使用当前路径,这对 Vim 可能是个 问题: echo exepath(v:progpath) 如果 {expr} 在 $PATH 里找不到,或者不可执行,返回空字符串。 也可用作 method : GetCommand()->exepath() exists() exists({expr}) 返回数值,如果 {expr} 被定义,返回 TRUE ,不然返回零。 要检查某特性是否支持,用 has() 。 要检查文件是否存在,用 filereadable(){expr} 参数是字符串,可以使用以下选择之一: &option-name Vim 选项 (只检查是否存在,而不是是否工 作) +option-name 能工作的 Vim 选项。 $ENVNAME 环境变量 (也可以通过和空字符串比较完 成) *funcname 已实现的内建函数 (见 functions ) 或者 用户定义的函数 (见 user-functions )。 也可用于指向函数引用的变量。 ?funcname 可实现的内建函数;用于检查 "funcname" 是否合法 varname 内部变量 (见 internal-variables )。也 适用于 curly-braces-namesDictionary 项目、 List 项目等等。 小心计算索引时可能会因为非法的表达式产 生错误信息。例如: :let l = [1, 2, 3] :echo exists("l[5]") 0 :echo exists("l[xx]") E121: Undefined variable: xx 0 :cmdname Ex 命令: 内建命令、用户命令或者命令修 饰符 :command 。 返回: 1 匹配命令的开始 2 完整匹配命令 3 匹配多个用户命令 要检查命令是否支持,检查返回值是否为 2。 :2match :2match 命令。 :3match :3match 命令。 #event 符合此事件的自动命令 #event#pattern 符合此事件和此模式的自动命令 (模式按本 义出现,和自动命令的模式逐字符比较) #group 存在自动命令组 #group#event 在该组里定义并符合此事件的自动命令。 #group#event#pattern 为该组定义、符合事件和模式的自动命令。 ##event 支持此事件的自动命令。 例如: exists("&shortname") exists("$HOSTNAME") exists("*strftime") exists("*s:MyFunc") exists("bufcount") exists(":Make") exists("#CursorHold") exists("#BufReadPre#*.gz") exists("#filetypeindent") exists("#filetypeindent#FileType") exists("#filetypeindent#FileType#*") exists("##ColorScheme") 符号 (&/$/*/#) 和名字之间不能有空格。 名字之后不能有附加字符,虽然现在有一些情况下会忽略这些字符,但 将来的检查可能更严格。所以不要依赖此行为! 可以通过的例子: exists(":make") 能通过的例子: exists(":make install") 注意 参数必须是字符串,不是变量的名字本身。例如: exists(bufcount) 不检查 "bufcount" 变量是否存在,而是提取 "bufcount" 的值,并检 查其 (根据此处的语法) 是否存在。 也可用作 method : Varname()->exists() exp({expr}) exp() 返回 {expr} 的指数函数值,返回值为 [0, inf] 区间内的浮点数。 {expr} 的计算结果必须是浮点数或数值。 示例: :echo exp(2) 7.389056 :echo exp(-1) 0.367879 也可用作 method : Compute()->exp() {仅当编译时加入 +float 特性才有效} expand({expr} [, {nosuf} [, {list}]]) expand() 扩展 {expr} 里的通配符和下列特殊关键字。 'wildignorecase' 此处适用。 如果给出 {list} 且为 TRUE ,返回列表。否则返回的是字符串,且 如果返回多个匹配,以 <NL> 字符分隔 [备注: 5.0 版本使用空格。但 是文件名如果也包含空格就会有问题]。 如果扩展失败,返回空字符串。如果 {expr} 以 '%','#' 或 '<' 开 始,不返回不存在的文件名。详见下。 如果 {expr} 以 '%'、'#' 或 '<' 开始,以类似于 cmdline-special 变量的方式扩展,包括相关的修饰符。这里是一个 简短的小结: % 当前文件名 # 轮换文件名 #n 轮换文件名 n <cfile> 光标所在的文件名 <afile> 自动命令文件名 <abuf> 自动命令缓冲区号 (以字符串形式出现!) <amatch> 自动命令匹配的名字 <cexpr> 光标所在的 C 表达式 <sfile> 载入的脚本文件或函数名 <slnum> 载入脚本文件行号或函数行号 <sflnum> 脚本文件行号,即使在函数中亦然 <SID> "<SNR>123_" 其中 "123" 是当前脚本 ID <SID> <stack> 调用栈 <cword> 光标所在的单词 <cWORD> 光标所在的字串 (WORD) <client> 最近收到的消息的 {clientid} server2client() 修饰符: :p 扩展为完整的路径 :h 头部 (去掉最后一个部分) :t 尾部 (只保留最后一个部分) :r 根部 (去掉一个扩展名) :e 只有扩展名 例如: :let &tags = expand("%:p:h") . "/tags" 注意 扩展 '%'、'#' 或者 '<' 开头的字符串的时候,其后的文本被忽 略。这样 行: :let doesntwork = expand("%:h.bak") 应该这样: :let doeswork = expand("%:h") . ".bak" 还要 注意 扩展 "<cfile>" 和其它形式只能返回被引用的文件名,而 不会进一步扩展。如果 "<cfile>" 是 "~/.cshrc",你需要执行另一个 expand() 把 "~/" 扩展为主目录的路径: :echo expand(expand("<cfile>")) 变量名和其后的修饰符之间不能有空白。 fnamemodify() 函数可以用 来修改普通的文件名。 使用 '%' 或 '#' 但当前或轮换文件名没有定义的时候,使用空字符 串。在无名缓冲区使用 "%:p" 生成当前目录,后加一个 '/'。 如果 {expr} 不以 '%'、'#' 或 '<' 开始,它以命令行上的文件名那 样被扩展。使用 'suffixes''wildignore',除非给出可选的 {nosuf} 参数而且为 TRUE 。 这里可以有不存在的文件的名字。"**" 项目可以用来在目录树里查 找。例如,要寻找当前目录及其下目录的所有的 "README": :echo expand("**/README") expand() 也可用来扩展变量和只有外壳知道的环境变量。但这会很 慢,因为需要使用外壳才能进行扩展。见 expr-env-expand 。 扩展后的变量还是被当作文件名的列表处理。如果不能扩展环境变量, 保留其不变。这样,":echo expand('$FOOBAR')" 返回的还是 "$FOOBAR"。 glob() 说明如何找到存在的文件。 system() 说明如何得到外部命 令的原始输出。 也可用作 method : Getpattern()->expand() expandcmd({expr}) expandcmd() :edit 这样的 Ex 命令那样扩展 {expr} 里的特殊项目。在 {expr} 的所有位置像 expand() 那样扩展特殊关键字,也扩展环境 变量。"~user" 和 "~/path" 只在开始处被扩展。 返回扩展后的字符串。示例: :echo expandcmd('make %<.o') 也可用作 method : GetCommand()->expandcmd() extend({expr1}, {expr2} [, {expr3}]) extend() {expr1}{expr2} 必须都是 List 或者都是 Dictionary 。 如果都是 List : 把 {expr2} 附加到 {expr1} 之后。 如果给出 {expr3},把 {expr2} 里的项目加到 {expr1} 中索引为 {expr3} 的项目之前。如果 {expr3} 为零,插在第一个项目之前。如 果 {expr3} 等于 len({expr1}),那么 {expr2} 会附加在最后。 例如: :echo sort(extend(mylist, [7, 5])) :call extend(mylist, [2, 3], 1) 如果 {expr1}{expr2} 是同一个列表,复制的项目数等于列表原来 的长度。例如,如果 {expr} 为 1,则复制列表首值 N 次 (N 是列表 原来的长度)。 用 add() 把一个项目加入列表。要连接两个列表成为一个新列表, 用 + 操作符: :let newlist = [1, 2, 3] + [4, 5] 如果都是 Dictionary : 把 {expr2} 里的所有项目加入 {expr1}。 如果 {expr1}{expr2} 包含相同的键,那么 {expr3} 决定应该怎 么做: {expr3} = "keep": 保持 {expr1} 的值 {expr3} = "force": 使用 {expr2} 的值 {expr3} = "error": 给出错误信息 E737 如果省略 {expr3},假设使用 "force"。 只要 {expr2} 非空,{expr1} 就被改变。如果需要,给 {expr1} 先做 个备份。 {expr2} 保持不变。 如果 {expr1} 被锁住且 {expr2} 非空,操作失败。 返回 {expr1}。 也可用作 method : mylist->extend(otherlist) extendnew({expr1}, {expr2} [, {expr3}]) extendnew() extend() 类似,但不是新增项目到 {expr1},而是创建并返回新 列表或字典。{expr1} 保持不变。项目仍然可用 {expr2} 改变,如果 不想如此,可先用 deepcopy() 。 feedkeys({string} [, {mode}]) feedkeys() {string} 里的字符放在队列里等候处理,就像它们来自映射或者用 户输入一样。 缺省它们加在预输入 (typeahead) 缓冲区的尾端,所以如果 仍然在执行映射,这些字符会出现在映射内容之后。用 'i' 标志位则 插入位置在其它字符之前,这样,它们在映射其它字符之前就会执行。 该函数不会等待 {string} 包含的键处理完毕。 {string} 如果要包含特殊键,可以使用双引号和 "\..." 记法 expr-quote 。例如,feedkeys("\<CR>") 会模拟 <Enter> 键击。但 feedkeys('\<CR>') 却实际压入五个字符。 一个可能有用的特殊代码是 <Ignore>,它会结束等待字符输入而不做 任何事。 <Ignore> {mode} 是字符串,包含以下字符标志位: 'm' 对键重映射。缺省。如果不给出 {mode},键会经过重映射。 'n' 不对键重映射。 't' 像用户输入那样处理键;如果不包含,像来自映射一样处理。 这会影响撤销、打开折叠等行为。 'L' 底层输入。只用于 Unix 或 GUI。键的使用就像来自终端那 样。不使用其它标志位。 E980 CTRL-C 中断且包含 't' 标志位时,设置内部 "got_int" 标 志位。 'i' 插入字符串而不是附加 (见上)。 'x' 执行命令,直至预输入为空为止。和 ":normal!" 类似。可以 不带 'x' 执行 feedkeys() 数次,然后一次性执行带 'x' 的 (可以只带空 {string}) 来执行所有的输入。注意 Vim 退出 插入模式时行为就如同按了 <Esc> 那样,以避免在脚本可以 继续前等待字符键入的阻塞情况。 注意 你执行命令时调用了 feedkeys(),会导致递归调用,而 所有的预输入会被最后的那个调用消耗。 '!' 使用 'x' 时不停止插入模式。可用于使定时器稍晚点才退出 插入状态的测试环境。对测试 CursorHoldI 有用。 返回值总为 0。 也可用作 method : GetInput()->feedkeys() filereadable({file}) filereadable() 返回数值,如果名为 {file} 的文件存在且可读,则为 TRUE 。如果 {file} 不存在,或者是一个目录,返回 FALSE{file} 可以是任何 返回字符串的表达式。 如果你不关心文件是否可读,可用 glob() 。 按本义使用 {file},你可能需要先扩展通配符: echo filereadable('~/.vimrc') 0 echo filereadable(expand('~/.vimrc')) 1 也可用作 method : GetName()->filereadable() file_readable() 已废弃的名字: file_readable()。 filewritable({file}) filewritable() 返回数值,如果名为 {file} 的文件存在且可写,则为 1。如果 {file} 不存在,或者不可写,返回 0。如果 {file} 是一个目录但是 可写,返回 2。 也可用作 method : GetName()->filewritable() filter({expr1}, {expr2}) filter() {expr1} 必须是 List 或者 Dictionary 。 对 {expr1} 里的每个项目计算 {expr2},如果结果为零,从该 ListDictionary 里删除该项目。 {expr2} 必须是 stringFuncref 。 如果 {expr2}string{expr2} 内的 v:val 包含当前项目的 值。 Dictionaryv:key 包含当前项目的键。 Listv:key 包含当前项目的索引。 例如: call filter(mylist, 'v:val !~ "OLD"') 删除所有出现 "OLD" 的项目。 call filter(mydict, 'v:key >= 8') 删除所有键小于 8 的值。 call filter(var, 0) 删除所有的值,从而清除该 ListDictionary 。 如果 {expr2}Funcref ,它必须接受两个参数: 1. 当前项目的键或索引。 2. 当前项目的值。 如果该项目应保留,此函数必须返回 TRUE 。 例如要保留列表中奇数项目: func Odd(idx, val) return a:idx % 2 == 1 endfunc call filter(mylist, function('Odd')) 使用 lambda 会更短: call filter(myList, {idx, val -> idx * val <= 42}) 如果不用 "val",可以不写: call filter(myList, {idx -> idx % 2 == 1}) 该操作是原位操作 (直接在输入上修改)。要想不更动 ListDictionary ,先建立备份: :let l = filter(copy(mylist), 'v:val =~ "KEEP"') 返回 {expr1},经过过滤的 ListDictionary 。如果执行 {expr2} 有错,不再处理 {expr1} 的其余项目。{expr2} 是函数引用 时,忽略函数里的错误,除非该函数用 "abort" 标志位定义。 也可用作 method : mylist->filter(expr2) finddir({name} [, {path} [, {count}]]) finddir() {path} 里查找目录 {name}。支持向下和向上的递归目录搜索。 {path} 的语法参见 file-searching 。 返回第一个找到的路径。如果找到的 路径在当前目录之下,返回相对路径。否则,返回完整路径。 如果省略 {path},使用 'path'。 如果给出可选的 {count},寻找 {path}{name}{count} 次出 现,而不是第一次。 如果 {count} 为负,返回所有的匹配的列表。 这和 ex 命令 :find 非常类似。 {仅当编译时加入 +file_in_path 特性才有效} 也可用作 method : GetName()->finddir() findfile({name} [, {path} [, {count}]]) findfile() 类似于 finddir() ,不过寻找文件而不是目录。 使用 'suffixesadd'。 例如: :echo findfile("tags.vim", ".;") 从当前文件所在的目录开始往上搜索,直到找到文件 "tags.vim" 为 止。 也可用作 method : GetName()->findfile() flatten({list} [, {maxdepth}]) flatten() 展平 {list},最多到 {maxdepth} 层。不给出 {maxdepth} 时返回完 全无嵌套的 List ,如同 {maxdepth} 为非常大的数值。 {list} 在原位被修改,如果不想如此,可用 flattennew() 。 Vim9 脚本中不能用 flatten(),必须使用 flattennew() E900 {maxdepth} 代表展平嵌套列表的最深层数。 {maxdepth} 为零时,不修改 {list}{maxdepth} 必须为正数。 如果有错,返回数值零。 示例: :echo flatten([1, [2, [3, 4]], 5]) [1, 2, 3, 4, 5] :echo flatten([1, [2, [3, 4]], 5], 1) [1, 2, [3, 4], 5] flattennew({list} [, {maxdepth}]) flattennew() flatten() ,但先创建 {list} 的备份。 float2nr({expr}) float2nr() 返回数值,即 {expr} 省略小数点部分的结果。 {expr} 的计算结果必须是浮点数或数值。 如果 {expr} 的值超出 Number 的范围,结果为 0x7fffffff 或 -0x7fffffff (有 64-位 数值支持时,则为 0x7fffffffffffffff 或 -0x7fffffffffffffff)。而 NaN 转换为 -0x80000000 (有64-位数 值支持时,则为 -0x8000000000000000)。 示例: echo float2nr(3.95) 3 echo float2nr(-23.45) -23 echo float2nr(1.0e100) 2147483647 (或 9223372036854775807) echo float2nr(-1.0e150) -2147483647 (或 -9223372036854775807) echo float2nr(1.0e-100) 0 也可用作 method : Compute()->float2nr() {仅当编译时加入 +float 特性才有效} floor({expr}) floor() 返回浮点数,即小于等于 {expr} 的最大整数 (向下取整)。 {expr} 的计算结果必须是浮点数或数值。 示例: echo floor(1.856) 1.0 echo floor(-5.456) -6.0 echo floor(4.0) 4.0 也可用作 method : Compute()->floor() {仅当编译时加入 +float 特性才有效} fmod({expr1}, {expr2}) fmod() 返回 {expr1} / {expr2} 的余数,该除法可能实际无法表达出来。选 择某整数 i,返回 {expr1} - i * {expr2},使得如果 {expr2} 非 零,结果和 {expr1} 同号而绝对值小于 {expr2} 的绝对值。如果 {expr2} 为零,返回零。返回值为浮点数。 {expr1}{expr2} 的计算结果必须是浮点数或数值。 示例: :echo fmod(12.33, 1.22) 0.13 :echo fmod(-12.33, 1.22) -0.13 也可用作 method : Compute()->fmod(1.22) {仅当编译时加入 +float 特性才有效} fnameescape({string}) fnameescape() 转义 {string} 以便用作命令的文件名参数。有特殊意义的字符,如 '%' 和 '|',会用反斜杠转义。 多数系统上,会转义的字符是 " \t\n*?[{`$\\%#'\"|!<"。在反斜杠可 以出现在文件名中的系统上,此字符集取决于 'isfname'。 也转义出现在开头的 '+' 和 '>' 字符 ( :edit:write 之后有 特殊意义),还有单个出现的 "-" ( :cd 之后有特殊意义)。 示例: :let fname = '+some str%nge|name' :exe "edit " . fnameescape(fname) 则会执行: edit \+some\ str\%nge\|name 也可用作 method : GetName()->fnameescape() fnamemodify({fname}, {mods}) fnamemodify() 根据 {mods} 修改文件名 {fname}{mods} 是一个字符序列组成的字 符串,就像命令行上使用的文件名那样。见 filename-modifiers 。 例如: :echo fnamemodify("main.c", ":p:h") 返回: /home/mool/vim/vim/src 如果 {mods} 为空,返回 {fname}注意: 环境变量不能用于 {fname},需要先用 expand() 扩展。 也可用作 method : GetName()->fnamemodify(':p:h') foldclosed({lnum}) foldclosed() 返回数值,如果行 {lnum} 在关闭的折叠中,返回该折叠开始的行号。 如果行 {lnum} 不在关闭的折叠中,返回 -1。 也可用作 method : GetLnum()->foldclosed() foldclosedend({lnum}) foldclosedend() 返回数值,如果行 {lnum} 在关闭的折叠中,返回该折叠结束的行号。 如果行 {lnum} 不在关闭的折叠中,返回 -1。 也可用作 method : GetLnum()->foldclosedend() foldlevel({lnum}) foldlevel() 返回数值,当前缓冲区第 {lnum} 行的折叠级别。如果在嵌套的折叠 里,返回最深的那层。如果行 {lnum} 没有折叠,返回零。这和折叠是 打开还是关闭无关。在更新折叠时 (在 'foldexpr' 里),如果折叠还 在更新而相应的折叠级别未知,返回 -1。一个特例是前一行的级别通 常总是知道的。 也可用作 method : GetLnum()->foldlevel() foldtext() foldtext() 返回关闭的折叠所显示的行。这是 'foldtext' 选项使用的缺省函数, 而且也只应该在计算 'foldtext' 时使用。它使用 v:foldstartv:foldendv:folddashes 变量。 返回的字符串看起来像: +-- 45 lines: abcdef 开头的连字符的数目取决于折叠级别。"45" 是折叠的行数。"abcdef" 是折叠第一个非空白行的文本。开头的空白、"//" 和 "/*" 还有 'foldmarker''commentstring' 选项的文本都被去除。 {仅当编译时加入 +folding 特性才有效} foldtextresult({lnum}) foldtextresult() 返回行 {lnum} 所在的关闭的折叠显示的文本。在合适的上下文里计算 'foldtext'。 如果 {lnum} 没有关闭的折叠,返回空字符串。 {lnum} 的用法类似于 getline() 。所以 "." 是当前行,"'m" 是位 置标记 m,等等。 可用于输出折叠文本,例如,到 HTML 格式。 {仅当编译时加入 +folding 特性才有效} 也可用作 method : GetLnum()->foldtextresult() foreground() foreground() 把 Vim 窗口带到前台。用于从客户发送到 Vim 服务器的时候。 remote_send() 在 Win32 系统上,可能不行,操作系统并不总能允许窗口把自己带到 前台。这时应使用 remote_foreground() 。 {仅当使用 Win32、Athena、Motif 和 GTK GUI 版本和 Win32 控制台 版本时才有效} fullcommand({name}) fullcommand() 获取简短缩写命令的完整命令名;关于命令缩写,详见 20.2{name} 可以 : 开始,也可以包含 [range],这些部分被跳过,且不 会返回。 如果命令不存在或有二义性 (出现于用户定义函数),返回空串。 Returns an empty string if a command doesn't exist or if it's ambiguous (for user-defined functions). 例如 fullcommand('s') 、`fullcommand('sub')`、 fullcommand(':%substitute') 都返回 "substitute"。 也可用作 method : GetName()->fullcommand() funcref() funcref({name} [, {arglist}] [, {dict}]) 类似于 function() ,但返回的函数引用通过引用来查找函数,而不 是名字。如果函数 {name} 之后被重定义,这很有意义。 和 function() 不同,{name} 必须是已经定义的用户函数。自动载 入函数也可以。{name} 不能是内建函数。 也可用作 method : GetFuncname()->funcref([arg]) function() E700 E922 E923 function({name} [, {arglist}] [, {dict}]) 返回指向函数 {name}Funcref 变量。{name} 可以是用户定义的 函数或者内部函数的名字。 {name} 可以是函数引用或偏函数。如果是偏函数,会使用其保存的字 典,而不接受 {dict} 参数。例如: let FuncWithArg = function(dict.Func, [arg]) let Broken = function(dict.Func, [arg], dict) 使用函数引用时,通过 {name} 查找函数,即使以后被重定义了亦然。 要保留相同的函数,用 funcref() 。 提供 {arglist}{dict} 则会建立偏函数。这意味着参数列表和/或 字典会存放在函数引用里,并在调用函数引用时使用。 参数被传递到函数里,在其它参数之前,但在来自 method 的参数之 后。例如: func Callback(arg1, arg2, name) ... let Partial = function('Callback', ['one', 'two']) ... call Partial('name') 函数的调用就类似于: call Callback('one', 'two', 'name') method 的话: func Callback(one, two, three) ... let Partial = function('Callback', ['two']) ... eval 'one'->Partial('three') 函数的调用就类似于: call Callback('one', 'two', 'three') function() 调用可以嵌套,来给函数引用加入更多的参数。额外的参 数附加于参数列表之后。如: func Callback(arg1, arg2, name) ... let Func = function('Callback', ['one']) let Func2 = function(Func, ['two']) ... call Func2('name') 函数的调用就类似于: call Callback('one', 'two', 'name') 字典只对 "dict" 函数的调用有用。该情况下,{dict} 作为 "self" 传入。例如: function Callback() dict echo "called for " . self.name endfunction ... let context = {"name": "example"} let Func = function('Callback', context) ... call Func() " 会回显: called for example 如果不需额外参数,function() 是没有必要的。这两者等价: let Func = function('Callback', context) let Func = context.Callback 可以合并参数列表和字典: function Callback(arg1, count) dict ... let context = {"name": "example"} let Func = function('Callback', ['one'], context) ... call Func(500) 函数的调用就类似于: call context.Callback('one', 500) 也可用作 method : GetFuncname()->function([arg]) garbagecollect([{atexit}]) garbagecollect() 清理不再使用但有循环引用的 ListDictionaryChannelJob 。 几乎没有需要调用这个函数,因为 Vim 内存不足或者 'updatetime' 之后等待用户按键时会自动执行此功能。没有循环引用的项目总是在不 再使用的时候就被立即释放了。 可用于删除很大的 List 和/或 Dictionary 而且有循环引用的时 候,尤其是在要运行很长时间的脚本里。 如果可选的 {atexit} 参数为一,并且之前还没做过的话,Vim 即使在 退出时也会执行垃圾回收。可用于检查内存泄漏。 垃圾清理不是立即进行的,它会等待安全的时机,就是等待用户输入字 符的时候。要强制立即进行垃圾清理,可用 test_garbagecollect_now() 。 get({list}, {idx} [, {default}]) get() 获取 List {list} 的第 {idx} 个项目。如果不存在此项目,返回 {default}。如果省略 {default},返回零。 建议用作 method : mylist->get(idx) get({blob}, {idx} [, {default}]) 获取 Blob {blob} 的第 {idx} 个字节。如果不存在此字节,返回 {default}。如果省略 {default},返回 -1。 建议用作 method : myblob->get(idx) get({dict}, {key} [, {default}]) 获取 Dictionary {dict} 键为 {key} 的项目。如果不存在此项目, 返回 {default}。如果省略 {default},返回零。有用的例子: let val = get(g:, 'var_name', 'default') 如果 g:var_name 存在,返回它的值,如果不存在返回 'default'。 建议用作 method : mydict->get(key) get({func}, {what}) 获取 函数引用 {func} 的项目。{what} 的可能值是: "name" 函数名 "func" 函数 "dict" 字典 "args" 参数列表 建议用作 method : myfunc->get(what) getbufinfo() getbufinfo([{expr}]) getbufinfo([{dict}]) 获取字典列表形式的缓冲区信息。 不带参数则返回关于所有缓冲区的信息。 只给出 Dictionary 参数时,返回匹配相关条件的缓冲区。{dict} 中可指定以下键值: buflisted 只包含在列表内的缓冲区。 bufloaded 只包含已载入的缓冲区。 bufmodified 只包含修改过的缓冲区。 否则,{expr} 指定特定的单个缓冲区并返回其信息。{expr} 的用法见 上述 bufname() 。如果找到缓冲区,返回的列表有一个项目。不然 返回空列表。 每个返回的列表项目是带有以下项目的字典: bufnr 缓冲区号。 changed 若缓冲区已修改则为 TRUE。 changedtick 缓冲区作过的改动次数。 hidden 若缓冲区隐藏则为 TRUE。 lastused 缓冲区最近修改时间, localtime() 那样 的以秒计的时间戳。 {仅当编译时加入 +viminfo 特性才有效} listed 若缓冲区在列表内,则为 TRUE。 lnum 在当前窗口里打开本缓冲区时所用的行号。 仅当该缓冲区在此窗口中曾经显示过才有 效。 如果要某个窗口最近已知的光标位置的行 号,可用 line() : :echo line('.', {winid}) linecount 缓冲区行数 (仅当缓冲区载入后才有效) loaded 若缓冲区已载入则为 TRUE。 name 缓冲区文件的完整列表。 signs 缓冲区内放置的标号的列表。 每个列表项目是以下项目的字典: id 标号的识别符 lnum 行号 name 标号名 variables 缓冲区局部变量的字典的引用。 windows 显示此缓冲区的所有 window-ID 的列表 popups 显示此缓冲区的弹出窗口 window-ID 的 列表 示例: for buf in getbufinfo() echo buf.name endfor for buf in getbufinfo({'buflisted':1}) if buf.changed .... endif endfor 要获取缓冲区局部选项,可用: getbufvar({bufnr}, '&option_name') 也可用作 method : GetBufnr()->getbufinfo() getbufline() getbufline({expr}, {lnum} [, {end}]) 返回 {expr} 缓冲区的第 {lnum}{end} (包含) 行的 List 。如 果省略 {end},返回只有一行 {lnum}List{expr} 的用法见上述 bufname(){lnum}{end} 可以使用 "$" 来表示缓冲区的最后一行。除此以 外,必须用数值。 如果 {lnum} 小于 1 或大于缓冲区的行数,返回空 List 。 如果 {end} 大于缓冲区的行数,就把它当成缓冲区的行数。如果 {end}{lnum} 之前,返回空 List 。 此函数只能用于已经载入的缓冲区。未载入或不存在的缓冲区总是返回 空 List 。 例如: :let lines = getbufline(bufnr("myfile"), 1, "$") 也可用作 method : GetBufnr()->getbufline(lnum) getbufvar({expr}, {varname} [, {def}]) getbufvar() 返回缓冲区 {expr} 里的选项或者局部变量 {varname} 的值。注意 必 须使用不带 "b:" 的名字。 如果 {varname} 为空,返回包含所有缓冲区局部变量的 Dictionary 。 如果 {varname} 为 "&",返回包含所有缓冲区局部选项的 Dictionary 。 否则,如果 {varname} 以 "&" 开始,返回单个缓冲区局部选项值。 也可用于全局或者局部于缓冲区的选项,但不能用于全局或者局部于窗 口的变量,还有局部于窗口的选项。 {expr} 的用法见上述 bufname() 。 如果缓冲区或者变量不存在,返回 {def} 或空字符串。不会有错误消 息。 示例: :let bufmodified = getbufvar(1, "&mod") :echo "todo myvar = " . getbufvar("todo", "myvar") 也可用作 method : GetBufnr()->getbufvar(varname) getchangelist([{expr}]) getchangelist() 返回缓冲区 {expr} 里的 changelist{expr} 的用法见上述 bufname() 。缓冲区 {expr} 不存在时返回空列表。 返回列表包含两个项目: 包含改变位置的列表以及在该列表中的当前位 置。改变位置列表的每个项目是包含以下内容的字典: col 列号 coladd 用于 'virtualedit' 的列偏移 lnum 行号 如果缓冲区 {expr} 是当前缓冲区,当前位置指的是在列表中的位置。 如果是其它缓冲区,它设为列表的长度。 也可用作 method : GetBufnr()->getchangelist() getchar([expr]) getchar() 从用户或输入流中提取单个字符。 如果忽略 [expr],等待直到有字符输入为止。 如果 [expr] 为 0,只有在有字符可用时才取得字符,否则返回零。 如果 [expr] 为 1,只检查是否有字符可用,并不消耗该字符。如果没 有字符,返回零。 如果省略 [expr] 或者 [expr] 为零,返回整个字符或者特殊键。如果 是单个字符,以数值形式返回。用 nr2char() 把它转化成字符串。否 则返回经过编码的字符构成的字符串。如果是特殊键,返回以 0x80 (十进制: 128) 开始的一串字节构成的字符串。它和字符串 "\<Key>" 等值,例如 "\<Left>"。如果用带修饰符 (Shift,Control, Alt) 的 字符而字符本身不包含该修饰符时,返回值也用字符串类型。 如果 [expr] 为 0 并已键入 Esc,会有短暂的延迟,以便 Vim 有机会 判断是否是转义序序列的开始。 如果 [expr] 为 1,只返回第一个字节。如果是单字节字符,返回的就 是该字符自身的数值形式。用 nr2char() 把它转化为字符串。 getcharmod() 可用于得到附加的修饰符。 用户点击鼠标时,返回鼠标事件。所在的位置可以在 v:mouse_colv:mouse_lnumv:mosue_winidv:mouse_win 里找到。也可 用 getmousepos() 。鼠标移动事件被忽略。 下例用通常的处理方法定位鼠标: let c = getchar() if c == "\<LeftMouse>" && v:mouse_win > 0 exe v:mouse_win . "wincmd w" exe v:mouse_lnum exe "normal " . v:mouse_col . "|" endif 使用括号内粘贴模式时,只返回首个字符。粘贴文本其余部分被丢弃。 xterm-bracketed-paste 。 这里没有提示,你需要想办法告诉用户,需要输入一个字符。屏幕不重 画,例如在窗口改变大小时也是如此。使用弹出窗口时,最好使用 popup-filter 。 字符不通过映射。 键码被替换。因而,用户输入 <Del> 键时,你得到 <Del> 的键码,而 不是原始的字符序列。比如: getchar() == "\<Del>" getchar() == "\<S-Left>" 下例重新定义 "f",使它忽略大小写: :nmap f :call FindChar()<CR> :function FindChar() : let c = nr2char(getchar()) : while col('.') < col('$') - 1 : normal l : if getline('.')[col('.') - 1] ==? c : break : endif : endwhile :endfunction 也可能收到模拟字符,例如 <CursorHold> 。通常你想忽略之跳到下 个字符: :function GetKey() : let c = getchar() : while c == "\<CursorHold>" : let c = getchar() : endwhile : return c :endfunction getcharmod() getcharmod() 返回数值,反映最近用 getchar() 或其它方式输入字符的修饰符状 态。这些值可以相加: 2 Shift 4 Control 8 Alt (Meta) 16 Meta (当和 ALT 不同时) 32 鼠标双击 64 鼠标三击 96 鼠标四击 (== 32 + 64) 128 Command (仅限于 Macintosh) 只有没有包含字符本身的修饰符被返回。因而,Shift-a 产生没有修饰 符的 "A"。 getcharpos() getcharpos({expr}) 得到 {expr} 的位置。和 getpos() 相同,但返回列表的列号是字 符索引而不是字节索引。 如果 getpos() 返回很大的列号,如 2147483647,那么 getcharpos() 会返回末字符的字符索引。 示例: 如果光标在第五行文本 "여보세요" 的 '세' 时: getcharpos('.') 返回 [0, 5, 3, 0] getpos('.') 返回 [0, 5, 7, 0] 也可用作 method : GetMark()->getcharpos() getcharsearch() getcharsearch() {dict} 形式返回当前字符搜索信息,带有以下项目: char 上次字符搜索 ( tfTF ) 使用的字 符;空字符串代表没有字符搜索进行过 forward 字符搜索的方向;1 为正向,0 为反向 until 字符搜索的类型;1 为 tT 字符搜索,0 为 fF 字符搜索 可用于使 ;, 永远进行正向/反向搜索而不管上次字符搜索的 方向: :nnoremap <expr> ; getcharsearch().forward ? ';' : ',' :nnoremap <expr> , getcharsearch().forward ? ',' : ';' 另见 setcharsearch() 。 getcmdline() getcmdline() 返回当前命令行。只有在编辑命令行时有效,所以必须在 c_CTRL-\_ec_CTRL-R_= 里使用。 例如: :cmap <F7> <C-\>eescape(getcmdline(), ' \')<CR> 另见 getcmdtype()getcmdpos()setcmdpos() 。 输入密码或用 inputsecret() 时返回空串。 getcmdpos() getcmdpos() 返回命令行的字节计算的光标位置。第一列为 1。 只有在编辑命令行时有效,所以必须在 c_CTRL-\_ec_CTRL-R_= 或表达式映射里使用。 不然,返回 0。 另见 getcmdtype()setcmdpos()getcmdline() 。 getcmdtype() getcmdtype() 返回当前命令行类型。可能的返回值是: : 普通 Ex 命令 > 调试模式命令 debug-mode / 正向搜索命令 ? 反向搜索命令 @ input() 命令 - :insert:append 命令 = i_CTRL-R_= 只能在编辑命令行时调用,因而必须在 c_CTRL-\_ec_CTRL-R_= 或表达式映射里使用。 否则,返回空字符串。 另见 getcmdpos()setcmdpos()getcmdline() 。 getcmdwintype() getcmdwintype() 返回当前 command-line-window 类型。可能的返回值和 getcmdtype() 相同。如果不在命令行窗口内,返回空字符串。 getcompletion({pat}, {type} [, {filtered}]) getcompletion() 返回命令行补全匹配列表。{type} 指定类型。支持以下的匹配类型: arglist 参数列表中的文件名 augroup 自动命令组 buffer 缓冲区名 behave :behave 子选项 color 色彩方案 command Ex 命令 (及参数) cmdline cmdline-completion 结果 compiler 编译器 cscope :cscope 子选项 diff_buffer :diffget:diffput 补全 dir 目录名 environment 环境变量名 event 自动命令事件 expression Vim 表达式 file 文件和目录名 file_in_path 'path' 中的文件和目录名 filetype 文件类型名 'filetype' function 函数名 help 帮助主题 highlight 高亮组 history :history 子选项 locale locale 名 (可见 locale -a 的输出) mapclear 缓冲区参数 mapping 映射名 menu 菜单 messages :messages 子选项 option 选项 packadd 可选包 pack-add 名 shellcmd 外壳命令 sign :sign 子选项 syntax 语法文件名 'syntax' syntime :syntime 子选项 tag 标签 tag_listfiles 标签、文件名 user 用户名 var 用户变量 如果 {pat} 为空串,返回所有匹配。否则只返回匹配 {pat} 的项目。 关于 {pat} 中特殊字符的使用,见 wildcards 。 如果可选的 {filtered} 标志位设为 1,应用 'wildignore' 来过滤结 果。否则返回所有匹配。'wildignorecase' 选项则总是有效。 如果 {type} 为 "cmdline",返回 cmdline-completion 的结果。例 如,要补全 ":call" 命令之后可能的取值: echo getcompletion('call ', 'cmdline') 如果没有匹配,返回空列表。如果 {type} 为非法值,报错。 也可用作 method : GetPattern()->getcompletion('color') getcurpos() getcurpos([{winid}]) 返回光标位置。类似于 getpos('.'),但返回列表中包含一个额外的 "curswant" 项目: [0, lnum, col, off, curswant] "curswant" 数值是垂直移动光标时的首选列。另见 getcursorcharpos()getpos() 。 首个 "bufnum" 项目总是为零。'col' 返回的是光标的字节位置。要得 到字符位置,用 getcursorcharpos() 。 可选的 {winid} 参数可指定窗口。可以是窗口号或 window-ID 。返 回最近已知的光标位置,如果缓冲区的当前值不是当前窗口,可能会非 法。如果 {winid} 非法,返回零组成的列表。 可用于保存和恢复光标位置: let save_cursor = getcurpos() 移动光标 call setpos('.', save_cursor) 注意 这只适用于同一窗口内的移动。要恢复更多状态,见 winrestview() 。 也可用作 method : GetWinid()->getcurpos() getcursorcharpos() getcursorcharpos([{winid}]) 同 getcurpos() ,但返回列表中的列号是字符索引而不是字节索引。 示例: 如果光标在第三行文本 "여보세요" 的 '보' 时: getcursorcharpos() 返回 [0, 3, 2, 0, 3] getcurpos() 返回 [0, 3, 4, 0, 3] 也可用作 method : GetWinid()->getcursorcharpos() getcwd() getcwd([{winnr} [, {tabnr}]]) 返回字符串,当前工作目录的名字。 有 {winr} 则返回当前标签页的该窗口的本地当前目录。{winr} 可以 是窗口号或 window-ID{winr} 为 -1 时返回全局工作目录名。另见 haslocaldir() 。 有 {winr}{tabnr} 则返回指定标签页和窗口的本地当前目录。如 果 {winnr} 为 -1,返回指定标签页的当前目录。 如果 {winr} 为零使用当前窗口。如果 {tabnr} 为零使用当前标签 页。 无参数时,返回当前窗口的工作目录。 如果参数非法,返回空串。 示例: " 返回当前窗口的工作目录 :echo getcwd() :echo getcwd(0) :echo getcwd(0, 0) " 返回标签页 2 中的窗口 3 的工作目录 :echo getcwd(3, 2) " 返回全局工作目录 :echo getcwd(-1) " 返回标签页 3 的工作目录 :echo getcwd(-1, 3) " 返回当前标签页的工作目录 :echo getcwd(-1, 0) 也可用作 method : GetWinnr()->getcwd() getenv({name}) getenv() 返回环境变量 {name} 的值。 如果该变量不存在返回 v:null 。这和变量设为空串时不同,不过有 的系统把空值解读为删除了的变量。另见 expr-env 。 也可用作 method : GetVarname()->getenv() getfontname([{name}]) getfontname() 如果没有参数,返回使用的正常字体的名字,也就是 Normal 高亮组 hl-Normal 使用的。 如果带了参数,检查 {name} 是否合法的字体名。如果不是,返回空字 符串。否则,返回实际的字体名,或者如果 GUI 不支持取得真正的名 字,返回 {name}。 只有在 GUI 运行的时候才能用,所以不能用于你的 vimrc 和 gvimrc 文件。用 GUIEnter 自动命令可以在 GUI 刚开始之后使用此函数。 注意 GTK GUI 接受任何字体名,所以不会检查名字是否合法。 getfperm({fname}) getfperm() 返回字符串,给定文件 {fname} 的读、写、执行权限。 如果 {fname} 不存在或者它所在的目录无法读取,返回空字符串。 返回值的形式是 "rwxrwxrwx",其中每组 "rwx" 标志位分别代表文件 所有者、文件所属组和其它用户的权限。如果用户没有某权限,相应的 标志位被字符串 "-" 代替。例如: :echo getfperm("/etc/passwd") :echo getfperm(expand("~/.vimrc")) 希望它会 (从安全角度而言) 显示字符串 "rw-r--r--" 或者甚至 "rw-------"。 也可用作 method : GetFilename()->getfperm() 要设置权限,可用 setfperm() 。 getfsize({fname}) getfsize() 返回数值,文件 {fname} 以字节数计算的大小。 如果 {fname} 是目录,返回 0。 如果找不到文件 {fname},返回 -1。 如果 {fname} 文件过大,超出了 Vim 的数值的范围,返回 -2。 也可用作 method : GetFilename()->getfsize() getftime({fname}) getftime() 返回数值,给定文件 {fname} 的最新修改时间。该时间为 1970 年 1 月 1 日开始计算的秒数,可以传给 strftime()。 另见 localtime()strftime() 。 如果找不到文件 {fname},返回 -1。 也可用作 method : GetFilename()->getftime() getftype({fname}) getftype() 返回字符串,给定文件 {fname} 的文件类型的描述。 如果 {fname} 不存在,返回空字符串。 下表列出各种不同文件类型的返回值: 普通文件 "file" 目录 "dir" 符号链接 "link" 块设备 "bdev" 字符设备 "cdev" 套接字 "socket" FIFO "fifo" 其它 "other" 例如: getftype("/home") 注意 只有在能支持的系统上才会返回 "link" 这样的类型。有的系统 只支持 "dir" 和 "file"。MS-Windows 上目录的符号链接返回 "dir" 而不是 "link"。 也可用作 method : GetFilename()->getftype() getimstatus() getimstatus() 返回数值,IME 状态激活时为 TRUE 。 见 'imstatusfunc'。 getjumplist([{winnr} [, {tabnr}]]) getjumplist() 返回指定窗口的 jumplist 。 无参数时使用当前窗口。 如果只带 {winnr},使用当前标签页的指定窗口。 {winnr} 也可以是 window-ID 。 有 {winr}{tabnr} 则返回指定标签页的指定窗口。 返回列表包含两个项目: 包含跳转位置的列表以及在该列表中的最近使 用的跳转位置号。跳转位置列表的每个项目是包含以下内容的字典: bufnr 缓冲区号 col 列号 coladd 用于 'virtualedit' 的列偏移 filename 文件名,如有的话 lnum 行号 也可用作 method : GetWinnr()->getjumplist() getline() getline({lnum} [, {end}]) 如果没有 {end},返回字符串,即当前缓冲区第 {lnum} 行文本。 例如: getline(1) 如果 {lnum} 是不以数字开始的字符串,调用 line() 来把该字符串 转化成数值。要得到光标所在的行: getline(".") 如果 {lnum} 小于 1 或者大于缓冲区的总行数,返回空字符串。 如果给出 {end},返回 List ,其中每个项目是当前缓冲区从 {lnum}{end} (包含) 范围的一行。 {end} 的用法同 {lnum}。 安静地忽略不存在的行。 如果 {end}{lnum} 之前,返回空 List 。 例如: :let start = line('.') :let end = search("^$") - 1 :let lines = getline(start, end) 也可用作 method : ComputeLnum()->getline() 要获取其它缓冲区的文本行,见 getbufline() 。 getloclist({nr} [, {what}]) getloclist() 返回 List ,包含窗口 {nr} 的位置列表的所有项目。{nr} 可以是窗 口号或 window-ID 。如果 {nr} 为 0,使用当前窗口。 如果是位置列表窗口,返回其显示的位置列表。如果窗口号 {nr} 非 法,返回空列表。其它的情况和 getqflist() 相同。 如果提供了可选的 {what} 字典参数,以字典形式返回 {what} 列出的 项目。关于 {what} 支持的项目,可参考 getqflist() 。 除了 getqflist(){what} 支持的项目以外, getloclist() 还 支持以下项目: filewinid 用于显示来自位置列表的文件的窗口的 id。只有当调用来自位置列表窗口时此域才 可用。详见 location-list-file-window 。 如果窗口 {nr} 没有位置列表,返回带缺省值的 Dictionary 。 如果窗口 {nr} 不存在,返回空字典。 示例 (另见 getqflist-examples ): :echo getloclist(3, {'all': 0}) :echo getloclist(5, {'filewinid': 0}) getmarklist([{expr}]) getmarklist() {expr} 参数时,返回 List ,给出所有全局位置标记的信息。 mark 给出可选的 {expr} 参数时,返回缓冲区 {expr} 中定义的局部位置标 记。{expr} 的用法可见 bufname() 。 返回列表的每个项目是包含以下内容的 Dict : name - 带 "'" 前缀的位置标记名 pos - 位置标记所在位置的 List : [bufnum, lnum, col, off] 详情请参考 getpos() 。 file - 文件名 要获取特定位置标记的信息,参见 getpos() 。 也可用作 method : GetBufnr()->getmarklist() getmatches([{win}]) getmatches() 返回之前 matchadd():match 命令为当前窗口定义的所有匹配 组成的列表 Listgetmatches() 常和 setmatches() 组合使 用,因为 setmatches() 可以恢复 getmatches() 保存的匹配列 表。 示例: :echo getmatches() [{'group': 'MyGroup1', 'pattern': 'TODO', 'priority': 10, 'id': 1}, {'group': 'MyGroup2', 'pattern': 'FIXME', 'priority': 10, 'id': 2}] :let m = getmatches() :call clearmatches() :echo getmatches() [] :call setmatches(m) :echo getmatches() [{'group': 'MyGroup1', 'pattern': 'TODO', 'priority': 10, 'id': 1}, {'group': 'MyGroup2', 'pattern': 'FIXME', 'priority': 10, 'id': 2}] :unlet m getmousepos() getmousepos() 返回鼠标最近已知位置的 Dictionary 。可用于鼠标点击的映射或弹 出窗口的过滤。项目是: screenrow 屏幕行 screencol 屏幕列 winid 点击所在的窗口 ID winrow "winid" 里的行 wincol "winid" 里的列 line "winid" 里的文本内容行 column "winid" 里的文本列 所有的数值从 1 开始。 如果鼠标不在窗口上,比如在命令行里,则只有 "screenrow" 和 "screencol" 是合法的,其它的值均为零。 如果鼠标在窗口底下的状态行上或窗口右侧的垂直分割线上,"line" 和 "column" 的值为零。 如果位置在文本之后,那么 "column" 是文本以字节计的长度。 如果鼠标在弹出窗口上,使用该窗口。 使用 getchar() 时,Vim 变量 v:mouse_lnumv:mouse_colv:mouse_winid 也能提供相应的这些值。 getpid() getpid() 返回数值,即 Vim 进程的进程号。Unix 和 MS-Windows 上这是个唯一 的数值,直到 Vim 退出为止。 getpos() getpos({expr}) 得到 {expr} 的位置。可用的 {expr} 的值见 line() 。要得到光标 位置,见 getcurpos() 。 返回 List ,包含四个数值: [bufnum, lnum, col, off] "bufnum" 为零,除非使用了 '0 或 'A 这样的位置标记,这时它是此 位置标记所在的缓冲区号。 "lnum" 和 "col" 是缓冲区里的位置。第一列为 1。 除非使用了 'virtualedit'。"off" 值为零,这是从对应字符开始位置 的以屏幕列计的位移。例如,在制表之中或最后一个字符之后的某个位 置。 注意 '< 和 '> 和可视模式有关: "V" (可视行模式) 时 '< 的列为 零,'> 的列为一大数。 返回列表中的列号是行内的字节位置。要得行内的字符位置,用 getcharpos() 。 列号可为一很大值,如 2147483647,这种情况代表 "在行尾之后"。 可以用来保存和恢复光标位置: let save_a_mark = getpos("'a") ... call setpos("'a", save_a_mark) 另见 getcharpos()getcurpos()setpos() 。 也可用作 method : GetMark()->getpos() getqflist([{what}]) getqflist() 返回 List ,包含所有当前快速修复错误。列表的每个项目是包含以 下项目的字典: bufnr 有此文件名的缓冲区号,bufname() 得到缓冲区名 module 模块名 lnum 缓冲区里的行号 (第一行是 1) col 列号 (第一列是 1) vcol TRUE : "col" 是可视列 FALSE : "col" 是字节位置 nr 错误号 pattern 用于定位错误的搜索模式 text 错误描述 type 错误类型,'E'、'1' 等。 valid TRUE : 能识别该错误信息 如果没有错误列表或者它为空,返回空列表。快速修复列表项目如果包 含不存在的缓冲区号,返回的 "bufnr" 置为零。 应用: 在多个文件里寻找模式的匹配,并对之进行处理: :vimgrep /theword/jg *.c :for d in getqflist() : echo bufname(d.bufnr) ':' d.lnum '=' d.text :endfor 如果提供了可选的 {what} 字典参数,以字典形式返回 {what} 列出的 项目。{what} 支持以下字符串项目: changedtick quickfix-changedtick 列表改变的总数 context 获取 quickfix-context efm 解析 "lines" 时使用的 errorformat。如果没有给 出,使用 'errorformat' 选项值。 id 获取快速修复列表 quickfix-ID 说明的信息。 零代表当前列表或 "nr" 指定的列表 idx 获取由 'id''nr' 指定的快速修复列表中在此索 引的项目信息。 如果设为零,使用当前项目。 见 quickfix-index items 获取快速修复列表的项目 lines 用 'efm' 解析文本行列表并返回其结果项目。只支 持 List 类型。不修改当前快速修复列表。见 quickfix-parse 。 nr 获取关于指定快速修复列表的信息;零代表当前快速 修复列表,"$" 代表最后的快速修复列表 qfbufnr 快速修复窗口显示的缓冲区号。快速修复缓冲区不存 在时返回 0。见 quickfix-buffer 。 size 快速修复列表的项目总数 title 获取列表标题 quickfix-title winid 获取快速修复 window-ID all 上述所有的快速修复属性 忽略 {what} 中非字符串项。要获取某个特定项之值,先设为零。 如果不给出 "nr",使用当前快速修复列表。 同时给出 "nr" 和非零 "id" 时,使用 "id" 指定的列表。 要取得快速修复栈的列表数目,在 {what} 中设置 'nr' 为 "$"。返回 字典中的 "nr" 值会告诉你快速修复的栈大小。 如果给出 "lines",忽略除 "efm" 外的所有其它项。返回的字典包 含 "items" 项,给出所有项目的列表。 返回字典包含以下项目: changedtick quickfix-changedtick 列表改变的总数 context 快速修复列表的上下文,见 quickfix-context 如果不存在,设为 ""。 id 快速修复列表 ID quickfix-ID 。如果不存在,设 为 0。 idx 列表中快速修复项目的索引。如果不存在,设为 0。 items 快速修复列表的项目。如果不存在,设为空列表。 nr 快速修复列表号。如果不存在,设为 0 qfbufnr 快速修复窗口显示的缓冲区号。如果不存在,设为 0。 size 快速修复列表的项数。如果不存在,设为 0。 title 快速修复列表标题文本。如果不存在,设为 ""。 winid 快速修复 window-ID 。如果不存在,设为 0 示例 (另见 getqflist-examples ): :echo getqflist({'all': 1}) :echo getqflist({'nr': 2, 'title': 1}) :echo getqflist({'lines' : ["F1:10:L10"]}) getreg([{regname} [, 1 [, {list}]]]) getreg() 返回字符串,寄存器 {regname} 的内容。例如: :let cliptext = getreg('*') 如果 {regname} 对应的寄存器没有设过,返回空串。 getreg('=') 返回最近一次表达式寄存器计算的返回值 (用于映射)。 getreg('=', 1) 返回表达式自身,以便用 setreg() 恢复。对于其 它寄存器,这个额外的参数被忽略,所以给出此参数总是无妨。 如果 {list} 给出且为 TRUE ,改变返回值为列表。每个列表项是一 个文本行。如果你在意寄存器内可能存在的零字节,可以用这种形式: 不用第三个参数时 NL 和零字节都用 NL 表示 (见 NL-used-for-Nul ) 。 如果 {regname} 对应的寄存器没有设过,返回空列表。 如果没有指定 {regname},使用 v:registerVim9-script{regname} 必须为单个字符。 也可用作 method : GetRegname()->getreg() getreginfo([{regname}]) getreginfo() 返回寄存器 {regname} 的详细信息,即带下列项目的字典: regcontents 寄存器 {regname} 包含的行列表,相当于 getreg ({regname}, 1, 1)。 regtype 寄存器 {regname} 的类型,见 getregtype() 。 isunnamed 布尔标志位,如果无名寄存器当前指向此寄 存器,返回 v:true。 points_to 用于无名寄存器,给出当前指向的寄存器的 单字母名 (见 quotequote )。例如,用 dd 删除一行后,此字段设为 "1",这是 包含被删除文本的寄存器。 如果 {regname} 非法或对应的寄存器没有设过,返回空列表。 如果没有指定 {regname},使用 v:register 。 返回的字典可传递给 setreg()Vim9-script{regname} 必须为单个字符。 也可用作 method : GetRegname()->getreginfo() getregtype([{regname}]) getregtype() 返回字符串,寄存器 {regname} 的类型。 该值会是以下可能之一: "v" characterwise (面向字符) 的文本 "V" linewise (面向行) 的文本 "<CTRL-V>{width}" blockwise-visual (面向列块) 的文本 "" 空或者未知的寄存器 <CTRL-V> 是一个字符,其值为 0x16。 如果没有指定 {regname},使用 v:registerVim9-script{regname} 必须为单个字符。 也可用作 method : GetRegname()->getregtype() gettabinfo([{arg}]) gettabinfo() 如果没指定 {arg},返回 List ,包含所有标签页的信息。每个列表 项是 Dictionary 。 否则,{arg} 指定标签页号,返回关于该标签页的信息。如果该标志页 不存在,返回空列表。 每个列表项是包含以下项目的 Dictionary : tabnr 标签页号 variables 包含标签页局部变量的字典的引用 windows 标签页中的 window-ID 列表。 也可用作 method : GetTabnr()->gettabinfo() gettabvar({tabnr}, {varname} [, {def}]) gettabvar() 得到标签页 {tabnr} 的标签页局部变量 {varname} 的值。 t:var 标签页的编号从一开始。 如果 {varname} 为空,返回包含所有标签页局部变量的字典。 注意 必须使用不带 "t:" 的名字。 如果标签页或者变量不存在,返回 {def} 或空字符串。不会有错误消 息。 也可用作 method : GetTabnr()->gettabvar(varname) gettabwinvar({tabnr}, {winnr}, {varname} [, {def}]) gettabwinvar() 得到标签页 {tabnr} 的窗口 {winnr} 的窗口局部变量 {varname} 的 值。 如果 {varname} 为 "&",返回包含所有窗口局部选项的 Dictionary 。 否则,如果 {varname} 以 "&" 打头,得到窗口局部选项的值。 如果 {varname} 为空,返回一个包含所有窗口局部变量的字典。 注意 {varname} 必须为不带 "w:" 的名字。 标签页的编号从一开始。当前标签页可用 getwinvar(){winnr} 可以是窗口号或 window-ID 。 如果 {winnr} 为零,使用当前窗口。 也可用于全局或者局部于缓冲区或局部于窗口的选项,但不能用于全局 或者局部于缓冲区的变量。 如果标签页、窗口或者变量不存在,返回 {def} 或空字符串。不会有 错误消息。 例如: :let list_is_on = gettabwinvar(1, 2, '&list') :echo "myvar = " . gettabwinvar(3, 1, 'myvar') 要得到所有窗口局部变量,可用: gettabwinvar({tabnr}, {winnr}, '&') 也可用作 method : GetTabnr()->gettabwinvar(winnr, varname) gettagstack([{nr}]) gettagstack() 返回字典,窗口 {nr} 的标签栈。 {nr} 可以是窗口号或 window-ID 。 如果没有给出 {nr},使用当前窗口。 如果窗口 {nr} 不存在,返回空字典。 返回字典包含如下项目: curidx 栈的当前索引。如果在栈顶,设为 (length + 1)。栈底的索引为 1。 items 栈中的项目列表。每个项目是包含下述项的 字典。 length 栈中的项目数。 栈中的每个项目是以下项的字典: bufnr 当前跳转的缓冲区号 from 标签跳转之前的光标位置。 getpos() 说 明返回列表的格式。 matchnr 当前的匹配标签号。用于同一名字有多个匹 配标签的时候。 tagname 标签名 tagstack 说明标签栈的更多信息。 也可用作 method : GetWinnr()->gettagstack() gettext({text}) gettext() {text} 进行翻译。 主要在发布的 Vim 脚本中使用。要生成消息翻译时,由 xgettext 对 {text} 进行提取,翻译者会把翻译后的消息加到 .po 文件,调用 gettext() 时,Vim 会依此查找翻译内容。 {text} 推荐使用双引号括起,因为 xgettext 不理解单引号字符串里 的转义。 getwininfo([{winid}]) getwininfo() 返回窗口信息,返回值是字典的 List 。 如果给出 {winid},返回给定 ID 的窗口的信息为包含单个项目的 List 。如果窗口不存在,返回空列表。 如果没有给出 {winid},返回所有标签页的所有窗口的信息。 每个列表项是包含以下项目的 Dictionary : botline 最近完整显示的缓冲区行 bufnr 窗口中的缓冲区号 height 窗口高度 (不计窗口工具条 winbar) loclist 1 如果显示了位置列表 {仅当加入 +quickfix 特性才有效} quickfix 1 如果是快速修复或位置列表窗口 {仅当加入 +quickfix 特性才有效} terminal 1 如果是终端窗口 {仅当加入 +terminal 特性才有效} tabnr 标签页号 topline 首个显示的缓冲区行 variables 包含窗口局部变量的字典的引用 width 窗口宽度 winbar 1 如果窗口有工具条,0 反之 wincol 窗口最左侧屏幕列, win_screenpos() 中的 "col" winid window-ID winnr 窗口号 winrow 窗口最顶侧屏幕行, win_screenpos() 中的 "row" 也可用作 method : GetWinnr()->getwininfo() getwinpos([{timeout}]) getwinpos() 返回两个数值组成的 List ,即 getwinposx()getwinposy() 结果的混合: [x-pos, y-pos] {timeout} 可用于以毫秒计的等待终端反馈的超时。省略时缺省为 100 毫秒。远程终端可用更长的超时。 如果取值小于 10 且在指定时限内没有收到反馈,返回如果有的上次报 告的位置。可用于轮询位置并在同时并发做其它的事: while 1 let res = getwinpos(1) if res[0] >= 0 break endif " 干些话 endwhile 也可用作 method : GetTimeout()->getwinpos() getwinposx() getwinposx() 返回数值,即 GUI Vim 窗口以像素计从左起算的 X 坐标。也适用于 xterm (100 毫秒超时)。 如果该信息得不到,返回 -1。 返回值可用于 ":winpos"。 getwinposy() getwinposy() 返回数值,即 GUI Vim 窗口以像素计从顶部起算的 Y 坐标。也适用于 xterm (100 毫秒超时)。 如果该信息得不到,返回 -1。 返回值可用于 ":winpos"。 getwinvar({winnr}, {varname} [, {def}]) getwinvar() 类似于 gettabwinvar() ,只用当前标签页。 例如: :let list_is_on = getwinvar(2, '&list') :echo "myvar = " . getwinvar(1, 'myvar') 也可用作 method : GetWinnr()->getwinvar(varname) glob({expr} [, {nosuf} [, {list} [, {alllinks}]]]) glob() 扩展 {expr} 里的文件通配符。 wildcards 说明其中特殊字符的使用 方法。 除非给出可选的 {nosuf} 参数且为 TRUE ,应用 'suffixes''wildignore' 选项: 跳过匹配任何 'wildignore' 模式的名字,而 'suffixes' 影响匹配结果的排序。 'wildignorecase' 则总是适用。 如果给出 {list} 且为 TRUE ,返回 List ,包含所有匹配的文件。 使用列表的优点是可以正确得到包含换行符的文件名。 否则返回的是字符串,且如果返回多个匹配,以 <NL> 字符分隔。 如果扩展失败,返回空字符串或空列表。 扩展结果不包含不存在文件的名字。仅当符号链接指向已存在文件时才 会包含在扩展结果内。但若给出了 {alllinks} 参数且为 TRUE ,则 包含所有符号链接。 多数系统上,可以用反引号从外部命令得到文件名。例如: :let tagfiles = glob("`find . -name tags -print`") :let &tags = substitute(tagfiles, "\n", ",", "g") 反引号包围的程序的输出结果必须每个项目一行。项目内部可以使用空 格。 特殊 Vim 变量的扩展见 expand()system() 说明如何得到外部 命令的原始输出。 也可用作 method : GetExpr()->glob() glob2regpat({expr}) glob2regpat() 转换 glob() 所用有文件模式为搜索模式。结果可用来匹配包含文件名 的字符串。例如 if filename =~ glob2regpat('Make*.mak') 等价于: if filename =~ '^Make.*\.mak$' 如果 {expr} 为空串,返回值是 "^$",匹配空串。 备注 结果与所用系统有关。MS-Windows 上反斜杠通常用作路径分隔 符。 也可用作 method : GetExpr()->glob2regpat() globpath() globpath({path}, {expr} [, {nosuf} [, {list} [, {alllinks}]]]) 在 {path} 的所有目录下的 {expr} 执行 glob() 并连接所有的返回结 果。例如: :echo globpath(&rtp, "syntax/c.vim") {path} 是逗号分隔的目录名的列表。每个目录名都附加在 {expr} 之 前,然后如同 glob() 那样被扩展。必要的话,插入路径分隔符。 要在目录名字里加上逗号,可以使用反斜杠转义。注意 在 MS-Windows 上目录的最后可能有一个反斜杠。如果你要在后面加上逗号进行分隔, 先把反斜杠去掉。 如果某个目录下的扩展失败,不会有错误信息。 除非给出可选的 {nosuf} 参数且为 TRUE ,应用 'suffixes''wildignore' 选项: 跳过匹配任何 'wildignore' 模式的名字,而 'suffixes' 影响匹配结果的排序。 如果给出 {list} 且为 TRUE ,返回匹配文件的列表。列表的好处是 会正确处理包含换行符的文件名,否则返回字符串,有多个匹配时,以 <NL> 字符分隔。例如: :echo globpath(&rtp, "syntax/c.vim", 0, 1) {alllinks} 的用法和 glob() 相同。 可以用 "**" 项目来搜索目录树。例如,寻找在 'runtimepath' 和它 之下所有目录里的 "README.txt" 文件: :echo globpath(&rtp, "**/README.txt") 不支持向上搜索和 "**" 的深度限制,所以 'path' 的使用不一定总能 正确工作。 也可用作 method ,基是作为第二个参数传递的: GetExpr()->globpath(&rtp) has() has({feature} [, {check}]) 如果 {check} 省略或为零: 返回数值,如果支持特性 {feature} 则为 1,不然为零。{feature} 参数是大小写忽略的字符串。见下面的 feature-list 。 如果 {check} 给出且非零: 返回数值,如果特性 {feature} 可以支 持,则为 1,不然为零。可用于检查 {feature} 是否有拼写错误,也 可用于检测死代码。要记住旧版本的 Vim 不知道新增的特性,而当前 版本的 Vim 也不会知道已废弃的特性。 另见 exists()注意 特性不可用时,要跳过会有语法错误的代码,Vim 可能会跳过行 的其余部分,从而丢失其中跟随的 endif 。所以, endif 请另起一 行: if has('feature') let x = this->breaks->without->the->feature endif 如果试图把 endif 移到第二行成为 "| endif",它不会被找到。 has_key({dict}, {key}) has_key() 返回数值,如果 Dictionary {dict} 有键为 {key} 的项目则为 TRUE,不然为 FALSE。 也可用作 method : mydict->has_key(key) haslocaldir([{winnr} [, {tabnr}]]) haslocaldir() 返回数值: 1 如果窗口用 :lcd 设置过局部目录 2 如果标签页用 :tcd 设置过局部目录 0 其它。 无参数时使用当前窗口。 有 {winr} 则使用当前标签页的该窗口。 有 {winr}{tabnr} 则使用指定标签页的该窗口。 {winr} 可以是窗口号或 window-ID 。 如果 {winnr} 为 -1,它被忽略,只使用标签页。 如果参数非法,返回 0。 Examples: if haslocaldir() == 1 " 窗口的局部目录情况 elseif haslocaldir() == 2 " 标签页的局部目录情况 else " 全局目录情况 endif " 当前窗口 :echo haslocaldir() :echo haslocaldir(0) :echo haslocaldir(0, 0) " 当前标签页的窗口 n :echo haslocaldir(n) :echo haslocaldir(n, 0) " 标签页 m 的窗口 n :echo haslocaldir(n, m) " 标签页 m :echo haslocaldir(-1, m) 也可用作 method : GetWinnr()->haslocaldir() hasmapto({what} [, {mode} [, {abbr}]]) hasmapto() 返回数值,如果存在某映射,其右边的表达式 (被映射到的部分) 的某 处包含 {what},并且该映射在 {mode} 指定的模式下存在,返回 TRUE。 如果提供 {abbr} 且为 TRUE ,使用缩写而不是映射。不要忘记指定 插入和/或命令行模式。 同时检查全局映射和局部于当前缓冲区的映射以寻找匹配。 如果没有匹配的映射,返回 FALSE。 {mode} 识别下列字符: n 普通模式 v 可视和选择模式 x 可视模式 s 选择模式 o 操作符等待模式 i 插入模式 l Language-Argument ("r"、"f"、"t" 等等) 模式 c 命令行模式 如果没有提供 {mode},使用 "nvo"。 该函数可用于检查是否存在映射到 Vim 脚本的某个函数的映射。例 如: :if !hasmapto('\ABCdoit') : map <Leader>d \ABCdoit :endif 这样,到 "\ABCdoit" 的映射只有在到 "\ABCdoit" 的映射还不存在的 时候才会进行。 也可用作 method : GetRHS()->hasmapto() histadd({history}, {item}) histadd() 把字符串 {item} 加到历史 {history} 里。后者可以是: hist-names "cmd" 或 ":" 命令行历史 "search" 或 "/" 搜索模式历史 "expr" 或 "=" 输入表达式历史 "input" 或 "@" 输入行历史 "debug" 或 ">" 调试命令历史 空 当前或最后使用的历史 {history} 字符串无须是完整名字,一个字符就够了。 如果 {item} 已经在历史里存在,它会被调整位置,从而成为最新的一 项。 返回结果为数值: 如果操作成功则为 TRUE,不然返回 FALSE。 例如: :call histadd("input", strftime("%Y %b %d")) :let date=input("Enter date: ") 该函数在沙盘里不可用 sandbox 。 也可用作 method ,基是作为第二个参数传递的: GetHistory()->histadd('search') histdel({history} [, {item}]) histdel() 清除 {history},换而言之,删除它所有的项目。 hist-names 解释 {history} 的所有可能值。 如果 {item} 计算结果为字符串,它被看作正规表达式。从历史里删除 所有匹配该模式的项目 (如果有的话)。 必须匹配大小写,除非使用 "\c" /\c 。 如果 {item} 的计算结果为数值,它被解释为索引值,见 :history-indexing 。如果该索引存在,删除相应的项目。 返回结果为数值: 如果操作成功则为 TRUE,不然返回 FALSE。 例如: 清除表达式寄存器历史: :call histdel("expr") 删除所有 "*" 开始的搜索历史: :call histdel("/", '^\*') 下面三者是等价的: :call histdel("search", histnr("search")) :call histdel("search", -1) :call histdel("search", '^'.histget("search", -1).'$') 要删除最后的搜索模式,并在 "n" 命令和 'hlsearch' 里使用倒数第 二个模式: :call histdel("search", -1) :let @/ = histget("search", -1) 也可用作 method : GetHistory()->histdel() histget({history} [, {index}]) histget() 返回字符串,即 {history} 历史的第 {index} 项。 hist-names 解 释 {history} 的所有可能值,而 :history-indexing 解释 {index}。如果没有这个项目,返回空字符串。如果忽略 {index},返 回历史里最近使用的项目。 例如: 重做历史里的倒数第二个搜索 :execute '/' . histget("search", -2) 定义 Ex 命令 ":H {num}",以重新执行 :history 输出的第 {num} 项。 :command -nargs=1 H execute histget("cmd", 0+<args>) 也可用作 method : GetHistory()->histget() histnr({history}) histnr() 返回当前项目在 {history} 里的编号。 hist-names 解释 {history} 的所有可能值。 如果有错,返回 -1。 例如: :let inp_index = histnr("expr") 也可用作 method : GetHistory()->histnr() hlexists({name}) hlexists() 返回数值。只要名为 {name} 的高亮组用某种方法定义过,返回 TRUE。不一定要为该组定义过高亮属性。一些语法项目可能已经使用该 组。 highlight_exists() 已废弃的名字: highlight_exists()。 也可用作 method : GetName()->hlexists() hlID() hlID({name}) 返回数值,即名为 {name} 的高亮组的 ID。如果该高亮组不存在,返 回零。 可用于提取高亮组的信息。比如,要得到 "Comment" 组的背景颜色: :echo synIDattr(synIDtrans(hlID("Comment")), "bg") highlightID() 已废弃的名字: highlightID()。 也可用作 method : GetName()->hlID() hostname() hostname() 返回字符串,即 Vim 运行的机器名字。超过 256 字符串长度的机器名 被截短。 iconv({expr}, {from}, {to}) iconv() 返回字符串,即文本 {expr}{from} 编码转到 {to} 编码以后的文 本。 如果转换完全失败,返回空字符串。如果部分字符无法转换,以 "?" 代替之。 编码名字可以是任何 iconv() 库函数接受的名字,见 ":!man 3 iconv"。 大多数转换需要 Vim 编译时加入 +iconv 特性。不然,只支持 UTF-8 和 latin1 的相互转换。 这可以用来显示包含特殊字符的消息。不管 'encoding' 设为何值,总 可以用 UTF-8 书写消息,然后使用: echo iconv(utf8_str, "utf-8", &enc) 注意 Vim 使用 UTF-8 进行所有的 Unicode 编码,从/到 UCS-2 的转 换都自动转为 UTF-8。你不能在字符串里使用 UCS-2,因为那里有 NUL 字节。 也可用作 method : GetText()->iconv('latin1', 'utf-8') indent() indent({lnum}) 返回数值,第 {lnum} 行的缩进距离。缩进的计算以空格计,因而它和 'tabstop' 的值是有关系的。{lnum} 的使用方式和 getline() 相 同。 如果 {lnum} 非法,返回 -1。 也可用作 method : GetLnum()->indent() index({object}, {expr} [, {start} [, {ic}]]) index() 如果 {object}List ,返回值等于 {expr} 的最小项目索引。这 里不进行自动转换,字符串 "4" 不同于数值 4,数值 4 也不等同于浮 点数 4.0。'ignorecase' 的值此处也不适用,大小写不忽略。 如果 {object}Blob ,返回字节值等于 {expr} 的最小索引。 如果给出 {start},从索引为 {start} 的项目开始寻找 (可以为负, 指定相对于尾部的项目)。 如果给出 {ic} 且为 TRUE ,忽略大小写。否则,必须匹配大小写。 如果在 {object} 里找不到 {expr},返回 -1。 示例: :let idx = index(words, "the") :if index(numbers, 123) >= 0 也可用作 method : GetObject()->index(what) input({prompt} [, {text} [, {completion}]]) input() 返回字符串,即用户在命令行上的输入内容,可以为任何值。参数 {prompt} 或者是一个提示字符串,或者是一个空白字符串 (没有提 示)。'\n' 可以在提示里使用,以开始新行。 该提示使用 :echohl 设置的高亮。 输入方法和命令行相似,也使用相同的编辑命令和映射。但 input() 输入的行使用另外的历史。 示例: :if input("咖啡还是啤酒?") == "啤酒" : echo "干杯!" :endif 如果给出可选的 {text} 参数,它被用作缺省的回答,就像是用户输入 的那样。例如: :let color = input("Color? ", "white") 可选的 {completion} 参数指定输入支持的补全类型。如果不给出,不 使用补全。支持的补全类型和用户定义命令用 "-complete=" 参数能给 出的类型相同。详情见 :command-completion 。例如: let fname = input("File: ", "", "file") 注意: 在只能运行于 GUI 模式的版本里 (比如 Win32 GUI),此函数不 能在启动文件里使用。 注意: input() 在映射里调用时,它会消耗该映射余下的字符,因为映 射的处理就像那些字符被键盘输入一样。在 input() 前使用 inputsave() 然后在 input() 输入之后 inputrestore() 可以避 免这一点。另一个方法是避免在映射的后面提供任何字符,比如,使用 :execute:normal 。 使用映射的例子: :nmap \x :call GetFoo()<CR>:exe "/" . Foo<CR> :function GetFoo() : call inputsave() : let g:Foo = input("enter search pattern: ") : call inputrestore() :endfunction 也可用作 method : GetPrompt()->input() inputdialog({prompt} [, {text} [, {cancelreturn}]]) inputdialog() 类似于 input() ,但如果运行 GUI 且支持文本对话框,弹出一个对 话框窗口来输入文本。 例如: :let n = inputdialog("value for shiftwidth", shiftwidth()) :if n != "" : let &sw = n :endif 如果对话框被取消,返回 {cancelreturn}。如果忽略,返回空字符 串。 输入 <Enter> 和按 OK 按钮相同。按 <Esc> 和按 Cancel 按钮相同。 备注: 不支持命令行补全。 也可用作 method : GetPrompt()->inputdialog() inputlist({textlist}) inputlist() {textlist} 必须是字符串的 List 。显示此 List ,每个字符串一 行。用户得到提示要输入一个数值,返回此值。 如果命令行上打开鼠标 ('mouse' 为 "a" 或包含 "c"),用户也可以用 鼠标点击项目来进行选择。第一个字符串返回 0。在第一个项目之上点 击返回负数。在提示行上点击返回 {textlist} 的长度加一。 确保 {textlist} 不超过 'lines' 个项目,否则无法使用。建议把项 目编号放在每个字符串的开始处,并在第一项上加上提示。例如: let color = inputlist(['Select color:', '1. red', \ '2. green', '3. blue']) 也可用作 method : GetChoices()->inputlist() inputrestore() inputrestore() 恢复前一个 inputsave() 保存的预输入。应该和 inputsave() 调 用的次数相同,不过调用更多次也无妨。 如果没有可以恢复的,返回 TRUE,不然返回 FALSE。 inputsave() inputsave() 保存预输入 (也包括映射的) 并清除之,使得下一个提示能从用户得到 输入。在提示之后应该跟上配套的 inputrestore()。可以多次使用, 此时应该有同样多次的 inputrestore() 调用。 如果内存不足,返回 TRUE,不然返回 FALSE。 inputsecret({prompt} [, {text}]) inputsecret() 该函数和 input() 函数类似,但有两个例外: a) 用户的应答显示为一串星号 ("*"),从而输入可以保密,还有 b) 用户的应答不会记录在输入 history 栈中。 返回字符串,即用户在命令行上根据提示输入的应答。 备注: 不支持命令行补全。 也可用作 method : GetPrompt()->inputsecret() insert({object}, {item} [, {idx}]) insert() 如果 {object}ListBlob ,在开始处插入 {item}。 如果指定 {idx}{item} 的插入位置在索引 {idx} 之前。如果 {idx} 为零,插入在第一个项目之前,和省略 {idx} 效果相同。也可 用负的 {idx},见 list-index 。-1 插入在最后一个项目之前。 返回新产生的 ListBlob 。例如: :let mylist = insert([2, 3, 5], 1) :call insert(mylist, 4, -1) :call insert(mylist, 6, len(mylist))add() 可以更简单的完成最后一个例子。 注意{item}List ,它被作为单个项目来插入。 extend() 用来连接多个 List 。 也可用作 method : mylist->insert(item) interrupt() interrupt() 中断脚本的执行。它或多或少像用户按了 CTRL-C 一样。多数命令不再 执行,控制权还给用户。可用于中止较底层如自动命令等的执行。 如: :function s:check_typoname(file) : if fnamemodify(a:file, ':t') == '[' : echomsg 'Maybe typo' : call interrupt() : endif :endfunction :au BufWritePre * call s:check_typoname(expand('<amatch>')) invert({expr}) invert() 按位取反。参数须转换为数值。列表、字典或浮点数参数会报错。 示例: :let bits = invert(bits) 也可用作 method : :let bits = bits->invert() isdirectory({directory}) isdirectory() 返回数值,如果名为 {directory} 的目录存在,返回 TRUE 。如果 {directory} 不存在或者不是目录,返回 FALSE{directory} 可以 是任何表达式,最终用作字符串。 也可用作 method : GetName()->isdirectory() isinf({expr}) isinf() 如果 {expr} 是正无穷大返回 1,负无穷大返回 -1,否则返回 0。 :echo isinf(1.0 / 0.0) 1 :echo isinf(-1.0 / 0.0) -1 也可用作 method : Compute()->isinf() {仅当编译时加入 +float 特性才有效} islocked({expr}) islocked() E786 返回数值,如果 {expr} 是某个加锁的变量名,返回 TRUE{expr} 必须是变量名、 List 项目,或 Dictionary 项目,不是变 量本身!例如: :let alist = [0, ['a', 'b'], 2, 3] :lockvar 1 alist :echo islocked('alist') " 1 :echo islocked('alist[1]') " 0 如果 {expr} 是不存在的变量,得到错误信息。用 exists() 可以检 查它是否存在。 isnan({expr}) isnan() 如果 {expr} 是值为 NaN 的浮点数,返回 TRUE echo isnan(0.0 / 0.0) 1 也可用作 method : Compute()->isnan() {仅当编译时加入 +float 特性才有效} items({dict}) items() 返回 List{dict} 的所有键-值组对。每个 List 项目是两个项 目的列表: {dict} 项目的键和此项目的值。 List 项目的顺序不定。 另见 keys()values() 。 示例: for [key, value] in items(mydict) echo key . ': ' . value endfor 也可用作 method : mydict->items() job_ 函数文档在这里: job-functions-details join({list} [, {sep}]) join() 连接所有 {list} 项目成为字符串。 如果指定 {sep},该分隔符出现在项目之间。如果省略 {sep},用单个 空格。 注意 尾部不加 {sep}。如果你坚持要加入: let lines = join(mylist, "\n") . "\n" 字符串项目照原样使用。用类似 string() 的方式把 ListDictionary 转化为字符串。 逆函数是 split() 。 也可用作 method : mylist->join() js_decode({string}) js_decode() json_decode() 类似,但有以下区别: - 对象键名不需用引号括起。 - 字符串可以用单引号括起。 - 接受数组的空项目 (两个逗句之间),返回 v:none 项目。 也可用作 method : ReadObject()->js_decode() js_encode({expr}) js_encode() json_encode() 类似,但有以下区别: - 对象键名不用引号括起。 - 数组里的 v:none 项目生成逗号之间的空项目。 例如,Vim 对象: [1,v:none,{"one":1},v:none] 会被编码为: [1,,{one:1},,] 而 json_encode() 会生成: [1,null,{"one":1},null] 对 Javscript,这种编码也是合法的。但比 JSON 更高效,尤其是使用 有可选项目的数组时。 也可用作 method : GetObject()->js_encode() json_decode({string}) json_decode() 解析 JSON 格式的字符串,返回等价的 Vim 值。见 json_encode() 了解 JSON 和 Vim 值的关系。 解码是容错的: - 忽略数组和对象拖尾的逗号,例如 "[1, 2, ]" 等同 "[1, 2]"。 - 对象中接受整数键,如 {1:2} 和 {"1":2} 相同。 - 识别更多浮点数,例如 "1." 相当于 "1.0",而 "001.2" 相当于 "1.2"。接受特殊浮点值 "Infinity"、"-Infinity" 和 "NaN" (大小 写无关)。 - 忽略整数值前导零,例如 "012" 相当于 "12",而 "-012" 相当于 "-12"。 - 按本义名 null、true 或 false 的大小写无关,例如 "NULL" 相当 于 "null","True" 相当于 "true"。 - 接受字符串中不转义的控制字符 U+0000 到 U+001F,例如 " " (字符串中的制表符) 相当于 "\t"。 - 接受空或只有空白组成的 JSON 表达式,生成 v:none。 - 忽略非法的两字符转义序列中的反斜杠,例如 "\a" 解码为 "a"。 - JSON 字符串中正确的代理对正常应是 12 字符的序列,如 "\uD834\uDD1E",但 json_decode() 安静地接受截断的代理对,例 如 "\uD834" 或 "\uD834\u"。 E938 对象里的重复键值,虽然在 rfc7159 中合法,便不被 json_decode() 接受,因为转换结果必须是合法的 Vim 类型,例如,这样不行: {"a":"b", "a":"c"} 也可用作 method : ReadObject()->json_decode() json_encode({expr}) json_encode() {expr} 进行 JSON 编码,返回字符串。 编码格式在此指定: https://tools.ietf.org/html/rfc7159.html Vim 值的转换如下: Number 十进制数 Float 浮点数 Float nan "NaN" Float inf "Infinity" Float -inf "-Infinity" String 双引号括起 (可为 null) Funcref 不接受,报错 List 作为数组 (可为 null);若递归使用: [] Dict 作为对象 (可为 null);若递归使用: {} Blob 作为一个个字节组成的数组 v:false "false" v:true "true" v:none "null" v:null "null" 备注 NaN 和 Infinity 作为值传递。这在 JSON 标准里没有提到,但 若干实现支持。如果不支持,可能会报错。 也可用作 method : GetObject()->json_encode() keys({dict}) keys() 返回 List{dict} 的所有键。 List 项目的顺序不定。另见 items()values() 。 也可用作 method : mydict->keys() len() E701 len({expr}) 返回数值,参数的长度。 如果 {expr} 为字符串或数值,返回它使用的字节数,和 strlen() 相同。 如果 {expr}List ,返回 List 的项目数量。 如果 {expr}Blob ,返回字节数。 如果 {expr}Dictionary ,返回 Dictionary 的项目数量。 否则给出错误。 也可用作 method : mylist->len() libcall() E364 E368 libcall({libname}, {funcname}, {argument}) 在运行库 {libname} 里调用函数 {funcname} 并给出单个参数 {argument}。 这可以用于调用库里的函数,尤其是 Vim 里用到的那些。因为只能使 用单个参数,所以可以调用的标准库函数相当有限。 结果是函数返回的字符串。如果函数返回 NULL,在 Vim 里会以空字符 串 "" 出现。 如果函数返回数值,请使用 libcallnr() ! 如果 {argument} 是数值,它以 int 类型传给函数;如果 {argument} 是字符串,它以 null 结尾的字符串类型传入。 在 restricted-mode 里,该函数不能运行。 libcall() 允许你写自己的 Vim '插件' 扩展,而无须重新编译程序。 它并 是用来调用系统函数的一个方法!如果你试图这么做,Vim 很 有可能会崩溃。 Win32 上,你写的函数必须在 DLL 里提供,而且必须使用普通的 C 调 用惯例 ( 不是 Windows 系统 DLL 使用的 Pascal 惯例)。函数必须 只能接受单个参数,或者是字符指针,或者是长整数,而且必须返回字 符指针或者 NULL。返回的字符指针必须指向在函数返回之后仍然指向 合法的内存 (比如 DLL 的静态区域)。如果指向分配的区域,那么内存 会发生泄漏。在函数里使用静态缓冲区应该可以,在 DLL 卸载时会被 释放。 警 告: 如果函数返回不合法的指针,Vim 会崩溃!如果函数返回数值 也会发生同样的问题,因为 Vim 把它当作指针看待。 Win32 系统上,{libname} 必须是不带 ".DLL" 后缀的 DLL 文件名。 只有 DLL 不在常见的位置的时候,才需要指定完整的路径名。 Unix 上: 如果编译你自己的插件,记住目标代码必须生成位置无关代 码 ('PIC')。 {仅当使用 Win32 和一些 Unix 版本且带有 +libcall 特性时才有 效} 例如: :echo libcall("libc.so", "getenv", "HOME") 也可用作 method ,基是作为第三个参数传递的: GetValue()->libcall("libc.so", "getenv") libcallnr() libcallnr({libname}, {funcname}, {argument}) 和 libcall() 类似,但函数返回 int,而不是字符串。 {仅当使用 Win32 和一些 Unix 版本且带有 +libcall 特性时才有 效} 例如: :echo libcallnr("/usr/lib/libc.so", "getpid", "") :call libcallnr("libc.so", "printf", "Hello World!\n") :call libcallnr("libc.so", "sleep", 10) 也可用作 method ,基是作为第三个参数传递的: GetValue()->libcallnr("libc.so", "printf") line({expr} [, {winid}]) line() 返回数值,即 {expr} 给定的文件位置的行号。可接受的位置是: . 光标位置 $ 缓冲区的最后一行 'x 位置标记 x 的位置 (如果该位置标记没有设置,返回 0) w0 当前窗口可见部分的首行 (如果显示不刷新,如安静 Ex 模式下,则为一) w$ 当前窗口可见部分的末行 (如果无行可见,返回比 w0 小 一的值) v 可视模式下: 可视区域的开始行 (光标是结束位置)。 如果不在可视模式下,返回当前光标位置。和 '< 不同 的是,会被立即更新。 注意 可以使用其它文件的位置标记。此时行号应用于那个缓冲区。 要得到列号用 col() 。两者都要可用 getpos() 。 给出可选的 {winid} 参数时,从该窗口取值而不是当前窗口。 例如: line(".") 光标所在的行号 line(".", winid) 同上,但取自窗口 "winid" line("'t") 位置标记 t 的行号 line("'" . marker) 名为 marker 的位置标记的行号 要在打开文件后跳转到最近已知的位置,见 last-position-jump 。 也可用作 method : GetValue()->line() line2byte({lnum}) line2byte() 返回当前缓冲区第 {lnum} 行从缓冲区开始计算的字节数。这里包括换 行符,但它具体的值取决于当前缓冲区的 'fileformat' 选项,第一行 返回 1。这和 'encoding' 有关但忽略 'fileencoding'。 这也可以用来得到最后一行之后的 "那行" 的字节计数: line2byte(line("$") + 1) 这就等于缓冲区大小加 1。如果 'fileencoding' 为空则等于文件大小 加 1。 如果 {lnum} 非法或者编译时关闭了 +byte_offset 特性,返回 -1。另见 byte2line()go:goto 。 也可用作 method : GetLnum()->line2byte() lispindent({lnum}) lispindent() 得到第 {lnum} 行根据 lisp 缩进规则应有的缩进距离,见 'lisp'。 缩进的计算以空格计,因而和 'tabstop' 的值是有关系的。 {lnum} 的使用方式和 getline() 相同。 如果 {lnum} 非法或者 Vim 编译时不带 +lispindent 特性,返回 -1。 也可用作 method : GetLnum()->lispindent() list2str({list} [, {utf8}]) list2str() {list} 中的每个数值转换为字符,并连接成字符串。例如: list2str([32]) 返回 " " list2str([65, 66, 67]) 返回 "ABC" 也可以这样实现 (慢): join(map(list, {nr, val -> nr2char(val)}), '') str2list() 是逆操作。 {utf8} 省略或为零时,使用当前 'encoding'{utf8} 为 1 时,总是返回 utf-8 字符。 使用 utf-8 时,组合字符正常工作: list2str([97, 769]) 返回 "á" 也可用作 method : GetList()->list2str() listener_add({callback} [, {buf}]) listener_add() 添加缓冲区 {buf} 有改动时会被执行的回调函数。 {buf} 可以是缓冲区名或号。它可接受的值见 bufname() 。省略 {buf} 时使用当前缓冲区。 返回唯一的 ID,可传递给 listener_remove(){callback} 调用时带五个参数: a:bufnr 发生改动的缓冲区 a:start 改动发生的首行行号 a:end 改动区域之下的首行行号 a:added 增加的行数,如果删除行则为负数 a:changes 关于改动细节的项目列表 示例: func Listener(bufnr, start, end, added, changes) echo 'lines ' .. a:start .. ' until ' .. a:end .. ' changed' endfunc call listener_add('Listener', bufnr) 此列表不能修改。a:changes 的每个项目是带以下项的字典: lnum 改动的首行行号 end 改动区域之下的首行行号 added 增加的行数,如果删除行则为负数 col "lnum" 中受改动影响的首列;如果未知或整行都受 影响则为一;这是字节计数,首个字符的值为一。 插入新行时,值为: lnum 在该行之上加入了新行 end 等于 "lnum" added 插入的行数 col 1 删除行时,值为: lnum 首个删除行 end 删除发生之前首 (译者注: 应为末?) 个删除行之下 的那行 added 负数,删除的行数 col 1 行发生改动时: lnum 首个改动行 end 最后改动行之下的那行 added 0 col 改动发生的首列,或 1 依改动发生的次序列出项目,这样最近发生的改动在最后。行号在回调 发生时是合法的,但之后的改动可能使之非法,所以保存它们以备后用 是不可行的。 在屏幕刚刚刷新前调用 {callback},此后调用 listener_flush() 或进行影响行的数目的改动会使得改动列表里的行号变成非法。 {callback} 调用时文本被锁定,见 textlock 。如果需要改动缓冲 区,使用定时器可以在之后某时进行需要的改动 timer_start() 。 缓冲区初次载入时不调用 {callback}BufReadPost 自动命令事件 可用来处理缓冲区的初始文本。 缓冲区被卸载时也不调用 {callback}BufUnload 自动事件可用于 此。 也可用作 method ,基是作为第二个参数传递的: GetBuffer()->listener_add(callback) listener_flush([{buf}]) listener_flush() 调用缓冲区 {buf} 的监听器回调。如果没有待处理的改动则不调用回 调。 {buf} 可以是缓冲区名或号。它可接受的值见 bufname() 。省略 {buf} 时使用当前缓冲区。 也可用作 method : GetBuffer()->listener_flush() listener_remove({id}) listener_remove() 删除之前用 listener_add() 加的监听器。 如果 {id} 找不到返回 FALSE,{id} 已删除时返回 TRUE。 也可用作 method : GetListenerId()->listener_remove() localtime() localtime() 返回当前时间,以 1970 年 1 月 1 日开始的秒数计算。另见 strftime()strptime()getftime() 。 log({expr}) log() 返回浮点数,即浮点数 {expr} 的自然对数 (即以 e 为底)。 {expr} 计算结果必须为 (0, inf] 区间内的浮点数或数值。 示例: :echo log(10) 2.302585 :echo log(exp(5)) 5.0 也可用作 method : Compute()->log() {仅当编译时加入 +float 特性才有效} log10({expr}) log10() 返回浮点数,即浮点数 {expr} 以 10 为底的对数。 {expr} 计算结果必须为浮点数或数值。 示例: :echo log10(1000) 3.0 :echo log10(0.01) -2.0 也可用作 method : Compute()->log10() {仅当编译时加入 +float 特性才有效} luaeval({expr} [, {expr}]) luaeval() 执行 Lua 表达式 {expr} 并把结果转换为 Vim 数据结构。第二个 {expr} 指定在第一个 {expr} 里可以使用的额外参数,可以 _A 形式 访问。 字符串原样返回。 布尔值对象转换为数值。 vim 编译时带 +float 特性时,数值转换为 Float ,否则作为数值 型返回。 vim.eval() 得到的字典和列表以原样返回。 lua-luaeval 有更多详情。 也可用作 method : GetExpr()->luaeval() {仅当编译时加入 +lua 特性才有效} map({expr1}, {expr2}) map() {expr1} 必须是 ListBlobDictionary{expr1} 里的每个项目被 {expr2} 的计算结果替代。 Blob 的每个字 节被替代。 如果项目的类型发生变化,可以考虑用 mapnew() 来创建新的列表或 字典。Vim9 脚本里这是必须的。 {expr2} 必须是 stringFuncref 。 如果 {expr2}string{expr2} 内的 v:val 包含当前项目的 值。 Dictionaryv:key 包含当前项目的键。 Listv:key 包含当前项目的索引。 例如: :call map(mylist, '"> " . v:val . " <"') "mylist" 里的每个项目之前放上 "> ",而之后放上 " <"。 注意 {string} 是表达式的计算结果,而它本身又用作表达式。通常, 最好用 literal-string 来避免反斜杠加倍。当然,你仍然需要加倍 ' 引号。 如果 {expr2}Funcref ,它必须接受两个参数: 1. 当前项目的键或索引。 2. 当前项目的值。 函数必须返回项目的新值。例如要改变每个值为 "键-值": func KeyValue(key, val) return a:key . '-' . a:val endfunc call map(myDict, function('KeyValue')) 使用 lambda 会更短: call map(myDict, {key, val -> key . '-' . val}) 如果不用 "val",可以不写: call map(myDict, {key -> 'item: ' . key}) 如果不用 "key",可以使用短名: call map(myDict, {_, val -> 'item: ' . val}) 本操作是原位操作 (直接在输入上修改)。要想不更动 ListDictionary ,先建立备份: :let tlist = map(copy(mylist), ' v:val . "\t"') 返回 {expr1},经过过滤的 ListBlobDictionary 。如果 执行 {expr2} 有错,不再处理 {expr1} 的其余项目。{expr2} 是函数 引用时,忽略函数里的错误,除非该函数用 "abort" 标志位定义。 也可用作 method : mylist->map(expr2) maparg({name} [, {mode} [, {abbr} [, {dict}]]]) maparg() {dict} 省略或为零,返回模式 {mode} 名为 {name} 的映射的右手 边 (rhs)。返回字符串中的特殊字符用和 ":map" 命令输出的同样方式 进行翻译。 如果没有名为 {name} 的映射,返回 "<Nop>"。 {name} 可包含特殊键名,一如 ":map" 命令。 {mode} 可以使用下列字符串之一: "n" 普通模式 "v" 可视模式 (包括选择) "o" 操作符等待模式 "i" 插入模式 "c" 命令行模式 "s" 选择模式 "x" 可视模式 "l" 语言映射 language-mapping "t" 终端-作业 "" 普通、可视和操作符等待模式。 如果没有提供 {mode},使用 "" 指定的模式。 如果提供 {abbr} 且为 TRUE ,使用缩写而不是映射。 如果提供 {dict} 且为 TRUE ,返回字典,包含关于映射的所有信 息。有如下项目: "lhs" 映射的 {lhs},作为键盘输入 "lhsraw" 映射的 {lhs},保留原始字节 "lhsrawalt" 映射的 {lhs},保留原始字节,这是一种替代形式,仅 当和 "lhsraw" 不同时才会存在 "rhs" 映射的 {rhs},作为键盘输入。 "silent" 1 若是 :map-silent 映射,否则为 0。 "noremap" 1 若是映射的 {rhs} 不能再映射。 "script" 1 若是映射使用 <script> 定义。 "expr" 1 若是表达式映射 ( :map-<expr> )。 "buffer" 1 若是缓冲区本地映射 ( :map-local )。 "mode" 映射定义使用的模式。除了以上提到的模式以外,还会 使用: " " 普通、可视和操作符等待模式 "!" 插入和命令行模式 ( mapmode-ic ) "sid" 脚本局部 ID,用于 <sid> 映射 ( <SID> )。 "lnum" "sid" 中的行号,如果未知则为零。 "nowait" 不等待其它更长的映射。( :map-<nowait> )。 此字典可用 mapset() 来恢复映射。 先检查局部于当前缓冲区的映射,然后再检查全局映射。 此函数可以用来给键映射。如果已经映射过,还可以使用原来映射的内 容。大意: exe 'nnoremap <Tab> ==' . maparg('<Tab>', 'n') 也可用作 method : GetKey()->maparg('n') mapcheck({name} [, {mode} [, {abbr}]]) mapcheck() 检查是否有模式 {mode} 下匹配 {name} 的映射。 maparg() 说明 {mode}{name} 里的特殊键名。 如果提供 {abbr} 且为 TRUE ,使用缩写而不是映射。 匹配在映射名以 {name} 开始或者映射名等于 {name} 的开始部分时候 发生。 匹配映射 "a" "ab" "abc" mapcheck("a") 是 是 是 mapcheck("abc") 是 是 是 mapcheck("ax") 是 否 否 mapcheck("b") 否 否 否 和 maparg() 的差别是,mapcheck() 查找匹配 {name} 的映射,而 maparg() 只查找名字完全符合 {name} 的映射。 如果没有 {name} 开始的映射,返回空字符串。如果有一个,返回该映 射的右手边。如果有多个,返回其中某一个的右手边。如果该右手边为 空,返回 "<Nop>"。 先检查局部于当前缓冲区的映射,然后再检查全局映射。 该函数用于检查是否可以无二义性地添加映射。例如: :if mapcheck("_vv") == "" : map _vv :set guifont=7x13<CR> :endif 就避免了在已有 "_v" 或者 "_vvv" 映射的时候添加 "_vv" 映射。 也可用作 method : GetKey()->mapcheck('n') mapnew({expr1}, {expr2}) mapnew() 类似于 map() ,但生成并返回新的列表或字典而不是替换 {expr1} 里的项目。{expr1} 保持不变。项目仍然可由 {expr2} 改变,如果不 想如此,先用 deepcopy() 。 mapset({mode}, {abbr}, {dict}) mapset() maparg() 返回的字典中恢复映射。 {mode}{abbr} 应和 maparg() 调用时所用之值相同. E460 {mode} 用于定义映射设置所在的模式,而不是 {dict} 中的 "mode" 项目。 保存和恢复映射的示例: let save_map = maparg('K', 'n', 0, 1) nnoremap K 其它映射值 ... call mapset('n', 0, save_map) 注意 要替换适用于若干模式下的映射,如 :map! 这样的,你需要分 别保存所有模式下的映射,因为它们之间可能不同。 match({expr}, {pat} [, {start} [, {count}]]) match() 如果 {expr}List ,返回匹配 {pat} 的第一个项目的索引。每个 项目用作字符串, ListDictionary 使用回显的形式。 否则,{expr} 用作字符串。返回数值,给出 {expr}{pat} 匹配的 (字节计算的偏移量) 位置。 在第一个字符或 List 项目上的匹配返回零。若无匹配,返回 -1。 要得到子匹配,见 matchlist() 。 例如: :echo match("testing", "ing") " 返回 4 :echo match([1, 'x'], '\a') " 返回 1 string-match 说明如何使用 {pat} strpbrk() Vim 没有 strpbrk() 函数。但你可以这么做: :let sepidx = match(line, '[.,;: \t]') strcasestr() Vim 没有 strcasestr() 函数。但你可以在模式里加入 "\c" 以忽略大 小写: :let idx = match(haystack, '\cneedle') 如果给出 {start},搜索从字符串的字节位置 {start}List 索 引为 {start} 的项目开始。 不过,结果仍然从第一个字符/项目开始算起。比如: :echo match("testing", "ing", 2) 返回结果是 "4"。 :echo match("testing", "ing", 4) 返回结果还是 "4"。 :echo match("testing", "t", 2) 返回 "3"。 对字符串而言,如果 {start} > 0,其行为就像该字符串在 {start} 个字节后开始,因而 "^" 会从 {start} 开始匹配。如果给出 {count} 时则不是如此,此时忽略 {start} 字节前的匹配 (有一点复杂,这是 为了后向兼容)。 对字符串而言,如果 {start} < 0,它被置为 0。对列表而言,此索引 从尾部起算。 如果 {start} 越界 (字符串 {start} > strlen({expr}),而 List {start} > len({expr})),返回 -1。 如果给出 {count},使用第 {count} 个匹配。如果字符串里找到一个 匹配,下一匹配从此匹配之后一个字符开始寻找。所以下例返回 1: echo match("testing", "..", 0, 2) List 里,搜索从下一个项目开始。 注意 如果加入 {count}{start} 使用的方式有所改变。见上。 pattern 说明可以接受的模式。 'ignorecase' 选项用来设定模式是否忽略大小写。 使用 'smartcase'。匹配总是假定置位了 'magic''cpoptions' 为空。 注意 优先考虑开始处的匹配,所以使用 "*" (任意数目的匹配) 时, 模式倾向于寻找开始处的零匹配而不是文本内部的多数目匹配。 也可用作 method : GetList()->match('word') matchadd() E798 E799 E801 E957 matchadd({group}, {pattern} [, {priority} [, {id} [, {dict}]]]) 定义模式 (一个 "匹配"), 在当前窗口用高亮组 {group} 高亮。返回 标识号 (ID), matchdelete() 可用该 ID 来删除匹配。该 ID 是和 窗口绑定的。 匹配是大小写敏感和带魔术的,但大小写敏感性和魔术性在 {pattern} 里可被显式关闭。不使用 'magic''smartcase''ignorecase' 选项。 "Conceal" 值是特别的,它使匹配被隐藏。 可选的 {priority} 参数指定匹配的优先级。高优先级的匹配的高亮会 否决低优先级匹配的高亮。优先级用整数指定 (负整数也无不可)。如 果未指定 {priority} 参数,缺省优先级为 10。'hlsearch' 的优先级 为零,这样所有正优先级的匹配都可以否决它。语法高亮 (见 'syntax') 采用不同的机制,无论选择的优先级如何,匹配总会否决语 法的高亮。 可选的 {id} 参数请求特定的匹配 ID。如果指定的 ID 已用,报错, 并不加入该匹配。ID 用正整数指定 (不含零)。ID 1、2 和 3 分别为 :match:2match:3match 命令保留。如果 {id} 未指定或 为 -1, matchadd() 自动选择一个可用的 ID。 可选的 {dict} 参数允许更多定制。目前,可用来指定特定于匹配的隐 藏字符,使用 hl-Conceal 高亮匹配来显示。该字典有以下成员: conceal 显示的特殊字符,而非匹配 (只用于 hl-Conceal 高亮匹配,见 :syn-cchar ) window 不使用当前窗口,而使用指定窗口号或窗口 ID 的其它窗口。 匹配的数目不限, :match 诸命令则有此局限。 示例: :highlight MyGroup ctermbg=green guibg=green :let m = matchadd("MyGroup", "TODO") 要删除该模式: :call matchdelete(m) getmatches() 可以得到 matchadd():match 定义的匹配 列表。 clearmatches() 可一次删除所有的匹配。 也可用作 method : GetGroup()->matchadd('TODO') matchaddpos() matchaddpos({group}, {pos} [, {priority} [, {id} [, {dict}]]]) 和 matchadd() 相同,但需要位置列表 {pos} 而非匹配模式。比 matchadd() 更快,因为无需处理正规表达式并设置缓冲区行边界以 重画屏幕。主要用于需要快速增加或删除匹配的场合,如匹配括号的高 亮。 {pos} 是位置的列表。每个位置为以下之一: - 数值。该行整行被高亮。首行的行号为 1。 - 单个数值的列表。如 [23]。该行整行被高亮。 - 包含两个数值的列表,如 [23, 11]。前面的数是行号,后面的是列 号 (首列为 1,必须对应 col() 返回的字节索引)。此位置的字符 被高亮。 - 包含三个数值的列表,如 [23, 11, 3]。同上,但第三个数给出高亮 字节计的长度。 {pos} 中最多可有 8 个位置。 示例: :highlight MyGroup ctermbg=green guibg=green :let m = matchaddpos("MyGroup", [[23, 24], 34]) 模式的删除: :call matchdelete(m) getmatches() 返回 matchaddpos() 加入的匹配。 也可用作 method : GetGroup()->matchaddpos([23, 11]) matcharg({nr}) matcharg() 选择 {nr} 号匹配的项目,它们分别用 :match:2match:3match 命令设置。 返回两个项目的 List : 使用的高亮组名 使用的模式。 如果 {nr} 不是 1、2 或 3,返回空 List 。 如果没有匹配的项目,返回 ['', '']。 这用来保存和恢复 :match 。 用 :match 命令高亮的匹配限于三个。 matchadd() 无此限制。 也可用作 method : GetMatch()->matcharg() matchdelete({id} [, {win}) matchdelete() E802 E803 删除之前用 matchadd():match 诸命令定义的 ID 为 {id} 的 匹配。如果成功,返回 0,不然返回 -1。示例见 matchadd()clearmatches() 可一次删除所有的匹配。 如果指定 {win},使用指定窗口号或窗口 ID 的窗口而不是当前窗口。 也可用作 method : GetMatch()->matchdelete() matchend({expr}, {pat} [, {start} [, {count}]]) matchend() match() 相同,但返回匹配之后的第一个字符的位置。比如: :echo matchend("testing", "ing") 返回 "7"。 strspn() strcspn() Vim 没有 strspn() 或 strcspn() 函数,但可用 matchend() 实现: :let span = matchend(line, '[a-zA-Z]') :let span = matchend(line, '[^a-zA-Z]') 不过没有匹配时,它返回 -1。 如果给出 {start},和 match() 里的用法相同。 :echo matchend("testing", "ing", 2) 返回 "7"。 :echo matchend("testing", "ing", 5) 返回 "-1"。 如果 {expr}List ,结果和 match() 相同。 也可用作 method : GetText()->matchend('word') matchfuzzy({list}, {str} [, {dict}]) matchfuzzy() 如果 {list} 为字符串列表,返回 List ,包含 {list} 中的所有模 糊匹配 {str} 的字符串。返回列表中的字符串依匹配分数排序。 可选的 {dict} 参数总是支持以下项目: matchseq 如果此项目存在且 {str} 包含空白分隔的多个单词, 只返回单词以该序列出现的匹配。 如果 {list} 为字典列表,则可选的 {dict} 参数还支持以下项目: key 用于模糊匹配 {str} 项目的键。该项目值必须为字 符串。 text_cb 对 {list} 中每个项目都会调用的 Funcref ,用于 获取模糊匹配的文本。此函数应接受字典项目作为参 数,并返回该项目用于模糊匹配的文本。 {str} 视作字符串常数, 支持正规表达式匹配。{str} 支持的最大 长度为 256。 如果 {str} 包含空白分隔的多个单词,返回包含所有这些单词的字符 串的列表。 如果没有匹配的字符串或有错误,返回空列表。如果 {str} 的长度大 于 256,也返回空列表。 示例: :echo matchfuzzy(["clay", "crow"], "cay") 返回 ["clay"]. :echo getbufinfo()->map({_, v -> v.name})->matchfuzzy("ndl") 返回模糊匹配 "ndl" 的缓冲区名的列表。 :echo getbufinfo()->matchfuzzy("ndl", {'key' : 'name'}) 返回模糊匹配 "ndl" 的缓冲区信息字典的列表。 :echo getbufinfo()->matchfuzzy("spl", \ {'text_cb' : {v -> v.name}}) 返回模糊匹配 "spl" 的缓冲区信息字典的列表。 :echo v:oldfiles->matchfuzzy("test") 返回模糊匹配 "test" 的文件名的列表。 :let l = readfile("buffer.c")->matchfuzzy("str") 返回 "buffer.c" 文件中模糊匹配 "str" 的行的列表。 :echo ['one two', 'two one']->matchfuzzy('two one') 返回 ['two one', 'one two']。 :echo ['one two', 'two one']->matchfuzzy('two one', \ {'matchseq': 1}) 返回 ['two one']。 matchfuzzypos({list}, {str} [, {dict}]) matchfuzzypos() matchfuzzy() 相同,但返回列表,包含匹配字符串的列表、匹配 {str} 中的字符的字符位置的列表、和匹配分数的列表。可用 byteidx() 把字符位置转为字节位置。 如果 {str} 在字符串中有多个匹配,只返回最佳匹配的位置。 如果没有匹配的字符串或有错,返回包含三个空列表项目的列表。 示例: :echo matchfuzzypos(['testing'], 'tsg') 返回 [['testing'], [[0, 2, 6]], [99]] :echo matchfuzzypos(['clay', 'lacy'], 'la') 返回 [['lacy', 'clay'], [[0, 1], [1, 2]], [153, 133]] :echo [{'text': 'hello', 'id' : 10}]->matchfuzzypos('ll', {'key' : 'text'}) 返回 [[{'id': 10, 'text': 'hello'}], [[2, 3]], [127]] matchlist({expr}, {pat} [, {start} [, {count}]]) matchlist() match() 相同,但返回 List 。列表第一项是匹配的字符串,和 matchstr() 返回值相同。其后的项目是子匹配,类似 :substitute 的 "\1"、"\2" 等。如果某个可选的子匹配不匹配,用 空字符串代替。例如: echo matchlist('acd', '\(a\)\?\(b\)\?\(c\)\?\(.*\)') 返回: ['acd', 'a', '', 'c', 'd', '', '', '', '', ''] 如果没有匹配,返回空列表。 也可用作 method : GetList()->matchlist('word') matchstr({expr}, {pat} [, {start} [, {count}]]) matchstr() match() 相同,但返回匹配的字符串。例如: :echo matchstr("testing", "ing") 返回 "ing"。 如果没有匹配,返回 ""。 如果给出 {start},它和 match() 里的用法相同。 :echo matchstr("testing", "ing", 2) 返回 "ing"。 :echo matchstr("testing", "ing", 5) 返回 ""。 如果 {expr}List ,返回匹配的项目。其类型不改变,因而不一 定是字符串。 也可用作 method : GetText()->matchstr('word') matchstrpos({expr}, {pat} [, {start} [, {count}]]) matchstrpos() matchstr() 相同,但返回匹配的字符串和匹配的始末位置。例 如: :echo matchstrpos("testing", "ing") 返回 ["ing", 4, 7]。 如果没有匹配,返回 ["", -1, -1]。 如果给出 {start},它和 match() 里的用法相同。 :echo matchstrpos("testing", "ing", 2) 返回 ["ing", 4, 7]。 :echo matchstrpos("testing", "ing", 5) 返回 ["", -1, -1]。 如果 {expr}List ,返回匹配项目,{pat} 匹配的首个项目的索 引,匹配的开始位置和结束位置。 :echo matchstrpos([1, '__x'], '\a') 返回 ["x", 1, 2, 3]。 不改变类型,不必然是字符串。 也可用作 method : GetText()->matchstrpos('word') max() max({expr}) 返回 {expr} 所有项目的最大值。例如: echo max([apples, pears, oranges]) {expr} 可以是 ListDictionary 。如果是字典,返回字典中所 有值的最大值。 如果 {expr} 不是列表或字典,或者其中某个项目不能用作数值,出 错。空 ListDictionary 返回零。 也可用作 method : mylist->max() menu_info({name} [, {mode}]) menu_info() 返回指定模式 {mode} 下的菜单 {name} 的信息。须指定不带快捷字符 ('&') 的菜单名。 {mode} 可为下列字符串之一: "n" 普通 "v" 可视 (包括选择) "o" 操作符等待 "i" 插入 "c" 命令行 "s" 选择 "x" 可视 "t" 终端作业 "" 普通、可视和操作符等待 "!" 插入和命令行 {mode} 省略时使用 "" 作为模式。 返回包含以下项的 Dictionary : accel 菜单项目加速文本 menu-text display 显示名 (不带 '&' 的名字) enabled 如果此菜单项目打开,返回 v:true 参考 :menu-enable icon 图标文件名 (用于工具栏) toolbar-icon iconidx 内建图标的索引 modes 菜单为之定义的模式。除了上述模式以外,还使用以 下字符: " " 普通、可视和操作符等待 name 菜单项目名。 noremenu 如果菜单项目的 {rhs} 不可重映射返回 v:true,否 则返回 v:false。 priority 菜单顺序优先级 menu-priority rhs 菜单项目的右手边。返回字符串中的特殊字符以 ":menu" 命令列表输出的同样的方式进行翻译。如果 菜单的 {rhs} 为空,返回 "<Nop>"。 script 如果 {rhs} 允许局部于脚本的重映射,返回 v:true,否则返回 v:false。见 :menu-script 。 shortcut 快捷键 (菜单名中 '&' 之后的字符) menu-shortcut silent 菜单项目创建时如带 <silent> 参数,返回 v:true :menu-silent submenus 包含返回子菜单名的 List 。仅当菜单项目有子菜 单时才存在。 如果菜单项目找不到,返回空字典。 示例: :echo menu_info('Edit.Cut') :echo menu_info('File.Save', 'n') 也可用作 method : GetMenuName()->menu_info('v') min() min({expr}) 返回 {expr} 所有项目的最小值。例如: echo min([apples, pears, oranges]) {expr} 可以是 ListDictionary 。如果是字典,返回字典中所 有值的最小值。 如果 {expr} 不是列表或字典,或者其中某个项目不能用作数值,出 错。空 ListDictionary 返回零。 也可用作 method : mylist->min() mkdir() E739 mkdir({name} [, {path} [, {prot}]]) 建立目录 {name}。 如果 {path} 为 "p",必要时建立中间的目录。否则它必须是 ""。 如果给出 {prot},它用于设置新目录的权限。缺省为 0o755 (rwxr-xr-x: 用户自己可读写,其它人可读)。用 0o700 使其它人不可 读。这只用于 {name} 的最后部分。所以,如果建立 /tmp/foo/bar, /tmp/foo 创建时的权限是 0o755。 示例: :call mkdir($HOME . "/tmp/foo/bar", "p", 0o700) 该函数在沙盘里不可用 sandbox 。 如果目录已存在且传递了 "p" 标志位,不报错 (从补丁 8.0.1708 起)。如果没有 "p" 位就会失败。 此函数返回数值,如果调用成功则为 TRUE,如果目录创建失败或部分 失败则为 FALSE。 不一定在所有系统上都可用。要检查这一点,使用: :if exists("*mkdir") 也可用作 method : GetName()->mkdir() mode() mode([expr]) 返回指示当前模式的字符串。 如果指定 [expr] 并且其值为非零的数值或非空的字符串 ( non-zero-arg ),返回完整模式,不然,返回第一个字母。 另见 state() 。 n 普通模式,终端-普通 no 操作符等待模式 nov 操作符等待模式 (强制面向字符 o_v ) noV 操作符等待模式 (强制面向行 o_V ) noCTRL-v 操作符等待模式 (强制面向列块 o_CTRL-V ); CTRL-V 是单个字符 niI Insert-modei_CTRL-O 进入的普通模式 niR Replace-modei_CTRL-O 进入的普通模式 niV Virtual-Replace-modei_CTRL-O 进入的普通模 式 v 面向字符的可视模式 V 面向行的可视模式 CTRL-V 面向列块的可视模式 s 面向字符的选择模式 S 面向行的选择模式 CTRL-S 面向列块的选择模式 i 插入模式 ic 插入模式补全 compl-generic ix 插入模式 i_CTRL-X 补全 R 替换模式 R Rc 替换模式补全 compl-generic Rv 虚拟替换模式 gR Rx 替换模式 i_CTRL-X 补全 c 命令行编辑模式 cv Vim Ex 模式 gQ ce 普通 Ex 模式 Q r 输入回车的提示 rm -- more -- 提示 r? :confirm 等等的询问 ! 执行外壳或外部命令时 t 终端-作业模式: 键入传给作业 可用于 'statusline' 选项或 remote_expr() 。在其它的多数地方, 它总是返回 "c" 或 "n"。 注意将来可能会加入更多模式和更多特定模式。最好不要比较整个字符 串而只比较开头的字符 (一或多个)。 另见 visualmode() 。 也可用作 method : DoFull()->mode() mzeval({expr}) mzeval() 计算 MzScheme 表达式 {expr} 并返回计算结果,转换为 Vim 本身的 数据结构。 数值和字符串返回本身。 组对 (pair) (包含列表 (list) 和非常规列表 (improper list)) 和 向量 (vector) 以 Vim List 形式返回。 哈希表 (hash table) 以 Vim Dictionary 形式返回,其键转换成字 符串。 所有其它类型依 display 函数调用的结果转换为字符串。 示例: :mz (define l (list 1 2 3)) :mz (define h (make-hash)) (hash-set! h "list" l) :echo mzeval("l") :echo mzeval("h") 也可用作 method : GetExpr()->mzeval() {仅当编译时带 +mzscheme 特性才有效} nextnonblank({lnum}) nextnonblank() 返回第一个从 {lnum} 开始的非空白行的行号。例如: if getline(nextnonblank(1)) =~ "Java" 如果 {lnum} 非法或者在从该行开始都没有非空白行,返回零。 另见 prevnonblank() 。 也可用作 method : GetLnum()->nextnonblank() nr2char({expr} [, {utf8}]) nr2char() 返回单个字符组成的字符串,该字符的数值为 {expr}。例如: nr2char(64) 返回 "@" nr2char(32) 返回 " " 如果 {utf8} 省略或为零,使用当前的 'encoding'。比如对 "utf-8" 来说: nr2char(300) 返回带有弓形的 I 如果 {utf8} 为 1,则总返回 utf-8 字符。 注意 文件里的 NUL 字符须用 nr2char(10) 指定。因为 Vim 用换行符 来表示 NUL。真正的 NUL 是 nr2char(0),而它会终结字符串,因而返 回空串。 要把字符值的列表转换为字符串: let list = [65, 66, 67] let str = join(map(list, {_, val -> nr2char(val)}), '') 结果是: "ABC" 也可用作 method : GetNumber()->nr2char() or({expr}, {expr}) or() 对两个参数进行按位或。参数须转换为数值。列表、字典或浮点数参数 会报错。 示例: :let bits = or(bits, 0x80) 也可用作 method : :let bits = bits->or(0x80) pathshorten({expr} [, {len}]) pathshorten() 缩短路径 {expr} 里的目录名,返回其结果。路径的尾部亦即文件名, 保持不变。路径的其余部分被缩短为 {len} 个字符。如果 {len} 省略 或小于 1,则假定为 1 (单个字母)。保持每个部分引导的 '~' 和 '.' 字符不变。例如: :echo pathshorten('~/.vim/autoload/myfile.vim') ~/.v/a/myfile.vim :echo pathshorten('~/.vim/autoload/myfile.vim', 2) ~/.vi/au/myfile.vim 该路径实际存在与否并不相干。 也可用作 method : GetDirectories()->pathshorten() perleval({expr}) perleval() 在标量上下文计算 Perl 表达式 {expr},返回结果转换为 Vim 数据结 构。如果其值不能转换,返回 Perl 表示的字符串形式。 备注: 如果要数组或哈希表,{expr} 必须返回它们的引用。 例如: :echo perleval('[1 .. 4]') [1, 2, 3, 4] 也可用作 method : GetExpr()->perleval() {仅当编译时加入 +perl 特性才有效} popup_ 函数文档在这里: popup-functions pow({x}, {y}) pow() 返回浮点数,即 {x}{y} 次方。 {x}{y} 的计算结果必须是浮点数或数值。 示例: :echo pow(3, 3) 27.0 :echo pow(2, 16) 65536.0 :echo pow(32, 0.20) 2.0 也可用作 method : Compute()->pow(3) {仅当编译时加入 +float 特性才有效} prevnonblank({lnum}) prevnonblank() 返回第一个 {lnum} 所在或之上的非空白行的行号。例如: let ind = indent(prevnonblank(v:lnum - 1)) 如果 {lnum} 非法或者在该行和它之前都没有非空白行,返回零。 另见 nextnonblank() 。 也可用作 method : GetLnum()->prevnonblank() printf({fmt}, {expr1} ...) printf() 返回 {fmt} 指定的字符串,其中每个 "%" 项目被它们对应的参数排版 后的形式取代。例如: printf("%4d: E%d %.30s", lnum, errno, msg) 可能的返回结果: " 99: E42 asdfasdfasdfasdfasdfasdfasdfas" 也可用作 method ,基是作为第二个参数传递的: Compute()->printf("result: %d") 常用的项目有: %s 字符串 %6S 右对齐到 6 个显示单元的字符串 %6s 右对齐到 6 个字节的字符串 %.9s 截短到 9 个字节的字符串 %c 单个字节 %d 十进制数 %5d 十进制数,用空格补足到 5 个字符 %x 十六进制数 %04x 十六进制数,用 0 补足到 4 个字符 %X 十六进制数,用大写字母的十六进制字母 %o 八进制数 %08b 二进制数,用 0 补足到 8 个字符 %f 浮点数,形如 12.23、inf、-inf 或 nan %F 浮点数,形如 12.23、INF、-INF 或 NAN %e 浮点数,形如 1.23e3、inf、-inf 或 nan %E 浮点数,形如 1.23E3、INF、-INF 或 NAN %g 浮点数,根据不同的值,使用合适的 %f 或 %e %G 浮点数,根据不同的值,使用合适的 %F 或 %E %% % 字符本身 转换规格说明以 '%' 开始,以转换类型结束。所有其它的字符按原样 复制到结果中。 "%" 开始转换规格说明。其后的参数依序如下: % [flags] [field-width] [.precision] type flags 零或多个下面的标志位: # 转换值为 "替换形式"。对 c、d 和 s 转换,此选项无 效。对 o 转换,增加数值的精度,使得输出字符串的 第一个字符总是 0 (除非打印零值,且显式地使用精度 0)。 对 b 和 B 转换,非零值在前面加上字符串 "0b" (B 转换用 "0B")。 对 x 和 X 转换,非零值在前面加上字符串 "0x" (X 转换用 "0X")。 0 (零) 以 0 填充。对所有的转换,左侧用 0 而非空格填充。 如果对数值的转换给出精度 (d、b、B、o、x 和 X), 忽略 0 标志位。 - 负域宽度标志位;转换后的值被左对齐到域边界上。该 值右侧用空格填充,而不是在左侧用空格或 0 填充。 如果两个标志位同时给出,- 否决 0。 ' ' (空格) 带符号转换 (d) 产生的正数左侧加上空格。 + 带符号转换产生的数值之前总加上符号。如果两个标志 位同时给出,+ 否决空格。 field-width 可选的十进制数位字符串,指定最小的字段宽度。如果转换后 的值的字节数小于字段宽度,在左侧 (或右侧,如果给定左对 齐标志位的话) 用空格填充到字段宽度。 .precision 可选的精度,形式为句号 '.' 后跟一个可选的数位字符串。 如果省略了数位字符串,假设精度为零。 它给出 d、o、x 和 X 转换显示的最小数位数量,或 s 转换 显示的字符串的字节的最大数量。 对浮点数而言,指定小数点后的数位个数。 type 指定要进行的转换类型的单个字符,见下。 字段宽度、精度 (两者都有亦可) 可以用星号 '*' 代替数位字符串。 此情形下,一个数值参数指定字段宽度或精度。负的字段宽度被理解为 带左对齐的标志位后跟一个正数字段宽度;负的精度被理解为就像不存 在一样。例如: :echo printf("%d: %.*s", nr, width, line) 限制 "line" 文本的长度为 "width" 个字节。 转换标识符和它们的含义如下: printf-d printf-b printf-B printf-o printf-x printf-X dbBoxX 数值参数被转换为带符号十进制 (d),无符号二进制 (b 和 B)、无符号八进制 (o) 或无符号十六进制 (x 和 X) 记法。x 转换用字母 "abcdef";X 转换用 "ABCDEF" 字母。 如果提供了精度,它给出必须出现的数位的最少数目;如果转 换后的值需要更少的数位,左侧用 0 填充。 任何情况下数值字段都不会被不存在或者更小的字段宽度所截 短;如果转换的结果宽于字段宽度,字段被扩展,以包含转换 后的结果。 'h' 修饰符指示参数为 16 位。 'l' 修饰符指示参数为 32 位。 'L' 修饰符指示参数为 64 位。 通常这些修饰符不怎么有用。如果类型可从参数推知,修饰符 被忽略。 i d 的别名 D ld 的别名 U lu 的别名 O lo 的别名 printf-c c 数值参数被转换为字节,写入产生的字符。 printf-s s 使用字符串参数的文本。如果指定精度,使用不多于给定数目 的字节数。 如果参数不是字符串型,使用 ":echo" 相同的格式自动转换 到文本。 printf-S S 使用字符串参数的文本。如果指定精度,使用不多于给定数目 的显示单元数。 printf-f E807 f F 浮点数参数被转换为形如 123.456 的字符串。精度指定小数 点后面的位数。如果精度为零,则省略小数点本身。如果未指 定精度,缺省为 6。那个很大很大的数 (超出返回或除以零的 结果) 用 %f 显示 "inf" 或 "-inf" (%F 则显示 INF 或 -INF)。 "0.0 / 0.0" 用 %f 显示 "nan" (%F 显示 NAN)。 示例: echo printf("%.2f", 12.115) 12.12 注意 截断方式取决于系统库。如不确定,使用 round() printf-e printf-E e E 浮点数参数被转换为形如 1.234e+03 或用 'E' 的话 1.234E+03 的字符串。精度指定小数点后面的位数,和 'f' 一样。 printf-g printf-G g G 如果浮点数参数在 0.001 (含) 和 10000000.0 (不含) 之 间,则其转换同 'f',不然,'g' 同 'e' 而 'G' 同 'E'。如 果未指定精度,除了小数点之后的那个零以外,不显示多余的 零和 '+' 负号。因而,10000000.0 显示为 1.0e7。 printf-% % 写入 '%'。不转换参数。这里完整的转换规格说明是 "%%"。 如果期待数值参数,字符串参数也被接受并自动转换。 如果期待浮点数或字符串参数,数值参数也被接受并自动转换。 其它参数类型产生错误信息。 E766 E767 {exprN} 参数的数量必须和 "%" 项目的数量完全匹配。不论参数不足 还是过多,都会给出错误。至多可用 18 个参数。 prompt_getprompt({buf}) prompt_getprompt() 返回缓冲区 {buf} 的实际提示文本。{buf} 可以是缓冲区名或号。 prompt-buffer 。 如果缓冲区不存在或不是提示缓冲区,返回空串。 也可用作 method : GetBuffer()->prompt_getprompt() prompt_setcallback({buf}, {expr}) prompt_setcallback() 设置缓冲区 {buf} 的提示回调为 {expr}{expr} 为空串时删除回 调。只对 'buftype' 为 "prompt" 的 {buf} 有效。 按下回车时触发本回调。此时当前缓冲区总是提示缓冲区。在回调触发 前,会加入一行新的提示行,因此,触发该回调的提示行会是倒数第二 行。 如果回调要为缓冲区增加新文本,必须在最后一行之前插入,因为那是 当前提示所在的位置,此操作可以异步进行。 回调调用时所带的一个参数是提示行输入的文本。如果用户直接按了回 车,这会是一个空串。 示例: call prompt_setcallback(bufnr(), function('s:TextEntered')) func s:TextEntered(text) if a:text == 'exit' || a:text == 'quit' stopinsert close else call append(line('$') - 1, 'Entered: "' . a:text . '"') " 复位 'modified',这样缓冲区才可以被关闭。 set nomodified endif endfunc 也可用作 method : GetBuffer()->prompt_setcallback(callback) prompt_setinterrupt({buf}, {expr}) prompt_setinterrupt() 设置缓冲区 {buf} 的回调为 {expr}{expr} 为空串时删除回调。只 对 'buftype' 为 "prompt" 的 {buf} 有效。 插入模式按 CTRL-C 时触发本回调。不设置回调会使 Vim 退出插入模 式,就和其它缓冲区一样。 也可用作 method : GetBuffer()->prompt_setinterrupt(callback) prompt_setprompt({buf}, {text}) prompt_setprompt() 设置缓冲区 {buf} 的提示文本为 {text}{text} 多数会以空格结 尾。 结果只对 'buftype' 为 "prompt" 的 {buf} 可见。示例: call prompt_setprompt(bufnr(), 'command: ') 也可用作 method : GetBuffer()->prompt_setprompt('command: ') prop_ 函数文档在这里: text-prop-functions pum_getpos() pum_getpos() 如果弹出菜单 (见 ins-completion-menu ) 不可见,返回空 Dictionary ,不然,返回带以下键的 Dictionary : height 可见项目数 width 屏幕单元格数 row 顶部屏幕行号 (0 为初行) col 最左侧屏幕列号 (0 为初列) size 项目总数 scrollbar 如果滚动条为可见则为 TRUE 这里的值和 CompleteChanged 发生时 v:event 的一样。 pumvisible() pumvisible() 如果弹出菜单可见,返回非零,不然返回零。见 ins-completion-menu 。 可以用来避免一些会删除弹出菜单的动作。 py3eval({expr}) py3eval() 计算 Python 表达式 {expr} 并返回计算结果,转换为 Vim 本身的数 据结构。 数值和字符串返回本身 (字符串经过复制,Unicode 字符串还须额外用 'encoding' 转换)。 列表返回 Vim List 类型。 字典返回 Vim Dictionary 类型,键值转换为字符串。 也可用作 method : GetExpr()->py3eval() {仅当编译时加入 +python3 特性才有效} E858 E859 pyeval({expr}) pyeval() 计算 Python 表达式 {expr} 并返回计算结果,转换为 Vim 本身的数 据结构。 数值和字符串返回本身 (字符串经过复制)。 列表返回 Vim List 类型。 字典返回 Vim Dictionary 类型,出现非字符串的键值报错。 也可用作 method : GetExpr()->pyeval() {仅当编译时加入 +python 特性才有效} pyxeval({expr}) pyxeval() 计算 Python 表达式 {expr} 并返回计算结果,转换为 Vim 本身的数 据结构。 使用 Python 2 或 3,见 python_x'pyxversion'。 另见: pyeval()py3eval() 也可用作 method : GetExpr()->pyxeval() {仅当编译时加入 +python+python3 特性才有效} E726 E727 range({expr} [, {max} [, {stride}]]) range() 返回数值的 List : - 如果只有指定 {expr}: [0, 1, ..., {expr} - 1] - 如果指定了 {max}: [{expr}, {expr} + 1, ..., {max}] - 如果指定了 {stride}: [{expr}, {expr} + {stride}, ..., {max}] (每次给 {expr} 递增 {stride},但不会产生超过 {max} 的 值)。 如果最大值比开始值小一,返回空列表。如果更小,报错。 例如: range(4) " [0, 1, 2, 3] range(2, 4) " [2, 3, 4] range(2, 9, 3) " [2, 5, 8] range(2, -2, -1) " [2, 1, 0, -1, -2] range(0) " [] range(2, 0) " 出错! 也可用作 method : GetExpr()->range() rand([{expr}]) rand() random {expr} 作为种子,返回 xoshiro128** 算法产生的伪随机数。返回 数值是 32 位的,为了统一起见,即使是 64 位系统上也是。 可由 srand() 初始化 {expr} ,rand() 会进行更新。如果省略 {expr},使用并更新一个内部的种子值。 示例: :echo rand() :let seed = srand() :echo rand(seed) :echo rand(seed) % 16 " 随机数 0 - 15 readblob({fname}) readblob() 以二进制方式读取文件 {fname},并返回 Blob 。 文件不能打开时报错,返回空 Blob 。 另见 readfile()writefile() 。 readdir({directory} [, {expr} [, {dict}]]) readdir() 返回 {directory} 中的文件和目录名的列表。如果不需要复杂的处 理,如限制匹配的数目等等,也可用 glob() 。 列表经过排序 (大小写敏感),要改变排序顺序,见下 {dict} 参数。 {expr} 省略时包含所有的项目。 如果给出 {expr},计算其值决定如何处理: 如果 {expr} 结果为 -1, 不处理后续的项目。 如果 {expr} 结果为 0,不把本项加入列表。 如果 {expr} 结果为 1,把本项加入列表。 总是排除 "." 和 ".." 项目。 每次计算 {expr}v:val 设为项目名。 {expr} 如果是函数,把名字作为参数传递。 例如,要得到 ".txt" 结尾的文件列表: readdir(dirname, {n -> n =~ '.txt$'}) 要跳隐藏和备份文件: readdir(dirname, {n -> n !~ '^\.\|\~$'}) 可选的 {dict} 参数允许更多定制。目前可用于指定排序是否和如何进 行。此字典有以下成员: sort 如何对系统返回值进行排序。 合法值是: "none" 不排序 (最快速的方法) "case" 大小写敏感排序 (按每个字符的字节 值,技术上,使用 strcmp()) (缺省) "icase" 大小写不敏感排序 (技术上,使用 strcasecmp()) "collate" 使用 "POSIX" 或 "C" locale 的排 序规则排序 (技术上,使用 strcoll()) 其它值被忽略,不报错。 例如,要得到当前目录下的所有文件的列表,而不对个别项目排序: readdir('.', '1', #{sort: 'none'}) 要想得到目录树: function! s:tree(dir) return {a:dir : map(readdir(a:dir), \ {_, x -> isdirectory(x) ? \ {x : s:tree(a:dir . '/' . x)} : x})} endfunction echo s:tree(".") 也可用作 method : GetDirName()->readdir() readdirex({directory} [, {expr} [, {dict}]]) readdirex() readdir() 的扩展版。 返回 {directory} 中的文件和目录信息字典的列表。 可用于在读取目录列表的同时获得这些文件和目录的属性。这比先调用 readdir() 然后为每个文件和目录分别调用 getfperm()getfsize()getftime()getftype() 要快得多,尤其是在 MS-Windows 上。 列表缺省按名字排序 (大小写敏感),可选的 {dict} 参数可用来改变 如何排序,见 readdir() 。 文件和目录信息字典包含以下项: group 项目的组名。(仅用于 Unix) name 项目名。 perm 项目权限。见 getfperm() 。 size 项目大小。见 getfsize() 。 time 项目时间戳。见 getftime() 。 type 项目类型。 Unix 上,大致相当于 getftype() ,除了以下例 外: 目录的符号链接 "linkd" 其它符号链接 "link" MS-Windows 上: 普通文件 "file" 目录 "dir" 连接点 "junction" 目录的符号链接 "linkd" 其它符号链接 "link" 其它重解析点 "reparse" user 项目拥有者的名字。(仅用于 Unix) Unix 上,如果项目是符号链接,字典包含链接目标的信息 (除了 "type" 项外)。 MS-Windows 上,由于性能方面的原因,同样情况包含的是符号链接本 身的信息。 {expr} 省略时包含所有的项目。 如果给出 {expr},计算其值决定如何处理: 如果 {expr} 结果为 -1, 不处理后续的项目。 如果 {expr} 结果为 0,不把本项加入列表。 如果 {expr} 结果为 1,把本项加入列表。 总是排除 "." 和 ".." 项目。 每次计算 {expr} 时, v:val 设为对应项目的 Dictionary 。 如果 {expr} 为函数,此项目被作为参数传入。 例如,要获取所有以 ".txt" 结尾的文件列表: readdirex(dirname, {e -> e.name =~ '.txt$'}) 例如,要得到当前目录下的所有文件的列表,而不对个别项目排序: readdirex(dirname, '1', #{sort: 'none'}) 也可用作 method : GetDirName()->readdirex() readfile() readfile({fname} [, {type} [, {max}]]) 读入文件 {fname} 并返回 List 。,文件每行一项。在 NL 字符处断 开行。以 CR 分隔的 Macintosh 文件会返回单个长行 (除非某处出现 了 NL)。 所有的 NUL 字符被 NL 字符替代。 如果 {type} 包含 "b",使用二进制模式: - 如果末行以 NL 结尾,附加额外的一个空列表项。 - 不删除 CR 字符。 否则: - NL 之前的 CR 字符被删除。 - 末行是否以 NL 结尾没有影响。 - 'encoding' 如是 Unicode 编码,删除文本可能有的 UTF-8 字节顺 序标识。 如果给出 {max},指定读入的最大行数。可用于只想检查文件开始十行 这样的场合: :for line in readfile(fname, '', 10) : if line =~ 'Date' | echo line | endif :endfor 如果 {max} 为负,返回从文件尾部起算 -{max} 行,有多少算多少。 如果 {max} 为零,返回空列表。 注意 如果没有 {max},把整个文件读到内存。 也要 注意 这里不识别编码。如果需要,把文件读到缓冲区里。 已废弃 (用 readblob() 代之): 如果 {type} 包含 "B",返回 Blob ,包含未经修改的文件二进制数据。 如果文件不能打开,给出错误信息,并返回空列表。 另见 writefile() 。 也可用作 method : GetFileName()->readfile() reduce({object}, {func} [, {initial}]) reduce() E998 {object} 中的每个项目调用 {func},其中 {object}ListBlob{func} 调用时带两个参数: 目前的结果,和当前项目。处 理完所有项目,返回最终结果。 {initial} 为初始值。如果省略,使用 {object} 的首个项目,而从第 二个项目开始调用 {func}。如果 {initial} 未给出且 {object} 为 空,则结果不能进行计算,报错 E998。 示例: echo reduce([1, 3, 5], { acc, val -> acc + val }) echo reduce(['x', 'y'], { acc, val -> acc .. val }, 'a') echo reduce(0z1122, { acc, val -> 2 * acc + val }) 也可用作 method : echo mylist->reduce({ acc, val -> acc + val }, 0) reg_executing() reg_executing() 返回在执行中的单个字母寄存器名。如果没有在执行的寄存器,返回空 串。见 @ 。 reg_recording() reg_recording() 返回在记录中的单个字母寄存器名。如果没有在记录的寄存器,返回空 串。见 q 。 reltime([{start} [, {end}]]) reltime() 返回代表时间值的项目。此项目为项目列表,成员项目取决于不同的系 统。Vim 9 脚本中其类型可用 list<any>。 可以把此项目传递给 reltimestr() 以转换为字符串,或 reltimefloat() 以转换为浮点数。 没有参数时,返回当前时间。 带一个参数时,返回参数指定的时间以来的时间。 带两个参数时,返回 {start}{end} 之间跨越的时间。 {start}{end} 参数必须是 reltime() 返回的值。 也可用作 method : GetStart()->reltime() {仅当编译时加入 +reltime 特性才有效} reltimefloat({time}) reltimefloat() 返回代表 {time} 的时间值的浮点数。 示例: let start = reltime() call MyFunction() let seconds = reltimefloat(reltime(start)) 参见 reltimestr() 关于开销的注释。 另见 profiling 。 也可用作 method : reltime(start)->reltimefloat() {仅当编译时加入 +reltime 特性才有效} reltimestr({time}) reltimestr() 返回字符串,代表 {time} 的时间值。 形式是秒数、句号和毫秒数。例如: let start = reltime() call MyFunction() echo reltimestr(reltime(start)) 注意 命令本身额外的开销也计算在时间里。时间的准确度取决于系 统。 返回结果包含引导的空格,使字符串能很好地对齐。如果你不需要,用 split() 可以删掉。 echo split(reltimestr(reltime(start)))[0] 另见 profiling 。 也可用作 method : reltime(start)->reltimestr() {仅当编译时加入 +reltime 特性才有效} remote_expr() E449 remote_expr({server}, {string} [, {idvar} [, {timeout}]]) 发送 {string}{server}。该发送的字符串是一个表达式,而返回 的是远端执行的结果。这个结果必然是字符串或 ListList 被转 换成字符串,转换方法是把项目用换行符连接起来 (末项之后没有), 就像用 join(expr, "\n") 那样。 如果给出 {idvar} 且非空,将 {serverid} 保存在以它命令的变量 里,此后的 remote_read() 需要使用此值。 如果给出 {timeout},在给定的秒数后读取超时。否则,使用 600 秒 超时。 另见 clientserver RemoteReply 。 该函数在沙盘里不可用 sandbox{仅当编译时加入 +clientserver 特性才有效} 注意: 任何错误会在本地产生错误信息,但返回的结果只是一个空字符 串。 在全局命名空间中计算变量,而和当前激活的函数无关。调试模式例 外,此时会计算局部于函数的变量和参数。 例如: :echo remote_expr("gvim", "2+2") :echo remote_expr("gvim1", "b:current_syntax") 也可用作 method : ServerName()->remote_expr(expr) remote_foreground({server}) remote_foreground() 把名为 {server} 的 Vim 服务器带到前台。 这类似于: remote_expr({server}, "foreground()") Win32 系统除外。那里,客户端完成实际的工作。因为操作系统不 总能允许服务器把自己带到前台。 注意: 如果窗口最小化,并不恢复之,foreground() 会这么做。 该函数在沙盘里不可用 sandbox 。 也可用作 method : ServerName()->remote_foreground() {仅可用在 Win32、Athena、Motif 和 GTK 的 GUI 版本和 Win32 的控 制台版本} remote_peek({serverid} [, {retvar}]) remote_peek() 如果 {serverid} 有可用的字符串,返回正数。如果指定了 {retvar},复制任何应答字符串到 {retvar} 指定的变量。{retvar} 必须是一个用来指定变量名的字符串。 如果没有可用的应答,返回 0。 如果出错,返回 -1。 另见 clientserver 。 该函数在沙盘里不可用 sandbox{仅当编译时加入 +clientserver 特性才有效} 示例: :let repl = "" :echo "PEEK: ".remote_peek(id, "repl").": ".repl 也可用作 method : ServerId()->remote_peek() remote_read({serverid}, [{timeout}]) remote_read() 返回从 {serverid} 发送的存在时间最长的应答,并删除之。除非给出 以秒计的 {timeout},该调用会等待直到有应答为止。 另见 clientserver 。 该函数在沙盘里不可用 sandbox{仅当编译时加入 +clientserver 特性才有效} 例如: :echo remote_read(id) 也可用作 method : ServerId()->remote_read() remote_send() E241 remote_send({server}, {string} [, {idvar}]) 发送 {string}{server}。发送的字符串是输入键的序列。函数立 即返回。Vim 的服务器端不对键进行映射 :map 。 如果给出 {idvar},将 {serverid} 保存在以它命令的变量里,此后的 remote_read() 需要使用此值。 另见 clientserver RemoteReply 。 该函数在沙盘里不可用 sandbox{仅当编译时加入 +clientserver 特性才有效} 注意: 任何错误会在服务器端报告,从而影响那里的显示。 例如: :echo remote_send("gvim", ":DropAndReply ".file, "serverid"). \ remote_read(serverid) :autocmd NONE RemoteReply * \ echo remote_read(expand("<amatch>")) :echo remote_send("gvim", ":sleep 10 | echo ". \ 'server2client(expand("<client>"), "HELLO")<CR>') 也可用作 method : ServerName()->remote_send(keys) remote_startserver() E941 E942 remote_startserver({name}) 成为服务器 {name}。如果已作为服务器运行,也即 v:servername 不为空时此操作失败。 也可用作 method : ServerName()->remote_startserver() {仅当编译时加入 +clientserver 特性才有效} remove({list}, {idx} [, {end}]) remove() 没有 {end}: 删除 List {list} 里索引为 {idx} 的项目并返回之。 有 {end}: 删除从 {idx}{end} (闭区间) 的项目,并返回这些项 目的 List 。如果 {idx} 指向和 {end} 相同的项目,返回单个项目 的列表。如果 {end} 指向 {idx} 之前的项目,报错。 list-index 说明 {idx}{end} 可能的取值。 例如: :echo "last item: " . remove(mylist, -1) :call remove(mylist, 0, 9)delete() 来删除文件。 也可用作 method : mylist->remove(idx) remove({blob}, {idx} [, {end}]) 没有 {end}: 删除 Blob {blob} 里索引为 {idx} 的字节并返回之。 有 {end}: 删除从 {idx}{end} (闭区间) 的字节,并返回这些字 节构成的的 Blob 。如果 {idx} 指向和 {end} 相同的字节,返回单 个字节构成的 Blob 。如果 {end} 指向 {idx} 之前的字节,报错。 示例: :echo "last byte: " . remove(myblob, -1) :call remove(mylist, 0, 9) remove({dict}, {key}) 删除 {dict} 里键为 {key} 的项目并返回其值。例如: :echo "removed " . remove(dict, "one") 如果 {dict} 里没有键 {key},报错。 rename({from}, {to}) rename() 把文件名 {from} 换成 {to}。这也可用来在文件系统间移动文件。返 回数值,如果文件成功换名,返回零,如果换名失败,返回非零。 注意 如果 {to} 已存在,它被覆盖且没有提示。 该函数在沙盘里不可用 sandbox 。 也可用作 method : GetOldName()->rename(newname) repeat({expr}, {count}) repeat() 重复 {expr} {count} 次,并返回连接后的结果。例如: :let separator = repeat('-', 80) 如果 {count} 为零或负,返回空。 如果 {expr}List 类型,返回连接 {expr} {count} 次的结果。 例如: :let longlist = repeat(['a', 'b'], 3) 返回 ['a', 'b', 'a', 'b', 'a', 'b']。 也可用作 method : mylist->repeat(count) resolve({filename}) resolve() E655 在 MS-Windows 上,如果 {filename} 是一个快捷方式 (.lnk 文件), 返回简化的快捷方式指向的路径。当 {filename} 为符号链接或连接点 (junction point) 时,返回目的地的完整路径。如果该连接 (junction) 的目的地已被删除,返回 {filename}。 在 Unix 上,反复分析 {filename} 的所有路径部分的符号链接的真正 路径,直到返回最简化的结果为止。为了处理循环链接的问题,符号链 接的分析在 100 次叠代之后停止。 在其它系统上,返回简化了的 {filename}。 简化的工作通过 simplify() 完成。 resolve() 保留指向当前目录的首个路径部分 (保证结果仍然是相对路 径名),也保留出现在尾部的路径分隔符。 也可用作 method : GetName()->resolve() reverse({object}) reverse() 反转 {object} 项目的顺序,直接对 {object} 进行原位修改。 {object} 可以是 ListBlob 。 返回 {object}。 如果你不想修改,先构建一个备份: :let revlist = reverse(copy(mylist)) 也可用作 method : mylist->reverse() round({expr}) round() 返回浮点数,即最接近于 {expr} 的整数。如果 {expr} 在两个整数的 正中间,使用 (译者注: 绝对值) 较大 (远离零的) 那个。 {expr} 的计算结果必须是浮点数或数值。 示例: echo round(0.456) 0.0 echo round(4.5) 5.0 echo round(-4.5) -5.0 也可用作 method : Compute()->round() {仅当编译时加入 +float 特性才有效} rubyeval({expr}) rubyeval() 计算 Ruby 表达式 {expr} 并返回计算结果,转换为 Vim 本身的数 据结构。 数值、浮点数和字符串返回本身 (字符串经过复制)。 数值返回 Vim List 类型。 哈希表返回 Vim Dictionary 类型。 其它对象返回它们 "Object#to_s" 方法返回的字符串。 也可用作 method : GetRubyExpr()->rubyeval() {仅当编译时加入 +ruby 特性才有效} screenattr({row}, {col}) screenattr() 类似于 screenchar() ,但返回属性。是个相当任意的值,只可用于 和其他位置的属性进行比较。 也可用作 method : GetRow()->screenattr(col) screenchar({row}, {col}) screenchar() 返回数值,即屏幕 [row, col] 位置的字符。可用于任何可能的屏幕 位置,包括状态行,窗口分隔符和命令行。左上位置的行列号都为一。 返回字符不包括组合字符。双字节编码可能只返回第一个字节。 主要用于调试。 行号或列号越界时返回 -1。 也可用作 method : GetRow()->screenchar(col) screenchars({row}, {col}) screenchars() 返回数值 List 。第一个数值和 screenchar() 返回的相同。其后 的数值是附加于基础字符之上的组合字符。 主要用于测试。 如果 row 或 col 超出范围返回空列表。 也可用作 method : GetRow()->screenchars(col) screencol() screencol() 返回数值,即当前光标的屏幕列号。最左列的列号为 1。 主要用于调试。 注意: 总是返回当前屏幕列,所以直接用于命令 (例如 ":echo screencol()") 时会返回命令行内的列号,其在命令执行时永远为 1。 要得到文件中的光标位置,可用下面这些映射: nnoremap <expr> GG ":echom ".screencol()."\n" nnoremap GG <Cmd>echom screencol()<CR> screenpos({winid}, {lnum}, {col}) screenpos() 返回字典,窗口 {winid} 在缓冲区行 {lnum} 和列 {col} 上的文本字 符的屏幕位置。{col} 是从一开始的字节索引。 字典有以下成员: row 屏幕行 col 首个屏幕列 endcol 末尾屏幕列 curscol 光标所在屏幕列 如果指定位置不可见,所有的值均为零。 当字符占据多于一个屏幕单元格时,"endcol" 和 "col" 的值会不同。 例如制表符的 "col" 可能是 1 而 "eolcol" 会是 8。 "curscol" 值是光标会放置的地方。对于制表符而言会和 "endcol" 相 同。而对双宽字符来说,就会为 "col" 相同。 也可用作 method : GetWinid()->screenpos(lnum, col) screenrow() screenrow() 返回数值,即当前光标的屏幕行号。最顶行的行号为 1。 主要用于调试。 代为替代,也可用 winline()注意: 和 screencol() 的限制相同。 screenstring({row}, {col}) screenstring() 返回字符串,包含在屏幕位置 [row, col] 上的基本字符和任何组合字 符。类似于 screenchars() ,但返回字符组成的字符串。 主要用于测试。 如果行或列超出范围,返回空串。 也可用作 method : GetRow()->screenstring(col) *search()* search({pattern} [, {flags} [, {stopline} [, {timeout} [, {skip}]]]]) 搜索正规表达式模式 {pattern}。搜索从光标位置 (用 cursor() 可 以得到) 开始。 如果找到了匹配,返回其所在的行号。 如果找不到匹配,返回 0 并且光标位置不改变。不会给出错误信息。 {flags} 是字符串,可以包含以下字符标志位: 'b' 反向 (Backward) 搜索,而不是正向搜索 'c' 接受光标 (Cursor) 位置上的匹配 'e' 移到匹配的尾部 (End) 'n' 不 (Not) 移动光标 'p' 返回匹配的子模式 (Pattern) 号 (见下) 's' 在光标上次的位置上设置 (Set) ' 位置标记 'w' 在文件尾部处回绕 (Wrap) 到文件开始处 'W' 不在文件尾部处回绕 (Wrap) 'z' 从光标列开始搜索而不是第零 (Zero) 列 如果 'w' 和 'W' 都没有给出,根据 'wrapscan' 选项决定。 如果提供 's' 标志位,只有在光标移动的时候才设置 ' 位置标记。 's' 标志位不能和 'n' 标志位一起使用。 适用 'ignorecase''smartcase''magic' 标志位。 如果没给出 'z' 标志位,前向搜索总是从第零列开始,然后跳过光标 之前的匹配。如果 'cpo' 中有 'c' 标志位,下次搜索从匹配之后的位 置开始。没有 'c' 标志位则下次搜索从光标后一列开始。这对有重叠 的匹配会有关系。 反向搜索给出 'z' 标志位时,搜索从第零列开始,所以不会找到当前 行的任何匹配 (除非从文件尾回绕)。 如果给出 {stopline} 参数,搜索在搜索完该行后结束。可用于限制搜 索在给出的行范围内。例如: let match = search('(', 'b', line("w0")) let end = search('END', '', line("w$")) 如果使用了 {stopline} 且非零,隐含意味着搜索不会在文件尾回绕。 零就相当于没给出该参数。 如果给出 {timeout} 参数,搜索在超过给出的毫秒数后中止。这样, 如果 {timeout} 为 500,搜索在半秒钟后中止。该值不能为负。 零就相当于没给出该参数。 {仅当在编译时加入 +reltime 特性才有效} 如果给出 {skip} 表达式,对匹配开始处的光标位置进行计算。如果计 算结果非零,跳过此匹配。可用于,比如说,跳过注释或字符串内部的 匹配。 {skip} 可以是作为表达式计算的字符串、函数引用或匿名函数。 {skip} 省略或为空时,接受所有匹配。 计算 {skip} 时如果出错,中断搜索并返回 -1。 search()-sub-match 如果有 'p' 标志位,返回值比第一个匹配的 \(\) 里的子模式的编号 多一。如果所有子模式都不匹配但整个模式匹配,返回一。 要得到列号,使用 searchpos() 。 光标定位在匹配的文本上,除非使用了 'n' 标志位。 示例 (遍历参数列表里的所有文件): :let n = 1 :while n <= argc() " 循环遍历参数列表的每个文件 : exe "argument " . n : " 从文件最后一个字符开始并回绕,这样第一个搜索可以找到 : " 文件开始的匹配 : normal G$ : let flags = "w" : while search("foo", flags) > 0 : s/foo/bar/g : let flags = "W" : endwhile : update " 如果修改过,写入文件 : let n = n + 1 :endwhile 使用一些标志位的示例: :echo search('\<if\|\(else\)\|\(endif\)', 'ncpe') 这会在光标之下或之后寻找关键字 "if"、"else" 和 "endif"。因为有 'p' 标志位,会根据找到的是哪 个关键字返回 1、2 或 3,如果找不 到会返回 0。如果光标在行的第一个单词上: if (foo == 0) | let foo = foo + 1 | endif 此函数返回 1。没有 'c' 标志位的话,函数会找到 "endif" 并返回 3。如果没有 'e' 标志位且光标在 "if" 的 "f" 上也会同样如此。'n' 标志位告诉函数不移动光标。 也可用作 method : GetPattern()->search() searchcount([{options}]) searchcount() 获取或更新最近搜索计数,就像不带 "S" 标志位的 'shoftmess' 所显 示的那样。即便 'shortmess' 包含 "S" 标志位,此函数同样适用。 返回 Dictionary 。如果没有设置前次模式且未指定 "pattern",此 字典为空。 键 类型 意义 current Number 匹配的当前位置; 0 如果光标位置在首个匹配之前 exact_match Boolean 1 如果 "current" 在 "pos" 上匹 配,否则为 0 total Number 找到的匹配总数 incomplete Number 0: 搜索全部完成 1: 重计算超时 2: 超过最大计数 {options} 见下。 要取得最近一次按下 nN 时的搜索计数,调用此函数,并带上 `recompute: 0`。有时,因为 nN 的最大计数为 99,这会返 回错误的信息。如果超过 99,结果必是最大计数 + 1 (100)。如果要 得到正确的信息,指定 `recompute: 1`: " result == 最大计数 + 1 (100) 如果有很多匹配 let result = searchcount(#{recompute: 0}) " 以下则返回正确结果 (recompute 缺省为 1) let result = searchcount() 此函数可用于给 statusline 加入计数: function! LastSearchCount() abort let result = searchcount(#{recompute: 0}) if empty(result) return '' endif if result.incomplete ==# 1 " 超时 return printf(' /%s [?/??]', @/) elseif result.incomplete ==# 2 " 超过最大计数 if result.total > result.maxcount && \ result.current > result.maxcount return printf(' /%s [>%d/>%d]', @/, \ result.current, result.total) elseif result.total > result.maxcount return printf(' /%s [%d/>%d]', @/, \ result.current, result.total) endif endif return printf(' /%s [%d/%d]', @/, \ result.current, result.total) endfunction let &statusline .= '%{LastSearchCount()}' " 如果只想打开 'hlsearch' 时显示计数,也可以如此 " let &statusline .= " \ '%{v:hlsearch ? LastSearchCount() : ""}' 也可以更新搜索计数,可用于 CursorMovedCursorMovedI 自 动命令: autocmd CursorMoved,CursorMovedI * \ let s:searchcount_timer = timer_start( \ 200, function('s:update_searchcount')) function! s:update_searchcount(timer) abort if a:timer ==# s:searchcount_timer call searchcount(#{ \ recompute: 1, maxcount: 0, timeout: 100}) redrawstatus endif endfunction 也可用 "pattern" 来统计在当前缓冲区里匹配指定模式的文本数目: " 统计此缓冲区中的 '\<foo\>' 数 " (注意 这也会更新搜索计数) let result = searchcount(#{pattern: '\<foo\>'}) " 要恢复旧模式的旧搜索计数,可再次搜索 call searchcount() {options} 必须为 Dictionary 。可包含: 键 类型 含义 recompute Boolean 如果为 TRUE ,就像执行了 nN 那样重新计算计数。 否则,返回最近的计算结果 (当执 行了 nN 假定 'shortmess' 里没有 "S",此函数 执行时有同样效果)。 (缺省: TRUE ) pattern String 就像给出和 @/ 不同的模式那样 重新计算。 和在调用此函数前执行以下命令的 效果相同 let @/ = pattern (缺省: @/ ) timeout Number 0 或负数代表无超时。 以毫秒计的对结果重计算的超时 (缺省: 0) maxcount Number 0 或负数代表无限制。对结果重计 算时匹配文本的最大计数。如果搜 索超过总数,"total" 值成为 `maxcount + 1` (缺省: 99) pos List 重计算结果时的 `[lnum, col, off]` 值。 这会改变 "current" 返回值。见 cursor()getpos() (缺省: 光标所在位置) searchdecl({name} [, {global} [, {thisblock}]]) searchdecl() 搜索 {name} 的声明。 如果 {global} 参数非零,使用 gD 的工作方式,寻找文件的第一个 匹配。否则使用 gd 的工作方式,寻找函数里的第一个匹配。 如果 {thisblock} 参数非零,忽略光标位置前结束的 {} 块里的匹 配。可以避免只有在别的作用域里才有效的变量声明。 移动光标到找到的匹配上。 返回零代表成功,非零代表失败。 例如: if searchdecl('myvar') == 0 echo getline('.') endif 也可用作 method : GetName()->searchdecl() searchpair() searchpair({start}, {middle}, {end} [, {flags} [, {skip} [, {stopline} [, {timeout}]]]]) 搜索嵌套的 start-end 组对的匹配。这可以用来查找匹配 "if" 的 "endif"。在这里面的其它的 if/endif 组对被忽略。搜索从光标开 始。缺省正向搜索,在 {flags} 里包含 'b' 的时候反向搜索。 如果找到一个匹配,光标移动到那里并返回行号。如果没有匹配, 返回 0 或者 -1,光标不移动。不会给出错误信息。 {start}{middle}{end} 都是模式,见 pattern 。它们不能包 含 \( \) 对,但可以使用 \%( \)。如果 {middle} 非空,在相应的方 向试图寻找它 (如果找到,停留在哪里),但在嵌套的 start-end 组对 里面的不算。一个典型的应用是: searchpair('\<if\>', '\<else\>', '\<endif\>') 如果 {middle} 为空,跳过 "else"。 {flags} 'b'、'c'、'n'、's'、'w' 和 'W' 的使用方式和 search() 类似。此外,还可用: 'r' 重复 (Repeat) 直到没有更多匹配位置;会找到最外层的组 对。隐含 'W' 标志位。 'm' 返回匹配 (Match) 的数目而不是匹配的行号;使用 'r' 时会 > 1。 备注: 最好使用 'W' 标志位,避免在文件尾回绕。 如果找到 {start}{middle}{end} 的匹配,计算 {skip} 表达 式,此时假定光标定位在匹配的开始处。如果返回零,该匹配被跳过。 比如,可能是出现在注释里的匹配。 如果 {skip} 不提供或者为空,接受每一个匹配。如果计算 {skip} 时 出现错误,搜索被中止,并返回 -1。 {skip} 可以是字符串、匿名函数、函数引用或偏函数。其它类型会报 错。 {stopline}{timeout}search() 。 使用 'ignorecase' 的值。忽略 'magic',使用模式时假设它总是置位 的。 搜索从准确的光标处开始。根据搜索方向,寻找从下一个字符开始的 {start}{middle}{end}。比如: if 1 if 2 endif 2 endif 1 如果从 "if 2" 开始且光标在 "i" 上并正向搜索,找到的是 "endif 2"。如果刚好在 "if 2" 之前开始,找到的是 "endif 1"。因 为先找到的了 "if 2",而它被认为是嵌套的 if/endif,以 "if 2" 开始,以 "endif 2" 结束。 如果反向搜索且 {end} 多于一个字符,在模式的最后加上 "\zs" 可能 有用,这样光标在 end 匹配的中间某位置的时候,仍然可以找到匹配 的 start 匹配。 例如,要找到 Vim 脚本里的 "endif" 命令: :echo searchpair('\<if\>', '\<el\%[seif]\>', '\<en\%[dif]\>', 'W', \ 'getline(".") =~ "^\\s*\""') 光标必须在要寻找匹配的 "if" 之上或之后。注意 单引号字符串的使 用,它避免了反斜杠的麻烦。skip 表达式只用来发现行首的注释,命 令之后的不行。另外,一行中间的单词 "en" 或 "if" 也被认为是匹 配。 另一个例子,搜索匹配 "}" 的 "{": :echo searchpair('{', '', '}', 'bW') 只需要光标在需要匹配的 "}" 之上或之前就可以了。要拒绝语法高亮 识别为字符串的匹配: :echo searchpair('{', '', '}', 'bW', \ 'synIDattr(synID(line("."), col("."), 0), "name") =~? "string"') searchpairpos() searchpairpos({start}, {middle}, {end} [, {flags} [, {skip} [, {stopline} [, {timeout}]]]]) 和 searchpair() 相同,但返回 List ,包含匹配的行号和列号。 List 的第一个元素是行号,而第二个元素是匹配所在的列位置的字 节位置。如果没有匹配,返回 [0, 0]。 :let [lnum,col] = searchpairpos('{', '', '}', 'n') match-parens 提供一个更复杂更有用的例子。 searchpos() searchpos({pattern} [, {flags} [, {stopline} [, {timeout} [, {skip}]]]]) 和 search() 相同,但返回 List ,包含匹配的行号和列号。 List 的第一个元素是行号,而第二个元素是匹配所在的列位置的字 节位置。如果没有匹配,返回 [0, 0]。 例如: :let [lnum, col] = searchpos('mypattern', 'n') 如果给出 'p' 标志位,返回值里有一个附加项目,包含匹配的子模式 号 search()-sub-match 。例如: :let [lnum, col, submatch] = searchpos('\(\l\)\|\(\u\)', 'np') 此例中如果找到小写字母 /\l "submatch" 为 2,如果找到大写字母 /\u 则为 3。 也可用作 method : GetPattern()->searchpos() server2client({clientid}, {string}) server2client() 发送应答字符串到 {clientid}。最近刚发送过字符串的 {clientid} 可以通过 expand("<client>") 得到。 {仅当在编译时加入 +clientserver 特性才有效} 返回零代表成功,-1 代表失败。 备注: 该 id 应在接受下一个命令前保存。也就是,在接收命令返回之前 (译 者注: 似应为 "之后") 和任何等待输入的命令之前。 另见 clientserver 。 示例: :echo server2client(expand("<client>"), "HELLO") 也可用作 method : GetClientId()->server2client(string) serverlist() serverlist() 返回可用的服务器名字列表,每行一个。如果没有服务器或者该信息 无法得到,返回空字符串。另见 clientserver{仅当编译时加入 +clientserver 特性才有效} 示例: :echo serverlist() setbufline({expr}, {lnum}, {text}) setbufline() 设置缓冲区 {expr} 的第 {lnum} 行为 {text}。相当于为指定缓冲区 调用 setline() 。 此函数只能用于已载入的缓冲区。有必要的话先调用 bufload() 。 要插入行可用 appendbufline() 。 清除 {lnum} 中的任何文本属性。 {text} 可以是字符串,用来设置单行文本,也可以是字符串列表,用 来设置多行文本。如果列表范围超出末行之下,则添加额外的行。 {expr} 的用法可见上述 bufname(){lnum} 的用法类似于 setline() 。 如果 {lnum} 正好在末行之下,在末行之下添加 {text}。 如果 {expr} 不是合法缓冲区、缓冲区未载入、或 {lnum} 不合法,返 回 1。成功时返回 0。 也可用作 method ,基是作为第三个参数传递的: GetText()->setbufline(buf, lnum) setbufvar({expr}, {varname}, {val}) setbufvar() 设置缓冲区 {expr} 的选项或局部变量 {varname} 的值为 {val}。 也可用于全局或者局部于窗口的选项,但不能用于全局或者局部于窗口 的变量。 如果设置局部于窗口的选项,全局值不会改变。 {expr} 的使用方式见上 bufname()注意必须使用不带 "b:" 的变量名。 示例: :call setbufvar(1, "&mod", 1) :call setbufvar("todo", "myvar", "foobar") 该命令在沙盘里不可用 sandbox 。 也可用作 method ,基是作为第三个参数传递的: GetValue()->setbufvar(buf, varname) setcellwidths({list}) setcellwidths() 指定字符范围的单元宽度覆盖。用于告知 Vim 字符以屏幕单元计的宽 度。此设置超越 'ambiwidth'。示例: setcellwidths([[0xad, 0xad, 1], \ [0x2194, 0x2199, 2]]) E1109 E1110 E1111 E1112 E1113 {list} 参数为三个数值组成的列表的列表。这三个数值为 [low, high, width]。"low" 和 "high" 可以相同,代表单个字符。否则,它 们指定从 "low" 到 "high" (闭区间) 的字符范围。"width" 可为 1 或 2,指定以屏幕单元计的字符宽度。 如果参数不合法或范围相互有重叠,报错。 只能指定值为 0x100 和更高的字符。 要清除覆盖,传递空列表: setcellwidths([]); 可用 $VIMRUNTIME/tools/emoji_list.vim 脚本来查看已知表情字符的 效果。 setcharpos({expr}, {list}) setcharpos() setpos() ,但使用指定列号作为行内字符索引,而不是字节索 引。 示例: 在第 8 行的文本 "여보세요" 上: call setcharpos('.', [0, 8, 4, 0]) 定位光标在第四个字符 '요' 上。 call setpos('.', [0, 8, 4, 0]) 定位光标在第二个字符 '보' 上。 也可用作 method : GetPosition()->setcharpos('.') setcharsearch({dict}) setcharsearch() {dict} 设置当前字符搜索信息,带有以下项目: char 下次 ,; 命令使用的字符;空字符串清除字 符搜索 forward 字符搜索的方向;1 为正向,0 为反向 until 字符搜索的类型;1 为 tT 字符搜索,0 为 fF 字符搜索 可用于在脚本中保存/恢复用户的字符搜索: :let prevsearch = getcharsearch() :" 执行改写用户搜索的命令 :call setcharsearch(prevsearch) 另见 getcharsearch() 。 也可用作 method : SavedSearch()->setcharsearch() setcmdpos({pos}) setcmdpos() 设置命令行的光标位置到字节位置 {pos}。第一个位置为 1。 用 getcmdpos() 得到当前的位置。 只有在编辑命令行时有效,所以必须在 c_CTRL-\_ec_CTRL-R_= 或带 '=' 的 c_CTRL-R_CTRL-R 里使用。对于 c_CTRL-\_e 和带 '=' 的 c_CTRL-R_CTRL-R ,在命令行设为表达式的内容之后才设置位 置。对于 c_CTRL-R_= ,在计算表达式之后但在插入返回的文本之前 设置位置。 如果数值太大,光标放在行尾。如果小于 1,结果没有定义。 如果成功,返回 FALSE,如果不在编辑命令行,返回 TRUE。 也可用作 method : GetPos()->setcmdpos() setcursorcharpos({lnum}, {col} [, {off}]) setcursorcharpos() setcursorcharpos({list}) 同 cursor() ,但使用指定列号作为行内的字符索引,而不是字节索 引。 示例: 在第 4 行的文本 "여보세요" 上: call setcursorcharpos(4, 3) 定位光标在第三个字符 '세' 上。 call cursor(4, 3) 定位光标在第一个字符 '여' 上。 也可用作 method : GetCursorPos()->setcursorcharpos() setenv({name}, {val}) setenv() 设置环境变量 {name} 值为 {val}。 如果 {val}v:null ,删除该环境变量。 另见 expr-env 。 也可用作 method ,基是作为第二个参数传递的: GetPath()->setenv('PATH') setfperm({fname}, {mode}) setfperm() chmod 设置 {fname} 的文件权限为 {mode}{mode} 必须是 9 个字符的字符串。形如 "rwxrwxrwx",每组 "rwx" 标志位代表着,按次序,文件拥有者、文件所属组和其他用户的权限。 '-' 字符代表关闭权限,其他字符代表打开。不支持多字节字符。 例如 "rw-r-----" 意味着用户可读写,组只读,其他不可访问。 "xx-x-----" 作用相同。 返回非零代表成功,零代表失败。 也可用作 method : GetFilename()->setfperm(mode) 要读取权限可见 getfperm() 。 setline({lnum}, {text}) setline() 设置当前缓冲区第 {lnum} 行的内容为 {text}。要插入新行,用 append() 。要设置其它缓冲区的行,可用 setbufline() 。清除 {lnum} 中的任何文本属性。 {lnum} 的用法同 getline() 。 如果 {lnum} 正好在末行之下,在末行之下添加 {text}{text} 可以是任何类型或任何类型的列表,每个项目会被转换为字符 串。 如果成功,返回 FALSE。如果失败 (多数是因为 {lnum} 不合法) 返回 TRUE。 例如: :call setline(5, strftime("%c")) 如果 {text}List ,那么第 {lnum} 行和其后的行被设为列表里 的项目。例如: :call setline(5, ['aaa', 'bbb', 'ccc']) 等价于: :for [n, l] in [[5, 'aaa'], [6, 'bbb'], [7, 'ccc']] : call setline(n, l) :endfor 注意: 这里不会设置 '[ 和 '] 位置标记。 也可用作 method ,基是作为第二个参数传递的: GetText()->setline(lnum) setloclist({nr}, {list} [, {action} [, {what}]]) setloclist() 创建或替代或加入到窗口 {nr} 的位置列表。 {nr} 可以是窗口号或 window-ID 。 如果 {nr} 为零,使用当前窗口。 如果是位置列表窗口,修改所显示的位置列表。如果窗口号 {nr} 非 法,返回 -1。 其它同 setqflist() 。 另见 location-list 。 关于 {action},可见 setqflist-action 。 如果给出可选的 {what} 字典参数,只设置 {what} 中列出的项目。 关于 {what} 支持的键值的列表,参见 setqflist() 。 setmatches({list} [, {win}]) setmatches() 恢复 getmatches() 为当前窗口保存的匹配列表。如果成功,返回 0,否则返回 -1。原有的所有匹配都被清除。示例见 getmatches() 。 如果给出 {win},使用带此窗口号或窗口 ID 的窗口而不是当前窗口。 也可用作 method : GetMatches()->setmatches() setpos() setpos({expr}, {list}) 设置 {expr} 的位置。可能的值: . 光标 'x 位置标记 x {list} 必须是带四个或五个数值的 List : [bufnum, lnum, col, off] [bufnum, lnum, col, off, curswant] "bufnum" 是缓冲区号。零代表当前缓冲区。如果设置大写位置标记, "bufnum" 是位置标记位置的一部分。对其它的位置标记,它用于指定 设置位置标记的缓冲区。可以用 bufnr() 函数把文件名转化为缓冲 区号。 设置光标和 ' 位置标记时忽略 "bufnum",因为它们和窗口相关,而不 是缓冲区相关。 不修改跳转表。 "lnum" 和 "col" 是缓冲区里的位置。第一列为 1。"lnum" 为零则删 除位置标记。"col" 如小于 1,则以 1 代替。要使用字符计数而不是 字节计数,用 setcharpos() 。 除非使用了 'virtualedit',不用 "off" 值。这是从对应字符开始位 置以屏幕列计的位移。例如,在制表之中或最后一个字符之后的某个位 置。 "curswant" 值只用于设置光标位置。它指定垂直移动光标时的首选 列。如果没有 "curswants" 值,不设置首选列。如果有但用于设置位 置标记时,也没有效果。 注意对 '< 和 '> 而言,改变行号可能会使两者在实际中被调换,以保 证 '< 总是在 '> 之前。 如果位置可以设置,返回 0,否则返回 -1。如果 {expr} 不合法,报 错。 另见 setcharpos()getpos()getcurpos() 。 这并不能恢复垂直移动使用的列;如果用它设置了光标位置, jk 动作会跳转到上次的列上! cursor() 也可设置首选列。另见 winrestview() 的 "curswant" 键。 也可用作 method : GetPosition()->setpos('.') setqflist({list} [, {action} [, {what}]]) setqflist() 创建或替代或加入到快速修复表。 如果提供了可选的 {what} 字典参数,只设置 {what} 列出的项目,忽 略首个参数 {list}{what} 支持的项目见下。 setqflist-what 如果不给出 {what},使用 {list} 里的项目。每个 {list} 项目是一 个字典。{list} 里非字典的项目被忽略。每个字典项目可以包含以下 的项目: bufnr 缓冲区号;必须为某个合法缓冲区的编号 filename 文件名;仅当 "bufnr" 不存在或者不合法时才使用 module 模块名;如果给出,在快速修复错误窗口用它而不是 文件名 lnum 缓冲区里的行号 pattern 用于定位错误的模式 col 列号 vcol 非零: "col" 是可视列 零: "col" 是字节位置 nr 错误号 text 错误描述 type 错误类型,'E'、'W' 等。 valid 经过识别的错误信息 "col"、"vcol"、"nr"、"type" 和 "text" 项目是可选的。"lnum" 或 "pattern" 项目用来定位匹配的错误行。 如果 "filename" 和 "bufnr" 项目都不存在或者 "lnum" 和 "pattern" 项目都不存在,那么此项目不被当作错误行处理。 如果 "pattern" 和 "lnum" 都存在,使用 "pattern"。 如果不提供 "valid" 项目,则在 "bufnr" 为合法的缓冲区或 "filename" 存在时,置位 valid 标志位。 如果 {list} 为空,快速修复列表被清除。 注意 此列表和 getqflist() 返回之值不尽相同。 {action} 值: setqflist-action E927 'a' 把 {list} 项目加入已有的快速修复列表。如果该列表尚不存 在,建立新表。 'r' {list} 项目替换当前快速修复列表项目。也可用于清除列 表: :call setqflist([], 'r') 'f' 释放快速修复堆栈上的所有快速修复列表。 如果 {action} 不存在或者设为 ' ',那么建立新表。栈中在当前快速 修复列表之后加入新快速修复列表并释放其后的所有列表。要在栈的尾 部加入新快速修复列表,把 {what} 中的 "nr" 设为 "$"。 {what} 支持以下项目: context 快速修复列表上下文。见 quickfix-context efm 解析 "lines" 时使用的 errorformat。如果没有给 出,使用 'errorformat' 选项值。 见 quickfix-parse id 快速修复列表标识号 quickfix-ID idx 'id''nr' 指定的快速修复列表的当前项的索 引。如果设为 '$',列表的末项设为当前项。见 quickfix-index items 快速修复项目的列表,同 {list} 参数。 lines 用 'efm' (译者注: 原文作 'errorformat',似不 妥) 解析文本行列表并其结果项目加入快速修复列表 {nr}{id} 中。只支持 List 类型。 见 quickfix-parse nr 快速修复堆栈中的列表号;零代表当前快速修复列 表,"$" 代表最后的快速修复列表。 quickfixtextfunc 获取显示在快速修复窗口的文本的函数。值可取函数 名、函数引用或匿名函数。参见 quickfix-window-function 解释如何写此函数并 给出示例。 title 快速修复列表标题。见 quickfix-title 忽略 {what} 中不支持的项目。 如果不给出 "nr",修改当前快速修复列表。要创建新的快速修复列 表,"nr" 可设为比快速修复栈大小大一的值。 在修改快速修复列表时,要保证修改的是正确的列表,应用 "id" 而不 是 "nr" 来指定列表。 示例 (另见 setqflist-examples ): :call setqflist([], 'r', {'title': 'My search'}) :call setqflist([], 'r', {'nr': 2, 'title': 'Errors'}) :call setqflist([], 'a', {'id':qfid, 'lines':["F1:10:L10"]}) 返回零代表成功,-1 代表失败。 该函数用来独立于 'errorformat' 的设置建立快速修复列表。 `:cc 1` 这样的命令可以跳转到第一个位置上。 也可用作 method ,基是作为第二个参数传递的: GetErrorlist()->setqflist() setreg() setreg({regname}, {value} [, {options}]) 设置寄存器 {regname} 的值为 {value}。 如果 {regname} 为 "" 或 "@",使用无名寄存器 '"'。 Vim9-script{regname} 必须为单个字符。 {value} 可以是 getreg()getreginfo() 返回的任何类型,包 括 ListDict 。 如果 {options} 包含 "a" 或者 {regname} 为大写,该值被附加于现 有值之后。 {options} 还可以指定寄存器新类型的规格: "c" 或 "v" characterwise (面向字符) 模式 "l" 或 "V" linewise (面向行) 模式 "b" 或 "<CTRL-V>" blockwise-visual (面向列块) 模式 如果 "b" 或 "<CTRL-V>" 之后紧跟数值,那么该数值用作选择的宽度 - 如果没有指定,那么列块的宽度设为最长的行字符数 (把 <Tab> 看作一个字符)。 如果 {options} 没有寄存器设置,那么字符串值 {value} 缺省使用面 向字符模式,除非 {value}<NL> 结尾,列表值的 {value} 缺省使 用面向行模式。不会自动选择面向列块模式。 返回零代表成功,非零代表失败。 E883 备注: 设置搜索和表达式寄存器时,不可使用多于一个项目的 List 。无项目的列表相当于空串。 示例: :call setreg(v:register, @*) :call setreg('*', @%, 'ac') :call setreg('a', "1\n2\n3", 'b5') :call setreg('"', { 'points_to': 'a'}) 本例说明如何使用函数来保存和恢复寄存器: :let var_a = getreginfo() :call setreg('a', var_a) 或: :let var_a = getreg('a', 1) :let var_amode = getregtype('a') .... :call setreg('a', var_a, var_amode) 备注: 如果不提供 getreg() 的第三个参数,就不能可靠地恢复寄存 器值,因为此时,换行符和 Nul 字节都用换行符表示,见 NL-used-for-Nul )。 你可以通过附加空串来改变寄存器的类型: :call setreg('a', '', 'al') 也可用作 method ,基是作为第二个参数传递的: GetText()->setreg('a') settabvar({tabnr}, {varname}, {val}) settabvar() 设置标签页 {tabnr} 的标签页局部变量 {varname} 的值为 {val}注意 自动命令是阻塞的,可能不会触发副作用,比如设置 'filetype' 的时候。 注意 必须使用不带 "t:" 的名字。 标签页的编号从一开始。 该命令在沙盘里不可用 sandbox 。 也可用作 method ,基是作为第三个参数传递的: GetValue()->settabvar(tab, name) settabwinvar({tabnr}, {winnr}, {varname}, {val}) settabwinvar() 设置窗口 {nr} 的选项或局部变量 {varname} 的值为 {val}。 标签页的编号从一开始。 setwinvar() 总是使用当前标签页。 {winnr} 可以是窗口号或 window-ID 。 如果 {winnr} 为零,使用当前窗口。 注意 自动命令是阻塞的,可能不会触发副作用,比如设置 'filetype''syntax' 的时候。 也可用于全局或者局部于缓冲区的选项,但不能用于全局或者局部于缓 冲区的变量。 如果设置局部于缓冲区的选项,全局值不会改变。 注意 必须使用不带 "w:" 的变量名。 示例: :call settabwinvar(1, 1, "&list", 0) :call settabwinvar(3, 2, "myvar", "foobar") 该命令在沙盘里不可用 sandbox 。 也可用作 method ,基是作为第四个参数传递的: GetValue()->settabvar(tab, winnr, name) (译者注: 原文如此,应为 settabwinvar) settagstack({nr}, {dict} [, {action}]) settagstack() {dict} 修改窗口 {nr} 标签栈。 {nr} 可以是窗口号或 window-ID 。 要查阅 {dict} 支持项的列表,可参考 gettagstack() 。 "curidx" 在标签栈修改之前生效。 E962 标签栈如何修改取决于 {action} 参数: - 如果 {action} 没给出或是 'r',标签栈被替换。 - 如果 {action} 是 'a',则 {dict} 中的新项被压进标签栈里。 - 如果 {action} 是 't',删除标签栈的当前项或 {dict} 中的 "curidx" 项里面的所有项目,然后把新项压进标签栈里。 当前索引设为修改之后的标签栈的长度之后的那项。 成功时返回零,失败则返回 -1。 示例 (更多示例可见 tag-stack-examples ): 清空窗口 3 的标签栈: call settagstack(3, {'items' : []}) 保存并恢复标签栈: let stack = gettagstack(1003) " do something else call settagstack(1003, stack) unlet stack 也可用作 method ,基是作为第二个参数传递的: GetStack()->settagstack(winnr) setwinvar({winnr}, {varname}, {val}) setwinvar() 类似于 settabwinvar() ,只用当前标签页。 示例: :call setwinvar(1, "&list", 0) :call setwinvar(2, "myvar", "foobar") 也可用作 method ,基是作为第三个参数传递的: GetValue()->setwinvar(winnr, name) sha256({string}) sha256() 返回 64 位十六进制字符串,即 {string} 的 SHA256 校验码。 也可用作 method : GetText()->sha256() {仅当编译时加入 +cryptv 特性才有效} shellescape({string} [, {special}]) shellescape() 转义 {string} 以便用作外壳命令的参数。 在 MS-Windows 上,如果未设定 'shellslash',用双引号包围 {string},并给 {string} 内的双引号加倍。 否则,用单引号包围,并把所有的 "'" 替换为 "'\''"。 如果给出 {special} 参数且它是非零的数值或非空的字符串 ( non-zero-arg ),则特殊项目如 "!"、"%"、"#" 和 "<cword>" 等会 在前面加上反斜杠。 :! 命令会再把反斜杠删除。 如果 'shell' 以 "csh" 结尾,"!" 字符会被转义 (仍是当 {special}non-zero-arg 时)。这是因为 csh 和 tcsh 即使在单引号内仍然 使用 "!" 用于历史替换。 如果 {special}non-zero-arg<NL> 也被转义。'shell' 以 "csh" 结尾时,转义两次。 :! 命令的示例: :exe '!dir ' . shellescape(expand('<cfile>'), 1) 返回光标所在文件给出的目录列表。 system() 的示例: :call system("chmod +w -- " . shellescape(expand("%"))) 另见 ::S 。 也可用作 method : GetCommand()->shellescape() shiftwidth([{col}]) shiftwidth() 返回 'shiftwidth' 的有效值。即 'shiftwidth' 值,除非其为零时则 返回 'tabstop' 的值。此函数是 2012 年 7.3.694 补丁版本引入的, 现在应该大家都有了 (不过可选的 {col} 参数是 8.1.542 以后才有 的)。 给出一个参数 {col} 时,指定列号,返回它所用的 'shiftwidth' 值。这和 'vartabstop' 特性有关。如果打开 'vartabstop' 设置没有 给出 {col},假定为列 1。 也可用作 method : GetColumn()->shiftwidth() sign_ 函数文档在这里: sign-functions-details 。 simplify({filename}) simplify() 在不改变含义的前提下,尽可能简化文件名。快捷方式 (MS-Windows 上) 或者符号链接 (Unix 上) 不会被解析。如果 {filename} 第一个 路径部分指定了当前目录,结果也会是如此。而结尾的路径分隔符也不 会被删除。在 Unix 上 "//path" 不作改动,但 "///path" 被简化为 "/path" (这符合 posix 规范)。 示例: simplify("./dir/.././/file/") == "./file/" 注意: 组合 "dir/.." 只有在 "dir" 是可以遍历的或者不存在的目录 才会被删掉。Unix 上,如果 "dir" 是同一目录下的符号链接,也会删 除该组合。为了在简化路径名之前解析所有牵涉到的符号链接,使用 resolve() 。 也可用作 method : GetName()->simplify() sin({expr}) sin() 返回浮点数,即以弧度测量的 {expr} 的正弦值。 {expr} 的计算结果必须是浮点数或数值。 示例: :echo sin(100) -0.506366 :echo sin(-4.01) 0.763301 也可用作 method : Compute()->sin() {仅当编译时加入 +float 特性才有效} sinh({expr}) sinh() 返回 {expr} 的双曲正弦值,返回值为 [-inf, inf] 区间内的浮点 数。 {expr} 的计算结果必须是浮点数或数值。 示例: :echo sinh(0.5) 0.521095 :echo sinh(-0.9) -1.026517 也可用作 method : Compute()->sinh() {仅当编译时加入 +float 特性才有效} slice({expr}, {start} [, {end}]) slice() 类似 slice 表达式 "expr[start : end]",但 "end" 的用法是闭 的。而且对字符串而言,索引使用的是字符索引而不是字节索引,就像 vim9script 里的处理方式一样。另外,不计算组合字符。 如果 {end} 省略,分片会继续到末项为止。 如果 {end} 为 -1,则末项会被排除。 也可用作 method : GetList()->slice(offset) sort({list} [, {func} [, {dict}]]) sort() E702 {list} 项目排序,原地直接修改列表。返回 {list}。 如果你不想修改列表,先构建一个备份: :let sortedlist = sort(copy(mylist)) 如果 {func} 省略、为空或为零,则 sort() 对每个项目使用字符串表 示形式进行排序。数值排在字符串之后, List 排在数值之后。要给 当前缓冲区的文本排序,用 :sort 。 如果给出 {func} 且为 '1' 或 'i',忽略大小写。 如果给出 {func} 且为 'l',排序使用当前排序规则 locale。实现细 节:用 strcoll() 来进行字符串比较。关于如何查看或设置排序规则 locale,参见 :languagev:collate 也可用于检查当前 locale。 按 locale 的排序通常忽略大小写。示例: " ö 的排位顺序类似于英语 locale 的 o。 :language collate en_US.UTF8 :echo sort(['n', 'o', 'O', 'ö', 'p', 'z'], 'l') ['n', 'o', 'O', 'ö', 'p', 'z'] " ö 在瑞典 locale 里排在 z 之后。 :language collate sv_SE.UTF8 :echo sort(['n', 'o', 'O', 'ö', 'p', 'z'], 'l') ['n', 'o', 'O', 'p', 'z', 'ö'] Mac 上此功能不能正常工作。 如果给出 {func} 且为 'n',按数值顺序排序 (实现细节: 用 strtod() 函数来解析数值,字符串、列表、字典和函数引用均视作 0)。 如果给出 {func} 且为 'N',按数值顺序排序。和 'n' 类似,但包含 数位的字符串会被当作数值。 如果给出 {func} 且为 'f',按数值顺序排序。所有值的类型必须是数 值或浮点数。 如果 {func}Funcref 或函数名,调用该函数来比较项目。函数 调用时使用两个项目作为参数,函数返回时,0 代表相等,1 或更高代 表第一个排在第二个之后,-1 或更小代表第一个排在第二个之前。 {dict} 用于带 "dict" 属性的函数,并设为局部变量 "self"。 Dictionary-function 排序是稳定的,相同值 (数值或字符串) 的项目保持原有的顺序不变。 例如,按数值顺序排序时,文本字符串会紧挨在一起,按原先的顺序出 现。 也可用作 method : mylist->sort() 另见 uniq() 。 例如: func MyCompare(i1, i2) return a:i1 == a:i2 ? 0 : a:i1 > a:i2 ? 1 : -1 endfunc let sortedlist = sort(mylist, "MyCompare") 对这个简单的例子,有更简短的一个比较版本,不考虑溢出情况: func MyCompare(i1, i2) return a:i1 - a:i2 endfunc sound_clear() sound_clear() 停止播放所有声音。 {仅当编译时加入 +sound 特性才有效} sound_playevent() sound_playevent({name} [, {callback}]) 播放 {name} 定义的声音。支持的事件名取决于系统。通常使用的是 XDG 声音名。Ubuntu 上可以在 /usr/share/sounds/freedesktop/stereo 中找到。例如: call sound_playevent('bell') MS-Windows 上,{name} 可以是 SystemAsterisk、SystemDefault、 SystemExclamation、SystemExit、SystemHand、SystemQuestion、 SystemStart、SystemWelcome 等等。 {callback} 给出时,在声音结束后调用。首个参数是声音 ID,第二个 参数是状态: 0 声音播放到结束 1 声音被中断 2 声音启动后出错 示例: func Callback(id, status) echomsg "sound " .. a:id .. " finished with " .. a:status endfunc call sound_playevent('bell', 'Callback') MS-Windows: 此函数不支持 {callback}。 返回声音 ID,可传递给 sound_stop() 。 如果声音不能播放,返回零。 也可用作 method : GetSoundName()->sound_playevent() {仅当编译时加入 +sound 特性才有效} sound_playfile() sound_playfile({path} [, {callback}]) 类似于 sound_playevent() 但播放声音文件 {path}{path} 必须 是完整路径。Ubuntu 上可以用此命令找可播放的文件: :!find /usr/share/sounds -type f | grep -v index.theme 也可用作 method : GetSoundPath()->sound_playfile() {仅当编译时加入 +sound 特性才有效} sound_stop({id}) sound_stop() 停止播放声音 {id}{id} 必须是之前 sound_playevent()sound_playfile() 的返回值。 MS-Windows 上,本函数不能用于 sound_playevent() 启动的事件声 音。要停止事件声音,用 sound_clear() 。 也可用作 method : soundid->sound_stop() {仅当编译时加入 +sound 特性才有效} soundfold() soundfold({word}) 返回 {word} 按发音折叠的等价形式。使用当前窗口的 'spelllang' 中第一个支持按发音折叠的语言。'spell' 必须置位。如果不能按发音 折叠,按原样返回 {word}。 可用来提供拼写建议。注意 此方法可能很慢。 也可用作 method : GetWord()->soundfold() spellbadword() spellbadword([{sentence}]) 没有参数: 返回光标所在或之后的拼写错误的单词。光标移动到这个坏 词的开始处。如果光标行上没有坏词,返回空字符串,不移动光标。 有参数: 返回 {sentence} 里第一个拼写错误的单词。如果没有拼写错 误,返回空字符串。 返回值是两个项目的列表: - 错误拼写的单词,或空字符串。 - 拼写错误的类型: "bad" 拼写错误 "rare" 偏僻词 "local" 只在其它区域里合法的单词 "caps" 单词应该大写开头 例如: echo spellbadword("the quik brown fox") ['quik', 'bad'] 使用当前窗口的拼写信息和 'spelllang' 的值。 也可用作 method : GetText()->spellbadword() spellsuggest() spellsuggest({word} [, {max} [, {capital}]]) 返回 List ,包含替代 {word} 的拼写建议。 如果给出 {max},返回的建议不超过此数目。否则,返回不超过 25 个 建议。 如果给出 {capital} 参数且非零,只给出大写开头的拼写建议。 'spellcapcheck' 匹配后再使用此功能。 {word} 可以是后跟其它文本的错误拼写单词。这样可以对两个被分开 的单词进行连接。建议里也包含附加文本,以便你替换整行。 {word} 也可以是个好词。返回和它类似的单词。建议里不包含 {word} 自身,但可能会出现其大写开头的形式。 使用当前窗口的拼写信息、 'spelllang''spellsuggest' 的值。 也可用作 method : GetWord()->spellsuggest() split({expr} [, {pattern} [, {keepempty}]]) split() {expr} 构造 List 。 如果 {pattern} 省略或为空,用每个空白分隔的字符序列构造一个项 目。否则,在匹配 {pattern} 的地方分割字符串,删除匹配部分的字 符。'ignorecase' 此处不适用,要忽略大小写,加上 \c。 /\c 如果列表的首末项目为空,省略它们,除非 {keepempty} 参数给出且 非零。其它空项目在 {pattern} 匹配至少一个字符或者 {keepempty} 非零的时候被保留。 例如: :let words = split(getline('.'), '\W\+') 要把字符串分割到每个字符: :for c in split(mystring, '\zs') 如果你想保留分隔符,可以在模式尾部用 '\zs': :echo split('abc:def:ghi', ':\zs') ['abc:', 'def:', 'ghi'] 分割首项可能为空的表格: :let items = split(line, ':', 1) 逆函数是 join() 。 也可用作 method : GetString()->split() sqrt({expr}) sqrt() 返回浮点数,即 {expr} 的非负平方根。 {expr} 的计算结果必须是浮点数或数值。如果 {expr} 为负,返回 NaN (Not a Number,非数)。 示例: :echo sqrt(100) 10.0 :echo sqrt(-4.01) nan "nan" 可能不同,取决于系统库。 也可用作 method : Compute()->sqrt() {仅当编译时加入 +float 特性才有效} srand([{expr}]) srand() 初始化 rand() 用的种子: - 如果没给出 {expr},如果可以,读取 /dev/urandom 并用作种子, 否则,用 time(NULL) 也就是 epoch 时间;后者只有秒级精确度。 - {expr} 给出时必须是数值。用于初始种子值。可用于测试或需要可 预测序列的场合。 示例: :let seed = srand() :let seed = srand(userinput) :echo rand(seed) state([{what}]) state() 返回字符串,包含指示当前状态的字符。主要用于要做一些可能不总是 安全的操作的回调。大致上,做的事是: - 回调使用 state() 检查工作是否安全。 是: 马上开始做。 否: 加入工作队列,新增 SafeState 和/或 SafeStateAgain 自动命令 ( SafeState 在顶层触发, SafeStateAgain 在处 理完信息和回调后触发)。 - SafeState 或 SafeStateAgain 触发时执行你的自动命令,检查 state() 看看工作现在是否可以了,如果是的话从队列中删除之并 执行,如果队列为空也删除自动命令。 另见 mode(){what} 给出时只加入此字符串中的字符。例如,下例检查屏幕是否有 滚动: if state('s') == '' " 屏幕还未滚动 这些字符指示状态,一般而言指示有东西在忙: m 映射、:normal 命令、feedkeys() 或庞大的命令进行到中途 时 o 操作符等待状态,如 d 之后 a 插入模式自动补全激活时 x 执行自动命令时 w 处于阻塞等待时,如 ch_evalexpr()、ch_read() 或 ch_readraw() 读入 json 时 S 不触发 SafeState 或 SafeStateAgain,如 f 或计数之后 c 调用了包括定时器在内的回调 (递归时会重复,多至 "ccc") s 屏幕已经为消息滚动过 str2float({expr}) str2float() 把字符串 {expr} 转换为浮点数。这和使用浮点数的工作方式一样,见 floating-point-format ,但稍稍宽松一点。例如,接受 "1e40",而 表达式中你必须书写 "1.0e40"。也接受十六进制形式 "0x123",但其 它的如二进制或八进制不行。 安静地忽略数值之后的文本。 小数点必须是 '.',和当前的 locale 无关。逗号会使数值转换结束: "12,345.67" 转换为 12.0。用 substitute() 可以拿掉千分位分 隔符: let f = str2float(substitute(text, ',', '', 'g')) 也可用作 method : let f = text->substitute(',', '', 'g')->str2float() {仅当编译时加入 +float 特性才有效} str2list({expr} [, {utf8}]) str2list() 返回包含代表字符串 {expr} 中的每个字符数值的列表。例如: str2list(" ") 返回 [32] str2list("ABC") 返回 [65, 66, 67] list2str() 是逆操作。 {utf8} 省略或为零时,使用当前 'encoding'{utf8} 为 1 时,总是把字符串当作 utf-8 字符。 使用 utf-8 时,组合字符正常工作: str2list("á") 返回 [97, 769] 也可用作 method : GetString()->str2list() str2nr({expr} [, {base} [, {quoted}]]) str2nr() 把字符串 {expr} 转化为数值。 {base} 是转换的基底,可以为 2、8、10 或 16。 给出 {quoted} 且非零时,忽略内嵌的单引号,所以 "1'000'000" 是 一百万。 如果省略 {base},使用基底 10。这也意味着开头的零不会导致八进制 的转换,缺省的字符串到数值的转化并非如此。例如: let nr = str2nr('0123') 如果 {base} 为 16,忽略开头的 "0x" 或 "0X"。如果使用别的基底, 返回零。类似的,如果 {base} 为 8,忽略开头的 "0"、"0o" 或 "0O",如果 {base} 为 2,忽略开头的 "0b" 或 "0B"。 安静地忽略数值之后的文本。 也可用作 method : GetText()->str2nr() strcharlen({expr}) strcharlen() 返回数值,给出字符串 {expr} 中的字符数。忽略组合字符。 strchars() 可计算组合字符分别计算的字符数目。 另见 strlen()strdisplaywidth()strwidth() 。 也可用作 method : GetText()->strcharlen() strcharpart({src}, {start} [, {len} [, {skipcc}]]) strcharpart() strpart() 类似,但用字符索引和长度而不是字节索引和长度。 {skipcc} 省略或为零时,组合字符也算一个字符。 {skipcc} 设为 1 时,计算时忽略组合字符,这和 slice() 类似。 使用字符索引时如果字符不存在,返回值里忽略之但算作一个字符。例 如: strcharpart('abc', -1, 2) 返回 'a'。 也可用作 method : GetText()->strcharpart(5) strchars({expr} [, {skipcc}]) strchars() 返回数值,给出字符串 {expr} 中的字符数。 {skipcc} 省略或为零时,组合字符也算一个字符。 {skipcc} 设为 1 时,计算时忽略组合字符。 strcharlen() 的行为总是如此。 另见 strlen()strdisplaywidth()strwidth(){skipcc} 只在 7.4.755 之后才出现。为了后向兼容,可以这样定义 包装函数: if has("patch-7.4.755") function s:strchars(str, skipcc) return strchars(a:str, a:skipcc) endfunction else function s:strchars(str, skipcc) if a:skipcc return strlen(substitute(a:str, ".", "x", "g")) else return strchars(a:str) endif endfunction endif 也可用作 method : GetText()->strchars() strdisplaywidth({expr} [, {col}]) strdisplaywidth() 返回数值,给出字符串 {expr}{col} 开始时在屏幕上占据的显示 单元的数目 (首列为零)。{col} 省略时假定为零。否则给出开始计算 的屏幕列号。该值对制表符的计算有影响。 使用当前窗口的选项设置。其中影响显示的选项也对返回值有影响,如 'tabstop''display'{expr} 如包含东亚二义性宽度字符类,'ambiwidth' 也会影响返回结 果。 另见 strlen()strwidth()strchars() 。 也可用作 method : GetText()->strdisplaywidth() strftime({format} [, {time}]) strftime() 返回字符串,即经过 {format} 字符串的格式转换的日期和时间。使用 给定的 {time},如果没有给出时间,使用当前时间。可以接受的 {format} 取决于你的系统。这意味着该函数不是可移植的! 可用的格式参见 C 函数 strftime() 的参考手册。返回结果的最大长 度是 80 个字符。另见 localtime()getftime()strptime() 。 可以用 :language 命令改变语言。 示例: :echo strftime("%c") Sun Apr 27 11:49:23 1997 :echo strftime("%Y %b %d %X") 1997 Apr 27 11:53:25 :echo strftime("%y%m%d %T") 970427 11:53:55 :echo strftime("%H:%M") 11:55 :echo strftime("%c", getftime("file.c")) 显示 file.c 的修改时间。 并非所有系统都可以用。要检查这一点,用: :if exists("*strftime") 也可用作 method : GetFormat()->strftime() strgetchar({str}, {index}) strgetchar() 获取 {str} 中的第 {index} 个字符。使用字符索引而不是字节索引。 这里,组合字符当作单独的字符。 另见 strcharpart()strchars() 。 也可用作 method : GetText()->strgetchar(5) stridx({haystack}, {needle} [, {start}]) stridx() 返回数值,给出字符串 {haystack} 里第一个字符串 {needle} 出现的 字节位置。 如果给出 {start},搜索从 {start} 位置开始。可用来寻找第二个匹 配: :let colon1 = stridx(line, ":") :let colon2 = stridx(line, ":", colon1 + 1) 搜索对大小写敏感。 模式搜索可用 match() 。 如果 {needle} 不出现在 {haystack} 里,返回 -1。 另见 strridx() 。示例: :echo stridx("An Example", "Example") 3 :echo stridx("Starting point", "Start") 0 :echo stridx("Starting point", "start") -1 strstr() strchr() stridx() 和 C 函数 strstr() 类似。如果使用单个字符,和 strchr() 类似。 也可用作 method : GetHaystack()->stridx(needle) string() string({expr}) 返回 {expr} 转换后的字符串。如果 {expr} 为数值、浮点数、字符 串、blob 或它们的复合形式,那么用 eval() 可以把结果转回去。 {expr} 类型 返回值 字符串 'string' (单引号加倍) 数值 123 浮点数 123.123456 或 1.23456e8 函数引用 function('name') blob 0z00112233.44556677.8899 列表 [item, item] 字典 {key: value, key: value} ListDictionary 中如有递归引用,被替换为 "[...]" 或 "{...}"。在此结果上运行 eval() 会出错。 也可用作 method : mylist->string() 另见 strtrans() strlen() strlen({expr}) 返回数值,即字符串 {expr} 的字节长度。 如果参数为数值,先把它转化为字符串。其它类型报错。 要计算多字节字符的数目,可用 strchars() 。 另见 len()strdisplaywidth()strwidth() 。 也可用作 method : GetString()->strlen() strpart({src}, {start} [, {len} [, {chars}]]) strpart() 返回字符串,{src} 从第 {start} 个字节开始字节长度为 {len} 的子 串。 {chars} 存在且为 TRUE 时,{len} 为字符位置的个数 (组合字符不单 独统计,因此 "1" 代表一个基本字符并可后跟任意的组合字符)。 要以字符而不是字节计算 {start},用 strcharpart() 。 如果选择不存在的字节,不会产生错误。只是那些字节被忽略而已。 如果没有提供 {len},子串从 {start} 开始直到 {src} 的结尾。 strpart("abcdefg", 3, 2) == "de" strpart("abcdefg", -2, 4) == "ab" strpart("abcdefg", 5, 4) == "fg" strpart("abcdefg", 3) == "defg" 注意: 要得到第一个字符,{start} 必须是零。比如,要得到光标所在 的字符: strpart(getline("."), col(".") - 1, 1, v:true) 也可用作 method : GetText()->strpart(5) strptime({format}, {timestring}) strptime() 返回数值,代表期待能匹配 {format} 指定格式的 {timestring} 中的 日期和时间的 unix 时间戳。 可接受的 {format} 取决于系统,所以不可移植!具体格式见 C 函数 strptime() 的手册页。特别要注意避免 "%c"。$TZ 的值也相关。 如果 {timestring} 不能用 {format} 格式解析,返回零。如果不知道 {timestring} 的格式,可以尝试不同的 {format} 值直到返回非零值 为止。 另见 strftime() 。 示例: :echo strptime("%Y %b %d %X", "1997 Apr 27 11:49:23") 862156163 :echo strftime("%c", strptime("%y%m%d %T", "970427 11:53:55")) Sun Apr 27 11:53:55 1997 :echo strftime("%c", strptime("%Y%m%d%H%M%S", "19970427115355") + 3600) Sun Apr 27 12:53:55 1997 不是在所有系统都可用。要确认: :if exists("*strptime") strridx({haystack}, {needle} [, {start}]) strridx() 返回数值,给出字符串 {haystack} 里最后一个字符串 {needle} 出现 的字节位置。 如果给出 {start},此位置之外的匹配被忽略。可用来寻找上次匹配之 前的匹配: :let lastcomma = strridx(line, ",") :let comma2 = strridx(line, ",", lastcomma - 1) 搜索对大小写敏感。 模式搜索可用 match() 。 如果 {needle} 不出现在 {haystack} 里,返回 -1。 如果 {needle} 为空,返回 {haystack} 的长度。 另见 stridx() 。示例: :echo strridx("an angry armadillo", "an") 3 strrchr() 如果使用单个字符,和 C 函数 strrchr() 类似。 也可用作 method : GetHaystack()->strridx(needle) strtrans({expr}) strtrans() 返回等于 {expr} 的字符串,但所有的不可显示字符被翻译成可显示的 字符序列 'isprint' ,类似于窗口里显示的形式。例如: echo strtrans(@a) 会显示寄存器里的换行符为 "^@" 而不是开启新行。 也可用作 method : GetString()->strtrans() strwidth({expr}) strwidth() 返回数值,给出字符串 {expr} 在屏幕上占据的显示单元的数目。制表 符算作一个单元。如果不想这样,可用 strdisplaywidth(){expr} 如包含东亚二义性宽度字符类,'ambiwidth' 也会影响返回结 果。 另见 strlen()strdisplaywidth()strchars() 。 也可用作 method : GetString()->strwidth() submatch({nr} [, {list}]) submatch() E935 只用于 :substitute 命令或 substitute() 函数中的表达式内。 返回匹配文本的第 {nr} 个子匹配。{nr} 为 0 则返回整个匹配的文 本。 注意 字符串中的 NL 既可以代表多行匹配的行尾,也可以是文件中的 NUL 字符。 另见 sub-replace-expression 。 如果给出 {list} 且非零,submatch() 返回字符串的列表,和带两个 参数的 getline() 类似。文本中的 NL 代表文件中的 NUL 字符。 只在 :substitute 中可能返回多于一个项目, substitute() 中此 列表总是包含一个或零个项目,因为没有真正的行尾。 递归使用 substitute() 时,只能得到当前 (最深的) 调用的子匹配。 例如: :s/\d\+/\=submatch(0) + 1/ :echo substitute(text, '\d\+', '\=submatch(0) + 1', '') 找到行内第一个数值并加 1。 使用 <NL> 可以包含换行符。 也可用作 method : GetNr()->submatch() substitute({expr}, {pat}, {sub}, {flags}) substitute() 返回相当于 {expr} 的字符串,但其中 {pat} 的首个匹配被替代成 {sub}。 如果 {flags} 为 "g",替换 {expr} 里的所有 {pat} 匹配。否则, {flags} 应该为 ""。 和 ":substitute" 命令 (不带任何标志位) 类似。但此处 {pat} 的匹 配总假定 'magic' 选项已置位且 'cpoptions' 为空 (为了脚本的可移 植性)。 'ignorecase' 仍然适用, /\c/\C 可用来直接指定是否忽略或 匹配大小写并忽略 'ignorecase' 的设置。 'smartcase' 此处不适用。 string-match 说明如何使用 {pat}{sub} 里的 '~' 不会被换成前一个 {sub}注意 {sub} 里的一些代码有特殊含义 sub-replace-special 。比 如,要替换若干文本为 "\n" (两个字符),要用 "\\\\n" 或 '\\n'。 如果 {pat}{expr} 里不能匹配,返回没有修改的 {expr}。 示例: :let &path = substitute(&path, ",\\=[^,]*$", "", "") 删除 'path' 选项的最后一部分。 :echo substitute("testing", ".*", "\\U\\0", "") 返回 "TESTING"。 {sub} 参数以 \= 开始时,其余部分视为一个表达式,见 sub-replace-expression 。示例: :echo substitute(s, '%\(\x\x\)', \ '\=nr2char("0x" . submatch(1))', 'g') {sub} 若是函数引用,调用该函数,带一个可选参数。示例: :echo substitute(s, '%\(\x\x\)', SubNr, 'g') 可选参数是包含完整匹配及多达九个子匹配的列表,就像 submatch() 的返回值那样。示例: :echo substitute(s, '%\(\x\x\)', {m -> '0x' . m[1]}, 'g') 也可用作 method : GetString()->substitute(pat, sub, flags) swapinfo({fname}) swapinfo() 返回字曲,保存关于交换文件 {fname} 的信息。可用的域是: version Vim 版本 user 用户名 host 主机名 fname 原始文件名 pid 创建交换文件的 Vim 进程的 PID mtime 以秒计的最近修改时间 inode 可选: 文件的 INODE 值 dirty 如果文件修改过为 1,否则为 0 注意 "user" 和 "host" 被缩短为最多 39 个字节。如果失败,加入 "error" 项目说明相关原因: Cannot open file: 文件找不到或不能访问 Cannot read file: 不能读入首块 Not a swap file: 没有包含正确的块 ID Magic number mismatch: 首块的信息不正确 也可用作 method : GetFilename()->swapinfo() swapname({expr}) swapname() 返回缓冲区 {expr} 所用的交换文件路径。 {expr} 的使用方式见上 bufname() 。 如果缓冲区 {expr} 是当前缓冲区,结果相当于 :swapname (除非没 有交换文件)。 如果缓冲区 {expr} 无交换文件,返回空串。 也可用作 method : GetBufname()->swapname() synID({lnum}, {col}, {trans}) synID() 返回数值,即当前窗口 {lnum}{col} 列所在的语法 ID。 语法 ID 可以用在 synIDattr()synIDtrans() ,以得到文本 的语法信息。 最左列的 {col} 为 1。第一行的 {lnum} 为 1。适用 'synmaxcol' 的 值,如果行比它更长,就返回零。 注意 位置在最后一个字符之后是插入模式下可能的光标位置。此时, synID() 返回零。 如果 {trans}TRUE ,透明的项目被简约为它们实际显露的项目。 这可以用于你想知道实际使用的颜色的情形。如果 {trans}FALSE ,返回透明的项目本身。这可用于想知道实际有效的语法项目 的情形 (比如,在括号内部)。 警告: 本函数可能很慢。最佳速度可以通过正向遍历文件获得。 例如 (回显光标所在的语法项目的名字): :echo synIDattr(synID(line("."), col("."), 1), "name") synIDattr({synID}, {what} [, {mode}]) synIDattr() 返回字符串,syntax ID {synID}{what} 属性。可用于得到语法项 目的相关信息。 {mode} 可以是 "gui"、"cterm" 或 "term",从而得到的是该模式下的 属性。如果忽略 {mode} 或者指定了非法的值,使用当前激活的高亮方 式的属性 (GUI、cterm 或 term)。 使用 synIDtrans() 来跟随链接的高亮组。 {what} 结果 "name" 语法项目的名字 "fg" 前景色 (GUI: 用于设置颜色的色彩名,cterm: 色彩 号,以字符串形式出现,term: 空字符串) "bg" 背景色 (细节同 "fg") "font" 字体名 (只适用于 GUI) highlight-font "sp" 用于 GUI 的特殊颜色 (细节同 "fg") highlight-guisp "ul" 用于 cterm 的下划线颜色: 字符串形式出现的数值 "fg#" 类似于 "fg",但只适用于 GUI,而且 GUI 使用的名 字形如 "#RRGGBB"。 "bg#" "bg",细节同 "fg#" "sp#" "sp",细节同 "fg#" "bold" "1" 如果粗体 "italic" "1" 如果斜体 "reverse" "1" 如果反显 "inverse" "1" 如果反显 (= reverse) "standout" "1" 如果突出 "underline" "1" 如果下划线 "undercurl" "1" 如果下曲线 "strike" "1" 如果删除线 示例 (回显光标所在的语法项目的颜色): :echo synIDattr(synIDtrans(synID(line("."), col("."), 1)), "fg") 也可用作 method : :echo synID(line("."), col("."), 1)->synIDtrans()->synIDattr("fg") synIDtrans({synID}) synIDtrans() 返回数值,即 {synID} 经过翻译的语法 ID。这是用于高亮字符的语法 组的 ID。":highlight link" 给出的高亮组被跟随,以找到实际使用 的组。 也可用作 method : :echo synID(line("."), col("."), 1)->synIDtrans()->synIDattr("fg") synconcealed({lnum}, {col}) synconcealed() 返回 List ,目前包含三个值: 1. 如果 {lnum}{col} 所在位置的字符不在可隐藏区域,列表的第 一个项目为 0,否则为 1。 2. 列表的第二个项目为字符串。如果第一个值为 1,第二个值包含代 替被隐藏文本实际显示的文本,视乎 'conceallevel''listchars' 的当前值而定。 3. 列表的第三个,也即最后一个项目是代表匹配的特定语法区域的唯 一的数值。这用于在有两个连续的使用相同替代字符的区域时,检 测此处是否是一个新的可隐藏区域的开始。例如,如果文本是 "123456","23" 和 "45" 都被隐藏,而替代字符是 "X",则: call returns synconcealed(lnum, 1) [0, '', 0] synconcealed(lnum, 2) [1, 'X', 1] synconcealed(lnum, 3) [1, 'X', 1] synconcealed(lnum, 4) [1, 'X', 2] synconcealed(lnum, 5) [1, 'X', 2] synconcealed(lnum, 6) [0, '', 0] synstack({lnum}, {col}) synstack() 返回 List ,即当前窗口在 {lnum}{col} 列语法项目的堆栈。列 表的每个项目是像 synID() 返回那样的 ID。 列表的第一个项目是最外层区域,其后依次是包含在内的项目。末项即 synID() 返回的项目,除非不是整个项目都被高亮,或者它是一个透 明项目。 此函数可用于调试语法文件。 显示光标所在的语法项目栈的示例: for id in synstack(line("."), col(".")) echo synIDattr(id, "name") endfor 如果 {lnum}{col} 指定的位置非法,不返回任何值。行末字符之 后的位置以及空行的第一个位置是合法的位置。 system({expr} [, {input}]) system() E677 得到外壳命令 {expr} 字符串形式的输出结果。要得到 List 形式的 输出结果,见 systemlist() 。 如果给出 {input} 且为字符串,该字符串被写到文件里,并传给外壳 命令作为标准输入。字符串照原样写入,你需要自己注意使用合适的换 行符。 如果给出 {input} 且为 List ,它被写到文件里,就像 writefile(){binary} 设为 "b" 的工作方式那样 (即,列表项 目间写入换行符,列表项目内部的换行符改写为 NUL)。 如果给出 {input} 且为数值,代表已存在的缓冲区的合法缓冲区号, 逐行将该缓冲区的内容写入文件,每行以 NL 结尾,文本内的 NL 以 NUL 字符代替。 不使用管道,也不使用 'shelltemp' 选项。 如果加上前缀 :silent ,终端不设为加工 (cooked) 模式。这用于不 需要用户输入的命令,以避免屏幕上显示多余的字符而需要用 CTRL-L 来清除。 :silent let f = system('ls *.vim') 注意: shellescape()expand()::Sfnamemodify() 可以转义命令参数里的特殊字符。{expr} 里的换行 可能会使命令失败。'shellquote''shellxquote' 里的字符也可能 会引起麻烦。 这不是用来执行交互命令的。 返回字符串。示例: :let files = system("ls " . shellescape(expand('%:h'))) :let files = system('ls ' . expand('%:h:S')) 要使结果更独立于所用的系统,外壳输出的结果被过滤,Macintosh 的 <CR> 被换成 <NL>,而 DOS 系列的系统上 <CR><NL> 也被换成 <NL>。 为了避免字符串在 NUL 处被截断,所有的 NUL 的字符被替换为 SOH (0x01)。 使用若干选项,以下面的方法构造要执行的命令: 'shell' 'shellcmdflag' 'shellxquote' {expr} 'shellredir' {tmp} 'shellxquote' ({tmp} 是自动生成的一个文件名)。 Unix 上,{expr} 用大括号包围,以便支持连接的多条命令。 以加工 ("cooked") 模式执行命令,这样 CTRL-C 可以用来中止命令 (至少在 Unix 上是如此)。 返回的错误代码可以在 v:shell_error 里找到。 该函数不能运行于 restricted-mode注意 上面提到的选项值如有错误,该函数就会失败。使用若干安全代 理应用时也有报告说它会失败。 不同于 ":!cmd",没有自动对改变过的文件的检查。使用 :checktime 来强制这种检查。 也可用作 method : :echo GetCmd()->system() systemlist({expr} [, {input}]) systemlist() system() 相同,但返回由行组成的 List (以 NL 分隔的输出 各部分),NUL 转换为 NL。输出的工作方式和 readfile(){binary} 参数设为 "b" 相同,除了结果以 NL 结尾时不会有额外的空 项目以外。 注意 MS-Windows 上可能会有拖尾的 CR 字符。 要看到 "echo hello" 和 "echo -n hello" 的区别,参见 system()split() : echo system('echo hello')->split('\n', 1) 有错时,返回空串。 也可用作 method : :echo GetCmd()->systemlist() tabpagebuflist([{arg}]) tabpagebuflist() 返回 List ,每个项目是当前标签页里每个窗口相关联的缓冲区的编 号。 {arg} 指定使用的标签页的编号。如果省略,使用当前标签页。 如果 {arg} 非法,返回数值零。 要得到所有标签页里的所有缓冲区的列表,这样用: let buflist = [] for i in range(tabpagenr('$')) call extend(buflist, tabpagebuflist(i + 1)) endfor 注意 缓冲区可能出现于多于一个窗口里。 也可用作 method : GetTabpage()->tabpagebuflist() tabpagenr([{arg}]) tabpagenr() 返回数值,当前标签页号。第一个标签页的编号为 1。 可选参数 {arg} 支持以下值: $ 最后一个标签页的编号 (即标签页总数)。 # 最近访问的标签页编号 ( g<Tab> 对应)。如果没有 前次标签页,返回 0。 该数值可用于 :tab 命令。 tabpagewinnr({tabarg} [, {arg}]) tabpagewinnr() 类似于 winnr() ,但使用标签页 {tabarg}{tabarg} 指定要使用的标签页号。 {arg} 的用法类似于 winnr() : - 如果省略,返回当前窗口号,也就是转到该标签页时会使用的窗口。 - 如果是 "$",返回窗口的总数。 - 如果是 "#",返回上次的窗口编号。 用于的例子: tabpagewinnr(1) " 标签页 1 的当前窗口 tabpagewinnr(4, '$') " 标签页 4 的窗口总数 如果 {tabarg} 非法,返回零。 也可用作 method : GetTabpage()->tabpagewinnr() tagfiles() tagfiles() 返回 List ,当前缓冲区用于搜索的标签文件名。这是 'tags' 选项 扩展后的内容。 taglist({expr} [, {filename}]) taglist() 返回匹配正规表达式 {expr} 的标签 List 。 如果传入 {filename},用于像 :tselect 那样给结果排序。见 tag-priority{filename} 必须是文件的完整路径。 每个列表项目是一个至少包含以下项目的字典: name 标签名。 filename 标签定义的文件名。它或者相对于当前目 录,或者包含完整路径。 cmd 用于在文件里定位标签的 Ex 命令。 kind 标签类型。该项目的值取决于特定于语言的 类型值。只在 Exuberant ctags 或 hdrtag 生成的标签文件里存在。 static 特定于文件的标签。详见 static-tag 。 可能还有一些其它项目,取决于标签文件的内容: access、 implementation、inherits 和 signature。这些字段的信息参见 ctags 文档。C 代码里可能出现字段 "struct"、"class" 和 "enum", 它们给出标签所在的实体的名字。 ex 命令 "cmd" 可以是 ex 搜索模式、行号或者行号后跟字节位置。 如果没有匹配的标签,返回空列表。 要得到标签的准确匹配,{expr} 里必须使用 '^' 和 '$'。这也可加快 函数的工作速度。 关于标签搜索正规表达式模式的详情见 tag-regexp'tags' 提供 Vim 如何定位标签文件的信息。 tags-file-format 说明不同的 ctags 工具生成的标签文件的格式。 也可用作 method : GetTagpattern()->taglist() tan({expr}) tan() 返回以弧度测量的 {expr} 的正切值。返回值是 [-inf, inf] 区间内 的浮点数。 {expr} 的计算结果必须是浮点数或数值。 示例: :echo tan(10) 0.648361 :echo tan(-4.01) -1.181502 也可用作 method : Compute()->tan() {仅当编译时加入 +float 特性才有效} tanh({expr}) tanh() 返回 {expr} 的双曲正切值,返回值为 [-1, 1] 区间内的浮点数。 {expr} 的计算结果必须是浮点数或数值。 示例: :echo tanh(0.5) 0.462117 :echo tanh(-1) -0.761594 也可用作 method : Compute()->tanh() {仅当编译时加入 +float 特性才有效} tempname() tempname() temp-file-name 返回字符串,它是一个不存在的文件名。可以用作临时文件。该文件在 至少 26 个接连的调用内不会重复。例如: :let tmpfile = tempname() :exe "redir > " . tmpfile Unix 上,文件会在用户个人的目录中 tempfile 。 MS-Windows 上,如果置位了 'shellslash' 选项或者 'shellcmdflag' 以 '-' 开始的时候,使用正斜杠。 term_ 函数文档在这里: terminal-functions-details terminalprops() terminalprops() 返回 Vim 从 t_RV 请求得到的响应中检测到的终端属性的 Dictionary 。响应本身见 v:termresponse 。如果 v:termresponse 为空,这里的多数值会是 'u',代表未知。 cursor_style 是否可发送 t_RS ** cursor_blink_mode 是否可发送 t_RC ** underline_rgb t_8u 是否可用 ** mouse 支持的鼠标类型 ** 值 'u' 代表未知,'y' 代表是,'n' 代表否 如果没有 +termresponse 特性,返回空字典。 如果 "cursor_style" 是 'y',则发送 t_RS 以请求当前光标风格。 如果 "cursor_blink_mode" 是 'y',则发送 t_RC 以请求当前光标 闪烁状态。 如果 t_u7 非空,也会置位 "cursor_style" 和 "cursor_blink_mode",此时 Vim 会在启动时检测 t_RSt_RC 是否可发送。 如果 "underline_rgb" 不是 'y', t_8u 会设为空。这会避免把它发 送到 xterm 以清除色彩。 "mouse" 对应的值 'u' 代表未知 另见: - 'ambiwidth' - 由 t_u7 检测。 - v:termstylerespv:termblinkresp ,对应 t_RSt_RC 的响应。 test_ 函数文档在这里: test-functions-details timer_info() timer_info([{id}]) 返回定时器信息的列表。 给出 {id} 时只返回此定时器的信息。如果定时器 {id} 不存在,返回 空列表。 省略 {id} 时,返回所有定时器的信息。 每个定时器的信息以 Dictionary 形式保存,有以下项目: "id" 定时器号 "time" 定时器开始时间 "remaining" 定时器剩余时间 "repeat" 定时器激活的次数;-1 代表永远 "callback" 回调 "paused" 如果定时器暂停为 1,否则为 0 也可用作 method : GetTimer()->timer_info() {仅当编译时加入 +timers 特性才有效} timer_pause({timer}, {paused}) timer_pause() 暂停或恢复定时器。暂停的定时器在到期是不调用回调。如果经过足够 时间,恢复定时器会使回调几乎被立即调用。 暂停定时器可用于短期停止回调的调用。 如果 {paused} 计算为非零的数值或非空的字符串,暂停定时器,否则 恢复定时器。 见 non-zero-arg 。 也可用作 method : GetTimer()->timer_pause(1) {仅当编译时加入 +timers 特性才有效} timer_start() timer timers timer_start({time}, {callback} [, {options}]) 新建定时器并返回定时器号。 {time} 是毫秒计的等待时间。只是调用回回调的最短时间。系统如果 繁忙或 Vim 不在等待输入时,时间会更长。 {callback} 是要调用的函数。可以是函数名或 Funcref 。调用时接 受一个参数,即定时器号。只有在 Vim 等待输入时才会调用回调。 如果要显示信息,看看 popup_notification() ,以避免信息显示干 扰用户的操作。 {options} 是字典。支持的项目: "repeat" 重复调用回调的次数。-1 代表永远。无定义时,调 用回调一次。 如果定时器连续出错三次,取消重复。这避免了 Vim 因为过多的错误信息导致的不可用的情形。 示例: func MyHandler(timer) echo 'Handler called' endfunc let timer = timer_start(500, 'MyHandler', \ {'repeat': 3}) 这会以 500 毫秒间隔调用 MyHandle() 三次。 也可用作 method : GetMsec()->timer_start(callback) 该命令在沙盘里不可用 sandbox{仅当编译时加入 +timers 特性才有效} timer_stop({timer}) timer_stop() 停止定时器。不再调用定时器回调。 {timer} 是 timer_start() 返回的定时器号,所以必须是数值。如果 {timer} 不存在,不报错。 也可用作 method : GetTimer()->timer_stop() {仅当编译时加入 +timers 特性才有效} timer_stopall() timer_stopall() 停止所有定时器。不再调用定时器回调。用于有定时器工作不正常的场 合。如果没有任何定时器,不报错。 {仅当编译时加入 +timers 特性才有效} tolower({expr}) tolower() 返回给出字符串的备份,但所有的大写字符变为小写 (就如同在字符串 上应用了 gu 一样)。 也可用作 method : GetText()->tolower() toupper({expr}) toupper() 返回给出字符串的备份,但所有的小写字符变为大写 (就如同在字符串 上应用了 gU 一样)。 也可用作 method : GetText()->toupper() tr({src}, {fromstr}, {tostr}) tr() 返回 {src} 字符串的备份,其中 {fromstr} 里的每个字符被 {tostr} 字符串里同样的位置的字符替代。也就是,{fromstr} 的第一个字符被 翻译成 {tostr} 的第一个字符,依此类推。和 unix 命令 "tr" 完全 相同。 能正确处理多字节字符。 例如: echo tr("hello there", "ht", "HT") 返回 "Hello THere" echo tr("<blob>", "<>", "{}") 返回 "{blob}" 也可用作 method : GetText()->tr(from, to) trim({text} [, {mask} [, {dir}]]) trim() 返回 {text} 从头部和/或尾部删除 {mask} 里出现的字符后的字符 串。 如果没给出 {mask}{mask} 是所有直到 0x20 的字符,包括 Tab、空 格、NL 和 CR,加上不换行空格 0xa0。 可选的 {dir} 参数指定删除字符的位置: 0 从 {text} 的头部和尾部删除 1 只从 {text} 的头部删除 2 只从 {text} 的尾部删除 省略时两端都进行删除。 此函数能正确处理多字节字符。 示例: echo trim(" some text ") 返回 "some text" echo trim(" \r\t\t\r RESERVE \t\n\x0B\xA0") . "_TAIL" 返回 "RESERVE_TAIL" echo trim("rm<Xrm<>X>rrm", "rm<>") 返回 "Xrm<>X" (不删除中间部分的字符) echo trim(" vim ", " ", 2) 返回 " vim" 也可用作 method : GetText()->trim() trunc({expr}) trunc() 返回浮点数,即绝对值小于等于 {expr} 的最大整数 (向零取整)。 {expr} 的计算结果必须是浮点数或数值。 示例: echo trunc(1.456) 1.0 echo trunc(-5.456) -5.0 echo trunc(4.0) 4.0 也可用作 method : Compute()->trunc() {仅当编译时加入 +float 特性才有效} type() type({expr}) 返回数值,代表 {expr} 的类型。 不要直接使用此值,最好用含有此值的 v:t_ 变量: 数值: 0 v:t_number 字符串: 1 v:t_string 函数引用: 2 v:t_func 列表: 3 v:t_list 字典: 4 v:t_dict 浮点数: 5 v:t_float 布尔值: 6 v:t_bool (v:false 和 v:true) None: 7 v:t_none (v:null 和 v:none) 作业: 8 v:t_job 通道: 9 v:t_channel blob: 10 v:t_blob 为了后向兼容,可以这样用此函数: :if type(myvar) == type(0) :if type(myvar) == type("") :if type(myvar) == type(function("tr")) :if type(myvar) == type([]) :if type(myvar) == type({}) :if type(myvar) == type(0.0) :if type(myvar) == type(v:false) :if type(myvar) == type(v:none) 要检查 v:t_ 这些变量是否存在,可用: :if exists('v:t_number') 也可用作 method : mylist->type() typename({expr}) typename() 返回 {expr} 类型的字符串描述。 例如: echo typename([1, 2, 3]) list<number> undofile({name}) undofile() 返回用于名为 {name} 的文件的撤销文件名。使用 'undodir' 选项并 寻找实际存在的目录。并不检查该撤销文件是否存在。 {name} 总是扩展为完整路径,因为内部是这么使用的。 {name} 为空时 undofile() 也返回空字符串,因为无名缓冲区不写入 任何撤销文件。 可用于 :wundo:rundo 。 如果编译时没有 +persistent_undo 选项,总是返回空字符串。 也可用作 method : GetFilename()->undofile() undotree() undotree() 返回撤销树的当前状态。返回值是包含以下项目的 Dictionary : "seq_last" 最大使用的撤销序列号。 "seq_cur" 撤销树中当前位置的序列号。如果有撤销过的改变, 和 "seq_last" 会有不同。 "time_cur" 最近用于 :earlier 和相关命令的时间。 可用 strftime() 转换成可读的格式。 "save_last" 最后的文件写入编号。如果没有写入,返回零。 "save_cur" 撤销树当前位置的编号。 "synced" 如果最后的撤销块已经同步,返回非零值。等待用户 输入时会发生。见 undo-blocks 。 "entries" 关于撤销块的信息的字典的列表。 "entries" 列表的第一个值是最老的撤销项目。每个列表项目是一个包 含以下项目的字典: "seq" 撤销序列号。和 :undolist 显示的相同。 "time" 改变发生的时间。可用 strftime() 转换成可读的 格式。 "newhead" 只出现在最后加入的项目。标识最后的改变,并指示 将来的改变加入所在的位置。 "curhead" 只出现在最后撤销的项目。表示撤销树当前的位置, 该块可用于 redo 命令。如果最后改变之后没有撤销 动作,此项目不出现。 "save" 只出现在文件写入前最后的块。该值为写入计数。首 次写入的编号为 1,最后一次是上面提及的 "save_last"。 "alt" 替代项。这又是一个撤销块的列表。每个项目又可以 有 "alt" 项目。 uniq({list} [, {func} [, {dict}]]) uniq() E882 原地删除重复相邻的 {list} 项目的第二个及之后的版本。返回 {list} 。如果不想对列表进行修改,先建立一个备份: :let newlist = uniq(copy(mylist)) 缺省比较函数使用每个项目的字符串表示形式。关于 {func}{dict} 的使用可见 sort() 。 也可用作 method : mylist->uniq() values({dict}) values() 返回 List{dict} 的所有值。 List 项目的顺序不定。另见 items()keys() 。 也可用作 method : mydict->values() virtcol({expr}) virtcol() 要得到屏幕列的位置,用 virtcol()注意 只能使用当前文件的位置标记。 返回数值,即 {expr} 给定的文件位置的屏幕列号。也就是,该位置的 字符占据的最后一个屏幕位置,这里假设屏幕有无限的宽度。如果该位 置是一个 <Tab>,返回的数值是 <Tab> 占据的最后一列。比如,如果 <Tab> 在第 1 列,而 'ts' 设为 8 的话,返回 8。忽略 conceal() 因素。 关于字节位置,见 col(){expr} 用法见 col() 。 如果使用 'virtualedit'{expr} 可以用 [lnum, col, off],其中 "off" 是字符位置开始计算的屏幕列。例如,制表中或最后一个字符之 后的某个位置。"off" 若省略,则假定为零。 如果在当前模式下使用了虚拟编辑,也可能返回行尾之后的位置。 'virtualedit' 可接受的位置是: . 光标位置 $ 光标行的行尾 (返回光标行显示的字符数加 1) 'x 位置标记 x 的位置 (如果该位置标记没有设置,返回 0) v 可视模式下: 可视区域的开始位置 (光标是结束位置)。 如果不在可视模式下,返回当前光标位置。和 '< 不同 的是,会被立即更新。 注意 只能使用当前文件的位置标记。 示例: virtcol(".") 文本 "foo^Lbar",光标在 "^L" 上,返回 5 virtcol("$") 文本 "foo^Lbar",返回 9 virtcol("'t") 文本 " there",'t 在 'h' 上,返回 6 第一列为 1。返回 0 代表错误。 一个更高级的示例,显示所有行的最大长度: echo max(map(range(1, line('$')), "virtcol([v:val, '$'])")) 也可用作 method : GetPos()->virtcol() visualmode([{expr}]) visualmode() 返回字符串,它描述当前缓冲区最近使用的可视模式。一开始,它返回 空字符串,一旦使用了可视模式,返回 "v"、"V" 或 "<CTRL-V>" (单 个 CTRL-V 字符),分别代表面向字符、面向行、和面向列块的可视模 式。 例如: :exe "normal " . visualmode() 进入和上次相同的可视模式。也可以用于在脚本里根据最近的可视模式 采取不同的行动。 如果当前正处于可视模式中, mode() 可得到具体的可视模式 (例如 在 :vmap 中可用)。 如果提供 {expr} 并且计算结果是非零数值或者是非空字符串,那么将 清除可视模式,并返回旧的值。见 non-zero-arg 。 wildmenumode() wildmenumode() 如果 wildmenu 打开,返回 TRUE ,否则返回 FALSE 。参见 'wildmenu''wildmode'。 可用于在映射中方便地处理 'wildcharm' 选项。(只对 mapmode-c 映射有意义)。 例如要使 <c-j> 在 wildmode 中等价于 <down>,可用: :cnoremap <expr> <C-j> wildmenumode() ? "\<Down>\<Tab>" : "\<c-j>" (备注,这需要 'wildcharm' 合适的设置配合)。 win_execute({id}, {command} [, {silent}]) win_execute() 类似于 execute() 但在窗口 {id} 的上下文中执行。该窗口会被临 时设为当前窗口,不触发自动命令。执行 {command} 时会触发自动命 令,这可能有意想不到的副作用。如有必要可用 :noautocmd 。 示例: call win_execute(winid, 'set syntax=python')setwinvar() 相同但不触发自动命令也不实际显示语法高亮。 E994 不是所有的命令都允许在弹出窗口中使用。 窗口 {id} 不存在时不报错,且返回空字符串。 也可用作 method ,基是作为第二个参数传递的: GetCommand()->win_execute(winid) win_findbuf({bufnr}) win_findbuf() 返回包含缓冲区 {bufnr} 的窗口的所有 window-IDList 。如 果没有这样的窗口,返回空列表。 也可用作 method : GetBufnr()->win_findbuf() win_getid([{win} [, {tab}]]) win_getid() 返回指定窗口的 window-ID 。 忽略 {win} 则使用当前窗口。 给定 {win} 时,这是窗口号。顶部窗口的窗口号为 1。 忽略 {tab} 则使用当前标签页,否则使用标签页 {tab}。首个标签页 的标签页号为一。 如果找不到这样的窗口,返回零。 也可用作 method : GetWinnr()->win_getid() win_gettype([{nr}]) win_gettype() 返回窗口类型: "autocmd" 自动命令窗口。用于执行自动命令的临时窗 口。 "popup" 弹出窗口 popup "preview" 预览窗口 preview-window "command" 命令行窗口 cmdwin (空) 正常窗口 "unknown" 窗口 {nr} 找不到 {nr} 省略时返回当前窗口的类型。 给出 {nr} 时返回给出窗口号或 window-ID 的窗口的类型。 另见 'buftype' 选项。在弹出窗口中运行终端时,'buftype' 为 "terminal" 而 win_gettype() 返回 "popup"。 win_gotoid({expr}) win_gotoid() 转到 ID 为 {expr} 的窗口。可能会改变当前标签页。 如果成功返回 TRUE,如果找不到这样的窗口,返回 FALSE。 也可用作 method : GetWinid()->win_gotoid() win_id2tabwin({expr}) win_id2tabwin() 返回包含 ID 为 {expr} 的窗口的标签页号和窗口号的列表: [tabnr, winnr]。 如果找不到这样的窗口,返回 [0, 0]。 也可用作 method : GetWinid()->win_id2tabwin() win_id2win({expr}) win_id2win() 返回 ID 为 {expr} 的窗口号。 如果在当前标签页下找不到这样的窗口,返回零。 也可用作 method : GetWinid()->win_id2win() win_screenpos({nr}) win_screenpos() 返回两个数值的列表,即窗口 {nr} 的屏幕位置: [row, col]。首个窗 口的位置总是 [1, 1],除非它有标签页行,此时为 [2, 1]。 {nr} 可以是窗口号或 window-ID 。零代表当前窗口。 如果在当前标签页找不到窗口,返回 [0, 0]。 也可用作 method : GetWinid()->win_screenpos() win_splitmove({nr}, {target} [, {options}]) win_splitmove() 移动窗口 {nr} 成为窗口 {target} 的新分割窗口。 类似于先移动到 {target},用 :split 创建新窗口但使用窗口 {nr} 相同的内容,然后关闭 {nr}{nr}{target} 都可以是窗口号或 window-ID 。两者必须都在当 前标签页中。 如果成功返回零,失败返回非零。 {options} 是包含以下可选项的 Dictionary : "vertical" 为 TRUE 时垂直分割,类似于 :vsplit 。 "rightbelow" 为 TRUE 时分割在下方或右方 (垂直时)。为 FALSE 时分割在上方或左方 (垂直时)。如果未给出,使用 'splitbelow''splitright'。 也可用作 method : GetWinid()->win_splitmove(target) winbufnr() winbufnr({nr}) 返回数值,即窗口 {nr} 相关联的缓冲区号。{nr} 可以是窗口号或 window-ID 。 如果 {nr} 为零,返回当前窗口的缓冲区号。 如果窗口 {nr} 不存在,返回 -1。 示例: :echo "当前窗口的文件是 " . bufname(winbufnr(0)) 也可用作 method : FindWindow()->winbufnr()->bufname() wincol() wincol() 返回数值,窗口光标的虚拟列。亦即从窗口左侧起算的屏幕列数。最左 列为第一列。 windowsversion() windowsversion() 返回字符串。MS-Windows 上指示 OS 版本。例如,Windows 10 是 "10.0"。Windows 8 是 "6.2",Windows XP 是 "5.1"。非 MS-Windows 系统上返回空串。 winheight({nr}) winheight() 返回数值,窗口 {nr} 的高度。 {nr} 可以是窗口号或 window-ID 。 如果 {nr} 为零,返回当前窗口的高度。如果窗口 {nr} 不存在,返回 -1。 存在的窗口的高度至少为零。 不计入任何窗口工具条行。 示例: :echo "当前窗口有 " . winheight(0) . " 行。" 也可用作 method : GetWinid()->winheight() winlayout([{tabnr}]) winlayout() 返回嵌套列表,包含标签页中的窗口布局。 未给出 {tabnr} 则使用当前标签页,否则使用号码为 {tabnr} 的标签 页。如果标签页 {tabnr} 找不到,返回空列表。 叶窗口返回: ['leaf', {winid}] 水平分割的窗口构成一列,它们返回: ['col', [{nested list of windows}]] 垂直分割的窗口构成一行,它们返回: ['row', [{nested list of windows}]] 示例: " 标签页中只有一个窗口 :echo winlayout() ['leaf', 1000] " 两个水平分割的窗口 :echo winlayout() ['col', [['leaf', 1000], ['leaf', 1001]]] " 第二个标签页,其中有三个水平分割的窗口,中间窗口有两 " 个垂直分割的窗口 :echo winlayout(2) ['col', [['leaf', 1002], ['row', [['leaf', 1003], ['leaf', 1001]]], ['leaf', 1000]]] 也可用作 method : GetTabnr()->winlayout() winline() winline() 返回数值,窗口光标所在的屏幕行,亦即,从窗口顶部起算的屏幕行 数。第一行返回 1。 如果光标移动,文件的视图会先更新,这可能会导致滚动。 winnr() winnr([{arg}]) 返回数值,当前窗口的编号。最上面的窗口的编号为 1。 弹出窗口返回零。 可选参数 {arg} 支持以下值: $ 返回最后一个窗口的编号 (即窗口的总数)。 # 返回最近访问的窗口号 ( CTRL-W_p 到的地 方)。如果没有上次窗口或它在另一个标签页中,返 回 0。 {N}j 当前窗口之下第 N 个窗口的窗口号 ( CTRL-W_j 到 的地方)。 {N}k 当前窗口之上第 N 个窗口的窗口号 ( CTRL-W_k 到 的地方)。 {N}h 当前窗口之左第 N 个窗口的窗口号 ( CTRL-W_h 到 的地方)。 {N}l 当前窗口之右第 N 个窗口的窗口号 ( CTRL-W_l 到 的地方)。 此编号可用于 CTRL-W_w 和 ":wincmd w" :wincmd 。 另见 tabpagewinnr()win_getid() 。 示例: let window_count = winnr('$') let prev_window = winnr('#') let wnum = winnr('3k') 也可用作 method : GetWinval()->winnr() winrestcmd() winrestcmd() 返回 :resize 命令序列,该序列应该能够恢复当前窗口的大小。只 有在没有窗口被打开或关闭且当前窗口和标签页都没有改变的时候才能 正确工作。 示例: :let cmd = winrestcmd() :call MessWithWindowSizes() :exe cmd winrestview() winrestview({dict}) 使用 winsaveview() 返回的 Dictionary 来恢复当前窗口的视 图。 注意 {dict} 不需要包含所有的 winsaveview() 返回的值。如果不 提供某值,则不恢复相应的设置。所以可以用: :call winrestview({'curswant': 4}) 它只会设置光标的 curswant 值 (垂直移动的光标想移动到的列) 到第 5 列 (是的,第 5 列),而其它设置保持不变。这可用于手动设置光标 位置。 如果你改变了其中的值,结果无法预测。如果窗口大小改变了,结果不 会完全一样。 也可用作 method : GetView()->winrestview() winsaveview() winsaveview() 返回 Dictionary ,包含当前窗口的信息,这些信息可用来恢复视 图。 winrestview() 进行视图的恢复。 可用于定义在缓冲区里跳转后想恢复的原来视图的映射。 这里不保存折叠的信息。用 'foldenable' 选项来暂时关闭折叠功能, 这样在移动时折叠就不会打开。这可能有副作用。 返回值包括: lnum 光标行号 col 光标列号 (注意: 首列为零,和 getpos() 不同) coladd 'virtualedit' 使用的光标列偏移 curswant 垂直移动使用的列 topline 窗口的第一行 topfill 填充行,只用于比较模式 leftcol 显示的第一列;只用于 'wrap' 关闭时 skipcol 跳过的列数 注意 这里不保存任何选项值。 winwidth({nr}) winwidth() 返回数值,窗口 {nr} 的宽度。 {nr} 可以是窗口号或 window-ID 。 如果 {nr} 为零,返回当前窗口的宽度。如果窗口 {nr} 不存在,返回 -1。 存在的窗口的宽度至少为零。 示例: :echo "当前窗口有 " . winwidth(0) . " 列。" :if winwidth(0) <= 50 : 50 wincmd | :endif 要得到终端或屏幕大小,可见 'columns' 选项。 也可用作 method : GetWinid()->winwidth() wordcount() wordcount() 返回字典,包含当前缓冲区的字节/字符/单词的统计。和 g_CTRL-G 包含的信息相同。 返回值包括: bytes 缓冲区的字节数 chars 缓冲区的字符数 words 缓冲区的单词数 cursor_bytes 光标前的字节数 (不在可视模式下) cursor_chars 光标前的字符数 (不在可视模式下) cursor_words 光标前的单词数 (不在可视模式下) visual_bytes 可视选择的字节数 (只在可视模式下) visual_chars 可视选择的字符数 (只在可视模式下) visual_words 可视选择的单词数 (只在可视模式下) writefile() writefile({object}, {fname} [, {flags}]) {object}List 时,把列表写到文件 {fname} 里。列表的项目间 以 NL 分隔。每个列表项必须是字符串或数值。 如果 {flags} 包含 "b",使用二进制模式: 最后一个列表项目之后没 有 NL,最后的空项目使得文件的末行以 NL 结尾。 {object}Blob 时,把这些字节不加修改地写到文件 {fname} 里。 如果 {flags} 包含 "a",使用附加模式,写入行附加到文件之后: :call writefile(["foo"], "event.log", "a") :call writefile(["bar"], "event.log", "a") 如果 {flags} 包含 "s",写入文件后调用 fsync()。在可能的情况下 它把文件刷新到盘上。这会多花些时间,但避免系统崩溃时丢失文件的 风险。 如果 {flags} 不包含 "S" 或 "s",'fsync' 选项置位时调用 fsync()。 如果 {flags} 包含 "S",无论 'fsync' 选项是否置位都不调用 fsync()。 所有的 NL 字符被 NUL 字符代替。 CR 字符的插入需要在把 {list} 传递给 writefile() 之前先做好。 如果可能,覆盖已有的文件。 如果写入失败,返回 -1,否则返回 0。如果文件不能建立或者写入失 败,会有错误信息。 另见 readfile() 。 要按字节复制文件: :let fl = readfile("foo", "b") :call writefile(fl, "foocopy", "b") 也可用作 method : GetText()->writefile("thefile") xor({expr}, {expr}) xor() 对两个参数进行按位异或。参数须转换为数值。列表、字典或浮点数参 数会报错。 示例: :let bits = xor(bits, 0x80) 也可用作 method : :let bits = bits->xor(0x80) feature-list 有三种类型的特性: 1. 只有在 Vim 编译时加入才会支持的特性 +feature-list 。例如: :if has("cindent") 2. 只有特定条件满足才会支持的特性。例如: :if has("gui_running") has-patch 3. 特定版本之后或在特定版本上并包含了特定补丁。"patch-7.4.248" 特性意味着 Vim 版本是 7.5 或之后,或 7.4 并包含了补丁 248。例如: :if has("patch-7.4.248") 注意 包含了补丁 249 但不包含补丁 248 是可能的,但这只适用于 cherrypick 补 丁的情况。 注意 此形式只可用于 7.4.237 补丁或之后版本,在这之前,你需要检查补丁号和 v:version。例如 (确定是 version 6.2.148 或更新的版本): :if v:version > 602 || v:version == 602 && has("patch148") 揭示: 要知道 Vim 是否支持文件名中的反斜杠 (MS-Windows), 用: `if exists('+shellslash')` acl 编译时加入了 ACL 支持。 all_builtin_terms 编译时打开了所有的内建终端。 amiga Vim 的 Amiga 版本。 arabic 编译时加入了阿拉伯语的支持。 Arabic 。 arp 编译时加入了 ARP 的支持。(Amiga)。 autocmd 编译时加入了自动命令的支持。(总为真) autochdir 编译时加入了 'autochdir' 的支持 autoservername 自动打开 clientserver balloon_eval 编译时加入了 balloon-eval 的支持。 balloon_multiline GUI 支持多行气泡。 beos Vim 的 BeOS 版本。 browse 编译时加入了 :browse 的支持。使 browse() 可以工作。 browsefilter 编译时加入了 browsefilter 的支持。 bsd 编译时使用了 BSD 家族的 OS (除了 macOS)。 builtin_terms 编译时打开了一些内建终端。 byte_offset 编译时加入了 'statusline' 中对 'o' 的支持。 channel 编译时加入了 channeljob 的支持 cindent 编译时加入了 'cindent' 的支持。 clientserver 编译时加入了远程调用的支持。 clientserver 。 clipboard 编译时加入了 'clipboard' 的支持。 clipboard_working 编译时加入了 'clipboard' 的支持且可用。 cmdline_compl 编译时加入了 cmdline-completion 的支持。 cmdline_hist 编译时加入了 cmdline-history 的支持。 cmdline_info 编译时加入了 'showcmd''ruler' 的支持。 comments 编译时加入了 'comments' 的支持。 compatible 编译时确保和 Vi 非常兼容。 conpty ConPTY 可用的平台。 cryptv 编译时加入了加密的支持。 encryption 。 cscope 编译时加入了 cscope 的支持。 cursorbind 编译时加入了 'cursorbind' 的支持 (总为真) debug 编译时定义了 "DEBUG"。 dialog_con 编译时加入了控制台对话框的支持。 dialog_gui 编译时加入了 GUI 对话框的支持。 diff 编译时加入了 vimdiff'diff' 的支持。 digraphs 编译时加入了二合字母的支持。 directx 编译时加入了 DirectX 和 'renderoptions' 的支持。 dnd 编译时加入了 "~ 寄存器的支持 quote_~ 。 ebcdic 在使用 ebcdic 字符集的机器上编译。 emacs_tags 编译时加入了 Emcac 标签的支持。 eval 编译时加入了表达式计算的支持。当然总要打开啦! ex_extra +ex_extra (总为真) extra_search 编译时加入了 'incsearch''hlsearch' 的支持。 farsi 删除了波斯语的支持 farsi 。 file_in_path 编译时加入了 gf<cfile> 的支持。 filterpipe 'shelltemp' 关闭时,外壳读/写/过滤命令使用管道 find_in_path 编译时加入了头文件搜索 +find_in_path 的支持。 float 编译时加入了 Float 的支持。 fname_case 文件名大小写敏感 (在 Amiga 和 Windows 本特性不存在)。 folding 编译时加入了 folding 的支持。 footer 编译时加入了 GUI 信息页脚的支持。 gui-footer fork 编译时决定使用 fork()/exec() 而不是 system()。 gettext 编译时加入了信息翻译 multi-lang 。 gui 编译时加入了 GUI 的支持。 gui_athena 编译时加入了 Athena GUI。 gui_gnome 编译时加入了 Gnome 支持 (同时也定义了 gui_gtk)。 gui_gtk 编译时加入了 GTK+ GUI (任何版本)。 gui_gtk2 编译时加入了 GTK+ 2 GUI (同时也定义了 gui_gtk)。 gui_gtk3 编译时加入了 GTK+ 3 GUI (同时也定义了 gui_gtk)。 gui_haiku 编译时加入了 Haiku GUI。 gui_mac 编译时加入了 Macintosh GUI。 gui_motif 编译时加入了 Motif GUI。 gui_photon 编译时加入了 Photon GUI。 gui_running Vim 在 GUI 上运行,或者 GUI 将很快启动。 gui_win32 编译时加入了 MS-Windows Win32 GUI。 gui_win32s 同上,使用了 Win32s 系统 (Windows 3.1) haiku Vim 的 Haiku 版本。 hangul_input 编译时加入了韩语输入的支持。 hangul hpux Vim 的 HP-UX 版本。 iconv 可以使用 iconv() 进行转换。 insert_expand 编译时加入了插入模式中 CTRL-X 扩展命令的支持。(总为真) job 编译时加入了 channeljob 的支持 ipv6 编译时加入了 channel 的 IPv6 网络支持 jumplist 编译时加入了 jumplist 的支持。 keymap 编译时加入了 'keymap' 的支持。 lambda 编译时加入了 lambda 的支持。 langmap 编译时加入了 'langmap' 的支持。 libcall 编译时加入了 libcall() 的支持。 linebreak 编译时加入了 'linebreak''breakat''showbreak''breakindent' 的支持。 linux Vim 的 Linux 版本。 lispindent 编译时加入了 lisp 缩进的支持。 listcmds 编译时加入了缓冲区列表 :files 和参数列表 arglist 的命令。 localmap 编译时加入了局部映射和缩写。 :map-local lua 编译时加入了 Lua 接口 Lua 。 mac Vim 的 Macintosh 版本,参照 osx macunix 同 osxdarwin menu 编译时加入了 :menu 的支持。 mksession 编译时加入了 :mksession 的支持。 modify_fname 编译时加入了文件名的修饰符支持。 filename-modifiers (总为真) mouse 编译时加入了鼠标的支持。 mouse_dec 编译时加入了 Dec 终端的鼠标支持。 mouse_gpm 编译时加入了 gpm (Linux 控制台鼠标) 的支持。 mouse_gpm_enabled GPM 鼠标可用 mouse_netterm 编译时加入了 netterm 的鼠标支持。 mouse_pterm 编译时加入了 qnx 的鼠标支持。 mouse_sysmouse 编译时加入了 sysmouse 支持 (*BSD 控制台鼠标) mouse_sgr 编译时加入了 sgr 的鼠标支持。 mouse_urxvt 编译时加入了 urxvt 的鼠标支持。 mouse_xterm 编译时加入了 xterm 的鼠标支持。 mouseshape 编译时加入了 'mouseshape' 的支持。 multi_byte 编译时加入了 'encoding' 的支持 (总为真) multi_byte_encoding 'encoding' 设为某个多字节的编码。 multi_byte_ime 编译时加入了 IME 输入方法的支持。 multi_lang 编译时加入了多语言的支持。 mzscheme 编译时加入了 MzScheme 接口支持 mzscheme 。 netbeans_enabled 编译时加入了 netbeans 的支持并且已连接上。 netbeans_intg 编译时加入了 netbeans 的支持。 num64 编译时加入了64 位 Number 的支持。 ole 编译时加入了 Win32 OLE automation 的支持。 osx 为 macOS 编译,参照 mac osxdarwin 为 macOS 编译,带有 mac-darwin-feature packages 编译时加入了 packages 的支持。 path_extra 编译时加入了 'path''tags' 上下搜索的支持。 perl 编译时加入了 Perl 接口。 persistent_undo 编译时加入了持久化撤销历史的支持。 postscript 编译时加入了 PostScript 文件打印的支持。 printer 编译时加入了 :hardcopy 的支持。 profile 编译时加入了 :profile 的支持。 python Python 2.x 接口可用。 has-python python_compiled 编译时加入了 Python 2.x 接口。 has-python python_dynamic Python 2.x 接口已动态载入。 has-python python3 Python 3.x 接口可用。 has-python python3_compiled 编译时加入了 Python 3.x 接口。 has-python python3_dynamic Python 3.x 接口已动态载入。 has-python pythonx Python 2.x 和/或 3.x 接口可用。 pythonx qnx Vim 的 QNX 版本。 quickfix 编译时加入了 quickfix 的支持。 reltime 编译时加入了 reltime() 的支持。 rightleft 编译时加入了 'rightleft' 的支持。 ruby 编译时加入了 Ruby 接口 ruby 。 scrollbind 编译时加入了 'scrollbind' 的支持。(总为真) showcmd 编译时加入了 'showcmd' 的支持。 signs 编译时加入了 :sign 的支持。 smartindent 编译时加入了 'smartindent' 的支持。 sound 编译时加入了声音的支持,例如 sound_playevent() spell 编译时加入了拼写检查的支持 spell 。 startuptime 编译时加入了 --startuptime 支持。 statusline 编译时加入了 'statusline''rulerformat' 还有 'titlestring''iconstring' 的特殊格式的支持。 sun Vim 的 SunOS 版本。 sun_workshop 删除了 Sun workshop 的支持。 syntax 编译时加入了语法高亮的支持 syntax 。 syntax_items 当前缓冲区有激活的语法高亮项目。 system 编译时决定使用 system() 而不是 fork()/exec()。 tag_binary 编译时加入了标签文件的二分搜索 tag-binary-search 。 tag_old_static 删除了老的静态标签的支持,见 tag-old-static 。 tcl 编译时加入了 Tcl 接口。 termguicolors 编译时加入了终端的真彩支持。 terminal 编译时加入 terminal 的支持。 terminfo 编译时决定使用 terminfo 而不是 termcap。 termresponse 编译时加入了 t_RVv:termresponse 的支持。 textobjects 编译时加入了 text-objects 的支持。 textprop 编译时加入了 text-properties 的支持。 tgetent 编译时加入了 tgetent 的支持,可以使用外部 termcap 或 terminfo 文件。 timers 编译时加入了 timer_start() 支持。 title 编译时加入了窗口标题的支持。 'title' 。 toolbar 编译时加入了 gui-toolbar 的支持。 ttyin 输入是终端 (tty) ttyout 输出是终端 (tty) unix Vim 的 Unix 版本。 +unix unnamedplus 编译时加入了 'clipboard' 对 "unnamedplus" 的支持。 user_commands 用户定义命令支持。(总为真) vartabs 编译时加入了可变制表位的支持 'vartabstop' 。 vcon Win32: 有虚拟终端支持,可用 'termguicolors'。另见 +vtp 。 vertsplit 编译时加入了垂直分割窗口的支持 :vsplit 。(总为真) vim_starting 如果在启动载入脚本的阶段则为真。 startup vim_starting viminfo 编译时加入了 viminfo 的支持。 vimscript-1 编译时加入了 Vim 脚本版本 1 的支持 vimscript-2 编译时加入了 Vim 脚本版本 2 的支持 vimscript-3 编译时加入了 Vim 脚本版本 3 的支持 virtualedit 编译时加入了 'virtualedit' 选项支持。(总为真) visual 编译时加入了可视模式的支持。(总为真) visualextra 编译时加入了附加的可视模式命令支持。(总为真) blockwise-operators 。 vms Vim 的 VMS 版本。 vreplace 编译时加入了 gRgr 命令支持。(总为真) vtp 编译时加入了 vcon 支持 +vtp (检查 vcon 可知当前控制 台是否支持)。 wildignore 编译时加入了 'wildignore' 选项支持。 wildmenu 编译时加入了 'wildmenu' 选项支持。 win16 旧版本 MS-Windows 3.1 (总为假) win32 Vim 的 Win32 版本。(MS-Windows 95 及其后的 32 或 64 位 版本)。 win32unix Vim 的 Win32 版本。使用 Unix 文件命名 (Cygwin) win64 Vim 的 Win64 版本。(MS-Windows 64 位)。 win95 支持 MS-Windows 95/98/ME 的 Win32 版本 (总为假) winaltkeys 编译时加入了 'winaltkeys' 选项。 windows 编译时加入了多窗口的支持。(总为真) writebackup 编译时决定缺省打开 'writebackup'。 xfontset 编译时加入了 X 字体集 的支持。 xfontset 。 xim 编译时加入了 X 输入法 的支持。 xim 。 xpm 编译时加入了 pixmap 的支持。 xpm_w32 编译时加入了 Win32 的 pixmap 的支持。(只为后向兼容而 保留,用 "xpm" 代替) xsmp 编译时加入了 X 会话管理 的支持。 xsmp_interact 编译时加入了交互的 X 会话管理 的支持。 xterm_clipboard 编译时加入了 xterm 剪贴板的支持。 xterm_save 编译时加入了保存和恢复 xterm 屏幕的支持。 x11 编译时加入了 X11 的支持。 string-match 字符串里的模式匹配 pattern 说明的正规表达式通常用于寻找缓冲区行的匹配。如果匹配用来在字符串里寻 找匹配,几乎所有的功能都相同。唯一的区别是,字符串是作为单行处理的。如果字符串 里包含了 "\n" 字符,它并不看作是模式里的换行。它可以匹配模式里的 "\n",甚至于 "."。示例: :let a = "aaaa\nxxxx" :echo matchstr(a, "..\n..") aa xx :echo matchstr(a, "a.x") a x 不要忘记 "^" 只会在字符串的第一个字符匹配,而 "$" 在字符串的最后一个字符匹配。 它们不会匹配 "\n" 之后和之前的位置。

5. 定义函数 user-functions

可以定义新的函数。调用的方式就像内建函数一样。函数执行一系列 Ex 命令。普通模式 下的命令可以用 :normal 命令执行。 此小节介绍的是老式函数。关于执行快很多、支持类型检查还有更多优点的 Vim9 函数, 参见 vim9.txt 。 函数名须以大写字母开始,以免和内建函数引起混淆。要避免在不同脚本使用相同的名 字,避免显见的或者过短的名字。一个好习惯是使用脚本名字作为函数名字的开头,比如 "HTMLcolor()"。 也可以使用花括号,见 curly-braces-namesautoload 机制可用于在调用时才提供 函数的定义。 local-function 局部于脚本的函数必须以 "s:" 开始。局部于脚本的函数只能在同一脚本和脚本中定义的 函数、用户命令和自动命令里调用。也可以在脚本定义的映射里调用该函数,但必须使用 <SID> 而不是 "s:",如果映射会在脚本之外被扩展的话。 只有局部于脚本的函数,没有局部于缓冲区或局部于窗口的函数。 :fu :function E128 E129 E123 :fu[nction] 列出所有函数和它们的参数。 :fu[nction] {name} 列出 {name} 命名的函数。 {name} 也可以是 Funcref 类型的 Dictionary 项目: :function dict.init :fu[nction] /{pattern} 列出名字匹配 {pattern} 的函数。 列出所有以 "File" 结束的函数的例子: :function /File$ :function-verbose 如果 'verbose' 非零,列出函数的同时也显示它上次定义的位置。例如: :verbose function SetFileTypeSH function SetFileTypeSH(name) Last set from /usr/share/vim/vim-7.0/filetype.vim :verbose-cmd 有更多信息。 E124 E125 E853 E884 :fu[nction][!] {name}([arguments]) [range] [abort] [dict] [closure] 定义 {name} 命名的新函数。函数体在之后的行给出,直到匹 配的 :endfunction 为止。 名字必须由字母数字和 '_' 字符组成,而且必须以大写字母 或者 "s:" 开头 (见上)。注意 "b:" 或 "g:" 是不允许的。( 从补丁 7.4.260 开始,如果函数名中有冒号,给出 E884, 如 "foo:bar()"。此补丁之前不报错)。 {name} 也可以是 Funcref 类型的 Dictionary 项目: :function dict.init(arg) "dict" 必须是一个已经存在的字典。如果还不存在,项目 "init" 被加入此字典。否则必须提供 [!] 以覆盖已经存在的 函数。返回指向一个编号函数的 Funcref 。该函数只能通过 Funcref 引用,没有引用指向它时,该函数会被删除。 E127 E122 如果同名的函数已经存在而且没有使用 [!],给出错误信息。 有一个例外: 再次执行脚本时,该脚本中之前定义过的函数会 被悄然替代。 如果给出 [!],已有的函数被悄然替代。如果该函数正在执行 期间除外。此时,这是一个错误。 备注: 小心使用 !。如果不小心,可能会意外地替代已有的函 数。这很难调试。 备注: Vim9 脚本里局部于脚本的函数不能被删除或重定义。 {arguments} 参见 function-argument :func-range a:firstline a:lastline 如果给出 [range] 参数,则该函数自己能理解并处理行范 围。该范围通过 "a:firstline" 和 "a:lastline" 定义。如 果没有 [range],":{range}call" 会在该范围的每一行分别 执行该函数,每次光标都定位在处理行的行首。见 function-range-example 。 就像所有的 Ex 命令一样,光标仍然会被移动到范围的首行。 :func-abort 如果给出 [abort] 参数,该函数在遇到错误时立即中止。 :func-dict 如果给出 [dict] 参数,该函数必须通过 Dictionary 的项 目才能调用。局部变量 "self" 这时设为该字典。见 Dictionary-function :func-closure E932 加入 [closure] 参数时,函数可以访问外部作用域的变量和 参数。通常这被称为闭包。此例中 Bar() 使用 Foo() 作用 域的 "x"。即使 Foo() 返回后仍被引用: :function! Foo() : let x = 0 : function! Bar() closure : let x += 1 : return x : endfunction : return funcref('Bar') :endfunction :let F = Foo() :echo F() 1 :echo F() 2 :echo F() 3 function-search-undo 最近使用的搜索模式和重做命令 "." 不会受到函数的影响。 这也意味着 :nohlsearch 的效果在函数返回时会被撤销。 :endf :endfunction E126 E193 W22 :endf[unction] 结束函数定义。最好单起一行,没有 [argument][argument] 可以是: | 命令 下面执行的命令 \n 命令 下面执行的命令 " 注释 总是忽略 其它 忽略,如果 'verbose' 非零给出 警告 对后续命令的支持是 Vim 8.0.0654 加入的,之前任何参数都 被悄悄地忽略。 要在 :execute 命令里定义函数,用换行符而不是 :bar : :exe "func Foo()\necho 'foo'\nendfunc" :delf :delfunction E130 E131 E933 :delf[unction][!] {name} 删除 {name} 命名的函数。 {name} 也可以是 Funcref 类型的 Dictionary 项目: :delfunc dict.init 会删除 "dict" 的 "init" 项目。如果没有更多指向它的引 用,该函数被删除。 用了 ! 后,即使函数不存在也不报错。 :retu :return E133 :retu[rn] [expr] 从函数返回。如果给出 "[expr]",计算该表达式的结果成为 函数的返回值。如果没有给出 "[expr]",返回 0。 如果函数退出时没有显式的调用 ":return",返回 0。 注意 没有不可到达行的检查,因而,如果有命令在 ":return" 之后,不会给出警告。 如果 ":return" 在 :try 之后使用但在匹配的 :finally (如果有的话) 之前的话,":finally" 之后直到匹配的 :endtry 的命令会先执行。该过程反复应用于所有函数内的 嵌套 ":try" 块。在最外层 ":endtry" 结束之后才真正返 回。 function-argument a:var 参数的定义只要给出它的名字。在函数里,可以使用 "a:name" 来访问 ("a:" 代表参数 (argument))。 a:0 a:1 a:000 E740 ... 可以给出不超过 20 个参数,以逗号分隔。最后,可以给出参数 "...",意味着可以有更 多的参数。在函数里,可以通过 "a:1"、"a:2" 等等访问它们。"a:0" 设为这些附加参数 的数目 (可以为 0)。"a:000" 设为包含这些参数的 List注意 "a:1" 等同于 "a:000[0]"。 E742 a: 作用域和其中的变量不能修改,它们是固定的。不过,如果使用了复合类型,例如 ListDictionary ,可以改变它们的内容。这样就可以传递给函数一个 List , 让该函数在里面增加项目。如果要确保函数不能修改 ListDictionary ,用 :lockvar 。 可以定义没有参数的函数。但你这时仍然需要提供 ()。 可以在函数体里定义别的函数。 optional-function-argument 可以提供位置命名参数的缺省值。这使得函数调用时它们成为可选参数。位置参数如果在 调用时不指定,则使用缺省表达式来初始化。 只用于 :function:def 声明的函数,而不适用于匿名表达式 expr-lambda 。 示例: function Something(key, value = 10) echo a:key .. ": " .. a:value endfunction call Something('empty') "empty: 10" call Something('key', 20) "key: 20" 参数的缺省表达式在函数调用时而非定义时进行计算。这样就可用函数定义时非法的表达 式。该表达式也只在调用中未指定参数时才进行计算。 none-function_argument v:none 可用来指示参数使用缺省表达式。注意 这意味着如果有缺省表达式,参数不接 受 v:none 作为其正常值传递。 示例: function Something(a = 10, b = 20, c = 30) endfunction call Something(1, v:none, 3) " b = 20 E989 带缺省表达式的可选参数必须在任何必选参数之后出现。"..." 可在所有可选命名参数之 后使用。 出现在后面的参数的缺省可引用在它之前的参数,反之不可以。就像所有参数一样,必须 使用 "a:" 前缀。 合法的例子: :function Okay(mandatory, optional = a:mandatory) :endfunction 合法的例子: :function NoGood(first = a:second, second = 10) :endfunction 如果不使用 "...",实际给出的参数数目必须至少等于必选参数的数目。如果使用 "...",参数的数目可以多于必选和可选参数的总数。 local-variables 在函数里,可以使用局部变量。它们在函数返回时就会消失。全局变量的访问需要通过 "g:"。 例如: :function Table(title, ...) : echohl Title : echo a:title : echohl None : echo a:0 . " items:" : for s in a:000 : echon ' ' . s : endfor :endfunction 该函数这时可以这样调用: call Table("Table", "line1", "line2") call Table("Empty Table") 要返回多于一个值,返回一个 List : :function Compute(n1, n2) : if a:n2 == 0 : return ["fail", 0] : endif : return ["ok", a:n1 / a:n2] :endfunction 该函数这时可以这样调用: :let [success, div] = Compute(102, 6) :if success == "ok" : echo div :endif :cal :call E107 E117 :[range]cal[l] {name}([arguments]) 调用函数。函数名和参数通过 :function 指定。可以使用不超过 20 个参数。忽略返回值。 如果没有给出范围而函数又接受范围,该函数被调用一次。如果给出范 围,光标在执行函数前定位在该范围的第一行的开始。 如果给出范围但函数自己不能处理之,该函数在范围里的每一行分别执 行。光标定位在每个处理行的第一列。光标留在最后一行 (但可能被最 后一个函数调用移动)。每一行上,参数被重新计算。所以这是可以的: function-range-example :function Mynumber(arg) : echo line(".") . " " . a:arg :endfunction :1,5call Mynumber(getline(".")) "a:firstline" 和 "a:lastline" 总是有定义的。它们可以用来在范围 的开始或结束处进行一些不同的处理。 能处理范围本身的函数示例: :function Cont() range : execute (a:firstline + 1) . "," . a:lastline . 's/^/\t\\ ' :endfunction :4,8call Cont() 该函数在范围里的每行开头插入续行符 "\",除了第一行以外。 如果函数返回复合值,该值可被进一步解除参照 (译者注: 调用其上的 方法),但该范围不能被继续使用。例如: :4,8call GetDict().method() 这里 GetDict() 得到范围值,method() 不会。 E132 用户函数的递归调用受到 'maxfuncdepth' 选项的限制。 也可以使用 :eval 。不支持范围,但支持方法的链式调用,例如: eval GetList()->Filter()->append('$') 函数也可以在表达式计算的一部分或作为方法调用: let x = GetList() let y = GetList()->Filter() 自 动 载 入 函 数 autoload-functions 如果使用很多或者很大的函数,可以在需要使用它们的时候才自动提供其定义。有两个方 法: 用自动命令,还有用 'runtimepath' 里的 "autoload" 目录。 使用自动命令 用户手册 41.14 一节有介绍。 自动命令可用于很长的 Vim 脚本的插件。你可以定义自动命令然后用 :finish 快速退 出脚本。这使得 Vim 启动快得多。这时,自动命令应该再次载入相同的文件,并设置变 量使得 :finish 命令被跳过。 使用 FuncUndefined 自动命令事件,它需要一个能匹配等待定义的函数的模式。例如: :au FuncUndefined BufNet* source ~/vim/bufnetfuncs.vim 文件 "~/vim/bufnetfuncs.vim" 这时应该定义 "BufNet" 开始的函数。另见 FuncUndefined使用 autoload 脚本 autoload E746 用户手册 41.15 一节有介绍。 在 "autoload" 目录里定义脚本更简单,但需要使用准确的文件名。能够自动载入的函数 的名字形如: :call filename#funcname() 这些函数总是全局的,在 Vim9 脚本中要用 "g:": :call g:filename#funcname() 这样的函数如果调用时还没有定义,Vim 在 'runtimepath' 里的 "autoload" 目录搜索 脚本文件 "filename.vim"。例如 "~/.vim/autoload/filename.vim"。该文件这时应该这 样定义函数: function filename#funcname() echo "Done!" endfunction 文件名和函数的 # 之前的名字必须完全匹配,而定义的函数名也必须和调用时使用的形 式完全一致。在 Vim9 脚本中必须要用 "g:" 前缀: function g:filename#funcname() 或对已编译函数而言: def g:filename#funcname() 可以使用子目录。函数名每个 # 相当于路径分隔符。这样,调用函数: :call foo#bar#func() 的时候,Vim 寻找 'runtimepath' 里的文件 "autoload/foo/bar.vim"。 也适用于读取还没有设置的变量: :let l = foo#bar#lvar 不过,如果 autoload 脚本已经载入,不会为未知的变量再次载入该脚本。 给这样的变量赋值并没有什么特别。这可以用于在载入 autoload 脚本之前给它传递一些 设置: :let foo#bar#toggle = 1 :call foo#bar#func() 注意 如果你不小心调用了应该在 autoload 脚本里定义,但该脚本实际没有定义的函数 时,会得到函数消失的错误信息。修正 autoload 脚本后它不会自动重新载入。需要重启 Vim 或手动载入该脚本。 还有,注意 如果你有两个脚本文件,不能在使用的函数定义之前同时从一个文件里调用 另一个文件里的函数并且从那个文件里调用这个文件的函数。 避免在顶层使用自动载入功能。 提示: 如果你发布很多脚本,可以用 vimball 工具把它们捆绑在一起。另请阅读用户 手册 distribute-script

6. 花括号名字 curly-braces-names

多数使用变量的地方可以改用 "花括号名字" 变量。和常规的变量名类似,但可以包含一 到多个花括号 {} 包围的表达式,形如: my_{adjective}_variable 如果 Vim 遇到这种情形,它会计算花括号内的表达式,把结果放在表达式所在的位置, 然后重新解释整个字符串为完整的变量名。所以在上例中,如果变量 "adjective" 设为 "noisy",那么引用的将是 "my_noisy_variable"。如果 "adjective" 设为 "quiet",那 么引用的将是 "my_quiet_variable"。 一个这种形式的应用是建立一系列变量,由一个选项管理。比如,语句 echo my_{&background}_message 会显示 "my_dark_message" 或者 "my_light_message" 的内容,取决于 'background' 的当前值。 你可以使用多个花括号对: echo my_{adverb}_{adjective}_message ..甚至嵌套使用: echo my_{ad{end_of_word}}_message 其中 "end_of_word" 可以是 "verb" 或者 "jective"。 不过,花括号里的表达式必须计算出合法的单个变量名,比如,这不行: :let foo='a + b' :echo c{foo}d .. 因为扩展的结果是 "ca + bd",这不是合法的变量名。 curly-braces-function-names 类似的,你可以调用和定义计算的出的函数名。比如: :let func_end='whizz' :call my_func_{func_end}(parameter) 会调用函数 "my_func_whizz(parameter)"。 这样 行: :let i = 3 :let @{i} = '' " 报错 :echo @{i} " 报错

7. 命令 expression-commands

备注: Vim9 脚本中 :let 用于声明变量而不是赋值。赋值没有 :let 命令部分。 vim9-declaration :let {var-name} = {expr1} :let E18 设置内部变量 {var-name} 为表达式 {expr1} 的计算结果。 该变量也会得到 {expr} 的类型。如果 {var-name} 不存在, 它会被创立。 :let {var-name}[{idx}] = {expr1} E689 设置列表项目为表达式 {expr1} 的返回值。{var-name} 必须 引用列表而 {idx} 必须是该列表里合法的索引值。嵌套的列 表可以重复使用索引。 不能用于给列表 List 增加项目。 不能用来给字符串改变个别字节。为此你可以这么做: :let var = var[0:2] . 'X' . var[4:] 如果 {var-name}Blob{idx} 可以等于 blob 的长 度,此时附加一个字节。 E711 E719 :let {var-name}[{idx1}:{idx2}] = {expr1} E708 E709 E710 设置 List 的一系列项目为表达式 {expr1} 的返回值,后 者必须是正确数量项目的列表。 {idx1} 可以省略,这时以零代替。 {idx2} 可以省略,这时意味着到列表尾部。 如果选择的项目范围部分越过列表的尾部,会加入新的项目。 :let+= :let-= :letstar= :let/= :let%= :let.= :let..= E734 E985 :let {var} += {expr1} 类似于 ":let {var} = {var} + {expr1}"。 :let {var} -= {expr1} 类似于 ":let {var} = {var} - {expr1}"。 :let {var} *= {expr1} 类似于 ":let {var} = {var} * {expr1}"。 :let {var} /= {expr1} 类似于 ":let {var} = {var} / {expr1}"。 :let {var} %= {expr1} 类似于 ":let {var} = {var} % {expr1}"。 :let {var} .= {expr1} 类似于 ":let {var} = {var} . {expr1}"。 :let {var} ..= {expr1} 类似于 ":let {var} = {var} .. {expr1}"。 如果 {var} 还没有设置或者 {var}{expr1} 的类型不符 合操作符的要求,失败。 Vim 脚本版本 2 或之后不支持 .= ,见 vimscript-version 。 :let ${env-name} = {expr1} :let-environment :let-$ 设置环境变量 {env-name} 为表达式 {expr1} 的计算结果。 它总是字符串型。 在有的系统中使环境变量为空会把它删除。很多系统不区别不 置位的环境变量和空的环境变量。 :let ${env-name} .= {expr1}{expr1} 附加到环境变量 {env-name} 之后。如果该环境 变量还不存在,相当于 "="。 :let @{reg-name} = {expr1} :let-register :let-@ 把表达式 {expr1} 的计算结果写到寄存器 {reg-name} 里。 {reg-name} 必须是单个字符,而且是一个可以写入的寄存器 (见 registers )。"@@" 可以用来访问无名寄存器,而 "@/" 设置搜索模式。 如果 {expr1} 的结果以 <CR><NL> 结束,该寄存器会成 为面向行类型,不然,它会成为面向字符类型。 这可以用来清除最近的搜索模式: :let @/ = "" 这和搜索空字符串不同,后者会在任何地方得到匹配。 :let @{reg-name} .= {expr1}{expr1} 附加到寄存器 {reg-name} 之后。如果寄存器为 空,相当于把它设为 {expr1} 的值。 :let &{option-name} = {expr1} :let-option :let-& 设置选项 {option-name} 为表达式 {expr1} 的计算结果。字 符串或数值类型的值总会被转化为选项需要的类型。 对于局部于窗口或者缓冲区的选项而言,这和 :set 命令的 效果相同: 局部值和全局值都被改变。 例如: :let &path = &path . ',/usr/local/include' 也可用于形如 t_xx 的终端代码。但只可用字母数字形式的名 字。例如: :let &t_k1 = "\<Esc>[234;" 如果代码还不存在,会新建一个终端键值,因此不会报错。 :let &{option-name} .= {expr1} 对字符串选项: 附加 {expr1} 到选项值之后。和 :set+= 不同,不会插入逗号。 :let &{option-name} += {expr1} :let &{option-name} -= {expr1} 对数值或布尔选项: 加减 {expr1}。 :let &l:{option-name} = {expr1} :let &l:{option-name} .= {expr1} :let &l:{option-name} += {expr1} :let &l:{option-name} -= {expr1} 同上,但只设置选项的局部值 (如果有的话)。和 :setlocal 类似。 :let &g:{option-name} = {expr1} :let &g:{option-name} .= {expr1} :let &g:{option-name} += {expr1} :let &g:{option-name} -= {expr1} 同上,但只设置选项的全局值 (如果有的话)。和 :setglobal 类似。 :let [{name1}, {name2}, ...] = {expr1} :let-unpack E687 E688 {expr1} 计算结果必须是 List 。该列表的第一项赋给 {name1},第二项给 {name2},依此类推。 命名的数量必须匹配 List 项目的数量。 每个名字必须是上面提到的 ":let" 命令的项目之一。 例如: :let [s, item] = GetItem(s) 细节: 先计算 {expr1},然后按顺序依次进行赋值。如果 {name2} 依赖于 {name1},该细节就有关系。例如: :let x = [0, 1] :let i = 0 :let [i, x[i]] = [1, 2] :echo x 结果是 [0, 2]。 :let [{name1}, {name2}, ...] .= {expr1} :let [{name1}, {name2}, ...] += {expr1} :let [{name1}, {name2}, ...] -= {expr1} 同上,但附加/加/减值到每个 List 项目。 :let [{name}, ..., ; {lastname}] = {expr1} E452 类似于上面的 :let-unpack ,但 List 可以包含比给出名 字的数量更多的项目。列表其余项目赋给 {lastname}。 如果没有余下的项目,{lastname} 设为空列表。 例如: :let [a, b; rest] = ["aval", "bval", 3, 4] :let [{name}, ..., ; {lastname}] .= {expr1} :let [{name}, ..., ; {lastname}] += {expr1} :let [{name}, ..., ; {lastname}] -= {expr1} 同上,但附加/加/减值到每个 List 项目。 :let=<< :let-heredoc E990 E991 E172 E221 :let {var-name} =<< [trim] {endmarker} text... text... {endmarker} 设置内部变量 {var-name} 为由 {endmarker} 字符串定界的 文本行的 List 。文本行视作 literal-string{endmarker} 不能包含空白。 {endmarker} 不能以小写字母开头。 末行必须以 {endmarker} 字符串结束,而不能有其它字符。 小心 {endmarker} 之后的空白! 如果不给出 "trim" 保留文本行中的空白字符。如果 {endmarker} 之前给出 "trim",则删除缩进,所以可以这 样: let text =<< trim END if ok echo 'done' endif END 结果是: ["if ok", " echo 'done'", "endif"] marker 必须和 "let" 对齐,此时从所有文本行中删除首行的 缩进。 具体地说: 和首个非空文本行引导缩进完全一致的所有输入行 的缩引导进会被删除。 和 let 之前的引导缩进完全一致的包含 {endmarker} 的行 的所有的引导缩进也会被删除。 注意 这里空格和制表是有区别的。 如果 {var-name} 还不存在,会被创建。 不能跟在其它命令后面,但后面可以跟注释。 要避免续行符的使用,考虑在 'cpoptions' 中加入 'C': set cpo+=C let var =<< END \ leading backslash END set cpo-=C 示例: let var1 =<< END Sample text 1 Sample text 2 Sample text 3 END let data =<< trim DATA 1 2 3 4 5 6 7 8 DATA E121 :let {var-name} .. 列出变量 {var-name} 的值。可以给出多个变量的名字。这里 识别特殊的名字包括: E738 g: 全局变量 b: 缓冲区的局部变量 w: 窗口的局部变量 t: 标签页的局部变量 s: 脚本的局部变量 l: 函数的局部变量 v: Vim 变量。 不适用于 Vim9 脚本。 vim9-declaration :let 列出所有变量的值。变量的类型在值之前给出: <空> 字符串 # 数值 * 函数引用 不适用于 Vim9 脚本。 vim9-declaration :unl[et][!] {name} ... :unlet :unl E108 E795 删除内部变量 {var-name}。可以给出多个变量的名字。它们 都被删除。该名字也可以是 ListDictionary 项目。 如果使用 [!],即使变量不存在也不会给出错误。 List 里可以删除一到多个项目: :unlet list[3] " remove fourth item :unlet list[3:] " remove fourth item to last Dictionary 里一次只能删除一个项目: :unlet dict['two'] :unlet dict.two 这对于清除全局和脚本局部变量很有用 (脚本结束时并不自动 删除这些变量)。函数局部变量在函数结束时是自动清除的。 :unl[et] ${env-name} ... :unlet-environment :unlet-$ 删除环境变量 {env-name}。 在一个 :unlet 命令里可以混合 {name} 和 ${env-name}。 不对不存在的变量报错,即使没有 ! 也是如此。 如果系统不支持删除环境变量,则将它清空。 :cons :const :cons[t] {var-name} = {expr1} :cons[t] [{name1}, {name2}, ...] = {expr1} :cons[t] [{name}, ..., ; {lastname}] = {expr1} :cons[t] {var-name} =<< [trim] {marker} text... text... {marker}:let 类似,但设置值后额外地给变量加锁。等价于 :let 之后立即用 :lockvar 给变量加锁,所以: :const x = 1 等价于: :let x = 1 :lockvar! x 注意: Vim9 脚本中 :const 的工作方式不同,可见 vim9-const 可用于保证变量之后不会被修改。如果值为列表或字典常量, 其中的项目也不能被修改: const ll = [1, 2, 3] let ll[1] = 5 " 报错! 嵌套引用不加锁: let lvar = ['a'] const lconst = [0, lvar] let lconst[0] = 2 " 报错! let lconst[1][0] = 'b' " OK E995 :const 不能用来修改变量: :let x = 1 :const x = 2 " Error! E996 注意 这里不能使用环境变量、选项值和寄存器值,因为它们 不能被锁定。 :cons[t] :cons[t] {var-name} 如果不给出参数或只给出 {var-name},等价于 :let 。 :lockv[ar][!] [depth] {name} ... :lockvar :lockv 给内部变量 {name} 加锁。加锁意味着不能再修改该变量 (直 到它被解锁为止)。 加锁的变量可以删除: :lockvar v :let v = 'asdf' " 失败! :unlet v " 没问题 E741 E940 如果试图修改加锁的变量,你会得到错误信息: "E741: Value is locked: {name}"。 如果试图加锁或解锁内建变量,会报错: "E940: Cannot lock or unlock variable {name}"。 给 ListDictionary 加锁时用到 [depth]。它决定加 锁到达的深度: 0 给变量 {name} 加锁,但其值可修改。 1 给 ListDictionary 自身加锁。不 能增加或者删除项目,但你可以修改它们的 值。 2 给这些值也加锁,不能修改项目。如果项目 是 ListDictionary ,不能增加或 删除其中项目,但仍然可以修改项目值。 3 同 2,但又适用于 List / Dictionary 中的 List / Dictionary 项目,更深 一层。 缺省的 [depth] 为 2,{name}ListDictionary 时,不能修改项目值。 [depth] 为 0 的示例: let mylist = [1, 2, 3] lockvar 0 mylist let mylist[0] = 77 " OK call add(mylist, 4] " OK let mylist = [7, 8, 9] " 出错! E743 要使用没有限制的深度,用 [!] 并省略 [depth]。不过,为 了捕获循环,设定最大深度为 100。 注意 如果两个变量引用同一个 List 而你锁住其中一个, 通过另一个变量来访问 List 也同时被锁住。 例如: :let l = [0, 1, 2, 3] :let cl = l :lockvar l :let cl[1] = 99 " won't work! 为了避免这一点,可以给列表建立备份。见 deepcopy() 。 :unlo[ckvar][!] [depth] {name} ... :unlockvar :unlo 给内部变量 {name} 解锁。和 :lockvar 刚好相反。 :if {expr1} :if :end :endif :en E171 E579 E580 :en[dif] 如果 {expr} 计算为非零,执行命令直到其后匹配的 ":else" 或者 ":endif" 为止。 从 Vim 版本 4.5 到 5.0,":if" 和 ":endif" 之间的 Ex 命 令被忽略。提供这两个命令只是为了后向兼容 (译者注,原文 如此),以方便未来的扩展。可以嵌套。注意 任何的 ":else" 或 ":elseif" 也被忽略,"else" 部分也一样不会执行。 利用这一点,你可以保持和旧版本的兼容: :if version >= 500 : 版本 5 专用的命令 :endif 为了找到 "endif",仍然需要分析命令。有时,旧版本的 Vim 不能识别新的命令。比如,":silent" 被识别为 ":substitute" 命令。这种情形可以用 ":execute" 来避 免: :if version >= 600 : execute "silent 1,$delete" :endif 注意: ":append" 和 ":insert" 命令在 ":if" 和 ":endif" 之间不能正常工作。 :else :el E581 E583 :el[se] 如果这之前的命令没有被执行,执行命令直到其后匹配的 ":else" 或 ":endif"。 :elseif :elsei E582 E584 :elsei[f] {expr1} ":else" ":if" 的缩写,而且无需另一个 ":endif"。 :wh[ile] {expr1} :while :endwhile :wh :endw E170 E585 E588 E733 :endw[hile] 只要 {expr1} 计算的结果非零,重复 ":while" 和 ":endwhile" 之间的命令。 如果发现循环里有命令出错,从 "endwhile" 之后继续执行。 例如: :let lnum = 1 :while lnum <= line("$") :call FixLine(lnum) :let lnum = lnum + 1 :endwhile 注意: ":append" 和 ":insert" 命令在 ":while" 和 ":for" 循环里不能正常工作。 :for {var} in {object} :for E690 E732 :endfo[r] :endfo :endfor 为每个 {object} 项目重复执行 ":for" 和 ":endfor" 之间 的命令。{object} 可以是 ListBlob 。变量 {var} 设为每个项目的值。如果循环里某个命令出错,从 "endfor" 之后继续执行。 在循环里修改 {object} 影响使用的项目。如果不希望如此, 构建一个备份: :for item in copy(mylist) 如果 {object}List 且没有备份,Vim 在为当前项目执 行命令前保存列表里下一个项目的引用。这样,删除当前项目 不会影响循环的继续。而删除任何后来的项目也会使循环跳过 它。这意味着下例可以工作 (一个效率低下的清空列表的方 法): for item in mylist call remove(mylist, 0) endfor 注意List 调整顺序 (例如用 sort() 或 reverse()) 可能会有意想不到的效果。 如果 {object}Blob ,Vim 总是先建立备份再循环。和 List 不同,对 Blob 的修改不影响循环。 :for [{var1}, {var2}, ...] in {listlist} :endfo[r] 和上面 ":for" 类似,但每个 {listlist} 项目必须是列表, 其中每个项目被依次赋予 {var1}{var2} 等。例如: :for [lnum, col] in [[1, 3], [2, 5], [3, 8]] :echo getline(lnum)[col] :endfor :continue :con E586 :con[tinue] 在 ":while" 或 ":for" 循环的内部,跳回循环开始的地方。 如果在循环内部的 :try 之后但在匹配的 :finally (如 果有的话) 之前,":finally" 之后,匹配的 :endtry 之前 的命令会被先执行。该过程反复应用于所有函数内的嵌套 ":try" 块。在最外层 ":endtry" 结束之后才跳回循环的开始 处。 :break :brea E587 :brea[k] 在 ":while" 或 ":for" 循环的内部,跳到相匹配的 ":endwhile" 或 ":endfor" 之后的命令。 如果在循环内部的 :try 之后但在匹配的 :finally (如 果有的话) 之前,":finally" 之后,匹配的 :endtry 之前 的命令会被先执行。该过程反复应用于所有函数内的嵌套 ":try" 块。在最外层 ":endtry" 结束之后才跳到循环之后的 命令。 :try :try :endt :endtry E600 E601 E602 :endt[ry] 改变 ":try" 和 ":endtry" 之间命令的错误处理,包括所有 执行的内容,":source" 里的命令,函数调用,或者自动命令 的激活等。 如果检测到错误或者中断,而其后又跟随了 :finally 命 令,执行从 ":finally" 之后继续。否则,或者在那以后遇到 了 ":endtry",则检查是否存在 (动态的) 往外一层的 ":try" 以及其相应的 ":finally" 等等。然后,脚本的处理 被终止。函数定义里是否有 "abort" 参数都不相干。 示例: try | call Unknown() | finally | echomsg "cleanup" | endtry echomsg "not reached" 另外,":try" 和 ":endtry" 之间的错误或者中断 (动态地) 被转换成一个例外。它的捕获过程如同它被 :throw 命令抛 出那样 (见 :catch )。这种情况下,脚本的处理不会被终 止。 "Vim:Interrupt" 的值用于中断例外。Vim 命令的错误被转换 成形如 "Vim({command}):{errmsg}" 的值,其它错误被转换 成形如 "Vim:{errmsg}"。这里,{command} 是完整的命令 名,而 {errmsg} 是错误例外如果没有被捕获的时候会显示的 消息,它总以错误号开始。 示例: try | sleep 100 | catch /^Vim:Interrupt$/ | endtry try | edit | catch /^Vim(edit):E\d\+/ | echo "error" | endtry :cat :catch E603 E604 E605 :cat[ch] /{pattern}/ 匹配 {pattern} 的例外抛出时,如果它没有被前一个 ":catch" 捕获,则执行本语句之后的命令,直到遇到和本 ":catch" 处于同一 :try 块的下一个 :catch:finally 或者 :endtry 为止。否则,这些命令被跳过。 如果没有提供 {pattern},所有的错误都会被捕获。 示例: :catch /^Vim:Interrupt$/ " 捕获中断 (CTRL-C) :catch /^Vim\%((\a\+)\)\=:E/ " 捕获所有的 Vim 错误 :catch /^Vim\%((\a\+)\)\=:/ " 捕获错误和中断 :catch /^Vim(write):/ " 捕获所有 :write 的错误 :catch /^Vim\%((\a\+)\)\=:E123:/ " 捕获错误 E123 :catch /my-exception/ " 捕获用户例外 :catch /.*/ " 捕获一切 :catch " 同 /.*/ 除了 / 以外,也可以用别的字符包围 {pattern},只要它没 有特殊含义 (比如 '|' 或 '"') 而且不出现在 {pattern} 里。 关于例外的信息可见 v:exception 。另见 throw-variables注意: 依赖 ":catch" 去捕获错误信息的 文本 是不可靠的, 因为不同的 locale 的信息可以不同。 :fina :finally E606 E607 :fina[lly] 任何匹配的 :try 和本 ":finally" 之间的部分要离开的时 候都执行本语句之后的命令,直到遇到匹配的 :endtry 为 止。包括这些情形: 正常完成且要执行到 ":finally",通过 :continue:break:finish:return ,或者由 于错误或者中断或者例外 (见 :throw )。 :th :throw E608 :th[row] {expr1} 计算 {expr1} 然后抛出例外。如果 ":throw" 在 :try 之 后但在第一个对应的 :catch 之前使用,它之后的命令被跳 过,直到遇到第一个匹配 {expr1} 为止。如果没有这样的 ":catch",或者如果 ":throw" 在 ":catch" 之后 :finally 之前使用,执行 ":finally" (如果有的话) 之后 直到匹配的 :endtry 为止的命令。如果本 ":throw" 在 ":finally" 之后之后出现,直到 ":endtry" 为止的命令都被 跳过。到达 ":endtry" 的时候,在动态计算的往外一层的 ":try" 块上再次重复本过程 (这可能出现在外层调用的函数 或者执行的脚本上),直到找到一个匹配的 ":catch"。如果最 终该例外没有被捕获,命令处理被终止。 示例: :try | throw "oops" | catch /^oo/ | echo "caught" | endtry 注意 "catch" 可能需要放在单独一行上,因为某些错误可以 导致整行在解析时被跳过而无法看到分隔命令的 "|"。 :ec :echo :ec[ho] {expr1} .. 回显每个 {expr1},以空格分隔。第一个 {expr1} 开启一个 新行。另见 :comment 。 使用 "\n" 来开启新行。使用 "\r" 把光标移到第一列。 使用 :echohl 命令的高亮设置。 后面不能跟注释。 示例: :echo "'shell' 的值是 " &shell :echo-redraw 后来的重画可能使消息再次消失。因为 Vim 常常会推迟重画 直到整个命令序列执行完为止,这个问题会频繁出现。要避免 ":echo" 之前的命令引起它之后的重画 (通常,重画被延迟到 有输入的时候才进行),使用 :redraw 命令强制重画。例 如: :new | redraw | echo "这里有一个新窗口" :echon :echon {expr1} .. 回显每个 {expr1},不附加其它字符。另见 :comment 。 使用 :echohl 命令的高亮设置。 后面不能跟注释。 例如: :echon "'shell' 的值是 " &shell 注意 两者的区别: ":echo" 是一个 Vim 命令,而 ":!echo" 是一个外部的外壳命令: :!echo % --> filename ":!" 的参数被扩展,见 :_% :!echo "%" --> filename or "filename" 和前例类似,你是否会看到双引号取决于你的 'shell' :echo % --> nothing '%' 不是一个表达式合法的字符。 :echo "%" --> % 只会回显 '%' 字符。 :echo expand("%") --> filename 调用 expand() 函数来扩展 '%'。 :echoh :echohl :echoh[l] {name} 让其后的 :echo:echon:echomsg 命令使用高亮 组 {name}。也可用于 input() 的提示。示例: :echohl WarningMsg | echo "Don't panic!" | echohl None 不要忘记把组设回 "None"。不然其后的 echo 都会被高亮。 :echom :echomsg :echom[sg] {expr1} .. 回显表达式的结果,将其作为一个真正的消息,并把该消息保 存在 message-history 里。 参数之间加入空格,和 :echo 类似。但不可显示的字符只 是回显而不会被解释。 这里的分析过程和 :echo 略有不同,而更像 :execute 。 所有的表达式都先经计算后进行连接,然后再进行回显。 如果表达式返回的不是数值或字符串,使用 string() 把它转 化为字符串。 应用 :echohl 命令的高亮设置。 示例: :echomsg "It's a Zizzer Zazzer Zuzz, as you can plainly see." :echo-redraw 说明如何避免屏幕重画时消息的消失问题。 :echoe :echoerr :echoe[rr] {expr1} .. 回显表达式的结果,将其作为一个错误消息,并把该消息保 存在 message-history 里。如果用在脚本或函数里,会加 入行号。 参数之间加入空格的方法和 :echomsg 类似。如果在 try 条件句里使用,该消息会抛出一个错误例外 (见 try-echoerr )。 示例: :echoerr "This script just failed!" 如果你只想要使用 :echohl 高亮的消息。 要得到铃声: :exe "normal \<Esc>" :echoc[onsole] {expr1} .. :echoc :echoconsole 用于测试: 类似于 :echomsg 但在 GUI 中运行且原来从终 端启动时,把文本写到标准输出。 :eval :eval {expr} 计算 {expr} 并忽略其返回值。例如: :eval Getlist()->Filter()->append('$') 因为不使用返回值,表达式假定有副作用。此例中 append() 调用会在缓冲区后附加列表中的文本。它类似于 :call ,但可用于所有表达式。 此命令本可缩短为 :ev:eva ,但不易记,所以不提 供。 此命令不能后跟 "|" 加其它命令,因为 "|" 视为表达式的一 部分。 :exe :execute :exe[cute] {expr1} .. 计算 {expr1},返回的字符串作为 Ex 命令执行。 多个参数用空格连接。如果不想有额外的空格,使用 ".." 操 作符来连接字符串使之成为一个参数。 {expr1} 用作被处理的命令,命令行编辑的键不会被识别。 后面不能跟注释。 示例: :execute "buffer" nextbuf :execute "normal" count .. "w" ":execute" 可以用来把命令附加到不能接受 '|' 的命令后 面。比如: :execute '!ls' | echo "theend" ":execute" 也是一个避免在 Vim 脚本里为 ":normal" 命令 输入控制字符的好方法: :execute "normal ixxx\<Esc>" 这里给出一个 <Esc> 字符,见 expr-string 。 要谨慎对待文件名中特殊字符的正确转义。 fnameescape() 可用于 Vim 命令, shellescape() 可用于 :! 命令。示 例: :execute "e " .. fnameescape(filename) :execute "!ls " .. shellescape(filename, 1) 注意: 执行的字符串可以是任何命令行,但开始或结束一个 "if"、"while" 和 "for" 命令不能保证没有问题,因为跳过 命令时,不执行 ":execute",Vim 就不能准确找到块开始和 结束的地方。另外,"break" 和 "continue" 不应出现在 ":execute" 内部。 下例不能工作,因为 ":execute" 不被执行,Vim 看不见 ":while",找到 ":endwhile" 时就报错: :if 0 : execute 'while i > 5' : echo "test" : endwhile :endif 但如果执行的字符串里有完整的 "while" 和 "if" 命令就没 有问题: :execute 'while i < 5 | echo i | let i = i + 1 | endwhile' :exe-comment ":execute"、":echo" 和 ":echon" 后面不能直接跟注释。 因它们把 '"' 看成字符串的开始。但你可以把注释加到 '|' 后面。例如: :echo "foo" | "这是一个注释

8. 例外处理 exception-handling

Vim 脚本语言包含了例外处理特性。本节解释如何在 Vim 脚本里应用该机制。 Vim 在出错或者中断的时候可以抛出例外。见 catch-errorscatch-interrupt 。 你也可以显式地使用 ":throw" 命令抛出例外。见 throw-catch 。 TRY 条 件 句 try-conditionals 例外可以被捕获或者用来激发清理代码的运行。你可以使用 try 条件句来指定 catch 子 句 (捕获例外) 和/或 finally 子句 (执行清理)。 try 条件句以 :try 命令开始,以匹配的 :endtry 命令结束。两者之间,你可以 使用 :catch 命令开始 catch 子句,或者用 :finally 命令开始 finally 子句。 catch 子句可有零到多个,但 finally 子句至多只有一个,且它之后不能再有 catch 子 句。catch 子句和 finally 子句之前的行称为 try 块。 :try : ... : ... TRY 块 : ... :catch /{pattern}/ : ... : ... CATCH 子 句 : ... :catch /{pattern}/ : ... : ... CATCH 子 句 : ... :finally : ... : ... FINALLY 子 句 : ... :endtry try 子句允许观察代码里是否有例外,并采取合适的行动。try 块里的例外可能被捕获。 try 块和 catch 子句里的例外可能引起清理动作。 如果 try 块的执行过程中没有抛出例外,控制转移到 finally 子句。在它执行后, 脚本从 ":endtry" 之后的行继续。 如果 try 块的执行过程中抛出了例外,该 try 块其余的行被跳过。例外和 ":catch" 命令的模式参数一一比较。第一个匹配的 ":catch" 之后的 catch 子句被采用,其余的 catch 子句则不会执行。catch 子句在下一个最早遇到的 ":catch"、":finally" 或 ":endtry" 命令结束。这时,finally 子句 (如果有的话) 被执行。当遇到 ":endtry" 的时候,脚本从后面的行继续,一如往常。 如果 try 块抛出的例外不能匹配任何 ":catch" 命令的模式,该例外不能由本 try 条件句捕获,因而不会执行任何的 catch 子句。只有 finally 子句,如果有的话,被采 用。该例外在 finally 子句的执行时被暂时搁置。在 ":endtry" 之后才继续。这样, ":endtry" 之后的命令不会被执行,而该例外可以在别的地方捕获,见 try-nesting 。 如果在 catch 子句的执行过程中抛出了另一个错误,catch 子句的其余部分不再执 行。新的例外不会和试图和同一个 try 条件句的任何 ":catch" 命令的模式匹配,因而 也不会执行任何它的 catch 子句。不过,如果有 finally 子句,它还是会被执行,而在 它的执行过程中暂时搁置新的例外。":endtry" 之后的命令也不会执行。而新的例外仍可 能在别的地方捕获,见 try-nesting 。 如果在 finally 子句 (如果有的话) 的执行过程中抛出了另一个错误,finally 子句 的其余部分不再执行。如果 finally 子句是因为 try 块或者某个 catch 子句里产生的 例外引起的,原先的 (被暂时搁置的) 例外被放弃。":endtry" 之后的命令也不会执行。 而 finally 子句的这个例外被传播,而可以在别的地方捕获,见 try-nesting 。 在 ":while" 循环包含的完整的 try 条件句里的 try 块或者某个 catch 子句里遇到 ":break" 或 ":continue" 时,或者在函数或者被执行的脚本里的 try 条件句里的 try 块或者某个 catch 子句里执行 ":return" (函数) 或者 ":finish" (脚本) 的时候,也 会执行 finally 子句。":break"、":continue"、":return" 或者 ":finish" 在 finally 子句的执行时被暂停,而在遇到 ":endtry" 时继续。不过,如果在执行 finally 子句时抛出例外,它们都被抛弃。 在 ":while" 循环包含的完整的 try 条件句里的 finally 子句里遇到 ":break" 或 ":continue" 时,或者在函数或者被执行的脚本里的 finally 子句里执行 ":return" ( 函数) 或者 ":finish" (脚本) 的时候,finally 子句的其余部分被跳过,而 ":break"、":continue"、":return" 或 ":finish" 会如常继续执行。如果 finally 的 执行是因为例外或者早先的 try 块或者 catch 子句的 ":break"、":continue"、 ":return" 或者 ":finish" 引起的,暂停的例外或者命令被放弃。 例子可见 throw-catchtry-finally 。 TRY 条 件 句 的 嵌 套 try-nesting try 条件句可以任意嵌套。也就是说,完整的 try 条件句可以在另一个 try 条件句的 try 块、某个 catch 子句或者 finally 子句里出现。如果内层的 try 条件句不能捕获 它的 try 块抛出的例外,或者在它的某个 catch 子句后者 finally 子句里抛出新的例 外的话,那么根据上述规则由外层的 try 条件句继续检查是否能捕获该例外。如果内层 try 条件句在外层 try 条件句的 try 块里,检查外层的 catch 子句,不然只有 finally 子句会被执行。对嵌套的处理而言,内层 try 条件句是直接包含在外层里面, 还是外层执行了脚本或者调用了函数,而后者又包含了内层 try 条件句,无关紧要。 如果没有活动的 try 条件句能捕获某个例外,只有它们的 finally 子句会执行。最后, 脚本结束它的处理。如果是 ":throw" 命令显式地抛出的未捕获的例外,显示错误信息。 对于 Vim 隐含抛出的未捕获的错误或者中断例外,错误信息或者中断信息也会像平常一 样显示。 例子可见 throw-catch 。 检 查 例 外 处 理 代 码 except-examine 例外处理的代码的编写可能很麻烦。如果你不知道发生了什么,把 'verbose' 设为 13, 或者在执行脚本文件时使用 ":13verbose" 命令修饰符。这样,你能看到什么时候例外被 抛出、放弃、捕获、或者最终处理。如果详细程度大于等于 14,finally 子句暂停什么 也会显示。这些信息在调试模式里也会给出 (见 debug-scripts )。 抛 出 和 捕 获 例 外 throw-catch 你可以抛出任何数值或者字符串作为例外。使用 :throw 命令然后把要抛出的值作为参 数传入: :throw 4711 :throw "string" throw-expression 你可以指定表达式参数。该表达式先进行计算,然后抛出其结果: :throw 4705 + strlen("string") :throw strpart("strings", 0, 6) 在计算 ":throw" 命令的参数的时候,也可能会抛出例外。除非它被捕获,不然表达式的 计算会被放弃。":throw" 命令这时不会抛出新的例外。 例如: :function! Foo(arg) : try : throw a:arg : catch /foo/ : endtry : return 1 :endfunction : :function! Bar() : echo "in Bar" : return 4710 :endfunction : :throw Foo("arrgh") + Bar() 这里抛出了 "arrgh",而不会显示 "in Bar",因为 Bar() 没有执行。 :throw Foo("foo") + Bar() 却显示 "in Bar" 并且抛出 4711。 别的接受表达式作为参数的命令也可能因为表达式计算过程的 (未捕获的) 例外而被放 弃。例外这时被传播给该命令的调用者。 例如: :if Foo("arrgh") : echo "then" :else : echo "else" :endif 这里 "then" 和 "else" 都不会显示。 catch-order try 条件句里的例外可以用一个或多个 :catch 命令捕获,见 try-conditionals 。 每个 ":catch" 命令可以捕获的值通过模式参数指定。捕获匹配的例外时,执行其后的 catch 子句。 例如: :function! Foo(value) : try : throw a:value : catch /^\d\+$/ : echo "Number thrown" : catch /.*/ : echo "String thrown" : endtry :endfunction : :call Foo(0x1267) :call Foo('string') 第一个 Foo() 的调用显示 "Number thrown",第二个 "String thrown"。 按照 ":catch" 命令本身的顺序,依次匹配例外。只用第一个成功匹配。所以,你应该把 更专门的 ":catch" 放在前面。下面的顺序并不合理: : catch /.*/ : echo "String thrown" : catch /^\d\+$/ : echo "Number thrown" 这里,第一个 ":catch" 总是会被匹配,所以第二个子句永远不可能被采用。 throw-variables 如果你使用通用的模式捕获到例外,可以通过变量 v:exception 得到准确的例外值: : catch /^\d\+$/ : echo "Number thrown. Value is" v:exception 你也许会对在什么地方抛出例外也感兴趣。它被保存在 v:throwpoint 里。注意 "v:exception" 和 "v:throwpoint" 可用于最近捕获的例外,只要该例外还没有完成处 理。 例如: :function! Caught() : if v:exception != "" : echo 'Caught "' . v:exception . '" in ' . v:throwpoint : else : echo 'Nothing caught' : endif :endfunction : :function! Foo() : try : try : try : throw 4711 : finally : call Caught() : endtry : catch /.*/ : call Caught() : throw "oops" : endtry : catch /.*/ : call Caught() : finally : call Caught() : endtry :endfunction : :call Foo() 会显示 Nothing caught Caught "4711" in function Foo, line 4 Caught "oops" in function Foo, line 10 Nothing caught 更实际的例子: 下面的命令 ":LineNumber" 显示调用它时,脚本或者函数里的行号: :function! LineNumber() : return substitute(v:throwpoint, '.*\D\(\d\+\).*', '\1', "") :endfunction :command! LineNumber try | throw "" | catch | echo LineNumber() | endtry try-nested try 条件句没有捕获的例外可以在包围它的 try 条件句中捕获: :try : try : throw "foo" : catch /foobar/ : echo "foobar" : finally : echo "inner finally" : endtry :catch /foo/ : echo "foo" :endtry 内层的 try 条件句没有捕获例外,只执行了 finally 子句。例外在外层得到捕获。本例 显示 "inner finally" 然后是 "foo"。 throw-from-catch 你可以捕获某例外,然后抛出另一个。它在该 catch 子句之外捕获: :function! Foo() : throw "foo" :endfunction : :function! Bar() : try : call Foo() : catch /foo/ : echo "Caught foo, throw bar" : throw "bar" : endtry :endfunction : :try : call Bar() :catch /.*/ : echo "Caught" v:exception :endtry 显示 "Caught foo, throw bar" 然后是 "Caught bar"。 rethrow Vim 脚本语言没有真正的 rethrow。但可以抛出 "v:exception" 来代替: :function! Bar() : try : call Foo() : catch /.*/ : echo "Rethrow" v:exception : throw v:exception : endtry :endfunction try-echoerr 注意 这个方法不能用来 "rethrow" Vim 错误或者中断例外,因为不能伪造 Vim 的内部 例外。试图这么做会产生一个错误例外。你应该抛出自己的例外来说明这种情形。如果你 想产生 Vim 的错误例外并包含原来的错误例外的值,可以使用 :echoerr 命令: :try : try : asdf : catch /.*/ : echoerr v:exception : endtry :catch /.*/ : echo v:exception :endtry 本代码会显示 Vim(echoerr):Vim:E492: Not an editor command: asdf 清 理 代 码 try-finally 脚本经常需要改变全局设定然后结束时恢复之。不过,如果用户按了 CTRL-C 中止脚本, 这些设定会处于不一致的状态。如果你处于某脚本的开发阶段而发生了错误或者你显式地 抛出例外而没有试图捕获之,也会有相同的情况。用带有 finally 子句的 try 条件句, 可以恢复设置,从而解决这个问题。可以保证无论是正常的控制流、出错或者显式的例外 ":throw"、还是被中断,都会执行 finally 子句 (注意 try 条件句的错误和中断被转换 成例外。如果没有捕获,它们在 finally 子句执行完之后会终止脚本。) 例如: :try : let s:saved_ts = &ts : set ts=17 : : " 这里执行重要的任务。 : :finally : let &ts = s:saved_ts : unlet s:saved_ts :endtry 无论任何函数还是脚本的一部分,只要它需要修改全局设置,而在失败或者成功退出该函 数或者脚本部分时需要恢复这些设置,就应该在本地应用本方法。 break-finally 清理代码也适用于 ":continue"、":break"、":return" 或 ":finish" 退出的 try 块或 catch 子句。 例如: :let first = 1 :while 1 : try : if first : echo "first" : let first = 0 : continue : else : throw "second" : endif : catch /.*/ : echo v:exception : break : finally : echo "cleanup" : endtry : echo "still in while" :endwhile :echo "end" 会显示 "first"、"cleanup"、"second"、"cleanup" 和 "end"。 :function! Foo() : try : return 4711 : finally : echo "cleanup\n" : endtry : echo "Foo still active" :endfunction : :echo Foo() "returned by Foo" 会显示 "cleanup" 和 "4711 returned by Foo"。你不需要在 finally 子句里加上附加 的 ":return"。(最终,它会覆盖原来的返回值。) except-from-finally finally 子句里可以使用 ":continue"、":break"、":return"、":finish" 或 ":throw",但不推荐,因为它放弃了 try 条件句的清理工作。不过当然了,finally 子 句里仍然可能有中断或者错误例外。 finally 子句的错误引起中断不能正常工作的例子: :try : try : echo "Press CTRL-C for interrupt" : while 1 : endwhile : finally : unlet novar : endtry :catch /novar/ :endtry :echo "Script still running" :sleep 1 如果你需要在 finally 里放入可能出错的命令,考虑捕获或者忽略这些命令的错误,见 catch-errorsignore-errors 。 捕 获 错 误 catch-errors 如果你想捕获特定的错误,你需要把要关注的代码放到 try 块里,然后为该错误消息加 入 catch 子句。try 条件句的存在使得所有的错误被转换为例外。不会显示消息,而 v:errmsg 也不会设置。要找到 ":catch" 命令右边的模式,你需要知道错误例外的格 式。 错误例外使用如下的格式: Vim({cmdname}):{errmsg} Vim:{errmsg} {cmdname} 是失败的命令名;第二种形式用于命令名未知的场合。{errmsg} 是错误在 try 条件句发生时,本应产生的错误消息。它总是以大写的 "E" 开始,后面跟两或者三 位的错误号,一个冒号和一个空格。 例如: 命令 :unlet novar 通常产生错误信息 E108: No such variable: "novar" 它在 try 条件句里被转换为例外 Vim(unlet):E108: No such variable: "novar" 命令 :dwim 通常产生错误信息 E492: Not an editor command: dwim 它在 try 条件句里被转换为例外 Vim:E492: Not an editor command: dwim 你可以这样捕获所有的 ":unlet" 错误 :catch /^Vim(unlet):/ 或者这样捕获所有拼错命令名字的错误 :catch /^Vim:E492:/ 有的错误信息可能由不同的命令产生: :function nofunc :delfunction nofunc 都会产生错误信息 E128: Function name must start with a capital: nofunc 它在 try 条件句里被分别转换为例外 Vim(function):E128: Function name must start with a capital: nofunc Vim(delfunction):E128: Function name must start with a capital: nofunc 使用下面的模式,你可以根据其号码捕获错误,而不管产生的命令是什么: :catch /^Vim(\a\+):E128:/ 有些命令,比如 :let x = novar 产生多个错误信息,这里: E121: Undefined variable: novar E15: Invalid expression: novar 只有第一个会用做例外的值,因为它是最专门的那个 (见 except-several-errors )。 所以你应该这样捕获它 :catch /^Vim(\a\+):E121:/ 你可以这样捕获所有和名字 "nofunc" 相关的错误 :catch /\<nofunc\>/ 你可以这样捕获 ":write" 和 ":read" 命令产生的所有 Vim 的错误 :catch /^Vim(\(write\|read\)):E\d\+:/ 你可以这样捕获所有的 Vim 错误 :catch /^Vim\((\a\+)\)\=:E\d\+:/ catch-text 注意: 永远不要根据错误信息文本本身捕获错误: :catch /No such variable/ 只适用于英语的 locale,如果用户用 :language 命令使用别的语言就不行了。不过, 在注释里引用该消息或许有帮助: :catch /^Vim(\a\+):E108:/ " No such variable 忽 略 错 误 ignore-errors 你可以通过在本地捕获来忽略某个 Vim 命令的错误: :try : write :catch :endtry 但强烈建议, 不要 使用这种简单的形式,因为它捕获的东西超过你的想象。":write" 命令里,会执行一些自动命令,它们可能引起与写入无关的错误。例如: :au BufWritePre * unlet novar 作为脚本的作者,你不应该负责处理这些错误: 使用你书写的脚本的用户可能定义了这些 自动命令。而你这么做只会屏蔽用户自己的错误。 更好的方法是用 :try : write :catch /^Vim(write):/ :endtry 这样,只捕获真正的 write 错误。总之,只应该捕获你有意忽略的错误。 对于单个不会执行自动命令的命令,你可以用 ":silent!" 命令来关闭错误到例外的转 换: :silent! nunmap k 即使在活动的 try 条件句里也能这么用。 捕 获 中 断 catch-interrupt 如果有活动的 try 条件句,中断 (CTRL-C) 被转换为例外 "Vim:Interrupt"。你可以和 其他例外一样捕获它。那样,脚本就不会中止。 例如: :function! TASK1() : sleep 10 :endfunction :function! TASK2() : sleep 20 :endfunction :while 1 : let command = input("Type a command: ") : try : if command == "" : continue : elseif command == "END" : break : elseif command == "TASK1" : call TASK1() : elseif command == "TASK2" : call TASK2() : else : echo "\nIllegal command:" command : continue : endif : catch /^Vim:Interrupt$/ : echo "\nCommand interrupted" : " Caught the interrupt. Continue with next prompt. : endtry :endwhile 这里,你可以用 CTRL-C 中止任务;脚本会询问新的命令。如果你在提示上按 CTRL-C, 脚本就会中止。 要测试在你脚本的某一行上如果按了 CTRL-C 会发生什么,使用调试模式,然后在那行上 执行 >quit>interrupt 。见 debug-scripts 。 捕 获 一 切 catch-all 命令 :catch /.*/ :catch // :catch 会捕获一切: 错误例外,中断例外和 :throw 命令显式抛出的例外。脚本的顶层可用此 捕获所有意料不到的问题。 示例: :try : : " 这里做重要的工作 : :catch /MyException/ : : " 处理未知的问题 : :catch /^Vim:Interrupt$/ : echo "脚本被中断" :catch /.*/ : echo "内部错误 (" . v:exception . ")" : echo " - 发生在 " . v:throwpoint :endtry :" 脚本结束 注意: 捕获一切可能会捕获到比你想得到的更多的错误。所以,强烈建议你只用指定模式 参数的 ":catch" 来捕获你真正处理的错误。 例如: 捕获一切会使得按 CTRL-C 来中断脚本几乎没有办法: :while 1 : try : sleep 1 : catch : endtry :endwhile 例 外 和 自 动 命 令 except-autocmd 执行自动命令的过程中可以使用例外。例如: :autocmd User x try :autocmd User x throw "Oops!" :autocmd User x catch :autocmd User x echo v:exception :autocmd User x endtry :autocmd User x throw "Arrgh!" :autocmd User x echo "Should not be displayed" : :try : doautocmd User x :catch : echo v:exception :endtry 会显示 "Oops!" 和 "Arrgh!"。 except-autocmd-Pre 有些命令里,自动命令在命令执行的主要动作之前执行。如果在自动命令的序列中抛 出没有捕获的例外,该序列和导致其执行的命令本身被放弃,而例外被传播到命令的调用 者那里。 例如: :autocmd BufWritePre * throw "FAIL" :autocmd BufWritePre * echo "应该不会显示" : :try : write :catch : echo "Caught:" v:exception "from" v:throwpoint :endtry 这里,":write" 命令不会写入当前编辑的文件 (你可以通过查看 'modified' 发现)。因 为例外来自 BufWritePre 自动命令,它放弃了 ":write"。然后,该例外被捕获而脚本会 显示: Caught: FAIL from BufWrite Auto commands for "*" except-autocmd-Post 有些命令里,自动命令在命令执行的主要动作之后执行。如果主要动作失败,而命令包含 在活动的 try 条件句里,将跳过这些自动命令并抛出错误例外,该命令的调用者可以捕 获这些例外。 例如: :autocmd BufWritePost * echo "文件被成功写入!" : :try : write /i/m/p/o/s/s/i/b/l/e :catch : echo v:exception :endtry 只会显示: Vim(write):E212: Can't open file for writing (/i/m/p/o/s/s/i/b/l/e) 如果你真想在主要动作失败的时候也执行自动命令的话,在 catch 子句里激活自动命令 事件。 例如: :autocmd BufWritePre * set noreadonly :autocmd BufWritePost * set readonly : :try : write /i/m/p/o/s/s/i/b/l/e :catch : doautocmd BufWritePost /i/m/p/o/s/s/i/b/l/e :endtry 你也可以用 ":silent!": :let x = "ok" :let v:errmsg = "" :autocmd BufWritePost * if v:errmsg != "" :autocmd BufWritePost * let x = "after fail" :autocmd BufWritePost * endif :try : silent! write /i/m/p/o/s/s/i/b/l/e :catch :endtry :echo x 会显示 "after fail"。 如果命令的主要动作没有失败,可以在命令的调用者那里捕获自动命令产生的例外: :autocmd BufWritePost * throw ":-(" :autocmd BufWritePost * echo "这里不应该被显示" : :try : write :catch : echo v:exception :endtry except-autocmd-Cmd 有的命令的正常动作可以被自动命令的序列代替。可以在命令的调用者那里捕获该序列产 生的例外。 例如: 对于 ":write" 命令,调用者并不知道发生例外时,文件是不是已经被写入。 你需要想办法告知调用者。 :if !exists("cnt") : let cnt = 0 : : autocmd BufWriteCmd * if &modified : autocmd BufWriteCmd * let cnt = cnt + 1 : autocmd BufWriteCmd * if cnt % 3 == 2 : autocmd BufWriteCmd * throw "BufWriteCmdError" : autocmd BufWriteCmd * endif : autocmd BufWriteCmd * write | set nomodified : autocmd BufWriteCmd * if cnt % 3 == 0 : autocmd BufWriteCmd * throw "BufWriteCmdError" : autocmd BufWriteCmd * endif : autocmd BufWriteCmd * echo "File successfully written!" : autocmd BufWriteCmd * endif :endif : :try : write :catch /^BufWriteCmdError$/ : if &modified : echo "Error on writing (file contents not changed)" : else : echo "Error after writing" : endif :catch /^Vim(write):/ : echo "Error on writing" :endtry 如果脚本在修改后执行了多次,它先显示 File successfully written! 然后 Error on writing (file contents not changed) 然后 Error after writing 等等。 except-autocmd-ill 你不能把一个 try 条件句分散到不同事件的自动命令。 下面的代码是非法的构造: :autocmd BufWritePre * try : :autocmd BufWritePost * catch :autocmd BufWritePost * echo v:exception :autocmd BufWritePost * endtry : :write 例 外 层 次 和 参 数 化 的 例 外 except-hier-param 有些编程语言支持使用例外类的层次结构,或者在例外类的对象里传入附加的信息。你可 以在 Vim 里完成类似的工作。 为了抛出属于某层次的例外,只要抛出完整的类名,部件之间用冒号分隔。比如,在 某个数学库里的溢出错误可以抛出字符串 "EXCEPT:MATHERR:OVERFLOW"。 如果你想给例外类传递附加的信息,把它加到括号里。比如写入文件 "myfile" 时的 错误,可以抛出字符串 "EXCEPT:IO:WRITEERR(myfile)"。 在 ":catch" 命令里使用合适的模式,可以捕获你的层次中的基本类或者派生类。括 号里的附加信息也可以运用 ":substitute" 命令从 v:exception 里切出。 例如: :function! CheckRange(a, func) : if a:a < 0 : throw "EXCEPT:MATHERR:RANGE(" . a:func . ")" : endif :endfunction : :function! Add(a, b) : call CheckRange(a:a, "Add") : call CheckRange(a:b, "Add") : let c = a:a + a:b : if c < 0 : throw "EXCEPT:MATHERR:OVERFLOW" : endif : return c :endfunction : :function! Div(a, b) : call CheckRange(a:a, "Div") : call CheckRange(a:b, "Div") : if (a:b == 0) : throw "EXCEPT:MATHERR:ZERODIV" : endif : return a:a / a:b :endfunction : :function! Write(file) : try : execute "write" fnameescape(a:file) : catch /^Vim(write):/ : throw "EXCEPT:IO(" . getcwd() . ", " . a:file . "):WRITEERR" : endtry :endfunction : :try : : " 一些算术和 I/O : :catch /^EXCEPT:MATHERR:RANGE/ : let function = substitute(v:exception, '.*(\(\a\+\)).*', '\1', "") : echo "Range error in" function : :catch /^EXCEPT:MATHERR/ " 捕获 OVERFLOW 和 ZERODIV : echo "Math error" : :catch /^EXCEPT:IO/ : let dir = substitute(v:exception, '.*(\(.\+\),\s*.\+).*', '\1', "") : let file = substitute(v:exception, '.*(.\+,\s*\(.\+\)).*', '\1', "") : if file !~ '^/' : let file = dir . "/" . file : endif : echo 'I/O error for "' . file . '"' : :catch /^EXCEPT/ : echo "Unspecified error" : :endtry Vim 自己抛出的例外 (错误或者按了 CTRL-C) 使用扁平的层次: 它们都在 "Vim" 类里。 你自己不能抛出带有 "Vim" 前缀的例外;它们是 Vim 保留的。 如果已知失败的命令名,Vim 错误例外使用该命令名作为参数。见 catch-errors 。 特 别 之 处 except-compat 例外处理的概念需要产生例外的命令序列被立即中止,而控制转移到 finally 子句和/或 catch 子句。 在 Vim 脚本语言里,有一些情况下脚本和函数在错误后还会继续: 在没有 "abort" 标志 位的函数或者 ":silent!" 之后的命令里,控制流转到下一行。而在函数外,控制流转到 最外层 ":endwhile" 或者 ":endif" 之后的行。另一方面,错误应该可以作为例外被捕 获 (因而,需要立即被中止)。 这个问题的解决方法是把仅在有活动 try 条件句的时候,把错误转化为例外,并立即中 止 (如果没有用 ":silent!" 抑制的话)。这不是一个限制,因为 (错误) 例外只能在活 动的 try 条件句里被捕获。如果你需要立即终止而不需要捕获错误的话,只要用一个没 有 catch 子句的 try 子句就可以了 (你可以用 finally 子句指定终止前执行的清理代 码。) 如果没有活动的 try 条件句,使用通常的中止和继续行为,而不是立即中止。这样,保 证了与 Vim 6.1 和之前版本编写的脚本的兼容性。 不过,如果在活动的 try 条件句里执行已有的不使用例外处理命令的脚本 (或者调用它 的一个函数),你也许会改变已有脚本发生错误时的控制流。你会在错误时立即中止并且 在新的脚本里捕获错误。如果被执行的脚本通过 ":silent!" 命令抑制了错误 (在合适的 时候测试 v:errmsg 来检查错误),它的执行路径没有改变。错误也不会转换为例外。 (见 :silent 。) 所以唯一留下的可能是不关心错误并产生错误信息的脚本。可能,你 也不希望在新的脚本里使用这样的代码吧。 except-syntax-err 例外处理命令的语法错误永远不会被它所属的 try 条件句的任何 ":catch" 命令所捕 获。不过,还是会执行它的 finally 子句。 例如: :try : try : throw 4711 : catch /\(/ " 有语法错误 : echo "in catch with syntax error" : catch : echo "inner catch-all" : finally : echo "inner finally" : endtry :catch : echo 'outer catch-all caught "' . v:exception . '"' : finally : echo "outer finally" :endtry 会显示: inner finally outer catch-all caught "Vim(catch):E54: Unmatched \(" outer finally 原来的例外被丢弃了,抛出的是取而代之的语法错误的错误例外。 except-single-line ":try"、":catch"、":finally" 和 ":endtry" 命令可以放在一行里,但这样如果有语法 错误,可能使得 "catch" 行无法被识别。所以,最好不要这么做。 例如: :try | unlet! foo # | catch | endtry ":unlet!" 参数之后的拖尾字符抛出了错误例外,但因此无法看到 ":catch" 和 ":endtry" 命令,从而只能丢弃该错误例外并且显示消息 "E488: Trailing characters"。 except-several-errors 如果多个错误在一个命令里出现,第一个错误信息通常是最专门的,因而它被转换为错误 例外。 例如: echo novar 产生 E121: Undefined variable: novar E15: Invalid expression: novar try 条件句里错误例外的值是: Vim(echo):E121: Undefined variable: novar except-syntax-error 不过,如果同一命令在普通错误之后发现了语法错误,语法错误被用作抛出的例外。 例如: unlet novar # 产生 E108: No such variable: "novar" E488: Trailing characters try 条件句里错误例外的值是: Vim(unlet):E488: Trailing characters 这么做是因为语法错误可能会以用户意想不到的方式改变执行的路径。例如: try try | unlet novar # | catch | echo v:exception | endtry catch /.*/ echo "outer catch:" v:exception endtry 显示 "outer catch: Vim(unlet):E488: Trailing characters",然后给出错误信息 "E600: Missing :endtry",见 except-single-line

9. 示例 eval-examples

用二进制显示 :" 函数 Nr2Bin() 返回数值的二进制字符串。 :func Nr2Bin(nr) : let n = a:nr : let r = "" : while n : let r = '01'[n % 2] . r : let n = n / 2 : endwhile : return r :endfunc :" 函数 String2Hex() 把字符串里的每个字符转换成二进制字符串,用连字符分隔字 :" 符。 :func String2Bin(str) : let out = '' : for ix in range(strlen(a:str)) : let out = out . '-' . Nr2Bin(char2nr(a:str[ix])) : endfor : return out[1:] :endfunc 使用示例: :echo Nr2Bin(32) 返回: "100000" :echo String2Bin("32") 返回: "110011-110010" 给行排序 下例用特定比较函数给行排序。 :func SortBuffer() : let lines = getline(1, '$') : call sort(lines, function("Strcmp")) : call setline(1, lines) :endfunction 可写为一行程序: :call setline(1, sort(getline(1, '$'), function("Strcmp"))) scanf() 的替代 sscanf Vim 里没有 sscanf() 函数。如果你需要提取一行的部分内容,可以使用 matchstr() 和 substitute() 完成。本例子说明如何得到从类似 "foobar.txt, 123, 45" 的行里提取文 件名,行号和列号。 :" 设置匹配模式 :let mx='\(\f\+\),\s*\(\d\+\),\s*\(\d\+\)' :"取得匹配整个表达式的文本部分 :let l = matchstr(line, mx) :"从匹配中提取每个项目 :let file = substitute(l, mx, '\1', '') :let lnum = substitute(l, mx, '\2', '') :let col = substitute(l, mx, '\3', '') 这里,输入是变量 "line",返回值放在变量 "file"、"lnum" 和 "col" 里。(Michael Geddes 提供的方法) 输出 scriptnames 到字典 scriptnames-dictionary :scriptnames 命令可用于得到执行过的所有脚本文件的列表。没有等价的函数或变量 (因为很少用到)。如果需要操作此列表,可以使用下面的代码: " 把 ":scriptnames" 的输出存放到 scriptnames_output 变量中。 let scriptnames_output = '' redir => scriptnames_output silent scriptnames redir END " 把输出分拆为行,并对每行进行分析。在 "script" 字典中加入项目。 let scripts = {} for line in split(scriptnames_output, "\n") " 只处理非空白行。 if line =~ '\S' " 获取每行的第一个数字。 let nr = matchstr(line, '\d\+') " 获取文件名,删除脚本号 " 123: "。 let name = substitute(line, '.\+:\s*', '', '') " 在字典中加入项目 let scripts[nr] = name endif endfor unlet scriptnames_output

10. Vim script versions vimscript-version vimscript-versions

scriptversion 随着时间推移,Vim 脚本加入很多新特性。这包括了 Ex 命令、函数、变量类型等等。每 个单独的特性都可以用 has()exists() 函数检查。 有时旧功能的语法阻碍了 Vim 的改进。而撤销相关支持又会破坏旧的 Vim 脚本。为此, 可用显式的 :scriptversion 命令。当 Vim 脚本和旧版本的 Vim 不兼容时,会显式地 报错,而不会出现各种奇怪的失败。 scriptversion-1 :scriptversion 1 这是原本的 Vim 脚本,和不使用 :scriptversion 命令一样。可用于把一段 代码回到旧语法。这样测试是否支持: has('vimscript-1') scriptversion-2 :scriptversion 2 不支持用 "." 进行字符串连接,而用 ".." 代替。 这避免了字典成员访问和浮点数的二义性。现在 ".5" 意味着数值 0.5。 scriptversion-3 :scriptversion 3 所有的 vim-variable 必须使用 "v:" 前缀。例如 "version" 不再用作 v:version 的简称,而可以用作正常变量。 同样适用于一些显而易见的名字,如 "count" 等等。 这样测试是否支持: has('vimscript-3') scriptversion-4 :scriptversion 4 不把零开始的数值识别为八进制。"0o" 或 "0O" 开始的还是能识别为八进制。 在之前的版本中你会看到: echo 017 " 显示 15 (八进制) echo 0o17 " 显示 15 (八进制) echo 018 " 显示 18 (十进制) 使用脚本版本 4 后: echo 017 " 显示 17 (十进制) echo 0o17 " 显示 15 (八进制) echo 018 " 显示 18 (十进制) 同时,可以在数值内部使用单引号来提高可读性: echo 1'000'000 引号必须在数位之间。 这样测试是否支持: has('vimscript-4')

11. 不包含 +eval 特性 no-eval-feature

如果编译时关闭了 +eval 特性,以上的表达式计算命令都不可用。为了避免因此导致 你的 Vim 脚本产生各种错误,":if" 和 ":endif" 命令仍然得到识别。不过 ":if" 的参 数和一切 ":if" 和匹配的 ":endif" 之间的内容都被忽略。可以嵌套 ":if" 块,但只允 许出现在行首。不识别 ":else" 命令。 下例演示如何在不存在 +eval 特性时不执行命令: :if 1 : echo "编译加入了表达式求值" :else : echo "你_永远_看不到这条消息" :endif 要在 +eval 特性关闭时才执行命令有两种方法。最简单的是提前退出脚本 (或 Vim): if 1 echo "带 +eval 执行的命令" finish endif args " 不带 +eval 执行的命令 如果不想中止脚本的载入可以用一些小技巧,如下例所示: silent! while 0 set history=111 silent! endwhile +eval 特性可用时,因为 "while 0" 跳过此命令。没有 +eval 特性时,"while 0" 是错误但被安静地忽略,从而执行此命令。

12. 沙盘 (sandbox) eval-sandbox sandbox E48

'foldexpr''formatexpr''includeexpr''indentexpr''statusline''foldtext' 选项在沙盘 (sandbox) 里进行计算。这意味着这些表达式不会产生可怕的副 作用。在模式行上设置这些选项时,以及在标签文件里和命令行上的 CTRL-R = 执行命令 时,这项措施提供了一定的安全性。 沙盘也用于 :sandbox 命令。 沙盘里,不允许以下操作: - 修改缓冲区文本 - 定义或者改变映射、自动命令和用户命令 - 设置若干选项 (见 option-summary ) - 设置若干 v: 变量 (见 v:var ) E794 - 执行外壳命令 - 读入或者写到文件 - 跳转到另一缓冲区或者去编辑文件 - 执行 Python、Perl 等命令 这并不能保证 100% 安全,但应该可以挡住大多数攻击。 :san :sandbox :san[dbox] {cmd} 在沙盘里执行 {cmd}。用于计算可能在模式行里设置的选项, 比如 'foldexpr' sandbox-option 一些选项包含表达式。对这些表达式进行计算时可能要使用沙盘才能避免安全性的威胁。 但沙盘限制较多,所以只有在从不安全的位置设置选项时才会如此。在此上下文中,不安 全的位置指: - 执行当前目录的 .vimrc 或 .exrc 时 - 在沙盘里执行时 - 来自模式行的值 - 执行沙盘里定义的函数时 注意 如果在沙盘里保存选项值然后恢复之,该选项仍然标记为在沙盘里设置。

13. 文本锁 textlock

在一些情况下,不允许修改缓冲区里的文本、跳转到其它窗口和一些其它会引起混淆或打 断 Vim 正在进行的操作的动作。这主要适用于和 Vim 实际正在进行其它操作的同时发生 的事情。例如,'balloonexpr' 的计算可能发生在鼠标指针定位在若干位置的任何时候。 文本锁激活时,不允许: - 修改缓冲区文本 - 跳转到其它缓冲区或窗口 - 编辑其它文件 - 关闭窗口或者退出 Vim - 其它 vim:tw=78:ts=8:noet:ft=help:norl: