内容简介:Vim 是 Linux 系统上的最著名的文本/代码编辑器,也是早年的 Vi 编辑器的加强版。一直以来,Vim 普遍被推崇为类 Vi 编辑器中最好的一个,其拥有代码补全、编译及错误跳转等诸多丰富的功能,接下来,本文将与大家分享一些 Vim 使用上的一些实用技巧,希望对技术路上的程序员们有所裨益。
Vim 是 Linux 系统上的最著名的文本/代码编辑器,也是早年的 Vi 编辑器的加强版。一直以来,Vim 普遍被推崇为类 Vi 编辑器中最好的一个,其拥有代码补全、编译及错误跳转等诸多丰富的功能,接下来,本文将与大家分享一些 Vim 使用上的一些实用技巧,希望对技术路上的 程序员 们有所裨益。
作者 | Hillel Wayne
译者 | 弯月,责编 | 屠敏
出品 | CSDN(ID:CSDNnews)
以下为译文:
我使用Vim已经8年多了,但至今仍然可以发现新的技巧。通常这算得上是一件好事。然而,在我看来,不断发现新事物也许是失败之处,因为你很难知道Vim还有哪些功能。
虽然人们经常谈论模态编辑或文本对象的美感,但我认为这并不是Vim的本质。Vim是一个拼凑而成的子系统,每一部分都塞满了各种特殊用途的工具。仅在普通模式下就有超过一百种不同的键盘输入命令。密集的功能成就了Vim的实用性。如果你想“显示与关键字匹配的所有标签”,那么只需输入“g]”,所以人人都喜欢使用这个工具。
由于这个系统很难发现新东西,我们必须依靠阅读指南来寻找。然而,有关Vim的文档并不多。入门文章的话,我们只有ciw等几篇(https://wikileaks.org/ciav7p1/cms/page_3375350.html),还有深入到子系统中的专家文章。但没有人真正谈论那些有特殊目的的技巧,所以人们只好在过去的6年中不断探索偶遇新功能。
我希望通过这篇文章向大家介绍一些Vim使用上的小技巧。这些技巧都很浅显,我鼓励你了解更多有趣的技巧。这些技巧之间没有关联性。总的来说,它们能给予你很多帮助。
组织形式
Vim的用户大致可以分为两类。第一类人是纯粹主义者,他们喜欢Vim的小巧和无处不在。在不熟悉的计算机上使用Vi(例如在ssh期间)时,他们倾向于保持最低限度的配置。另外一类人是形式主义者,他们喜欢在Vim中安装各种插件、函数以及和自定义的键盘映射,目的只是为了假装他们正在使用Emacs。如果你拿走这些形式主义者的vimrc,他们就会感到非常无助。
而我本人可能更加偏向于形式主义者。根据是否涉及向基本的Vim添加映射或设置,我可以将Vim的使用技巧分成两个部分。
纯粹主义者的Vim
我使用标准Vim帮助中的表示形式来书写模态命令,即<cr>表示按下回车键。在需要使用:h获取帮助的时候,例如:h E676,我会将帮助的字符串写到括号中。
其他普通命令
":,@:
": 是保存最后执行的命令的寄存器。可以使用":p将该寄存器的内容显示到当前缓冲区中。@:返回最后一条命令。
"=
这个是“表达式”寄存器。可以在该寄存器中输入任何vimL表达式,并使用ctrl-R等进行粘贴。例如,输入"=strftime("%c")<cr>p可以粘贴当前时间戳。
mA,'A
m{letter}在当前光标位置设置标记。之后可以用'{letter}跳转到标记所在行。小写字母的标记仅限于当前缓冲区,所以可以用它们进行导航。大写字母是全局的:如果你当前不在标记A指明的文件中,那么'A将会跳转到那个文件。利用:marks:命令可以查看设置过的所有标记。
ctrl-A和ctrl-X
增加或减少当前行内、当前光标所在位置之后的下一个数字。该命令将会跳转到数字,所以可以在任何地方使用。例如,10c-A要比wwwwwciw20容易得多。
q:
打开之前输入过的命令的历史窗口。该窗口可以像任何Vim文本窗口一样进行操作,但对其进行修改则不会被保存。但按下<CR>可以运行修改后的命令。该功能可以十分方便快捷地修改并重新运行命令,或者搜索旧命令以便重新使用。
q/,q?
与q:相同,不过打开的是搜索历史。
ctrl-I,ctrl-O
跳转到跳转列表中的下一个或上一个位置。常用于翻看一个东西后跳转回原位置。阅读帮助文件时非常有用。
宏
关于宏的进阶内容参考这篇文章(https://www.hillelwayne.com/post/vim-macro-trickz/)。
可视模式
gv
选择前一个可视范围。
v_o
跳转到可视块的另一端。当你发现可视块开始处少了一行时非常有用。在块模式下,该命令会跳转到对角位置;使用v_O可以跳转到水平方向的另一端。
g ctrl-A / ctrl-X
在可视模式下,ctrl-A仅增加每一行的第一个数字。相反,g ctrl-A会对每个匹配的行进行增一的操作。用表格解释可能更方便:
operators: v,V,c-v(:h o_v)
你肯定知道可视模式中,v是按照字符选择,V是按照行选择,ctrl-V是按照块选择。但这三个命令也可以作为移动操作符使用,按照相应的选择方式执行移动操作。例如,如果有下面的文本:
abc abc abc
如果将光标放在第一行的b上然后输入d2j,就会删除所有三行。因为j是按行移动。如果按d<c-V>2j,就可以将移动转变为块移动,从而仅删除中间的b的一列。
/regex/{n}
移动到匹配行下方的第n行,如果n是负数则向上移动。它还可以让移动变成按行移动。所以如果要删除当前位置到第一个正则匹配所在行的所有内容,可以使用d/regex//0。
ex命令
ex命令是在命令模式下输入的东西,如:s。除了替换之外,ex还有许多有用的用法。下面所有例子都需要指定范围,如%。
:g/regex/ex
仅在匹配regex的行上运行ex命令。例如,使用g/regex/d删除所有匹配regex的行。v类似于g,不过它会在所有不匹配regex的行上运行命令。
与norm和friends结合使用更强大。
:norm {Vim}
该命令可以在指定范围内的每一行运行{Vim}的命令。例如,g/regex/norm f dw会删除匹配regex的每一行的第一个空格之后的第一个词。这个方法通常比宏更简单。
norm遵循所有键盘映射。比如你在插入模式下映射jk为<esc>,那么norm I jk$diw将在行首插入一个空格,然后退出插入模式,然后删除行的最后一个词。我非常喜欢这个功能,但如果你希望不使用键盘映射,那么可以执行norm!。
:co .
将范围复制到当前行。也可以指定任意地点,如+3或'a.mv等。
:y {reg}
将范围复制到寄存器{reg}。如果{reg}是大写字母,则追加到已有的寄存器。即,如果执行
let @a = '' | %g/regex/y A
则复制整个文件中所有匹配regex的行到寄存器a。这个方法可以从文件中提取文本并复制到系统剪贴板(使用let @+ = @a)。
:windo {ex}
在所有窗口上运行ex。:windo $能将所有窗口滚动到最底部。也可以使用bufdo,cdo,tabdo等。
该命令非常适合与g、s一起使用。如果要替换所有AA为BB,但希望在每次替换前进行确认,那么可以使用vimgrep AA将所有匹配加载到quickfix中,然后使用cdo s/AA/BB来查找替换所有匹配。
形式主义者的Vim
有一些命令需要永久存储,或者需要改变Vim会话。理论上作为纯粹主义者你也可以键入这些命令,但有些命令已经超出了纯粹主义者的理想范围。
这里我只想写一些不常见的东西。比如很多人都会把H映射到^,这个我就不需要再提了。我也不需要介绍vim-sensible或vim-surround,这里只介绍更加不为人知的插件。
如果你经常修改vimrc,可以添加一个命令来做这件事:
command! Vimrc :vs $MYVIMRC
设置
我将所有的设置、键盘映射和函数都放在一个vimrc文件中。拆成多个文件后,我很难找到想找的东西。
许多设置实际上并不是Vim的“技巧”。最好去读一下vim-sensible(https://github.com/tpope/vim-sensible),里面介绍了适合vimrc的几乎所有好东西。
set lazyredrew
不要在宏的执行过程中重绘屏幕。可以让宏更快一些。
set smartcase/ignorecase
两者全启用后,搜索关键字中不含大写字母则进行不区分大小写搜索,包含大写字母则进行区分大小写搜索。
set undofile
支持永久的撤销,即使重新启动Vim也可以撤销。与undotree插件一起使用非常好。
set foldcolumn={n}
使得折叠在侧边栏中可见。n越大,以可视形式显示的折叠就越多,以数字形式显示的折叠越少。
set suffixesadd={str}
gf通常是“跳转到光标所在处的文件”,但字符串中必须包含文件扩展名。suffixesadd可以同时检查suffix指定的扩展名。例如,如果设置suffixesadd=.md,那么在字符串“foo”下按gf会查找文件foo.md。
set inccommand=nosplit
该命令仅限Neovim。inccommand能够实时显示ex命令会造成的改变。现在它仅支持s,但即使如此,这个功能也极其有用。例如,输入:s/regex会高亮显示所有匹配regex的文本。如果继续输入/change,则会显示出所有匹配替换成change的样子。该功能适用于所有曾泽表达式属性,甚至包括后向引用和分组。
set statusline (:h statusline)
设置每个窗口底部的栏中显示什么东西。与其他设置相比,这里指定的格式非常复杂详尽,要想完全解释清楚需要写一整篇文章。这里仅从技巧的角度介绍几点。首先,Vim的默认statusline为
:set statusline=%<%f\ %h%m%r%=%-14.(%l,%c%V%)\ %P
最容易替换的就是%p,它显示当前位置在文件中的百分比。statusline格式中的%{exp()}为输出exp()的结果。所以对于Markdown文件,我们可以这样写:
:set statusline=%<%f\ %h%m%r%=%-14.(%l,%c%V%)\ %{wordcount()[\"words\"]}
即可将百分比替换成文档的单词数。
还可以set tabline。如果你不使用标签页,那么可以将tabline改成“全局的statusline”。比如:
set tabline=%{strftime('%c')}
这样可以永远在顶端显示日期。
键盘映射
我设置了许多键盘映射。
Vim中许多快捷键都是无用的。s占了整个键,它的功能只不过是cl。U跟u一样,只不过它把撤销当做新的修改,从功能上来说完全没有用。Q跟gQ一样。Z仅用于ZZ和ZQ。Vim手册还推荐把_,,等绑定到自定义命令上,因为“你几乎永远不会用到它们”。然而,与节省几次击键相比,我更愿意增加全新的功能。我的一些键盘映射包括:
nnoremap Q @@
不要进入ex模式,而是重复上一次运行的宏。
nnoremap s "_d
使s(以及ss和S的相应映射)表现得像d一样,但不会将删除的文本放到寄存器中。在需要删除东西又不想搞乱匿名寄存器时很有用。
nnoremap <c-j> <c-w>j
将窗口移动到下方。还有对应于h,k,l的映射。使得移动窗口更容易。
nnoremap <leader>e :exe getline(line('.'))<cr>
将当前行当做命令执行。在试验东西时通常比q:更方便。
特殊参数(:h map-arguments)
命令 map <buffer> lhs rhs 可以让映射仅对该缓冲区生效。与自动命令结合作为临时快捷键使用非常方便,也可以在函数中定义映射时使用。缓冲区映射比全局映射优先级更高,也就是说你可以用特殊用途的命令来覆盖通用的命令。
每次使用map <expr> {lhs},{expr}都会对{expr}求值,然后用返回值作为实际的映射。一个简单的例子就是条件映射。如:
nnoremap <expr> k (v:count == 0 ? 'gk' : 'k') nnoremap <expr> j (v:count == 0 ? 'gj' : 'j')
将映射j和k为在折行内部移动,但如果设置了count,则按照正常的规则移动。这样j和k可以在很长的段落内部移动,同时不会改变10j等命令的行为。
如果要用映射来启动ex命令,那么<silent>非常方便。
inoremap
使用inoremap可以定义插入模式下的键盘映射。映射在插入模式下触发,所以inoremap ;a aaaa将输入'aaaa'而不是输入';a'。如果想进行一般模式下的动作,可以使用<c-O>。即,
inoremap ;1 <c-o>ma
那么输入;1将会在输入的地方设置'a的标记。
我喜欢使用分号作为imap的leader键,因为分号后面除了空格和换行之外几乎不会接任何其他字符。
autocmd
自动命令非常适合在配置中使用。通常写成如下形式:
augroup {name} autocmd! " Prevents duplicate autocommands au {events} {file regex} {command} augroup END
这样,一旦在匹配{file regex}的文件中发生任何{events},{command}就会执行。事件可以用:h event列出。例如,如果这样写:
augroup every autocmd! au InsertEnter * set norelativenumber au InsertLeave * set relativenumber augroup END
那么Vim仅在插入模式下禁用relativenumber。
命令au {event} <buffer> {ex}可以仅在当前缓冲区中应用自动命令。有时候我会利用该命令为某个文件添加临时的事件处理。
BufNewFile,BufRead
BufNewFile在创建新文件时触发,而BufRead在第一次打开缓冲区时触发。这两个命令通常用于给特定文件类型添加设置和映射。我用到的一个例子是
augroup md autocmd! au BufNewFile,BufRead *.md syntax keyword todo TODO au BufNewFile,BufRead *.md inoremap <buffer> ;` ```<cr><cr>```<Up><Up> augroup END
这段代码的意思是,仅对于markdown文件高亮显示TODO,在插入模式下输入;`可以添加代码符号。
自动命令还可以完成更复杂的事情。例如,给BufWriteCmd添加au可以重载标准的保存操作,从而添加自定义的逻辑。这些内容已经超出了“Vim技巧”的范围,已经属于“黑科技”了。
插件
许多人都知道vim-surround、NERDtree等流行插件。下面是一些我认为非常有用的、不那么流行的插件。
Undotree
大多数文本编辑器的撤销都是线性的。如果你做了修改A,然后将其撤销,再做修改B,那么A就永久丢失了。而Vim会保存整个撤销树。u只能撤销到当前分支的前一个状态。g-能恢复到按时间 排序 的前一个版本。用:undolist精灵可以查看所有的撤销叶节点。
但输出格式不太容易阅读。最好是能看到实际的树状结构。这就是Undotree的功能,它会为撤销树生成漂亮的ASCII表示形式,以便阅读。
vim.swap
该插件可以交换两个参数的位置,因此只需几个键即可将(a, f(b, c))改成(f(b, c), a)。我经常需要做这种编辑,所以这个插件能极大地提高我的生活水准。
Neoterm
该插件为neo/vim内嵌的终端提供了高阶API。比如,:T {text}可以将{text}发送到终端。更方便使用REPL。
" TODO {{{
还有许多东西太复杂太长了,比如编写函数,或者编写语法系统,就不在此一一介绍了。而且还有许多我不知道的东西。下面是我打算继续学习的内容:
预览,quickfix,窗口列表
有时我需要使用的 工具 用到了这些功能,但我不知道应该怎样手动操作。我希望给我的TLA+插件(https://github.com/hwayne/tla.vim/)添加quickfix的功能。我还希望在预览窗口中添加辅助信息和回调命令。这些功能很难在IDE中找到。
Neovim API
Neovim有丰富的API,可以将外部程序与Vim结合。所以可以使用 Python 脚本发送命令给Neovim实例,或者通过服务器来控制。我见过一些非常酷的概念演示,可以根据浏览器中的内容实现自动完成。看起来非常有意思!
文本对象
从来没有自己定义过。
----
不管怎样,以上是我介绍的一些不为人知的Vim功能。希望对你有所帮助!
原文:https://www.hillelwayne.com/post/intermediate-vim/
本文为 CSDN 翻译,转载请注明来源出处。
【END】
「2019以太坊技术及应用大会」门票惊喜大促!
V神携手众多海内外知名区块链专家来北京啦!自6月14日起,大会隆重推出618特惠票,低至399元,感恩新老用户,惊喜不断,虚左以待!扫码了解详情。
热 文推 荐
☞从制造业转型物联网,看博世如何破界
☞回报率850%? 这个用Python优化的比特币交易机器人简直太烧脑了...
☞老 码农 冒死揭开编程黑幕:这些Bug让我认输,谁踩谁服!
点击阅读原文,精彩继续。
你点的每个“在看”,我都认真当成了喜欢
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- CSS实用技巧
- CSS实用技巧干货
- Python实用技巧,你不知道的7个好玩的Python技巧
- Kubernetes 实用技巧: 使用 ksniff 抓包
- 你可能不知道的 npm 实用技巧
- 高性能网站实用技巧之消息队列篇
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
算法的陷阱
阿里尔•扎拉奇 (Ariel Ezrachi)、莫里斯•E. 斯图克 (Maurice E. Stucke) / 余潇 / 中信出版社 / 2018-5-1 / CNY 69.00
互联网的存在令追求物美价廉的消费者与来自世界各地的商品只有轻点几下鼠标的距离。这诚然是一个伟大的科技进步,但却也是一个发人深思的商业现象。本书中,作者扎拉奇与斯图克将引领我们对由应用程序支持的互联网商务做出更深入的检视。虽然从表面上看来,消费者确是互联网商务兴盛繁荣过程中的获益者,可精妙的算法与数据运算同样也改变了市场竞争的本质,并且这种改变也非总能带来积极意义。 首当其冲地,危机潜伏于计算......一起来看看 《算法的陷阱》 这本书的介绍吧!