Mapping a key in VIM - vim

I've tried:
:map <F2> :.y" :g/<C-R>"/d<CR>
No luck :(
What this does, yank the current line into register "
Then, globally, delete lines that match exactly the line in the register.
It works dandy when I do it manually.
:vmap <F2> ["]yy<ESC><ESC> :g/<C-R>"/d<CR>
Similar to above - I select a few words, whatever - I make a selection, then yank it to register ". I then globally, delete the lines that match whats in the register.
It works dandy when I do it manually.
What am I doing wrong?

You might try this for the first one:
:nnorempa <F2> :silent exe "g/".getline(".")."/d"<CR>
For the second, something like this if you want to delete only the words:
:vmap <F7> y:silent exe "%s/".#"."//g"<CR>
And this if you want to delete the matching lines:
:vmap <F7> y:silent exe "g/".#"."/d"<CR>

You have remapped F2 to :.y" :etc. You need <cr> not a simple space. If you type :.y" in vim and don't hit ENTER but space, nothing will happen.
So:
:nnoremap <f2> :.y"<CR>:g/<C-R>"/d<CR>
could do it.
Still, warning, if your line contains any of /\*[~$^. this could fail. You could use the expression register in order to escape in-place:
:nnoremap <f2> :.y"<CR>:g/<c-r>=escape(#", '/\*[~$^.')<cr>/d<cr>
Still better, without overwriting your default (") register is:
:nnoremap <f2> :g/^<c-r><c-o>=escape(getline('.'), '/\*[~$^.')<CR>$/d<cr>
which will delete all identical lines. Still note that 'ignorecase' or 'smartcase' matter.

First of all - make sure you're using vim :)
vim --version
Here's the mapping I was going for. As I go through lots of data in log files, this will be incredibly useful. Select the area you want to eliminate, then and all instances of highlight area is done for.
NOTE: This does NOT go through the highlighted text and escape any regex characters. So a /, *, ^ will foul it up.
:map <F2> y:g/<C-R>"/d<CR>
:)

Related

Setting mouse=a and mapping <esc> to :noh breaks mouse working on vim? [duplicate]

I am a happy VIM user, although I admit I'm quite far from being fluent. I found this nice post:
Vim clear last search highlighting and I thought I'd become a better person if I didn't have to hammer away a random character sequence every time I did a search. Now, I'm also using the vimrc config from here:
http://amix.dk/vim/vimrc.html
and the problem I have is that when I add the line nnoremap <esc> :noh<return><esc> to it (it doesn't seem to make a difference where I put it) I get awkward behaviour when I use arrows in command mode, namely letters from A to D appear in a newline and I get switched to insert mode.
There has to be some mapping conflict but for the life of me I can't figure out where it is.
EDIT: As it follows from the answers it turns out the Ultimate vimrc part is not relevant, the mentioned nnoremap command will cause altered arrow behaviour even if it's the only vimrc entry. Changing title to a more informative one.
PS. I know I shouldn't use arrows, hopefully I'll get there one day.
The mapping
nnoremap <esc> :noh<return><esc>
will conflict with so called "grey keys" and I believe that it should be used either in GVim only or in terminal Vim by someone who does not use special keys like arrows.
From what I know (and guess) how Vim processes keys, I would say that it's impossible to do anything with this. For Vim to recognize special key all its components should go in a row, so when you press Arrow Left Vim gets the following sequence of codes:
<esc> [ D
But after your mapping Arrow Left becomes:
: n o h l <cr> <esc>
[ D
Vim sees two separate sequences and treats <esc> as a single press of Escape key, thus next two codes of Left Arrow key lose their special meaning.
So I suggest you to map :noh to some other key sequence (e.g. to one starting with <leader>, see :help mapleader; I don't recommend you to use F-keys, using them is as bad as using of arrow keys).
The cause had been explained well, but solution was not mentioned. However there is a straight one.
If you’ll tell to Vim explicitly that there are key sequences starting from <esc>[
:nnoremap <silent><esc> :noh<CR>
:nnoremap <esc>[ <esc>[
than when single <esc> will be pressed Vim will wait for a second (or different time, see :h 'timeoutlen') or for a next key (second <esc> for example) and only then replace it with :noh<CR>.
This solution preserves the ESC mapping to :nohlsearch.
The comment on this answer explaining why this is happening tells us that the root cause is the TermResponse behavior of vim. This can be compensated for by wrapping the mapping in an autocommand for the TermResponse event.
This ensures that the binding doesn't happen until after the term response is set, which prevents Esc from also sending a string like ]>1;3201;0c to vim.
Change your line in vimrc to this:
augroup no_highlight
autocmd TermResponse * nnoremap <esc> :noh<return><esc>
augroup END
The augroup commands are not strictly necessary, but they prevent multiple mappings when you reload your vimrc without quitting vim.
EDIT: If you also use a graphical vim like Gvim or Macvim, the TermResponse event will not fire. Assuming you use a single vimrc, you'll need some additional code like
if has('gui_running')
nnoremap <silent> <esc> :nohlsearch<return><esc>
else
" code from above
augroup no_highlight
autocmd TermResponse * nnoremap <esc> :noh<return><esc>
augroup END
end
Problem is that when you press an arrow terminal emits something like <Esc>OA. Vim part that supports terminal seems to use the same mapping mechanism to do the job as you are using: while nmap <Esc>OA will tell you nothing, call feedkeys("\eOA") will move one line up and call feedkeys("\eOA", 'n') will add letter A beyond current line. With your mapping being noremappable you forbid vim to use <Esc> as a part of the key. The problem is that you need remappable mapping here, but can have remappable mapping without it being recursive as well only if it starts with {lhs}, but <Esc>:noh<CR>OA is not going to work. I thought the following code will (it uses <expr> and function with side effect to make <Esc> be the first character of the actual {rhs} and still launch :noh), but in fact it does not:
function s:NoHlSearch()
nohlsearch
return "\e"
endfunction
nmap <expr> <Esc> <SID>NoHlSearch()
. I have no other idea how to solve the problem of having non-recursive remappable mapping which includes {lhs} but not at the start.
I have had good luck with this
if $TERM =~ 'xterm'
set noek
endif
nnoremap <silent> <esc> <esc>:noh<cr>
The disadvantage is that function keys can not be used in insert mode.
:h ek

Mapping <esc> in vimrc causes bizarre arrow behaviour

I am a happy VIM user, although I admit I'm quite far from being fluent. I found this nice post:
Vim clear last search highlighting and I thought I'd become a better person if I didn't have to hammer away a random character sequence every time I did a search. Now, I'm also using the vimrc config from here:
http://amix.dk/vim/vimrc.html
and the problem I have is that when I add the line nnoremap <esc> :noh<return><esc> to it (it doesn't seem to make a difference where I put it) I get awkward behaviour when I use arrows in command mode, namely letters from A to D appear in a newline and I get switched to insert mode.
There has to be some mapping conflict but for the life of me I can't figure out where it is.
EDIT: As it follows from the answers it turns out the Ultimate vimrc part is not relevant, the mentioned nnoremap command will cause altered arrow behaviour even if it's the only vimrc entry. Changing title to a more informative one.
PS. I know I shouldn't use arrows, hopefully I'll get there one day.
The mapping
nnoremap <esc> :noh<return><esc>
will conflict with so called "grey keys" and I believe that it should be used either in GVim only or in terminal Vim by someone who does not use special keys like arrows.
From what I know (and guess) how Vim processes keys, I would say that it's impossible to do anything with this. For Vim to recognize special key all its components should go in a row, so when you press Arrow Left Vim gets the following sequence of codes:
<esc> [ D
But after your mapping Arrow Left becomes:
: n o h l <cr> <esc>
[ D
Vim sees two separate sequences and treats <esc> as a single press of Escape key, thus next two codes of Left Arrow key lose their special meaning.
So I suggest you to map :noh to some other key sequence (e.g. to one starting with <leader>, see :help mapleader; I don't recommend you to use F-keys, using them is as bad as using of arrow keys).
The cause had been explained well, but solution was not mentioned. However there is a straight one.
If you’ll tell to Vim explicitly that there are key sequences starting from <esc>[
:nnoremap <silent><esc> :noh<CR>
:nnoremap <esc>[ <esc>[
than when single <esc> will be pressed Vim will wait for a second (or different time, see :h 'timeoutlen') or for a next key (second <esc> for example) and only then replace it with :noh<CR>.
This solution preserves the ESC mapping to :nohlsearch.
The comment on this answer explaining why this is happening tells us that the root cause is the TermResponse behavior of vim. This can be compensated for by wrapping the mapping in an autocommand for the TermResponse event.
This ensures that the binding doesn't happen until after the term response is set, which prevents Esc from also sending a string like ]>1;3201;0c to vim.
Change your line in vimrc to this:
augroup no_highlight
autocmd TermResponse * nnoremap <esc> :noh<return><esc>
augroup END
The augroup commands are not strictly necessary, but they prevent multiple mappings when you reload your vimrc without quitting vim.
EDIT: If you also use a graphical vim like Gvim or Macvim, the TermResponse event will not fire. Assuming you use a single vimrc, you'll need some additional code like
if has('gui_running')
nnoremap <silent> <esc> :nohlsearch<return><esc>
else
" code from above
augroup no_highlight
autocmd TermResponse * nnoremap <esc> :noh<return><esc>
augroup END
end
Problem is that when you press an arrow terminal emits something like <Esc>OA. Vim part that supports terminal seems to use the same mapping mechanism to do the job as you are using: while nmap <Esc>OA will tell you nothing, call feedkeys("\eOA") will move one line up and call feedkeys("\eOA", 'n') will add letter A beyond current line. With your mapping being noremappable you forbid vim to use <Esc> as a part of the key. The problem is that you need remappable mapping here, but can have remappable mapping without it being recursive as well only if it starts with {lhs}, but <Esc>:noh<CR>OA is not going to work. I thought the following code will (it uses <expr> and function with side effect to make <Esc> be the first character of the actual {rhs} and still launch :noh), but in fact it does not:
function s:NoHlSearch()
nohlsearch
return "\e"
endfunction
nmap <expr> <Esc> <SID>NoHlSearch()
. I have no other idea how to solve the problem of having non-recursive remappable mapping which includes {lhs} but not at the start.
I have had good luck with this
if $TERM =~ 'xterm'
set noek
endif
nnoremap <silent> <esc> <esc>:noh<cr>
The disadvantage is that function keys can not be used in insert mode.
:h ek

stopping vim from removing indentation on empty lines

When the cursor is placed at the end of a line containing nothing but withspace characters, vim will, when i press enter, remove that whitespace. I find this irritating, as it breaks my script for selecting code that are indented to the same level. How can I prevent vim from doing this?
In my .vimrc (http://bjuhn.com/randomstuff/vimrc) I have the following:
filetype plugin on
set copyindent
that is, I am not using any syntax-aware auto-indention, as I have yet to find one that does everything to my liking.
The Vim wiki suggests this:
inoremap <CR> <CR>x<BS>
because the indenting is not removed if some text has been entered on the line, even if it has been deleted.
[EDIT - milimetric]
Just a couple of pieces missing from a full solution. You also need remaps for o and O and whatever else you use to add lines:
inoremap <CR> <CR>x<BS>
nnoremap o ox<BS>
nnoremap O Ox<BS>
Same idea but people newer to vim might not figure it out quickly.
For me this code works:
inoremap <silent> <Esc> <C-O>:stopinsert<CR>

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.

Vim oddities in keymapping

I like to insert blank lines without entering insert mode and I used this keymapping:
nomap go o <esc>
This does create the blank line but introduces some weird behaviour. I have smart indent and autoindent set. The new line follows the indents but doesn't remove them even though doing so manually automatically removes the redundant whitespace. It also adds a single whitespace where the cursor is each time.
Anyone have any insights as to explain this behaviour?
Vim is very literal with how you write your mapping commands - it's actually processing the space in your mapping before it does the <ESC>. In other words, your mapping does this:
nnoremap go o<SPACE><ESC>
You should change it to:
nnoremap go o<ESC>
And make sure you don't have any extra spaces in the mapping!
I agree with "too much php".
This is the relevant section from my .vimrc
nnoremap <A-o> o<ESC>k
nnoremap <A-O> O<ESC>j
I think it's faster since you get the cursor back at the original line (Although not on the original character).
As usual, the vim wiki has a useful tip: Quickly adding and deleting empty lines. The trick is to set paste before adding the new line and afterwards set nopaste. Additionally, this will set a mark to remember the cursor position and jump back to where you were.
nnoremap go :set paste<CR>m`o<Esc>``:set nopaste<CR>
nnoremap gO :set paste<CR>m`O<Esc>``:set nopaste<CR>

Resources