0

Say I have a line 1234text5678, where I have selected text in visual mode. I would like to have a command <Shift>+, that moves text to the right one character and selects text again. I.e. the result should be 12345text678, and text being selected. From playing around, I got

xnoremap * dpgv=gv

but this selects 5tex after the movement. How can it be adjusted? (I don't know if this is standard, but on German keyboards <Shift>+ is the same as *.)

Then I would also like to create a similar command to move to the left, but probably I can figure that one out myself once I got the other version.

1

Choice of Mapping

I personnally like to use v_* for searching the visually selected text, similar to what n_* does in normal mode for the word under the cursor. Using v_* for shifting a visual selection sideways is in conflict with vim-visualstar which I think could actually be the default behavior of vanilla vim.

Using viwdp or with an additional movement between d and p here is good enough for me.

A typical related feature request is shifting lines up and down. Greg Hurrell has produced a screencast how to do this (youtube). However, he does not recommend it because:

it encourages bad habits ... do not mash keys ... not the vim way

I agree and would say that repeat is an anti-pattern here.

If you want such behaviour and a direct key to press, consider also following plugins and their suggestions for mappings:

Plugins and their Suggested Mappings

  • vim-move

    The default mappings use the Alt-key as prefix which does not work in all circumstances:

    <A-k>   Move current line/selection up
    <A-j>   Move current line/selection down
    <A-h>   Move current character/selection left
    <A-l>   Move current character/selection right
    
  • vim-textmanip

    xmap <C-j> <Plug>(textmanip-move-down)
    xmap <C-k> <Plug>(textmanip-move-up)
    xmap <C-h> <Plug>(textmanip-move-left)
    xmap <C-l> <Plug>(textmanip-move-right)
    

    The plugin vim-tmux-navigator uses the same set in normal mode to switch windows. This makes them a little bit inconsistent between modes.

  • vim-schlepp

    vmap <unique> <up>    <Plug>SchleppUp
    vmap <unique> <down>  <Plug>SchleppDown
    vmap <unique> <left>  <Plug>SchleppLeft
    vmap <unique> <right> <Plug>SchleppRight
    

    Some may argue arrow keys are too far away from the homerow.

Related Plugins

  • If you want to shift list items, function arguments and similar, consider the plugins sideways.vim and vim-swap. Suggested mappings by the plugin author Andrew Radev are again:

    nnoremap <c-h> :SidewaysLeft<cr>
    nnoremap <c-l> :SidewaysRight<cr>
    

    vim-swap defines following two which I think are a quite good choice:

    nmap g< <Plug>(swap-prev)
    nmap g> <Plug>(swap-next)
    
  • vim-exchange works differently by not shifting things around. I think this plugin fits better to the vim way. The mappings are

    call s:create_map('n', 'cx', '<Plug>(Exchange)')
    call s:create_map('x', 'X', '<Plug>(Exchange)')
    call s:create_map('n', 'cxx', '<Plug>(ExchangeLine)')
    

    and allows to use . if the target is addressed by the same mapping. E.g. swapping distant lines cxx, <no>G and then press . or cxiw, move and then ..

    I point the reader to the screencast by Drew Neil to see it in action.

1

Here’s two alternative solutions:

xnoremap * dp`[1v

xnoremap * dpgvlol
  • `[ — Jump to start of pasted text
  • 1v — reselect the same amount of text as the last visual operation, but starting from the current cursor position
  • gv — reselect the same visual area as last selection,
  • lol — move visual selection right by moving the end one character to the right, and then jumping to the start and moving that one character to the right also.
2
  • 1
    Didn't know [count]v, thanks +1. But to be precise, it should be last visual operation instead of last selection, it's quite different. – dedowsdi May 19 '19 at 0:06
  • Yes, I was sloppy there. I’ll correct. Thanks! – Rich May 19 '19 at 6:27
0
xnoremap * dp`[v`]
  • dp shift right
  • `[v`] select newly pasted content.
    • :h `[ mark start of last changed or yanked text.
    • :h `] mark end of last changed or yanked text.

Your Answer

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