小例子
新建一个vim脚本test.vim
,输入下面的代码,并保存
vim9script
var i = 1
while i < 5
echo "count is" i
i += 1
endwhile
然后输入
:source %
即可看到上述代码被执行。当然,source %
执行的是文本内容,对文件名的后缀是无要求的。但首行必须是vim9script
,表明此为vim9
脚本文件。
考虑到大部分vim使用者都是编程大佬,对于var i = 1
、while
等语句,但凡有一点编程直觉,都会看懂。
唯一需要说明的是,如果不小心写了死循环,可以通过Ctrl C
或者Ctrl
+Breakspace
终止。
下面对VIM9Script中通用的编程元素做一个基础的解释,包括变量、数据类型、运算符、函数以及控制流。
变量
VIM中的变量分为局部和全局变量两种,和一般编程语言不同,在VIM中所谓的全局变量,可以贯穿当前VIM程序打开的任何一个VIM脚本。
通过var
声明的变量为局部变量,通过g:
声明的变量则是全局变量。
例如在a.vim
中输入
vim9script
var test_a = 5
g:test_b = 6
保存并执行之后,在命令模式下调用这两个变量,
:source % #编译执行a.vim
:echo test_a #将会报错
:echo g:test_b
6
VIM中内置了一些全局变量,可输入:let
查看,在定义了g:test_b
之后,test_b #6
的确出现在了全局变量中。而通过:let
获取的全局变量,除了前面一些无后缀的变量名外,后面还出现了b:
、v:
等开头的变量。
这些变量也不同程度上具备全局性,其说明如下
buffer-variable | b: | 局部于当前缓冲区。 |
window-variable | w: | 局部于当前窗口。 |
tabpage-variable | t: | 局部于当前标签页。 |
global-variable | g: | 全局。 |
local-variable | l: | 局部于函数 (只限于老式函数内使用)。 |
script-variable | s: | 局部于 :source 的 Vim 脚本。 |
function-argument | a: | 函数参数 (只限于老式函数内使用)。 |
vim-variable | v: | Vim 预定义的全局变量。 |
g:test_b
只是一个临时用于演示的全局变量,其实是毫无卵用的,故而可用unlet
对其删除
:unlet g:test_b
这回再输入:let
调用全局变量就看不到test_b
了,而且echo
也会报错。
数据类型
在VIM9脚本中,字符串通过单引号或者双引号进行标识,区别在于,双引号字符串开启了反斜杠转义;单引号字符串中,除了单引号需要用两个单引号表示之外,不对任何其他字符做转义。
双引号中常见的转义字符有
\t | <Tab> | \n | 换行 |
\r | 回车 | \e | esc |
\b | 退格 | " | " |
\ | 反斜杠 | ||
\<C-W> | CTRL-W |
数值则可以为十进制、十六进制、八进制或者二进制
十进制 | 十六进制 | 八进制 | 二进制 |
---|---|---|---|
30 | 0x1e/0X1e | 0o36/0O36 | 0b00011110/0B00011110 |
echo
在打印数值时,会自动转为十进制,例如
:echo 0x15
21
由于echo
可以同时打印多组值,那么在打印两个负值时就会产生逻辑上的歧义。在VIM9中,会将第二个负号优先识别为减号,这当然是是符合程序员直觉的;如希望输出两个负值,那么可以将后面的值用括号括起来。
:echo -5 -5
-10
:echo -5 (-5)
-5 -5
尽管通过var
新建变量时并未说明数据类型,但VIM并不允许将一个数值变量重新赋值为字符串。换言之,VIM脚本是静态类型语言,之所以var a = 9
并未声明变量类型,得益于自动的类型推导。
如果一个变量尚未赋值,那么类型无从推导,就需要在声明时定义数据类型
vim9script
var name: string
var age: number
运算符
VIM中的运算符如下
+-*/% | 加减乘除余 |
a ? b : c | 三元表达式 |
== /!= | 等于/不等于 |
> /< />= /<= | 大于/小于/大于等于/小于等于 |
.. | 字符串连接 |
=~ /!~ | 字符串匹配/不匹配 |
条件和循环
VIM中通过if..elseif...else...endif
来完成条件语句
if {condition}
{statements}
elseif{condition}
{statements}
else
{statements}
endif
while
循环以endwhile
作为结尾标志,在循环语句中,可通过continue
来跳过某一次循环,通过break
跳出循环,这与大多数编程语言是一样的。
函数
在VIM中通过关键字def
定义函数,通过enddef
来结束函数,其基本方法如下,唯一需要注意的是,函数名必须以大写字母开始。
def Min(num1: number, num2: number): number
var smaller: number
if num1 < num2
return num1
else
return num2
endif
enddef
首行表示,这是一个名为Min
的函数,输入两个数字num1, num2
,输出也是一个数字,不难看出,其返回值是二者中间较小的那个。
return
后面可以接表达式,即上式可写为
def Min(num1: number , num2: number): number
return num1 < num2 ? num1 : num2
enddef
函数同样可以定义为全局的,例如
def g:Min(num1: number, num2: number): number
return num1 < num2 ? num1 : num2
enddef
这样,在编译后就可以在:
模式下直接调用了,编译时别忘了写vim9script
,以及保存。
:source %
:echo g:Min(5,1)
1
删除全局函数可用
:delfunction SetSyn
函数中return
并不是必须的,即函数并不一定要有返回值
def test(txt: string)
echo txt
enddef
当返回值定义为any
时,表示返回值数据类型不确定。
def GetValue(): any