Tip #147: How to write a plugin
tip karma |
Rating 61/24, Viewed by 5068
|
created: |
|
October 24, 2001 7:42 |
|
complexity: |
|
advanced |
author: |
|
Charles E. Campbell, Jr. |
|
as of Vim: |
|
6.0 |
This tip gives a skeleton for writing a plugin; Vim's help files have plenty
of details (:he plugin, :he write-plugin, :he plugin-details).
# ------------------------------------------------------------------------------
# Exit when your app has already been loaded (or "compatible" mode set)
if exists("loaded_YourAppName") || &cp;
finish
endif
# Public Interface:
# AppFunction: is a function you expect your users to call
# PickAMap: some sequence of characters that will run your AppFunction
# Repeat these three lines as needed for multiple functions which will
# be used to provide an interface for the user
if !hasmapto('<Plug>AppFunction')
map <unique> <Leader>PickAMap <Plug>AppFunction
endif
# Global Maps:
#
map <silent> <unique> <script> <Plug>AppFunction
\ :set lz<CR>:call <SID>AppFunc<CR>:set nolz<CR>
# ------------------------------------------------------------------------------
# AppFunction: this function is available vi the <Plug>/<script> interface above
fu! <SID>AppFunction()
..whatever..
# your script function can set up maps to internal functions
nmap <silent> <left> :set lz<CR>:silent! call <SID>AppFunction2<CR>:set nolz<CR>
# your app can call functions in its own script and not worry about name
# clashes by preceding those function names with <SID>
call <SID>InternalAppFunction(...)
# or you could call it with
call s:InternalAppFunction(...)
endf
# ------------------------------------------------------------------------------
# InternalAppFunction: this function cannot be called from outside the
# script, and its name won't clash with whatever else the user has loaded
fu! <SID>InternalAppFunction(...)
..whatever..
endf
# ------------------------------------------------------------------------------
Plugins are intended to be "drop into <.vim/plugin>" and work. The problem
that the <Plug>, <SID>, etc stuff is intended to resolve: what to do about
functions that have the same names in different plugins, and what to do about
maps that use the same sequence of characters? The first problem is solved
with <SID> (a script identifier number) that vim assigns: program with it and
your users will be happier when your stuff works with all their other stuff.
The second problem: what to about those maps is addressed with <Plug>, <unique>,
etc. Basically the idea is: let the user know that there are clashes and don't
overwrite previously existing maps. Use the user's preferred map-introducer
sequence (I like the backslash, but there are many keyboards which make
producing backslashes unpleasant, and those users usually prefer something
else).
What I like to do is to have a pair of start/stop maps to reduce my impact on
the namespace. When the starting map is used, it kicks off a starting function
that introduces all the maps needed. When the stopping map is used, it not
only removes the maps the starter made but restores any maps the user had had
that would have clashed. I also use the start/stop pair of functions to set
and restore options that cause my scripts difficulties.
Check out DrawIt.vim's SaveMap() function for a way to save user maps.
Restoring maps with it is easy:
if b:restoremap != ""
exe b:restoremap
unlet b:restoremap
endif
So you can see it sets up a string variable with all the maps that the user
had that would have clashed with my application.
One final thing: if your application needs to share information between its
various functions, see if you can use s:varname (a variable that only your
script's functions can access) or b:varname (a variable that anything associated
with the buffer your application is running with can access) instead of using
global variables.
Good luck and happy Vimming!
<<opening multiple files from a single command-line |
Make great use of those homemade menus >>
Additional Notes
|