Make Vim Curly Braces, Square Braces, Parens act like Textmate - vim

So I guess I'm not searching for the right thing but I'm looking to see how you can get VIM to act like Textmate when it comes to writing a set of curly braces, parens, or square brackets hit enter and you get this. Pipe indicates cursor.
function doSomething(){
|
}
#selector{
|
}
Instead of this garbage
function doSomething(){
|}
#selector{
|}
I already have the [{( closing each other when they are typed just the return and indentation is jacked. As usual any help would be appreciated.

I use the following mappings in my .vimrc:
inoremap {<cr> {<cr>}<c-o>O<tab>
inoremap [<cr> [<cr>]<c-o>O<tab>
inoremap (<cr> (<cr>)<c-o>O<tab>
So when I input:
function foo(){<cr>
I get:
function foo(){
|
}
Similar with (<cr> and [<cr>.

A note to delimitMate users
When using the delimitMate plugin, the mappings of the other answers interfere with the plugin. Luckily, this behavior is already available in delimitMate (but disabled by default), by setting the delmitMateExpansion options. E.g. add
let delimitMate_expand_cr = 1
to your .vimrc

This is my modification of Randy Moris' answer that works better for me:
inoremap {<cr> {<cr>}<c-o><s-o>
inoremap [<cr> [<cr>]<c-o><s-o>
inoremap (<cr> (<cr>)<c-o><s-o>

My solution for this was to put this little function (with corresponding insert-mode mapping) in my .vimrc:
fun! MyCR()
if strpart(getline('.'), col('.') - 2, 2) == '{}'
return "\<CR>\<CR>\<Up>\<Tab>"
endif
return "\<CR>"
endfun
autocmd FileType c,cpp inoremap <CR> <C-R>=MyCR()<CR>
You can change the autocmd so that it will work for your preferred file types.
It remaps <CR> in insert mode to check if the cursor is currently inside curly braces and adds the extra line and indentation where appropriate.

If you like Text make you should check Vim plugin, snipMate, as indicated by tarek11011.
For C/C++ it has by default a snippet for functions
# Function
snippet fun
${1:void} ${2:function_name}(${3}) {
${4:/* code */}
}
, which would solve the curly braces issue.

I have the following on my .vimrc
imap {<Space> {<Space><Space>}<left><left>
imap { {<CR>}
imap {<CR> {<CR><CR>}<Up>;<Esc>==i
imap ( ()
imap () ()
inoremap <silent> (. ().<C-x><C-o>
inoremap <silent> (- ()-><C-x><C-o>
imap (<space> (<space><space>)<left><left>
imap [ []
imap [<space> [<space><space>]<left><left>
inoremap " ""<left>
inoremap "" ""
ok, explanations:
when you hit {, sometimes you want to break a line and put and ending }, but sometimes you just want to stay in the same line, just like: a = {1,2,3};
# means where the cursor is:
So when you hit { and just after that you hit space -> { # }
when you hit { after a little delay or any other than space is used the line will be break
when you hit { just after an enter, the code will be:
foo(){
#
}
When you hit (. results in ().<call to omnicomplete> Just line namespace::Singleton::Create().
You have to use inoremap with ", to avoid infinite """""""""""""""""""""""

I have set ai in my vimrc which I believe does what you want?

Related

How to autocomplete per conditions in vim?

When coding in vim, I add autocomplete for "{(' in vimrc as below:
inoremap " ""<ESC>i
inoremap ' ''<ESC>i
inoremap { {<Cr>}<Esc>O
inoremap ( ()<ESC>i
But I find it's quite annoying to add an additional semicolon ; manually in the end of a function call or expression.
Example 1: print("hello world"); => autocomplete should be ); when input (
Example 2: if (true) or while (true) => autocomplete should be only ) when input (
When inputting a single (, how to autocomplete correctly for both example 1 and example 2? My focus here is whether there are some easy ways to add if/else for key mapping.
It could be a pretty challenging task to handle all the options properly. But if all you ask is just a simple and very incomplete example code then, perhaps, this small snippet could be of some help:
inoremap <expr>( Paren()
function! Paren() abort
return printf("()%s\<Left>",
\ search('\v(if|while)\s*%#', 'bn', line('.')) ? "" : ";\<Left>")
endfunction
The idea is to match the current line (just before the cursor) against regex. Depending on the result, we build an expression to be inserted.
See :h search(), :h :map-expression etc.

What vim plugin does leetcode use to auto-close parenthesis?

I like the way leetcode vim auto close braces.
It closes when I type " ' ( { [ which can be done with simple vim map
When I try to close one more tim it doesn't add another " ' ) } ] and skip. Most vim plugin works like this.
When I press { and enter, it automatically add new line for my code and indent for me.
To be specific
{<cursor>}
when I press enter, it becomes
{
cursor
}
I don't know which plugin works like leetcode vim.
Plus, what is some vanilla vim way to solve 2nd issue?
I tried to analyze by looking at plugins but it was too complicated.
These vanilla vim mapping will do what you are looking for, especially the last two is interesting.
inoremap " ""<left>
inoremap ' ''<left>
inoremap ( ()<left>
inoremap [ []<left>
inoremap { {}<left>
inoremap {<CR> {<CR>}<ESC>O
inoremap {;<CR> {<CR>};<ESC>O
This autocomplete in insert mode, provided set paste is not set. When we don't want the mapping, we need to escape it using ctrl + v before typing the mapped char like ( { etc.
#dlmeetei's answer would print ()) when I type (), and escape mapping would be burdensome.
So, I improved the answer above, by creating a simple function, so please correct and improve my idea.
"" check whether current charcter (on cursor) equals parameter
"" then decide whether to put new parenthesis
func! AutoClose(...)
let cur = getline(".")[col(".")]
if cur != a:1
if a:1 == "'" || a:1 == '"'
execute "normal!a".a:1.a:1
else
execute "normal!a".a:1
endif
execute "normal!h"
else
execute "normal!l"
endif
endfunc
inoremap ( ()<left>
inoremap [ []<left>
inoremap { {}<left>
inoremap ) <ESC>:call AutoClose(')') <CR>a
inoremap ] <ESC>:call AutoClose(']') <CR>a
inoremap } <ESC>:call AutoClose('}') <CR>a
inoremap " <ESC>:call AutoClose('"') <CR>a
inoremap ' <ESC>:call AutoClose("'") <CR>a
inoremap {<CR> {<CR>}<ESC>O
inoremap {;<CR> {<CR>};<ESC>O

Vim smart insert semicolon

Is there a Vim plugin that can handle smart semicolon insertion, like the one in Eclipse?
Example (pipe character is insertion cursor):
foobar(|)
I type a semicolon:
foobar();|
Similarly:
foobar("blah|")
I type a semicolon:
foobar("blah");|
If I want a semicolon at the original cursor position, I press backspace after the smart re-position:
foobar("hello|")
foobar("hello");|
foobar("hello;|")
I use this mapping:
inoremap <leader>; <C-o>A;
It's not ; because I use semicolons often and in more than one context.
<C-o> is used to input a single normal mode command.
A; means "add a ; at the end of the line".
I want to do the same thing, I works on it whole night, tons of code, but at last, I got a simple solution.
inoremap ;<cr> <end>;<cr>
and if I am in a brace, I want to add a semicolon or a dot at the end, like this
foo({
|
})
I press ;;<cr> or ..<cr> to do this
inoremap ;<cr> <end>;<cr>
inoremap .<cr> <end>.
inoremap ;;<cr> <down><end>;<cr>
inoremap ..<cr> <down><end>.
You should try Cosco.vim plugin.
For vscode vim users:
"vim.insertModeKeyBindings": [
{
"before": [";", ";"],
"after": ["<Esc>","A",";"]
},
],
I was inspired by romainl's answer above, but <C-o> seems have a switch problem in vocode vim, so just use <Esc> will work.
I use the following function and a mapping to insert a semicolon to the end of the line and to delete the remaning spaces:
imap <leader>. <C-R>=Semicolonfun()<CR>
fun! Semicolonfun() "{{{
call setline(line('.'), substitute(getline('.'), '\s*$', ';', ''))
return "\<End>"
endfunction "}}}
So if you have something like:
log.warning("you miss the |identifier")
Pressing . or ,. if you remap the leader, you get the following:
log.warning("you miss the identifier");|
inoremap <expr> ;<cr> getline('.')[-1:] == ';' ? '\<Nop>' : '<End>;<CR>'
The code above will check if there is ; at the end of the line.
If ; not exists, then it will add ; otherwise do nothing.
" ftplugin/c/c_snippet.vim
inoremap <expr> <buffer> ; getline('.')[col('.')-1:-1]=~')$' ? '<right>;' : ';'
This version shall not pose problems with for if your snippets engine expands it into
for (...|) {
<+code+>
}<++>
If the open bracket is on a newline, it will mess things up.
You could easily change the regex to '"\=)\+$' to answer your initial question.
inoremap <expr> <buffer> ; getline('.')[col('.')-1:-1]=~'"\=)\+$' ? '<end>;' : ';'
However, I don't think it's a good idea. In that case, the mapping for <bs>will be:
inoremap <expr> <buffer> <bs> getline('.')[:col('.')-2] =~ '.*")\+;$' ? '<bs><c-o>F";' : '<bs>'

Vim magic closing bracket

It would be great in vim if I could type ] (or some other character, maybe <C-]>) and have it automatically insert whichever bracket properly closes the opening bracket. Eg. if I have this in my buffer:
object(function(x) { x+[1,2,3
And I press ]]], the characters ]}) would be inserted. How might one accomplish this this?
Here's a sketch of what you probably wanted. The builtin functions searchpair and searchpairpos are of enormous help for various text editing tasks :)
" Return a corresponding paren to be sent to the buffer
function! CloseParen()
let parenpairs = {'(' : ')',
\ '[' : ']',
\ '{' : '}'}
let [m_lnum, m_col] = searchpairpos('[[({]', '', '[\])}]', 'nbW')
if (m_lnum != 0) && (m_col != 0)
let c = getline(m_lnum)[m_col - 1]
return parenpairs[c]
endif
return ''
endfun
To use it comfortably, make an imap of it:
imap <C-e> <C-r>=CloseParen()<CR>
Edit: over-escaped the search regexp so \ got included in the search. One less problem now.
Combined with the autoclose plugin, you can set:
imap <c-l> <c-o>l
Autoclose will insert the matching bracket, then ctrl-L will skip over it without leaving insert mode. Ctrl-L makes more sense to me than ctrl-].
This is as close as I can get to what I'd say you're asking for: "let me just press the same key every time to skip entering the correct bracket, no matter what that bracket is". I'd not imap ] (without modifier) to this, but there's nothing stopping you if you want to try it out.
You can add that to your .vimrc and it will autoclose brackets
inoremap ( ()<Left>
inoremap [ []<Left>
inoremap { {}<Left>

Auto insert text at a newline in vim

I am editing a LaTeX file with vim. When I am in the \begin{itemize} environment, is there any way to tell vim to autoinsert \item whenever I open a new line?
function CR()
if searchpair('\\begin{itemize}', '', '\\end{itemize}', '')
return "\r\\item"
endif
return "\r"
endfunction
inoremap <expr><buffer> <CR> CR()
Put this into your .vim/ftplugins/tex.vim file (or any .vim inside .vim/ftplugins/tex directory).
I would recommend http://vim-latex.sourceforge.net. This package defines several maps useful for latex.
In particular for inserting \item you press <ATL-I>
I know noting about latex but I think it is a good idea to search in vim scripts
use the search button up left :D
for example search for
latex auto completion
I can hit Cntl-I and it'll put it in for me in either normal mode or insert mode. This is what I put in my .vimrc:
:imap <C-i> \item
:nmap <C-i> o\item
Note that there is a space at the end of \item.
I hacked the script ZyX supplied and came up with this. It adds support for the o and O commands. It does not require LaTeX-VIM.
function AddItem()
if searchpair('\\begin{itemize}', '', '\\end{itemize}', '')
return "\\item "
else
return ""
endif
endfunction
inoremap <expr><buffer> <CR> "\r".AddItem()
nnoremap <expr><buffer> o "o".AddItem()
nnoremap <expr><buffer> O "O".AddItem()
Extended Version of Answer by Samad Lotia and ZyX
Place this in your ~/.vim/after/ftplugin/tex.vim
function! AddItem()
let [end_lnum, end_col] = searchpairpos('\\begin{', '', '\\end{', 'nW')
if match(getline(end_lnum), '\(itemize\|enumerate\|description\)') != -1
return "\\item "
else
return ""
endif
endfunction
inoremap <expr><buffer> <CR> getline('.') =~ '\item $'
\ ? '<c-w><c-w>'
\ : (col(".") < col("$") ? '<CR>' : '<CR>'.AddItem() )
nnoremap <expr><buffer> o "o".AddItem()
nnoremap <expr><buffer> O "O".AddItem()
Improvements
auto-insert of \item also happens for environments enumerate and description
auto-insert of \item only happens if the immediate surrounding environment is one of the three (itemize/enumerate/description). It does not happen in following circumstance
\begin{itemize}
\item
\begin{minipage}
<CURSOR>
\end{minipage}
\end{itemize}
auto-insert of \item only happens if you are at the end of the line
deletion of auto inserted \item by pressing <CR> a second time. If one wants to add some indention in this case, change '<c-w><c-w>' to '<c-w><c-w><c-t>'.

Resources