这篇 Vim 技巧文章,包含了一些我觉得比较有意思的从中级到高级的 Vim 技巧,让我们一起来回顾一下。
在 Vim 中有 3 种命令行模式:
- :something
- /something
进入):
- C-r>=
- =1+1<cr>
假如我们通过以下命令在 Ex 命令模式里运行规范文件:
- :!rspec spec/models/code_spec.rb
1 |
:!rspec spec/models/code_spec.rb |
我们可以在普通模式里输入
来重复上一次 Ex 命令。
- @:
如果我们想对 CSS 选择器里面的属性行按照字母顺序排序,我们只需要在可视化模式里选择这些属性行并且输入
,然后就可以看到排序后的结果。
- :sort
- h4 {
- font-size: 11px;
- margin: 15px;
- background: red;
- }
1 2 3 4 5 |
h4 { font-size: 11px; margin: 15px; background: red; } |
我们可以通过使用
来选择上一次选择复制的文本。并且,可以使用
- gv
来选择上一次粘贴的文本,
- gv
是一个我们已经添加到 vimrc 文件里的自定义映射。当我们进行方法重构、剪切 - 复制然后进行缩进对齐时,这些命令尤为好用。有了
- gb
命令,我们可以很容易地选中刚粘贴的文本,然后使用
- gb
或者
- <
来修正缩进。
- >
- " select last paste in visual mode
- nnoremap <expr> gb '`[' . strpart(getregtype(), 0, 1) . '`]'
1 2 |
" select last paste in visual mode nnoremap <expr> gb '`[' . strpart(getregtype(), 0, 1) . '`]' |
假设我们现在处于插入模式并且想在不离开插入模式的情况下粘贴文本,我们可以使用
命令。如果复制的文本里包括换行符,
- <C-r>0
命令可以帮我们处理缩进问题。
- <C-r><C-p>0
当我们处于 Vim 的插入模式、命令行模式或者 Shell 的命令行,我们可以使用以下快捷键来删除一个字符、单词或者一行:
- <C-h>
- " 向前删除一个字符(类似退格键)
- <C-w>
- " 向前删除一个单词
- <C-u>
- " 删除至行首
- <C-k>
- " 删除至行尾
1 2 3 4 |
<C-h> " 向前删除一个字符(类似退格键) <C-w> " 向前删除一个单词 <C-u> " 删除至行首 <C-k> " 删除至行尾 |
假设我们忘了给以下的 Javascript 代码行的行尾添加
:
- ;
- var element = $(this)
- var tabName = element.data('tab')
- var report = element.data('report')
1 2 3 |
var element = $(this) var tabName = element.data('tab') var report = element.data('report') |
要给每一行添加分号,我们可以在可视化模式里选中这 3 行代码,然后运行
命令。Vim 会在选中的每一行中执行
- :normal A;
命令(添加
- A;
的命令)。我们也可以使用另外一种方式,我们可以对整个文件的内容使用
- ;
命令。
- :%normal A;
在上面的代码片段中,如果我们只在第一行上面使用
命令向行尾添加
- A;
。我们可以选择 2 到 3 行的代码并且运行
- ;
命令,为选中的每一行执行点号命令(dotcommand)重复上一次修改命令。
- :'<,'> normal .
在 Vim 中,对多个文件执行替换操作并不是一个直观的操作。要在多个文件里进行搜索和替换,首先我们需要创建一个文件列表,之后在这些文件里面执行命令。我们可以使用
命令来创建文件列表。例如,加载所有以 "ext" 开头的 Javascript 文件:
- :args
- :args app/assets/javascripts/ext*.js
1 |
:args app/assets/javascripts/ext*.js |
我们可以通过
命令来查看有哪些文件被加载到参数列表中。当文件都加载到参数列表中后,我们可以运行搜索和替换命令:
- :args
1 |
:argdo %s/From/To/g |
一旦修改应用到文件后,我们可以通过以下命令来更新参数列表中的文件:
1 |
:argdo update |
当我们知道要执行替换命令的文件在那的情况下,之前的替换技巧会很有用。但是,在大多数情况下,我们想要的是,在一堆文件里搜索文本并且仅在匹配的文件里执行替换命令。要实现这个替换操作,我们可以使用
命令在文件中搜索匹配的文本。
- vimgrep
命令会创建一个快速列表(quicklist)来展示包含与模式匹配的文本的文件列表,我们可以使用
- vimgrep
命令来打开这个列表。如果我们想充分利用好快速列表(quicklist),我们可以使用
- :copen
命令把快速列表转换为参数列表,
- :Qargs
命令是我们在 vimrc 文件里设置的一个映射:
- :Qargs
- command! -nargs=0 -bar Qargs execute 'args' QuickfixFilenames()
- " populate the argument list with each of the files named in the quickfix list
- function! QuickfixFilenames()
- let buffer_numbers = {}
- for quickfix_item in getqflist()
- let buffer_numbers[quickfix_item['bufnr']] = bufname(quickfix_item['bufnr'])
- endfor
- return join(map(values(buffer_numbers), 'fnameescape(v:val)'))
- endfunction
1 2 3 4 5 6 7 8 9 10 |
command! -nargs=0 -bar Qargs execute 'args' QuickfixFilenames() " populate the argument list with each of the files named in the quickfix list function! QuickfixFilenames() let buffer_numbers = {} for quickfix_item in getqflist() let buffer_numbers[quickfix_item['bufnr']] = bufname(quickfix_item['bufnr']) endfor return join(map(values(buffer_numbers), 'fnameescape(v:val)')) endfunction |
最后, 下面是一个在多个文件中进行搜索和替换的操作命令:
- :vimgrep /CurrencyNumberHelper/ app/models/*.rb
- :Qargs
- :argdo %s/CurrencyNumberHelper/CurrencyHelper/g
- :argdo update
1 2 3 4 |
:vimgrep /CurrencyNumberHelper/ app/models/*.rb :Qargs :argdo %s/CurrencyNumberHelper/CurrencyHelper/g :argdo update |
buztard 在评论里提出一个更简单的方法,使用 ack-grep 来创建参数列表:
- :args `ack-grep -l CurrencyNumberHelper`
- # or, if you're using Ack plugin, then just :Ack CurrencyNumberHelper
- :argdo %s/CurrencyNumberHelper/CurrencyHelper/g
- :argdo update
1 2 3 4 |
:args `ack-grep -l CurrencyNumberHelper` # or, if you're using Ack plugin, then just :Ack CurrencyNumberHelper :argdo %s/CurrencyNumberHelper/CurrencyHelper/g :argdo update |
如果你使用版本比较新的 Vim, 这个操作会更简单。正如 Thiago A. z 在评论里提出的方法,你可以简单地使用
和
- cdo
命令即可:
- cfdo
- :Ack CurrencyNumberHelper
- :cfdo s/CurrencyNumberHelper/CurrencyHelper/g | update
1 2 |
:Ack CurrencyNumberHelper :cfdo s/CurrencyNumberHelper/CurrencyHelper/g | update |
在录制宏的过程中经常会出现误操作,当出现出现误操作时,对已录制的宏进行编辑比重新录制更简单方便。假设我们录制了一个宏到寄存器 a 里,我们可以使用
命令把宏的内容打印到当前的缓冲区里,然后在 Vim 里对这个宏进行编辑。一旦对宏的内容进行了修改,我们可以选择修改后的宏并且使用
- :put a
命令把它复制到寄存器
- "ay
中。之后我们就可以使用
- a
命令运行寄存器 a 中的新宏。
- @a
如果我们已经录制了宏,并且想在某些文件里运行它。首先,我们需要使用这些文件来建立一个参数列表。比如我们需要加载一个 Rails 应用的所有 model:
1 |
:args app/models/*.rb |
然后我们使用以下命令老来运行宏(这个宏已经录制保存在寄存器 a1a 中):
1 |
:argdo normal @a1a |
最后,我们使用下面命令来保存所有缓冲区的修改:
1 |
:argdo update |
Bash shell 提供了两种命令行编辑模式:emacs 和 vi 模式。emacs 编辑模式是命令行的默认模式,我们可以使用以下命令来把命令行的编辑模式改为 vi 模式:
1 |
set -o vi |
然后我们就可以在命令行模式里使用 ESC 键来进入 vi 的编辑模式,并且可以使用 vi 文本行编辑能力。当我们在命令行里处于 vi 编辑模式时,我们可以使用 v 键弹出编辑器,我们在里面编辑保存的命令会直接在命令行里运行。这是一个很赞的功能, 你觉得呢?:)
如果我们需要返回 emacs 模式,打印一下命令即可:
1 |
set -o emacs |
这里有一张速查表,记录了在 bash shell 中使用 vi 模式的可用命令。
在寻找更多的 Vim 技巧? 可以查看作者的 vimfiles,还有《25 个 Vim 教程、视频和资源》和《提高 Vim 使用效率的 12 个技巧》。
来源: http://blog.jobbole.com/111962/