How to save a Vim macro that contains "Escape" key presses? - vim

I use the following Vim macro a lot (it puts the current line inside XML tags):
I<e>^[A</e>
So I saved it into my .vimrc
let #e='I<e>^[A</e>'
But it does not work.
The ^[ part means "Escape" but it is not understood as such in .vimrc
How can I save this macro, or any macro that contains "Escape" ?

Try entering the escape with <Ctrl-v><Esc> in insert mode.
See :help i_CTRL-V in vim.

For a macro:
:let #e='^[I<e>^[A</e>'
Where ^[ is just one char formed by hitting CTRL+VESC (CTRL+QESC on Windows). Note the escape right at the beginning of the macro.
See :help c_CTRL-V in Vim for more information.
For those who've landed on this post looking for how to add ESC to a mapping, the answer is different.
Literally type <ESC>, thus:
:nnoremap <Leader>E I<e><ESC>A</e><ESC>
See :help key-notation in Vim for more info.

For readability purpose, it's possible to use the proper key-notation tags such as <Esc> or <CR> instead of ^[ or ^M
You would need to escape the tag <Esc> with a single \ and use double quotes instead of single quotes which would result in "\<Esc>".
The following examples are equivalent
:let #e='^[I<e>^[A</e>'
:let #e="\<Esc><e>\<Esc>A</e>"
A list of all key notations can be found by typing :help key-notation or here.

If you're using Windows behavior for vim where Ctrl+V is the Paste command, the equivalent sequence is Ctrl+Q

Today I discovered a vim plug-in called MARVIM (http://www.vim.org/scripts/script.php?script_id=2154).
It is capable of storing macros and executing them later using shortcuts.

Saving macros in plain file without plugins.
Having for example macro m . In insert mode, at e.g beginning of new line, then type 3 keys
ctrl-r ctrl-r m
the macro with escapes will be put in that line. (editable as needed)
In another line name/comment it.
Add other macros if you wish - then save this file as e.g.
:w my_vim_macros
When you want to reuse such saved macro(s):
place cursor on the beginning of macro string, then 4keys
"xy$
and your macro (this line) will be yanked to register x.

I'm answering what I do to add Escape in macro.
Using in vim editor
:let #a='iabcjj'
here I map <ESC> to jj by
.vimrc file
imap jj <esc>

Related

Creating HTML Tags in VIM

I am trying to keep my VIM plugin use to a minimum (call me crazy) and I came across a great VIM script that does what I need quite well.
imap <C-t> <></><Esc>5hdiw3lpT>i
It works great for creating a <div></div> however, I am currently working in Vuetify and there are tags like <v-img></v-img> and the letters before the dash gets missed. I get something like: v-<img></img>.
Any idea what adjustments I can make to my script that will use the letter before the dash as part of the tag?
Thank you,
You can change a few things…
If you add - to :help 'isfname' the diw part of your mapping will cover the whole v-img.
Here is a version of your mapping that doesn't rely on counting characters:
inoremap <C-t> <C-o>diw<<C-r>"></<C-r>"><C-o>T>
<C-o> leaves insert mode only for one normal mode command, without triggering autocomands,
diw cuts the word under the cursor to the unnamed register, ",
< inserts <,
<C-r>" inserts the content of register ",
></ inserts ></,
<C-r>" inserts the content of register ",
> inserts >,
<C-o> leaves insert mode only for one normal mode command, without triggering autocomands,
T> moves the cursor between the opening and closing tags.
Reference:
:help i_ctrl-o
:help i_ctrl-r
:help ""
:help T

Vim mapping to copy all text in visual mode

I would like to map ctrl+a in visual mode to select and copy all text from the current buffer.
The basic idea is to execute: %y* (copy all buffer to clipboard). So, the mapping should be: xmap :%y* (xmap for visual mode only)
However, whenever I run this mapping, this output is shown:
E492: Not an editor command: '<,'>%y*
And, I think Vim is right :-). When in visual mode, pressing the ":", makes the cmd-line show those surprising characters:
":'<,'>"
The only relevant piece of info where I could find this pattern ('<,'>) is that one: http://vimdoc.sourceforge.net/htmldoc/cmdline.html#v_:
(and it didn't help me).
Question: Am I doing something wrong (configuration...) ? Is there another answer to my need (copy all text to clipboard) ?
I am running Vim 7.3 and I only set nocompatible in my vimrc
Thanks for your help,
Tom
Use:
xnoremap <whatever> :<c-u>%y*<return>
The additional ctrl-u erases the command line till the cursor.
From vim reference:
*c_CTRL-U*
CTRL-U Remove all characters between the cursor position and
the beginning of the line. Previous versions of vim
deleted all characters on the line. If that is the
preferred behavior, add the following to your .vimrc: >
:cnoremap <C-U> <C-E><C-U>
Use the following mapping:
nmap <C-A> ggVGy
It yanks all the current file. By the way, I'm not sure it's exactly what you what. I don't understand why you want a visual mapping.

Vim Pre-Exit (Esc Key) Command?

Right now in Vim when I go to a new line (or press 'p' or 'o' in normal mode) I get a lovely automatic indent, that also disappears if I exit insert mode without adding anything to it.
Is there a way to bind something to before I exit insert mode, such as inserting a phantom character then removing it?
Argh, I just read about this exact thing like two days ago but I can't remember where.
Anyway, the trick is to input a character right after <CR> and delete it immediately. There are a bunch of ways to do it:
<CR>a<Esc>x
<CR>a<C-w>
<CR>a<BS>
--EDIT--
Vim being Vim there are probably many other ways.
To automate these, you need to add a mapping to your .vimrc:
inoremap <CR> <CR>a<BS> " insert mode mapping for <CR>
nnoremap o oa<BS> " normal mode mapping for o
But I'm not sure you should overwrite defaults like that.
--EDIT--
However, what is annoying with Vim's default behaviour is that you may need to do some <Tab><Tab><Tab><Tab> before actually inputing some text on non-indented line or do == when you are done or rely on the automatic indentation rules for your language at the next <CR>.
All that can be skipped by using <S-S> which puts you in INSERT mode right at the correct indentation level.
Try either cc or S in normal mode to change a line with respect to indention. No need for phantom characters.
:h cc
:h S
A mapping like the following should do the trick:
imap <esc> <esc>:s/\s\+$//<CR>
This one deletes trailing characters when you press esc in insert mode.

Vim Dumb Indenting?

Is there a way to just have Vim copy the indent from the line above, whether it be spaces or tabs, oblivious of the file types?
:set ai
See :help autoindent
I assume you are going to paste something and adjust the indent.
Try ]p
If you are at the beginning of the line and want to copy all the indenting characters above the line that you are currenly on now you can use Ctrl+y. It copies the character from the line above one at a time. Ctrl+e does the same thing but it copies from the line below.
It seems what I've wanted isn't actually possible as Vim automatically removes whitespaces, and uses configuration settings for its indention.
I've avoided this put slapping these in to my vimrc:
:inoremap <CR> x<BS><CR>x<BS>
:inoremap <up> x<BS><up>
:inoremap <down> x<BS><down>
:nnoremap o ox<BS>
:nnoremap O Ox<BS>
It simply puts a character in place and then removes it before I exit the editing mode, so Vim doesn't remove the empty line. If this is the case then it may be simply Vim checking if any editing was done to the line, auto indenting not counted. Maybe someday I'll check out the source and poke around.
I also wanted to use the previous line's indent (so I'd get different indents for different files and not have to tamper with settings each time), but I've managed to compromise and use the lovely Vim plugin.

How to paste in a new line with vim?

I often have to paste some stuff on a new line in vim. What I usually do is:
o<Esc>p
Which inserts a new line and puts me in insertion mode, than quits insertion mode, and finally pastes.
Three keystrokes. Not very efficient. Any better ideas?
Shortly after :help p it says:
:[line]pu[t] [x] Put the text [from register x] after [line] (default
current line). This always works |linewise|, thus
this command can be used to put a yanked block as
new lines.
:[line]pu[t]! [x] Put the text [from register x] before [line]
(default current line).
Unfortunately it’s not shorter than your current solution unless you combined it with some keyboard map as suggested in a different answer. For instance, you can map it to any key (even p):
:nmap p :pu<CR>
Options:
1) Use yy to yank the whole line (including the end of line character). p will then paste the line on a new line after the current one and P (Shift-P) will paste above the current line.
2) Make a mapping: then it's only one or two keys:
:nmap ,p o<ESC>p
:nmap <F4> o<ESC>p
3) The function version of the mapping (unnecessary really, but just for completeness):
:nmap <F4> :call append(line('.'), #")<CR>
" This one may be a little better (strip the ending new-line before pasting)
:nmap <F4> :call append(line('.'), substitute(#", '\n$', '', ''))<CR>
:help let-register
:help :call
:help append()
:help line()
:help nmap
You can paste a buffer in insert mode using <C-R> followed by the name of the buffer to paste. The default buffer is ", so you would do
o<C-R>"
I found that I use <C-R>" very often and bound that to <C-F> in my vimrc:
inoremap <C-F> <C-R>"
This still uses three keystrokes, but I find it easier than Esc:
o<Alt-p>
Since you're in insert mode after hitting o, the Alt modifier will allow you to use a command as if you weren't.
Using this plugin: https://github.com/tpope/vim-unimpaired
]p pastes on the line below
[p pastes on the line above
advantages:
works on all yanked text (word, line, character, etc)
indents the pasted text to match the indentation of the text
around it
2 keystrokes instead of 3 and much "easier" strokes
fast
Personally I've nmapped Enter (CR) like this:
nmap <CR> o<Esc>k
...based on this Vim Wikia article.
This way I can make newlines directly from normal mode, and combining this with wanting to paste to a newline below I'd do:
<CR>jp
You could also skip k in the nmap above, depending on what functionality you prefer from Enter, so it would just be <CR>p.
I've also imapped jj to Esc, which would also assist in this case. Esc is way too far away from the home row for how significant it is in vim.
Not shorter than the other solutions, but I do think it feels less clunky than some of them, and it has other uses too.
If you wanted to stay in the insert mode, you can do o ctrl+o p
o – insert mode and go to the new line
ctrl+o – run a single command
like in normal mode
p – paste
It's three keystrokes but you stay in insert mode and also o ctrl+o is quite fast so I personally treat it as 2.5 keystrokes.
If you're copying a whole line then pasting a whole line, use Y to yank the line or lines, including line break, in the first place, and p to paste. You can also use V, which is visual line mode, in contrast with plain v for visual mode.
I have mapping inoremap jj <ESC>. So it is easy to insert new line with ojj and Ojj and then p.
so ojjp paste new a newline. it have one more stroke then o<esc>p but ojjp is easy for me.
I found an elegant solution to this. If you are putting the yank register in your OS's clipboard (which is great anyway), with
set clipboard+=unnamed
than you can do o<Ctl-v>.
Besides being fewer strokes, this improves on both o<Esc>p and :pu because it preserves indenting: both of the other options start you at character zero on the new line.
Caveat is that this may or may not be OS dependent. All I know is that it works on recent version of OS X, but clipboard is just one of many ways to get yank in the OS clipboard.
If you want to paste in a new line and still keep indentation, create this mapping:
nnoremap <leader>p oq<BS><Esc>p
Prerequisite: you have leader mapped and you have set autoindent in your .vimrc.
Explanation: a new line is created with 'o', 'q' is typed and then back-spaced on (to keep indentation), and 'esc' brings you back to normal mode where you finally paste.
If you also want to end in insert mode, it is possible to paste while in insert mode using CTRL-R ". https://stackoverflow.com/a/2861909/461834
Still three keystrokes, but no escape, and you save a keystroke if you want to end in insert anyway.
I use the following mapping in my Neovim config:
nnoremap <leader>p m`o<ESC>p``
nnoremap <leader>P m`O<ESC>p``
A little explanation:
m`: set a mark in the current cursor position.
o<Esc>p: create a new line below and paste the text in this line
O<Esc>P: create a new line above and paste the text in this line
``: put the cursor in the original position
See :h mark for more information about marks in Vim.
This solution only seems to apply when the block of copied text starts on a new line (as opposed to grabbing a snippet of text somewhere within a line), but you can always start your copy on the last character you want to grab, then navigate to the last character at the end of line prior to the start of your desired copy block. Then when you want to paste it, place the cursor at the end of the line under which you want your text to be pasted and hit p. If I haven't screwed up the explanation, this should provide the effect you're looking for.

Resources