高效使用vim (Efficient Editing With vim)
原英文教程见 (Original tutorial in English)
http://jmcpherson.org/editing.html
About copyright: I sent e-mail to Jonathan McPherson (author of this tutorial) to ask whether I could translate this tutorial into Chinese and post it on my web log. Jonathan supported my request. All rights of this tutorial belongs to Jonathan, if you want to redistribute or use it for other purpose, please ask Jonathan. You can find his contact information on his websitehttp://jmcpherson.org/contact.html. Thanks to JonathanMcPherson for his greate tutorial.
声明: 我给此教程作者Jonathan McPherson发送电子邮件, 询问是否可以把它翻译成中文并贴在我的web log上, 他同意了我的要求. 关于此教程, 所有的权利属于作者Jonathan, 如果你希望转载或者把此教程用于其它用途, 请与作者Jonathan联系, 你可以在他的网站找到他的联系方法http://jmcpherson.org/contact.html. 感谢作者Jonathan写了这篇精彩的教程(至少个人认为非常有用).
之于我, vi即禅. 用vi如修禅, vi命令如禅之心印. 用者不可窥其堂奥, 门外汉视其晦涩如天书. 常用之, 实可知其道. --reddy@lion.austin.com
(译注: 以上为作者引文, 本人未知reddy何许人也)
此教程假设读者具备vim的基础知识, 明白什么叫插入模式(insert mode), 命令模式(command mode), 载入保存文件等等. 教程的目的是帮助新手们学习vi技巧, 更高效的用vi. (译注: 原作者在教程中大部分时候混用vi和vim两个名字, 本人未做更动)
在此教程中, <C-X>表示Ctrl-X – 就是按住Ctrl键然后按X. 命令模式下, 你可以在vim中输入:help command获得大部分命令的帮助, command是你需要看帮助的命令. (译注: 比如你想知道x命令的用法, 就输入:help x, 看完了帮助如果不知道怎么回到原来的编辑界面, 可以输入:bd命令, bd的意思是buffer delete, 关于buffer的相关描述请参看相关的vim帮助, 了解buffer也是vim用户必须要干的)
高效移动
珍爱生命, 远离插入模式
一般情况下, 你应该尽量少把时间花在插入模式, 因为在这种模式下vi和其它sb编辑器区别不大. 这也是大部分vim新手把大部分时间花在插入模式的原因 – 插入模式很易用. 但是vim真正的优势在命令模式. 你会发现越了解vim, 你花在插入模式的时间越少.
使用h,j,k, l
高效率用vim编辑的第一步是绝了你用方向键(上下左右)的念头. vim设计出”模式”操作方式的一大优势就是可以让你不需要老是把手从方向键和字母键之间移来移去. 当你在命令模式下, 用字母h, j, k, l对应方向左, 下, 上, 右. 这个需要练习一下才能习惯, 但是你会发现一旦你习惯了它们, 比用方向键快多了. (译注: 这几个移动键一定要动手试, 然后反复用, 靠记忆忒艰难了)
在你编辑电子邮件或其他段落式文本的时候, 你可能注意到移动方向跳的行数比你料想的多. 这是因为你的段落对vim来说在很长的同一个行里. 用h, j, k, l移动前输入g可以让移动相对于屏幕看上去的行数而不是vim内部的行数.
用motion在当前行移动 (译注: 没想到特别合适的词翻译motion, 可以理解为”高级移动”, 另请注意, motion仅在当前行移动)
大部分编辑器只有简单的光标移动功能(上下左右, 行首行尾等等). vim有非常高级的光标移动命令, 这些命令叫做Motion. 当用motion把光标从文本中的一个点移动到另一个点的时候, 两点间的文本(包括两个点本身)被motion”掠过”. (这个概念在接下来的教程中非常重要.) (译注: 举例说明一下”掠过”概念, 比如你有一行文本, 内容是abcdefg, 当前光标在c上, 如果你用motion $, 光标移动到了g上, 那么从c到g这段文本就被motion $”掠过”了).
以下是一些有用的motion:
fx | 在当前行向前移动光标到下一个字符x (很明显, x可以是任意你想要移动到的字符). 这是一个超级有用的命令. 你可以输入;来重复前一个f命令. |
tx | 和上面的命令基本相同, 除了移动光标到字符x之前而不是x字符本身. (这个真的很有用) |
Fx | 在当前行向后移动光标到上一个字符x. |
w | 将光标向前移动一个词. |
b | 将光标向后移动一个词. |
0 | 将光标移动到当前行首. |
^ | 将光标移动到当前行的第一个字符. (译注: 第一个字符可能不是行首, 比如行首有space, tab等不可见符号, 0会把光标停在这些符号之前, 而^会把光标停在这些符号之后的第一个可见字符.) |
$ | 将光标移动到当前行尾. |
) | 将光标移动到下一个句子. (写电子邮件或者文本文档的时候很有用.) |
( | 将光标移动到上一个句子. |
在文件中高效移动
vim有很多命令可以让你在文件中任意移动光标 – 很少需要手工一页一页滚动. 以下按键技术上说不算motion, 因为它们是在文件中移动, 而不是在某一特定的行.
<C-F> | 将光标向前(下)移动一页(屏幕). |
<C-B> | 将光标向后(上)移动一页. |
G | 移动到文件尾 |
numG | 将光标移动到某一行. (例如, 10G是把光标移动到第10行.) |
gg | 将光标移动到文件开头 |
H | 将光标移动到当前页的第一行. |
M | 将光标移动到当前页的中间一行. |
L | 将光标移动到当前页的最后一行. (译注: 有了HML3个命令, 可以把鼠标撇了, 爽) |
* | 读取光标下的字串, 然后移动到当前文件中下一次出现该字串的位置. (比如说如果你的光标所在的位置的字串为"bob,", 按了*之后, 光标将移动文件中下一个"bob"出现的位置.) |
# | 和*命令基本相同, 除了它移动到上一次出现字串的位置. |
/text | 从当前光标位置开始, 查找下一个含有text的字串并且移动到那里. 需要按回车(Enter)键来执行查找. 如果要重复执行查找, 输入n(n代表next occurance). (译注: text指你想搜索的字串, 比如你要在文件查找字串"abc", 就输入/abc然后回车) |
?text | 和/text相似, 区别是?text进行反向查找(查找上一个字串). |
ma | 给当前光标所在位置设置一个名字为a的书签. 书签的名字可以是任何小写字母. 你看不到书签, 但它确实在. |
`a | 移动光标到书签a. 注意`不是单引号, 大部分键盘上它在数字1的左面. (译注: 本人使用的vim 7.1 windows版本用单引号也能完成同样功能) |
`. | 移动到你之前编辑过的行. 这个又是"真有用". 如果你需要在文件中"滚来滚去"查看一些东西, 你可以用这个命令回到你之前编辑的行尽管你没把它设成书签. |
高效输入
使用关键字自动完成(补全)
vim 有个非常好的关键字自动完成系统. 就是说你可以只输入很长的词的一部分, 按一个键, vim帮你把这个词自动补全. 比如说在你的代码中有一个变量叫iAmALongAndAwkwardVarName, 你可能不愿意每次用这个变量都把整个词打一遍, 这时候就可以用自动完成功能.
要使用关键字自动完成, 只要输入一个字串的前几个字母 (比如 iAmAL) 然后按 <C-N> (按住Ctrl然后按N>)或者<C-P>. 如果vim没有选择你需要的字串, 继续按<C-N>或<C-P> – vim会遍历所有和你输入的前几个字母匹配的字串.
用点脑子开始插入模式
大部分新用户输入i来进入插入模式. 这种方法有时候相当低效, vi有一堆可以高效进入插入模式的命令. 这里是最常用的一些:
i | 在当前字符的左侧开始插入. |
I | 在当前行行首开始插入. |
a | 在当前字符的右侧开始插入. |
A | 在当前行行尾开始插入. |
o | 在当前行的下一行开始新的一行并在那插入. (译注, 写code用这个很爽) |
O | 在当前行的上一行开始新的一行并在那插入. |
c{motion} | 删除(change)motion"掠过"的文本然后插入新文本代替它. 比如说, c$会删除当前光标位置到当前行尾的文本并开始插入模式. ct!会删除当前光标位置到下一个!出现位置(不包括!本身)之间的文本并进入插入模式. 删除的文本会被复制到剪切板可以被粘贴使用. (译注: 可以到前面复习一下"掠过"的概念, 参考例子. 输入c{motion}命令的时候, 不需要输入花括号) |
d{motion} | 删除motion"掠过"的文本 -- 和c{motion}相似, 但是不进入插入模式. |
高效移动成块的的文本
用可视化选择, 用合适的选中模式
和最早的vi不同, vim可以让你把文本置为高亮然后对高亮的文本操作. 以下是主要的3个可视化选中模式 (即文本高亮模式).
v | 字符选中模式. 大部分人习惯用这个, 所以玩其他模式之前先把这个练熟. |
V | 行选中模式. 选中整行. 当你需要复制或移动几行的时候, 这个比字符选中模式要好. |
<C-V> | 块选中模式. 超级nb而且很少有其他的编辑器支持(译注: 还是有一些支持的, 比如ultraedit, 但是得付钱...). 你可以在任何文本中选择一个矩形块来操作. (译注: 在windows版本的vim中<C-V>默认被映射为粘贴, 可以通过更改键盘映射或者使用<C-Q>来进行块操作) |
在可视化选中模式下进行剪切和复制
一旦你有了高亮选择, 你可能想要干点啥. 以下是对选中的高亮文本最有用的命令:
d | 剪切(删除)高亮选中的文本到剪切板. (译注: 据本人所知, vim所有的删除其实都是剪切) |
y | 复制 (或者说"拽"(yank), vim用"拽"来表示复制...)高亮选中的文本到剪切板. |
c | 剪切高亮选中的文本到剪切板. 和d很相似, 只是c会进入插入模式. |
在非可视化选择模式进行剪切和复制
如果你确知你想要复制或者剪切什么, 你可以不进入可视化选择模式就完成这些操作. 这样速度更快.
d{motion} | 把由motion"掠过"的文本剪切到剪切板. 比如dw把当前光标开始的一个词剪切到剪切板, 而dfS把从当前行从光标是到下一个S之间的文本剪切到剪切板. |
y{motion} | 把motion"掠过"的文本复制到剪切板. |
c{motion} | 把motion"掠过"的文本剪切到剪切板并且进入插入模式. |
dd | 剪切当前行到剪切板. |
yy | 复制当前行到剪切板. |
cc | 剪切当前行到剪切板并且进入插入模式. |
D | 剪切光标当前位置到行尾的文本到剪切板. |
Y | 复制整行到剪切板, 和yy相似. (yes, 这个命令和命令D的操作方式没保持一致, 你可以用y$完成类似D的操作) |
C | 剪切光标当前位置到行尾的文本到剪切板并进入插入模式. |
x | 剪切当前字符. (类似于命令模式的退格(backspace)键) |
s | 剪切当前字符并进入插入模式. |
粘贴
粘贴很简单. 把光标移动到你想要粘贴的位置输入p. (译注: 粘贴操作需要在命令模式下, 另外P(大写)命令把剪切板的内容粘贴到光标当前位置之前, 对用惯其它编辑器的人来说, P命令可能更符合习惯)
使用多个剪切板
大部分编辑器只有一个剪切板. (译注: 貌似不算太'大部分') vim有多个. 在vim里剪切板叫做寄存器(regiseter). 你可以输入:reg列出所有当前定义过的寄存器和它们的内容. 大多数情况下你会使用以小写字母命名寄存器, 其他的有各自不同的vim内部用途, 偶尔可能会有用.
要使用指定的某个寄存器来完成复制和粘贴, 很简单, 在复制粘贴操作之前输入”a, a表示你希望用的寄存器.
举个例子, 复制当前行到寄存器k, 输入”kyy. (也可以用V”ky. 想想为啥这个也成). 那一行就会被存放在寄存器k里, 直到有其他的东西被复制到到寄存器k覆盖它. 复制之后可以用”kp来把寄存器k里存放的内容粘贴到到文本中.
不干机械劳动
给你惊喜的.命令
在vi中, 输入.(英文的句号)可以重复上一个你执行过的命令. 比如你上一个命令是dw, 当你输入.命令, vi会删除下一个词.
使用计数器执行重复操作
计数器是vim最nb的提速功能. 任何命令之前都可以加一个数. 这个数告诉vim你想把命令执行多少次. 例如:
3j会把光标向下移动3行.
10dd会删除10行文本.
y3”在当前行, 把光标当前位置到第三个双引号之间的文本复制到剪切板. 这种计数器用法可以大大扩展motion的操作范围. (译注: 本人认为y3”不能完成这样的功能, 对应的命令应该是y3f”, 可能原作者漏写了f命令, 有空的时候问问原作者)
录制宏
你可能偶然会发现你对一个文档中的某块文本反反复复的进行相同的操作. vim可以录制一个特定的宏来完成这些操作.
qregister | 开始录制一个宏并保存在某个有名字的寄存器. 比如qa开始录制一个宏并把这个宏存放在寄存器a中. |
q | 结束录制 |
@register | 回放存放在某个寄存器的宏. 比如@a播放寄存器a中的宏. |
用vim写程序代码
vim是优秀的源代码编辑器, 有很多的功能是专门为写程序设计的. 这里是一些常用的:
]p | 和p相似, 但是它可以自动调整粘贴的代码和已有的代码缩进. 试试吧. |
% | 把光标放在某个花括号{}, 中括号[]或者圆括号()上, 按%会把光标移动到与之对应的花括号, 中括号或者圆括号上. 对于修正多层嵌套逻辑代码块的括号解析问题来说, 这个功能堪称救人于水火之中. |
>> | 缩进高亮选中的代码. (对高亮选中请查看前面章节, 如果没有文本被高亮选中, 则将当前行缩进) |
<< | 和>>类似, 但是反方向(译注: 缩进是向右移动行, 反方向既向左移动). |
gd | 把光标移动到当前光标所在位置的函数或者变量的定义(definition)(或声明(declaration)). |
K | 打开当前光标所在词对应的手册页(man page). (比如你的光标当前在sleep这个词上, vim会显示sleep的手册页) (译注: 这个功能貌似只对vim的原生OS--unix上有用) |
(译注: 结合ctags, cscope之类的辅助工具, vim可以提供更强大的程序代码编写功能)