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.


Questions

  • 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?


Requirements

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

Setup

Source code is maintained on GitHub, as are the documentation files and README.md. 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 git@github.com:vim-utilities/nudge-lines.git

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

./linked-install.sh

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


Usage

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

plugin/nudge-lines.vim

#!/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
    return
  endif

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

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

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

  silent! foldopen!
endfunction

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.