Vim技巧汇总

2017-04-29|Categories: Vim|

查看Vim帮助文件

Vim的模式有多种,比如Normal(普通模式),Insert(插入模式),Command(命令行模式),Visual(可视化模式)。相同的命令和快捷键在不同的模式下功能是不一样的,因此帮助信息也是分模式的。

Keystroke Meaning
:h :r 查找命令行模式下的帮助信息
:h r 查找普通模式下的帮助信息
:h v_r 查找可视化模式下的帮助信息
:h i_ctrl-w 查找插入模式下快捷键的帮助信息
:h c_ctrl-w 查找命令行模式下快捷键的帮助信息
:h /\r 查找正则表达式的帮助信息
:h 'bs' 查找选项的帮助信息
:set bs? 获取选项的值
:h -r 查找参数的帮助信息

文件编码、特殊字符、字体

快速更改MacVim字体

  1. :set guifont=*
  2. 在弹出的对话框选择字体,调整字号
  3. 通过:set gfn查看当前设置,把命令输出内容添加到.vimrc

用指定编码重新读取文件

Vim打开某些文件可能会乱码,此时可以指定编码重新读取文件,就可以正常显示。

  • :e ++enc=cp936
  • :e ++enc=gbk
  • :e ++enc=utf-8

cp936代表「简体中文」。

显示换行符、回车符

很多时候我们需要保证每一行文本的末尾没有额外的不可见字符,Vim可以让它们变得「可见」:

  • :set list shows newline ($)
  • :e ++ff=unix shows CR (^M)
  • if you want to see both, :set list then :e ++ff=unix

https://stackoverflow.com/questions/3860519/see-line-breaks-and-carriage-returns-in-editor

去除Windows文本的^M符号

在Linux/Unix下編輯文件時,經常會在文件中看到一個^M符號,代表的是 Windows(DOS) 系統的換行符

  • 方案一(首选)::%s/\r//gc
  • 方案二::%s/<ctrl-v><ctrl-m>//gc
    • 注意:ctrl-vctrl-m不是输入,而是按键,显示在屏幕上是:%s/^M//gc
  • 方案三:利用Vim对文本进行转换:
    1. 首先打开文本
    2. 然后set fileformat=unix
    3. 重新保存该文件就可以去除^M

搜索特殊字符 2018-02-26

从网上复制的内容可能包含特殊字符,例如下图中第二行光标高亮(黄色)的空白字符就很特殊,既不是空格,也不是制表符TAB,通过:as命令查看光标所在字符的ASCII编码是12288(十进制):

unum工具查看对应的字符是ideographic space(表意空格):

此时可以用字符的十进制ASCII代码将所有相同字符搜索出来,以便进一步处理:

上图使用的搜索字符串是/\%d12288,正斜线开始搜索,反斜线转义后面的百分号,%d表示后面是十进制数字(decimal),详见:h /\%d

如果要删除所有特殊空格和后面的数字,可以执行:%s/\%d12288.*$//

文本编辑

在长短不一致的行尾统一添加内容

如下图所示,需要给多行文本末尾添加</li>标签:

vim adds multiple html close tags at one time

  1. 光标移到第二行末尾
  2. ctrl-v
  3. $5jA</li>
    • 重点在于$:在Visual block模式下,$命令会让每一行的被选择区域扩展到该行的末尾,不管这些行的长短是否参差不齐。
  4. <ESC>

快速删除所有空行

在Normal模式输入以下命令:

" method 1
:g/^$/d

" method 2
:v/./d

方法一::g会在匹配正则表达式的行执行命令,这里的表达式是^$(空行),命令是:d(delete)。详见:h :g:h :d

方法二::v会在不匹配正则表达式的行执行命令:这里的表达式是.(一个任意字符)。

直接打开到文件的末尾

vim + file_name

相当于打开文件之后,在Normal模式下按 G

查看或编辑远程主机的文件 2017-11-19

vimdiff /etc/inputrc scp://user@host//etc/inputrc

注意:主机与文件绝对路径之间有一个/作为分隔符,合起来就是两个斜线://etc/inputrc

把所有竖线替换成换行符 2018-04-25

原始文本如下:

debug|info|notice|warning|err|crit|alert|emerg

替换命令:

:s/|/\r/g 

这里必须使用回车符\r,不能使用换行符\n,否则将是错误的结果:

上图中的^@表示控制字符NUL,用unum小工具查看十六进制ASCII编码为0x00,在屏幕上可见,但不可打印,两个空行是为了截图手工添加的,便于查看控制字符的特殊颜色。

坦白说,我并不明白这里为什么要用到换行符\r。因为这个缓冲区的fileformat=unix,Vim帮助文件明确指出unix的行结束符(EOL)是<NL>(New Line),而\r是匹配<CR>(Carriage Return)的。为此我特意在Windows系统上安装了gVim,fileformat=dos,输入同样的文本,但需要的替换命令是一样的。

目前看来,这个诡异的行为只能死记硬背了。

把所有换行符替换成竖线 2018-04-25

原始文本如下:

debug
info
notice
warning
err
crit
alert
emerg

替换命令:

:%s/\n/|/g

替换结果如下:

debug|info|notice|warning|err|crit|alert|emerg|

注意,行尾多了一条竖线,这不是我们想要的,因此需要把前面的替换命令稍作修改:

:1,$-1s/\n/|/g

也就是把表示所有行的百分号%替换成了1,$-1,表示替换操作从第一行执行到倒数第二行。

和前面的《把所有竖线替换成换行符》小节相比,这里必须使用换行符\n,不能使用回车符\r,否则将报错E486: Pattern not found: \r

合并行不出现空格 2018-04-28

J命令可以合并相邻的两行,但会保留一个空格,对于英文这种需要空格作为分隔符的语言,这是非常周到的设计。但对于中文则没有必要,因为中文是依靠单个字符本身的间距来分隔的,此时可以使用gJ命令来合并,合并的同时不保留空格。

如果需要合并多行,第一次执行gJ命令之后,按圆点.命令重复执行即可,也可以添加命令计数,例如5.表示重复执行5次。

复制粘贴

复制当前文件的文件名、路径到本机系统剪贴板 2017-09-12

" Copy current file's Name to the system clipboard
" `:help registers`, `:help expand`
:nmap <leader>cn :let @+ = expand("%")<cr>

" Copy current file's Path to the system clipboard
:nmap <leader>cp :let @+ = expand("%:p")<cr>

复制内容到本机系统剪贴板 2017-09-12

使用y可以把内容复制到Vim默认的寄存器"",这个寄存器只有Vim可以访问,无法粘贴到其它应用程序。

使用"+y可以把内容复制到"+寄存器,也就是系统剪贴板,稍后就可以随意粘贴到其它应用程序。

也可以使用"+p把系统剪贴板的内容粘贴到Vim。

从远程主机复制内容到本机系统剪贴板 2017-11-26

通过ssh连接到远程主机,然后使用远程主机的Vim编辑文件时,会发现"+y无法把远程主机的内容复制到本地系统剪贴板,因为此时的"+寄存器是指运行Vim那台远程主机的系统剪贴板,而不是本机系统剪贴板,二者无法通信。

Vim插件PowerYank可以解决这个问题。安装插件之后,在Visual模式选中内容,然后输入:PowerYankOSC52即可。

当然,挨个输入这么长的命令肯定是非常痛苦的,此时要开启ignorecasewildmenu两个选项,输入pow三个字母就可以按<tab>键自动补全命令。

调用shell命令

读取外部命令的标准输出

编写shell脚本、修改配置文件的时候,经常需要输入一些特殊的字符串,比如挂载某个设备需要UUID,这些字符串很长、没有规律难以记忆,手工输入容易出错,而直接读取外部命令输出就可以解决这些问题。

:r! mdadm --detail /dev/md0 | grep -i uuid

详见:h :r!

把文件保存到不存在的目录 2017-09-16

使用Vim时可能出现这样的场景:突然需要新建一个文件,比如~/.config/nvim/init.vim,尽管nvim这个目录并不存在,还是可以在Vim里输入:e ~/.config/nvim/init.vim编辑这个文件,但却无法保存,这时候可以执行以下命令:

:! mkdir %:p:h

调用外部的mkdir命令创建需要的目录,%:p:h的意思如下:

  • %:当前文件;
  • p:当前文件的完整路径(path);
  • h:完整路径的头部(head),也就是不包含路径最后的文件名。

详细解释可以通过:h expand查询。然后就可以输入:w保存了。

当然,回到shell手工输入完整路径创建目录也可以,但效率偏低,还可能输入错误。

代码格式化

格式化xml 2017-09-12

https://unix.stackexchange.com/questions/62464/vim-making-xml-text-pretty

:%! xmllint --format %
  • macOS自带xmllint
  • 如果opening tagclosing tag不匹配,执行命令会报错。
  • 如果文件顶部没有xml声明,执行命令会自动添加。

格式化shell脚本 2018-04-21

:set ft=sh
gg=G

Vim插件

查询某个快捷键由哪个插件绑定

下面的命令可以查询「插入模式」下,<tab>键是被哪个插件的哪个命令所绑定:

:verbose imap <tab>

check key mappings in vim

如果只输入:imap <tab>,输出就不会包含Last set from ...这一行。imap可以被替换成nmapvmap,分别代表「Normal模式」、「Visual模式」。

这种方式只会显示插件和.vimrc绑定的快捷键,Vim内建的快捷键可以通过:h index查询。这里是我最常用的Vim内建快捷键

在netrw显示行号

let g:netrw_bufsettings = 'noma nomod nu nobl nowrap ro'

如果安装了EasyMotion插件,可以快速、精准跳转,不再需要根据行号跳转。

从netrw返回之前编辑的文件

  • ctrl-^ = ctrl-6 = :e #
    • 详见:h ctrl-^
    • 此快捷键在GUI版本的MacVim上无效,但在控制台版本的MacVim上有效
  • :Rex
    • 如果设置了set ignorecase,只需要输入:rex<tab>,不需要切换大小写

vim-surround

使用vim-surround添加括号(方括号、圆括号、花括号、尖括号)时,输入开括号或闭括号可以决定是否添加额外的空格,非常精妙:

  • 开括号:添加空格
  • 闭括号:不添加空格

vim-surround

Leave A Comment