How to insert at the very left of the line in vim? - vim

Imagine I am editing this code in vim, and wish to comment out the bar(); line:
while (foo()) {
bar();
baz();
}
If I press I# while on that line, I get this:
while (foo()) {
#bar();
baz();
}
However, our coding standards say I should have done this:
while (foo()) {
# bar();
baz();
}
I can work around this by pressing 0i# instead (or even putting map I 0i in my .vimrc for a more permanent fix) but this is not repeatable with . as it just repeats the i rather than the 0i.
Many other editors have options to make Home not be "smart" and just go to column 0 rather than trying to work with the indentation. I've tried searching the docs, but have drawn a blank — is there a way to do this in vim?
Alternatively, is there a way to make the bound command atomic, so that repeating it with . repeats the whole thing rather than the last command of the bound sequence?
Thanks

Use gI instead of I.
From :help gI :
gI
gI Insert text in column 1 [count] times. {not in Vi}

You're looking for the gI command. In the excellent and comprehensive help, you would have found that just below the entry for :help I.

What you really want is a commenting plugin like commentary (which I use), Nerd Commenter, EnhCommentify, tComment, ..., etc. However from what I can tell only EnhCommentify has an option to respect indention or not (g:EnhCommentifyRespectIndent).
If you already have a commenting plugin that you like and it doesn't work the way you like I suggest you open an issue via the plugin's issue tracker and request the option.
If you want to skip the plugin then you use these quick n' dirty mappings inspired by commentary:
nnoremap <expr> gcc getline('.') =~ '^#' ? '0"_xw' : "gI#\<esc>w"
xnoremap <expr> gc ':norm! ' . (getline("'<") =~ '^#' ? '0"_x' : "gI#") . "\<cr>"

Use the home key to go to the beginning of the line and then insert

Related

Delete specific lines above current line in vim normal mode? [duplicate]

I have a mapping in my vimrc that downwardly comments out regions of c code:
nmap comc :normal! I//<ESC>
Since the 'normal' ex command implicitly converts input such as "Ncomc" to ".,.+N-1 comc", I can range comments downwardly without many keystrokes and without leaving normal mode. This is, however, a very limited subset of what vim ranges can do. If I'm willing to be verbose, I can achieve upward ranging comments like so:
.,.-5 normal comc
While editing text, I would much prefer to type something like "-6comc" or make a mapping of "Comc" that uses upward ranges. I'm haven't been able to do so successfully.
Similarly, range operations support commenting until a search pattern is reached, e.g :
.,/int main/ comc
I would, however, like to do so without all that typing.
The behavior you requested is normally done with :h map-operator mapping. With this commenting 3 lines down will turn into comc2j though, but 3 lines up is now just as easy: comc2k.
You can also use visual mode without changing your mapping at all: V2kcomc. You will have to add xnoremap with the identical lhs and rhs because nnoremap works only for normal mode. (And do not use nmap.)
Third option is mapping - to something that moves {count} lines up and puts count back:
nnoremap <expr> - (v:count ? ":\<C-u>\n" . (v:count-1) . 'k' . v:count : '')
. This assumes you are writing 6-comc, not -6comc.
// By the way, I would suggest The NERD Commenter if it comes to the plugin.
While it's commendable to go as far as possible without any plugins, sometimes they're just the best option. What will you do when you start working in a language that has comments with # or (*...*)? Add new mappings for these comment characters?
I recommend commentary.vim which does filetype-aware commenting.
The default commenting operator in commentary.vim is gc. You can combine it with motions, and use it in Visual mode too.
Your use cases:
Comment downwards N lines (say, 3): :.,.+3normal gcc, or gc3j or 4gcc.
Comment upwards 5 lines: :.,.-5normal gcc, or simply gc5k.
Comment until int main: :.,/int main/-1normal gcc, or simply gc/int main followed by Enter.

insert something in front of and in end of some word

I have many many source code files, and have to do many same work like this
find some phrase(totally random, have to be done by human eyes)
for example asdf in this line printf("asdf")
and fdsa asdf asdf in this line "* fdsa asdf asdf |"
insert ${' in front of the phrase, and '} in end of the phrase
so printf("asdf") becomes printf("${'asdf'}")
I'm currently using vim to do the edit, is there any plugin can let me, for example, move the cursor onto asdf and press ctrl+shift+i to automatically insert ${' and '} ?
Also I'm open to switch to any other editor which has such capability.
You don't need a plugin for that. A simple mapping would be enough:
xnoremap <key> c${'<C-r>"'}<Esc>
See :h key-notation for <key>.
The :substitute command would have been a great solution as well:
:%s/asdf/${&}/g
And if you want to confirm each replacement before doing it, add the c flag -> %s/asdf/${&}/gc
In addition to the great answers using built-in commands, there's one "famous" plugin for this purpose: the surround plugin. It comes with many mappings for common stuff, and also is customizable.
To define a ysv (you surround variable) mapping, just put the following into your ~/.vimrc:
let g:surround_118 = "${\r}"
(118 is the code point for v, see :help surround)

How to imap a character in Vim based on previous character

I have created the following mapping to simulate behaviour in some IDEs where when you insert { after a function declaration like foo() a closing } and empty row is inserted automatically and cursor is set to the empty row on tabbed position.
:imap { {<CR><CR>} <up><Tab>
This of course does this behavior when I insert { in any context. How do I do it based on the previously inserted character? Must be a vim script function involved?
Note: I do not want to use external vim plugins.
IDEs usually do this expansion after typing {<CR>, which is easy to do in vimscript:
:imap {<CR> {<CR><CR>} <up><Tab>
This will not expand if you keep on typing other things on the same line.
The caveat is that there's a small delay when typing a { with this mapping. See the 'timeout' and 'timeoutlen' options for details.
These code snippets give you the character just before and just after the cursor when in insert mode:
let previous_character = getline(".")[col(".")-2]
let next_character = getline(".")[col(".")-1]
You can use them in an <expr> mapping:
:inoremap <expr> { getline(".")[col(".")-2] == " " ? "{^M}^OO" : "{"
The pointless mapping above checks if the character before the cursor is a space before deciding if it inserts a { or an expanded {}.
If you want a "smart" mapping you won't be able to avoid writing one or more functions. The one I use, for example, is 69 lines long.
You'll find multiple approaches and a list of plugins on the Automatically append closing characters Vim Tips Wiki page. Note that though there are simplistic solutions, they usually have some downsides, and the whole approach is unfortunately broken in Vim 7.4 with regards to undo.

Advanced Usage of Ranges with Vim Keymappings

I have a mapping in my vimrc that downwardly comments out regions of c code:
nmap comc :normal! I//<ESC>
Since the 'normal' ex command implicitly converts input such as "Ncomc" to ".,.+N-1 comc", I can range comments downwardly without many keystrokes and without leaving normal mode. This is, however, a very limited subset of what vim ranges can do. If I'm willing to be verbose, I can achieve upward ranging comments like so:
.,.-5 normal comc
While editing text, I would much prefer to type something like "-6comc" or make a mapping of "Comc" that uses upward ranges. I'm haven't been able to do so successfully.
Similarly, range operations support commenting until a search pattern is reached, e.g :
.,/int main/ comc
I would, however, like to do so without all that typing.
The behavior you requested is normally done with :h map-operator mapping. With this commenting 3 lines down will turn into comc2j though, but 3 lines up is now just as easy: comc2k.
You can also use visual mode without changing your mapping at all: V2kcomc. You will have to add xnoremap with the identical lhs and rhs because nnoremap works only for normal mode. (And do not use nmap.)
Third option is mapping - to something that moves {count} lines up and puts count back:
nnoremap <expr> - (v:count ? ":\<C-u>\n" . (v:count-1) . 'k' . v:count : '')
. This assumes you are writing 6-comc, not -6comc.
// By the way, I would suggest The NERD Commenter if it comes to the plugin.
While it's commendable to go as far as possible without any plugins, sometimes they're just the best option. What will you do when you start working in a language that has comments with # or (*...*)? Add new mappings for these comment characters?
I recommend commentary.vim which does filetype-aware commenting.
The default commenting operator in commentary.vim is gc. You can combine it with motions, and use it in Visual mode too.
Your use cases:
Comment downwards N lines (say, 3): :.,.+3normal gcc, or gc3j or 4gcc.
Comment upwards 5 lines: :.,.-5normal gcc, or simply gc5k.
Comment until int main: :.,/int main/-1normal gcc, or simply gc/int main followed by Enter.

mapping # in vim

In my .vimrc I have mapped the #-key to a macro for commenting out/in lines of code.
Unfortunately # in vim already has a function - it searches backwards for the word beneath the cursor.
What I would now like to have is a way to map this functionality to another key-sequence (ideally I would like to have Control-* for that as * alone searches forward).
Does anyone know how to achieve this?
Many thanks!
Unfortunately, Ctrl + * cannot be used; I would propose \*; it's longer to type, but backwards searches are probably not that common.
:nnoremap <Leader>* #
Like Ingo Karkat said, mapping Ctrl+certain keys is impossible in vim. However, you can map Alt+8 instead:
noremap <A-8> #
I suggest Alt+8 instead of Alt+* because if you wanted to bend your hand in unnatural ways to press more than one modifier keys to perform a command, you would probably be using Emacs instead of Vim.
I use \+c for commenting and \+d for removing comments. The mappings are following :
:map \c <ESC>:s,^\(\s*\)[^/ \t]\#=,\1// <ESC>,e<CR>j$a
:map \d <ESC>:s,^\(\s*\)// \s\#!,\1<ESC>,e<CR>j$a
Above mappings are used in command mode. Taken from one answer on SO, which I am currently unable to find.

Resources