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.
Related
I'm a C# developer and I'm new to using Vim. I'm curious, what would you put in your .vimrc file so that when you type a curly brace and hit Enter, like this:
public void Foo() {<Enter>
that brace gets put on a new line, and the caret moves to the innards of the braces, like this:
public void Foo()
{
|
}
Any help would be appreciated, thanks!
Your question is very close to auto-close plugin issuse with curly brackets where
inoremap <expr> <cr> getline(".")[col(".")-2:col(".")-1]=="{}" ? "<cr><esc>O" : "<cr>"
answers the question -- this is somewhat what I use in lh-brackets.
Here, it seems you aren't using any bracketing plugin. The text to search becomes '\S\s*{$', and you can insert instead: <BS><cr>{<cr>}<esc>O, or just {<cr>}<esc>O if there is only { on the line. If the cursor is within {}, you should also integrate the previous test.
This becomes:
inoremap <expr> <cr>
\ getline(".") =~ '\S\s*{$' ? "<bs><cr>{<cr>}<esc>O"
\ : getline('.') =~ '^\s*{$' ? "<cr>}<esc>O"
\ : getline(".")[col(".")-2:col(".")-1]=="{}" ? "<cr><esc>O"
\ : "<cr>"
There are a lot of ways to program this. Just as an example I might do this:
inoremap {<Cr> <Esc>:call AutoBracketDrop()<Cr>a
function! AutoBracketDrop()
if col('.') == col('$') - 1
substitute /\s*$//
exec "normal! A\<Cr>{\<Cr>X\<Cr>}\<Esc>k$x"
else
exec "normal! a{\<Cr>\<Esc>"
endif
endfunction
First I add a insert map that will break out of insert and call the AutoBracketDrop function and when finished enter back into insert mode.
The function simply checks to see if the cursor column matches the last column of the line. If so we remove the trailing whitespace and append the test:
cursor is here>
{
X
}
Because the use of <Cr> it should keep the indentation as if you typed them. We have to have a marker X otherwise Vim will remove whitespace from the empty line and continuing with an append (a) will loose the indentation. This way the text ends up as:
cursor was here>
{
X
}
Then we move the cursor up a line, delete the X and exit the function.
In the case of it being in the middle of the line we just simple recreate the characters typed that were used to trigger the mapping.
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>'
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>
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?
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>'.