你大概都不知道vim是什么。何来谈它是不是难用?
vim,是一种编辑器的编辑模式。
visual studio code在编辑器模式领域的第一插件,是vim。
idea在编辑器模式领域的第一插件,也是vim
Android studio也如是。
eclipse也同上。
几乎所有排名前列的主流IDE,他们的编辑器模式排名第一的插件,都是vim。
也就是说。学习了vim的操作。将来无论你用哪个ide,无论你用哪个终端,无论你用何种环境,都可以使用一套统一的编辑模式与命令操作。
对程序员来说,掌握vim编辑模式,简直算是一本万利,性价比最高的知识了。
至于一款独立的vim,它是什么?
嗯,好问题,我们可以把它当作一款实现了vim编辑模式,并且支持插件系统可自定义扩展的高级记事本。
为什么要使用独立的vim应用?因为我们不光在ide编程的时候要使用vim编辑模式,在用记事本的时候也想要使用vim编辑模式。——甚至,在命令行终端也想要使用vim模式(bash、zsh支持vim编辑模式)。
因为学习使用 vim 有三个阶段:
首先是孩童时期,刚刚开始接触 Vim,觉得非常别扭,这里也不顺畅,那里也不够高效,表现为在知乎上问,“Vim 到底好在哪里?”,或者“学完 vimtutor 以后该干嘛?”
接下来是青春期,感受到 Vim 的爽点,开始欣喜若狂的探索 Vim 的边界,表现为疯狂的尝试各种 mapping 和插件,阅读网上一切关于 Vim 的文章和内容,尝试一切可能的事情。
最后进入成熟期,开始移除所有无用的东西,真正变得高效起来。表现为开始冷静思考自己的工作流程,逐步针对性定制 vim ,让 vim 越来越顺手。
--
只有对编辑器足够挑剔的人,才会使用 Vim。真要尝试,你要先问问自己是不是对编辑器有很高的要求,是不是对身边的编辑器都有不满意的地方,还是只是好奇,并不希望投入多少时间:
当你真的决定入坑了,那么主要问题就是怎么完成第一个阶段到第二个阶段的切换呢。
我的建议是,开始迭代你的 vimrc 配置,先要花 20 分钟把 vimtutor 过一遍,这个是必须的。然后 github/gitlab 上面建立个项目里面只有一个 init.vim,然后编辑你的 vimrc,里面就一句话:
source /path/to/init.vim
然后用刚刚学完的 vimtutor 的知识,开始用 vim 去编辑并迭代你的 init.vim。用 vim 是一个积累的过程,把你的配置托管到 git,然后一边学习网上的相关教程,一边逐步迭代你的配置,才能让你的 Vim 变得越来越顺手。
在这个阶段,不用把你的正式工作切换过来,原来用啥编辑器工作,继续用着那个编辑器,只是迭代 init.vim 的时候坚持用 vim 编辑就行,因为这时候切换过来,你只会充满挫折的离开。而你坚持用 vim 编辑和迭代 init.vim 的话,一方面可以巩固之前学习的 vim 键位,一方面可以把你最新学习到的内容加以练习和实践,每次更改了 init.vim 只需要命令行:
:so %
就能重新 source 当前文件了。
--
期间你可能会充满疑问,到底该不该用鼠标?平时大部分时候是在 INSERT 模式下面还是 NORMAL 模式下面?标准答案是平时干任何事情,最后都要复位到 NORMAL 状态,编程就像画画,大部分时候不是在输入新字符,而是在“合成/编辑”旧文本,因此 NORMAL 状态是一切状态结束后,不知道做啥时就先回归 normal 状态。
不过不用强迫自己,都有一个习惯过程,我才学习 Vim 时,一进去就 i 进入 INSERT 模式,靠上下左右来控制光标,当成 nano 再用,最后才 esc :wq 的。似乎不少人也是这样开始的,这样做是完全 OK 的,不要听某些老鸟说什么禁用方向键,学习的过程最开始都是先用新壶装旧水,习惯了,再逐步尝试新壶装新水。
刚开始就是要不管什么方法,先把原来可以做的事情,在 Vim 里找到一个方式去做,然后再逐步迭代,假设我当年一开始听别人的话把方向键禁止了,我估计我都用不下去。
同理,鼠标也一样,该用就用,我鼓励你在 Vim 里用鼠标,用上下左右,比如你装了个 NERDTree,就用鼠标去点,没有任何问题。等你熟练了自然会尝试键盘操作,等你更熟练了或许你直接把 NERDTree 给卸载了换更好的方法。
那么经过这样的迭代,你会逐步感觉到编辑 init.vim 也不那么费力了,似乎还挺顺手的,这时候就是将原有工作逐步切换到 Vim 的时间点了,恭喜你进入青春期。
--
当你真正进入成熟期后,你的收获会是两个方面的,除了熟练掌握 vim keymapping 外,更重要的是轻而易举定制 Vim 的能力,让他变成自己想要的样子,随着时间的增长,你不断发现工作中存在不够高效的地方,然后琢磨用更高效的方式代替,或者是一种新的用法,或用 VimScript 给 Vim 增添一条新命令,然后反复迭代,不用投入太多时间,但是每隔一段时间你都能变得比之前更高效一点,同时再也看不上其他编辑器了。
他编辑器,大部分用熟练了以后,效率基本就固化锁定下来了,我用 Vim 很多年,到现在我都在不断的反思和优化我的工作流,学习新的用法,能感受到持续数年的逐步效率提升,这种能持续很多年渐进式提升的感觉在其他编辑器里是找不到的。
我右手大拇指有腱鞘炎。
鼠标拖动对我来说非常痛苦。
因此上我习惯于用y命令复制代码。之后粘贴到其他地方。
VIM这个东西,看怎么用。如果你连接到远程的高延迟服务器,那简直就是找死。
如果你是连接到公司内部,每天搬砖,确实熟能生巧。
如果你是生手,或者搞新东西,需要经常摸索调试的,我觉得你用VIM是精神有问题。
总结:公司内部搬砖或者调试远程服务器用的。
2022-02-24 1:23 , 我是大概在 21 年 7,8 月份的时候强制自己使用 Vim 的,回答这个问题的时候是 2021 年10 月,回答了这个问题后的4 个月里面,现在 我的 VSCode Sumlime 等工具都已经切换到正常模式了,主要还是我感觉在 VSCode 里面 Vim 支持没有 Jetbrains 里面好。然后 整理了大家在评论区提到的在学习 Vim 过程会遇到的问题。因为个人感觉 VIm 想要入门是最难的,很多的同学想学,但是总是会被各种问题阻碍住,比如 Esc 键问题,中英文切换问题,复制问题,快捷键冲突问题,有的时候还没开始就已经结束了。常见问题及解决方案放在文章的最后。
Vim
是一个高度可配置的文本编辑器,旨在高效地创建和更改任何类型的文本。 它作为“vi
”包含在大多数 UNIX
系统和 Apple OS X
中。
Vim 非常稳定,并且正在不断开发以变得更好。
它的特点包括:
为什么要在 Intellj Idea
中使用 Vim
?
在我们学习某一项新技能,或者新的编程语言,新的编程模式。
我们应该自问让我们做出这样的行为的驱动力是什么?
学习完它之后它能解决你什么样的疼点问题。这样我们学习起来会更有动力一些。
让我尝试学习 Vim
的理由
Mac
平台下 Intellj Idea
的很多的常用的 action
都是需要 command + option
这个组合键,从我转到 Mac
下,就一直很懊恼,个人感觉这个按键很反人类。linux
服务器上去修改服务器的系统配置文件。比如 nginx
配置,这个时候不可避免的需要使用到 vim
编辑器。如果你不熟练 操作起来还是相当的难受的。Intellj Idea
中安装了 vim
插件之后。是一个互补的状态 利用各自的优势 使得编程更有效率。
在 Intellj Idea
中 安装以下三个插件
IdeaVim
IdeaVim-EasyMotion
IdeaVimExtension
发现图标像上面一样编程一个小方块的时候 就代表插件安装成功
不得不说 vim
的学习成本还是有的,典型的入门很难 入门之后就会爱不释手。
我这里对一些基础操作进行一些简单的总结和整理。
根据我自己的经验总结下来从原生编辑器过度到 Vim
最不习惯的当属方向键的移动从原本的 方向键变成了 hjkl
这个其实没有太多好说的 就是需要克服这一关。多练就行。(下图为 Gif 演示)
CV
大法好,毕竟大家有时候自嘲都是 C V
工程师 所以 复制 粘贴 还是需要在第一时间学会,这样才能更好的 coding
yy
复制当前行p
粘贴
练习三:在学多一点点
在学习一些其他的命令 提交效率。
gif 中步骤如下
yy
复制当前行 private String username;
p
将复制的内容进行粘贴f;
跳转到字符 ;
处,这里其实就是相当于行位。h
向左移动一个光标ciw
删除当前处的词,并进入 插入模式
password
输入 password 完成
gif 中步骤如下
V
进入内容选择模式kkk
向上移动 3 行,并进行选中d
删除选中部分
块级删除「常用」di* da*
di"
删除"
内的内容,个人感觉这个还是非常常用了。也是初步在效率上优于传统的 intellj idea 的操作方式。如果想要删除之后马上进入插入模式 可以使用 ci"
di(
删除(
内的内容,如果想要删除之后马上进入插入模式 可以使用 ci(
di{
删除{
内的内容,如果想要删除之后马上进入插入模式 可以使用 ci{
各种进入插入模式
i
在光标之前,进入插入模式I
在本行开头,进入插入模式a
在光标之后,进入插入模式A
在本行结尾,进入插入模式o
在本行之后新增一行,并进入插入模式O
在本行之前新增一行,并进入插入模式s
删除当前字符,并进入插入模式S
删除当前行中的所有文本,并进入插入模式
在我最开始的学习 vim 的时候只知道 i
进入插入模式。后面才知道还有这么多种方式。
如果你真的是切换过来之后 这里所有的方式都能用到。
下面是 gif 演示 可以直接跳过
a
在光标之后,进入插入模式i
在光标之前,进入插入模式o
在本行之后新增一行,并进入插入模式A
在本行结尾,进入插入模式I
在本行开头,进入插入模式O
在本行之前新增一行,并进入插入模式
练习四:jump
不得不说我们使用 vim 更多的就是为了减少鼠标操作,因为使用鼠标你的手需要离开键盘。
一来一回 麻烦!!!所以我们需要了解更多光标移动操作
[n]f{word}
f
用来查找在当前行 当前光标后是否存在某个字符 {word}
如果存在则将光标移动过去$ | ^
$
跳转到行尾 ^
跳转到行首%
括号匹配跳转 () [] {}
*
跳转到上一个字符的定位处[n]h/j/k/l
数字加上方向键 代表重复运行多少次 G | gg
H | M | L
[n]w
移动到后面 word 的开始位置,前面加上数字 代表重复多少次e
移动到下一个词语的末尾b
移动到上一个单词的开头zz
改变窗口的整体位置,将当前光标所在处 移动到窗口中部
下面是 gif 演示
[n]f{word}
f
用来查找在当前行 当前光标后是否存在某个字符 {word}
如果存在则将光标移动过去。$ | ^
$
跳转到行尾 ^
跳转到行首%
括号匹配跳转 () [] {}
zo | zc
dt{char}
在安装了 Vim 之后,其实官方只是给我们了一个基本的架子,能够实现 Vim 的基本操作。如果你想要用的更加顺手,那么你需要对 Vim 进行自己的个性化配置。
这是一张白纸,它会被书写成什么样子由你自己决定。
如何对 Idea 中的 Vim 模块进行配置
在右下角点击 Vim 图标,然后点击 Open ~/.ideavimrc
基础配置
"语法高亮 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
在 Idea 中大部分的操作都可以抽象为一个 Action 比如
在 Vim 中可以通过插入命令模式 直接调用 action
上图中 gif 中演示的就是通过 调用 RenameElement
Action 重命名变量。
初步的介绍完 Intellj Idea
的 action
之后,下面分享我自己目前在用的几个比较常用的配置,通过快捷键 调用 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 list Intellj Idea
中只是的所有的 action
列表
插件配置
其实本来 Vim 中的插件体系是非常强大的,但是因为我们是在 Intellj Idea
中使用 Vim
可以利用很多 Intellj Idea
原本的很多功能。目前我个人还没有发现有很亮眼的插件。所以如果你也正在使用 可以分享一下。
其他
先不说 Vim 好不好用,因为我发现大部分人在还没有学会的时候 就因为各种问题 放弃了。
在你在学习 Vim 的路途中一定会遇到一些问题,如果你没有解决,那么可能还没学会就放弃了。
这也是为什么很多大佬说 Vim 其实入门是最难的。这里我先把我自己学习过程中遇到的问题整体梳理了一遍。
第一个问题就是 Esc 可太远了。
因为 Vim 从编辑模式到插入模式需要通过 Esc 键进行切换,但是 Esc 键说实话太远了,毕竟其实每次从编辑模式到命令模式都需要退出的,所以 Esc 键是非常常用的键,所以 Esc 一直放在左上角肯定不行,这样下去手肯定都废了。
在 Vim 中我们可以设置键位映射,怎么理解,就是可以将键盘上的某个按键与Vim的命令绑定起来。例如使用以下命令,可以通过F5键将单词用花括号括起来:
:map <F5> i{ea}<Esc>
因为有这种映射方案,所以我们就可以选择将一些不常用的按键替换为 Esc键,社区里面使用的比较多的是使用 jk 键 替换掉 Esc,我自己试用过,我感觉还是很不错的.
还有一种方案就是将 CAPSLOCK 替换为 Esc ,我目前就是使用这种方案,感觉还不错。Mac 下直接就可以系统修改按键了,Windows 则需要借助一些外部工具,我知道的有 AutoHotKey.
这个问题最开始我是不知道的,根本不知道还有这种问题,因为这个问题我自己一度想要放弃使用中 Vim ,主要是真的非常麻烦
有的时候我们在书写完注释后,需要切换到下一个地方编码,然后就会发现 人傻了,直接弹出输入法。
还有一个场景就是我可以刚好之前是在使用 企业微信 和产品各自问候家人
然后回到编辑器写代码,发现没反应直接弹出输入法,还是比较烦人的。
好在社区也有解决方案,
im-select 从终端切换输入法。该项目是对 VSCodeVim 的基本支持。它为 VSCodeVim 的 autoSwitchIM 功能提供命令行程序
里面针对 Window,Linux,Mac Inter | M1 都有对应的方案
AppCode | CLion | DataGrip | DataSpell | Fleet | GoLand | IntelliJ IDEA | PhpStorm | PyCharm | Rider | RubyMine | WebStorm
Jetbrains 的方案更加简单一点,只需要两步操作就可以完美解决
" 为IdeaVim插件增加自动切换为英文输入法的功能, " idea 需要安装 IdeaVimExtension plugin set keep-english-in-normal
这样就可以解决这个问题了
上面的两个问题解决了,你会发现你又会遇到一个新的问题,那就是 Vim 的剪切板和 电脑的剪切板不是互通的,当时也是一度让我想放弃。觉得这是什么垃圾玩意,太难用了吧。哈哈哈哈哈
解决方案
Jetbrains 加入以下配置文件,在 .ideavimrc 中加入以下配置
set clipboard^=unnamed,unnamedplus
VSCode
在 设置页面 选择 Vim Configuration 找到 Vim: Use System Clipboard 勾选一下
这位同学提到的这个算事一个小问题,不过问题虽小,如果你不知道解决方案也是很头痛的,因为本来我们用 Vim 其实也是和 Idea 编辑器的功能互相结合,利用各自的优势来更加高效的完成任务。
如果因为用了 Vim 而不能使用 IDE 中其他非常好的功能,那属实 路走窄了 The road is narrow
JetBrains 系列 IDE 处理快捷键冲突
进入 设置 -> Editor -> Vim
这里就列举出了 IDE 中常见的快捷键和你想要让他使用 IDE 的功能,还是 Vim 的功能。像实现接口,重写父类方法,最近文件,延展光标 这些肯定还是需要用原生 IDE 的 好一些。
VSCode 配置键位映射
{ "vim.easymotion": true, "vim.incsearch": true, "vim.useSystemClipboard": true, "vim.useCtrlKeys": true, "vim.hlsearch": true, "vim.insertModeKeyBindings": [ { "before": ["j", "j"], "after": ["<Esc>"] } ], "vim.normalModeKeyBindingsNonRecursive": [ { "before": ["<leader>", "d"], "after": ["d", "d"] }, { "before": ["<C-n>"], "commands": [":nohl"] } ], "vim.leader": "<space>", "vim.handleKeys": { "<C-a>": false, "<C-f>": false } }