这篇文章主要总结了我在使用 Vim 过程中遇到的一些问题及解决方案,都是一些比较零碎的内容,如果要看 Vim 系统的内容可以参考之前的几篇文章。

Vim 中格式话 JSON

依赖 jq 命令:

sudo apt install jq

然后在 vim 中就可以:

:%!jq .

查看 Vim 使用的配置

在 vim 中输入

:script 来查看 Vim 加载使用的配置

查看 Vim 的版本

:version 来查看 Vim 的版本

在有一次使用 Vim 的时候总是无法将 Vim 选中的内容和系统粘贴板用到一起 "+y"+p 根本无法使用,后来经过网上一查, 通过 :version 一查才知道原来本地安装的 Vim 版本根本没有把 clipboard 支持编译进去。所有有的时候遇到问题第一时间检查一下版本还是比较重要的。

查看 Vim 中所有的快捷键映射

使用 :map 来查看当前 Vim 配置中所有的快捷键映射。

列选

  1. 进入 Visual Block Mode Ctrl + V
  2. 选中编辑的列
  3. Shift + i 进入编辑模式 Insert Mode
  4. 输入编辑
  5. esc 两次

批量缩进代码

如果使用 VS,或者 IDE 的同学应该都知道,如果要批量缩进代码,在这些 IDE 中都能够选择 +tab 键实现,而 Vim 中则不太一样,之前困扰我很久,现在终于有了解决方案。在之前的文章中已经提到了 Vim 的模式,现在我们要用到其中的一种 —- 选择模式。

批量缩进代码的方式如下:

  • 按下 v , 进入选择模式,如果要进入行选择模式则使用大写的 V
  • j/k 移动光标选择需要缩进行
  • 按一次> 缩进一次,按 < 回缩

如果是需要选中的行数比较多可以使用 数字 num+j 方法移动 num 行,对于有括号 { } 的方法,例如

function functionName(){
// a lot of code
}

则可以使用 % 进行括号匹配,按下 v 进入选择模式,将光标移动到 { ,按下 % ,Vim 自动找到匹配的括号并选择该函数,利用 > 即可缩进该函数。

那么,其实单行缩进就是两个大于号 >> , 回缩就是两个小于号 <<

不重启使 vimrc 文件生效

在学习阶段,我经常改动 vimrc 文件,而每一次改动就要重启一下 Vim,甚是烦恼。偶然间看到 Google Group 中有人讨论一些无关紧要的问题,其中看到写了不重启使 vimrc 文件生效的代码,尝试一下确实可行,做一下记录:

在命令模式下运行
:so #MYVIMRC
去帮助查看 so,其实 so 是 source 的缩写

当然你也可以在 vimrc 文件中加入

"编辑 vimrc 之后,重新加载
autocmd! bufwritepost _vimrc source $VIM/_vimr

这样每一次保存 vimrc 文件就自动加载 vimrc 文件,使之生效。而如果在 vimrc 文件中存在函数,可能会遇到 vim 警告“函数 已存在,请加!强制替换”,同样讨厌,虽然作为新手的我还不知道为什么出现这些警告,但总之解决方法就是把 vimrc 中的函数全部定义成 function! 这种形式。但其实那些警告不影响效果,不定义成 function! 也行,但是很烦人。

均匀插入空行

均匀的在行与行之间插入空行,原先的空行保留。

Vim 的 :g 命令就是为类似的任务设计的,给每一行运行单独的命令。使用如下命令完成目标:

:g/.\n\n\@!/norm o

正则匹配 /.\n\n\@!/ ,拆分成不同部分来解释:

  • . 匹配行中所有字符。(这个例子中用来排除空行)
  • \n 匹配行末尾
  • \n\@! 如果有连续两个换行则匹配失败

用命令 :h E59 查看 \@! 更多信息。我们使用 :g 命令正则匹配到符合规则的行之后,我们告诉 Vim 执行 norm o ,也就是 Normal Mode 下的 o 命令,也就是在当前行下插入空行。

总结来说,这行命令匹配所有下一行不是空行的行,然后在他们下面增加一行空行。通过这个例子,你也许想要查看一下 vim 的 wiki Power of G 来学习一下 :g 命令,已经它的姐妹命令 :v

This note is taken from superuser

从 vim 中复制到粘贴板

使用 shift+v 选中几行内容之后,如果只使用y 无法复制到系统的粘贴板中,此时在选中的情况下输入 "+y , 即可将所选内容复制到粘贴板。注意需要输入的是:引号 + 加号 + 小写 y。

而这样做需要输入三次,可以使用 map 绑定到喜欢的快捷键上,比如:

vmap <C-c> "+y

这一行配置的含义就是在可视模式下,Ctrl+c,就是将所选择内容复制到粘贴板。 但是需要注意的是如果运行 :echo has('clipboard') 返回的结果是 0,那么这个方法就没用,因为该版本的 vim 在编译的时候没有将 +clipboard 加入。

同理,如果想要从系统粘贴板中粘贴内容到 vim 中,使用 "+y or "*y, 引号 + 加号 +y,来从系统粘贴板中将内容粘贴到 vim 中。

NERDTree Tip

Vim 中极好用的文件管理插件,用了也有一些时间了,但是有些内容并没有仔细地看,今天突然有些需求就看了一下。常用的 NERDTree 命令有:

  • o 打开或关闭文件或目录
  • i 在水平分割的新窗口打开文件
  • s 在垂直分割的窗口中打开文件
  • t 在新标签页中打开文件
  • j/k 移动
  • J/K 到第一个或者最后一个节点
  • ? 帮助菜单

创建目录与文件

打开 NERDTree,在 NERDTree 中使用m 然后选择a,来创建文件或者文件夹,要创建文件夹只需要在输入的名字后面加上/

删除文件与目录

同理,在 NERDTree 中按下 m 会由很多选项可选,使用 d 就可以删除结点,也就是删除文件或者文件夹。

显示隐藏文件

在 NERDTree 中使用Shift+i 来显示隐藏文件。

vim 删除偶数行

使用命令:

:g/^/+d

:g 命令在所有匹配正则的行上执行

:g/LinesMatchThisRegex/ExecuteThisCommand

举例:

:g/hello/d

以上命令会删除所有包含 “hello” 的行

而与此同时 :%s 仅仅提供正则的搜索和替换,命令最后的 g 表示全局,整个文件中

:%s/hello/world/g

因此该命令会替换文中所有的 hello 为 world.

:%s 中的 s 表示替换 (substitute) , 而 % 表示整个 buffer. 因此 :%s 表示从整个文件 buffer 中替换,:%s 还可以指定行范围:

:10,15s/hello/world/g

搜索并替换 10 至 15 行中的 hello 为 world.

快速移动

在 vim 中移动 hjkl, 左下上右移动光标已经不用多说, wb, 向后向前移动一个 word。

gg 移动到第一行, G 移动到最后一行,这是最基本的,也可以使用 nG 来移动到第 n 行。

翻页技能,使用 Ctrl D 向下移动半页, Ctrl U 向上移动半页

Ctrl B 向上翻页, Ctrl F 向下翻页

  • * 号用来向下查找整个单词
  • # 号用来将光标移动到上一个在光标下的字符,比如光标正在单词 String 上,使用 # 来向上查找上一个 String。
  • % 百分号用来在匹配的括号之间跳转。
  • fx 光标跳转到下一个 x 位置,可以用来快速跳转到下一个预期的字符 x
  • Fx 向前跳跃到字符 x 位置
  • tx til 下一个 x,光标在 x 前面
  • Tx 上一个 x

让 vim 支持系统粘贴板

sudo apt install vim-gnome

配置 leader

配置的 leader 要在 map 之前

let mapleader = ","
let g:mapleader = ","

Vim 自动保存

使用现在的配置有一段时间了,不过最近有一篇文章,因为没有使用 Vim 的保存,而丢失了部分,所以想到了 Vim 应该能够自动保存的。在我丢失部分为保存内容的时候,我想起了 Vim 的 swp 文件,可惜的是我在 vimrc 配置中禁用了 swp 文件

set noswapfile

所以丢失了 swp 文件的我,依然找不回来丢失的内容。网上大致搜了一下,真的有解决方法,在 vim 丢失 focus 的时候自动保存 1

:au FocusLost * :wa
:au FocusLost * silent! wa

把这句话放到 vimrc 中,保存。另外一种方法就是 autocmd CursorHold * updateCursorHold 命令会在用户间隔 updatetime 时间 (milliseconds) 没有按下任何按键时被触发。:update 命令会保存被修改的 buffer。如果想要在插入模式下面也自动保存,那么 CursorHoldI 事件也可以被使用:

autocmd CursorHold,CursorHoldI * update

增减数字

将光标停在数字上,Vim 中 Ctrl + x 会将数字减 1, 而 Ctrl + a</kdb> 能将数字加 1 , 默认为 8 进制。

在插入模式下移动 {#move under insert mode}

前段时间听到一个问题:“Vim 如何在插入模式下移动?“,一开始听到这个问题的时候,我有点楞,但是对于这个问题,我开始相信有解法的,毕竟 Vim remap 还是很强大的,大致搜了一下,大部分的答案是使用 imap <C-n> <Down> 这样将 Ctrl + n 来映射到向下移动,但直到我看到了这样一则评论:

Vim is designed for navigation to be done in normal mode and text insertion to be done in insert mode. You will be much happier and more productive in the long term if you learn to use Vim the way it was designed to be used instead of fighting it. If you try it for a while and find you really don’t like a moded editor, you may want to try Emacs. It is another very powerful editor, but lets you navigate and edit without changing modes. – garyjohn Jan 7 ‘13 at 7:05

顿时我恍然大悟,Vim 设计的一大准则就是将文本的移动放到了 normal mode 中,只有插入文本的时候才会进入 insert mode。而对于这个问题,其实本质上是对 Vim 设计的挑战。所以才有了 Emacs,可以在不切换模式的情况下在编辑器中快速移动。我平时在使用的时候,其实这个需求也很少,并且 ESC ,从插入模式到 Normal mode 也不是很难的操作,所以对于我来说还好,不过可能对于许多刚刚接触 Vim ,并且对以前无模式编辑器使用比较深入的人来说,可能是一个比较难越过的坎。

不过 Vim 在 Insert mode 下还是有两个比较常用的快捷键

  • 在插入模式下,删除该行当前输入的文字,通过 `:help i_CTRL-U` 查看帮助
  • 在插入模式下,删除光标前的 word, 通过 `:help i_CTRL-W` 查看帮助

将当前单词插入到命令行

在 Vim 命令行下, Ctrl-r Ctrl-w 会复制光标下的单词并插入到命令行中。

把文件保存到不存在的目录中

:!mkdir -p %:h
:write

以超级管理员权限保存文件

:w !sudo tee % > /dev/null

参考配置

  1. http://vim.wikia.com/wiki/Auto_save_files_when_focus_is_lost