Vim Habits of GM
Contents
此文献给一只猪和一头牛
影响开发效率的因素很多,有一项基本要素是编码过程中思维的连续程度。程序员开发代码往往不是线性效率,设计与实现是一件非常消耗精力的事,一般会在一个窄的时间段,思考到比较兴奋,忍不住要开始写。在这段时间内,主力思考一个小片段,然后快速实现(原型),再思考下个小片段,然后快速实现,有节奏的写写停停。被外界打断或完成最主体设计或遇到瓶颈阻塞时,会从此状态脱离。长期线性效率往往意味着长期在修修补补、瓶颈或低效率。
有节奏的写写停停,最核心的部分是设计思考,快速实现用于印证设计思考。然而快速实现往往成为我们大多数人的瓶颈:语法不熟、设计模型少、存量接口库少、英语不熟、IDE快捷键不熟、文本编辑不熟、键盘键位敲击不准等等,都非常容易打断连续的设计思考。解决上述问题的方式莫过于熟练+少而精。
作为一名vim快捷键的重度、浅度使用者,主要看中主流IDE、文本编辑器均有vim插件提供,掌握常用的vim快捷键,可以单文本内,屏蔽不同产商的快捷键设定,少而精,且容易熟练使用。
文中主要描述作者的vim快捷键使用习惯,因人而异,仅做参考。vim的熟练,一靠常用,二靠理解键位作用,顺手顺口的东西总容易成为习惯。
键盘键位
键盘上有两个键位比较特殊:F、J,上面有两个小凸点。无论手指怎么移动,哪怕是拿下鼠标,都需要快速让食指的指肚落在上面,称为归位。归位的过程一般是手指放到键盘上,然后加上少量滑动(快速输入时候,滑动敲击键盘的声音比较小)。小凸点可识别度低,键帽滑动手感不好的键盘,赶紧丢了吧,提高效率,早个月涨薪,年终奖多点儿,买个十个八个不是问题。
食指位于F、J位置后,两手大拇指轻轻搭在空格键上,不只是敲击空格比较方便而已,很多时候,食指需要离开小凸点,空格键是食指快速归位的关键。尽量避免偶有手指都离开键位。小指、无名指、中指,从左往右依次放在A、S、D,K、L、;上。
左手小指:Q、1、tab、shift、ctrl(caps lock用的较少,大写一般结合shift键)
左手无名指:W、S、Z、2
左手中指:E、D、X、3、4
左手食指:R、F、T、G、C、V、5、6
左手拇指:alt、space
右手拇指:space
右手食指:Y、U、H、J、B、N、M、7
右手中指:I、K、,、8、9
右手无名指:O、L、。、0、-、=
左手小指:;、'、[、]、\、enter、?
常用的还有esc键和delete键,小指伸比较远时比较无力,所以esc使用左手无名指,delete使用右手无名指或小指。基本思路是下方的键,手指呈抓势;上方的键,手指呈张势;上方角落的键,张势+外旋;下方角落的键,指左下,右下键不用,主要是shift和ctrl,大拇指和小指固定,三指移动。
模式切换
vim有两种模式:命令模式、插入模式。命令模式,如其名,一切操作均是命令;插入模式,普通的文本编辑模式。
插入模式->命令模式:esc键,按多少次都是命令模式,不爽就狂点吧
命令模式->插入模式:选择相对要多些,i、a、o、I、A、O
- i = insert。insert动作对于数组、链表操作时,会将当前位置的元素往后移动,即insert是当前元素之前放置新元素,如此去理解i进入插入模式,插入位置为当前字符之前
- a = append。追加到当前字符之后,比较直观,插入位置为当前字符之后
- o = open a new line。向下新起一行,进入插入模式,光标在新行(光标列位置不定,很多软件会自动调整格式)
vim模式中,大多数场景下,大写字母表现的基础能力和小写字母一致,但作用范围会更大,后续会陆续遇到。
- I,针对段落,进入插入模式,插入位置为当前行首
- A,针对段落,进入插入模式,插入位置为当前行尾
- O,向上新起一行,与o的作用方向相反
严格分类:i、a一组,在字符前后插入;I、A、O、o一组,在段落的前后上下插入。
光标移动
字符级别移动
字符是编码或写作时的最小单位,需要熟悉掌握的基础能力,至少学会字符级别的移动,文本内哪儿都能到达。
对应于方向键的上下左右,命令模式下,字符级别移动j、k、h、l。若从字母含义看,h = high,应该向上,l = low,应该向下,l = left,应该向左,j、k就更找不到解释了。
这时候的理解是,字符级别移动是非常基础的、频繁的动作,尽量放在手指正常放的位置,至少相对F、J的位置应该是不变的。所以上下左右方向键不满足条件,不同的键盘部署差异很大,且移动时,右手五指都将离开初始的位置。键盘上其他位置也没有严格的上下左右布局,那不妨将二维的上下左右降维,那便是水平的左、上、下、右,左、下、上、右或垂直的上、左、右、下,上、右、左、下。水平位置键盘上比较多,而垂直位置只有两个边。文档增长、阅读方向是往下,即向下比较常用,所以j键作为向下键,左边只有个h在管辖范围内。
j下,k上,左时食指往左偏移一个键,右时中指往右偏移一个键(无名指位置,无名指点一下)
单词内/单词间移动
单词移动是左右移动。此处的单词指连续的数字字母,或连续的符号,空格不算单词。
- b = begin。跳转到单词词首,若已在词首,向前移动一个单词
- e = end。跳转到单词词尾,若已在词首,向后移动一个单词
- w = word。向后移动一个单词,并停留在词首
begin、end可认为迭代器的首尾,是词内移动;已在首尾位置时,跳转的下一个单词,是词间移动。word可理解为正常的一个单词一个单词从前往后跳,停留单词词首,最基础最原始的诉求。
对于单词,还有另外一种场景。指代连续的数字字母符号,空格不算单词。使用大写的B、E、W进行跳转。
行内移动
- ^。正则表达式的行首,但此处跳过了行首的空格
- $。正则表达式的行尾,行位保留空格不是正常程序员该干的事儿
- 0。跳转到标准行首,不过滤空格
但是,^是个非常尴尬的命令,位置不好。所以对于^,个人倾向于g__(g+2个_)。**g_**可以跳转到行尾,但没有$单手操作来的更顺手。
块间移动
类似单词间移动,以空行分割连续的非空行为一个块,块间移动即在这些块之间移动。
- {。跳转到块首上的空行
- }。跳转到块尾下的空行
不是非常常用的移动方式,先用屏内移动命令H、M、L跳转到比较临近的位置,然后j、k快速调整。
屏内移动
光标在编辑器可见域内移动,是非常有用的功能。其又分为两类:
屏内内容不变,光标移动
- H = highest。将光标移动到编辑器可见域的最上方
- M = middle。将光标移动到编辑器可见域的中央
- L = lowest。将光标移动到编辑器可见域的最下发
用于屏内光标的快速跳转。
屏内光标所在内容不变,光标与内容一起移动
- zt = lazy to top。光标与内容一起移动到编辑器可见域的最上方
- zz = lazy, more lazy。光标与内容一起移动到编辑器可见域的中央,居中显示
- zb = lazy to bottom。光标与内容一起移动到编辑器可见域的最下方
适合查看上下文。z想到是lazy,光标想偷懒了,内容好似滚轴画一样,上下拖拖画轴,把光标拖到对应的位置。
页内移动
首尾
- gg。滚回页首
- G。跳转到页尾
翻页
- ctrl+u,up,向上翻页,半页
- ctrl+d,down,向下翻页,半页
- ctrl+b,before,向上翻页,整页
- ctrl+f,向下翻页,整页(没搞定该怎么记)
翻半页感觉挺不错,体验在代码无法一页展示时,上下翻一次可以看到更大的范围,并且有一半参考代码。但跳转后需要立即返回原有工作区,除非工作区发生切换。与翻整页不同,翻半页需要看一半熟悉一半不熟悉的代码,眼睛定位相对比较难受,多次翻半页后,容易发生错乱。
跳转指定行
大多数IDE或文本编辑器使用ctrl+g弹出行号输出框。vim模式中有两种选择:
- lineNum gg
- lineNum G
个人比较倾向于使用下面的方式,同时输入两个g是不可控的,G相对安全很多。
行内查找
行内使用单词间移动来抵达某位置,相对位置偏移较小时非常实用,与当前光标间隔很大时,更倾向于使用行内查找字符。
- f = find。行内查找,后跟需要查找的字符
- ; = next。试试想想C++中分号表示一段表达式的结束,结束之后就是下一个
行内的字符数量有限,大多数情况下,重复字符数量不会太多。移动到新行后,;命令可查号上次f查找的字符,无需再操作一遍。
页内查找/替换
页内查找有两种方式,其中一种可认为是对于频繁使用的场景进行的优化。
- 通用检索
- /+检索内容。**/**将在左下角打开命令行界面,继续输入检索内容,enter后即开始查找
- n = next。查找下一个
- N = reversed next。查找上一个
- 特化检索
- * = find word。在光标所在单词上使用,将查找光标所在的单词。n往下继续查找,N往上继续查找
- # = find word reversed。在光标所在单词上使用,将查找光标所在的单词,查找方向与*相反
特化检索只要将其中一项练熟即可,两种特化检索差异不大。
页内替换略微复杂,不推荐使用。但这不是主要原因,主要原因是:页内替换不会展示所有替换列表,且替换范围是整页,操作风险比较高。推荐使用IDE自带的重构工具,或IDE、文本编辑器带的查找/替换功能。
其他
对于大多数程序来说,vim快捷键还提供了个非常棒的功能,括号匹配。即成对的括号可以相互跳转
- %。光标置于{}、[]、()上,可通过%进行跳转切换
选择模式
在讨论复制、删除等操作之前,不得不先提一下如何选中一段内容。后续将提及的诸多操作均可以在选择模式下,结合移动操作选中一段范围,再执行后续的诸多操作。选中的内容将高亮显示。
ctrl + v,开启选择模式,初始会选中一个字符,并作为选择的起点。结合移动命令,可扩大选择范围(字符级)
V,开启选择模式,初始会选中一行,并以行为最小的复制单位。结合移动命令,可扩大选择范围(行级)
esc,退出选择模式
选中单词比较麻烦,光标可能在单词的任何位置,作者常用v+i+w,习惯就好。
复制/粘贴
复制、删除(剪切)、覆盖等行为会将复制或删除或被覆盖的内容放到剪切板。剪切板除初始无内容,其他时候,有且有一份可粘贴的内容。即一次操作,可多次粘贴,再次操作,剪切板中内容会刷新。
复制
y = yes,最基础的复制命令,复制字符,需要结合选择模式,选中所有内容将进入剪切板(字符级)
yy,直接复制一行,包括换行符(行级)
粘贴
p = paste与P是两种粘贴方式,其关系和操作位置同a与i、同o与O。
若剪切板中的内容,使用字符级操作而来,则同a与i;
若剪切板中的内容,使用行级操作(如yy/dd)而来,则同a与i;
若对一段选择模式下的内容使用粘贴,行为是覆盖。被覆盖的内容将进入剪切板。
删除
删除后直接使用粘贴,其行为是剪切。
x,形似常见的标记叉叉,删除字符,需要结合选择模式,选中所有内容被删除,且将进入剪切板(字符级)
dd,直接删除一行,包括换行符(行级)
此处很奇怪的是,删除一行居然不是xx。单独的一个d是没有效果的,需要结合其他移动命令才有意义,如d$:删除当前到行位;dj:删除当前行和下一行等等。
其他
还有个作者非常喜欢的命令J,会将下一行与当前行合并为一行。
n + 命令,此类方式作者并不是很喜欢,计算行数很容易分散注意,不如一行行选中,或一行行操作来的直接。
还有s,c等命令,作者不太善于记忆,善于逻辑顺序,多做一次i或a反而更适合。
绝大部分IDE或文本编辑工具都有vim的插件,但往往会有冲突,如ctrl + v,可用shift + insert替代。
本文只代表作者个人的使用习惯,提供参考,选择一款合适的键盘,联系并强化自己的风格才是重点。
Author 朦呆农码
LastMod 2018-06-10