本文根据 Devhints / Vim scripting 翻译。代码示例及版本范围沿用原文。原文标注更新日期:2020-07-05。
开始动手定制
let name = "John"
echo "Hello, " . name
你可以将其放入脚本中(script.vim)并运行它(:source script.vim),或者你也可以在普通模式下逐个输入这些命令,例如: :let 以及 :echo.
通过示例学习
function! SuperTab()
let l:part = strpart(getline('.'),col('.')-2,1)
if (l:part =~ '^\W\?$')
return "\<Tab>"
else
return "\<C-n>"
endif
endfunction
imap <Tab> <C-R>=SuperTab()<CR>
变量
定义
let var = "hello"
变量前缀
let g:ack_options = '-s -H' " g: global
let s:ack_program = 'ack' " s: local (to script)
let l:foo = 'bar' " l: local (to function)
该 s: 前缀也可用于函数名称。请参阅 :help local-variables
其他前缀
let w:foo = 'bar' " w: window
let b:state = 'on' " b: buffer
let t:state = 'off' " t: tab
echo v:var " v: vim special
let @/ = '' " @ register (this clears last search pattern)
echo $PATH " $ env
Vim 选项
echo 'tabstop is ' . &tabstop
if &insertmode
echo &g:option
echo &l:option
为 Vim 选项添加前缀 &
运算符
a + b " numbers only!
'hello ' . name " concat
let var -= 2
let var += 5
let var .= 'string' " concat
字符串
字符串
let str = "String"
let str = "String with \n newline"
let literal = 'literal, no \ escaping'
let literal = 'that''s enough' " double '' => '
echo "result = " . re " concatenation
另请参阅 :help literal-string 以及 :help expr-quote。参见: 字符串
字符串函数
strlen(str) " length
len(str) " same
strchars(str) " character length
split("one two three") "=> ['one', 'two', 'three']
split("one.two.three", '.') "=> ['one', 'two', 'three']
join(['a', 'b'], ',') "=> 'a,b'
tolower('Hello')
toupper('Hello')
另请参阅 :help functions
参见: 字符串函数
函数
函数
" prefix with s: for local script-only functions
function! s:Initialize(cmd, args)
" a: prefix for arguments
echo "Command: " . a:cmd
return 1
endfunction
参见: 函数
覆盖
function f1()
echo "f1"
endfunction
function! f1()
echo "f1 overridden"
endfunction
如果定义了两个同名函数,Vim 会抛出错误,提示该函数 f1 已存在。若要覆盖之前定义的同名函数,请添加 ! (置于 function 关键字之后)。
命名空间
function! myplugin#hello()
调用函数
call s:Initialize()
call s:Initialize("hello")
使用返回值
echo "Result: " . s:Initialize()
可中止
function! myfunction() abort
endfunction
发生错误时中止执行。
可变参数
function! infect(...)
echo a:0 "=> 2
echo a:1 "=> jake
echo a:2 "=> bella
for s in a:000 " a list
echon ' ' . s
endfor
endfunction
infect('jake', 'bella')
参见 :help function-argument。请参阅: 可变参数
循环
for s in list
echo s
continue " jump to start of loop
break " breaks out of a loop
endfor
while x < 5
endwhile
自定义命令
自定义命令
command! Save :set fo=want tw=80 nowrap
自定义命令以大写字母开头。 ! 如果命令已存在,则会对其进行重定义。
调用函数的命令
command! Save call <SID>foo()
function! s:foo()
...
endfunction
带参数的命令
command! -nargs=? Save call script#foo(<args>)
| 内容 | 内容 |
|---|---|
-nargs=0 | 0 个参数(默认) |
-nargs=1 | 1 个参数(包含空格) |
-nargs=? | 0 个或 1 个参数 |
-nargs=* | 0 个或多个参数(以空格分隔) |
-nargs=+ | 1 个或多个参数(以空格分隔) |
Flow
条件判断
let char = getchar()
if char == "\<LeftMouse>"
" ...
elseif char == "\<RightMouse>"
" ...
else
" ...
endif
真值性 (Truthiness)
if 1 | echo "true" | endif
if 0 | echo "false" | endif
if 1 "=> 1 (true)
if 0 "=> 0 (false)
if "1" "=> 1 (true)
if "456" "=> 1 (true)
if "xfz" "=> 0 (false)
无布尔类型。 0 为假, 1 为真。请参阅: 真值性 (Truthiness)
运算符
if 3 > 2
if a && b
if (a && b) || (c && d)
if !c
参见 :help expression-syntax。参见: 运算符
字符串
if name ==# 'John' " case-sensitive
if name ==? 'John' " case-insensitive
if name == 'John' " depends on :set ignorecase
" also: is#, is?, >=#, >=?, and so on
同一性运算符
a is b
a isnot b
检查是否为同一个实例对象。
正则表达式匹配
"hello" =~ 'xx*'
"hello" !~ 'xx*'
"hello" =~ '\v<\d+>'
\v 启用“扩展”正则表达式模式,支持单词边界(<>), +等。
单行
if empty(a:path) | return [] | endif
a ? b : c
使用 | 用于将多行合并在一起。
布尔逻辑
if g:use_dispatch && s:has_dispatch
···
endif
列表 (Lists)
列表 (Lists)
let mylist = [1, two, 3, "four"]
let first = mylist[0]
let last = mylist[-1]
" Suppresses errors
let second = get(mylist, 1)
let second = get(mylist, 1, "NONE")
函数
len(mylist)
empty(mylist)
sort(list)
let sortedlist = sort(copy(list))
split('hello there world', ' ')
连接
let longlist = mylist + [5, 6]
let mylist += [7, 8]
子列表
let shortlist = mylist[2:-1]
let shortlist = mylist[2:] " same
let shortlist = mylist[2:2] " one item
推送 (Push)
let alist = [1, 2, 3]
let alist = add(alist, 4)
映射 (Map)
call map(files, "bufname(v:val)") " use v:val for value
call filter(files, 'v:val != ""')
字典
字典
let colors = {
\ "apple": "red",
\ "banana": "yellow"
}
echo colors["a"]
echo get(colors, "apple") " suppress error
参见 :help dict
使用字典
remove(colors, "apple")
" :help E715
if has_key(dict, 'foo')
if empty(dict)
keys(dict)
len(dict)
max(dict)
min(dict)
count(dict, 'x')
string(dict)
map(dict, '<>> " . v:val')
迭代
for key in keys(mydict)
echo key . ': ' . mydict[key]
endfor
前缀
keys(s:)
前缀(s:, g:, l:等)实际上就是字典。
扩展
" Extending with more
let extend(s:fruits, { ... })
类型转换(Casting)
str2float("2.3")
str2nr("3")
float2nr("3.14")
数字
数字
let int = 1000
let int = 0xff
let int = 0755 " octal
参见 :help Number。参见: 数字
浮点数
let fl = 100.1
let fl = 5.4e4
参见 :help Float
算术运算
3 / 2 "=> 1, integer division
3 / 2.0 "=> 1.5
3 * 2.0 "=> 6.0
数学函数
sqrt(100)
floor(3.5)
ceil(3.3)
abs(-3.4)
sin() cos() tan()
sinh() cosh() tanh()
asin() acos() atan()
Vim 特有用法
执行命令
execute "vsplit"
execute "e " . fnameescape(filename)
运行 ex 命令(通常在 Vim 中使用的命令) :. 另请参阅 :help execute。参见: 执行命令
执行按键序列
normal G
normal! G " skips key mappings
execute "normal! gg/foo\<cr>dd"
使用 :normal 模拟在普通模式(normal mode)下的按键输入。可结合 :execute 使用以实现特殊按键操作。参见: 执行按键序列
获取文件名
echo expand("%") " path/file.txt
echo expand("%:t") " file.txt
echo expand("%:p:h") " /home/you/path/file.txt
echo expand("%:r") " path/file
echo expand("%:e") " txt
参见 :help expand
静默处理
silent g/Aap/p
抑制输出。参见 :help silent
回响 (Echo)
echoerr 'oh it failed'
echomsg 'hello there'
echo 'hello'
echohl WarningMsg | echomsg "=> " . a:msg | echohl None
设置
set number
set nonumber
set number! " toggle
set numberwidth=5
set guioptions+=e
提示符
let result = confirm("Sure?")
execute "confirm q"
内置功能
has("feature") " :h feature-list
executable("python")
globpath(&rtp, "syntax/c.vim")
exists("$ENV")
exists(":command")
exists("variable")
exists("+option")
exists("g:...")
映射
映射命令
nmap
vmap
imap
xmap
nnoremap
vnoremap
inoremap
xnoremap
...
说明
[nvixso](nore)map
│ └ don't recurse
│
└ normal, visual, insert,
eX mode, select, operator-pending
参数
<buffer> | 仅在当前缓冲区(buffer)内生效 |
<silent> | 无回显 |
<nowait> |
语法
高亮显示
hi Comment
term=bold,underline
gui=bold
ctermfg=4
guifg=#80a0ff
文件类型检测
augroup filetypedetect
au! BufNewFile,BufRead *.json setf javascript
augroup END
au Filetype markdown setlocal spell
隐藏(Conceal)
set conceallevel=2
syn match newLine "<br>" conceal cchar=}
hi newLine guifg=green
区域隐藏
syn region inBold concealends matchgroup=bTag start="<b>" end="</b>"
hi inBold gui=bold
hi bTag guifg=blue
语法
syn match :name ":regex" :flags
syn region Comment start="/\*" end="\*/"
syn region String start=+"+ end=+"+ skip=+\\"+
syn cluster :name contains=:n1,:n2,:n3...
flags:
keepend
oneline
nextgroup=
contains=
contained
hi def link markdownH1 htmlH1
包含保护(Include guards)
if exists('g:loaded_myplugin')
finish
endif
" ...
let g:loaded_myplugin = 1