转自:捡田螺的小男孩
本教程并不是单纯的vim操作介绍,更多的是与Intellj Idea进行配合。需要同时具备Intellj Ideavim使用基础的同学学习。


1
简介
Vim是一个高度可配置的文本编辑器,旨在高效地创建和更改任何类型的文本。它作为“vi”包含在大多数UNIX系统和Apple OS X中。Vim 非常稳定,并且正在不断开发以变得更好。
它的特点包括:
  1. 持久的、多级撤消树
  2. 广泛的插件系统
  1. 支持数百种编程语言和文件格式
  2. 强大的搜索和替换
  3. 与许多工具集成

为什么要在 Intellj Idea 中使用 Vim?在我们学习某一项新技能,或者新的编程语言,新的编程模式。我们应该自问让我们做出这样的行为的驱动力是什么?学习完它之后它能解决你什么样的疼点问题。这样我们学习起来会更有动力一些。

让我尝试学习Vim的理由:

Mac平台下Intellj Idea的很多的常用的action都是需要command + option这个组合键,从我转到Mac下,就一直很懊恼,个人感觉这个按键很反人类。
作为一名服务端开发同学,还是会经常需要在linux服务器上去修改服务器的系统配置文件。比如nginx配置,这个时候不可避免的需要使用到vim编辑器。如果你不熟练 操作起来还是相当的难受的。
Intellj Idea中安装了vim插件之后。是一个互补的状态 利用各自的优势 使得编程更有效率。


2
安装
Intellj Idea中 安装以下三个插件
  • IdeaVim
  • IdeaVim-EasyMotion
  • IdeaVimExtension
发现图标像上面一样编程一个小方块的时候 就代表插件安装成功


3
Vim
不得不说vim的学习成本还是有的,典型的入门很难 入门之后就会爱不释手。我这里对一些基础操作进行一些简单的总结和整理。
练习一:方向键联系 hjkl
根据我自己的经验总结下来从原生编辑器过度到Vim最不习惯的当属方向键的移动从原本的 方向键变成了hjkl
这个其实没有太多好说的 就是需要克服这一关。多练就行。(下图为 Gif 演示)

练习二:复制 & 粘贴

CV大法好,毕竟大家有时候自嘲都是C V工程师 😈 所以 复制 粘贴 还是需要在第一时间学会,这样才能更好的coding💩。
  • yy复制当前行
  • p粘贴
练习三:在学多一点点
在学习一些其他的命令 提交效率。
y p f h c i
GIF 中步骤如下:
  1. yy复制当前行private String username;
  2. p将复制的内容进行粘贴
  3. f;跳转到字符;处,这里其实就是相当于行位。
  4. h向左移动一个光标
  5. ciw删除当前处的词,并进入插入模式
  6. password输入 password 完成

v j d

GIF 中步骤如下:
  1. V进入内容选择模式
  2. kkk向上移动 3 行,并进行选中
  3. d删除选中部分

块级删除「常用」di* da*

di"删除"内的内容,个人感觉这个还是非常常用了。也是初步在效率上优于传统的 intellj idea 的操作方式。如果想要删除之后马上进入插入模式 可以使用ci"
di(删除(内的内容,如果想要删除之后马上进入插入模式 可以使用ci(
di{删除{内的内容,如果想要删除之后马上进入插入模式 可以使用ci{

各种进入插入模式

  • i在光标之前,进入插入模式
  • I在本行开头,进入插入模式
  • a在光标之后,进入插入模式
  • A在本行结尾,进入插入模式
  • o在本行之后新增一行,并进入插入模式
  • O在本行之前新增一行,并进入插入模式
  • s删除当前字符,并进入插入模式
  • S删除当前行中的所有文本,并进入插入模式
在我最开始的学习 vim 的时候只知道i进入插入模式。后面才知道还有这么多种方式。
如果你真的是切换过来之后 这里所有的方式都能用到。
在IDEA Intellij小技巧和插件一文中简单介绍了一下IdeaVim插件。在这里详细总结一下这个插件在日常编程中的一些常用小技巧。供有兴趣使用这个插件,但对Vim还不十分熟悉的朋友参考。当然基本的hjkl移动光标和几种常见模式等等基本概念就略过不提了。为了确保只包含常用操作,这里提到的技巧都没有从现成文档里抄,而是凭记忆列出(不常用自然就不记得了)。估计会有所遗漏,慢慢再补充。
1.切换Vim模拟器状态
这个插件允许设置一个快捷键一键开启或关闭,在切换模式时会同时自动切换keymap,十分方便。默认键位是Ctrl+Alt+V,但这个键位覆盖了很常用的“抽取局部变量”功能,建议重设,在setting->keymap中查找VIM Emulator即可。
由于开启和关闭状态分别使用两套keymap,因此两套都需要设定。可以把两套keymap下的都设为一样的键,也就是用同一个键切换。但个人建议设为不同的键,这样能清楚知道当前处于那种模式中。并且,如果在开启Vim的插入模式下关闭Vim模拟器,下次进入时仍然是插入模式,比较混乱(因为你关闭模拟器就是为了使用默认keymap输入大段代码,重新开启Vim模拟器就是为了使用普通模式下的命令)。因此建议把Vim keymap中的Exit Insert Mode设为与另一个keymap的Vim Emulator相同的键(也就是进入Vim模拟器的快捷键)。例如,我使用的设定是:
Default keymap -> Vim Emulator :Ctrl+;(用Ctrl+分号开启Vim模拟器)
Vim keymap -> Vim Emulator : Ctrl+,(用Ctrl+逗号关闭Vim模拟器)
Vim keymap -> Vim Emulator : Ctrl+;(用Ctrl+分号退出插入模式,进入普通模式)
这样,在任何时候只要连按两下ctrl+分号,就能保证必定在Vim模拟器的普通模式中。
2. ScrollOff参数
启动Intellij后在Vim模拟器下输入命令:set so=5可以令屏幕滚动时在光标上下方保留5行预览代码(也就是光标会在第5行触发向上滚动,或者在倒数第5行触发向下滚动)。在代码窗口比较狭小时(例如单步跟踪调试时)非常方便。可惜仅在Vim模拟器开启时有效。
3.行号定位
普通模式下输入行号G或:行号<回车>都能快速定位到某一行。区别在于前者在输入行号时屏幕上没有任何提示,后者则在Vim命令输入框中可以看到输入过程。(题外话:Sublime Text 2也是用:行号来快速定位到某行,应该是沿用了Vim的习惯)
4.进入修改
进入插入模式的方式有很多,直接选用合适的方式进入插入模式比进入后再用箭头键移动光标要好。常用的有:
o -在当前行下方插入新行并自动缩进
O -在当前行上方插入新行并自动缩进(普通模式下的大写字母命令用shift+字母键输入,下同)
i -在当前字符左方开始插入字符
a -在当前字符右方开始插入字符
I -光标移动到行首并进入插入模式
A -光标移动到行尾并进入插入模式
s -删除光标所在字符并进入插入模式
S -删除光标所在行并进入插入模式
c<范围> -删除光标所在位置周围某个范围的文本并进入插入模式。关于范围请看第5点,常用的组合有:caw -删除一个单词包括它后面的空格并开始插入;ciw -删除一个单词并开始插入;ci" -删除一个字符串内部文本并开始插入;c$ -从光标位置删除到行尾并开始插入;ct字符-从光标位置删除本行某个字符之前(保留该字符)并开始插入。等等。
C -删除光标位置到行尾的内容并进入插入模式(相当于c$)
r -修改光标所在字符,然后返回普通模式
R -进入覆盖模式
5.范围操作
某些普通模式的动作命令后面可以追加一些表示范围的指令,表示该动作将作用在整个范围上。这类命令常用的有:
d<范围> -删除一定范围内的文本
c<范围> -删除一定范围内的文本并进入插入模式
y<范围> -将范围内的文本放入0号和"号注册栏
v<范围> -选择范围内的文本
=<范围> -自动缩进范围内的文本
gU<范围> -将范围内的字符转换为大写
gu<范围> -将范围内的字符转换为小写
><范围> -将范围中的内容缩进一格
<<范围> -将范围中的内容取消缩进一格
常用的范围指令有:
空格-光标所在位置字符。(例如gU空格-将光标位置字符转为大写)
重复某些动作命令-光标所在行。(例如dd删除一行,yy复制一行,cc删除一行文本并开始插入,>>当前行缩进一格,==自动缩进当前行)
$ -从光标位置到行尾
^ -从光标位置到行首,不包含缩进空白
0 -从光标位置到行首,包含缩进空白
gg -从光标位置到文件开头
G -从光标位置到文件结尾
% -从光标位置到另一边匹配的括号
f<字符> -从光标位置到光标右边某个字符首次出现的位置,包括该字符
F<字符> -从光标位置到光标左边某个字符首次出现的位置,包括该字符
t<字符> -从光标位置到光标右边某个字符首次出现的位置,包括该字符
F<字符> -从光标位置到光标左边某个字符首次出现的位置,包括该字符
/正则表达式-从光标位置到下一个匹配正则表达式的位置(跨行)
?正则表达式-从光标位置到上一个匹配正则表达式的位置(跨行)
aw -一个单词加一个空格(a可理解为“一个”,下同)
iw -一个单词(i可理解为in,下同)
a" -一个字符串包括双引号
i" -一个字符串内部文本
a< -一组< >包含的文本,包括<
>号本身
同理类推:i<, a[, i[, a(, i(
注意:真正vim中的it范围(一对xml标签内部)在ideaVim中不生效。
用/或?命令查找时,正则表达式默认大小写敏感,如果需要不敏感,可以在正则表达式开始处加上\c标志。例如/\cabc可以匹配到ABC。下面提到的:s命令同样适用。
6.选择文本
在Vim中,选择文本需要进入“可视模式”(Visual Mode),这个名称比较奇怪,它的来由据说是因为在Vim的前身Vi中,选择区域是不可见的。在Vim中选择区域会高亮显示,因此称为“可视模式”。
v -进入字符选择模式,V -进入行选择模式,Ctrl+v -进入块选择模式。
进入相应模式后移动光标即可选中文本。过程中可按o键令光标在选区两端切换。
在块选择模式中选中多行,然后按I或A后输入文本,再退出插入模式,所输入的文本将自动加入到每一行的开头或结尾。
7.复制粘贴
在Vim模式下,复制粘贴并不直接使用系统的剪贴板,而是使用Vim提供的多个“寄存器”,每个寄存器都以一个字符来表示。关于寄存器的详细说明可以看这里http://blah.blogsome.com/2006/04/27/vim_tut_register/(随便google的一个网页),这里简单列一些常用的操作技巧(注意,vim使用双引号"来作为选择寄存器的命令,因此下文中的双引号均指在普通模式下按双引号键):
a)用y命令将文本存入寄存器后,如果想在别处替换原有内容,可以先用v命令选中原有内容,然后用p命令粘贴。但第一次粘贴后,默认的寄存器"将被替换为刚刚删除的内容。如果要再次粘贴之前复制的内容,需要使用"0p命令组合来复制。也可以进入插入模式后用Ctrl+r 0来复制,例如ciw0命令组合将用粘贴内容替换光标处的一个单词,并停留在插入模式。
b)在Windows下,寄存器+和*都代表系统剪贴板,可以互换使用,选一个顺手的即可。例如"+yy命令组合可将当前行复制到系统剪贴板。ci"*命令组合则将系统剪贴板的内容替换字符串的内部文本。
c)寄存器1至9记录之前九次的删除大段文本,每次超过一行的删除操作都会导致这9个寄存器的内容发生位移,最近删除的文本会存入寄存器1。但只有删除超过1行时才会影响寄存器1至9,行内的删除内容则会被存入寄存器-(减号)。如果用q命令录制宏时不涉及跨行删除,可以在宏中直接使用这9个寄存器来暂存文本。(在Vim中,复制内容与录制宏共享同一套寄存器,因此我习惯把字母寄存器留给宏使用)
d)普通模式下小写p把寄存器内容复制到当前位置之后,大写P把寄存器内容复制到当前位置之前。
e)使用:regs命令可以列出当前所有寄存器的内容
8.一些插入模式下的常用快捷键
Ctrl+h -删除光标左边字符
Ctrl+w -删除光标左边的单词
Ctrl+y -复制上方的一个字符
Ctrl+e -复制下方的一个字符
Ctrl+r 0 -插入前一次用y命令寄存的内容
Ctrl+r * -插入系统剪贴板的内容
Ctrl+r <寄存器名称> -插入指定寄存器的内容
Ctrl+a -插入前一次插入模式所键入的内容
Ctrl+o -执行一个普通模式下的命令然后返回插入模式。例如Ctrl+o A相当于按End键,Ctrl+o I相当于按Home键
9.退出插入模式
退出插入模式可以用ESC键,但键位太远。其实也可以用Ctrl+[键退出插入模式。当然也可以用第1点自定义的Ctrl+;快捷键,但这不是标准vim按键,会养成不良习惯,不建议使用。
10.重复操作
普通模式下按.(小数点)可重复上一次的修改操作
& -重复上一次的:s替换命令
@@ -重复上一次执行的宏
11.跳转
Ctrl+]跳转到当前标识符的定义位置(相当于在当前光标位置的单词上按住ctrl用鼠标点击)
Ctrl+o回退一步(go back)
Ctrl+i前进一步(go forward)
`.跳转到之前修改位置
``在前一次跳转位置与当前位置间切换
行号G或:行号<回车>跳转到某一行
gg跳转到文件开头
G跳转到文件末尾
H跳转到屏幕顶端(如果设置了set
so=n,则跳转到第n行)
L跳转到屏幕底端(如果设置了set
so=n,则跳转到倒数第n行)
M跳转到屏幕中间
f或F跳转到本行某个字符,小写f向右查找,大写F向左查找。用;或,在匹配间切换
t或T跳转到本行某个字符之前,小写t向右查找,大写T向左查找。用;或,在匹配间切换
/正则表达式跳转到下一个匹配。用n或N在匹配间切换。
?正则表达式跳转到上一个匹配。用n或N在匹配间切换。
(结合前面第5点,你也许注意到了,在指定范围时,使用跳转命令将指定一个从光标位置到跳转目标的区域)
这里补充一部分文章《vim的跳转与回跳》的内容:
vim的跳转
1. 标签跳转,
1.1 跳到标签xxx处
1) 移动光标到xxx处, 按 CTRL+]
2) :tag xxx
1.2. 标签跳转的回跳.
CTRL+T, 可以多次回跳
2. 普通跳转
2.1 跳转: 各种可以导致移动到当前行以外的操作.
2.2 普通跳转的回跳
2.2.1 ``  可以回跳到上一个位置. 多次按``会在两个位置间跳转.
2.2.2 CTRL+o, 向后跳.  CTRL+i 向前跳.
2.2.3 内部标记
'  或 `  上一次的位置
" 上次编辑该文件时的位置.
[ 最后一次修改的起始位置(似乎不管用)
] 最后一次修改的结束为止(似乎不管用).
2.2.4 marks
2.2.4.1 :marks  现实当前可用marks
2.2.4.2 在任意位置, 按mt, (t可以为任意字母), 就做好了一个名字为t的mark,
可用:marks查看, 也可用`t跳到此位置(t为上述的任意字符).
12书签
在普通模式下按m<小写字母>即可定义书签,按`<字母>则可跳转到某个书签的精确位置,按'<字母>可跳转到某个书签所在行的行首(用来录制宏时比较有用)。最常用的自然是mm, mn, mj, mk, ml这几个顺手的键位。
真正的vim中的全局书签m<大写字母>在目前IdeaVim版本中不生效。需要定义全局书签可以使用Idea原本的F11 +数字方式
13文本替换
使用:s/正则表达式/替换文本/可在本行内替换首次出现的匹配
使用:s/正则表达式/替换文本/g在本行内替换所有出现的匹配
使用:%s/正则表达式/替换文本/g在当前文件内替换所有出现的匹配
在可视模式下选中文本后,使用:'<,'>s/正则表达式/替换文本/g命令可在选中区域中替换文本。其中'<,'>部分在可视模式下,按:冒号后自动加入,直接输入s命令即可。但有效区域只能以行为单位。真正Vim中的\%V标志在IdeaVim中不生效。
11代码折叠
zo -打开折叠
zc -关闭折叠
14宏定义
在IdeaVim中定义宏比Idea自带的宏功能要轻量许多。按在普通模式下q<寄存器名称>即可开始把后续按键序列录制到指定寄存器中(寄存器参考前面第7条)。录制完毕进入普通模式再按q键即可停止录制。之后用@<寄存器名称>即可重放。需要注意的是宏和复制粘贴共用一套寄存器,因此在录制宏时就注意不要把当前宏正在使用的寄存器用来复制了。寄存器内容是自动保存的,重启Idea仍然生效。但IdeaVim没有导出宏独立保存的功能。因此最好把用来保存宏的寄存器和用来复制粘贴的寄存器分开,不要同一个寄存器有时用来记录宏,有时用来复制粘贴。我的习惯是键盘左手区用来保存一些长期使用的宏(比如说我有一个宏专门用来把pom.xml中的版本号抽取到property区域,原来的位置则改用${property}引用)。右手区的hjklnm键用来保存一些临时宏。yuiop五个寄存器保留用来复制粘贴。如果录制的宏不涉及删除大段代码,寄存器1至9也可以用来进行复制粘贴。
执行一次宏后,可以用@@命令重复上一次执行的宏。
在Idea中录制宏时,如果触发了代码自动完成,在自动完成列表启动的状态输入的字符不会被记录。因此最好在Setting -> Code Completion -> Autopopup code completion中把延迟设为500ms以上或干脆关掉。在录制宏的过程中避免触发代码自动完成功能。
录制一些长期有效的宏时,开始录制后,最好先用0,^,T, F, $等命令把光标对齐到行首行末或某个特定起始位置(比如说用F"跳转到字符串的左边引号),再用一个f或/指令跳转到操作位置,这样的宏就不用必须把光标放在某个特定字符才能使用了。
15.一些常用组合技
全选:ggvG
调换两个字符位置:xp
复制一行:yyp
调换两行位置:ddp
插入模式下到行尾继续输入(相当于End键):Ctrl+o A或Ctrl+[ A
插入模式下到行首继续输入(相当于Home键):Ctrl+o I或Ctrl+[ I
到类定义位置(适用于正确缩进的public,protected类):?^p回车
16.一些在目前版本已知没有实现的一些常用Vim功能
(如果对Vim不熟悉可以跳过这节)
a)let命令(没有let命令就无法导出/导入寄存器内容,也就是无法导入宏)
b):g命令(在文本处理中很有用的一个命令,在编程中倒是不那么常用)
c)!命令(执行shell命令)
d)大部分正则表达式标记(例如\%V,\v等等)
e)某些多键命令双击最后一个字符表示作用于当前行。例如在Vim中gUU可以把当前行转换为大写,在IdeaVim中无效,实现同样功能可以先用V命令选中当前行,再用gU转换为大写。
f)关于窗口操作的大部分命令(Ctrl+w系列命令, :split等)
g)所有Vim脚本插件(不过大部分可以用Idea自身的功能和插件来补偿)
嗯,差点忘了,在普通模式下按u撤销上一个修改(相当于其他IDE的Ctrl+z),按Ctrl+r重做被撤销的修改。
下面是 gif 演示 可以直接跳过
  • a在光标之后,进入插入模式
  • i在光标之前,进入插入模式
  • o在本行之后新增一行,并进入插入模式
  • A在本行结尾,进入插入模式
  • I在本行开头,进入插入模式
  • O在本行之前新增一行,并进入插入模式

练习四:jump

不得不说我们使用 vim 更多的就是为了减少鼠标操作,因为使用鼠标你的手需要离开键盘。
一来一回 麻烦!!!所以我们需要了解更多光标移动操作
  • [n]f{word}f用来查找在当前行当前光标后是否存在某个字符{word}如果存在则将光标移动过去
  • $ | ^$跳转到行尾^跳转到行首
  • %括号匹配跳转() [] {}
  • *跳转到上一个字符的定位处
  • [n]h/j/k/l数字加上方向键 代表重复运行多少次
    • 2jj 向下移动两行
    • 10l 向右移动 10 个字符
    • 3kk 向下移动 3 行
    • 20h 向左移动 20 字符
  • G | gg
    • G 移动到最后一行
    • gg 移动到第一行
  • H | M | L
    • H 移动到当前页的第一行
    • M 移动到编辑器中部
    • L 移动到当前页的最后一行
  • [n]w移动到后面 word 的开始位置,前面加上数字 代表重复多少次
  • e移动到下一个词语的末尾
  • b移动到上一个单词的开头
  • zz改变窗口的整体位置,将当前光标所在处 移动到窗口中部
下面是 gif 演示
  • [n]f{word}f用来查找在当前行当前光标后是否存在某个字符{word}如果存在则将光标移动过去。
  • 如果将这里的 f 改为 F 则是反向查找
  • $ | ^$跳转到行尾^跳转到行首
  • %括号匹配跳转() [] {}

练习五 学习一些通用场景

其他的比较好用的命令
  • zo | zc
  • dt{char}


4
配置
在安装了 Vim 之后,其实官方只是给我们了一个基本的架子,能够实现 Vim 的基本操作。如果你想要用的更加顺手,那么你需要对 Vim 进行自己的个性化配置。这是一张白纸,它会被书写成什么样子由你自己决定。
如何对 Idea 中的 Vim 模块进行配置
在右下角点击 Vim 图标,然后点击Open ~/.ideavimrc

基础配置

老规矩,个人感觉对于新手对编辑器进行配置,还是参照社区的常用配置进行使用。当自己对 Vim 更加熟练的时候可以在加入自己的东西
"语法高亮

syntax on

"显示行号

set number relativenumber

"显示光标所在位置的行号和列号

set ruler

set wrap "自动折行

set shiftwidth=4

set tabstop=4

set softtabstop=4

set expandtab "将tab替换为相应数量空格

set smartindent

set backspace=2

set co=5

"设置取消备份 禁止临时文件生成

set nobackup

set noswapfile

" 为IdeaVim插件增加自动切换为英文输入法的功能,

" idea 需要安装 IdeaVimExtension plugin

set keep-english-in-normal

"设置匹配模式 类似当输入一个左括号时会匹配相应的那个右括号

set showmatch

set clipboard^=unnamed,unnamedplus

"set laststatus=2 "命令行为两行

"set fenc=utf-8 "文件编码

"set mouse=a "启用鼠标

"set ignorecase "忽略大小写

set cursorline "突出显示当前行

"set cursorcolumn "突出显示当前列

set fdm=marker
上面当中比较特别的配置就是
  • 设置 relativenumber 这样可以看相对行号
  • keep-english-in-normal 这个设置开启之后可以在进入命令模式之后自动将输入法切换为英文。这个还是非常推荐设置的,不然每次从 插入模式 切换到 命令模式的时候 如果这个时候是中文输入法,体验就极差了
  • set clipboard^=unamed,unnamedplus共享剪切板,Vim 的剪切板和系统的剪切板是隔离的。设置之后可以共享。
Action 配置
在 Idea 中大部分的操作都可以抽象为一个 Action 比如
  • 文件重命名 Rename File
  • 重命名变量 或者 类名 RenameElement
  • 去到接口实现 GotoImplementation
  • 复制 Class 引用 CopyReference
  • ...
在 Vim 中可以通过插入命令模式 直接调用 action
上图中 gif 中演示的就是通过 调用RenameElementAction 重命名变量。
初步的介绍完Intellj Ideaaction之后,下面分享我自己目前在用的几个比较常用的配置,通过快捷键 调用action
"jk退出insert模式

inoremap jk <ESC>


let mapleader = '\<space>'

"Idea action 配置

" 重命令元素

nnoremap <Leader>re :action RenameElement<CR>

nnoremap <Leader>gi :action GotoImplementation<CR>

nnoremap <Leader>im :action ImplementMethods<CR>

nnoremap <Leader>rv :action IntroduceVariable<CR>

nnoremap <Leader>cr :action CopyReference<CR>

nnoremap <Leader>em :action ExtractMethod<CR>

nnoremap <Leader>sw :action SurroundWith<CR>
action listIntellj Idea中只是的所有的action列表
插件配置
其实本来 Vim 中的插件体系是非常强大的,但是因为我们是在Intellj Idea中使用Vim可以利用很多Intellj Idea原本的很多功能。目前我个人还没有发现有很亮眼的插件。所以如果你也正在使用 可以分享一下。


参考文献
  • B 站 vim 入门讲解:bilibili.com/video/BV1Yt411X7mu
  • 简明 VIM 练级攻略:coolshell.cn/articles/5426.html
  • learn-vim:github.com/iggredible/Learn-Vim
  • Vim 配置:ruanyifeng.com/blog/2018/09/vimrc.html
推荐阅读点击标题可跳转
继续阅读
阅读原文