第一章 VimL 语言主要特点
1.1 Hello World 的四种写法
按惯例,我们讨论一门语言,首先看下如何写最简单的 “Hello World” (程序)。 由于 Vim 是高度自由的,VimL 也有多种不同的方式玩转 “Hello World”。
速观派:直接操起命令行
最快速的办法是在 Vim 命令行下用 :echo
命令输出 “Hello World”:
: echo 'Hello World!'
唯一需要注意的是,得把 “Hello World” 用引号括起来,单引号或双引号都可以。 这样再按下回车就能在 Vim 的消息区显示出 “Hello World” 这行字符串了。
由于这条消息字符串很简短,一行就能显示完整,Vim 将其直接显示在命令行的位置,并 且运行完直接返回 Vim 普通模式。如果字符串很长或多行字符串,则消息区将向上滚动 ,以显示完整的消息,用户需要额外按个回车才回普通模式。
试试在命令行输入这条命令,看看有啥不同反应:
: echo "Hello World! \n Hello World! \n Hello World!"
好了,你已经学会了如何用 VimL 输出 “Hello World” 了。这也算编程吗?别逗了!其 实,别把编程想得那么严肃,那这就算编程!
正规派:建立脚本文件
把刚才在命令行输入的那条命令保存在一个 .vim
后缀的文本文件中,那就是一个 vim script
了,这是用 VimL 编程比较正常的用法。
为了方便,建议在本地建个目录,用于保存本教程的示例代码。比如:
$ cd ~/.vim
$ mkdir vimllearn
$ vim vimllearn/hello1.vim
这将在 ~/.vim
目录下新建一个 vimllearn
目录,并用 vim 开始编辑一个名为 hello1.vim
的文件。vim 会为该文件新建一个缓冲区 buffer
,在该 buffer
中输 入以下文本,然后输入命令 :w
保存:
" 文件:hello1.vim
" 用途:VimL hello world 示例
" 作者:lymslive
" 时间:2017-08
echo 'Hello World!'
finish
脚本结束了,可以随便浪~~
不管写些什么乱七八糟的都木有关系。
你其实可以只在该文件中写入 echo 'Hello World!'
这一行就够了。几点说明:
- 前面以一个双引号
"
开始的行是注释,注释也可以写在行尾。 - 在脚本文件中,
echo
命令前不必加冒号:
,但是加上冒号也是允许的。 finish
表示直接结束脚本,在之后的语句都不再被 vim 解析;这是可选的,没有 遇到finish
就会执行到文件最后一行。
当有了 *.vim
脚本文件,就可以在 vim 环境中用 :source
命令加载运行了:
: source ~/.vim/vimllearn/hello1.vim
需要将脚本文件的路径写在 source
命令之后作为参数。如果当前 vim 正常编辑 hello1.vim
这个文件,则可用 %
表示当前文件的路径:
: source %
折腾并解释了这许久,终于可以通过 source
一个 vim 脚本打印输出 “Hello World” 了,与此前的效果是一样一样的。当然了,用 VimL 写脚本肯定不能只满足于写 “Hello World” 吧,所以这才是标准用法。
此外 Vim 的命令是可以简写的,source
可简写为 so
。当你在写一个 vim 脚本时想 快速验证执行该脚本时,可以只输入:
: so %
如果还想更省键,就定义一个快捷键映射吧,比如:
: nnoremap <F5> :update<CR>:source %<CR>
可以将这行定义加入你的 vimrc
中,不过最好是放在 ~/.vim/ftplugin/vim.vim
中 ,并加上局部参数,让它只影响 *.vim
文件:
: nnoremap <buffer> <F5> :update<CR>:source %<CR>
测试派:进入 Ex 模式
直接在命令行用 :echo
查看一些东西其实很有用的,可以快速验证一些记不清楚的细 节。比如你想确认下在 VimL 中字符 '0'
是不是与数字 0
相等,可以这样:
: echo '0' == 0
但如果要连续输入多条命令并查看结果,每次都要(从普通模式)先输入个冒号,不免有 些麻烦。这时,Ex
模式就有用了。默认情况下(若未在 vimrc 被改键映射),在普通 模式下用 Q
键进入 Ex
模式。例如,在 Ex
模式下尝试各种输出 “Hell World” 的写法,看看不同引号对结果的影响:
Entering Ex mode. Type "visual" to go to Normal mode.
: echo 'Hello World!'
: echo "Hello World!"
: echo 'Hello \t World! \n Hello \t World!'
: echo "Hello \t World! \n Hello \t World!"
: vi
最后,按提示用 visual
或简写 vi
命令回到普通模式。
Vim 的 Ex
模式有点像 VimL 的交互式的解释器,不过语法完全一样(有些脚本语言的 交互式解释器与执行脚本有些不同的优化),仍然要用 echo
显示变量的值。
*索隐派:从 shell 直接运行
如果只为了运行一个 vim script 脚本,也不一定要先启动 vim 再 source
,直接在启 动 vim 时指定特定参数也能办到。-e
参数表示以 Ex
模式启动 vim,-S
参数启 动后立即 source 一个脚本。因此,也可以用如下的命令来输出 “Hello World”:
$ cd ~/.vim/vimllearn
$ vim -eS hello1.vim
这就相当于使用 vim
解释器来运行 hello
.vim这个脚本,并且停留在交互式界面 上。此时可以用
:q命令退出,或
:vi` 以正常方式继续使用 Vim。
vim 本身的命令行启动参数其实还支持很多功能,请查阅 :help starting
。其中还有 个特殊的参数是 -s
,如果与 -e
联用,就启动静默的批处理模式,试试这个:
$ vim -eS hello1.vim -s
没有任何反应输出?因为 -s
使普通的 echo
提示无效,看不到任何提示!赶紧输入 q
回车退出 vim 回到 shell。因为如果不小心按了其他键,vim 可能就将其当作命令 来处理了,而且不会有任何错误提示,这就会让大部分人陷入不知如何退出 vim 的恐慌 。
虽然 vim -e -s
不适合来输出 “Hello World”,但如果你的脚本不是用来做这种无聊 的任务,这种模式还是有用的。比如批处理,在完全不必启动 vim 可视编辑的情况下, 批量地对一个文件或多个文件执行编辑任务。可达到类似 sed
的效果。而且,在 vim 脚本写好的情况下,不仅可以按批处理模式执行,也可以在正常 Vim 可视编辑某个文件 时,遇到类似需求时,也可以再手动 :source
脚本处理。
小结
运行 vim 脚本的常规方法用 :source
命令,而且有很多情况下并不需要手动输入 :source
命令,在满足一定条件下,vim 会自动帮你 source 一些脚本。vim 的启动参 数 -S
其实也是执行 :source
。
Vim 的命令行可以随时手动输入一些简短命令以验证某些语法功能,进入 Ex
模式则可 以连续手动输入命令并执行。Ex
模式虽然比较少用,但不该反感排斥,这对学用 VimL 还是大有裨益的,以后会讲到,VimL 的 debug 功能也是在 Ex
模式中的。
静默批处理 vim -e -s
本质上也是 Ex
模式,不过禁用或避免了交互的中断。属于 黑科技,一般的 vim 用户可先不必深究。
*拓展阅读:Vim 与可视化
“可视化”是个相对的概念。现在说到可视化,似乎是指功能丰富的 IDE 那种,有很多辅 助窗口展示各方面的信息,甚至有图形化来表示类层次关系与函数调用关系。还有传说中 的唯一的中文编程语言“易语言”还支持图文框拖拖拽拽就能编写代码的东东……而 vim 这 种古董,只有编辑纯文本,似乎就该归属于“不可视”。
然而,让我们回顾洪荒时代,体验一下什么叫真正的“不可视”编辑。
在 Vi 都还没诞生的时代,有一个叫 ed
的行编辑器,它只能通过命令以行为单位去操 作或编辑文本文件。它完全没有界面,无从知道当前编辑的是哪个文件,在哪行,当前行 是什么内容,用户只能“记住”,或用命令查询。比如用 p
命令打印显示当前行(不过 也可以在前面带上行地址打印多行,至今 vim
的大部分命令都可以带地址参数)。要 编辑当前行,请用 a
i
或 c
命令(vimer 有点眼熟吧),不过编辑完后也无从知 晓结果是否正确,可能还需要再用 p
命令打印查看确证。
之后,有个 ex
编辑器,不过是对 ed
的命令进行了扩展,本质上仍是行编辑器。直 到 vi
横空出世,那才叫“屏幕编辑器”。意思是可以全屏显示文件的许多行,移动光标 实时修改某一可见行,修改结果即时显示……这才像我们现在可认知的编辑器了。
然后是 vim
对 vi
的扩展增强。事实上,vim
还不如 vi
的划时代意义,它的 增强与此前 ex
对 ed
的增强是差不多的程度,基本上是平行扩展。
可视化程度不是越高越好。 vim
与 vi
都保留与继承了 ex
的命令,因为 ex
命令确实高效,当你能确知一个命令的运行结果,就没必要关注中间过程了。比如最平凡 无奇但常用的 ex
命令就是 :s
全局替换命令。
VimL 语言就是基于 ex
命令的,再加上一些流程控制,就成了一种完整的脚本语言。 如果说 vim
对 vi
有什么压倒性的里程碑意义,我觉得应是丰富完善了 VimL 语言 ,使得 vim
有了无穷的扩展与定制。利用 VimL 写的插件,既可以走增加可视化的方 向,也可以不增加可视化而偏向自动化。依每人的性格习惯不同,可能会在 Vim 的可视 化与自动化之间找到适合自己的不同的平衡点。