Vimscript 学习笔记

这篇文章是学习Vimscript的一些笔记,涉及少量的使用技巧。主要是知识点的罗列,不涉及实战。

作为一个Vimer用了这么久vim,其实Vimscript一直是一知半解,从刚开始接触的时候复制别人的配置,到现在的各种需求已经无法满足。看着自己1000+行的vimrc,看来是很有简化和优化的必要,这篇文章是学习Vimscript的一些笔记。

本文写作使用的vim版本:8.1.177,+gui,文中的测试都是在此之上进行的

使用技巧

这里是对使用技巧的补充,不涉及脚本。纯粹是在学脚本的过程中顺便学习到的(有点惭愧,:-\)

  • CTRL-T 插入模式缩进当前行
  • CTRL-D 插入模式反缩进当前行
  • CTRL-W 插入模式删除前一个单词
  • CTRL-U 插入模式删除行
  • CTRL-A 增加数字
    • 插入模式下重复上一次插入模式插入的所有内容
  • CRTL-X 减少数字(目前设置为0开头八进制 0x开头十六进制)
  • 插入模式下CTRL-G+u设置undo点,下一次普通模式的undo会从这里截止(准确地说是在插入的文本打上undo节点,这和脚本结合非常强大)

非脚本特性

实用命令

  • :execute 将字符串里的内容当作命令执行,同时对其中的特殊字符进行转义,比如\r,\\。后面需要<cr>
  • :normal 将命令当作普通模式的键入而操作,只是键入,不会解释<cr>之类的特殊字符,要这样做需要在外部使用execute输入特殊字符
    • :normal! 忽略用户定义的映射
    • 总是使用normal!
  • execute “normal! xxxx"是很好的组合

消息

  • :echo 打印消息,空格分割表达式 “\n”换行
    • 不会扩展,比如%,需要使用expand
    • 可以使用外部echo,%会被扩展但是会暂时退出vim
  • :echom 打印消息,添加至消息历史,但是不打印特殊字符
  • :messages 查看消息历史 大部分情况下可以记录100条(history可以设置记录条数)
    • :echo errmsg 可以打印错误信息

选项

格式

  • set <bool>
  • set no<bool>
  • set <bool>! 切换开关
  • set <bool>? 查看当前值
  • set <name> = <value>
  • setlocal 设置选项为针对缓冲区,但并非所有时候都有效

一些选项

  • showmatch 插入配对符号时短暂跳转到对应符号 matchtime 设置十分之一秒数
  • wrap 设置长行是否回旋
  • shiftwidth 自动缩进空白数
  • statusline 状态条显示的格式 注意空格需要转义
  • hlsearch 高亮搜索结果
  • incsearch 实时搜索

映射

  • 普通的映射可以依次被解析,也许是优点,不过更多是缺点,只需要考虑递归的映射就可以了
  • noremap 系列不会进行递归
    • 尽量使用非递归的映射 或者说得直白:只用noremap
  • 在lfs前加入<buffer>创建本地映射。本地映射会覆盖全局映射
  • onoremap 是对移动操作符的映射,只有在操作符之后接上这些映射才会生效
    • 结合本地映射、exe、normal、regex、自动命令可以相当强大

Leader

  • :let mapleader=
  • :let maplocalleader=

缩写

  • iabbrev 插入模式下输入非字母数字下划线引发自动替换
  • 和inoremap的不同是缩写只会对独立的单词有效
  • 类似,加入<buffer>创建本地缩写

正则表达式

vim默认的正则表达式需要对正则的特殊符号转义,要使用通常意义下的正则方式,可以输入\v,则之后的模式按照一般正则的规则进行。

要使用vim的默认模式,但避免双重反斜杠的话,可以用下面所说的单引号字面量,但是就不能转义回车一类的不可输入字符。

解决办法是用.操作符连接,使用双引号输入不可输入字符

自动命令

  • :autocmd <事件> <模式> <命令>
  • 可以创建绑定多个事件的自动命令
    • BufRead BufNewFile应该一起使用,这样无论是新建还是读取都有效
    • BufWritePre 写入数据前的操作
    • FileType 设置文件类型的事件
  • 和缩写结合,可以创建高效的Snippets

自动命令组

  • :augroup <name>
  • :augroup END
  • 可以给自动命令分组,之后主动调用或者删除的时候可以按组进行
  • 有一个作用是防止重复定义相同的自动命令(重复载入配置时),只需要在组内加入autocmd!
    • autocmd!删除当前组的所有自动命令,不在组内则是默认的全局

脚本语言

管道符|用于分割不同命令。命令被认为是独立而顺序执行

字面量

数字

  • 整数 可以使用十六进制、八进制。但如果八进制写法有误,隐式转化十进制
  • 浮点数 可以用科学计数法
  • 强制类型转换:从整数到浮点数。
  • 除法: 除非整数相除舍弃余数,否则是浮点数除法

字符串

  • 字符串连接符是.而不是+(+只对数有效。对字符串用+会强制转换为整数,它甚至不能转换为浮点数)
  • .操作符如果对非字符串使用也会强制转换,但一样只对整数有效
  • TIP:显示调用函数转换类型,不要进行强制转换。
  • 可以在字符串里转义,但是只对echo有效。echom会输出特殊字符
  • 用单引号定义的字符串不需要转义,除非是用两个单引号表示单引号。类似于py的r字面量。

变量

  • 变量用关键字let设置
  • 选项可以作为变量使用,可以理解为对选项值“引用”
    • 格式为&选项名
  • 选项也可以通过引用+let设置,和set的不同是可以通过脚本的特性在运行时计算选项值,而不是set所设置的固定值
    • 如:
      1
      
      let &textwidth=&textwidth +10
      
  • 寄存器的值也可以被作为变量。
    • 格式为@x
    • 寄存器:
      • _ 寄存器 类似于/dev/null,文档称为黑洞寄存器
      • 无名寄存器"是默认的寄存器,不管有没有指定目标,最近的操作都会被存在这个寄存器里
      • /寄存器存储了搜索模式
      • 英文字母代表的寄存器可以通过大写和小写访问,大写是追加,小写是覆盖。只有主动指定才使用这些
      • -寄存器是行内删除时存储删除内容的寄存器
      • 0寄存器是最近抽出的文本,除非特别指定
      • 1~9寄存器是最近删除或修改,且不存储在行内寄存器的文本。随着修改,寄存器的值依次复制到后一个寄存器。直到9寄存器后被丢弃
      • . 寄存器只读, 有最近插入的文本。类似于插入模式ctrl-a的效果
      • % 寄存器只读。有当前文件名
      • : 寄存器只读。保存上一次执行的命令行,但映射除外。可以用@:重复。
      • + * ~和gui剪贴板相关;
      • = 表达式寄存器。当使用@=时会交互输入表达式并执行
    • @x 执行寄存器的内容
    • qx 将按键输入存入寄存器

变量作用域

字符: 代表作用域
b: 局部于当前缓冲区。
w: 局部于当前窗口。
t: 局部于当前标签页。
g: 全局。
l: 局部于函数。
s: 局部于:source的 Vim 脚本。
a: 函数参数 (只限于函数内使用)。
v: Vim 预定义的全局变量。

分支语句

  • if的判断值是通过整数来判断,其他类型的变量会被强制转换
1
2
3
if command 
    echo "hi"
endif
- 比如字符串,如不能转换为数字,则为0(false)
  • elseif
  • else

比较运算

  • 字符串的==比较运算符 大小写是否敏感是由ignorecase的设置决定的
  • 使用==# 无论如何大小写敏感
  • 或者==? 无论如何大小写不敏感
    • Tip: 一直使用==#或者==?

函数

  • function关键字定义函数
  • 函数的首字母必须大写(不一定是必须的,不过是大多数人的标准)
  • 调用函数:
    1. 使用call,函数返回值会被丢弃
    2. 将函数用在任意一个表达式中,取决于返回值。如果函数没有返回值,返回0
  • 本人测试:可以使用下划线,不能用重音符号和点,不能用unicode
  • return关键字返回值
  • 函数体内使用参数需要a:作用域符(见上)
  • 参数无法在函数体内被赋值,但可以被拷贝。除非传入的是列表或字典,则可以对其元素进行操作

可变参数

1
2
3
4
5
6
function foo(bar,...)
    echo a:bar
    echo a:0
    echo a:1
    echo a:000
endfunction

可变参数用…指定,这样,0将被设置为额外可变参数的数量,从1开始是传入的额外可变参数。000是所有可变参数的列表

内置函数

部分的:

函数 作用 参数
strlen 字符串长度 string
split 切割字符串 string,分隔符
join 连接字符串 string的列表,分隔符
tolower/toupper 转换大小写 string
add 列表尾部增添元素 元素
len 列表长度 列表
get 可以设定默认值的列表元素访问 列表,索引值,默认值
index 列表中元素第一次出现处 列表,键值
join 将列表元素以字符串形式拼接 列表,分隔符
reverse 就地反转列表 列表

全部函数使用:h functions 查看

关于实战,将在后续单独post中讲述。接下来我会对我又臭又长的vimrc进行一次修改:)

发表于 2018-07-13
JS
Arrow Up