How to escape in g command's norm mode of Vim - vim

I want to add []( to the beginning of a line and ) to the end of a line that starts with http in Vim.
To do this I am using the following g command:
g/^htt/norm I[](
Now, I want to press Esc key now inside g and put A). How can I do that?

You can escape the Esc key by using ctrl+vfollowed by esc.
ctrl+v will insert the next non-digit literally.
Note: You may have to use ctrl+q depending on your system. (Nice mnemonic is quote)
See help for more information
:h c_Ctrl-V

To be able to use two :normal commands in sequence, you have to wrap them in :execute. When you use double quotes, you can then write the Escape as \<Esc>, like this:
:g/^htt/exe "norm I[](\<Esc>" | norm A)
Notes:
Unless you need mappings to apply, using :normal! (with the bang) is preferred, because it's more robust.
You could have also used :substitute here.

This is easier to do with :s:
:%s/^htt.*/[](&)/

Related

Vim: Is there a way to replace all occurrences of a word without typing it?

I have the following code:
long_word: ISubscription['long_word'];
This is what I normally do:
shift v
:s/long_word/new_word/g
It's tedious to have to type the word I'm trying to replace. So sometimes I just do
ciw
new_word
esc
$
hhhh
.
which feels inefficient.
Is there a way to do something like ciw but on the whole line?
You could do:
:s/short-string/new_word
to set the replacement pattern, then put the cursor on long_word and type * or # to set the search pattern, and then do:
g&
to replace all occurrences of long_word with new_word. It's not super elegant, but it's not terrible.
Make sure short-string is easy to type and not actually a string that occurs on the current line (you don't actually want to replace it!). I find short-string usually ends up being something like kjkjkjj. Not elegant, but effective.
First things first: V is not necessary because the default range for :help :s is the current line. So that's one improvement.
Then there is the unavoidable fact that the string to substitute has to be defined, somehow. You can't just have your cursor anywhere on the line and expect Vim to figure it out on its own. The only way to start the process is to literally point Vim at the string in question… by placing your cursor on it.
So, assuming the string to substitute is under your cursor and matches Vim's definition of a word (see :help word), you can use :help c_ctrl-r_ctrl-w to insert it in the command-line:
:s/<C-r><C-w>/new-word/g<CR>
If you have to do that often, you could save yourself a lot of effort with a simple mapping:
nnoremap <key> :s/\<<C-r><C-w>\>//g<Left><Left>
Note the \< and \>, which makes sure that only whole words are matched.
Now, the string to substitute might not be a word (or a WORD, in which case you would use :help c_ctrl-r_ctrl-a). In that case, you can still visually select it, yank it, and insert it in the command-line:
v{motion}
y
:s/<C-r>"/new-word/g<CR>
which, of course, could also be turned into a mapping:
xnoremap <key> y:s/<C-r>"//g<Left><Left>

Vim normal! sending literal <Space> string instead of whitespace character

I'm not sure what I'm doing wrong here.
:normal! I###<Space><Esc>
The end result I want when I execute this command over a word is this:
### word
But instead I get this:
###<Space>word
Vim's :normal is a nightmare with anything moderately complicated. I don't remember why, but this is the easiest way to get what you want. You need to escape the opening < in a string passed to execute.
execute "normal! I###\<Space>\<Esc>"
Edit: Vim doesn't really explain why, but :help normal
An alternative is to use |:execute|, which uses an
expression as argument. This allows the use of
printable characters to represent special characters.
Lets first explain the vim command:
:normal! run the rest of the commands as normal mode
I enter insert mode from the beginning of the line <shift> + i
###<Space><Esc> - type out the characters ###<Space><Esc> literally since we are in insert mode (notice that if you just enter insert mode, and type ###<space><esc>, you'll get just that literally.)
When this command finishes, you'll notice how it's still in normal mode. This means that your command can just omit the <space><esc> and enter the space literally:
:norm! I###
(There is an extra space after the last hash)

vim command for adding Parentheses efficiently

what is the vim command can put something into Parentheses efficiently and then I can use . to repeat it? ?
for example, data['max'] to (data['max'])
visually select your text:
viW
change it with the opening parenthesis, followed by the selected text, followed by the closing parenthesis:
c(<C-r><C-o>")<Esc>
If you are confident with text-objects, this can be done in one step:
ciW(<C-r><C-o>")<Esc>
which can be repeated with ..
I'd recommend using two plugins for this. Tim Pope's vim-surround and vim-repeat.
Just follow the links and install those plugins.
Inorder to put parenthesis around a word, just do ysiw)
Otherwise, select text in visual mode, press S(Capital S) and type in paranthesis
You can use a map for that.
:nmap \. I(<ESC>A)
You can put this line in your ~/.vimrc file.
When you press \ and . in normal mode, it will add a opening bracket at the start of the line and closing bracket at the end of the line.
Assuming that you are using a language like Tcl and surround the hash element with a bracket,
You can try this by keeping the cursor anywhere on the hash name,
: nmap \. bi(<Esc>f]li)
This will surround the expected one with circular braces.
You can use a map in vimrc:
xnoremap <leader>a <ESC>`>a)<ESC>`<i(<ESC>
And use <leader> and a to add parentheses efficiently

All occurrences of text between quotes (like * but for the whole text, not a single word)

When I edit XML-files I sometimes want to jump to the next occurrence of text between quotes. For example, when my cursor is on my.attr in attr="my.attr" I want to jump to the next occurence of my.attr. I want to do it via some key combination (like Shift + * which is for words occurrences). Is is possible?
You can create a visual selection of the attribute value inside double quotes with vi". Then, there are several plugins that implement the * command for visual mode (usually by overloading the * command), i.e. they search for the next occurrence of the selected text. One such plugin is my SearchHighlighting plugin. (The plugin page has links to alternative plugins.)
Related plugins
If you want to change all attribute values (without constructing a :%s/ substitution), my ChangeGlobally plugin provides a gc{motion} and {Visual}gc command that does that.
I would yank the text inside the quotes with yi" (only works if the opening and closing quotes are on the same line) and then /<C-R>". (The <C-R> means CTRL-R, not 5 characters.)
This gives you a chance to modify the pattern before submitting it; as #Kalanidhi pointed out, you may have to escape some special characters. It uses the same i" text object as in #Ingo Karkat's answer.
If your text is short, then you can edit the command line with the arrow keys, but if it is long you may want to edit it in a command-line window with <C-F>. (Alternatively, if you are thinking ahead, use q/ instead of /.)
:help y
:help text-objects
:help c_CTRL-R
:help cmdline-editing
:help cmdline-window
You can use in command mode type /<exact pattern> if any special character then escape the special character like \
For example In command mode /"my\.attr"
So only search the exact pattern. N or n to move forward and backward .

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.

Resources