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


77

我花的方式太多时间摸索周围因为Vim不处理花括号最喜欢的IDE做。这是我想发生的事情:

输入:

if( whatever )
{ <CR>

并得到这个:

if( whatever )
{
  |  
}

其中,<CR>平均值表示ENTER按键,|是光标的位置。这就是Eclipse所做的。这就是Visual Studio所做的。这就是我想要Vim要做的。

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



2
注意:Vim是一个功能强大的文本编辑器,在某些方面它可以像IDE一样工作,但它不是IDE。在这种情况下,这是文本编辑功能,这正是Vim擅长的功能,因此,您很上乘。
基思·品森

Answers:


43

在VimL中,您可以{完全按照自己的意愿映射操作:

inoremap { {<CR>}<Esc>ko

根据您的自动缩进设置,您可能需要添加一个<BS>after <CR>

有关更完整的解决方案,建议您看看Luc Hermitte的vim插件。。到目前为止,他们从未让我失望。


1
映射{<CR>也是可能的吗?我的意思是,如果我仅{"something":"like this"}在python,js或ruby中输入哈希,该怎么办?
拉普利·安德拉斯

4
是的,{<CR>有可能。这就是我的.vimrc文件中的内容{<CR> {<CR>}<Esc>ko
AgmLauncher 2014年

@AgmLauncher,您好:如果我输入,它可以工作{,但是当我粘贴包含的代码块时出现问题{,它将}在末尾添加一个。
Evan Hu

2
@Evan-粘贴代码时,很多事情都会出错,尤其是使用自动缩进之类的东西时。在粘贴之前尝试:set paste,然后在完成后:set nopaste。这将切换粘贴模式。
Abhinav Gujjar 2015年

11

结合使用自动关闭功能和以下功能可以正常工作。

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

至少对于我的系统(在Mac OS X上为Unix终端),这是正确的。


7

这是我的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。


6

将以下内容放入您的.vimrc文件:

inoremap { {}<ESC>ha

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

也许有人可以弄清楚如何计算光标所在的选项卡数量,然后在}换行符的前面生成相等数量的选项卡。


6

大括号,方括号和括号之间的选项卡之间的解决方案。

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

结果:

function() {
  |
}

4

我一直喜欢类似sublime文本的操作,在该文本中将右花括号附加为下一个字符,因此我在.vimrc中添加了以下内容:

inoremap (  ()<ESC>hli

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


替换(()hli。在Mac上为Vim8。
Vitaly Zdanevich

3

对于像我一样遇到这种情况并且正在寻找比AutoClose更新的东西的任何人:delimitMate我发现,这不仅是对AutoClose的首选解决方案,在行为上也很明智,而且在主动开发中。根据vim.org的资料,自2009年以来未更新AutoClose。


1
请注意,delmitMateExpand默认情况下该选项处于关闭状态。您需要添加let delimitMate_expand_cr = 1 到中.vimrc
塞巴斯蒂安

3

我尝试了不同的插件,但发现最准确,最容易使用的自动配对。它非常直观,安装后即可立即获得期望的结果。


1
此答案发布已经五年了。如果遇到其他类似问题的人,这对我有用,至少没有破坏其他插件。
dekarpaulvictor

3

正如您将在Wikia技巧中看到的:这个重复出现的问题有很多解决方案(我什至有我的)。

就是说,如果您只限于括号对。在这里,您处于控制语句的上下文中。因此,您更有可能找到不希望您在键入“ if”语句时键入“){”的代码段系统。Vim的快捷方式往往比我在您的问题中读到的要短。同样,这里有很多选择,您会发现最有可能的选择,也许就是我的C&C ++套件


仅供参考:尝试获取lh-cpp-1.0.0.vba vimball时,Google会给出404。我使用了svn,从没注意到。
Michael Foukarakis 2010年

确实。我的错。我想先完成文档,然后再对vimball等进行正式发布。
卢克·赫米特

2

delimitMate为此进行设置。


请提供更多信息。哪个设定?
docwhat 2012年

嗯,这是前一段时间。我可能已经说过了delimitMate_expand_cr,尽管它似乎并没有完全按照要求进行。似乎正确插入了换行符,但可能没有添加结尾括号。帮助文件在这里:github.com/Raimondi/delimitMate/blob/master/doc/delimitMate.txt就我个人而言,这几天我只使用endwise(github.com/tpope/vim-endwise),否则使用我自己的括号,因为没有自动化完全正确。
Henrik N

感谢您指向结束的指针。以前看的时候我不知道那是什么。
docwhat 2012年

2

Vim补丁7.4.849添加了绑定,以允许光标移动而无需重新启动撤消序列。一旦更新为> = 7.4.849,则类似的效果很好。

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

请注意,我直接从补丁中包含的文档中获取了该信息。此功能的最佳简单解决方案。


这是修复程序“。” 无法使用自动匹配的括号。
John Eikenberry

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

2

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

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


1

只是对@Bob的注释。

卡尔·古尔汀(Karl Guertin)的自动关闭(AutoClose)具有一个名为``双括号''的功能,即您可以键入两次大括号,如下所示。

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

会导致:

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

然后,您可以键入一个选项卡,即可根据您的'shiftwidth”的设置缩进,然后键入。


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>

\在线路二和三的开始仅仅是一个续行符。您可以在一行上完成所有操作,但是我添加了它,以便我可以以反映您要查找的输出的方式来分发缩写-只是使事情变得更加直观。


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>

0

如果您键入{}并单击,则alti您将处于INSERT模式下的大括号之间(至少在终端中)。然后您可以按一下,ENTER然后altshifto插入换行符。你也可以只做到{<CR>}altshifto

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.