Vimscript

:help eval 查看Vimscript的帮助

set 内部选项 = 值 对内部选项赋值
let &内部选项 = 值 用let为内部选项赋值
let @寄存器 = 值 用let为寄存器赋值
let 变量名 = 值 对用户变量赋值

变量名和函数名前可加上命名空间

let g:global_var = 'Hello'
function g:HelloWorld()
let l:local_var = 'World'
echo g:global_var . ' ' . l:local_var
endfunction

g 全局命名空间(全局变量默认使用的命名空间)
l 局部命名空间(函数内的变量默认使用的命名空间)
a 函数参数命名空间
v 为Vim定义的全局命名空间
b 当前缓冲区
w 当前窗口
t 当前标签页
s 局部文件命名空间(使用 :so[urce] 执行)

Vimscript没有布尔类型, 1为真, 0为假.

'值' 字符串
"值" 字符串(支持非字面量字符), 与注释用的符号相同

:h list

let animals = ['cat', 'dog', 'parrot']
let cat = animals[0]
let parrot = animals[-1]
let slice = animals[1:] " ['dog', 'parrot']
let slice = animals[0:1] " ['cat', 'dog']
let animals = add(animals, 'octopus') " 尾部追加
let animals = insert(animals, 'bobcat') " 头部追加
" Vimscript的函数调用除非是在表达式内部, 否则需要用关键字call
call add(animals, 'octopus')
call insert(animals, 'bob'cat', 2) " 第三个参数可省略, 为添加的索引位置
unlet animals[2] " 删除元素
unlet animals[:1] " 删除切片
call remove(animals, -1) " 删除元素
call remove(animals, 0, 1) " 删除切片
let mammals = ['dog', 'cat']
let birds = ['raven', 'parrot']
let animals = mammals + birds " 联结
call extend(mammals, birds) " 联结到第一个变量
call sort(animals) " 排序
let i = index(animals, 'parrot') " 查找元素索引
" 判断列表是否为空
if empty(animals)
echo 'There aren''t any animals!'
endif
len(animals) " 列表长度
count(animals, 'cat') " 元素在列表内的个数

:h dict

let animal_names = {
\ 'cat': 'Miss Cattington',
\ 'dog': 'Mr Dogson',
\ 'parrot': 'Polly'
}
let cat_name = animal_names['cat']
let cat_name = animal_names.cat
let animal_names['raven'] = 'Raven R. Raventon'
unlet animal_names['raven']
let raven = remove(animal_names, 'raven)
call extend(animal_names, { 'bobcat': 'SirMeowtington' })
if !emtpy(animal_names)
echo 'We have names for ' . len(animal_names) . ' animals'
endif
if has_key(animal_names, 'cat')
echo 'Cat''s name is ' . animal_names['cat']
endif

. 连接两个字符串
'' 在字符串里使用单引号(输入两次单引号)

&&
||
!

== " 比较字符串是否相等(是否忽略大小写取决于内部选项ignorecase的设置)
==? " 比较字符串是否相等, 忽略大小写
==# " 比较字符串是否相等, 考虑大小写
=~ " 左值是否匹配右值的模式
=~? " 忽略大小写版本
=~# "考虑大小写版本k
!~ " 左值是否不匹配右值的模式
!~? " 忽略大小写版本
!~# " 考虑大小写版本
if g:animal_kind == 'cat'
echo g:animal_name . ' is a cat'
elseif g:animal_kind == 'dog'
echo g:animal_name . ' is a dog'
else
echo g:animal_name . ' is something else'
endif
" 三元运算符
echo g:animal_name . (g:is_cat ? ' is a cat' : ' is something else')

支持 break 和 continue

" list
for element in list
echo element
endfor
" dict
for key in keys(dict)
echo dict[key]
endfor
for [key, value] in items(dict)
echo key . ' ' . value
endfor
while !empty(list)
echo remove(list, 0)
endwhile

函数需以大写字符开头

function CreateDebugString(text)
return 'Debug: ' . a:text " 函数访问参数需要a命名空间
endfunction
" 由于函数被定义多次会报错(由于:source命令), 需要加上!表示强制定义
function! HelloWorld()
echo 'Hello World'
endfunction
function! ListArgs(first, ...)
echo a:first " 参数列表可与普通参数混用
echo a:000 " 获取参数列表
echo a:1 " 获取参数列表的第一项
echo a:2 " 获取参数列表的第二项
endfunction
let animl_names = {
\ 'cat': 'Miss Cattington',
\ 'dog': 'Mr Dogson',
\ 'parrot': 'Polly'
}
function animal_names.GetGreeting(animal)
return self[a:animal] . ' says hello'
endfunction
echo animal_names.GetGreeting('cat')
let animals = {
\ 'animl_names' = {
\ 'cat': 'Miss Cattington',
\ 'dog': 'Mr Dogson',
\ 'parrot': 'Polly'
\ }
}
function GetGreeting(animal)
return self.animal_names[a:animal] . ' says hello'
endfunction
let animals['GetGreeting'] = function('GetGreeting') " function(函数名字符串) 创建函数引用
echo animal_names.GetGreeting('cat')
let AnimalGreeting = { animal -> animal . ' says hello'
echo AnimalGreeting('cat')
function IsProperName(name)
if a:name =~? '\(Mr\|Miss\) .\+'
return 1
endif
return 0
endif
let animl_names = {
\ 'cat': 'Miss Cattington',
\ 'dog': 'Mr Dogson',
\ 'parrot': 'Polly'
}
call filter(animal_names, 'IsProperName(v:val)')
" v:key 展开字典键 或 列表索引
" v:val 展开字典值 或 列表元素
" 使用函数引用作为参数时, 需要准备合适的函数参数
function IsProperNameProxy(key, value)
return IsProperName(a:value)
endfunction
call filter(animal_names, function('IsProperNameProxy'))
" 使用Lambda作为参数
call map(animal_names, { key, val -> IsProperName(val) ? val : 'Miss ' . val })

检查当前Vim是否支持某个特性

:h feature-list 查看完整的特性列表(其中也包含操作系统的标识符)

if has('python3')
echom '当前Vim在编译时启用了Python 3支持'
endif

对文件路径进行操作

echo expand('%') " 输出当前文件名
echo expand('%:e') " 输出当前文件扩展名
" :p 展开为完整路径 absolute
" :h 路径头 去除最后一节(例如将文件路径的文件部分去掉变成目录路径)
" :t 路径尾 与:h相反的操作, 只保留最后一节(只保留文件名部分)
" :e 文件扩展名
" :r 根路径 与:e相反的操作, 去除文件扩展名

接受对话形式的用户输入(yes/no/cancel)

let answer = confirm('Are you ok?', "&yes\n&no") " &后的字符决定按哪个键有效, \n为不同选项的分隔符
echo answer " cancel为0, 其他选项按显示顺序依次返回递增数字1, 2, 3...

接受用户输入

let animal = input('What is your favorite animal?')
echo "\n"
echo animal
" 当相关函数用于键盘映射时, 需要将input放在inputsave和inputrestore调用之间以避免后续的映射内容被input获取, 建议在任何情况下都使用下述方法(或编写一个符合此模式的专门函数)
inputsave()
let text = input('Please input: ')
inputrestore()

echo 变量名 打印内容
echom[sg] 变量名 打印内容到当前会话的消息日志
messages 查看当前会话的消息日志

即vimscript的eval函数

execute 'echo ' . animal .' says hello'

用于执行按键序列, 相当于在正常模式下输入对应的按键

normal /cat^Mdw " 此处的^M并非字符串, 而是通过<C-v><Cr>输入得到的
normal! /cat^Mdw " 忽略用户定义的按键映射
silent echo 'Hello World' " 加在命令之前, 可隐藏命令的输出
silent !echo 'Hello World in a shell' " 也可隐藏在终端执行的外部命令的输出