Vim 是一个功能强大的文本编辑器,适用于编程和文档编辑。Vimscript 是 Vim 的脚本语言,可以帮助用户实现更高效的工作流。本文将详细介绍 Vimscript 的基本用法,包括常用命令、数据类型、函数、按键映射等,帮助您更好地掌握 Vimscript。
一、基本命令
在 Vim 中输入 :help <CMD> 可以查看该命令详细的帮助信息,比如 :help echo、:help python。
打印信息
打印信息可以使用 :echo "hi, axiaoxin.",也可以使用 :echom "hi, Mr.axiaoxin",运行时都会输出后面的字符串。他们的区别在于 :echom 会在运行后将其打印的信息保存在 messages 的列表中,而 :echo 则不会。运行 :messages 可以查看 Vim 所有历史输出的信息,用 echom 可以更方便地进行调试信息的输出。
二、Vimscript 基本数据类型及强制类型转换
1. 数字
数字包括整型、浮点型,基本的数字运算和 Python 都差不多:
:echom 100
:echom 0xff "16进制
:echom 010 "8进制
:echom 019 "不合法8进制,自动被视为十进制
2. 字符串
字符串不能使用 + 连接,+ 只用于数字。当用 + 连接字符串时,会强制将字符串转为开头的数字再相加。正确的连接符号为 .:
:echom "Hello, " + "world" " return 0
:echom "3 mice" + "2 cats" " return 5
:echom "3 mice" + "cats 2" " return 3
:echom 10 + "10.1" " return 10
:echom 10 + 10.1 " return 20.1
:echom "Hello, " . "world" " return hello, world
当整数和字符串用 . 连接时,会将整数转换成字符串,但不能将浮点数和字符串连接,会报错。
当字符串用单引号包住时,里面的特殊字符只会显示为原来的样子:
:echo "foo\nbar" "显示为两行
:echom "foo\nbar" "显示为foo^@bar,^@表示换行字符
:echom '\n\\' "显示为\n\\,失去本身的意义
:echom 'That''s enough.' "显示为That's enough. 单引号需要用'来转义,用\是错误语法
字符串也可以像 Python 一样切片::echo "abcd"[0:2]
用下标取字符串中的字符不能使用负数下标,:echo "abcd"[-1] 返回为空,但可以使用负数进行切片::echo "abcd"[-2:]
3. 列表
列表下标从 0 开始,比如 :echo [0, [1, 2]][1] 输出 [1, 2],:echo [0, [1, 2]][-2] 输出倒数第二个元素 0,同样支持 Python 风格的切片操作。列表可以相加::echo ['a', 'b'] + ['c'] 返回 ['a', 'b', 'c']。
列表函数
add(list, item)
len(list)
get(list, index, default) " 获取给定index的item,index超过range返回default
index(list, item) " 返回-1表示不存在该item
join(list[, joiner])
reverse(list)
sort(list)
function! Sorted(l)
let new_list = deepcopy(a:l)
call sort(new_list)
return new_list
endfunction
4. 字典
取值:
:echo {'a': 1, 100: 'foo',}['a']
:echo {'a': 1, 100: 'foo',}[100]
:echo {'a': 1, 100: 'foo',}.a
:echo {'a': 1, 100: 'foo',}.100
删除有两种方式,一种是 :let a = remove(dict, key),另一种是 unlet dict.key,区别在于第一种方式有返回值(即被删除 key 的 value),第二种没有,如果删除一个不存在的 key 会报错:
:let foo = {'a': 1, 'b': 2}
:let test = remove(foo, 'a')
:unlet foo.b
:echo foo
:echo test
赋值:
:let foo.x = 11
字典方法:
get(dict, key, default)
has_key(dict, key) " 返回0/1
items(dict) " 返回list
:echo items({'a': 100, 'b': 200}) 返回 [['a', 100], ['b', 200]]
三、Vimscript 变量
变量赋值
:let foo = "bar"
:echo foo
使用 let 关键字,等号左右可以有空格也可以没有,直接使用变量名。
使用变量 scope 指定为当前 buff 的 local 变量:
:let b:foo = "bar"
:echo b:foo
g: 代表 global。
选项变量
:set textwidth=80
:echo &textwidth
使用 set 关键字,当变量为设置选项时,等号左右不能有空格,而且 echo 时必须加 &。也可以使用 let 赋值,但是前面要加 &::let &textwidth = 100。
Local 选项变量
在同一窗口 split 多个窗口,在不同的窗口设置自己的 local 变量:
:let &l:number = 1
注册变量:
:let @h = 'hi axiaoxin' " 现在按 "hp 将 h 中保存的值粘贴到当前位置
选中文字按 y 复制后,执行 :echo @" 便可以打印出按 y 复制的值。
:echo @/ 可以查看查找过的文字,如果没有查找过则返回 noh,noh 就是在你查找高亮后取消高亮的命令 :noh。
四、Vimscript 控制结构
if 语句
1 代表 True,0 代表 False,非空字符串如果不是数字开头被强制转换为 0(False),数字字符串或数字开头的字符串为 True:
:if 1
: echom "ONE" "display
:endif
:if 10 > 1
: echom "foo" "display
:elseif 100 == 10
: echom "bar"
:else
: echom "ooxx"
:endif
:if "9024"
: echom "WHAT?!" "display
:endif
:if "something"
: echom "INDEED" "no display
:endif
当比较字符串的时候不要使用 == 来判断相等,因为有 :set ignorecase 和 :set noignorecase 来修改是否区分大小写。如果 :if "foo" == "FOO" 前被添加了 :set ignorecase,该判断依旧为 True。
正确的方式应该总是使用 ==? 和 ==# 来判断,无论是否使用 set ignorecase or noignorecase,? 总是不区分大小写,而 # 总是区分大小写,< > 同样适用:
:if "foo" ==# "FOO"
: echom "no, it couldn't be"
:elseif "foo" ==# "foo"
: echom "this must be the one"
:endif
五、Vimscript 布尔设置开关
所有布尔设置都是通过 :set <name> 来开启,通过 :set no<name> 来关闭。
也可以用 toggle 来设置自动开或关,:set <name>!。
检查某个布尔设置的开关情况可以使用 :set <name>?,比如查看是否显示行号用 :set number?,如果是显示行号则显示 number,不显示行号显示为 nonumber。
特别笔记下 :set shiftround 命令,其作用是在你按 > 或 < 或者是在插入模式下按 C-T 或 C-D 时的缩进取整对齐。比如我设置了 :set shiftwidth=4,然后有如下缩进不规则的文本:
asdasd
asd
先 :set noshiftround,然后光标移动到行首,按 >> 将其缩进一次,输出为:
asdasd
asd
然后再按一次 >>,输出为:
asdasd
asd
最后再按一次 << 将其反向缩进,输出为:
asdasd
asd
可以看出,没有使用 shiftround,缩进时文本会不规则,而使用 shiftround 后的缩进更加整齐。
六、Vimscript 函数定义与调用
1. 定义函数
使用 function 定义函数,endfunction 结束函数,函数参数用 a: 作为前缀:
function! MyFunction(arg1, arg2)
return a:arg1 + a:arg2
endfunction
调用函数时使用 call:
:let result = call('MyFunction', [5, 10])
:echo result " 15
2. 匿名函数
可以使用 function 直接定义匿名函数,但无法通过 call 直接调用,只能使用 :execute:
:execute 'call function("add", [5, 10])'
3. lambda 表达式
Vim 8.0 之后支持 lambda 表达式,使用 {} 定义:
:let add = {a, b -> a + b}
:echo add(5, 10) " 15
七、Vimscript 按键映射
在 Vim 中,可以使用 nnoremap、inoremap、vnoremap 等命令进行按键映射。
1. 普通模式映射
使用 nnoremap 进行普通模式的映射:
:nnoremap <F5> :echo "Hello, World!"<CR>
2. 插入模式映射
使用 inoremap 进行插入模式的映射:
:inoremap jk <Esc>
3. 可视模式映射
使用 vnoremap 进行可视模式的映射:
:vnoremap <C-c> "+y
八、总结与建议
Vimscript 是 Vim 的强大脚本语言,掌握其基本用法可以极大提升您的 Vim 使用效率。可以从常用的命令、数据类型、函数、按键映射等方面入手,逐步熟悉并灵活应用这些知识。
建议多实践,尝试编写一些简单的 Vim 插件或配置,逐渐深入了解 Vimscript 的魅力。同时,定期查阅 Vim 的帮助文档,学习更多的内置函数和命令,保持对 Vim 的探索与热爱。








