Skip to content

Vim: The Art of Zen Coding

Published: at 02:00 PM

A primate-like creatures that happen to know how to press a keyboard.

Today

I Want to Tell You

Vim 是从 vi 发展出来的一个文本编辑器。其代码补完、编译及错误跳转等方便编程的功能特别丰富,在程序员中被广泛使用。和Emacs并列成为类 Unix 系统用户最喜欢的编辑器。

以下介绍的 vim,可和 neovim 等同。

Vim 区别于其他编辑器最显著的特点:

  1. 导航
  2. 模式
  3. 命令

下面让我们来基本的介绍 (无特殊说明都在_Normal_模式):

Just live

最为基本的映射:

hjkl → 对应方向键 → 左下上右

基本的模式切换:

`i`, `a` → _Insert_ 模式,在光标前后插入,用于编辑文本.
`v` or `V` → _Visual_ 模式,用于选取文本。
`ESC` → 回到 _Normal_ 模式
`:` → 输入命令

Vim 中常用模式有_Normal_ 模式,_Insert_模式,_Visual_模式和命令模式。

当然,你需要先知道如何退出 vim :-)

`:wq` → 存盘 + 退出 (`:w` 保存, `:q` 退出)
`:q!` → 强制退出

Feel good

你可以重新进入 vim,同时你现在处于 _Normal_ 模式

在 vim,hjkl 还不够,更快的移动:

`w` → 以一个单词为单位,向后移动到单词头
`b` → 以一个单词为单位,向前移动到单词头
`0` → 数字零,到行头
`^` → 到本行第一个不是 blank 字符的位置(所谓 blank 字符就是空格,tab,换行,回车等)
`$` → 到本行行尾

更多的插入方式:

`cw` → change word, 删除光标处的单词,并进入插入模式
`s` → 删除光标处的字母,并进入插入模式,如同 `cl`
`o` → 在当前光标换行插入一行

更重要的,要知道如何查看 help:

`:h <++>` → 查看 <++> 的帮助文档

Want more?

为了基本的文本编辑,我们还需要知道更多操作,如下

复制,打印和删除 (vim 剪贴板默认使用的寄存器不是系统寄存器,详见下文):

`y` → yank,复制,可结合 _Visual_ 模式使用
`p` → paste, 打印
`d` → delete, 删除,可结合 _Visual_ 模式使用,删除的文本也会录入剪贴板

搜索:

`f` → find, 行内向后搜索,光标到达目标处
`t` → til, 行内向后搜索,光标到达目标前一位

全局搜索:

`/` → 全局搜索,并使用 `n`, `N` 导航搜索结果

替换 (命令行模式):

`:[range]s/{pattern}/{string}/[flags] [count]`

比如:`:s/foo/bar/` → 在当前行中搜索字符串 foo 的第一个匹配项,并将其替换为 bar

该命令在[range]中的每一行中搜索{pattern},并将其替换为{string}。是与命令[count]相乘的正整数。

如果未给出[range]和[count],则仅替换当前行中找到的 pattern。当前行是光标所在的行。

如果你知道更多,请使用 help

匹配移动:

`%` → 匹配括号移动,包括 (, {,  [, 你需要把光标先移到括号上
`*``#` →  匹配光标当前所在的单词,移动光标到下一个(或上一个)匹配单词(* 是下一个,# 是上一个)

撤销和重做:

`u` → undo, 撤销
`<Ctrl-r>` → redo, 重做

光标历史位置导航:

`Ctrl-o` → 向后移动到较旧的跳转位置。例如,如果你从行 1 跳转到行 50,然后按 `Ctrl-o`,你的光标将回到行 1。
`Ctrl-i` → 向前移动到较新的跳转位置。在上面的例子中,如果你在行 1 按 `Ctrl-o` 回到行 1,然后按 `Ctrl-i`,你的光标将回到行 50。

以上是笔者日常中常用的命令,当然,vim 远远不止如此,你还可以其他关键字浏览的更快,建议使用 vimtutor 跟着敲一遍。

接下来,笔者将介绍 vim 的相关基础,同时告诉你使用语义化的 vim (略过上面👆的指令也能知晓一二)

Fixing a Hole

Operation & Motion

Motion 是指在文本中移动光标的位置。常见的 motion 命令包括:

Operation 是指对文本执行的操作, 如 v(visual), c(change), y(yank), d(delete) 都是一种 operation,一种操作。

operation 通常与 motion 组合使用,以对特定范围的文本执行操作。例如:

通过组合 motion 和 operation,可以高效地编辑文本。

Text Object

Text Object 是 vim 中一个非常重要的概念,基于此能够更加高效的编辑 vim 中的内容。

最为基本的文本对象即:

同时我们也能用以下符号选定文本范围

同时为了去选中他们,你可以使用 a -all (all是笔者的粗浅理解,包括空格和符号),i -inner (不包括空格和符号)

例如:

Hello, world    ?

当你的光标的在 w 上,你使用 viw,你会得到 world,同时,你使用 vaw, 会得到 world

Hello, "world"    ?

当你的光标在 w 上,你使用 vi",你会得到 world,同时,你使用 vaw, 会得到 "world"

你可以尝试一下。同时,我也介绍另一种范围选定,使用 f (find) 和 t (til)

同样的荔枝:

Hello, "world"    ?

当你的光标在 w 上,你使用 vi",你会得到 world,同时,你使用 vaw, 会得到 "world"

差点忘了,你还可以在 ia 前添加数字,表示第几层,不过这个应该只对匹配较强的符号有效 ((), []…)。比如:

(map (+) ("foo"))

当你的光标在 o 上,你使用 v2i), 你会得到 map (+) ("foo"), 同时,你使用 v2a), 会得到 (map (+) ("foo"))

看到这里,你是否会觉得 vim 的操作很语义化,非常符合直觉的一种逻辑🤥

寄存器

在这里我想讨论一下 vim 的寄存器,如果你兴趣,请使用 :h registers, 然后你会看到

There are ten types of registers:		*registers* *{register}* *E354*
1. The unnamed register ""
2. 10 numbered registers "0 to "9
3. The small delete register "-
4. 26 named registers "a to "z or "A to "Z
5. Three read-only registers ":, "., "%
6. Alternate buffer register "#
7. The expression register "=
8. The selection registers "* and "+
9. The black hole register "_
10. Last search pattern register "/

默认情况下,vim 在编辑器内使用第一个寄存器,而系统寄存器为第八个,因此

- 复制到系统剪贴板:
    "+y
这个命令会复制当前行到系统剪贴板。

- 从系统剪贴板粘贴:
    "+p
这个命令会从系统剪贴板粘贴内容。

你可以使用类似指令操作其他寄存器。🤥

块操作

块操作,典型的操作: 0 <C-v> <C-d> I-- [ESC]

  • ^ → 到行头
  • <C-v> → 开始块操作
  • j → 向下移动 (你也可以使用其他方式来移动光标)
  • I-- [ESC] → I 是插入,插入 “--”,按 ESC 键来为每一行生效。

宏录制和执行

在 Vim 中,你可以使用宏来录制和重播一系列的命令。以下是如何录制和使用宏的步骤:

  1. 在普通模式下,按 q 键开始录制宏。然后按一个字母键(例如 a)来选择一个寄存器来存储宏。在这个例子中,我们将使用 a 寄存器,所以你应该按 qa
  2. 现在你正在录制宏。你可以进行任何你想要重播的操作,例如移动光标、编辑文本等。
  3. 当你完成了所有的操作,再次按 q 键来停止录制。
  4. 现在你的宏已经录制完成,存储在 a 寄存器中。你可以通过在普通模式下按 @a 来重播这个宏。如果你想要重播这个宏多次,你可以先输入一个数字,然后按 @a。例如,10@a 将重播宏 10 次。
  5. @@ 是一个快捷键用来 replay 最新录制的宏。

示例

在一个只有一行且这一行只有 “1” 的文本中,键入如下命令:

  • qaYp<C-a>q
    • qa 开始录制
    • Yp 复制行.
    • <C-a> 增加 1.
    • q 停止录制.
  • @a → 在 1 下面写下 2
  • @@ → 在 2 正面写下 3
  • 现在做 100@@ 会创建新的 100 行,并把数据增加到 103.

书签

在 Vim 中,你可以使用书签(bookmark)功能来快速跳转到文件中的特定位置。以下是如何设置和使用书签的步骤:

  1. 在普通模式下,将光标移动到你想要标记的行。
  2. 按 m 键,然后按一个字母键(例如 a)来设置一个书签。在这个例子中,我们将使用 a 作为书签,所以你应该按 ma
  3. 现在你的书签已经设置好了。你可以通过在普通模式下按 'a(注意是单引号)来跳转到这个书签。如果你在其他文件中,你可以按 `a(注意是反引号)来跳转到这个书签。
  4. 如果你想要删除这个书签,你可以在普通模式下按 :delmarks a

Getting Better

有用的小技巧

在这里介绍一下常用的小技巧:

  1. 数字的增减
`<c-a>`     " 增加光标处数值
`<c-x>`     " 减小光标处数值
  1. 缩进
`J`           " 取消选中行的换行符

" 插入模式
`<c-t>`       " 缩进
`<c-d>`       " 去缩进

" 普通模式
`>>`          " 缩进
`<<`          " 去缩进

" 可视模式
`>`           " 缩进
`<`           " 去缩进
`=`           " 自动缩进
  1. 排序
1. 可视模式下,选中一片区域
2. 按下 `:` 进入命令模式,输入 `sort` 对选中文本排序
  1. 更多的等你发现…

自定义配置

ok,到这里,更加宽阔的 vim world !!!🤫, 那个折腾👻不想动手配置一番出自己的 vim?

(折腾半生,归来仍是默认🤣)

怎么样定制自己的 vim:

但是现在 vim 开放了 lua api,所以我们终于有一个正常的语言来写我们的配置了吗🤨?

(同时,你可以使用 AI 将 vimscript 翻译为 lua,还挺准的)

这里我会使用 lua 来展示一些配置

Go on …

基本配置

一些最基本的预设 (当然远不如此):

-- 设置行号
vim.o.number = true
-- 设置相对行号
vim.o.relativenumber = true
-- tab 宽度为 2
vim.o.tabstop = 2
vim.o.smarttab = true
...

自定义事件

在 Vim 中,你可以使用 autocmd 命令来定义自定义事件。这个命令允许你指定一个或多个事件,以及当这些事件发生时要执行的命令。

举个栗子:

这段配置的作用是:每次保存文件时,自动删除行尾的空格。

vim.cmd([[autocmd BufWritePre * :%s/\s\+$//e]])

同时,你也可以使用 :h events 查看 vim 中有哪些事件。

Plugins

关于插件我不想说太多,毕竟插件迭代速度也不慢,现在推荐的插件说不定几个月后便过时了。

总的来说,插件大多有这几个方向:

Run for Your Life

Vim 哲学

核心操作:<number><command><scope>

Do one thing and do it well. 我认为 vim 作为一款文本编辑器做到了这点, 同时他确实做到了让你的指尖在键盘飞舞(花里胡哨的, 笔者帮你吐槽了😚).

笔者自了解 vim 也有几年,对 vim 的了解仍浮于表面,vim 依托于终端的工作环境对于笔者来说,使用并不频繁,对于开发而言,市面也有更加成熟的 IDE 或编辑器,像是 vscode, jetbrains 的 IDE, 纯终端的工作流笔者暂时没有太多接触,maybe 我想要一台没有桌面系统的 linux,但是别做梦了,日常使用还得花里胡哨😋

但是实际上,对于笔者来说,不太可能放弃 vim,maybe 我不想敲键盘了。有些时候,我认为这是一种对于操作逻辑的认可和依赖,我喜欢 vim 的哲学,对于我来说,vim 就像弹钢琴一样 (笑,夸张了)。不管怎么样,我现在仍会使用 vim。

但是,在不停地反复配置 vim,有时也使我感到厌烦,大部分时候我觉得这是个东拼西凑的玩具 (笔者配的烂),它仅用于简单的项目开发或文件浏览。不管怎么说,对于开发者,大部分时间都放在写代码上,业余时间可能会折腾下配置,谁不想开箱即用呢?

Here, There And Everywhere

在这里介绍一些和 vim 相关的工具

借鉴 vim 的工具,其中大部分工具都借鉴了 vim 的移动方式 (把双手放在键盘中间真的舒服很多🥰), 少部分会基于 vim 的操作逻辑做出一个开箱即用的 IDE 或编辑器

Tomorrow Never Knows

最后,还有什么好说的呢?笔者以上记录了使用 vim 的一些心得,就如同我所说的,这仅仅是 vim 这个编辑器的凤毛麟角,很多的细节我并没有深入。

对于使用者来说,这只是一个工具;不过稍微深入一点,这是一种逻辑或哲学,由 vim 开创的一个编辑和移动的逻辑。

日后,我可能不再使用 vim,但 vim 的逻辑,实实在在的影响了我。在一定程度上,让键盘操作区更加集中,双手的效率得以提高。

同时,不得不提的一点是,vim 的开发者 Bram Moolenaar 于 2023年8月3日去世了,Bram 的一生将大部分时间都奉献给了 Vim,致力于开源和慈善。

这篇文章完笔时,vim 9.x 已发行,vim 的未来会怎么样呢?笔者不得而知,未来如何无从知晓,至少 vim 是一部分…


Previous Post
2023 年终总结