又又又又开始学 Vim 了😪

为了能像 Gilles Castel 那样记笔记(用 Vim + snippets 居然可以在课堂上同步记数学笔记😱),我又又又又一次捡起了 Vim 。感觉 Vim 之所以这么难学,是因为没一篇教程写对路了的😒。

我的最初想法是重现一个新手可能会遇到的问题,寻找原生的解决方案 & 更优雅的方案。不过回头看,更加深切地感受到,这么多年过去,Vim & Emacs 的对手(各种 IDE )换了一波又一波,它俩却还屹立在那,不得不说其设计中有很多先进那个时代、即使在今天仍不过时的思想(当然,也必然存在很多缺陷。当我们认识了这些缺陷,并知道原生如何解决、以及如何更好地解决,使用插件🧩就更加得当)。就算从程序设计的角度,Vim 仍然值得深入学习。

Unix 上最早的文本编辑器是 ed ,而后经过几代的改进,包括 em (editor for mortals) ,en ,最终到 ex 。再之后才是 vi ,Vim (vi improved) 。这段有趣而没用的历史,我一定要告诉你。

1. 打开 & 退出

  • 用 Vim 打开某份文件:vim a.txt
  • MD,怎么卡死了!<ctrl-w> 也退不出去🤯!
  • 哦,要按 i (insert) 进入「编辑模式🖋[1]」才可以写字😒;
  • MD,ctrl-s 怎么保存不了🤯!
  • 哦,要按 <esc> 退出「编辑模式🖋」,进入到「思考模式🤔[2]」才能执行命令;
  • 保存 & 退出::wq (其实是进入了「命令行模式」);

这么会有这么反人性的设计😒。改下配置 vim ~/.vimrc (即,告诉 Vim 你的使用习惯)。当然,你可以改成熟知的 ctrl + s( Vim 习惯写成 c-s ),但为了符合 Vim 的用键传统,还是用单字母吧:

" Save & quit
map Q :q<CR>
map S :w<CR>

现在你可以用 S 保存,按 Q 退出了。

但是,要是在新文件里写了点什么,怎么保存呢?:w <new_filename>

map S :write %<CR>  " % :活动缓冲区的完整文件路径。

其实,这样写也不准确。改变原生键位最好准确指定起效的模式,要是能给出原生键位的替代方案就更好了。比如,幸运的是,不会和 surround.vim 的 S 命令冲突。

" Save & quit
nnoremap S :w %<CR>     " ⚠️ 幸运的是,不会和 surround.vim 的 S 命令(只在 visual mode 下起效)冲突。
nnoremap Q :q<CR>

听人说,Vim 的强大来自「多模式」?呵呵,你也可以将「多模式」理解为「反人性」(例如:同一键位在不同的模式下作用可能天差地别。详见下表)。∴别再说什么「「多模式」是 Vim 之髓」了😓。我认为,Vim 的强大源于它既提供了粗粒度的操作,又提供了细粒度的操作。强大的工具其实莫不如是,比如 PS 。后面再详细解释。

no. 操作 思考模式🤔 可视模式🌈 编辑模式🖋
::no.:: i & a 进入「编辑模式🖋」插入 (insert / append) (或「思考模式🤔」下 <operator> 后)i<text-object>(inner / inside) & a<text-object>(arround / all)
::no.:: o 进入「编辑模式🖋」并插入新行 在高亮选区两端来回切换
::no.:: c-r 重做 (redo) <c-r><register> 意为插入寄存器 register 的内容

2. 怎么对调 caps lockesc

你听到的第一个建议,大概率是改键:将 <caps lock> 改为 <esc> 。这件事在 MacOS 上原生自带:

caps2esc

Windows 上也不难,下一个 PowerToys ,用里面的 Keyboard Manager 就搞定。

最麻烦的是 Linux ,折腾了很久都没有成功😓。

3.界面太丑怎么办🥴🤢🤮?

Vim 最为人诟病的就是「记忆负担太重」。比如:在不同的模式之间切换,完全凭脑力。再比如什么 marks 啦、buffers 啦、tabs 啦……原厂的统统不显示。

最简单的改造方式是高亮显示当前行 / 列:

set cursorline
set cursorcolumn

可以装个叫 vim-airline 的美化插件😍,至少不同模式的颜色不同。但你得先装个管理插件的插件 vim-plug

装好以后在 ~/.vimrc 里写:

call plug#begin()
" ...
call plug#end()

现在你终于可以装 vim-airline 了:

call plug#begin()

Plug 'vim-airline/vim-airline'
Plug 'vim-airline/vim-airline-themes'

call plug#end()

let g:airline_theme = 'simple'

airline 除了好看,一定要把 Smarter tab line 打开:

let g:airline#extensions#tabline#enabled = 1
Smarter tab line

现在,当你打开多个文件 vim *.md ,就可以用 :bprevious & :bnext 来回切换缓冲区 (buffers) 了。太蠢了是不🤢🤮?还是改个快捷键吧。这是从 Tim Pope 的 unimpaired.vim 那抄来的:

" 快速遍历 Vim 列表
" ⚠️ 加 ! 后可以强制切换缓冲区。
nnoremap <silent> [b :bprevious!<CR>
nnoremap <silent> ]b :bnext!<CR>
nnoremap <silent> [B :bfirst!<CR>
nnoremap <silent> ]B :blast!<CR>

你最好再装个 Powerline

但还是没有解决 marks、buffers、tabs 的提示问题啊?那还得靠插件:

文件导航插件🧭:NERDTree
masks 提示插件:vim-signature
registers 提示插件:vim-peekaboo

4. 怎么在窗口间切换啊?

当你装插件上瘾以后,比如 NERDTreeUndo Tree,会遇到一个问题,怎么切换到新开的窗口上呢?

原生命令是:

命令 效果
<C-w>w 在窗口间循环切换 🔁
<C-w>h 切换到左边的窗口 ⬅️
<C-w>j 切换到下边的窗口 ⬇️
<C-w>k 切换到上边的窗口 ⬆️
<C-w>l 切换到下边的窗口 ⬇️
<C-w>c 关闭活动窗口 ❌

但还是喜欢 @TheCW 的改法:

" ===
" === Window management
" ===
" Set <LEADER> as <SPACE>
let mapleader="\<space>"
" Use <space> + new arrow keys for moving the cursor around windows
map <LEADER>w <C-w>w
map <LEADER>k <C-w>k
map <LEADER>j <C-w>j
map <LEADER>h <C-w>h
map <LEADER>l <C-w>l

5. 最纠结的改键😵

排名 原生键位 想改成 改键原因 得失
::no.:: : ; 需要频繁进入 Ex mode 。 ; & , 是一对操作。
::no.:: <Leader>[3] 用哪个?缺省是 \

6. 常用连招

从按键效率来说,当然是「单键」>「双击单键」>「易记的键组合」>……:

no. 快捷键 效果 初始模式 切入模式
::no.:: A (等效于 $a)在行尾添加文本。 normal mode🤔 insert mode🖋
::no.:: I (等效于 ^i)在行首添加文本。 normal mode🤔 insert mode🖋
::no.:: o (等效于 A<CR>)在当前行下方新起一行。 normal mode🤔 insert mode🖋
::no.:: O (等效于 ko)在当前行上方插入一行。 normal mode🤔 insert mode🖋
::no.:: C (等效于 c$ normal mode🤔 insert mode🖋
::no.:: s (等效于 cl)删掉光标下的字符,然后进入插入模式。即,替换光标下的字符。 normal mode🤔 insert mode🖋
::no.:: S (等效于 ^c normal mode🤔 insert mode🖋
::no.:: dd 删除当前行。 normal mode🤔 normal mode🤔
::no.:: >> 增加当前行缩进。 normal mode🤔 normal mode🤔
::no.:: << 减少当前行缩进。 normal mode🤔 normal mode🤔
::no.:: ea 在单词结尾 (end) 添加文本。 normal mode🤔 insert mode🖋
::no.:: gf go to file. normal mode🤔 normal mode🤔
::no.:: xp 调换光标之后的两个字符。 normal mode🤔 normal mode🤔
::no.:: gUU 将当前行整行转换为大写。 normal mode🤔 normal mode🤔
::no.:: yyp 复制当前行,并粘贴在下方。 normal mode🤔 normal mode🤔
::no.:: daw delete a word. normal mode🤔 normal mode🤔
::no.:: vit visully select inside the tag.
::no.:: gv 重选上次的高亮选区。
::no.:: f,dt. 删除句子的后半段。 normal mode🤔 normal mode🤔
::no.:: qaq 清空寄存器 a
::no.:: gUaw 将当前单词转换为大写。 normal mode🤔 normal mode🤔

7. 成对操作🎎

我觉得,学 Vim 完全可以比照学二外的方式——比较 & 联系。

no. 快捷键 效果 初始模式 切入模式
::no.:: a v.s. A 从后方 (append) 插入。 normal mode🤔 insert mode🖋
::no.:: i v.s. I 从前方插入 (insert) 。 normal mode🤔 insert mode🖋
::no.:: n v.s. N 下一处 (next) 。
::no.:: o v.s. O 插入新行。 normal mode🤔 insert mode🖋
::no.:: v v.s. V 进入 Visual mode 。
::no.:: f<char> / F<char> v.s. t<char> / T<char> 正向 / 反向行内查找 <char> ,区别在于包不包括 chartill 不包括)。 normal mode🤔 normal mode🤔
::no.:: ; v.s. , 继续寻找与调转方向搜寻前次搜寻的位置。 normal mode🤔 normal mode🤔
::no.:: /<pattern><CR> v.s. ?<pattern><CR> 文内查找。 normal mode🤔 comand mode🎛
::no.:: <C-a> v.s. <C-x> 对当前行其后最近的数字执行加 / 减操作。 normal mode🤔 normal mode🤔
::no.:: . v.s. u 重复与撤回。 normal mode🤔 normal mode🤔
::no.:: normal mode🤔下的命令 v.s. Ex 命令 ⚠️:normal mode🤔下的命令适合在本地操作,而 Ex 命令则可远距离操作。比如: p v.s. :t (copy To) 。
::no.:: <c-]> v.s. :tag <keyword> 跳转到 tag 到定义处。
::no.:: mm v.s. ``m` 标记位置📌 m / 跳转到标记📌 m
::no.:: (in visual mode)o v.s. (in normal mode)% 在高亮选区两端来回切换 v.s. 在括号(([{ v.s. }]))间跳转 。
::no.:: <c-o> v.s. <c-i> 在跳转列表 (:jumps) 中后退 / 前进(📢注意:低头看一下,在 qwerty 键盘⌨️中,i o 是紧挨在一起的)。
::no.:: g, v.s. g;
::no.:: /someWord v.s. ?someWord
重复类型 重复操作符 回退操作符
文本编辑重复 . u
行内查找重复 ; ,
全文查找重复 n N
文本替换重复 & u
宏重复 @<register> u

8. 插件🧩

no. 插件名 用途 原生解决方案
::no.:: NERDTree 文件管理 netrw,标配插件,across NETwork Read and Write files 的意思。
::no.:: coc-yank 可视复制
::no.:: vim-peekaboo 寄存器增强。(Peekaboo extends " and @ in normal mode and <CTRL-R> in insert mode so you can see the contents of the registers.)
::no.:: Undo Tree
::no.:: vim-devicons 美化插件:添加图标
::no.:: vim-table-mode 美化插件:增强表格
::no.:: vim-signature 增强书签📌 marks
::no.:: vim-gitgutter 在行号栏显示修改状态(必须置于 Git 看管之下)。 (changs list):changes & g;, g,
::no.:: vim-surround 增强 text object ,实现快速环绕编辑。请和 wildfire.vim 配合食用。
::no.:: wildfire.vim 按下 <enter> 就能智能选中最近的文本块。请和 vim-surround 配合食用。
::no.:: vim-expand-region 快速扩大 / 缩小选中区域
::no.:: vim-commentary 注释
::no.:: NERD Commenter 注释
::no.:: coc.nvim 补全🤖️
::no.:: ctrlp.vim
::no.:: Tagbar tag 导航
::no.:: vim-markdown MarkDown 增强
::no.:: markdown-preview.nvim MarkDown 预览

从 @theCW 那抄来的超有用的 MarkDown 速记技巧

动作 用途
,b 加粗
,d code
,c 代码块
,p 图片🎨
,a 链接🔗
,f 跳转到下一定位点 <++>
autocmd Filetype markdown inoremap ,f <Esc>/<++><CR>:nohlsearch<CR>c4l
autocmd Filetype markdown inoremap ,n ---<Enter><Enter>
autocmd Filetype markdown inoremap ,b **** <++><Esc>F*hi
autocmd Filetype markdown inoremap ,s ~~~~ <++><Esc>F~hi
autocmd Filetype markdown inoremap ,i ** <++><Esc>F*I
autocmd Filetype markdown inoremap ,d `` <++><Esc>F`i
autocmd Filetype markdown inoremap ,c ~~~<Enter><++><Enter>~~~<Enter><Enter><++><Esc>4kA
autocmd Filetype markdown inoremap ,h ====<Space><++><Esc>F=hi
autocmd Filetype markdown inoremap ,p [图片上传失败...(image-302a4-1669910210820)] <++><Esc>F[a
autocmd Filetype markdown inoremap ,a [](<++>) <++><Esc>F[a
autocmd Filetype markdown inoremap ,1 #<Space><Enter><++><Esc>kA
autocmd Filetype markdown inoremap ,2 ##<Space><Enter><++><Esc>kA
autocmd Filetype markdown inoremap ,3 ###<Space><Enter><++><Esc>kA
autocmd Filetype markdown inoremap ,4 ####<Space><Enter><++><Esc>kA
autocmd Filetype markdown inoremap ,l --------<Enter>

Ref📚


  1. 本应译为「插入模式🖋」,但我不喜欢这个翻译。

  2. 借用 @Drew Neil 在《Practical Vim》里的话就是:画家在休息时不会把画笔放在画布上。对 Vim 而言也是这样,normal 模式就是 Vim 的自然放松状态。所以我更喜欢把 normal mode 称之为「思考模式🤔」。

  3. 用来自定义用户自己的名字空间。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342

推荐阅读更多精彩内容