-
Notifications
You must be signed in to change notification settings - Fork 117
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit ee8e88e
Showing
35 changed files
with
8,591 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
*.pyc | ||
*.swp | ||
tags | ||
*.o | ||
*.out | ||
*.log | ||
core.* | ||
Session.vim | ||
Sessionx.vim | ||
*.tgz | ||
*.tar.gz |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
# VimL 语言编程指北路 | ||
|
||
## 初稿目录 | ||
|
||
+ [前言 ](./z/20170816_1.md) | ||
|
||
+ 第一章 VimL 语言主要特点 | ||
- [1.1 Hello World 的四种写法 ](./z/20170816_2.md) | ||
- [1.2 同源 ex 命令行 ](./z/20170816_3.md) | ||
- [1.3 弱类型强作用域 ](./z/20170816_4.md) | ||
- [1.4\* 自动加载脚本机制 ](./z/20170816_5.md) | ||
|
||
+ 第二章 VimL 语言基本语法 | ||
- [2.1 变量与类型 ](./z/20170817_1.md) | ||
- [2.2 选择与比较 ](./z/20170817_2.md) | ||
- [2.3 循环与迭代 ](./z/20170817_3.md) | ||
- [2.4 函数定义与使用 ](./z/20170817_4.md) | ||
- [2.5\* 异常处理 ](./z/20170817_5.md) | ||
|
||
+ 第三章 Vim 常用命令 | ||
- [3.1 选项设置 ](./z/20170818_1.md) | ||
- [3.2 快捷键重映射 ](./z/20170818_2.md) | ||
- [3.3 自定义命令 ](./z/20170818_3.md) | ||
- [3.4 execute 与 normal ](./z/20170818_4.md) | ||
- [3.5\* 自动命令与事件 ](./z/20170818_5.md) | ||
- [3.6\* 调试命令 ](./z/20170818_6.md) | ||
|
||
+ 第四章 VimL 数据结构进阶 | ||
- [4.1 再谈列表与字符串 ](./z/20170819_1.md) | ||
- [4.2 通用的字典结构 ](./z/20170819_2.md) | ||
- [4.3 嵌套组合与扩展 ](./z/20170819_3.md) | ||
- [4.4\* 正则表达式 ](./z/20170922_1.md) | ||
|
||
+ 第五章 VimL 函数进阶 | ||
- [5.1 可变参数 ](./z/20170819_4.md) | ||
- [5.2 函数引用 ](./z/20170819_5.md) | ||
- [5.3 字典函数 ](./z/20170819_6.md) | ||
- [5.4\* 闭包函数 ](./z/20171023_1.md) | ||
- [5.5 自动函数 ](./z/20171028_1.md) | ||
|
||
+ 第六章 VimL 内建函数使用 | ||
- [6.1 操作数据类型 ](./z/20170821_1.md) | ||
- [6.2 操作编辑对象 ](./z/20170821_2.md) | ||
- [6.3 操作系统文件 ](./z/20170821_3.md) | ||
- [6.4 其他实用函数 ](./z/20170821_4.md) | ||
|
||
+ 第七章 VimL 面向对象编程 | ||
- [7.1 面向对象的简介 ](./z/20170821_5.md) | ||
- [7.2 字典即对象 ](./z/20170821_6.md) | ||
- [7.3 自定义类的组织管理 ](./z/20170821_7.md) | ||
<!-- - 7.4\* 面向对象实现示例 20170821_8.md --> | ||
|
||
+ 第八章 VimL 异步编程特性 | ||
- 8.1 异步工作简介 | ||
- 8.2 使用异步任务 | ||
- 8.3 使用通道控制任务 | ||
|
||
+ 第九章 Vim 插件管理与开发 | ||
- 9.1 典型插件的目录规范 | ||
- 9.2 插件管理器插件介绍 | ||
- 9.3 内置的 pack 机制 | ||
- 9.4\* 自定义开发插件基础 | ||
|
||
+ 第十章 VimL 混合编程 | ||
- 10.1 内嵌其他脚本语言 | ||
- 10.2 调用其他语言脚本 | ||
- 其他待定 | ||
|
||
+ 结语 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# VimL 语言编程指北路 | ||
|
||
本教程只完成了三分之二,有关 VimL (vim script) 编程的基础知识与中级用法算是完 | ||
稿了,但高级应用尚未完成。 | ||
|
||
[进入目录](./content.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
# 《VimL 语言编程指北路》前言 | ||
`+` `book/vimllearn` | ||
|
||
这是一篇有关 Vim 脚本语言的入门与进阶教程。是“指北”,不是“指南”,所以如果不慎 | ||
指错了路,切勿见怪。不过要相信地球是圆的,绕了一圈之后,希望还是能找对目标的。 | ||
|
||
初学者如果第一章看不懂,建议直接看第二章;如果第二章看不懂,建议直接看第三章; | ||
如果第三章也看不懂,建议直接放弃治疗,汝须先培养对 vim 的信仰习惯。 | ||
|
||
以下……开始严肃话题。 | ||
|
||
## 正名约定 | ||
|
||
Vim 是上古神器之一,且能历久弥新,与时俱进。随着 Vim 的发展,Vim 的脚本也逐渐 | ||
发展壮大,支持的功能与特性越来越丰富,俨然成为一种新的或老的实用脚本语言。然而 | ||
这语言的名字,网上的称谓似乎还有点五花八门。 | ||
|
||
为了行文统一与方便,在这里我采用“VimL”(Vim Language 缩写)来表示该脚本语言,用“ | ||
Vim” 表示编辑器;而小写的 “vim” 则是指系统中可执行的编辑器程序,若从“VimL”角度 | ||
看,也算是它的解释器程序;然后“vim script”就是存放“VimL”代码且可用“vim”解释运 | ||
行它的文本文件。 | ||
|
||
## 目标假设 | ||
|
||
本教程针对的目标群体,假定是有使用 Vim 的基础及一定的编程基础。尽管我尽量从基 | ||
本概念讲起,但一些最基础的东西怕无从再细致了。然后最重要的是要热爱 Vim ,并且 | ||
有折腾的精神来打造或调教自己的 Vim。 | ||
|
||
其实,不管是使用 Vim 还是 VimL,最好的资源都是 Vim 的内置帮助文档(`:help`)。 | ||
外部教程都不免有所侧重,较适于学习阶段的引领者。 | ||
|
||
本教程依据的 Vim 版本是 `8.0`,系统环境 Linux。但除了一些新特性,应该也适用 | ||
Vim7 以下版本。同时由于 Vim 本身是跨平台的,VimL 自然也与操作系统无关。虽然无 | ||
法一一验证,但在一些重要的差异处,尽量在文中指出。 | ||
|
||
## VimL 的优缺点 | ||
|
||
作为一种语言,首先指出 VimL 的缺点一是只能在 Vim 环境下运行,二是运行速度有点 | ||
慢。但是,对于热衷 Vim 的程序猿,每天的编码工作都在 Vim 环境下,VimL 的编程方 | ||
式与 Vim 的操作方式无间密合,应该算是个优势。 | ||
|
||
另外,程序的运行速度都是相对的。所有的动态脚本语言,相对静态的编译语言,都很慢 | ||
。但这不要紧,只要完成大部分工作能足够快,脚本的简单便捷性就能体现出来了。VimL | ||
同样具有脚本语言这个共性。 | ||
|
||
用 Vim 编写 VimL 代码,另有个天然的优势,就是编辑器,解释器,与文档手册一体化 | ||
,同时仍然保持了 Vim 的小巧,不像静态语言的IDE那么笨重。 | ||
|
||
编程思想基本是独立于语言的,大多数语言都是相通的。现代的高级脚本语言更是几乎都 | ||
能提供差不多的功能。(而且,据说只要是“图灵完备”的语言,理论上都能做任何事)。 | ||
所以,经常使用 Vim 的程序猿,如果想多学一门脚本语言,那 VimL 是个不坏的选择。 | ||
|
||
## 文本约定 | ||
|
||
本教程拟用 `.md` 文件书写,章用一级标题,节用二级标题,每节至少一个文件。初稿 | ||
不一定严格按目录大纲的顺序书写,并且在此过程中或有增删调整。 | ||
|
||
带星号 `*` 的章节,表示略有艰深晦涩的内容,可以选择性略过。 | ||
|
||
关于示例代码块,`:` 开始的行表示 Vim 的命令行(也叫 ex 命令),`$` 开始的行表 | ||
示从 shell 运行的命令行。较短的示例代码,可以直接输入或粘贴入 vim 的命令行,较 | ||
长的示例代码,建议保存 `.vim` 文件,然后 `:source`。 | ||
|
||
希望能有节奏地写完全部教程,然人艰不拆,不期何时完稿。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,198 @@ | ||
# 《VimL 语言编程指北路》第一章 VimL 语言主要特点 | ||
`+` `book/vimllearn` | ||
|
||
## 1.1 Hello World 的四种写法 | ||
|
||
按惯例,我们讨论一门语言,首先看下如何写最简单的 “Hello World” (程序)。 | ||
由于 Vim 是高度自由的,VimL 也有多种不同的方式玩转 “Hello World”。 | ||
|
||
### 速观派:直接操起命令行 | ||
|
||
最快速的办法是在 Vim 命令行下用 `:echo` 命令输出 “Hello World”: | ||
```vim | ||
: echo 'Hello World!' | ||
``` | ||
唯一需要注意的是,得把 “Hello World” 用引号括起来,单引号或双引号都可以。 | ||
这样再按下回车就能在 Vim 的消息区显示出 “Hello World” 这行字符串了。 | ||
|
||
由于这条消息字符串很简短,一行就能显示完整,Vim 将其直接显示在命令行的位置,并 | ||
且运行完直接返回 Vim 普通模式。如果字符串很长或多行字符串,则消息区将向上滚动 | ||
,以显示完整的消息,用户需要额外按个回车才回普通模式。 | ||
|
||
试试在命令行输入这条命令,看看有啥不同反应: | ||
```vim | ||
: echo "Hello World! \n Hello World! \n Hello World!" | ||
``` | ||
|
||
好了,你已经学会了如何用 VimL 输出 “Hello World” 了。这也算编程吗?别逗了!其 | ||
实,别把编程想得那么严肃,那这就算编程! | ||
|
||
### 正规派:建立脚本文件 | ||
|
||
把刚才在命令行输入的那条命令保存在一个 `.vim` 后缀的文本文件中,那就是一个 | ||
`vim script` 了,这是用 VimL 编程比较正常的用法。 | ||
|
||
为了方便,建议在本地建个目录,用于保存本教程的示例代码。比如: | ||
```bash | ||
$ cd ~/.vim | ||
$ mkdir vimllearn | ||
$ vim vimllearn/hello1.vim | ||
``` | ||
|
||
这将在 `~/.vim` 目录下新建一个 `vimllearn` 目录,并用 vim 开始编辑一个名为 | ||
`hello1.vim` 的文件。vim 会为该文件新建一个缓冲区 `buffer`,在该 `buffer` 中输 | ||
入以下文本,然后输入命令 `:w` 保存: | ||
```vim | ||
" 文件: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` 命令加载运行了: | ||
```vim | ||
: source ~/.vim/vimllearn/hello1.vim | ||
``` | ||
需要将脚本文件的路径写在 `source` 命令之后作为参数。如果当前 vim 正常编辑 | ||
`hello1.vim` 这个文件,则可用 `%` 表示当前文件的路径: | ||
```vim | ||
: source % | ||
``` | ||
|
||
折腾并解释了这许久,终于可以通过 `source` 一个 vim 脚本打印输出 “Hello World” | ||
了,与此前的效果是一样一样的。当然了,用 VimL 写脚本肯定不能只满足于写 “Hello | ||
World” 吧,所以这才是标准用法。 | ||
|
||
此外 Vim 的命令是可以简写的,`source` 可简写为 `so`。当你在写一个 vim 脚本时想 | ||
快速验证执行该脚本时,可以只输入: | ||
```vim | ||
: so % | ||
``` | ||
|
||
如果还想更省键,就定义一个快捷键映射吧,比如: | ||
```vim | ||
: nnoremap <F5> :update<CR>:source %<CR> | ||
``` | ||
可以将这行定义加入你的 `vimrc` 中,不过最好是放在 `~/.vim/ftplugin/vim.vim` 中 | ||
,并加上局部参数,让它只影响 `*.vim` 文件: | ||
```vim | ||
: nnoremap <buffer> <F5> :update<CR>:source %<CR> | ||
``` | ||
|
||
### 测试派:进入 Ex 模式 | ||
|
||
直接在命令行用 `:echo` 查看一些东西其实很有用的,可以快速验证一些记不清楚的细 | ||
节。比如你想确认下在 VimL 中字符 `'0'` 是不是与数字 `0` 相等,可以这样: | ||
```vim | ||
: echo '0' == 0 | ||
``` | ||
|
||
但如果要连续输入多条命令并查看结果,每次都要(从普通模式)先输入个冒号,不免有 | ||
些麻烦。这时,`Ex` 模式就有用了。默认情况下(若未在 vimrc 被改键映射),在普通 | ||
模式下用 `Q` 键进入 `Ex` 模式。例如,在 `Ex` 模式下尝试各种输出 “Hell World” | ||
的写法,看看不同引号对结果的影响: | ||
```vim | ||
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”: | ||
```vim | ||
$ cd ~/.vim/vimllearn | ||
$ vim -eS hello1.vim | ||
``` | ||
|
||
这就相当于使用 `vim` 解释器来运行 `hello`.vim` 这个脚本,并且停留在交互式界面 | ||
上。此时可以用 `:q` 命令退出,或 `:vi` 以正常方式继续使用 Vim。 | ||
|
||
vim 本身的命令行启动参数其实还支持很多功能,请查阅 `:help starting`。其中还有 | ||
个特殊的参数是 `-s`,如果与 `-e` 联用,就启动静默的批处理模式,试试这个: | ||
```vim | ||
$ 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 的可视 | ||
化与自动化之间找到适合自己的不同的平衡点。 | ||
|
||
—— 楼上的天花乱坠地在说些什么呀 | ||
|
||
—— 不知道耶,再看看吧 |
Oops, something went wrong.