Vim Tips Wiki
Tip 591 Printable Monobook Previous Next

created 2003 · complexity intermediate · author Jean-Christophe Clavier · version 6.0

Are you tired of hundreds of mappings and functions that pollute your vimrc? Do you want to nicely organize your customization to quickly find what you search ? Perhaps is it time for you to consider the use of plugins (if it is not already done).

Plugins are really easy to do and provide a simple way to organize functions and mappings. They are automatically loaded.

Here is an example of simple and very short plugin that provides a command :MyCommand that saves the selected text in the file passed in parameter. I don't know if the function is useful but the example show the parameter passing, the autocompletion and the use of ranges in a function.

Autocompletion is very practical to help to remember the commands you defined. It is often a problem to remember all the mappings you've done so it may be faster to type your command than to remember the mapping you've chosen.

Using user-commands allows you to use mappings only when it is absolutely pertinent.

" file MyPlugin.vim
" save 'cpo'
let s:cpo_save = &cpo
set cpo&vim

" To Edit the Plugin
nnoremap <F12> :e $VIMRUNTIME/plugins/MyPlugin.vim
" To reload the plugin if you modify it
nnoremap <S-F12> :so $VIMRUNTIME/plugins/MyPlugin.vim

" It is very interesting to define commands to call your functions because you can then use
" autocompletion and other features you cannot use for usual functions
if !exists(':MyCommand')
  command -range=% -nargs=1 -complete=file MyCommand <line1>,<line2>call s:MyCommandFunction(<f-args>)

" the ! allows you to modify the function and reload the plugin. It will be your new version that
" will be considered
function! s:MyCommandFunction(...) range
  execute "norm! " . a:firstline . "GV"
  execute "norm! " . a:lastline . 'G"ay'
  norm! "ap
  exe "sav! " . a:1

" restore 'cpo'
let &cpo = s:cpo_save
unlet s:cpo_save

Commented version of the function:

function! s:MyCommandFunction(...) range
  " create a temporary window
  " select and copy the lines in the range passed (a:firstline and a:lastline are the vim
  " variables for the first and the last lien of the range)
  execute "norm! " . a:firstline . "GV"
  execute "norm! " . a:lastline . 'G"ay'
  " create a new file and paste
  norm! "ap
  " saves the file with the name passed in parameter
  " exe executes the string passed as a command
  " a:1 is the first parameter (if you have more, a:2, a:3. a:0 gives you the number of parameter
  " passed
  exe "sav! " . a:1
  " quit the temporary window

Of course you can separate your functions in different plugins (one for the mapping, one for the functions... You can use prefix to classify your functions and use the autocompletion more efficiently.



I definitively agree that plugins are a must -- AFAIK, ftplugins are the major improvment of Vim over Vi.

However, I have a few remarks:

  • You forget the anti-reinclusion guards,
  • You can propose a way to override the default mappings you propose in your plugin -- check VimTip147 that is a must-read
  • You'd better always use ":normal!" and "*noremap" instead of ":normal" and ":*map". We are never sure of mappings defined into other plugins.
  • If you want the exact path of the current plugin:
let s:file = expand('<sfile>:p')
nnoremap <silent> <s-12> :silent exe 'source '.s:file

But a better solution is to rely on ":runtime". BTW, $VIMRUNTIME is not really meant to be polluted with our own scripts.