How do I insert a linebreak where the cursor is without entering into insert mode in Vim? - 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.

Related

How to switch modes when operating on multiple selected lines

I have created a line selection in Vim by Shift+V and followed by jjjj.
I can do something against all lines separately like :normal ^i//, which moves the cursor to the beginning of each line and enter insert mode, then insert two /.
Is it possible to switch back to normal mode after this?
The example in the question is just to demonstrate the problem and I only want to discuss the Vim usage skills.
I tried :normal ^i//<Esc>A// in the hope of adding two / to the end of each line, but it didn't work.
Is this possible?
The :normal command does not interpret special characters. In your last try, all the chars after i would be interpreted as normal text then inserted at the beginning of each selected line: //<Esc>A//.
The Esc character is a special char (actually the ASCII code 27), so you have to ask Vim to insert this char in a different way (because hitting Esc would escape the command line).
In order to do this (either in Command mode or Insert mode), press Ctrl + V then the wanted key, e.g. Esc. This will insert the real <esc> character in you flow, then perform the desired behaviour.
To summarize:
Press Shift + V followed by jjjj...
Type :normal ^i//Ctrl + VEscA//
Hit Return to validate the command

Delete text *after* cursor in vim (leaving what is under the cursor)

Let's say I've got this text on a line:
myNewFunction(argument); // some junk I don't need
^
my cursor
What is the fastest way to delete everything after the semicolon (which I'm on). So for example, D will not work, because it deletes the semicolon too. I know I can do lD (move right one, then delete)
Is there a general way to delete after cursor though? Ideally I could even do something like Da3 (delete everything three characters after the cursor position)
EDIT: This often happens after I'm finished typing a semicolon and then I press Esc - now my cursor is on the semicolon.
lol.... Okay, I'll type it up.
So - If you're in insert mode, <C-O> switches it off for one command only, without moving the cursor. So if you do <C-O>D, you will delete the rest of the line and get dropped back into insert mode.
If you are in normal mode, lD should be fast enough.
I think it's not posible without mappings or repeating a substitution.
If you don't have problem 'repeating' a substitution, you can do a first substitution:
:s/;\ze.*$//
And then, repeat it using & is one key stroke, but you nead to make the substitution and then, repeat it. Just to be clear, pressing & repeats the last substitution. It's like the . command but only for substitutions
Try to create a function and use it with a normal mapping.
This gets character under current cursor position and instead of D use C that sets insert mode and lets us to put the character saves previosly:
function! DeleteUntilEOL()
let c = getline('.')[col('.')-1]
execute 'normal C' . c
endfunction
Now create the mapping:
:nnoremap <leader>D :call DeleteUntilEOL()<CR>

Opposite of newline in vim

In vim, is there a command to delete the newline, and all empty space behind the cursor?
Say I stand in the middle of a text in insert mode and press Enter, what command would the reverse what I just did?
A) An example:
"some code{ in here }"
B) After pressing Enter:
"some code{
in here }"
Now pressing backspace will delete one space of the indentation. I would rather have it delete all indentation, and jump back to A.
Can this be done in a command or by doing some remapping to the backspace key?
It's tragic how unknown the J command is. It joins lines in normal mode.
In insert mode, you can press <C-U> twice; first, it'll delete the indent before the cursor, then it'll join with the previous line. Note that this requires
:set backspace=indent,eol,start
did you try J (uppercase) ? it will give exactly what you want.
"some code{ cursor on this line, pressJ
in here }"
You can do ᴇꜱᴄ, K, Shift+J.
K jumps up to the previous line and Shift+J joins the two lines.
However, with properly configured indentation and syntax, a backspace doesn’t just delete a space, it deletes the full previous indentation block.
One easy way is up one line, to end of that line and just delete. As long as you still are in insert mode it will do the same thing as J when deleting at the last position - like most other editors. For me that is the quickest alternative because I'm used to it from other editors.
That is: ↑, End, Delete (when still in insert mode)
One quick alternative (the VIM-way) is (when still in insert mode):
↑, Ctrl+o, J (when still in insert mode)
(Ctrl+o is used in insert mode to enter one normal mode command.)
It's also possible to use a remapping of the backspace key:
inoremap <expr> <bs> getline('.')[:col('.')-2]=~'^\s\+$' ? "<c-u><c-u>" : "<bs>"
Note that this mapping completely overrides the normal behavior the backspace key. This will only be useful when you don't intend to use its normal behavior. This is not recommended if you can easily access the other options (c-u or J)
However, (as far as I know) there's no way to distinguish between manually added leading white spaces and auto indent. If you use noexpandtab, you can edit the regex to only match tabs.
This also does not work in some modes of auto-indent (for example, in block comment in C, vim automatically start a new line starts with *)

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>

How do I specify "the word under the cursor" on VIM's commandline?

I want to write a command that specifies "the word under the cursor" in VIM. For instance, let's say I have the cursor on a word and I make it appear twice. For instance, if the word is "abc" and I want "abcabc" then I could type:
:s/\(abc\)/\1\1/
But then I'd like to be able to move the cursor to "def" and use the same command to change it to "defdef":
:s/\(def\)/\1\1/
How can I write the command in the commandline so that it does this?
:s/\(*whatever is under the commandline*\)/\1\1
While in command-line mode, CTRL+R CTRL+W will insert the word under the cursor.
See the help for c_CTRL-R for a listing of all the other special registers:
:help c_CTRL-R
<cword> is the word under the cursor (:help <cword>).
You can nmap a command to it, or this series of keystrokes for the lazy will work:
b #go to beginning of current word
yw #yank to register
Then, when you are typing in your pattern you can hit <control-r>0<enter> which will paste in your command the contents of the 0-th register.
You can also make a command for this like:
:nmap <leader>w :s/\(<c-r>=expand("<cword>")<cr>\)/
Which will map hitting '' and 'w' at the same time to replace your command line with
:s/\(<currentword>\)/
yiwP
yiw: Yank inner word (the word under the cursor). This command also moves the cursor to the beginning of the word.
P: Paste before the cursor.
You can then map the e.g.: < ALT > - D to this command:
:nmap < ALT >-D yiwP
Another easy way to do this is to use the * command.
In regular mode, when over a word, type
*:s//\0\0<Enter>
* makes the search pattern the current word (e.g. \<abc\>).
:s// does a substitution using the current search pattern, and \0 in the replacement
section is the matched string.
You can then repeat this behaviour, say over word "def", by either typing the same again, or by typing
*#:
#: just repeats the last ex command, without a need for an <Enter>, in this case the substitution.
You can also record a quick macro to do this using the q command
qd*:s//\0\0<Enter>q
Then repeat it to your hearts content by typing
#d
when over a word you want to double. As this is only one character less than the prior solution, it may not be worth it to you - unless you will be doing other ex-commands between the word-doubling, which would change the behaviour of #:
You need to escape the backslashes within the mapping. You can also include the substitution string within the mapping.
:nmap <leader>w :s/\\(<c-r>=expand("<cword>")<cr>\\)/\\1\\1<cr>
ywPx
will do what you describe.
ywPxw
will also advance the cursor to the next word.
#user11211 has the most straightforward way to duplicate the word under cursor:
yiwP
yank inner word (moves cursor to start of word), paste (before cursor).
eg. straigh[t]forward ----> straightforwar[d]straightforward
[] is cursor
To elaborate...
You probably want to have the cursor following your duplicated word:
yiwPea
straigh[t]forward ----> straightforwardstraightforward[]
NOTE:
yiw
is yank inner word (without whitespace)
yaw
is yank all word (including trailing whitespace).
yawPea
is therefore duplicate word including whitespace, and position cursor.
straigh[t]forward ----> straightforward straightforward[]
" count word (case sensitive)
nmap <F4> :%s/\(<c-r>=expand("<cword>")<cr>\)//gn<cr>

Resources