Vim使用指北

0x0.简介

这是一个几乎所有Linux发行版都会自带的,(比较)轻量级的,功能强大的恰到好处的文本编辑器。

因为其功能极度强大,所以人赐外号:“编辑器之神”。

不过,因为它的一切操作只依靠键盘,所以对于用习惯GUI的朋友们而言,不太友好。在谷歌上输入How to quit,联想结果的第一个就是How to quit vim(相对其他几个编辑器而言,它的学习曲线还是比较适中的。初学的时候记下几个快捷键,用熟了再继续慢慢学,不知不觉就能用得越来越爽了。

要想用好Vim,就离不开下面这几个关键点:

  • 快捷键(灵魂)
  • 配置文件(用得更爽)
  • 插件(?)
  • 帮助文档(!),输入:help即可查看

Vim的灵魂是按键操作,而不是花里胡哨的插件。想要用各种插件把Vim打造的媲美IDE的,不妨去试用各种集成Vim的IDE,而不是Vim——你只会浪费时间,很多时候还不会达到目的。

我各种IDE(jb全家桶/VSCode)+Vim插件用的都比较爽。虽然支持的不是很全面,不过只要支持各种语义操作、宏操作以及可视化之类的操作,其实就差不多了。目前体验最好的是VSCode+Vim插件,基本功能支持良好,VSCode Native Integration也做的有可取之处(很多VSCode的重要按键都能映射给VSCode)。Vim已经是一种哲学了。当然如果你是原教旨主义者那随你喜好咯(

另外,想要真正学习Vim的,建议Vimtutor,并且重点就是学习各种编辑快捷键,以及Vim的编辑器模型设计。

反正我现在原生的Vim使用场景要么是C/C++/Bash之类的主力开发,博客/笔记,要么是其他重量级语言/项目的轻度开发。写博客/写文章这种纯语言的输出挺适合Vim,重度写代码的话,还是自己组合一套合适的工具链完成吧。

0x01.基础操作

假定你在用任意一个Linux发行版(Windows需要单独下载),根据下面的步骤来尝试Vim吧。

首先,在命令行中输入vim,进入Vim。也可以输入vim filename来编辑一个现存的文件,或者创建并编辑一个新的文件。

进入Vim后,按键盘上的i以进入编辑模式。此时,最下方的状态指示变为INSERT,即插入模式。这时,我们可以像使用其他文本编辑器一样使用Vim,不过只能用键盘输入、删除和移动光标,并且不能用Ctrl+Z/C/V等组合键,它们不仅没有作用,有的还会终止编辑器使得你丢失编辑进度。

输入完毕后,按一下键盘左上角的Esc,退出编辑模式。随后,输入:(即英文冒号)进入命令模式,此时输入的命令在最底下的状态栏显示。接着,输入wq保存并退出vim。除了用:wq保存并退出,也可以按ESC之后直接输入ZZ(大写)来保存并退出。

这就是Vim的基本使用,现在可以尝试用它进行最基础的文件编辑。

0x02.常用操作与技巧

查找替换

  1. 查找

首先是单字符查找命令:f命令。它的用法为f{char},也就是先按f再按要查找的字符。使用;查找下一个字符,使用,查找上一个字符。

其次是查找匹配项。可以使用/pattern来查找。用法很简单,输入/和要匹配的对象的表达式,回车即可。使用n查找下一项,用N查找上一项。

  1. 替换

Vi/Vim 中可以使用 :s 命令来替换字符串。以前只会使用一种格式来全文替换,今天发现该命令有很多种写法(vim 真是强大啊,还有很多需要学习的),记录几种在此,方便以后查询。

:s/vivian/sky/ 替换当前行第一个 vivian 为 sky
:s/vivian/sky/g 替换当前行所有 vivian 为 sky
:n,$s/vivian/sky/ 替换第 n 行开始到最后一行中每一行的第一个 vivian 为 sky
:n,$s/vivian/sky/g 替换第 n 行开始到最后一行中每一行所有 vivian 为 sky

n 为数字,若 n 为 . 则表示从当前行开始到最后一行

:%s/vivian/sky/(等同于 :g/vivian/s//sky/) 替换每一行的第一个 vivian 为 sky
:%s/vivian/sky/g(等同于 :g/vivian/s//sky/g) 替换每一行中所有 vivian 为 sky

替换可以使用&重复,使用u撤销。

或者,可以在普通模式上使用r进行单次替换,使用R/Insert进行多次替换。借助后者,可以进入替换模式。在这模式下,输入任意字符都会替换当前位置的字符。如果替换错误的话,使用Backspace退格取消替换,或者先返回普通模,再按u撤销上次更改即可。

跳转

Vim的复杂,一定程度上就是因为跳转功能十分丰富。比如:

  • {}:跳转到下一个空白行
  • C-fC-b:上下滚动屏幕
  • C-uC-d:上下滚动半屏
  • we:跳转到下一个词开头/当前词结尾
  • gh/j/k/l:无视行,在折行中进行上下左右的跳转
  • *:跳转到下一个和光标下匹配的词
  • nN:跳转到下/上一个搜索词
  • {}:跳转到上/下一个空行

标记-mark

此外还有一个标签(mark)系统可以让你在一个地方插标记传送锚点,然后跳回来。标签记录的位置信息是相对于行而言,而非行号。

:help mark-motions查看所有帮助。

  • 创建
    使用m[a-zA-Z]在光标所在处创建标记,其中小写字母创建的标记只在当前缓冲区生效,大写字母的标记则在所有缓冲区生效。

  • 跳转
    使用'[a-zA-Z]跳转到标记行首个非空字符,''跳转到上个标记行的首个非空字符,\[a-zA-Z]用于跳转到标记时光标所在的位置,同理也可以使用 `` ` 跳转到上一个标记的光标位置。

  • 查看
    使用:marks可以查看所有标记,其中也会混入一些系统特殊标记:

  • .最近编辑的位置

  • 0-9最近使用的文件

  • ^最近插入的位置

  • '上一次跳转前的位置

  • "上一次退出文件时的位置

  • [上一次修改的开始处

  • ]上一次修改的结尾处

  • 删除标记
    删除一行会删除这行包含的标记,另外'a这样的标记也可以作为字符实体使用,比如d'a就可以删除标记的行。用:delmarks a b c删除多个标记,:delmarks!删除所有标记。

组合编辑

另外有一些命令将一些操作组合到了一起,实现了很多种的编辑方式,比如:

  • sS:删除当前字符/行并进入编辑模式
  • ccC:等价上面的S操作符
  • J:将下一行的内容拼接到当前行尾

其他的什么oOiIaA暂时懒得写了,因为有个更重要的就是按键组合。比如c$删除到行尾并编辑,caw/a/s/p删除并编辑当前单词/语块/行/段落等,都是很好用的组合编辑命令。

特别注意。上面的组合命令格式类似于动词+名词的结构,给一个可组合动词(反例就是s/S,按下就执行,无法组合)后面加上语义,构成了一种愉快的编辑体验:比手动框选更加精确迅速的编辑模式。

而且上面的操作也可以借助一次移动一次编辑的形式重复化利用,合起来就是编辑高效的秘诀。

Visual模式

Vim的使用场景一般都是SSH连接到无头服务器上。那种情况一般没有GUI,也没有鼠标。难道就不能像在Windows里一样用鼠标拖拽选择文字了?仍然可以,借助V模式即可。

V模式,也就是可视化模式,在按ESC退出编辑模式后,按v即可进入。此时,状态栏会显示--VISUAL--,这时用方向键/HJKL移动光标则会从当前位置“拖拽”选择文字,并且此时也一样支持gg/G:nn+方向键/HJKL来快速移动光标。此时再按一次v即可退出V模式。

进入V模式后,选择了需要编辑的内容之后,使用x可以剪切被框选的内容,y则可以复制区域内容,用p可以粘贴内容并覆盖所选区域;除此之外,"+y则可以复制内容到系统剪贴板"+p可以从系统剪贴板粘贴。注意这快捷键前的双引号是必须的。

如果需要多次复制粘贴内容,需要在~/.vimrc添加如下配置来直接同步系统剪贴板和Vim剪贴板:

1
>set clipboard=unnamedplus

借助V模式,不用鼠标也能选取文字、复制粘贴。更详细的用法可以阅读Vim的help手册。

分屏与文件浏览

使用vim时,用vim [filename]就可以打开/创建并编辑一个文件,不过filename也可以是目录名称,这样就会用vim内置的文件管理器打开目标目录。这个模式使用起来很简单,上下键移动光标,回车键确认。

分屏也是一个实用操作,不过学了tmux之后我就不怎么用vim的分屏操作了。

核心快捷键只有两组:Ctrl+w,h/vCtrl+w,h/j/k/l。第一组是分屏,h表示水平分屏,v表示垂直分屏。第二组快捷键表示在各个分屏中移动,h/j/k/l和vim默认模式的含义一样,表示向左/下/上/右移动。

另外,也可以通过:sp/vsp [filename]来水平/垂直分屏并打开名为filename的文件。

关闭分屏和关闭文件一样,选择当前分屏,用:q/wq(!)ZZ都可以退出(并保存)当前文件。

命令模式

在vim中也能直接和CLI交互,使用:![command]即可。其中,%表示当前文件的文件名。通过这个方法,我们可以快速调试单文件程序,例如:

1
2
:w    # 一定记得先保存当前文件再编译
:!gcc % && ./a.out

在命令模式输入上述代码,即可编译并运行当前文件。同时,命令模式也支持上下键回溯历史命令。

编写脚本时,借助它能够快速验证/执行脚本。

Ctrl+r

这是一个常用的插入快捷键,用于在insert模式下插入各种内容。下面用<C-r>表示Ctrl+r

插入寄存器中的内容

在vim中,寄存器用于存储文本。您可以使用以下命令将寄存器中的内容插入到当前位置:

1
<C-r>{register}

其中,{register}是要插入内容的寄存器名。例如,<C-r>0将插入0号寄存器中的内容。

插入表达式的结果

您可以使用以下命令将表达式的结果插入到当前位置:

1
<C-r>= {expression} <CR>

其中,{expression}是要求值的表达式。例如,<C-r>=2+2<CR>将在当前位置插入“4”,<C-r>=strftime('%c')<CR>可以插入当前日期。

插入文件名

如果您希望将文件名插入到当前位置,可以使用以下命令:

1
<C-r>%

这将在当前位置插入当前文件的名称。

插入上一次插入的文本

如果您需要在插入模式下重新插入上一次插入的文本,可以使用以下命令:

1
<C-r>"

这将在当前位置插入最后一次插入的文本。

高效编辑

这一部分比较杂,包含一些快捷操作。

插入删除

  • x 删除当前字符
  • i 在光标前插入
  • a 在光标后插入
  • o 在当前行后另起一行插入
  • O 在当前行前另起一行插入

另外,使用:g/pattern/d可以删除所有含有pattern的行。

快速跳转

  • :[line number] 快速跳转到目标行号
  • w 向后跳转一个单词
  • gg 跳转到全文开头,G 跳转到全文末
  • 0 跳转到当前行初,$ 跳转到当前行末
  • /[keyword] 搜索并跳转到keyword处,n 继续向后搜索,N 向前搜索
  • n+h/j/k/l 向前/下/上/后跳转n单位
  • ctrl+i 跳转到上一个历史位置
  • ctrl+o 跳转到下一个历史位置
  • gi 跳转到上一次编辑的位置
  • [number]G 跳转到第number行,和:number效果一样

除了上面那些操作,Vim还提供了很多移动功能。比如浏览一些可以折叠的代码块时,可以用下面的命令展开和折叠:

1
2
3
4
zM      "折叠代码块
zf[n]G "折叠当前行到第n行
zE "删除所有的折叠标签(被折叠的区域会有大括号作为提示)
zR "展开代码块

这部分的内容,详细可以看Vim的帮助文档。输入:h Folding即可查看。

复制粘贴

  • dd 删除当前行,ndd 删除从当前行往后的n行,dn+h/l 删除光标前/后n个字符
  • yy 复制当前行,nyy 复制从当前行往后的n行,yn+h/l 复制光标前/后n个字符
  • p 粘贴复制的内容

重复操作(宏)

这是Vim中最强大的功能之一。在处理较多数据的时候,真的能节省大量的时间。

  • q+[letter] 进入操作记录模式,随后除了 q的所有按键都会被记录
  • q 退出操作录制模式并保存之前的操作到letter
  • @[letter] 重复录制的操作,n@[letter] 重复n次录制的操作

举个例子吧。比如我想删掉每行行末的两个字符,我就可以这么用:

1
2
3
4
Esc+gg    "跳转到开头
qq "开始录制宏到q中
$,xx,j "逗号表示隔开的操作。它表示先跳转到行末,然后删除两个字符,再跳到下一行
q "停止并保存宏到q

这样就完成录制了。随后移动光标到你编辑的起始位置,并输入n@q来批量操作,其中的n表示你需要重复操作的次数。

随后,欣赏魔法吧(雾

在录制宏的时候,尽量用相对定位,例如0$(行首和行末),同时尽量先确认操作是能达到效果的,不然自动机乱飞就不好玩了(其实误操作也能用u救回来

借助其他程序处理Buffer

Vim里边一个很好用的命令是:%![command],它的作用是把Vim缓冲区作为command的标准输入,再把缓冲区替换为程序的标准输出。最近写go的时候这个就很方便了,需要格式化代码的时候:%!gofmt就好了。

Bin编辑

Esc+:进入命令模式后,输入%!xxd就可以用二进制模式查看文件。

要返回正常模式,只需要输入%!xxd -r即可返回。

jyy好强(

Vim+grep

在Vim命令模式中可以这样使用grep:

1
2
:%!grep execve      # 提取出含有execve的行
:%!grep -v ENOENT # 过滤掉含有ENOENT的行

这对buffer中的数据调用命令行进行处理,并替换(?)Vim Buffer中的内容。实质上和上面的Bin编辑类似(?)。

JSON内容格式化

1
:%!jq

使用jq对缓冲区中的内容进行格式化并替换缓冲区。

内容按照首字母排序

众所周知bash里边可以在各种命令管道里边组合sort,其实Vim也可以:

1
:%!sort

上面的命令使用sort命令对缓冲区中的行按照首字母进行排序。

范式

.命令会重复上次修改,而查找命令(无论是/+n还是f+;)可以快速移动到下一个匹配位置。一个理想的Vim范式,就是使用一个命令修改,另一个命令移动>.

上面的范式平时可以多用用。.不光可以重复操作,也可以重复键入上次编辑的内容,比如cw+输入+<ESC>这一段就可以用.来重复,然后用Vim的移动黑魔法带你去任何你想重复这个操作的地方,比如快速更改某个关键字但是又不能一股脑批量替换的情况。

MISC-其他技巧

从磁盘重新加载文件

比如,在日常编写一些文件的时候,可能会想顺手将一些内容直接输出(附加)到当前文件后,而不是输出后再想办法选择复制粘贴。但是如果你使用cat fname >> file_editing.md时,Vim的默认行为是不会自动从磁盘重新加载文件内容的。

这种时候就可以用:e!或者:edit!强制清空当前未保存更改并从磁盘加载文件最新内容,覆盖当前缓冲区。因此有重要内容记得先yy复制一下以防丢失。

这种使用场景多见于写问题分析报告的时候,写着写着从终端输出一段日志到当前编写的报告里边来作为报告内容。当然,也可以是其他的内容,比如重要持续任务的数据流等,我会将文件作为输出并直接编辑输出内容。

另外也可以用:w start,end dest_file_name.md来将文件的一部分内容输出到另一个文件中。

输出重定向到Vim

1
strace -f gcc a.c |& vim -

上面的管道符将strace的输出(stdin)重定向到了Vim中,便于我们查看和编辑。

另外,其实有不少UNIX程序都接受这个参数-,这个参数的约定一般指的是让程序使用标准输入和标准输出读取和写入内容。比如tardd两个命令都接受这个参数的约定语义。

0x03.配置文件

一般指的是用户目录下的.vimrc文件。Vim启动时会自动读取并加载它。它的内容主要包含Vim设置项,自定义函数等。

下面是一份示例配置文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
"这是注释,以英文双引号开头

syntax enable
syntax on

set tabstop=4
set shiftwidth=4
set autoindent
set smartindent
set ignorecase
set cindent
set shiftround
set encoding=utf-8
set number
set ruler
set hlsearch
set laststatus=2
"set showmatch
"set cursorline
highlight StatusLine guifg=SlateBlue guibg=Yellow

let g:netrw_winsize=30
let g:netrw_liststyle=1
let g:netrw_timefmt='%Y-%m-%d %H:%M:%S'

filetype plugin on

map <F5> :call PRUN()<CR>
nmap <F6> :Sexplore!<CR>
inoremap <TAB> <C-R>=InsertTabWrapper()<CR>

func! PRUN()
exec "w"
if &filetype == 'python'
exec "!python %"
elseif &filetype == 'c'
exec "!gcc % && ./a.out && rm ./a.out"
endif
endfunc

func! InsertTabWrapper()
let col=col('.')-1
if !col || getline('.')[col-1] !~ '\k'
return "\<TAB>"
else
return "\<C-N>"
endif
endfunc

Vim配置文件的路径在当前用户目录下,也就是/home/usrname/.vimrc,不同的用户都有各自的配置文件。

配置结构

前两行是开启代码高亮和语法分析。第一大块主要是和缩进有关,前四行都是缩进设置,后几行分别是搜索时忽略大小写,启用C语言语法缩进,shiftround是啥来着忘了(

下一个小块(只有一行)是设置编码为utf-8

下一个大块基本是界面显示相关设置。第一行是开启行号显示,第二行没啥用给注释掉了,第三行是显示当前光标在第几行第几列,第四行是高亮被搜索的关键字,下一行是在当前行显示下划线,用不上所以我注释掉了。下一行是显示编辑状态栏,再下一行是设置状态栏样式。

下一大块是设置自带的树状图文件浏览器的。

后面的一堆xxmap是配置按键事件/映射的。

后面那一堆func是各种函数,能够实现一些简单的功能,比如TAB补全,F5代码运行。

综上,可以看出,vim配置文件.vimrc的结构大致==可以分为5个部分==,分别是

  • 编辑器一般设置。包括格式,高亮,vim外观等
  • 常量设置。通过预设一些常量来更改vim行为
  • 插件设置。
  • 按键映射绑定。更改/添加按键功能
  • 函数。给编辑器添加自定义的功能

通过更改配置文件,我们可以十分简便地更改vim的外观,操作,代码高亮和补全等。并且可以非常轻松地迁移配置——复制.vimrc到新的地方即可。唯一的缺点是,你通常不知道都有什么可以更改的设置。在这一点上,充分利用vim自带的帮助文档吧:输入:help并回车即可查看。

常用配置

  • set wrap/set nowrap 禁用换行
  • set number/set nonumber 启用/禁用行号
  • set ai/set noai 启用/禁用自动缩进,粘贴进代码自动缩进的话可以暂时关掉自动

0x04.常见问题

  1. GVIM主界面乱码

修改C:\Program Files (x86)\Vim\vim80\menu.vim文件,增加

1
set encoding=utf-8
  1. 改变字体大小

也是在上面的文件里,添加如下设置:

1
set guifont=Lucida\ Console:h14

如果没效果就把语句从文件末尾移到开头。

  1. 无法使用剪切板

最近用Vim的时候总是会跳出一个info:Authorization required, but no authorization protocol specified。最后在网上的vim-use邮件列表里边找到这个问题的答案了。原因是Vim和X-Server通信失败,导致出现了这个问题。为啥要访问X-Server呢?为了使用Vim的系统剪切板支持。所以解决方法可以是使用vim -X直接让Vim不和X-Server通信,100%有效。或者就是排查一下你的*nix发生了什么导致X-Server权限异常。

0x05.插件

就我的观点来看,插件一般是没啥必要折腾的,当你Vim的各种特性熟悉之后,基本上大部分插件提供的功能你都能用原生Vim在可以接受的步骤里达到。

言归正传,现在的插件安装一般推荐使用Vim-plug,是个韩国人写的插件管理器,轻量好用,便于复刻。

0x06.写在最后

编辑器之神的称号源于它编辑文本贼6,而不是能变身All in one IDE(虽然确实可以这么干),写大型项目还是建议直接一步到胃用VS/IDEA。Vim一般也就写写单文件程序/改改配置之类,以及适用于一切要求快速编辑的场合比如做笔记

Vim可以给你黑魔法,让你用令人目瞪口呆的速度写下你所想的东西,或者是更改需要更改的东西。最大限度地消除了编辑器和你的思想间的带宽限制之后,所剩下唯一的桎梏,就是——

你。

0x07.参考内容

作者

xeonds

发布于

2021-06-19

更新于

2024-05-13

许可协议

评论