1

Many useful mappings need to temporarily save text.

Some practical examples are:

" Move line up/down
nnoremap <c-j> ddp
nnoremap <c-k> ddkP

" Substitute word under cursor (use `cc` instead of default `S`)
nnoremap SS yiw:s/<c-r>"/
nnoremap S% yiw:%s/<c-r>"/

" Substitute selection
vnoremap SS y:s/<c-r>"/
vnoremap S% y:%s/<c-r>"/

These mappings has to yank a piece of text for later use. I have always used the default register for this but there is a problem with this approach.

By using the default register in the mapping I am overwriting it's previous content.

If the user has yanked some text and then executes one of the mappings the yanked text will be overwritten. This is something very minor but it has started to annoy me lately.

There has to be a better way to do this.

Is there a way to make mappings like these but do not affect the global Vim environment? If not then what is your solution to this problem?

  • 1
    vi.stackexchange.com/q/3997/205? – muru Aug 15 '15 at 20:38
  • It should be noted that S is already a vim normal command (although you can use cc instead). This overshadowing can cause a delay. Also surround.vim, a very common plugin, uses S for visual mappings. Just thoughts to think about when choosing your mappings. You may want to look into <Leader>. See :h <Leader>. – Peter Rincker Aug 17 '15 at 4:51
  • How does overshadowing cause delay? I do use <leader> for most of my mappings but I do not see a problem remapping some of the default bindings that I never use (like H, M, K, L, S and Q). – wefwefa3 Aug 17 '15 at 10:34
3

Move line up/down

nnoremap <key> :<C-u>silent! move+<CR>==
nnoremap <key> :<C-u>silent! move-2<CR>==

Explanation:

  • <C-u> is used to get rid of any automatically added range (safer but not strictly necessary)
  • :silent! prevents useless output
  • :move+ moves the line below the line below
  • :move-2 moves the line below the second line above

See:

:help c_ctrl-u
:help :silent
:help :move
:help range

Substitute word under cursor

nnoremap <key> :s/\<<C-r><C-w>\>/
nnoremap <key> :%s/\<<C-r><C-w>\>/

Explanation:

  • In the command-line, <C-r><C-w> is used to insert the word under the cursor.
  • \<pattern\> restrict matches to whole words so you match pattern but not mypatterniscool

See:

:help c_ctrl-r_ctrl-w
:help \<

Substitute selection

This one is a little trickier: we need to yank the visual selection because there's no equivalent of <C-r><C-w> in that context but it's relatively easy to go around that limitation and avoid side effects with a bit of vimscript:

function! GetVisualSelection()
    " save the content of register v (it could be any alphabetic register)
    let old_reg = getreg("v")

    " reselect the visual selection and yank it in register v
    normal! gv"vy

    " get the content of register v (what we just yanked)
    let raw_search = getreg("v")

    " restore register v
    call setreg("v", old_reg)

    " return a sanitize version of the yanked text
    " useful if the text contains "special" characters or is multiline
    return substitute(escape(raw_search, '\/.*$^~[]'), "\n", '\\n', "g")
endfunction

xnoremap <key> :<C-u>s/<C-r>=GetVisualSelection()<CR>/
xnoremap <key> :<C-u>%s/<C-r>=GetVisualSelection()<CR>/

See:

:help :function
:help :let
:help registers
:help :normal
:help gv
:help substitute()
:help escape()
:help c_ctrl-r_=
  • You should also reset the register type see :h getregtype() – Christian Brabandt Aug 16 '15 at 11:44
  • This is mostly workarounds for my specific examples. I was wondering if there is a universal pattern to would work for all mappings that need to yank text. Judging by the low amount of answers I assume that there is not so I will accept this answer as it shows a few good workarounds for the problem. – wefwefa3 Aug 17 '15 at 10:40
  • These are not workaround, they show the "right" way to do what you want. The universal pattern you ask for is demonstrated in GetVisualSelection(): 1. backup an arbitrary register, 2. yank to that register, 3. use the content of that register and 4. restore it when you are done. – romainl Aug 17 '15 at 12:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.