97

I spend way too much time fumbling around because Vim doesn't handle closing braces like most IDEs do. Here's what I want to happen:

Type this:

if( whatever )
{ <CR>

and get this:

if( whatever )
{
  |  
}

where <CR> mean hit the ENTER key and | is the position of the cursor. This is what Eclipse does. It's what Visual Studio does. And it's what I want Vim to do.

I've seen a few plugins, tried a few, and none of them seem to give me this behavior. Surely I can't be the first programmer to want this.

Keith Pinson
  • 7,835
  • 7
  • 61
  • 104
Bob
  • 3,283
  • 3
  • 20
  • 14
  • https://github.com/garbas/vim-snipmate – JuanPablo Jun 14 '12 at 19:51
  • 2
    Note: Vim is such a powerful text editor that it can act like an IDE in ways... but it is not an IDE. In this case, this is a text editing functionality, which is what Vim is good at, so you're golden. – Keith Pinson Jul 31 '12 at 16:10

20 Answers20

51

In VimL, you can map the { to do exactly as you wish:

inoremap { {<CR>}<Esc>ko

depending on your autoindent setup, you may want to add a <BS> after <CR>.

For a more complete solution, I'd suggest you take a look at Luc Hermitte's vim plugins. They've never failed me so far.

Michael Foukarakis
  • 39,737
  • 6
  • 87
  • 123
  • 1
    is mapping `{` also possible? I mean, what if I type just a hash `{"something":"like this"}` in python, js or ruby? – Rápli András Oct 09 '14 at 18:09
  • 4
    Yes, `{` is possible. This is what I have in my .vimrc `{ {}ko` – AgmLauncher Nov 24 '14 at 16:48
  • Hi @AgmLauncher, it works if I am typing the `{`, but there is a problem when I am pasting a block of code which contains `{`, it will add a `}` at the end. – Evan Hu Apr 12 '15 at 14:22
  • 3
    @Evan - When pasting code a lot of things can go wrong especially with auto indent and the likes. try :set paste before pasting and then :set nopaste once you're done. This toggles the paste mode. – Abhinav Gujjar Oct 13 '15 at 16:20
23

No need for plugin. Much cleaner and flexible solution:

inoremap { {}<Esc>ha
inoremap ( ()<Esc>ha
inoremap [ []<Esc>ha
inoremap " ""<Esc>ha
inoremap ' ''<Esc>ha
inoremap ` ``<Esc>ha
Nika Tsogiaidze
  • 949
  • 14
  • 18
15

Using AutoClose with the following works correctly.

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

This is true for my system at least (Unix terminal on Mac OS X).

dmonopoly
  • 3,251
  • 5
  • 34
  • 49
13

A solution for braces, brackets and parenthesis with tab in between.

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

Result:

function() {
  |
}
Rodrigo Pinto
  • 2,384
  • 22
  • 23
8

Here is what I have in my 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('<')

And, for some filetypes:

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

// I know that InsertPair function is trivial, but it saves time because with it I can define both command and normal mode mappings with one command without having to write lots of <Left>s.

ZyX
  • 52,536
  • 7
  • 114
  • 135
7

Put the following in your .vimrc file:

inoremap { {}<ESC>ha

Whenever you press { in insert mode, {} is generated and puts your cursor on the right brace, so that you can start typing between them straight away. By putting the curly braces in sequence rather than on different lines, you can put tabs in front of } manually. That way you never have the wrong amount of tabs in front of it.

Perhaps someone can figure out how to count the amount of tabs the cursor is on, and then generate an equal amount of tabs in front of the } on a new line.

user1534664
  • 3,258
  • 8
  • 40
  • 66
5
inoremap ( ()<ESC>i
inoremap " ""<ESC>i
inoremap ' ''<ESC>i
inoremap { {<Cr>}<Esc>O
max
  • 187
  • 1
  • 2
  • 9
4

For anyone that runs across this like I did, and was looking for something more recently updated than AutoClose: delimitMate I have found to be, not only a preferable solution to AutoClose, behavior wise, but also in active development. According to vim.org, AutoClose has not been updated since 2009.

Eric H
  • 1,100
  • 16
  • 32
  • 1
    Note that the `delmitMateExpand` options are off by default. You need to add `let delimitMate_expand_cr = 1 ` to your `.vimrc`. – sebastian May 28 '15 at 16:50
4

I have tried different plugins but I found most accurate and most easy to use auto-pairs. It is really intuitive and when you install it you get what you've expected out of the box.

egelev
  • 1,175
  • 2
  • 11
  • 27
  • 2
    It's five years since this answer was posted. In case someone else facing a similar problem comes along this is what worked for me, at least without breaking other plugins. – dekarpaulvictor Aug 08 '20 at 14:58
4

I've always preferred something like what sublime text does where it appends the closing brace as the next character, so I added the following to my .vimrc:

inoremap (  ()<ESC>hli

which moves the cursor to between the two braces.

Aneesh Durg
  • 464
  • 4
  • 14
3

As you'll see in the wikia tip: there are many solutions to this recurrent question (I even have mine).

That is if you limit yourself to bracket pairs. Here you are in the context of a control statement. You're thus more likely to find snippet systems that will not expect you to type the ") {" when typing an "if" statement. Vim shortcut tend to be shorter from what I read in your question. Here again there are a lot of choices, you'll find most likely snipmate, and may be my C&C++ suite.

Luc Hermitte
  • 31,979
  • 7
  • 69
  • 83
3

Insert this into your ~/.vimrc if you have auto-indent enabled:

inoremap {<CR> {<CR>}<Esc>ko
inoremap [<CR> [<CR>]<Esc>ko
inoremap (<CR> (<CR>)<Esc>ko

and if not

inoremap {<CR> {<CR>}<Esc>ko<tab>
inoremap [<CR> [<CR>]<Esc>ko<tab>
inoremap (<CR> (<CR>)<Esc>ko<tab>

Then you can map a key (in my case the key is ä, this can be replaced with anything you want)...

map ä A<space>{<CR>

...to automatically do all of this for you, if you are anywhere in the line on key press.

example ('|' symbolizes where your cursor is):
int main(int a|rgc)
When you press the key now (in my case ä in command mode), the result will be this:

int main(int argc) {
    |
}
larsaars
  • 2,065
  • 3
  • 21
  • 32
2

Vim patch 7.4.849 added a binding to allow for cursor movements without restarting the undo sequence. Once updated to >= 7.4.849 then something like this works great.

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

Note that I grabbed that straight from the documentation included in the patch. Best simple solution for this feature yet.

John Eikenberry
  • 1,133
  • 12
  • 12
2

delimitMate has a setting for this.

Henrik N
  • 15,786
  • 5
  • 82
  • 131
  • More info, please. Which setting? – docwhat Mar 02 '12 at 05:44
  • Hm, this was a while ago. I might have meant `delimitMate_expand_cr`, though it doesn't seem to do exactly what is asked for. Seems to insert linebreaks correctly but perhaps not add the ending bracket. Helpfile is here: https://github.com/Raimondi/delimitMate/blob/master/doc/delimitMate.txt Personally, I only use endwise (https://github.com/tpope/vim-endwise) these days and match my own brackets otherwise, since no automation quite gets it right. – Henrik N Mar 03 '12 at 17:51
  • Thanks for the pointer to endwise. I didn't realize what it was when I saw it before. – docwhat Mar 05 '12 at 00:34
1

Install and use Vim script AutoClose as recommended in the article titled Automatically append closing characters.

Derek Mahar
  • 27,608
  • 43
  • 124
  • 174
  • 2
    AutoClose doesn't do what I want. It leaves the closing brace on the same line, making me hit enter twice, go back to command mode, move up a line, insert mode, tab, and finally type. – Bob Dec 23 '10 at 19:33
1

Just a note to @Bob.

Karl Guertin's AutoClose has a function named ``double brace'', that is, you can type curly brace twice, as below.

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

would result in:

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

Then, you can type a single Tab, to get indented according to your `shiftwidth' setting, then type.

jtuki
  • 385
  • 1
  • 5
  • 8
1

If you type {} and hit alti you will be in between the braces in INSERT mode (at least in a terminal). Then you can hit ENTER followed by altshifto to insert the line break. You could also just do {<CR>} and altshifto.

This may not be fully automatic, but I consider it semi-auto. It removes the need for more plugins, and is useful info to know for other use cases. For example, I use altshifto all the time to insert blank lines without having to explicitly leave INSERT mode, and alti for getting inside () etc.

0

You do not need a special plugin to do this - but it is a two-step process.

First, add the following to your .vimrc to eat the triggering character:

" eat characters after abbreviation
function! Eatchar(pat)
    let c = nr2char(getchar(0))
    return (c =~ a:pat) ? '' : c
endfunction

and then add this abbreviation to your .vimrc:

inoreabbr <silent> { {
      \<cr><space><space>
      \<cr><esc>0i}<esc>k$i<c-r>=Eatchar('\m\s\<bar>\r')<cr>

The \ at the start of lines two and three is just a line continuation character. You could have done this all on one line, however and i added it so that i could spread the abbreviation out in a way that mirrors the output you're looking for -- just so things are a little more intuitive.

ricardo
  • 8,195
  • 7
  • 47
  • 69
0

My solution:

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

Explaination:

The code above first check if you are using Enter to do confirm a code completion, if not it will indent the {|} when you type Enter. Also, it provides html tags auto indent.

Examples:

if( whatever ){|}

press Enter and you will get

if( whatever )
{
  |  
}

This also works for html file. See the following example

<html>|<html>

press Enter and you will get

<html>
    |
</html>
WW00WW
  • 417
  • 4
  • 15
0

This works great!

Put this in your .vimrc.

inoremap { {^M}<C-o>dd<C-o>k<C-o>]p<C-o>O

This matches the indenting level to the indenting level of the first {.

Henrik
  • 43
  • 1
  • 4