How to ignore error in VIM key mapping command series? - vim

I'm editing key mappings for line movement as following:
vnoremap <silent> <C-j> :m '>+1<CR>gv
vnoremap <silent> <C-k> :m '<-2<CR>gv
They are supposed to move the line block up and down and work fine in most cases except at the top and bottom of a file.
When I select the line 1 2, and input ctrl-k, sure, it cannot move anymore upwards, while the expected behavior is that the line 1 2 are still highlight in visual mode.
The current appearance is that, the line 1 2 are not highlight anymore. I know that's because the ":m '<-1" failed, then gv will not be executed.
So my question is how to ignore this error to ensure gv executed anyway? Or some other solutions?
Please note, I know a solution linemovement.vim. It run these in two separated commands and some functions. While I suppose this should be a lightweight code.

You need :silent! to suppress the output and skip errors:
vnoremap <C-j> :<C-u>silent! '<,'>m '>+1<CR>gv
vnoremap <C-k> :<C-u>silent! '<,'>m '<-2<CR>gv
<C-u> removes the "selection range" inserted automatically by Vim because :silent doesn't accept a range.
we add '<,'> before :move so that it still works on the visual selection.
Here is that fix applied to my enhanced (adds autoindenting) version of those mappings:
nnoremap ,<Up> :<C-u>silent! move-2<CR>==
nnoremap ,<Down> :<C-u>silent! move+<CR>==
xnoremap ,<Up> :<C-u>silent! '<,'>move-2<CR>gv=gv
xnoremap ,<Down> :<C-u>silent! '<,'>move'>+<CR>gv=gv
Thanks for the idea.

Related

How can I define a key mapping in vim and use the repeat number more than once?

I edit files with relative line numbers. Often I would like to copy a line from let's say 16 lines above to the current location.
In normal mode I would enter: 16kyy16jP
But when it is line 14, it is: 14kyy14jP
How can I define a key mapping/command to be able to enter something like 16LK or 14LK in normal mode to achieve the same result?
16kyy16jP
What a waste… You could use :help :t instead:
:-16t.
:-14t.
May be something like
nnoremap <silent> µ :<c-u>exe "normal! ".v:count1."kyy".v:count1."jP"<cr>
But, honestly, I'd use functions here as there is no need to move around that much:
nnoremap <silent> µ :<c-u>call append(line('.')-1, getline(line('.')-v:count1))<cr>
Note that the following also works thanks to :yank
nnoremap <silent> µ :<c-u>exe '-'.v:count1.'y'<cr>P
EDIT: I didn't know about :t, #romainl's answer (with #Kent's patch) makes more sense than mine. If you want a mapping it could be mode with:
nnoremap <silent> µ :<c-u>exe '-'.v:count1.'t-1'<cr>
" which isn't much different than the previous answer.
You can map a function call, which accepts input parameters.
function! YourMap(n)
exec 'normal! '.a:n.'-Y'.a:n.'+P'
endfunction
nnoremap <leader>c :call YourMap(input('lines:')) <CR>
You press <leader>c, then input the relative line numbers, the copy/paste should be done.
The <leader>c is the mapping key, you can change it into other key combinations.

Insert blank line above or below the current line in Vim [duplicate]

This question already has answers here:
Vim command to insert blank line in normal mode
(4 answers)
Closed 8 years ago.
I recently surprised myself wanting to insert blank lines above or below the current line either in normal or insert mode.
I usually add blank lines to my code for better reading or to properly separate blocks of code.
To do this I am using the following in my .vimrc:
" Add empty line above and below the current line
nnoremap <silent> <C-K> mP:pu! _<cr>:']+1<cr>`P
inoremap <silent> <C-K> <esc>mP:pu! _<cr>:']+1<cr>`Pa
nnoremap <silent> <C-J> mP:pu _<cr>:'[-1<cr>`Pa
nnoremap <silent> <C-J> <esc>mP:pu _<cr>:'[-1<cr>`Pa
The only ugly thing with these mapping is I'm using the marker P just to go back to the previous cursor position. I tried to use `` instead but it doesn't do what I expected.
Perhaps there is a slightly better solution otherwise this snippet works quite well for me.
I am slowly adding new mapping in my .vimrc. I noticed the <C-[a-z]> combinaisons are mostly free and the existing ones are pretty useless (i.e. <C-Q>, <C-H>, <C-M>…). Then I decided to bind them to new useful mapping:
<C-N> New file
<C-S> Save (:update!)
<C-P> CtrlP mixed mode
<C-S-P> CtrlPCmdPalette
<C-B> CtrlP buffers mode
<C-D> <C-C>ciw
…
instead of using a named marker, you can use the backtick ' to explicitly add a jump. like:
nnoremap <c-k> m`O<esc>``
nnoremap <c-j> m`o<esc>``
inoremap <c-j> <esc>m`o<esc>``a
inoremap <c-k> <esc>m`O<esc>``a
If you want a robust mapping that also handles [count], my LineJuggler plugin contains ]<Space> mappings (among others). This particular mapping can also be found in the unimpaired plugin.

Move current line (up/down) to one position in Vim

Sometimes I want to swap current line with line up or below in vim. I can do it with commands :m+1 or :m-1. However it is too wordy. Is there shorter way doing the same?
give this a try:
ddp and ddkP
if it gives what you want. ;)
Both Tim Pope's unimpaired.vim - Pairs of handy bracket mappings and my own LineJuggler plugin provide (among others; my plugin has a focus on line moves and copies, whereas Tim's has a mixture of useful stuff) [e and ]e mappings to move the current line / selection above or below. These don't clobber the default register, as ddp et al. would do.
Give mappings a chance:
nnoremap <leader>k :move-2<CR>==
nnoremap <leader>j :move+<CR>==
xnoremap <leader>k :move-2<CR>gv=gv
xnoremap <leader>j :move'>+<CR>gv=gv
Vim has the :move command that allows you to move one line.
For instance, :m +1 will move the current line down.
I have these mappings in my .vimrc :
" move the lines of visual mode up or down
" JK to move and keep a correct indentation (with =)
" <up><down> to move keeping the correct indentation
vnoremap <silent> J :m '>+1<cr>gv=gv
vnoremap <silent> <down> :m '>+1<cr>gv
vnoremap <silent> K :m '<-2<cr>gv=gv
vnoremap <silent> <up> :m '<-2<cr>gv
With these lines, if you select a bunch of lines in visual mode, and then press <up> or <down> arrows, the lines will be moved up or down (and you will stay in the same visual selection thanks to the gv at the end).
J and K are almost the same, but they keep and autoindentation, using the = operator (gv= autoindents the last visual selection).
For sure, i encourage you to do modify the keys that are mapped to your own preferences. These are just mine. Also, copy-pasting without understanding is probably a bad idea. If you understand that mapping, you could check help pages for :m, gv and =.

Toggle highlight while searching in Vim

I like highlighting while searching in vim. Here's what I want:
I search for a word with /
Then, all of the results are highlighted. If I press any key other than n or N, I want the highlighting to be toggled off.
If I press n or N again after any number of commands, I want to toggle on the highlighting.
Where do I start? I'm not even sure what to google.
I have this in my .vimrc
nnoremap <CR> :noh<CR>
so that when I'm done seeing the highlighting, I just hit enter to remove it. It stays gone until I hit n or N again.
Note: If you want to keep the functionality of enter, add another <CR> on the end of the command.
I remap control-l (lower case L) so that it clears the search result as well as repaints the screen. This line in .vimrc does it:
nnoremap <silent> <C-l> :nohl<CR><C-l>
You can manually disable the last highlight with nohl.
I will let you know if I can figure out how to automate this.
One method is to setup a toggle mapping. These are some toggle mappings I have in my .vimrc:
let mapleader="\\"
noremap <silent> <Leader>th :set invhls hls ?<CR>
noremap <silent> <Leader>tn :set invnumber number ?<CR>
noremap <silent> <Leader>ts :set invspell spell ?<CR>
noremap <silent> <Leader>tw :set invwrap wrap ?<CR>
To toggle highlighting just type \th for toggle hls. The others are line number, spell checking, line wrapping. The final hls ? will display the new mode.
I prefer this, because to me it is nothing but natural.
Start searching with /<pattern> and once done, simply type <Leader>/ to stop the highlighting.
nnoremap <silent> <Leader>/ :set nohl<CR>

CTRL-K in Vim produces unexpected results

Hi I'm trying to optimise my window management in vim by mapping ctrlk to ctrl+w, k so i can just press ctrl+k to switch to the split window above the one I'm working in (I'm doing this for h,j and l also but it's only k that's causing the problem).
I've added this into my .vimrc
noremap <silent> <c-k> <C-W>k
noremap <silent> <c-j> <C-W>j
noremap <silent> <c-h> <C-W>h
noremap <silent> <c-l> <C-W>l
However if I press ctrl+k, then something weird happens. It changes depending on where I am in the document.
If I'm at the top of a document with many lines beneath my curser, the cursor hops down a few lines and columns into a completely different place.
If I'm at the bottom of a document, it creates loads of spaces from the cursor onwards.
I've tested and removing the above lines causes the symptoms to stop happening. I'm just really confused as to what is going on!
Some info: I'm using the vim binary that comes with macvim via the command line.
Any help would be greatly appreciated!
Thanks!
I can’t explain the second problem, but if you pasted everything directly from the vimrc then you have lots of trailing spaces that must not be there. It can explain the first problem. Try running
:%sm/\s\+$
then save and see whether problem disappears. If it is so, use
:set list listchars=trail:-
to be able to see trailing spaces so that you won’t run into this problem again.
Maybe <C-k> is already mapped to something else. Try :verbose map <C-k>.
Maybe your mapping is triggered in visual or operator mapping, where <c-w>k has a different meaning.
You could try this:
nnoremap <C-J> <C-W>j
nnoremap <C-K> <C-W>k
nnoremap <C-H> <C-W>h
nnoremap <C-L> <C-W>l
, which will trigger only in normal mode.

Resources