在Vim中自动插入匹配的括号

时间:2010-12-23 19:28:51

标签: vim autocomplete

我花了太多时间来浏览,因为Vim不像大多数IDE那样处理关闭括号。这就是我想要发生的事情:

输入:

if( whatever )
{ <CR>

得到这个:

if( whatever )
{
  |  
}

其中<CR>表示按 ENTER 键,|表示光标的位置。这就是Eclipse的功能。这就是Visual Studio的功能。这就是我想让Vim做的事情。

我见过几个插件,试了几个,但似乎没有一个插件给我这个行为。当然,我不能成为第一个想要这个的程序员。

20 个答案:

答案 0 :(得分:32)

在VimL中,您可以将{映射为完全按照您的意愿执行:

inoremap { {<CR>}<Esc>ko

根据您的自动设置,您可能需要在<BS>之后添加<CR>

要获得更完整的解决方案,我建议您查看Luc Hermitte's vim plugins。到目前为止,他们从未让我失望过。

答案 1 :(得分:16)

要在新行上获得右括号并将光标放在两个括号之间的行上,请按照标题为 Making Parenthesis And Brackets Handling Easier 的文章中第一条评论的建议。

答案 2 :(得分:9)

使用AutoClose,以下功能正常。

inoremap {<CR> {<CR>}<C-o>O

至少对我的系统来说是这样(Mac OS X上的Unix终端)。

答案 3 :(得分: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。

答案 4 :(得分:4)

括号,方括号和括号之间的制表符解决方案。

" Automatically closing braces
inoremap {<CR> {<CR>}<Esc>ko<tab>
inoremap [<CR> [<CR>]<Esc>ko<tab>
inoremap (<CR> (<CR>)<Esc>ko<tab>

结果:

function() {
  |
}

答案 5 :(得分:3)

正如您在wikia tip中看到的那样:这个反复出现的问题有很多解决方案(我甚至有mine)。

那就是你将自己限制为括号对。在这里,您处于控制语句的上下文中。因此,您更有可能找到不希望您在键入“if”语句时键入“){”的代码段系统。 Vim快捷方式往往比我在你的问题中读到的更短。这里有很多选择,你会发现很可能是snipmate,可能是我的C&C++ suite

答案 6 :(得分:3)

对于那些像我一样经历过这种情况的人,并且正在寻找比AutoClose更近期更新的东西:delimitMate我发现,不仅是AutoClose的一个更好的解决方案,行为明智,而且还有效发展。根据{{​​3}},自2009年以来,AutoClose尚未更新。

答案 7 :(得分:2)

我尝试了不同的插件,但我发现最准确且最易于使用auto-pairs。它非常直观,当您安装它时,您可以获得开箱即用的功能。

答案 8 :(得分:2)

最后,我发现不需要插件,但这对我来说很完美:

inoremap { {}<Esc>ha
inoremap ( ()<Esc>ha
inoremap [ []<Esc>ha
inoremap " ""<Esc>ha
inoremap ' ''<Esc>ha
inoremap ` ``<Esc>ha

答案 9 :(得分:2)

我总是喜欢像sublime文本那样将大括号作为下一个字符附加的东西,所以我将以下内容添加到我的.vimrc中:

inoremap (  ()<ESC>hli

将光标移动到两个大括号之间。

答案 10 :(得分:2)

Vim补丁7.4.849添加了一个绑定,允许光标移动而不重新启动撤消序列。一旦更新到&gt; = 7.4.849,那么类似的东西效果很好。

inoremap ( ()<C-G>U<Left>

请注意,我直接从补丁中包含的文档中抓取了它。这个功能的最佳简单解决方案。

答案 11 :(得分:2)

将以下内容放在.vimrc文件中:

inoremap { {}<ESC>ha

每当您在插入模式下按{时,都会生成{}并将光标放在右大括号上,以便您可以立即开始在它们之间键入。通过按顺序而不是在不同的行上放置花括号,您可以手动将标签放在}前面。这样你就不会有错误的标签数量。

也许有人可以弄清楚如何计算光标所在的标签数量,然后在新行的}前面生成相同数量的标签。

答案 12 :(得分:2)

delimitMate有此设置。

答案 13 :(得分:1)

按照标题为AutoClose的文章中的建议安装和使用Vim脚本Automatically append closing characters

答案 14 :(得分:1)

给@Bob留言。

Karl Guertin的AutoClose有一个名为``double brace''的函数,也就是说,你可以输入两次大括号,如下所示。

int func_name(void) {{ ==> Type `{' twice here.

会导致:

int func_name(void) {
| ==> Cursor here.
}

然后,您可以键入单个标签,根据您的`shiftwidth'设置缩进,然后输入。

答案 15 :(得分:0)

您不需要特殊的插件来执行此操作 - 但这需要两个步骤。

首先,将以下内容添加到.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>

第二行和第三行开头的\只是一个行继续符。你可以在一条线上完成所有这一切,然而我添加它以便我可以以一种镜像你正在寻找的输出的方式传播缩写 - 只是因此事情更直观一些。

答案 16 :(得分:0)

我的解决方案:

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>

答案 17 :(得分:0)

inoremap ( ()<ESC>i
inoremap " ""<ESC>i
inoremap ' ''<ESC>i
inoremap { {<Cr>}<Esc>O

答案 18 :(得分:0)

如果您键入{}并按 alt i ,则您将处于INSERT模式下的括号之间(至少在终端中) 。然后,您可以按 ENTER ,然后按 alt shift o ,以插入换行符。您也可以只进行{<CR>} alt shift o

这可能不是全自动的,但我认为它是半自动的。它消除了对更多插件的需求,对于了解其他用例是有用的信息。例如,我一直使用 alt shift o 来插入空白行,而不必显式退出INSERT模式,而< kbd> alt i 用于进入()等。

答案 19 :(得分:0)

如果您启用了自动缩进,请将其插入您的 ~/.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) {
    |
}