至少一个您不知道的Vim技巧

我在Vim工作了八年,不断发现新东西。 它被认为是Vim的优点。 对我而言,这是缺乏开放性的:一堆隐藏函数隐藏得太深了。

他们谈论了模态编辑和文本对象的美丽,但在我看来,Vim的本质并非如此。 Vim是被其他工具阻塞的拼凑而成的子系统。 仅在普通编辑模式下,一百多个键盘快捷键! 工具包的密集程度在很大程度上解释了Vim为什么如此有用。 如果“显示关键字的所有标签”仅为g] ,则此命令将更频繁地使用。

在缺乏开放性的系统中,必须依靠领导才能。 但是对于Vim来说,并不是很多。 有适合初学者的文章,例如ciw (请勿与CIA混淆, CIA手册针对Vim )等。 并且有沉浸在子系统中的专家文章。 但是没有人真正谈论让您惊叹的这些特殊技巧:该死的,因为过去六年中我需要它!

本文是关于我在Vim中使用的一些小技巧。 它们都不是所有细节都可以分解的,因此,如果有兴趣,我建议您挖掘其他信息。 它们也彼此不相关。 但这是正常的。 总的来说,有太多的东西可以真正帮助几乎每个人。

文章结构


Vim用户非常粗鲁,分为两类。 纯粹主义者赞赏其体积小和普遍存在。 通常,如果您必须在不熟悉的计算机上工作(例如,通过ssh),它们会最小化配置。 另一方面,扩展器在Vim中填充了插件,函数和本地映射,从而徒劳地假装使用Emacs。 如果您从他们那里取走vimrc,那么这些家伙将仍然完全无助。

您可能会猜到,与纯粹主义者相比,我更接近扩张者。 我根据基本Vim是否需要更改将技巧分为两部分。

纯粹主义者


对于模式命令,使用标准帮助视图,即<cr>表示按Enter键。 当您需要帮助时:h用于特定行,例如:h E676 ,该行将放在括号中。

普通模式下的各种命令


“:和@:


":是保存最后执行的命令的寄存器。您可以键入":p以将其打印到缓冲区。 @:重复最后一个命令。

“ =


注册“表达式”。 在这里,您可以输入任何vimL表达式并将其插入并与ctrl-R一起使用,等等。因此,例如,通过键入"=strftime("%c")<cr>p来插入本地时间戳。

毫安


m{letter}将标记放置在光标位置。 然后'{letter}将转到此行。 对于小写字母,它作用在缓冲区上,因此适合导航。 它在全局上适用于大写字母:即使您在另一个文件中, 'A也会转到标有的文件中” 您可以使用命令:marks:查看所有标签:marks:

ctrl-A和ctrl-X


在光标位置或其右侧的行中增加和减少下一个数字。 由于它会立即显示数字,因此可以在任何地方使用该组合。 10c-Awwwwwciw20简单得多。

问:


打开以前团队的历史。 您可以像处理任何Vim文本一样使用它,但是不会保存更改。 但是,您可以使用<CR>运行修改后的命令。 这使您可以非常快速地更改和重新启动命令,或查找旧命令以供重用。

q /,q?


q:相同,但搜索除外。

Ctrl-I,Ctrl-O


移动到跳转列表中的下一个或上一个位置。 用于快速检查然后回溯。 读取帮助文件非常好。

巨集


请参阅这篇文章 ,以更深入地了解宏的使用。

视觉模式


gv


选择上一个视觉项目。

v_o


转到可视块的另一侧。 如果您开始的行太低或类似的情况很有用。 在块模式下,它将变为相反的对角,并使用v_O切换到相反的v_O

g ctrl-A / ctrl-X


在可视模式下,Ctrl-A只是增加每行的第一个数字。 另一方面, g ctrl-A每行将增加一行。 在表中更容易解释:

已选ctrl-Ag ctrl-A2 g ctrl-A
  0
 00
 ç
 0天 
  1
 11
 ç
 1天 
  1
 b 2
 ç
 3天 
 一个2
 b 4
 ç
第6天 

运算子:v,V,cv(:h o_v)


您可能知道,在可视模式下可以选择字符(v),行(V)和块(ctrl-V)。 但是这三个组合可以用作相应片段的运动运算符。 例如,您具有以下文本:

abc
abc
abc


如果将光标放在顶部b并按d2j ,它将删除所有三行,因为j逐行移动。 如果改为按d<cV>2j ,则移动将逐块进行,仅删除带有三个字母b的中间列。

一种用例是在搜索中删除。 正常d/逐个字符移动。 因此,我将dV/用于逐行删除运动。 还有另一种方法:

/正则表达式/ {n}


在匹配项下移动n行,如果该值为负,则向上移动多行。 作为副作用,移动是逐行发生的。 因此,如果要删除与regex对应的第一行, regex可以输入d/regex//0

前队


您可以在命令模式下输入前命令,例如,命令:s 。 除了替换以外,还有许多其他有用的命令。 所有这些示例都需要一个范围,例如%

:g / regex / ex


仅在与正则表达式匹配的行上运行命令。 例如,您可以输入g/regex/d删除所有与regex匹配的行。 v命令类似于g ,但可在所有匹配正则表达式的行上使用。

技巧随着规范和其他方面变得更加强大。

:规范{Vim}


就像您在范围的每一行上运行{Vim}一样。 例如, g/regex/norm f dw将删除与regex正则表达式对应的每一行中第一个空格之后的第一个单词。 这通常比宏简单得多。

norm遵循您的所有比较。 例如,如果您在插入模式下将jk分配给<esc> ,则norm I jk$diwnorm I jk$diw的开头添加一个空格, 离开insert模式 ,然后删除该行的最后一个单词。 我真的很喜欢此功能,但是如果您不想使用映射,则可以应用norm!

:公司


将范围复制到当前行。 您还可以指定任意值而不是句点,例如+3'a. mv 'a. mv移动。

:y {reg}


将范围复制到{reg}寄存器。 如果{reg}大写,则将其添加到现有案例中。 即这样的团队

let @a = '' | %g/regex/y A

将复制到整个文件中与regex对应a所有行。 这有助于从文件中提取损坏的文本并将其复制到系统剪贴板(使用let @+ = @a )。

:windo {ex}


在所有窗口中运行命令。 例如:windo $向下:windo $所有窗口。 有bufdocdotabdo等。

gs配合得很好。 要将所有AA组合替换为BB并提供替换预览,您可以通过将所有匹配项加载到quickfix中来输入vimgrep AA ,然后使用cdo s/AA/BB/cge搜索/替换所有匹配项。

Vim的扩展


这里列出了一些技巧,需要保存设置或更改Vim会话。 假设地,它们可以仅通过输入命令就可以在“清教徒”模式下使用,但是有些涉及相当严重的变化,与清教徒的精神背道而驰。

这只是最不寻常的。 许多人将H分配给cap ^ ,所以这些事情不值得一提。 另外,谈论vim-sensiblevim-surround毫无意义,而只谈论更多奇特的插件。

如果您一直在配置vimrc,请您自己做,并为此添加一个单独的命令:

command! Vimrc :vs $MYVIMRC

设定值


我将所有设置,按键绑定和功能存储在单个vimrc文件中。 拆分成多个文件使搜索变得困难。

大多数设置实际上并不是任何“技巧”。 最好看一下适合vim的内容 :几乎所有在那里的设置都适合您的vimrc。

设置lazyredraw


不要在宏中间重画屏幕(以提高性能)。

设置smartcase / ignorecase


使用这两个设置,不使用大写字母的搜索将不区分大小写,而使用大写字母的搜索将区分大小写。

设置撤消文件


即使关闭并打开Vim,也要保存操作,以使撤消操作始终可用。 与undotree插件结合使用非常方便。

设置foldcolumn = {n}


带有折叠块的侧柱。 n越大,该列中折叠的块越多,其余数字则用数字表示。

set suffixesadd = {str}


gf通常表示“转到光标下的文件”,但该行中需要文件扩展名。 suffixesadd添加指定的扩展名。 如果suffixesadd=.md ,则在'foo'行上的gf命令将查找文件foofoo.md

设置inccommand = nosplit


仅适用于Neovim。 incommand实时显示团队将进行哪些更改。 当前仅支持s ,但即使这样也非常有用。 如果输入:s/regex:s/regex所有匹配项都突出显示。 如果您随后添加/change ,它将显示所有替换项。 适用于所有正则表达式属性,包括反向链接和组。

设置状态行(:h状态行)


确定在每个窗口底部的面板中显示什么。 与其他设置相比,此处的格式要复杂得多,而且比较挑剔,因此您必须花一些时间来解释它。 有一些简单的技巧。 首先,查看默认的Vim状态栏:

:set statusline=%<%f\ %h%m%r%=%-14.(%l,%c%V%)\ %P

在这里,最容易替换%P (光标上的文件百分比)。 状态栏格式是百分号后的值。 因此,对于Markdown文件,您可以这样编写:

:set statusline=%<%f\ %h%m%r%=%-14.(%l,%c%V%)\ %{wordcount()[\"words\"]}

并用文档中的单词数替换文件的百分比。

或安装tabline 。 如果您不使用制表符,则可以将该行设置为“全局状态行”。 举个例子

set tabline=%{strftime('%c')}

将始终在顶部显示日期。

按键绑定


我有很多绑定。

默认情况下,愚蠢地分配了Vim中许多方便的键。 例如,保存击键scl (保存一个击键)是同义词,并且Uu相同,除了将undo作为新更改写入,这在功能上是无用的。 QgQ相同,并且在任何情况下都是一个巨大的陷阱。 Z仅用于ZZZQ 。 天哪,甚至Vim手册也建议将_和键重新分配给某些功能,因为“您可能永远不会使用它们”。 我不想保存一键,而是要向键盘添加全新的功能。 这是我的一些绑定:

nnoremap Q @@


在不减慢向ex模式的过渡的情况下,重复最后一个宏。

nnoremap s“ _d


它使s键(具有ssS的适当设置)的工作方式与d相似,只是不将已删除的文本保存在寄存器中。 有用以免阻塞寄存器。

nnoremap <cj> <cw> j


转到下面的窗口。 hkl适当分配。 使用Windows更容易。

nnoremap <leader> e:exe getline(行('。'))<cr>


像命令一样运行当前行。 在实验中,它通常比q:更方便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')


这使得jk沿着直线移动, 直到找到一个数字,然后取消该键。 因此,我可以浏览散文的较长段落而不会破坏10j组合。

<silent>参数有助于在任何绑定中运行ex命令。

inoremaps


感谢inoremap绑定可以在插入模式下工作。 他们在那里开始工作,因此是inoremap ;a aaaa将引入'aaaa'而不是'; a'。 如果要在普通模式下执行某些操作,请使用<cO> 。 例如,如果我们有

inoremap ;1 <co>ma

然后;1设置'a

我喜欢指定使用分号作为重新分配的键,因为在普通文本中,分号后几乎总是有空格或换行符。

自动命令


自动命令非常适合配置。 通常,您可以这样配置它们:

 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}命令仅将auto命令应用于当前缓冲区。 有时,我使用它向特定文件添加短期事件处理程序。

BufNewFile,BufRead


BufnewFile在创建新文件BufnewFile时启动-首次打开缓冲区时。 它们通常用于向特定文件类型添加参数和重新映射。 我有一个这样的:

 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-surroundNERDtree 。 这是一些我认为非常有用的鲜为人知的列表。

撤销树


在大多数文本编辑器中,撤消操作是线性发生的。 如果对A进行更改,请撤消它,然后对B进行更改,那么A将永远丢失。 但是,Vim存储整个未完成操作的树。 u命令回滚当前树分支中的操作,并且g转到先前的时间顺序版本。 您可以使用以下命令查看已取消操作的列表:undolist

但是这种格式不是很清楚。 最好查看实际的树。 这正是Undotree所做的:它以便捷的导航方式对取消的动作树进行了良好的ASCII表示。

交换


该插件提供用于交换参数的命令,因此您可以通过几次击键将(a, f(b, c))替换为(f(b, c), a) 。 我经常必须进行此类编辑,因此这是生活质量的重大改善。

新学期


将更高级别的API连接到neo / vim嵌入式终端。 例如:T {text}将{text}发送到控制台。 非常适合创建交互式环境。

“ TODO {{{


本文不讨论许多主题,因为它们过于技术性或需要详细解释,例如函数编写或语法系统。 而且我了解不多。 我想更详细地研究以下主题:

预览,快速修复和列表窗口


我有时会在这些窗口上使用工具,但是我不知道如何操作它们。 我想在我的TLA +插件中添加quickfix错误。 我也喜欢将支持信息和回调命令放在预览窗口中的想法。 这提供了一些很难在IDE中重现的可能性。

Neovim API


Neovim提供了用于将Vim与外部程序集成的高级API。 您的Python脚本可以将命令发送到Neovim实例,例如,您可以通过服务器控制编辑器。 我看到了一些很酷的概念演示,其中基于浏览器中的信息进行自动完成。 看起来很酷!

文字对象


从来没有创造这样的。



因此,这是Vim某些隐式功能的简要概述。 希望您发现有用的东西!

Source: https://habr.com/ru/post/zh-CN454742/


All Articles