在 Vim 中自动插入匹配的大括号
Posted
技术标签:
【中文标题】在 Vim 中自动插入匹配的大括号【英文标题】:Automatically insert a matching brace in Vim 【发布时间】:2011-05-30 03:21:20 【问题描述】:我方式花了太多时间摸索,因为 Vim 不像大多数 IDE 那样处理右括号。这就是我想要发生的事情:
输入这个:
if( whatever )
<CR>
然后得到这个:
if( whatever )
|
<CR>
表示点击 ENTER 键,|
是光标的位置。这就是 Eclipse 所做的。这就是 Visual Studio 所做的。这就是我希望 Vim 做的事情。
我看过一些插件,尝试了一些,但似乎没有一个会出现这种行为。当然,我不可能是第一个想要这个的程序员。
【问题讨论】:
github.com/garbas/vim-snipmate 注意:Vim 是一个非常强大的文本编辑器,它在某些方面可以像 IDE 一样工作……但它不是 IDE。在这种情况下,这是一个文本编辑功能,这是 Vim 擅长的,所以你是金子。 【参考方案1】:在 VimL 中,您可以映射 以完全按照您的意愿进行操作:
inoremap <CR><Esc>ko
根据您的自动缩进设置,您可能需要在<CR>
之后添加<BS>
。
要获得更完整的解决方案,我建议您查看Luc Hermitte's vim plugins。到目前为止,他们从来没有让我失望过。
【讨论】:
映射<CR>
也可以吗?我的意思是,如果我在 python、js 或 ruby 中只输入一个哈希 "something":"like this"
会怎样?
是的,<CR>
是可能的。这就是我的 .vimrc <CR> <CR><Esc>ko
嗨@AgmLauncher,如果我输入
,它可以工作,但是当我粘贴包含
的代码块时会出现问题,它会添加
at结束。
@Evan - 粘贴代码时,很多事情都会出错,尤其是自动缩进等。在粘贴之前尝试 :set paste ,然后在完成后尝试 :set nopaste 。这会切换粘贴模式。【参考方案2】:
将 AutoClose 与以下配合使用可以正常工作。
inoremap <CR> <CR><C-o>O
至少对我的系统来说是这样(Mac OS X 上的 Unix 终端)。
【讨论】:
【参考方案3】:大括号、方括号和括号的解决方案,中间有制表符。
" Automatically closing braces
inoremap <CR> <CR><Esc>ko<tab>
inoremap [<CR> [<CR>]<Esc>ko<tab>
inoremap (<CR> (<CR>)<Esc>ko<tab>
结果:
function()
|
【讨论】:
【参考方案4】:这是我的 vimrc 中的内容:
let s:pairs=
\'<': '>',
\'': '',
\'[': ']',
\'(': ')',
\'«': '»',
\'„': '“',
\'“': '”',
\'‘': '’',
\
call map(copy(s:pairs), 'extend(s:pairs, v:val : v:key, "keep")')
function! InsertPair(left, ...)
let rlist=reverse(map(split(a:left, '\zs'), 'get(s:pairs, v:val, v:val)'))
let opts=get(a:000, 0, )
let start = get(opts, 'start', '')
let lmiddle = get(opts, 'lmiddle', '')
let rmiddle = get(opts, 'rmiddle', '')
let end = get(opts, 'end', '')
let prefix = get(opts, 'prefix', '')
let start.=prefix
let rmiddle.=prefix
let left=start.a:left.lmiddle
let right=rmiddle.join(rlist, '').end
let moves=repeat("\<Left>", len(split(right, '\zs')))
return left.right.moves
endfunction
noremap! <expr> ,f InsertPair('')
noremap! <expr> ,h InsertPair('[')
noremap! <expr> ,s InsertPair('(')
noremap! <expr> ,u InsertPair('<')
而且,对于某些文件类型:
inoremap <CR> <C-o>o<C-o>O
// 我知道 InsertPair 函数是微不足道的,但它可以节省时间,因为有了它我可以用一个命令定义命令和普通模式映射,而无需编写大量 <Left>
s。
【讨论】:
【参考方案5】:最后我发现不需要插件,但这对我来说很完美:
inoremap <Esc>ha
inoremap ( ()<Esc>ha
inoremap [ []<Esc>ha
inoremap " ""<Esc>ha
inoremap ' ''<Esc>ha
inoremap ` ``<Esc>ha
【讨论】:
【参考方案6】:将以下内容放入您的 .vimrc 文件中:
inoremap <ESC>ha
每当您在插入模式下按 时,都会生成
并将您的光标放在右大括号上,这样您就可以立即开始在它们之间输入。通过将花括号按顺序而不是放在不同的行上,您可以手动将制表符放在
前面。这样你就不会在它前面有错误数量的标签。
也许有人可以弄清楚如何计算光标所在的标签数量,然后在新行上的 前面生成相同数量的标签。
【讨论】:
【参考方案7】:对于像我一样遇到这种情况并且正在寻找比 AutoClose 更新的东西的任何人:delimitMate 我发现它不仅是 AutoClose 的更可取的解决方案,行为明智,而且还在积极开发中。根据vim.org 的说法,AutoClose 自 2009 年以来一直没有更新。
【讨论】:
请注意delmitMateExpand
选项默认是关闭的。您需要将let delimitMate_expand_cr = 1
添加到您的.vimrc
。【参考方案8】:
我尝试了不同的插件,但我发现auto-pairs 最准确和最容易使用。它非常直观,当您安装它时,您会得到开箱即用的预期效果。
【讨论】:
这个答案发布已经五年了。万一其他人遇到类似问题,这对我有用,至少不会破坏其他插件。【参考方案9】:我一直更喜欢 sublime text 的作用,它将右大括号作为下一个字符附加,所以我在我的 .vimrc 中添加了以下内容:
inoremap ( ()<ESC>hli
将光标移动到两个大括号之间。
【讨论】:
这会将(
替换为()hli
。 Mac 上的 Vim8。【参考方案10】:
inoremap ( ()<ESC>i
inoremap " ""<ESC>i
inoremap ' ''<ESC>i
inoremap <Cr><Esc>O
【讨论】:
【参考方案11】:正如您将在wikia tip 中看到的那样:对于这个反复出现的问题有很多解决方案(我什至有mine)。
也就是说,如果您将自己限制在括号对中。在这里,您处于控制语句的上下文中。因此,您更有可能发现在键入“if”语句时不会期望您键入“) ”的 sn-p 系统。 Vim 快捷方式往往比我在你的问题中读到的更短。这里再次有很多选择,你会找到最有可能的狙击手,可能是我的C&C++ suite。
【讨论】:
仅供参考:Google 在尝试获取 lh-cpp-1.0.0.vba vimball 时会给出 404。我用的是svn,以前没注意过。 确实如此。我的错。我想在正式发布 vimball 之前完成文档。【参考方案12】:delimitMate 对此进行了设置。
【讨论】:
更多信息,请。哪种设置? 嗯,这是不久前的事了。我的意思可能是delimitMate_expand_cr
,尽管它似乎并没有完全按照要求做。似乎正确插入换行符,但可能没有添加结束括号。帮助文件在这里:github.com/Raimondi/delimitMate/blob/master/doc/delimitMate.txt 就个人而言,这些天我只使用 endwise (github.com/tpope/vim-endwise) 并匹配我自己的括号,因为没有自动化完全正确。
感谢指向 endwise 的指针。以前看的时候不知道是什么。【参考方案13】:
Vim 补丁 7.4.849 添加了一个绑定以允许光标移动而无需重新启动撤消序列。一旦更新到 >= 7.4.849,这样的东西就很好用。
inoremap ( ()<C-G>U<Left>
请注意,我是直接从补丁中包含的文档中获取的。此功能迄今为止最简单的解决方案。
提交补丁 7.4.849: https://github.com/vim/vim/commit/8b5f65a527c353b9942e362e719687c3a7592309 邮件列表线程:http://vim.1045645.n5.nabble.com/Any-automatic-bracket-insertion-plugins-not-breaking-undo-td5723654.html【讨论】:
这是修复 '.'不使用自动匹配的括号。【参考方案14】:按照标题为 Automatically append closing characters 的文章中的建议安装和使用 Vim 脚本 AutoClose。
【讨论】:
自动关闭不符合我的要求。它将右大括号留在同一行,让我按两次 Enter,返回命令模式,向上移动一行,插入模式,制表符,最后键入。【参考方案15】:只是给@Bob 的便条。
Karl Guertin 的AutoClose 有一个名为“双大括号”的函数,即可以键入两次大括号,如下所示。
int func_name(void) ==> Type `' twice here.
会导致:
int func_name(void)
| ==> Cursor here.
然后,您可以键入 单个 Tab,根据您的 `shiftwidth' 设置缩进,然后键入。
【讨论】:
【参考方案16】:如果您输入 并点击alti,您将在
INSERT
模式下处于大括号之间(至少在终端中)。然后你可以点击 ENTER 后跟 altshifto 来插入换行符。你也可以只做<CR>
和 altshifto。
这可能不是全自动的,但我认为它是半自动的。它消除了对更多插件的需求,并且是了解其他用例的有用信息。例如,我一直使用 altshifto 来插入空行,而不必显式离开 INSERT
模式,而 alti 用于进入()
等。
【讨论】:
【参考方案17】:如果您启用了自动缩进,请将其插入您的 ~/.vimrc
:
inoremap <CR> <CR><Esc>ko
inoremap [<CR> [<CR>]<Esc>ko
inoremap (<CR> (<CR>)<Esc>ko
如果不是
inoremap <CR> <CR><Esc>ko<tab>
inoremap [<CR> [<CR>]<Esc>ko<tab>
inoremap (<CR> (<CR>)<Esc>ko<tab>
然后你可以映射一个键(在我的例子中,键是ä
,这可以替换为你想要的任何东西)...
map ä A<space><CR>
...自动为您完成所有这些操作,如果您在按键行中的任何位置。
示例('|' 表示您的光标所在的位置):int main(int a|rgc)
当你现在按下键时(在我的例子中是 ä
在命令模式下),结果将是这样的:
int main(int argc)
|
【讨论】:
【参考方案18】:您不需要特殊的插件来执行此操作 - 但这是一个两步过程。
首先,将以下内容添加到您的.vimrc
以吃掉触发字符:
" eat characters after abbreviation
function! Eatchar(pat)
let c = nr2char(getchar(0))
return (c =~ a:pat) ? '' : c
endfunction
然后将此缩写添加到您的.vimrc
:
inoreabbr <silent>
\<cr><space><space>
\<cr><esc>0i<esc>k$i<c-r>=Eatchar('\m\s\<bar>\r')<cr>
第二行和第三行开头的\
只是一个续行字符。您可以在一行中完成所有这些,但是我添加了它,以便我可以以一种反映您正在寻找的输出的方式传播缩写 - 只是让事情更直观一些。
【讨论】:
【参考方案19】:我的解决方案:
inoremap <expr> <CR> InsertMapForEnter()
function! InsertMapForEnter()
if pumvisible()
return "\<C-y>"
elseif strcharpart(getline('.'),getpos('.')[2]-1,1) == ''
return "\<CR>\<Esc>O"
elseif strcharpart(getline('.'),getpos('.')[2]-1,2) == '</'
return "\<CR>\<Esc>O"
else
return "\<CR>"
endif
endfunction
说明:
上面的代码首先检查你是否使用Enter
来确认代码完成,如果不是,它会在你输入Enter
时缩进|
。此外,它还提供html标签自动缩进。
示例:
if( whatever )|
按Enter
你会得到
if( whatever )
|
这也适用于 html 文件。看下面的例子
<html>|<html>
按Enter
你会得到
<html>
|
</html>
【讨论】:
以上是关于在 Vim 中自动插入匹配的大括号的主要内容,如果未能解决你的问题,请参考以下文章