如何在 vim 中自动创建匹配的大括号?
它应该按如下方式工作:如果我输入一个左大括号,右大括号应该自动出现,并且光标应该放置在中间。要跳出大括号对,Ctrl-j请使用组合。
有很多插件提供自动大括号插入。但他们
- Ctrl-j使用与跳出大括号对不同的组合键或
- 干扰多功能剪键绑定。
以下工作按预期进行
:inoremap ( ()<Esc>:let leavechar=")"<CR>i
:imap <C-j> <Esc>:exec "normal f" . leavechar<CR>a
但通过这些设置,UltiSnips 片段不再起作用。所以我使用 UltiSnips 插入右大括号:
inoremap ( (<C-R>=UltiSnips_Anon('($1)$0', '(')<CR>
这几乎有效。匹配的大括号已插入,我可以使用 跳过结束大括号Ctrl-j。然而,只有当左大括号前面有空格时,这才有效。
main () // works, the closing parentheses is added
main( // fails without a space
我的解决方案要么需要不同的键绑定来跳过右大括号,要么需要在左大括号前面有一个空格。如何解决这个问题?
注意:我使用括号作为示例。它应该与圆括号、大括号、方括号和小于号一起使用,并且不会干扰 UltiSnips 插件。
答案1
如何在 vim 中自动创建匹配的大括号?
正如您将看到的,这个问题并不简单。简单的答案是:使用插件,例如自动关闭或者智能输入。只需天真地重新映射 ( [ .. 键就会在几行中向您呈现边缘情况,这就是制作这些插件的原因,以及为什么它们通常非常复杂(如果它们有什么好处的话)。
所以我使用 UltiSnips 插入右大括号
你可以尝试这个(这与我最初的建议不同):
inoremap ( ()<CR>=UltiSnips_Anon('$1)$0', ')')<CR>
UltiSnips 将在其中分割线(
而不是包含main
在匹配中。为此使用片段插件的问题是它们(通常)不支持嵌套,因此当插入下一个(嵌套)片段时它们会忘记任何跳转位置。
要跳出大括号对,Ctrl-j请使用组合。
您可以重新映射Ctrl-jUltiSnips 或冲突的插件。如果文档中未列出映射,您可以使用:map/imap/nmap <key>
显示映射。如果您想Ctrl-j挑选并完成这两个插件的工作,您需要:
- 比我怀疑你想象的要先进得多
- 我怀疑你并不真正想要的东西
考虑这个 bash 循环:
while (( ${arr1[i]} < ${arr2[i<CURSOR>]} )); do
[next_snippet_position_marker]
done
在这种情况下,您需要按Ctrl-j5 次才能到达循环体。使用右大括号跳出相应的大括号可以让您更好地控制光标实际移动的位置。您可以实现一个堆栈来跟踪插入的对并用于Ctrl-j弹出和移动,但是如果您开始手动删除大括号而不将它们从堆栈中删除,那么您会遇到问题。因此,您将开始解决大括号插件试图解决的问题。这是一个很难重新发明的轮子。
对此进行扩展,您可以得到您最初要求的内容,使用Ctrl-j跳出大括号和片段。如果您使用一些虚拟值来表示片段位置,并将它们除了右大括号之外推入堆栈,并动态重新映射 来Ctrl-j对应片段或大括号的处理。但是,然后您需要实现一些相当先进的启发式方法来弄清楚应该发生什么魔法,因为您本质上是同时解决两个问题,目前正在由片段插入插件和大括号匹配插件的创建者分别解决,并且再次重新解决这些问题他们的解决方案,以实现便利和神奇。
这归结为控制与便利。我认为在这种情况下控制会更好地为您服务,这意味着您应该将这些问题及其相关的插件和键映射分开。如果你仍然想要方便,这是可行的,但很难。
答案2
我发现自动关闭增加了一点滞后,并且还干扰了我的设置(Ultisnips 和 Supertab),但我喜欢它模拟 Eclipse CDT 的方法。
我用定界伴侣使用以下地图来帮助导航和缩进,尝试获得相同的结果:
imap <C-F> <C-G>g " To jump out brackets in same line.
inoremap <C-K> <ESC>ki<TAB> " To move and insert an indent on the line before the current cursor (assuming empty line)
我这样使用它:插入开口{ <CR><CR><C-K>
并开始在缩进的内行中书写。
答案3
我个人使用智能输入用于自动插入括号和引号。例如,{
在任何地方键入都会使{}
光标位于中间。要离开{
括号组,}
只需在插入的}
.
然而,这确实支持您对制表符和跳转到括号外的要求。它也不会在你的括号之间创建一个新的,但无论如何你只需要一个额外的键 - <CR>
。
您可以映射<C-J>
以跳转到下一行:
:inoremap <C-J> <C-O>j
或者如果您想移动到下一行的开头:
:inoremap <C-J> <C-O>+
答案4
我认为定界伴侣做你需要的。
它会自动关闭括号或引号并将光标置于其间。要跳出一对括号(在插入模式下),您可以执行Ctrl-g+但您可以通过将其添加到您的g来重新映射它:Ctrl-jvimrc
% Jump out of a block of parentheses (uses delimitMate)
imap <C-j> <C-g>g