1.1 Hello World 的四种写法

第一章 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!' 这一行就够了。几点说明:

  1. 前面以一个双引号 " 开始的行是注释,注释也可以写在行尾。
  2. 在脚本文件中,echo 命令前不必加冒号 :,但是加上冒号也是允许的。
  3. 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 ic 命令(vimer 有点眼熟吧),不过编辑完后也无从知 晓结果是否正确,可能还需要再用 p 命令打印查看确证。

之后,有个 ex 编辑器,不过是对 ed 的命令进行了扩展,本质上仍是行编辑器。直 到 vi 横空出世,那才叫“屏幕编辑器”。意思是可以全屏显示文件的许多行,移动光标 实时修改某一可见行,修改结果即时显示……这才像我们现在可认知的编辑器了。

然后是 vimvi 的扩展增强。事实上,vim 还不如 vi 的划时代意义,它的 增强与此前 exed 的增强是差不多的程度,基本上是平行扩展。

可视化程度不是越高越好。 vimvi 都保留与继承了 ex 的命令,因为 ex 命令确实高效,当你能确知一个命令的运行结果,就没必要关注中间过程了。比如最平凡 无奇但常用的 ex 命令就是 :s 全局替换命令。

VimL 语言就是基于 ex 命令的,再加上一些流程控制,就成了一种完整的脚本语言。 如果说 vimvi 有什么压倒性的里程碑意义,我觉得应是丰富完善了 VimL 语言 ,使得 vim 有了无穷的扩展与定制。利用 VimL 写的插件,既可以走增加可视化的方 向,也可以不增加可视化而偏向自动化。依每人的性格习惯不同,可能会在 Vim 的可视 化与自动化之间找到适合自己的不同的平衡点。