VIM: command to clear current line and drop into insert mode - vim

I am in normal mode, at the end of a line. I want to clear the line (delete all characters of the line), and drop into insert mode so that I can start writing something else on that line. Is there a Vim shortcut for this?
Ideally, I would like to preserve the leading whitespaces on the line, but even if I can't that should be fine.

You can use S or cc to do that (synonyms). They will keep your indentation if the autoindent option is on. Both can accept an optional count if you want to remove multiple lines.

You're looking for :help cc. Without a [count], cc deletes the entire current line and goes into insert mode. Works from anywhere in the line, not just at the end. Depending on your intent settings, that will be preserved, too.
Possible alternatives: A<C-u>, or ddO.

I do not know the shortcut. But just to add, we can do this normally by using first "dd" to delete the line and pressing "o" to enter into insert mode for the deleted line.

Related

Vim: Select all without scrolling away

is it possible in vim to select all lines in the current file, but leave the position where my cursor is unchanged?
Let's say I am currently at line 500 (of 3000) and want to quickly select everything (not yank), as my selection is simply set up to show whitespace characters. Can this be done without leaving my current line?
To achieve exactly what you like, you can press the following:
ggVG<Esc><Ctrl-O><Ctrl-O>
gg moves to the beginning of the file
V starts visual line mode
G moves to the and of the file (now you have selected the whole
file)
<Esc> leaves visual mode
<Ctrl-O> moves your cursor back to the prevois location (first to the beginning of the file, then the second time to your last position before pressing gg)
And if you like to select only the visible lines in you window (to not scroll away). You can use HVL instead of ggVG (H moves to the top of your window and L to the bottom).
You also could show whitespaces without using visual selection with something like this in your .vimrc:
set list listchars=tab:»·,trail:·,nbsp:·
This helps me to detect trailing whitespaces, and mixed (spaces/tabs) indentation.
usually pressing
ggVG
in normal mode will select all the lines, but it will leave your cursor at the last line of the file.
If you wants to highlights the whitespace characters then you can highlight this by using the below command in command mode (this white color chosen is for dark theme)
: hi ExtraWhitespace ctermbg=White guibg=White
Depending on what you are trying to achieve you can use something like :
%cmd
To apply the command to the whole file.
For example, %y will yank the whole file, %=will format the whole file, without moving your cursor. It does not really work if you do something like %d...
It is not a real selection though but rather a way to apply a command on the whole file.
To go further you can use something like
%norm Atest
To add 'test' at the end of each line. (Actually this is a bad example, because this command will move to the last line...)
It is not possible to have the cursor inside a visual selection. This caused by that, vim defines visual selection through two marks. As soon as you move the cursor one of the marks gets updated. Basically this means one of the marks is always lays where the cursor is(at least when using "v" to select). You cannot have the border in the middle of the region that the border defines :)

Duplicating line in Vim and appending few letters

I am editing a dictionary in a text file, containing Russian words - one word per line.
Some nouns are missing their derivatives, which are usually the same word appended by few more letters - in 6-7 variations as shown in this screenshot:
In Vim I would like to put the cursor in the first column and scroll down line by line. And when I recognize a noun, I'd like to press some (as few as possible!) keystrokes to take that word, copy it in separate lines and append the letters.
I can get rid of the duplicates by issuing %sort u later.
If I could run that command on the whole file it would be something like:
%s/\(.\+\)$/\1^M\1а^M\1ам^M\1ами^M\1ах^M\1е^M\1ном^M/
Do you please have an idea, how to create such a "macro" in Vim?
There are a couple of ways that you can handle this. You can create a macro or you can create a map. Either can be done while running VIM. Either can be placed in another file (your .vimrc, for example, or a file with bindings specific to this project) and sourced when needed.
I will also give you a bit more advice with regular expressions: if you are writing something particularly complex, you can greatly decrease the number of \s needed by starting the regular expression with \v (i.e., :s/\v([0-9a-f]+\s)/0x\1/g).
Creating a Macro in VIM
You can start a macro in VIM by pressing q in Normal mode, followed by the key that you wish to use for the macro. You can then invoke the macro by pressing # followed by the macro's letter. Press q again in Normal mode to stop recording.
You can therefore enter this macro as follows (using the q register):
qq:s/\(.\+\)$/\1\r\1а\r\1ам\r\1ами\r\1ах\r\1е\r\1ном\r/Enterq
Then, when you are on a line and you want to run this command, enter #q from Normal mode.
Storing a macro in a file and sourcing it
When you created a macro in the last step, what you were actually doing was setting the q register. You can check this by entering the registers in command mode. You can instead set this macro in your .vimrc file as follows and it will be available every time you start VIM.
Create the file you want to store this macro in (:new).
Add the following line to the file:
let #q=":s/\\(.\\+\\)$/\\1\\r\\1a\\r\\1b\\r\\1ам\\r\\1ами\\r\\1ах\\r\\1е\\r\\1ном\\r/^M"
(If you yank the line and paste it in VIM with Ctrl+R", there will be a proper ^M character at the end of the line. You'll need to do some manual editing to make sure that it's inside the quotes. Alternatively, you can enter Ctrl+VCtrl+M to enter the ^M character.)
Save the file (:w testmacro.vim).
Source it (:so % or :source %).
Test your macro by typing #q on one of the lines you'd like to do this to.
Later, you will be able to load this macro by running :so testmacro.vim.
Create a Mapping
You can instead create a mapping. The following mapping copies the last word in a given line, pastes it onto the following six lines, and then appends to each of the given lines.
nnoremap <c-j> yy6pAа<esc>jAам<esc>jAами<esc>jAах<esc>jAе<esc>jAном<esc>j
n at the beginning of "nnoremap" indicates that it only functions in Normal mode.
noremap means that this command won't engage in any recursive remapping (whereas with nmap, this could happen).
<c-j> maps to Ctrl+J
yy6p yanks the line and pastes it 6 times.
Aa<esc>j appends to the end of the current line, enters the text (in this case a), exits Insert mode, and moves down a line.
You can enter this command in VIM's command mode or you can store it in a file and load it with the :source command.
Combining Registers with Mappings
You can access a register in your mappings. This means that if you know that entering a given replacement regex will do what you want, you can save that in a register and then enter your command on the current line.
To do this, enter the following commands in a file and then source it:
nnoremap <c-i> :<c-r>f<cr>
let #f="s/\\(.\\+\\)$/\\1\\r\\1a\\r\\1b\\r\\1ам\\r\\1ами\\r\\1ах\\r\\1е\\r\\1ном\\r/^M"
Now you can enter Ctrl+I to run the replacement regex in register f on the current line.
Alternatively, dedicate a few registers to the purpose - let's say a-f.
nnoremap <c-l> yy6p$"apj"bpj"cpj"dpj"epj"fpj
let #a="a"
let #b="ам"
let #c="ами"
let #d="ax"
let #e="e"
let #f="ном
In this case, we're using the ability to press " and the name of a register before hitting a command that uses it, such as paste.
You can record macros by pressing q in the escape mode. For example,
position your cursor on the noun you want to edit.
press qa to start recording macro and store it in register a (other alphabet and digits may also be used for registers) .
do whatever general actions you want to do (copy line, paste, append letters, etc. as in you have tried to show in your search string).
once you are done with the changes, in escape mode press q again.
Your macro is now created in register a. Whenever, you want to repeat your key sequences, just press #a.
Note that you can do anything in recording mode, including any kinds of commands, insertions, cursor movements, and so on. For more information on macros and related options, check out Vim help :h complex-repeat.
Vim registers are shared as place holders for both macros and yanked test; this feature allows you to even save and edit your macros in a file. See this question for details.
Here is a map solution - which copies the line into a buffer and then pastes using p.
The A appends at the end of the line
map <F2> 0dwpo<esc>pAa<enter><esc>pAam<enter><esc>pAax ...etc
If your goal is, when your cursor on a special word, and press something, vim will append different "suffixes" (I hope I used the right word, but you knew what I mean). You could go macro (q). However since you have already written the :s command, you could create a mapping using that command do the same, and it would be shorter.
in command line, you can get the word under cursor by pressing <c-r><c-w>. so you could try:
nnoremap <leader>z :s/<c-r><c-w>/& & &..../<cr>
I didn't write the & & &... part, since I don't know (never tried, I don't have vim under windows. I don't even have windows) if the line break \n could be used here under windows. & means the whole matched part, which in this case is the word under your cursor.
So you just move your cursor to the word, type <leader>z, vim will do the job for you. (if the replacement part is correct :) ).

Vim: Smart indent when entering insert mode on blank line?

When I open a new line (via 'o') my cursor jumps to a correctly indented position on the next line. On the other hand, entering insert mode while my cursor is on a blank line doesn't move my cursor to the correctly indented location.
How do I make vim correctly indent my cursor when entering insert mode (via i) on a blank line?
cc will replace the contents of the current line and enter insert mode at the correct indentation - so on a blank line will do exactly what you're after.
I believe that the behaviour of i you describe is correct because there are many use cases where you want to insert at that specific location on a blank line, rather than jumping to wherever vim guesses you want to insert.
Well this actually wasn't as bad as I thought it would be. One way to enable this is to add the following to your ~/.vimrc
"smart indent when entering insert mode with i on empty lines
function! IndentWithI()
if len(getline('.')) == 0
return "\"_ccO"
else
return "i"
endif
endfunction
nnoremap <expr> i IndentWithI()
It simply checks for an empty line when you hit 'i' from insert mode. If you are indeed on an empty line it will delete it and open a new one, effectively leveraging the working 'open line' behavior.
Note: "_ before the cc makes sure that your register doesn't get wiped
On an empty line, to enter insert mode correctly indented, you can simply use s.
Note that s is a synonym for cl, so if you're not actually on an empty line, it'll end up deleting a single character and not indenting. In that case, you're better off using cc, as sml suggested some 18 months ago. But I've frequently improved my score at VimGolf by using this shortcut, so thought I'd mention it. ;)

How do I insert a linebreak where the cursor is without entering into insert mode in Vim?

Is possible to insert a line break where the cursor is in Vim without entering into insert mode? Here's an example ([x] means cursor is on x):
if (some_condition) {[ ]return; }
Occasionally, I might want to enter some more code. So I'd press i to get into insert mode, press Enter to insert the line break and then delete the extra space. Next, I'd enter normal mode and position the cursor before the closing brace and then do the same thing to get it on its own line.
I've been doing this a while, but there's surely a better way to do it?
For the example you've given, you could use rEnter to replace a single character (the space) with Enter. Then, fspace. to move forward to the next space and repeat the last command.
Depending on your autoindent settings, the above may or may not indent the return statement properly. If not, then use sEnterTabEsc instead to replace the space with a newline, indent the line, and exit insert mode. You would have to replace the second space with a different command so you couldn't use '.' in this case.
A simple mapping to break the line at the cursor by pressing Ctrl+Enter:
:nmap <c-cr> i<cr><Esc>
essentially enters 'insert' mode, inserts a line break and goes back to normal mode.
put it in your .vimrc file for future use.
Here's how to create a macro that inserts a newline at the cursor whenever you press 'g' while not in insert mode:
From within vim, type:
:map g i[Ctrl+V][Enter][Ctrl+V][Esc][Enter]
Where:
[Ctrl+V] means hold the Ctrl key and press 'v'
[Enter] means press the Enter key
[Esc] means press the Esc key
You'll see the following at the bottom of your vim window until you press the final Enter:
:map g i^M^[
Explanation:
[Ctrl+V] means "quote the following character" -- it allows you to embed the newline and escape characters in the command.
So you're mapping the 'g' key to the sequence: i [Enter] [Escape]
This is vim for insert a newline before the cursor, then exit insert mode.
Tweaks:
You can replace the 'g' with any character that's not already linked to a command you use.
Add more to the command, e.g. f}i^M^[O -- This will find the } and insert another newline, then escape from insert mode and Open an empty line for you to enter more code.
You can add the command to your .vimrc or .exrc file to make it permanent. Just omit the colon from the beginning, so the command starts with "map"
Enjoy!
If you're usually expanding a one line block to three lines, try substitution. Change the opening bracket into bracket/return, and the closing bracket into return/bracket.
The command for substituting bracket/return for bracket looks like this:
:s/{/{\r/
Since you want to use this often, you could map the full sequence to an unused keystroke like this:
:map <F7> :s/{/{\r/ ^M :s/}/\r}/ ^M
Where you see ^M in the sequence, type [Ctrl-V], then press enter.
Now with your cursor anywhere on your sample line, press the mapped key, and the carriage returns are added.
Check :help map-which-keys for advice on selecting unused keystrokes to map.
Assuming you're okay with mapping K to something else (choose a different key of your liking), and using marker ' as a temporary marker is okay why not do this?
:nmap K m'a<CR><Esc>`'
now pressing K in normal mode over the character after which you want the line break to occur will split the line and leave the cursor where it was.
Basically, when you split a line you either want to just insert a carriage return, or in the case that you're on a space, replace that with a carriage return. Well, why settle for one or the other? Here's my mapping for K:
"Have K split lines the way J joins lines
nnoremap <expr>K getline('.')[col('.')-1]==' ' ? "r<CR>" : "i<CR><Esc>"
I use the ternary operator to condense the two actions into one key map. Breaking it down, <expr> means the key map's output can dynamic and in this case hinges on the condition getline('.')[col('.')-1]==' ' which is the long winded way to ask vim if the character under the cursor is a space. Finally, the familiar ternary operator ? : either replaces the space with linebreak (r<CR>) or inserts a new one (i<CR><Esc>)
Now you have a lovely sister key map to the J command.
Vim will automatically kill any whitespace to the right of the cursor if you break a line in two while autoindent (or any other indentation aid) is enabled.
If you do not want to use any of those settings, use s instead of i in order to substitute your new text for the blank rather than just inserting. (If there are multiple blanks, put the cursor on the leftmost and use cw instead.)
In fact you need the following combined operations:
Press v to enter Visual Mode
Select the line you want to split
Press : to enter in Command Mode
s/\s/\r/g
Done
If you have the input:
aaa bbb ccc ddd
and want to output
aaa
bbb
ccc
ddd
You can use the command
f r<ENTER>;.;.
o ESC command will do it for you.
Set this key mapping in your vimrc
:map <C-m> i<CR><Esc>h
Then press Ctrl+m if you want to use it in your vim.
IMHO, the built-in mapping gs is not a useful mapping (put vim to sleep), one could use this for splitting:
nmap gs i<CR><ESC>
In Vrapper you can use gql which will split a line without entering insert mode, but may not always maintain indentation.
I found this to be the most faithful implementation of what I'd expect the opposite behaviour to J
nnoremap S i<cr><esc>^mwgk:silent! s/\v +$//<cr>:noh<cr>`w
It does the simplistic new line at cursor, takes care of any trailing whitespace on the previous line if there are any present and then returns the cursor to the correct position.
i <cr> <esc> - this is one of the most common solutions suggested, it doesn't delete non-whitespace characters under your cursor but it also leaves you with trailing whitespace
^mw - goto start of new line and create a mark under w
gk - go up one line
:silent! s/\v +$//<cr> - regex replace any whitespace at the end of the line
:noh<cr> - Clear any search highlighting that the regex might have turned on
`w - return the the mark under w
Essentially combines the best of both r<esc><cr> and i<cr><esc>
Note: I have this bound to S which potentially overwrites a useful key but it is a synonym for cc and since I don't use it as often as I do splits I am okay with overwriting it.
This mapping will break up any one-line function you have. Simply put your cursor on the line and hit 'g' in normal mode:
:map g ^f{malr<CR>`a%hr<CR>`a
This assumes that you have a space after the opening brace and a space before the closing brace. See if that works for you.

How to insert text at beginning of a multi-line selection in vi/Vim

In Vim, how do I insert characters at the beginning of each line in a selection?
For instance, I want to comment out a block of code by prepending // at the beginning of each line assuming my language's comment system doesn't allow block commenting like /* */. How would I do this?
Press Esc to enter 'command mode'
Use Ctrl+V to enter visual block mode
Move Up/Downto select the columns of text in the lines you want to
comment.
Then hit Shift+i and type the text you want to insert.
Then hit Esc, wait 1 second and the inserted text will appear on every line.
For further information and reading, check out "Inserting text in multiple lines" in the Vim Tips Wiki.
This replaces the beginning of each line with "//":
:%s!^!//!
This replaces the beginning of each selected line (use visual mode to select) with "//":
:'<,'>s!^!//!
Note that gv (in normal mode) restores the last visual selection, this comes in handy from time to time.
The general pattern for search and replace is:
:s/search/replace/
Replaces the first occurrence of 'search' with 'replace' for current line
:s/search/replace/g
Replaces all occurrences of 'search' with 'replace' for current line, 'g' is short for 'global'
This command will replace each occurrence of 'search' with 'replace' for the current line only. The % is used to search over the whole file. To confirm each replacement interactively append a 'c' for confirm:
:%s/search/replace/c
Interactive confirm replacing 'search' with 'replace' for the entire file
Instead of the % character you can use a line number range (note that the '^' character is a special search character for the start of line):
:14,20s/^/#/
Inserts a '#' character at the start of lines 14-20
If you want to use another comment character (like //) then change your command delimiter:
:14,20s!^!//!
Inserts a '//' character sequence at the start of lines 14-20
Or you can always just escape the // characters like:
:14,20s/^/\/\//
Inserts a '//' character sequence at the start of lines 14-20
If you are not seeing line numbers in your editor, simply type the following
:set nu
Another way that might be easier for newcomers:
some█
code
here
Place the cursor on the first line, e.g. by
gg
and type the following to get into insert mode and add your text:
I / / Space
// █some
code
here
Press Esc to get back to command mode and use the digraph:
j . j .
// some
// code
//█here
j is a motion command to go down one line and . repeats the last editing command you made.
And yet another way:
Move to the beginning of a line
enter Visual Block mode (CTRL-v)
select the lines you want (moving up/down with j/k, or jumping to a line with [line]G)
press I (that's capital i)
type the comment character(s)
press ESC
This adds # at the beginning of every line:
:%s/^/#/
And people will stop complaining about your lack of properly commenting scripts.
If you want to get super fancy about it, put this in your .vimrc:
vmap \c :s!^!//!<CR>
vmap \u :s!^//!!<CR>
Then, whenever in visual mode, you can hit \c to comment the block and \u to uncomment it. Of course, you can change those shortcut keystrokes to whatever.
Yet another way:
:'<,'>g/^/norm I//
/^/ is just a dummy pattern to match every line. norm lets you run the normal-mode commands that follow. I// says to enter insert-mode while jumping the cursor to the beginning of the line, then insert the following text (two slashes).
:g is often handy for doing something complex on multiple lines, where you may want to jump between multiple modes, delete or add lines, move the cursor around, run a bunch of macros, etc. And you can tell it to operate only on lines that match a pattern.
To insert "ABC" at the begining of each line:
Go to command mode
% norm I ABC
For commenting blocks of code, I like the NERD Commenter plugin.
Select some text:
Shift-V
...select the lines of text you want to comment....
Comment:
,cc
Uncomment:
,cu
Or just toggle the comment state of a line or block:
,c<space>
I can recommend the EnhCommentify plugin.
eg. put this to your vimrc:
let maplocalleader=','
vmap <silent> <LocalLeader>c <Plug>VisualTraditional
nmap <silent> <LocalLeader>c <Plug>Traditional
let g:EnhCommentifyBindInInsert = 'No'
let g:EnhCommentifyMultiPartBlocks = 'Yes'
let g:EnhCommentifyPretty = 'Yes'
let g:EnhCommentifyRespectIndent = 'Yes'
let g:EnhCommentifyUseBlockIndent = 'Yes'
you can then comment/uncomment the (selected) lines with ',c'
Mark the area to be comment as a visual block (<C-V)
and do c#<ESC>p
change it to "#"
put it back
If you do it often, define a short cut (example \q) in your .vimrc
:vmap \q c#<ESC>p
In case someone's multi-line-selection is actually a paragraph, there is no need to manually select the lines. vim can do that for you:
vip: select and mark the whole paragraph
shift-i: insert text at line beginning
escape: leave insert mode/enter normal mode [line beginnings still selected]
escape: unselect line beginnings
Mapping of most voted answer:
1st visual select the desired lines, then execute <leader>zzz, which values:
vnoremap <leader>zzz <C-V>^I-<Space><Esc>
<C-V> to enter visual mode
^ goes to start of line ( or use '0' to 1st non blank)
I to insert in block mode
-<Space> to insert '- ' (for example, edit as you need)
<Esc> to apply same insert to all visual block lines
Or of last visual selection from normal mode:
nnoremap <leader>zzz gv<C-V>^I-<Space><Esc>

Resources