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 区别于其他编辑器最显著的特点:
- 导航
- 模式
- 命令
下面让我们来基本的介绍 (无特殊说明都在_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 命令包括:
- h:向左移动一个字符
- j:向下移动一行
- k:向上移动一行
- l:向右移动一个字符
- w:移动到下一个单词的开头
- b:移动到前一个单词的开头
- 0:移动到行首
- $:移动到行尾
Operation 是指对文本执行的操作, 如 v
(visual), c
(change), y
(yank), d
(delete) 都是一种 operation,一种操作。
operation 通常与 motion 组合使用,以对特定范围的文本执行操作。例如:
- dw:删除从光标当前位置到下一个单词开头的文本
- y$:复制从光标当前位置到行尾的文本
- c0:更改从光标当前位置到行首的文本
通过组合 motion 和 operation,可以高效地编辑文本。
Text Object
Text Object 是 vim 中一个非常重要的概念,基于此能够更加高效的编辑 vim 中的内容。
最为基本的文本对象即:
W
-wordS
-sentenceP
-paragraph
同时我们也能用以下符号选定文本范围
)
,]
,}
,"
,'
等at
: 一对 xml 标签,it
: xml 标签内部
同时为了去选中他们,你可以使用 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"
差点忘了,你还可以在 i
或 a
前添加数字,表示第几层,不过这个应该只对匹配较强的符号有效 (()
, []
…)。比如:
(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 中,你可以使用宏来录制和重播一系列的命令。以下是如何录制和使用宏的步骤:
- 在普通模式下,按
q
键开始录制宏。然后按一个字母键(例如a
)来选择一个寄存器来存储宏。在这个例子中,我们将使用a
寄存器,所以你应该按qa
。 - 现在你正在录制宏。你可以进行任何你想要重播的操作,例如移动光标、编辑文本等。
- 当你完成了所有的操作,再次按
q
键来停止录制。 - 现在你的宏已经录制完成,存储在
a
寄存器中。你可以通过在普通模式下按@a
来重播这个宏。如果你想要重播这个宏多次,你可以先输入一个数字,然后按@a
。例如,10@a
将重播宏 10 次。 @@
是一个快捷键用来 replay 最新录制的宏。
示例
在一个只有一行且这一行只有 “1” 的文本中,键入如下命令:
qaYp<C-a>q
→
qa
开始录制Yp
复制行.<C-a>
增加 1.q
停止录制.@a
→ 在 1 下面写下 2@@
→ 在 2 正面写下 3- 现在做
100@@
会创建新的 100 行,并把数据增加到 103.
书签
在 Vim 中,你可以使用书签(bookmark)功能来快速跳转到文件中的特定位置。以下是如何设置和使用书签的步骤:
- 在普通模式下,将光标移动到你想要标记的行。
- 按
m
键,然后按一个字母键(例如a
)来设置一个书签。在这个例子中,我们将使用a
作为书签,所以你应该按ma
。 - 现在你的书签已经设置好了。你可以通过在普通模式下按
'a
(注意是单引号)来跳转到这个书签。如果你在其他文件中,你可以按`a
(注意是反引号)来跳转到这个书签。 - 如果你想要删除这个书签,你可以在普通模式下按
:delmarks a
。
Getting Better
有用的小技巧
在这里介绍一下常用的小技巧:
- 数字的增减
`<c-a>` " 增加光标处数值
`<c-x>` " 减小光标处数值
- 缩进
`J` " 取消选中行的换行符
" 插入模式
`<c-t>` " 缩进
`<c-d>` " 去缩进
" 普通模式
`>>` " 缩进
`<<` " 去缩进
" 可视模式
`>` " 缩进
`<` " 去缩进
`=` " 自动缩进
- 排序
1. 可视模式下,选中一片区域
2. 按下 `:` 进入命令模式,输入 `sort` 对选中文本排序
- 更多的等你发现…
自定义配置
ok,到这里,更加宽阔的 vim world !!!🤫, 那个折腾👻不想动手配置一番出自己的 vim?
(折腾半生,归来仍是默认🤣)
怎么样定制自己的 vim:
- 可配置性:Vim 允许用户通过 vimrc 文件进行高度的个性化配置,包括键绑定、颜色主题、插件等。
- 可扩展性:Vim 支持使用 Vimscript 编写插件,这使得用户可以根据自己的需要扩展 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
关于插件我不想说太多,毕竟插件迭代速度也不慢,现在推荐的插件说不定几个月后便过时了。
总的来说,插件大多有这几个方向:
- 插件管理器
- UI, UX
- 文件内编辑体验, 这个方向很广
- 文件管理
- Git 相关
- 模糊查找
- 自动补全
- Lsp (Language Server Protocol) 和 dap (Debug Adapter Protocol)
- 针对不同语言不同的开发插件
- …
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 或编辑器
- zsh,bash 的 vim 模式(你可能会想试试)
- man, Fzf(经典的命令行模糊查找器)
- lazygit(终端下的gui git, 笔者力荐😋)
- Ranger, joshuto, yazi, 三个都是终端下的文件管理器, 主推 yazi
- Svim (一款有意思的小工具, 有兴趣看看https://github.com/FelixKratz/SketchyVim)
- Chrome 插件 by vim
- VscodeVim, ideaVim
- Neovide, helix,更加现代化版本的 vim
- …
Tomorrow Never Knows
最后,还有什么好说的呢?笔者以上记录了使用 vim 的一些心得,就如同我所说的,这仅仅是 vim 这个编辑器的凤毛麟角,很多的细节我并没有深入。
对于使用者来说,这只是一个工具;不过稍微深入一点,这是一种逻辑或哲学,由 vim 开创的一个编辑和移动的逻辑。
日后,我可能不再使用 vim,但 vim 的逻辑,实实在在的影响了我。在一定程度上,让键盘操作区更加集中,双手的效率得以提高。
同时,不得不提的一点是,vim 的开发者 Bram Moolenaar 于 2023年8月3日去世了,Bram 的一生将大部分时间都奉献给了 Vim,致力于开源和慈善。
这篇文章完笔时,vim 9.x
已发行,vim 的未来会怎么样呢?笔者不得而知,未来如何无从知晓,至少 vim 是一部分…