Case Study in Vim Plugin Development
I don’t know a lot about writing plugins.
My own experience goes as far as trying to write a plugin for Eclipse (which
gets very complicated as soon as a plugin isn’t a “monolithic” bundle); as
well as writing a quite small plugin for my C
worksheet. (The fanciest thing it
does is to download a JAR archive dependency if not present in the system.).
So I’m not particularly qualified to say what is or isn’t a good plugin architecture, etc.
I recently came across the problem: “In Vim, use *
to find next occurence of
current selection in visual mode”.
Vim doesn’t offer this behaviour out of the box.
The fella on IRC was using
nelstrom/vim-visual-star-search.
The readme for this somewhat helpfully links to
thinca/vim-visualstar. – Neither
of these repos is outstandingly popular.
Nelstrom remarks “Looks like it uses a lot more code to do pretty much the same thing. Is it better?”.
Nelstrom’s plugin is simple enough to show here:
" From http://got-ravings.blogspot.com/2008/07/vim-pr0n-visual-search-mappings.html
" makes * and # work on visual mode too.
function! s:VSetSearch(cmdtype)
let temp = @s
norm! gv"sy
let @/ = '\V' . substitute(escape(@s, a:cmdtype.'\'), '\n', '\\n', 'g')
let @s = temp
endfunction
xnoremap * :<C-u>call <SID>VSetSearch('/')<CR>/<C-R>=@/<CR><CR>
xnoremap # :<C-u>call <SID>VSetSearch('?')<CR>?<C-R>=@/<CR><CR>
" recursively vimgrep for word under cursor or selection if you hit leader-star
nmap <leader>* :execute 'noautocmd vimgrep /\V' . substitute(escape(expand("<cword>"), '\'), '\n', '\\n', 'g') . '/ **'<CR>
vmap <leader>* :<C-u>call <SID>VSetSearch()<CR>:execute 'noautocmd vimgrep /' . @/ . '/ **'<CR>
Thinca’s is certainly longer:
function! s:search(type, g)
let s:count = v:count1 . a:type
let reg = '"'
let [save_reg, save_type] = [getreg(reg), getregtype(reg)]
normal! gv""y
let text = @"
call setreg(reg, save_reg, save_type)
let [pre, post] = ['', '']
if !a:g
....
endif
let text = substitute(escape(text, '\' . a:type), "\n", '\\n', 'g')
let @/ = '\V' . pre . text . post
call histadd('/', @/)
endfunction
(Code truncated at ....
for brevity).
With my current proficiency, I’m sure Nelstrom writes closer to how I’d write:
Cites any sources / close inspiration.
Leaves comments explaining anything non-trivial. (Which Thinca doesn’t do AT ALL. Not even for functions!).
Even from this snippet it’s clear that Thinca’s is of higher quality. I’d base
that one the use of functions to do caretaking of the editor environment. –
It’s not clear what the argument g
is for (like the g
in substitute?), but
the ommitted lines seem to take care of some edge case.
– Something to note, I guess, it seems that in both cases the VimL is ‘impure’
in providing read-only info. (Again, I’m not sure if it’s possible to get this
without the caretaking.).
Not hatin’ on Nelstrom: while the Vim community has some excellent plugins, I think most Vim users don’t bother touching VimL enough to learn how to do this kindof thing.