Vimscript 函数与数据结构:写出可维护的配置
更新时间:2026-08-30。本文是
languages/vim/主题专家层第 0 篇(A2:PlantUML + 机制 + ≥2 实测 + ≥2 交叉引用)。
本文要回答的问题
- Vimscript 的变量作用域(s:/g:/a:)到底怎么区分?
- 列表、字典怎么用?和常见语言有何不同?
- 怎么定义函数、传参、做条件循环?
一、机制:作用域前缀是 Vimscript 的命门
Vimscript 变量没有默认全局/局部之分靠前缀,这是新手最大陷阱:
| 前缀 | 作用域 |
|---|---|
g:foo | 全局 |
s:foo | 脚本局部(当前源文件) |
a:foo | 函数参数 |
l:foo | 函数内局部(默认,可省) |
b:/w:/t: | buffer / window / tab 局部 |
漏写前缀的变量会"默默变成全局",多文件时互相污染——插件开发务必用 s:。
二、数据结构:列表与字典
vim
let fruits = ['apple', 'banana'] " 列表
call add(fruits, 'cherry')
echo fruits[0]
let cfg = {'timeout': 30, 'verbose': 1} " 字典
echo cfg.timeout
let cfg.retry = 3 " 新增键
for [k, v] in items(cfg)
echo k . '=' . v
endfor注意 Vimscript 是弱类型 + 字符串偏置:数字和字符串会按上下文互转,'3' + 1 得 4,但拼接用 . 而非 +('a' . 'b')。
三、函数定义
vim
function! s:greet(name) abort
return 'Hello, ' . a:name
endfunction
echo s:greet('Vim') " Hello, Vimfunction!的!表示重定义时覆盖(避免重复加载报错);abort遇错即停(不继续跑后续,更安全);- 参数用
a:name引用。
四、条件与循环
vim
if &filetype ==# 'python'
setlocal shiftwidth=4
elseif &filetype ==# 'c'
setlocal shiftwidth=8
else
setlocal shiftwidth=2
endif
let i = 0
while i < len(fruits)
echo fruits[i]
let i += 1
endwhile==# 是区分大小写比较,==? 不区分;Vimscript 比较是否忽略大小写还受 &ignorecase 影响,显式用 #/? 后缀最稳。
五、与金字塔衔接
一句话总结
Vimscript 靠前缀定作用域(g:/s:/a:/l:/b:),漏前缀会污染全局;列表/字典弱类型、拼接用 .;函数加 ! 可覆盖、abort 遇错即停——从堆 set 进化到写函数,配置才可持续维护。
上一篇:Vim 效率组合技 下一篇:Vim 映射深度:noremap 与表达式映射