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.
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.
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
Details about vim and above mapping.
Mapping:- a mapping is a way to define a shortcut for a sequence of keystrokes.
keystroke:- a keystroke refers to a single key press on the keyboard.
About above mappings.
The :inoremap command is used to create a mapping that works in insert mode. Whenever you type { in insert mode, it will be replaced with {}. The <Esc> is used to exit insert mode, and the ha moves the cursor back to the position after the opening curly brace. Like that these all mapping works.
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).
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() {
|
}
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.
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.
inoremap ( ()<ESC>i
inoremap " ""<ESC>i
inoremap ' ''<ESC>i
inoremap { {<Cr>}<Esc>O
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.
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.
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.
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.
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) {
|
}
delimitMate has a setting for this.
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.
commit for patch 7.4.849:
https://github.com/vim/vim/commit/8b5f65a527c353b9942e362e719687c3a7592309
mailing list thread: http://vim.1045645.n5.nabble.com/Any-automatic-bracket-insertion-plugins-not-breaking-undo-td5723654.html
Install and use Vim script AutoClose as recommended in the article titled Automatically append closing characters.
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.
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.
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.
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>
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 {.
Related
Note: The bar symbol (|) represents the editor caret throughout this question
I've made an UltiSnips snippet like this:
snippet "(\w+)" "HTML tag" r
<`!p snip.rv = match.group(1)`>$0</`!p snip.rv = match.group(1)`>
endsnippet
This lets me expand any word into a HTML tag, for example typing "body" and pressing tab expands to <body>|</body>.
The caret is placed between the tags. When I now press return, I would like to end up with:
<body>
|
</body>
This could be done with a keybind like this:
:ino <buffer> <CR> <CR><Esc>O
But I don't want to permanently rebind my return key. I only want this specific keybind to be active when my caret is placed between an opening and a closing HTML tag.
How can that be done most simply?
Another example is when I have my caret placed between two curly brackets, like so:
function() {|}
And press enter, I would like the result to be:
function() {
|
}
Again this can be done with the above key mapping, but in this case I would only want it to be active when my caret is placed between two curly brackets.
You could use map-expression (see :h map-expression) to decide whether what <CR> get mapped to when you hit it:
for example the following insert mode map:
inoremap <expr> <CR> strpart(getline('.'), col('.')-2, 1) =~ '[>{]' ? '<CR><ESC>O' : '<CR>'
checks the charachter before cursor and if its > or { it returns <CR><ESC>O in other situations it simply do <CR>
In place of conditional ternary expression you could define a full functional function to respond in any situatuion with any pairs; But there is already great plugins that intend to do such tasks gracefully:
demilitMate and auto-pairs are two famous one.
give them a try.
I've implemented this in lh-brackets, and I remember giving an answer to a very close question here: How to move opening curly braces to a new line in Vim?
I define it with:
call lh#brackets#enrich_imap('<cr>',
\ {'condition': 'getline(".")[col(".")-2:col(".")-1]=="{}"',
\ 'action': 'lh#brackets#_add_newline_between_brackets()'},
\ 0,
\ '\<cr\>'
\ )
If you want to distinguish language situations, you'll have to have ftplugins for c (and all other bracket based languages), xml (and other tag based languages) where you have a inoremap <buffer> <expr> that tests the context (see the test above) to return either "<cr>" or "<cr><esc>O".
" to be put in c, js, java, c#... ftplugins
inoremap <buffer> <expr> <cr> getline(".")[col(".")-2:col(".")-1]=="{}" ? '<cr> : '<cr><esc>O'
" to be put in a xml and HTML ftplugin
inoremap <buffer> <expr> <cr> getline(".")[col(".")-2:col(".")-1]=="><" ? '<cr> : '<cr><esc>O'
You can also define them globally in your vimrc, but then, it will be triggered all the time -- the tests will need to be merged in that case.
I am using vim from terminal as C++ IDE, and I have some issues with the autoclose curly brackets. I am using vim-autoclose plugin.
My problem is that when I am making new function and open curly brackets, the cursor doesn't return inside the function (inside the curly brackets) but it's returning at the end of the function.. Is there any way to fix that?
Also, when I am creating a new class, is there any way to automatically put a semicolon at the closing curly brackets of that class?
Most of the autoclose plugins that I have seen does not provide the ; append part on class and struct. Hence, I don't use plugins for autoclose and added, in ~/.vimrc
inoremap {;<CR> {<CR>};<ESC>O
After typing class Test, typing {; and Enter will render
class Test {
_ //cursor here
};
and of course, indentation need to be enabled from your end, for instance by ai or cindent
Here is some more mapping, might not be relevant to vim-autoclose, that works fine on plain vim.
inoremap " ""<left>
inoremap ' ''<left>
inoremap ( ()<left>
inoremap [ []<left>
inoremap { {}<left>
inoremap {<CR> {<CR>}<ESC>O
inoremap {;<CR> {<CR>};<ESC>O
The last line gives
if (true) {
_ //cursor
}
and whenever, you don't want the mapping, we need to escape it using Ctrl - v before typing the mapped char
Hope this helps
lh-cpp mapping on { will insert the semi-colon when the key is hit while on the same line as class, enum or struct. I haven't taken the time to do something more advanced.
And in all case, the cursor goes back to in between the pair of curly brackets. If you want a newline, you'll have to hit <CR>.
I most IDEs and modern text editors (Sublime Text 3) the cursor is correctly indented after inserting a newline in between an html tag (aka 'expanding" the tag):
Before:
<div>|</div>
After pressing CR:
<div>
|
</div>
But in Vim, this is what I get:
<div>
|</div>
How can I get the same behaviour in Vim like in most other editors (see above)?
The only correct behavior of <CR> in insert mode is to break the line at the cursor.
What you want is an enhanced behavior and you need to add something to your config to get it: a mapping, a short function or a full fledged plugin.
When I started to use vim, that behavior was actually one of the first things I added to my vimrc. I've changed it many times in the past but this mapping has been quite stable for a while:
inoremap <leader><CR> <CR><C-o>==<C-o>O
I've used <leader><CR> to keep the normal behavior of <CR>.
Here is a small function that seems to do what you want:
function! Expander()
let line = getline(".")
let col = col(".")
let first = line[col-2]
let second = line[col-1]
let third = line[col]
if first ==# ">"
if second ==# "<" && third ==# "/"
return "\<CR>\<C-o>==\<C-o>O"
else
return "\<CR>"
endif
else
return "\<CR>"
endif
endfunction
inoremap <expr> <CR> Expander()
This little snippet will remap Enter in insert mode to test whether or not the cursor is between > and < and act accordingly if it is. Depending on your indent settings the \<Tab> may need to be removed.
It will not play nice with other plugins that might be also be mapping the Enter key so be aware that there is probably more work to do if you want that compatibility.
function EnterOrIndentTag()
let line = getline(".")
let col = getpos(".")[2]
let before = line[col-2]
let after = line[col-1]
if before == ">" && after == "<"
return "\<Enter>\<C-o>O\<Tab>"
endif
return "\<Enter>"
endfunction
inoremap <expr> <Enter> EnterOrIndentTag()
I have only tested the simple cases (beginning of the line, end of the line, inside and outside of ><), there are probably edge cases that this would not catch.
#RandyMorris and #romainl have posted good solutions for your exact problem.
There are some other possibilities you might be interested in if you are typing out these tags yourself: there's the ragtag.vim plugin for HTML/XML editing.
With ragtag.vim you type this to create your "before" situation (in insert mode):
div<C-X><Space>
To create your "after" situation you would instead type:
div<C-X><Enter>
So if you know beforehand that you are going to "expand" the tag, typing just the element name and the combo CtrlX followed by Enter is enough.
There are also other more advanced plugins to save keystrokes when editing HTML, such as ZenCoding.vim and Sparkup.
Since no one have mentioned it I will. There is excellent plugin that does exactly that
delemitmate
I always type paired characters by pairs:
'' "" () [] {} <>
How do I map Vim immediately jump inside them when I type them during Insert Mode? I tried some googling but I can't seem to get the right search term.
Use the AutoClose plugin, which will insert the closing brace for you, leaving your cursor inside them. If you type the matching bracket quickly enough, it will move your cursor outside the pair.
Without using any plugin, I found out I could use this:
inoremap '' ''<esc>i
inoremap "" ""<esc>i
inoremap () ()<esc>i
inoremap [] []<esc>i
inoremap {} {}<esc>i
inoremap <> <><esc>i
is there some way to tell VIM place the cursor at some position after abbreviation expansion?
Say you have something like this in .gvimrc
iabberv <? <?=|?>
and you want to place cursor where pipe character is automatically.
A quick solution that I'd use in this case is to insert some key presses to the abbreviation:
iabbrev <? <?=?><Left><Left>
Would place the cursor two places left, after the =.
In this manner, you can use various movement keys such as <End>, <Home>, or even return to normal mode with <Esc> and command usual normal-mode commands. The example would then be
iabbrev <? <?=?><Esc>hha
and it does the same as the first example. If you expand an abbreviation with space, it will have one extra space. which you can get rid of by using a <BS> (backspace) in the abbreviation. Or expand with <C-]> which will leave no space.
Correction: since the abbreviation is first expanded, and after that the space inserted, you need a small function found in the help (map.txt):
func Eatchar(pat)
let c = nr2char(getchar(0))
return (c =~ a:pat) ? '' : c
endfunc
This is best put in .vimrc. Now the following abbreviation will work fully as intented:
:iabbrev <silent> <? <?=?><Left><Left><C-R>=Eatchar('\s')<CR>
It is a bit messy, but has an external function call that removes the white space and it should work well.
What you want are snippets. I use snipmate for that.
It can be done with lh-map-tools:
"
" in {rtp}/ftpluvin/vim/vim_snippets.vim
inoreab <buffer> <silent> if
\ <C-R>=InsertSeq('if', 'if!cursorhere!\nendif!mark!')<CR>
Other plugins offer a similar feature.