vimscript – Vim plugin Nudge Lines

I’ve published a Vim plugin that nudges visually selected lines up or down, which for the most part seems to function as designed. However, I believe there are likely ways that this plugin could be improved.


  • How do I register a movement that takes an optional amount?

In other words how can this plugin differentiate between Shift^J and 3Shift^J?


This plugin is tested on Linux based operating systems, but suggestions on how to make it OS agnostic are certainly welcomed; regardless Vim should be installed prior to using this plugin, eg…

sudo apt-get install vim


Source code is maintained on GitHub, as are the documentation files and Included within this question are the TLDR and source .vim script code files.

mkdir -vp ~/git/hub/vim-utilities

cd ~/git/hub/vim-utilities

git clone

If not utilizing some form of Vim plugin manager, then the script may be run on most ‘nix devices…


… which will symbolically link plugin scripts and documentation, and update Vim documentation tags.


After visually selecting a line, or range of lines, use the following keyboard shortcuts:

  • Ctrl^k Nudge visual selection up

  • Shift^K Nudge visual selection up and reformat tabs

  • Ctrl^j Nudge visual selection down

  • Shift^J Nudge visual selection down and reformat tabs

Source Code


#!/usr/bin/env vim

vnoremap <S-K> :call Nudge_Selection__Laterally(-1, 'reformat')<CR>
vnoremap <C-K> :call Nudge_Selection__Laterally(-1)<CR>

vnoremap <S-J> :call Nudge_Selection__Laterally(1, 'reformat')<CR>
vnoremap <C-J> :call Nudge_Selection__Laterally(1)<CR>

" Nudges visually selected lines up or down
" @param {number} a:amount - Signed integer of lines to nudge selection by
" @param {string()} a:0 - Optionally reformat tabs
" @example
"   :'<,'> call Nudge_Selection__Laterally(-1, 'reformat')
" @author S0AndS0
" @license AGPL-3.0
function! Nudge_Selection__Laterally(amount, ...) abort range
  let l:not_visual_mode = visualmode() != 'V'
  let l:at_limits__lower = a:lastline == line('$')
  let l:at_limits__upper = a:firstline == 1
  if l:not_visual_mode
   || (a:amount > 0 && l:at_limits__lower)
   || (a:amount < 0 && l:at_limits__upper)
    normal! gv

  if a:amount > 0
    let l:move_command = "'>+" . a:amount
  elseif a:amount < 0
    let l:move_command = "'<-" . (1 - a:amount)
    throw 'amount must be greater or less than 0'

  execute "'<,'>move " . l:move_command

  if a:0 == 0
    normal! gv
    normal! gv=gv

  silent! foldopen!

Side note, I’m not sure what’s going on with syntax highlighting here, but as of latest revisions this plugin seem to function without error.