Skip to content

Commit

Permalink
old article, new git resp
Browse files Browse the repository at this point in the history
  • Loading branch information
lymslive committed Mar 22, 2018
0 parents commit ee8e88e
Show file tree
Hide file tree
Showing 35 changed files with 8,591 additions and 0 deletions.
11 changes: 11 additions & 0 deletions .gitignore
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
70 changes: 70 additions & 0 deletions content.md
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 调用其他语言脚本
- 其他待定

+ 结语

6 changes: 6 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# VimL 语言编程指北路

本教程只完成了三分之二,有关 VimL (vim script) 编程的基础知识与中级用法算是完
稿了,但高级应用尚未完成。

[进入目录](./content.md)
64 changes: 64 additions & 0 deletions z/20170816_1.md
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`

希望能有节奏地写完全部教程,然人艰不拆,不期何时完稿。
198 changes: 198 additions & 0 deletions z/20170816_2.md
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 的可视
化与自动化之间找到适合自己的不同的平衡点。

—— 楼上的天花乱坠地在说些什么呀

—— 不知道耶,再看看吧
Loading

0 comments on commit ee8e88e

Please sign in to comment.