2b3d5ee5c4a4

Add a unit test. This here is a grey triangle moment, folks.
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Wed, 10 Nov 2010 19:52:08 -0500
parents f51ce473589b
children 30bd82f5d2cd
branches/tags (none)
files tests/bundled/lh-vim-lib/autoload/lh/UT.vim tests/bundled/lh-vim-lib/autoload/lh/askvim.vim tests/bundled/lh-vim-lib/autoload/lh/buffer.vim tests/bundled/lh-vim-lib/autoload/lh/buffer/dialog.vim tests/bundled/lh-vim-lib/autoload/lh/command.vim tests/bundled/lh-vim-lib/autoload/lh/common.vim tests/bundled/lh-vim-lib/autoload/lh/encoding.vim tests/bundled/lh-vim-lib/autoload/lh/env.vim tests/bundled/lh-vim-lib/autoload/lh/event.vim tests/bundled/lh-vim-lib/autoload/lh/function.vim tests/bundled/lh-vim-lib/autoload/lh/graph/tsort.vim tests/bundled/lh-vim-lib/autoload/lh/list.vim tests/bundled/lh-vim-lib/autoload/lh/menu.vim tests/bundled/lh-vim-lib/autoload/lh/option.vim tests/bundled/lh-vim-lib/autoload/lh/path.vim tests/bundled/lh-vim-lib/autoload/lh/position.vim tests/bundled/lh-vim-lib/autoload/lh/syntax.vim tests/bundled/lh-vim-lib/autoload/lh/visual.vim tests/bundled/lh-vim-lib/doc/lh-vim-lib.txt tests/bundled/lh-vim-lib/lh-vim-lib.README tests/bundled/lh-vim-lib/macros/menu-map.vim tests/bundled/lh-vim-lib/mkVba/mk-lh-vim-lib.vim tests/bundled/lh-vim-lib/plugin/let.vim tests/bundled/lh-vim-lib/plugin/lhvl.vim tests/bundled/lh-vim-lib/plugin/ui-functions.vim tests/bundled/lh-vim-lib/plugin/words_tools.vim tests/bundled/lh-vim-lib/tests/lh/function.vim tests/bundled/lh-vim-lib/tests/lh/list.vim tests/bundled/lh-vim-lib/tests/lh/path.vim tests/bundled/lh-vim-lib/tests/lh/test-Fargs2String.vim tests/bundled/lh-vim-lib/tests/lh/test-askmenu.vim tests/bundled/lh-vim-lib/tests/lh/test-command.vim tests/bundled/lh-vim-lib/tests/lh/test-menu-map.vim tests/bundled/lh-vim-lib/tests/lh/test-toggle-menu.vim tests/bundled/lh-vim-lib/tests/lh/topological-sort.vim tests/bundled/ut/UT.README tests/bundled/ut/autoload/lh/UT.vim tests/bundled/ut/autoload/should/be.vim tests/bundled/ut/doc/UT.txt tests/bundled/ut/ftplugin/vim/vim_UT.vim tests/bundled/ut/mkVba/mk-UT.vim tests/bundled/ut/plugin/UT.vim tests/bundled/ut/tests/lh/UT-fixtures.vim tests/bundled/ut/tests/lh/UT.vim tests/run-tests.sh tests/test-toggle.vim tests/vim_test/autoload/lh tests/vim_test/colors/desert.vim tests/vim_test/ftplugin/vim tests/vim_test/macros/menu-map.vim tests/vim_test/plugin/UT.vim tests/vim_test/plugin/gundo.vim tests/vim_test/plugin/let.vim tests/vim_test/plugin/lhvl.vim tests/vim_test/plugin/ui-functions.vim tests/vim_test/plugin/words_tools.vim tests/vimrc_test

Changes

--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/lh-vim-lib/autoload/lh/UT.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,1 @@
+/Users/sjl/src/gundo.vim/tests/bundled/ut/autoload/lh/UT.vim
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/lh-vim-lib/autoload/lh/askvim.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,147 @@
+"=============================================================================
+" $Id: askvim.vim 246 2010-09-19 22:40:58Z luc.hermitte $
+" File:		autoload/lh/askvim.vim                                    {{{1
+" Author:	Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
+"		<URL:http://code.google.com/p/lh-vim/>
+" Version:	2.2.1
+" Created:	17th Apr 2007
+" Last Update:	$Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $ (17th Apr 2007)
+"------------------------------------------------------------------------
+" Description:	
+" 	Defines functions that asks vim what it is relinquish to tell us
+" 	- menu
+" 
+"------------------------------------------------------------------------
+" Installation:	
+" 	Drop it into {rtp}/autoload/lh/
+" 	Vim 7+ required.
+" History:	
+" 	v2.0.0:
+" TODO:		«missing features»
+" }}}1
+"=============================================================================
+
+
+"=============================================================================
+let s:cpo_save=&cpo
+set cpo&vim
+
+"------------------------------------------------------------------------
+" ## Functions {{{1
+" # Debug {{{2
+function! lh#askvim#verbose(level)
+  let s:verbose = a:level
+endfunction
+
+function! s:Verbose(expr)
+  if exists('s:verbose') && s:verbose
+    echomsg a:expr
+  endif
+endfunction
+
+function! lh#askvim#debug(expr)
+  return eval(a:expr)
+endfunction
+
+"------------------------------------------------------------------------
+" # Public {{{2
+" Function: lh#askvim#exe(command) {{{3
+function! lh#askvim#Exe(command)
+  echomsg 'lh#askvim#Exe() is deprecated, use lh#askvim#exe()'
+  return lh#askvim#exe(a:command)
+endfunction
+
+function! lh#askvim#exe(command)
+  let save_a = @a
+  try 
+    silent! redir @a
+    silent! exe a:command
+    redir END
+  finally
+    " Always restore everything
+    let res = @a
+    let @a = save_a
+    return res
+  endtry
+endfunction
+
+
+" Function: lh#askvim#menu(menuid) {{{3
+function! s:AskOneMenu(menuact, res)
+  let sKnown_menus = lh#askvim#exe(a:menuact)
+  let lKnown_menus = split(sKnown_menus, '\n')
+  " echo string(lKnown_menus)
+
+  " 1- search for the menuid
+  " todo: fix the next line to correctly interpret "stuff\.stuff" and
+  " "stuff\\.stuff".
+  let menuid_parts = split(a:menuact, '\.')
+
+  let simplifiedKnown_menus = deepcopy(lKnown_menus)
+  call map(simplifiedKnown_menus, 'substitute(v:val, "&", "", "g")')
+  " let idx = lh#list#match(simplifiedKnown_menus, '^\d\+\s\+'.menuid_parts[-1])
+  let idx = match(simplifiedKnown_menus, '^\d\+\s\+'.menuid_parts[-1])
+  if idx == -1
+    " echo "not found"
+    return
+  endif
+  " echo "l[".idx."]=".lKnown_menus[idx]
+
+  if empty(a:res)
+    let a:res.priority = matchstr(lKnown_menus[idx], '\d\+\ze\s\+.*')
+    let a:res.name     = matchstr(lKnown_menus[idx], '\d\+\s\+\zs.*')
+    let a:res.actions  = {}
+  " else
+  "   what if the priority isn't the same?
+  endif
+
+  " 2- search for the menu definition
+  let idx += 1
+  while idx != len(lKnown_menus)
+    echo "l[".idx."]=".lKnown_menus[idx]
+    " should not happen
+    if lKnown_menus[idx] =~ '^\d\+' | break | endif
+
+    " :h showing-menus
+    " -> The format of the result of the call to Exe() seems to be:
+    "    ^ssssMns-sACTION$
+    "    s == 1 whitespace
+    "    M == mode (inrvcs)
+    "    n == noremap(*)/script(&)
+    "    - == disable(-)/of not
+    let act = {}
+    let menu_def = matchlist(lKnown_menus[idx],
+	  \ '^\s*\([invocs]\)\([&* ]\) \([- ]\) \(.*\)$')
+    if len(menu_def) > 4
+      let act.mode        = menu_def[1]
+      let act.nore_script = menu_def[2]
+      let act.disabled    = menu_def[3]
+      let act.action      = menu_def[4]
+    else
+      echomsg string(menu_def)
+      echoerr "lh#askvim#menu(): Cannot decode ``".lKnown_menus[idx]."''"
+    endif
+    
+    let a:res.actions["mode_" . act.mode] = act
+
+    let idx += 1
+  endwhile
+
+  " n- Return the result
+  return a:res
+endfunction
+
+function! lh#askvim#menu(menuid, modes)
+  let res = {}
+  let i = 0
+  while i != strlen(a:modes)
+    call s:AskOneMenu(a:modes[i].'menu '.a:menuid, res)
+    let i += 1
+  endwhile
+  return res
+endfunction
+" Functions }}}1
+"------------------------------------------------------------------------
+let &cpo=s:cpo_save
+"=============================================================================
+" vim600: set fdm=marker:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/lh-vim-lib/autoload/lh/buffer.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,97 @@
+"=============================================================================
+" $Id: buffer.vim 246 2010-09-19 22:40:58Z luc.hermitte $
+" File:		autoload/lh/buffer.vim                               {{{1
+" Author:	Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
+"		<URL:http://code.google.com/p/lh-vim/>
+" Version:	2.2.1
+" Created:	23rd Jan 2007
+" Last Update:	$Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $
+"------------------------------------------------------------------------
+" Description:	
+" 	Defines functions that help finding windows and handling buffers.
+" 
+"------------------------------------------------------------------------
+" Installation:	
+" 	Drop it into {rtp}/autoload/lh/
+" 	Vim 7+ required.
+" History:	
+"	v 1.0.0 First Version
+" 	(*) Functions moved from searchInRuntimeTime  
+" 	v 2.2.0
+" 	(*) new function: lh#buffer#list()
+" TODO:	
+" }}}1
+"=============================================================================
+
+
+"=============================================================================
+let s:cpo_save=&cpo
+set cpo&vim
+
+" ## Functions {{{1
+"------------------------------------------------------------------------
+" # Debug {{{2
+function! lh#buffer#verbose(level)
+  let s:verbose = a:level
+endfunction
+
+function! s:Verbose(expr)
+  if exists('s:verbose') && s:verbose
+    echomsg a:expr
+  endif
+endfunction
+
+function! lh#buffer#debug(expr)
+  return eval(a:expr)
+endfunction
+
+"------------------------------------------------------------------------
+" # Public {{{2
+
+" Function: lh#buffer#find({filename}) {{{3
+" If {filename} is opened in a window, jump to this window, otherwise return -1
+" Moved from searchInRuntimeTime.vim
+function! lh#buffer#find(filename)
+  let b = bufwinnr(a:filename)
+  if b == -1 | return b | endif
+  exe b.'wincmd w'
+  return b
+endfunction
+function! lh#buffer#Find(filename)
+  return lh#buffer#find(a:filename)
+endfunction
+
+" Function: lh#buffer#jump({filename},{cmd}) {{{3
+function! lh#buffer#jump(filename, cmd)
+  if lh#buffer#find(a:filename) != -1 | return | endif
+  exe a:cmd . ' ' . a:filename
+endfunction
+function! lh#buffer#Jump(filename, cmd)
+  return lh#buffer#jump(a:filename, a:cmd)
+endfunction
+
+" Function: lh#buffer#scratch({bname},{where}) {{{3
+function! lh#buffer#scratch(bname, where)
+  try
+    silent exe a:where.' sp '.a:bname
+  catch /.*/
+    throw "Can't open a buffer named '".a:bname."'!"
+  endtry
+  setlocal bt=nofile bh=wipe nobl noswf ro
+endfunction
+function! lh#buffer#Scratch(bname, where)
+  return lh#buffer#scratch(a:bname, a:where)
+endfunction
+
+" Function: lh#buffer#list() {{{3
+function! lh#buffer#list()
+  let all = range(0, bufnr('$'))
+  " let res = lh#list#transform_if(all, [], 'v:1_', 'buflisted')
+  let res = lh#list#copy_if(all, [], 'buflisted')
+  return res
+endfunction
+" Ex: echo lh#list#transform(lh#buffer#list(), [], "bufname")
+"=============================================================================
+let &cpo=s:cpo_save
+"=============================================================================
+" vim600: set fdm=marker:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/lh-vim-lib/autoload/lh/buffer/dialog.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,268 @@
+"=============================================================================
+" $Id: dialog.vim 246 2010-09-19 22:40:58Z luc.hermitte $
+" File:		autoload/lh/buffer/dialog.vim                            {{{1
+" Author:	Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
+"		<URL:http://code.google.com/p/lh-vim/>
+" Version:	2.2.1
+" Created:	21st Sep 2007
+" Last Update:	$Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $
+"------------------------------------------------------------------------
+" Description:	«description»
+" 
+"------------------------------------------------------------------------
+" Installation:	
+" 	Drop it into {rtp}/autoload/lh/
+" 	Vim 7+ required.
+" History:	
+"	v 1.0.0 First Version
+" 	(*) Functions imported from Mail_mutt_alias.vim
+" TODO:		
+" 	(*) --abort-- line
+" 	(*) custom messages
+" 	(*) do not mess with search history
+" 	(*) support any &magic
+" 	(*) syntax
+" 	(*) add number/letters
+" 	(*) tag with '[x] ' instead of '* '
+" }}}1
+"=============================================================================
+
+
+"=============================================================================
+let s:cpo_save=&cpo
+set cpo&vim
+
+
+
+"=============================================================================
+" ## Globals {{{1
+let s:LHdialog = {}
+
+"=============================================================================
+" ## Functions {{{1
+" # Debug {{{2
+function! lh#buffer#dialog#verbose(level)
+  let s:verbose = a:level
+endfunction
+
+function! s:Verbose(expr)
+  if exists('s:verbose') && s:verbose
+    echomsg a:expr
+  endif
+endfunction
+
+function! lh#buffer#dialog#debug(expr)
+  return eval(a:expr)
+endfunction
+
+
+"=============================================================================
+" # Dialog functions {{{2
+"------------------------------------------------------------------------
+function! s:Mappings(abuffer)
+  " map <enter> to edit a file, also dbl-click
+  exe "nnoremap <silent> <buffer> <esc>         :silent call ".a:abuffer.action."(-1, ".a:abuffer.id.")<cr>"
+  exe "nnoremap <silent> <buffer> q             :call lh#buffer#dialog#select(-1, ".a:abuffer.id.")<cr>"
+  exe "nnoremap <silent> <buffer> <cr>          :call lh#buffer#dialog#select(line('.'), ".a:abuffer.id.")<cr>"
+  " nnoremap <silent> <buffer> <2-LeftMouse> :silent call <sid>GrepEditFileLine(line("."))<cr>
+  " nnoremap <silent> <buffer> Q	  :call <sid>Reformat()<cr>
+  " nnoremap <silent> <buffer> <Left>	  :set tabstop-=1<cr>
+  " nnoremap <silent> <buffer> <Right>	  :set tabstop+=1<cr>
+  if a:abuffer.support_tagging
+    nnoremap <silent> <buffer> t	  :silent call <sid>ToggleTag(line("."))<cr>
+    nnoremap <silent> <buffer> <space>	  :silent call <sid>ToggleTag(line("."))<cr>
+  endif
+  nnoremap <silent> <buffer> <tab>	  :silent call <sid>NextChoice('')<cr>
+  nnoremap <silent> <buffer> <S-tab>	  :silent call <sid>NextChoice('b')<cr>
+  exe "nnoremap <silent> <buffer> h	  :silent call <sid>ToggleHelp(".a:abuffer.id.")<cr>"
+endfunction
+
+"----------------------------------------
+" Tag / untag the current choice {{{
+function! s:ToggleTag(lineNum)
+   if a:lineNum > s:Help_NbL()
+      " If tagged
+      if (getline(a:lineNum)[0] == '*')
+	let b:NbTags = b:NbTags - 1
+	silent exe a:lineNum.'s/^\* /  /e'
+      else
+	let b:NbTags = b:NbTags + 1
+	silent exe a:lineNum.'s/^  /* /e'
+      endif
+      " Move after the tag ; there is something with the two previous :s. They
+      " don't leave the cursor at the same position.
+      silent! normal! 3|
+      call s:NextChoice('') " move to the next choice
+    endif
+endfunction
+" }}}
+
+function! s:Help_NbL()
+  " return 1 + nb lines of BuildHelp
+  return 2 + len(b:dialog['help_'.b:dialog.help_type])
+endfunction
+"----------------------------------------
+" Go to the Next (/previous) possible choice. {{{
+function! s:NextChoice(direction)
+  " echomsg "next!"
+  call search('^[ *]\s*\zs\S\+', a:direction)
+endfunction
+" }}}
+
+"------------------------------------------------------------------------
+
+function! s:RedisplayHelp(dialog)
+  silent! 2,$g/^@/d_
+  normal! gg
+  for help in a:dialog['help_'.a:dialog.help_type]
+    silent put=help
+  endfor
+endfunction
+
+function! lh#buffer#dialog#update(dialog)
+  set noro
+  exe (s:Help_NbL()+1).',$d_'
+  for choice in a:dialog.choices
+    silent $put='  '.choice
+  endfor
+  set ro
+endfunction
+
+function! s:Display(dialog, atitle)
+  set noro
+  0 put = a:atitle
+  call s:RedisplayHelp(a:dialog)
+  for choice in a:dialog.choices
+    silent $put='  '.choice
+  endfor
+  set ro
+  exe s:Help_NbL()+1
+endfunction
+
+function! s:ToggleHelp(bufferId)
+  call lh#buffer#find(a:bufferId)
+  call b:dialog.toggle_help()
+endfunction
+
+function! lh#buffer#dialog#toggle_help() dict
+  let self.help_type 
+	\ = (self.help_type == 'short')
+	\ ? 'long'
+	\ : 'short'
+  call s:RedisplayHelp(self)
+endfunction
+
+function! lh#buffer#dialog#new(bname, title, where, support_tagging, action, choices)
+  " The ID will be the buffer id
+  let res = {}
+  let where_it_started = getpos('.')
+  let where_it_started[0] = bufnr('%')
+  let res.where_it_started = where_it_started
+
+  try
+    call lh#buffer#scratch(a:bname, a:where)
+  catch /.*/
+    echoerr v:exception
+    return res
+  endtry
+  let res.id              = bufnr('%')
+  let b:NbTags            = 0
+  let b:dialog            = res
+  let s:LHdialog[res.id]  = res
+  let res.help_long       = []
+  let res.help_short      = []
+  let res.help_type       = 'short'
+  let res.support_tagging = a:support_tagging
+  let res.action	  = a:action
+  let res.choices	  = a:choices
+
+  " Long help
+  call lh#buffer#dialog#add_help(res, '@| <cr>, <double-click>    : select this', 'long')
+  call lh#buffer#dialog#add_help(res, '@| <esc>, q                : Abort', 'long')
+  if a:support_tagging
+    call lh#buffer#dialog#add_help(res, '@| <t>, <space>            : Tag/Untag the current item', 'long')
+  endif
+  call lh#buffer#dialog#add_help(res, '@| <up>/<down>, <tab>, +/- : Move between entries', 'long')
+  call lh#buffer#dialog#add_help(res, '@|', 'long')
+  " call lh#buffer#dialog#add_help(res, '@| h                       : Toggle help', 'long')
+  call lh#buffer#dialog#add_help(res, '@+'.repeat('-', winwidth(bufwinnr(res.id))-3), 'long')
+  " Short Help
+  " call lh#buffer#dialog#add_help(res, '@| h                       : Toggle help', 'short')
+  call lh#buffer#dialog#add_help(res, '@+'.repeat('-', winwidth(bufwinnr(res.id))-3), 'short')
+
+  let res.toggle_help = function("lh#buffer#dialog#toggle_help")
+  let title = '@  ' . a:title
+  let helpstr = '| Toggle (h)elp'
+  let title = title 
+	\ . repeat(' ', winwidth(bufwinnr(res.id))-strlen(title)-strlen(helpstr)-1)
+	\ . helpstr
+  call s:Display(res, title)
+ 
+  call s:Mappings(res)
+  return res
+endfunction
+
+function! lh#buffer#dialog#add_help(abuffer, text, help_type)
+  call add(a:abuffer['help_'.a:help_type],a:text)
+endfunction
+
+"=============================================================================
+function! lh#buffer#dialog#quit()
+  let bufferId = b:dialog.where_it_started[0]
+  echohl WarningMsg
+  echo "Abort"
+  echohl None
+  quit
+  call lh#buffer#find(bufferId)
+endfunction
+
+" Function: lh#buffer#dialog#select(line, bufferId [,overriden-action])
+function! lh#buffer#dialog#select(line, bufferId, ...)
+  if a:line == -1
+    call lh#buffer#dialog#quit()
+    return
+  " elseif a:line <= s:Help_NbL() + 1
+  elseif a:line <= s:Help_NbL() 
+    echoerr "Unselectable item"
+    return 
+  else
+    let dialog = s:LHdialog[a:bufferId]
+    let results = { 'dialog' : dialog, 'selection' : []  }
+
+    if b:NbTags == 0
+      " -1 because first index is 0
+      " let results = [ dialog.choices[a:line - s:Help_NbL() - 1] ]
+      let results.selection = [ a:line - s:Help_NbL() - 1 ]
+    else
+      silent g/^* /call add(results.selection, line('.')-s:Help_NbL()-1)
+    endif
+  endif
+
+  if a:0 > 0 " action overriden
+    exe 'call '.dialog.action.'(results, a:000)'
+  else
+    exe 'call '.dialog.action.'(results)'
+  endif
+endfunction
+function! lh#buffer#dialog#Select(line, bufferId, ...)
+  echomsg "lh#buffer#dialog#Select() is deprecated, use lh#buffer#dialog#select() instead"
+  if a:0 > 0 " action overriden
+    exe 'call lh#buffer#dialog#select(a:line,  a:bufferId, a:1)'
+  else
+    exe 'call lh#buffer#dialog#select(a:line,  a:bufferId)'
+  endif
+endfunction
+
+function! Action(results)
+  let dialog = a:results.dialog
+  let choices = dialog.choices
+  for r in a:results.selection
+    echomsg '-> '.choices[r]
+  endfor
+endfunction
+
+
+"=============================================================================
+let &cpo=s:cpo_save
+"=============================================================================
+" vim600: set fdm=marker:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/lh-vim-lib/autoload/lh/command.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,224 @@
+"=============================================================================
+" $Id: command.vim 246 2010-09-19 22:40:58Z luc.hermitte $
+" File:		autoload/lh/command.vim                               {{{1
+" Author:	Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
+"		<URL:http://code.google.com/p/lh-vim/>
+" Version:	2.2.1
+" Created:	08th Jan 2007
+" Last Update:	$Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $ (08th Jan 2007)
+"------------------------------------------------------------------------
+" Description:	
+" 	Helpers to define commands that:
+" 	- support subcommands
+" 	- support autocompletion
+" 
+"------------------------------------------------------------------------
+" Installation:	
+" 	Drop it into {rtp}/autoload/lh/
+" 	Vim 7+ required.
+" History:	
+" 	v2.0.0:
+" 		Code move from other plugins
+" TODO:		«missing features»
+" }}}1
+"=============================================================================
+
+
+"=============================================================================
+let s:cpo_save=&cpo
+set cpo&vim
+
+" ## Debug {{{1
+function! lh#command#verbose(level)
+  let s:verbose = a:level
+endfunction
+
+function! s:Verbose(expr)
+  if exists('s:verbose') && s:verbose
+    echomsg a:expr
+  endif
+endfunction
+
+function! lh#command#debug(expr)
+  return eval(a:expr)
+endfunction
+
+"------------------------------------------------------------------------
+" ## Functions {{{1
+
+" Tool functions {{{2
+" Function: lh#command#Fargs2String(aList) {{{3
+" @param[in,out] aList list of params from <f-args>
+" @see tests/lh/test-Fargs2String.vim
+function! lh#command#Fargs2String(aList)
+  if empty(a:aList) | return '' | endif
+
+  let quote_char = a:aList[0][0] 
+  let res = a:aList[0]
+  call remove(a:aList, 0)
+  if quote_char !~ '["'."']"
+    return res
+  endif
+  " else
+  let end_string = '[^\\]\%(\\\\\)*'.quote_char.'$'
+  while !empty(a:aList) && res !~ end_string 
+    let res .= ' ' . a:aList[0]
+    call remove(a:aList, 0)
+  endwhile
+  return res
+endfunction
+
+"------------------------------------------------------------------------
+" ## Experimental Functions {{{1
+
+" Internal functions        {{{2
+" Function: s:SaveData({Data})                             {{{3
+" @param Data Command definition
+" Saves {Data} as s:Data{s:data_id++}. The definition will be used by
+" automatically generated commands.
+" @return s:data_id
+let s:data_id = 0
+function! s:SaveData(Data)
+  if has_key(a:Data, "command_id")
+    " Avoid data duplication
+    return a:Data.command_id
+  else
+    let s:Data{s:data_id} = a:Data
+    let id = s:data_id
+    let s:data_id += 1
+    let a:Data.command_id = id
+    return id
+  endif
+endfunction
+
+" BTWComplete(ArgLead, CmdLine, CursorPos):      Auto-complete {{{3
+function! lh#command#complete(ArgLead, CmdLine, CursorPos)
+  let tmp = substitute(a:CmdLine, '\s*\S*', 'Z', 'g')
+  let pos = strlen(tmp)
+  if 0
+    call confirm( "AL = ". a:ArgLead."\nCL = ". a:CmdLine."\nCP = ".a:CursorPos
+	  \ . "\ntmp = ".tmp."\npos = ".pos
+	  \, '&Ok', 1)
+  endif
+
+  if     2 == pos
+    " First argument: a command
+    return s:commands
+  elseif 3 == pos
+    " Second argument: first arg of the command
+    if     -1 != match(a:CmdLine, '^BTW\s\+echo')
+      return s:functions . "\n" . s:variables
+    elseif -1 != match(a:CmdLine, '^BTW\s\+\%(help\|?\)')
+    elseif -1 != match(a:CmdLine, '^BTW\s\+\%(set\|add\)\%(local\)\=')
+      " Adds a filter
+      " let files =         globpath(&rtp, 'compiler/BT-*')
+      " let files = files . globpath(&rtp, 'compiler/BT_*')
+      " let files = files . globpath(&rtp, 'compiler/BT/*')
+      let files = s:FindFilter('*')
+      let files = substitute(files,
+	    \ '\(^\|\n\).\{-}compiler[\\/]BTW[-_\\/]\(.\{-}\)\.vim\>\ze\%(\n\|$\)',
+	    \ '\1\2', 'g')
+      return files
+    elseif -1 != match(a:CmdLine, '^BTW\s\+remove\%(local\)\=')
+      " Removes a filter
+      return substitute(s:FiltersList(), ',', '\n', 'g')
+    endif
+  endif
+  " finally: unknown
+  echoerr 'BTW: unespected parameter ``'. a:ArgLead ."''"
+  return ''
+endfunction
+
+function! s:BTW(command, ...)
+  " todo: check a:0 > 1
+  if     'set'      == a:command | let g:BTW_build_tool = a:1
+    if exists('b:BTW_build_tool')
+      let b:BTW_build_tool = a:1
+    endif
+  elseif 'setlocal'     == a:command | let b:BTW_build_tool = a:1
+  elseif 'add'          == a:command | call s:AddFilter('g', a:1)
+  elseif 'addlocal'     == a:command | call s:AddFilter('b', a:1)
+    " if exists('b:BTW_filters_list') " ?????
+    " call s:AddFilter('b', a:1)
+    " endif
+  elseif 'remove'       == a:command | call s:RemoveFilter('g', a:1)
+  elseif 'removelocal'  == a:command | call s:RemoveFilter('b', a:1)
+  elseif 'rebuild'      == a:command " wait for s:ReconstructToolsChain()
+  elseif 'echo'         == a:command | exe "echo s:".a:1
+    " echo s:{a:f1} ## don't support «echo s:f('foo')»
+  elseif 'reloadPlugin' == a:command
+    let g:force_reload_BuildToolsWrapper = 1
+    let g:BTW_BTW_in_use = 1
+    exe 'so '.s:sfile
+    unlet g:force_reload_BuildToolsWrapper
+    unlet g:BTW_BTW_in_use
+    return
+  elseif a:command =~ '\%(help\|?\)'
+    call s:Usage()
+    return
+  endif
+  call s:ReconstructToolsChain()
+endfunction
+
+" ##############################################################
+" Public functions          {{{2
+
+function! s:FindSubcommand(definition, subcommand)
+  for arg in a:definition.arguments
+    if arg.name == a:subcommand
+      return arg
+    endif
+  endfor
+  throw "NF"
+endfunction
+
+function! s:execute_function(definition, params)
+    if len(a:params) < 1
+      throw "(lh#command) Not enough arguments"
+    endif
+  let l:Fn = a:definition.action
+  echo "calling ".string(l:Fn)
+  echo "with ".string(a:params)
+  " call remove(a:params, 0)
+  call l:Fn(a:params)
+endfunction
+
+function! s:execute_sub_commands(definition, params)
+  try
+    if len(a:params) < 1
+      throw "(lh#command) Not enough arguments"
+    endif
+    let subcommand = s:FindSubcommand(a:definition, a:params[0])
+    call remove(a:params, 0)
+    call s:int_execute(subcommand, a:params)
+  catch /NF.*/
+    throw "(lh#command) Unexpected subcommand `".a:params[0]."'."
+  endtry
+endfunction
+
+function! s:int_execute(definition, params)
+  echo "params=".string(a:params)
+  call s:execute_{a:definition.arg_type}(a:definition, a:params)
+endfunction
+
+function! s:execute(definition, ...)
+  try
+    let params = copy(a:000)
+    call s:int_execute(a:definition, params)
+  catch /(lh#command).*/
+    echoerr v:exception . " in `".a:definition.name.' '.join(a:000, ' ')."'"
+  endtry
+endfunction
+
+function! lh#command#new(definition)
+  let cmd_name = a:definition.name
+  " Save the definition as an internal script variable
+  let id = s:SaveData(a:definition)
+  exe "command! -nargs=* ".cmd_name." :call s:execute(s:Data".id.", <f-args>)"
+endfunction
+
+" Functions }}}1
+"------------------------------------------------------------------------
+let &cpo=s:cpo_save
+"=============================================================================
+" vim600: set fdm=marker:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/lh-vim-lib/autoload/lh/common.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,93 @@
+"=============================================================================
+" $Id: common.vim 246 2010-09-19 22:40:58Z luc.hermitte $
+" File:		autoload/lh/common.vim                               {{{1
+" Author:	Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
+"		<URL:http://code.google.com/p/lh-vim/>
+" Version:	2.2.1
+" Created:	07th Oct 2006
+" Last Update:	$Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $ (08th Feb 2008)
+"------------------------------------------------------------------------
+" Description:	
+" 	Some common functions for:
+" 	- displaying error messages
+" 	- checking dependencies
+" 
+"------------------------------------------------------------------------
+" Installation:	
+" 	Drop it into {rtp}/autoload/lh/
+" 	Vim 7+ required.
+" History:	
+" 	v2.1.1
+" 		- New function: lh#common#echomsg_multilines()
+" 		- lh#common#warning_msg() supports multilines messages
+"
+" 	v2.0.0:
+" 		- Code moved from other plugins
+" }}}1
+"=============================================================================
+
+
+"=============================================================================
+let s:cpo_save=&cpo
+set cpo&vim
+"------------------------------------------------------------------------
+" Functions {{{1
+
+" Function: lh#common#echomsg_multilines {{{2
+function! lh#common#echomsg_multilines(text)
+  let lines = split(a:text, "[\n\r]")
+  for line in lines
+    echomsg line
+  endfor
+endfunction
+function! lh#common#echomsgMultilines(text)
+  return lh#common#echomsg_multilines(a:text)
+endfunction
+
+" Function: lh#common#error_msg {{{2
+function! lh#common#error_msg(text)
+  if has('gui_running')
+    call confirm(a:text, '&Ok', '1', 'Error')
+  else
+    " echohl ErrorMsg
+    echoerr a:text
+    " echohl None
+  endif
+endfunction 
+function! lh#common#ErrorMsg(text)
+  return lh#common#error_msg(a:text)
+endfunction
+
+" Function: lh#common#warning_msg {{{2
+function! lh#common#warning_msg(text)
+  echohl WarningMsg
+  " echomsg a:text
+  call lh#common#echomsg_multilines(a:text)
+  echohl None
+endfunction 
+function! lh#common#WarningMsg(text)
+  return lh#common#warning_msg(a:text)
+endfunction
+
+" Dependencies {{{2
+function! lh#common#check_deps(Symbol, File, path, plugin) " {{{3
+  if !exists(a:Symbol)
+    exe "runtime ".a:path.a:File
+    if !exists(a:Symbol)
+      call lh#common#error_msg( a:plugin.': Requires <'.a:File.'>')
+      return 0
+    endif
+  endif
+  return 1
+endfunction
+
+function! lh#common#CheckDeps(Symbol, File, path, plugin) " {{{3
+  echomsg "lh#common#CheckDeps() is deprecated, use lh#common#check_deps() instead."
+  return lh#common#check_deps(a:Symbol, a:File, a:path, a:plugin)
+endfunction
+
+" Functions }}}1
+"------------------------------------------------------------------------
+let &cpo=s:cpo_save
+"=============================================================================
+" vim600: set fdm=marker:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/lh-vim-lib/autoload/lh/encoding.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,49 @@
+"=============================================================================
+" $Id: encoding.vim 246 2010-09-19 22:40:58Z luc.hermitte $
+" File:		autoload/lh/encoding.vim                               {{{1
+" Author:	Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
+"		<URL:http://code.google.com/p/lh-vim/>
+" Version:	2.2.1
+" Created:	21st Feb 2008
+" Last Update:	$Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $
+"------------------------------------------------------------------------
+" Description:	
+" 	Defines functions that help managing various encodings
+" 
+"------------------------------------------------------------------------
+" Installation:	
+" 	Drop it into {rtp}/autoload/lh/
+" 	Vim 7+ required.
+" History:	
+" 	v2.0.7:
+" 	(*) lh#encoding#Iconv() copied from map-tools
+" TODO:		«missing features»
+" }}}1
+"=============================================================================
+
+let s:cpo_save=&cpo
+set cpo&vim
+"------------------------------------------------------------------------
+
+" Function: lh#encoding#iconv(expr, from, to)  " {{{3
+" Unlike |iconv()|, this wrapper returns {expr} when we know no convertion can
+" be acheived.
+function! lh#encoding#iconv(expr, from, to)
+  " call Dfunc("s:ICONV(".a:expr.','.a:from.','.a:to.')')
+  if has('multi_byte') && 
+	\ ( has('iconv') || has('iconv/dyn') ||
+	\ ((a:from=~'latin1\|utf-8') && (a:to=~'latin1\|utf-8')))
+    " call confirm('encoding: '.&enc."\nto:".a:to, "&Ok", 1)
+    " call Dret("s:ICONV convert=".iconv(a:expr, a:from, a:to))
+    return iconv(a:expr,a:from,a:to)
+  else
+    " Cannot convert
+    " call Dret("s:ICONV  no convert=".a:expr)
+    return a:expr
+  endif
+endfunction
+
+"------------------------------------------------------------------------
+let &cpo=s:cpo_save
+"=============================================================================
+" vim600: set fdm=marker:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/lh-vim-lib/autoload/lh/env.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,75 @@
+"=============================================================================
+" $Id: env.vim 244 2010-09-19 22:38:24Z luc.hermitte $
+" File:         autoload/lh/env.vim                               {{{1
+" Author:       Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
+"		<URL:http://code.google.com/p/lh-vim/>
+" Version:      2.2.1
+" Created:      19th Jul 2010
+" Last Update:  $Date: 2010-09-19 18:38:24 -0400 (Sun, 19 Sep 2010) $
+"------------------------------------------------------------------------
+" Description:
+"       Functions related to environment (variables)
+" 
+"------------------------------------------------------------------------
+" Installation:
+"       Drop this file into {rtp}/autoload/lh
+"       Requires Vim7+
+" History:      
+" 	v2.2.1 First Version
+" TODO:         «missing features»
+" }}}1
+"=============================================================================
+
+let s:cpo_save=&cpo
+set cpo&vim
+"------------------------------------------------------------------------
+" ## Misc Functions     {{{1
+" # Version {{{2
+let s:k_version = 221
+function! lh#env#version()
+  return s:k_version
+endfunction
+
+" # Debug   {{{2
+let s:verbose = 0
+function! lh#env#verbose(...)
+  if a:0 > 0 | let s:verbose = a:1 | endif
+  return s:verbose
+endfunction
+
+function! s:Verbose(expr)
+  if s:verbose
+    echomsg a:expr
+  endif
+endfunction
+
+function! lh#env#debug(expr)
+  return eval(a:expr)
+endfunction
+
+
+"------------------------------------------------------------------------
+" ## Exported functions {{{1
+function! lh#env#expand_all(string)
+  let res = ''
+  let tail = a:string
+  while !empty(tail)
+    let [ all, head, var, tail; dummy ] = matchlist(tail, '\(.\{-}\)\%(${\(.\{-}\)}\)\=\(.*\)')
+    if empty(var)
+      let res .= tail
+      break
+    else
+      let res .= head
+      let val = eval('$'.var)
+      let res .= val
+    endif
+  endwhile
+  return res
+endfunction
+"------------------------------------------------------------------------
+" ## Internal functions {{{1
+
+"------------------------------------------------------------------------
+let &cpo=s:cpo_save
+"=============================================================================
+" vim600: set fdm=marker:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/lh-vim-lib/autoload/lh/event.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,68 @@
+"=============================================================================
+" $Id: event.vim 246 2010-09-19 22:40:58Z luc.hermitte $
+" File:		autoload/lh/event.vim                               {{{1
+" Author:	Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
+"		<URL:http://code.google.com/p/lh-vim/>
+" Version:	2.2.1
+" Created:	15th Feb 2008
+" Last Update:	$Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $
+"------------------------------------------------------------------------
+" Description:	
+" 	Function to help manage vim |autocommand-events|
+" 
+"------------------------------------------------------------------------
+" Installation:
+" 	Drop it into {rtp}/autoload/lh/
+" 	Vim 7+ required.
+" History:
+" 	v2.0.6:
+" 		Creation
+" TODO:		
+" }}}1
+"=============================================================================
+
+let s:cpo_save=&cpo
+set cpo&vim
+
+"------------------------------------------------------------------------
+" ## Functions {{{1
+" # Debug {{{2
+function! lh#event#verbose(level)
+  let s:verbose = a:level
+endfunction
+
+function! s:Verbose(expr)
+  if exists('s:verbose') && s:verbose
+    echomsg a:expr
+  endif
+endfunction
+
+function! lh#event#debug(expr)
+  return eval(a:expr)
+endfunction
+
+"------------------------------------------------------------------------
+" # Event Registration {{{2
+function! s:RegisteredOnce(cmd, group)
+  " We can't delete the current augroup autocommand => increment a counter
+  if !exists('s:'.a:group) || s:{a:group} == 0 
+    let s:{a:group} = 1
+    exe a:cmd
+  endif
+endfunction
+
+function! lh#event#register_for_one_execution_at(event, cmd, group)
+  let group = a:group.'_once'
+  let s:{group} = 0
+  exe 'augroup '.group
+  au!
+  exe 'au '.a:event.' '.expand('%:p').' call s:RegisteredOnce('.string(a:cmd).','.string(group).')'
+  augroup END
+endfunction
+function! lh#event#RegisterForOneExecutionAt(event, cmd, group)
+  return lh#event#register_for_one_execution_at(a:event, a:cmd, a:group)
+endfunction
+"------------------------------------------------------------------------
+let &cpo=s:cpo_save
+"=============================================================================
+" vim600: set fdm=marker:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/lh-vim-lib/autoload/lh/function.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,214 @@
+"=============================================================================
+" $Id: function.vim 161 2010-05-07 01:04:44Z luc.hermitte $
+" File:		autoload/lh/function.vim                               {{{1
+" Author:	Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
+"		<URL:http://code.google.com/p/lh-vim/>
+" Version:	2.2.0
+" Created:	03rd Nov 2008
+" Last Update:	$Date: 2010-05-06 21:04:44 -0400 (Thu, 06 May 2010) $
+"------------------------------------------------------------------------
+" Description:	
+" 	Implements:
+" 	- lh#function#bind()
+" 	- lh#function#execute()
+" 	- lh#function#prepare()
+" 	- a binded function type
+" 
+"------------------------------------------------------------------------
+" Installation:	
+" 	Drop it into {rtp}/autoload/lh/
+" 	Vim 7+ required.
+" History:	
+" v2.2.0: first implementation
+" TODO:		«missing features»
+" }}}1
+"=============================================================================
+
+let s:cpo_save=&cpo
+set cpo&vim
+"------------------------------------------------------------------------
+
+" ## Functions {{{1
+" # Debug {{{2
+function! lh#function#verbose(level)
+  let s:verbose = a:level
+endfunction
+
+function! s:Verbose(expr)
+  if exists('s:verbose') && s:verbose
+    echomsg a:expr
+  endif
+endfunction
+
+function! lh#function#debug(expr)
+  return eval(a:expr)
+endfunction
+
+" # Function: s:Join(arguments...) {{{2
+function! s:Join(args)
+  let res = ''
+  if len(a:args) > 0
+    let res = string(a:args[0])
+    let i = 1
+    while i != len(a:args)
+      let res.=','.string(a:args[i])
+      let i += 1
+    endwhile
+  endif
+  return res
+endfunction
+
+" # Function: s:DoBindList(arguments...) {{{2
+function! s:DoBindList(formal, real)
+  let args = []
+  for arg in a:formal
+    if type(arg)==type('string') && arg =~ '^v:\d\+_$'
+      let new = a:real[matchstr(arg, 'v:\zs\d\+\ze_')-1]
+    elseif type(arg)==type('string')
+      let new = eval(s:DoBindEvaluatedString(arg, a:real))
+    else
+      let new = arg
+    endif
+    call add(args, new)
+    unlet new
+    unlet arg
+  endfor
+  return args
+endfunction
+
+" # Function: s:DoBindString(arguments...) {{{2
+function! s:DoBindString(expr, real)
+  let expr = substitute(a:expr, '\<v:\(\d\+\)_\>', a:real.'[\1-1]', 'g')
+  return expr
+endfunction
+
+function! s:ToString(expr)
+  return  type(a:expr) != type('')
+	\ ? string(a:expr)
+	\ : (a:expr)
+endfunction
+
+function! s:DoBindEvaluatedString(expr, real)
+  let expr = a:expr
+  let p = 0
+  while 1
+    let p = match(expr, '\<v:\d\+_\>', p)
+    if -1 == p | break | endif
+    let e = matchend(expr, '\<v:\d\+_\>', p)
+    let n = eval(expr[p+2 : e-2])
+    " let new = (type(a:real[n-1])==type('') && a:real[n-1]=~ '\<v:\d\+_\>')
+	  " \ ? a:real[n-1]
+	  " \ : string(a:real[n-1])
+    let new = s:ToString(a:real[n-1])
+    " let new = string(a:real[n-1]) " -> bind_counpound vars
+    let expr = ((p>0) ? (expr[0:p-1]) : '') . new . expr[e : -1]
+    " echo expr
+    let p += len(new)
+    " silent! unlet new
+  endwhile
+
+  return expr
+endfunction
+
+" # Function: s:Execute(arguments...) {{{2
+function! s:Execute(args) dict
+  if type(self.function) == type(function('exists'))
+    let args = s:DoBindList(self.args, a:args)
+    " echomsg '##'.string(self.function).'('.join(args, ',').')'
+    let res = eval(string(self.function).'('.s:Join(args).')')
+  elseif type(self.function) == type('string')
+    let expr = s:DoBindString(self.function, 'a:args')
+    let res = eval(expr)
+  elseif type(self.function) == type({})
+    return self.function.execute(a:args)
+  else
+    throw "lh#functor#execute: unpected function type: ".type(self.function)
+  endif
+  return res
+endfunction
+
+" # Function: lh#function#prepare(function, arguments_list) {{{2
+function! lh#function#prepare(Fn, arguments_list)
+  if     type(a:Fn) == type(function('exists'))
+    let expr = string(a:Fn).'('.s:Join(a:arguments_list).')'
+    return expr
+  elseif type(a:Fn) == type('string')
+    if a:Fn =~ '^[a-zA-Z0-9_#]\+$'
+      let expr = string(function(a:Fn)).'('.s:Join(a:arguments_list).')'
+      return expr
+    else
+      let expr = s:DoBindString(a:Fn, 'a:000')
+      return expr
+    endif
+  else
+    throw "lh#function#prepare(): {Fn} argument of type ".type(a:Fn). " is unsupported"
+  endif
+endfunction
+
+" # Function: lh#function#execute(function, arguments...) {{{2
+function! lh#function#execute(Fn, ...)
+  if type(a:Fn) == type({}) && has_key(a:Fn, 'execute')
+    return a:Fn.execute(a:000)
+  else
+    let expr = lh#function#prepare(a:Fn, a:000)
+    return eval(expr)
+  endif
+endfunction
+
+" # Function: lh#function#bind(function, arguments...) {{{2
+function! lh#function#bind(Fn, ...)
+  let args = copy(a:000)
+  if type(a:Fn) == type('string') && a:Fn =~ '^[a-zA-Z0-9_#]\+$'
+	\ && exists('*'.a:Fn)
+    let Fn = function(a:Fn)
+  elseif type(a:Fn) == type({})
+    " echo string(a:Fn).'('.string(a:000).')'
+    " Rebinding another binded function
+    " TASSERT has_key(a:Fn, 'function')
+    " TASSERT has_key(a:Fn, 'execute')
+    " TASSERT has_key(a:Fn, 'args')
+    let Fn = a:Fn.function
+    let N = len(a:Fn.args)
+    if N != 0 " args to rebind
+      let i = 0
+      let t_args = [] " necessary to avoid type changes
+      while i != N
+	silent! unlet arg
+	let arg = a:Fn.args[i]
+	if arg =~ 'v:\d\+_$'
+	  let arg2 = eval(s:DoBindString(arg, string(args)))
+	  " echo arg."-(".string(args).")->".string(arg2)
+	  unlet arg
+	  let arg = arg2
+	  unlet arg2
+	endif
+	call add(t_args, arg)
+	let i += 1
+      endwhile
+      unlet a:Fn.args
+      let a:Fn.args = t_args
+    else " expression to fix
+      " echo Fn
+      " echo s:DoBindString(Fn, string(args))
+      " echo eval(string(s:DoBindString(Fn, string(args))))
+      let Fn = (s:DoBindEvaluatedString(Fn, args))
+    endif
+    let args = a:Fn.args
+  else
+    let Fn = a:Fn
+  endif
+
+  let binded_fn = {
+	\ 'function': Fn,
+	\ 'args':     args,
+	\ 'execute':  function('s:Execute')
+	\}
+  return binded_fn
+endfunction
+
+" }}1
+"------------------------------------------------------------------------
+let &cpo=s:cpo_save
+"=============================================================================
+" vim600: set fdm=marker:
+" Vim: let g:UTfiles='tests/lh/function.vim'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/lh-vim-lib/autoload/lh/graph/tsort.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,177 @@
+"=============================================================================
+" $Id: tsort.vim 246 2010-09-19 22:40:58Z luc.hermitte $
+" File:		autoload/lh/tsort.vim                        {{{1
+" Author:	Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
+"		<URL:http://code.google.com/p/lh-vim/>
+" Version:	2.2.1
+" Created:	21st Apr 2008
+" Last Update:	$Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $
+"------------------------------------------------------------------------
+" Description:	Library functions for Topological Sort
+" 
+"------------------------------------------------------------------------
+" 	Drop the file into {rtp}/autoload/lh/graph
+" History:	«history»
+" TODO:		«missing features»
+" }}}1
+"=============================================================================
+
+let s:cpo_save=&cpo
+set cpo&vim
+
+"------------------------------------------------------------------------
+" ## Debug {{{1
+function! lh#graph#tsort#verbose(level)
+  let s:verbose = a:level
+endfunction
+
+function! s:Verbose(expr)
+  if exists('s:verbose') && s:verbose
+    echomsg a:expr
+  endif
+endfunction
+
+function! lh#graph#tsort#debug(expr)
+  return eval(a:expr)
+endfunction
+
+"------------------------------------------------------------------------
+"## Helper functions                         {{{1
+"# s:Successors_fully_defined(node)          {{{2
+function! s:Successors_fully_defined(node) dict
+  if has_key(self.table, a:node)
+    return self.table[a:node]
+  else
+    return []
+  endif
+endfunction
+
+"# s:Successors_lazy(node)                   {{{2
+function! s:Successors_lazy(node) dict
+  if !has_key(self.table, a:node)
+    let nodes = self.fetch(a:node)
+    let self.table[a:node] = nodes
+    " if len(nodes) > 0
+      " let self.nb += 1
+    " endif
+    return nodes
+  else
+    return self.table[a:node]
+  endif
+endfunction
+
+"# s:PrepareDAG(dag)                         {{{2
+function! s:PrepareDAG(dag)
+  if type(a:dag) == type(function('has_key'))
+    let dag = { 
+	  \ 'successors': function('s:Successors_lazy'),
+	  \ 'fetch'     : a:dag,
+	  \ 'table' 	: {}
+	  \}
+  else
+    let dag = { 
+	  \ 'successors': function('s:Successors_fully_defined'),
+	  \ 'table' 	: deepcopy(a:dag)
+	  \}
+  endif
+  return dag
+endfunction
+
+"## Depth-first search (recursive)           {{{1
+" Do not detect cyclic graphs
+
+"# lh#graph#tsort#depth(dag, start_nodes)    {{{2
+function! lh#graph#tsort#depth(dag, start_nodes)
+  let dag = s:PrepareDAG(a:dag)
+  let results = []
+  let visited_nodes = { 'Visited':function('s:Visited')}
+  call s:RecursiveDTSort(dag, a:start_nodes, results, visited_nodes)
+  call reverse(results)
+  return results
+endfunction
+
+"# The real, recursive, T-Sort               {{{2
+"see boost.graph for a non recursive implementation
+function! s:RecursiveDTSort(dag, start_nodes, results, visited_nodes)
+  for node in a:start_nodes
+    let visited = a:visited_nodes.Visited(node)
+    if     visited == 1 | continue " done
+    elseif visited == 2 | throw "Tsort: cyclic graph detected: ".node
+    endif
+    let a:visited_nodes[node] = 2 " visiting
+    let succs = a:dag.successors(node)
+    try
+      call s:RecursiveDTSort(a:dag, succs, a:results, a:visited_nodes)
+    catch /Tsort:/
+      throw v:exception.'>'.node
+    endtry
+    let a:visited_nodes[node] = 1 " visited
+    call add(a:results, node)
+  endfor
+endfunction
+
+function! s:Visited(node) dict 
+  return has_key(self, a:node) ? self[a:node] : 0
+endfunction
+
+"## Breadth-first search (non recursive)     {{{1
+"# lh#graph#tsort#breadth(dag, start_nodes)  {{{2
+" warning: This implementation does not work with lazy dag, but only with fully
+" defined ones
+function! lh#graph#tsort#breadth(dag, start_nodes)
+  let result = []
+  let dag = s:PrepareDAG(a:dag)
+  let queue = deepcopy(a:start_nodes)
+
+  while len(queue) > 0
+    let node = remove(queue, 0)
+    " echomsg "result <- ".node
+    call add(result, node)
+    let successors = dag.successors(node)
+    while len(successors) > 0
+      let m = s:RemoveEdgeFrom(dag, node)
+      " echomsg "graph loose ".node."->".m
+      if !s:HasIncomingEgde(dag, m)
+	" echomsg "queue <- ".m
+        call add(queue, m)
+      endif
+    endwhile
+  endwhile
+  if !s:Empty(dag)
+    throw "Tsort: cyclic graph detected: "
+  endif
+  return result
+endfunction
+
+function! s:HasIncomingEgde(dag, node)
+  for node in keys(a:dag.table)
+    if type(a:dag.table[node]) != type([])
+      continue
+    endif
+    if index(a:dag.table[node], a:node) != -1
+      return 1
+    endif
+  endfor
+  return 0
+endfunction
+function! s:RemoveEdgeFrom(dag, node)
+  let successors = a:dag.successors(a:node)
+  if len(successors) > 0
+    let successor = remove(successors, 0)
+    if len(successors) == 0
+      " echomsg "finished with ->".a:node
+      call remove(a:dag.table, a:node)
+    endif
+    return successor
+  endif
+  throw "No more edges from ".a:node
+endfunction
+function! s:Empty(dag)
+  " echomsg "len="len(a:dag.table)
+  return len(a:dag.table) == 0
+endfunction
+" }}}1
+"------------------------------------------------------------------------
+let &cpo=s:cpo_save
+"=============================================================================
+" vim600: set fdm=marker
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/lh-vim-lib/autoload/lh/list.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,338 @@
+"=============================================================================
+" $Id: list.vim 236 2010-06-01 00:43:34Z luc.hermitte $
+" File:         autoload/lh/list.vim                                      {{{1
+" Author:       Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
+"               <URL:http://code.google.com/p/lh-vim/>
+" Version:      2.2.1
+" Created:      17th Apr 2007
+" Last Update:  $Date: 2010-05-31 20:43:34 -0400 (Mon, 31 May 2010) $ (17th Apr 2007)
+"------------------------------------------------------------------------
+" Description:  
+"       Defines functions related to |Lists|
+" 
+"------------------------------------------------------------------------
+" Installation: 
+"       Drop it into {rtp}/autoload/lh/
+"       Vim 7+ required.
+" History:      
+"       v2.2.1:
+"       (*) use :unlet in :for loop to support heterogeneous lists
+"       (*) binary search algorithms (upper_bound, lower_bound, equal_range)
+"       v2.2.0:
+"       (*) new functions: lh#list#accumulate, lh#list#transform,
+"           lh#list#transform_if, lh#list#find_if, lh#list#copy_if,
+"           lh#list#subset, lh#list#intersect
+"       (*) the functions are compatible with lh#function functors
+"       v2.1.1: 
+"       (*) unique_sort
+"       v2.0.7:
+"       (*) Bug fix: lh#list#Match()
+"       v2.0.6:
+"       (*) lh#list#Find_if() supports search predicate, and start index
+"       (*) lh#list#Match() supports start index
+"       v2.0.0:
+" TODO:         «missing features»
+" }}}1
+"=============================================================================
+
+
+"=============================================================================
+let s:cpo_save=&cpo
+set cpo&vim
+
+"------------------------------------------------------------------------
+" ## Functions {{{1
+" # Debug {{{2
+function! lh#list#verbose(level)
+  let s:verbose = a:level
+endfunction
+
+function! s:Verbose(expr)
+  if exists('s:verbose') && s:verbose
+    echomsg a:expr
+  endif
+endfunction
+
+function! lh#list#debug(expr)
+  return eval(a:expr)
+endfunction
+
+"------------------------------------------------------------------------
+" # Public {{{2
+" Function: lh#list#Transform(input, output, action) {{{3
+" deprecated version
+function! lh#list#Transform(input, output, action)
+  let new = map(copy(a:input), a:action)
+  let res = extend(a:output,new)
+  return res
+
+  for element in a:input
+    let action = substitute(a:action, 'v:val','element', 'g')
+    let res = eval(action)
+    call add(a:output, res)
+    unlet element " for heterogeneous lists
+  endfor
+  return a:output
+endfunction
+
+function! lh#list#transform(input, output, action)
+  for element in a:input
+    let res = lh#function#execute(a:action, element)
+    call add(a:output, res)
+    unlet element " for heterogeneous lists
+  endfor
+  return a:output
+endfunction
+
+function! lh#list#transform_if(input, output, action, predicate)
+  for element in a:input
+    if lh#function#execute(a:predicate, element)
+      let res = lh#function#execute(a:action, element)
+      call add(a:output, res)
+    endif
+    unlet element " for heterogeneous lists
+  endfor
+  return a:output
+endfunction
+
+function! lh#list#copy_if(input, output, predicate)
+  for element in a:input
+    if lh#function#execute(a:predicate, element)
+      call add(a:output, element)
+    endif
+    unlet element " for heterogeneous lists
+  endfor
+  return a:output
+endfunction
+
+function! lh#list#accumulate(input, transformation, accumulator)
+  let transformed = lh#list#transform(a:input, [], a:transformation)
+  let res = lh#function#execute(a:accumulator, transformed)
+  return res
+endfunction
+
+" Function: lh#list#match(list, to_be_matched [, idx]) {{{3
+function! lh#list#match(list, to_be_matched, ...)
+  let idx = (a:0>0) ? a:1 : 0
+  while idx < len(a:list)
+    if match(a:list[idx], a:to_be_matched) != -1
+      return idx
+    endif
+    let idx += 1
+  endwhile
+  return -1
+endfunction
+function! lh#list#Match(list, to_be_matched, ...)
+  let idx = (a:0>0) ? a:1 : 0
+  return lh#list#match(a:list, a:to_be_matched, idx)
+endfunction
+
+" Function: lh#list#Find_if(list, predicate [, predicate-arguments] [, start-pos]) {{{3
+function! lh#list#Find_if(list, predicate, ...)
+  " Parameters
+  let idx = 0
+  let args = []
+  if a:0 == 2
+    let idx = a:2
+    let args = a:1
+  elseif a:0 == 1
+    if type(a:1) == type([])
+      let args = a:1
+    elseif type(a:1) == type(42)
+      let idx = a:1
+    else
+      throw "lh#list#Find_if: unexpected argument type"
+    endif
+  elseif a:0 != 0
+      throw "lh#list#Find_if: unexpected number of arguments: lh#list#Find_if(list, predicate [, predicate-arguments] [, start-pos])"
+  endif
+
+  " The search loop
+  while idx != len(a:list)
+    let predicate = substitute(a:predicate, 'v:val', 'a:list['.idx.']', 'g')
+    let predicate = substitute(predicate, 'v:\(\d\+\)_', 'args[\1-1]', 'g')
+    let res = eval(predicate)
+    if res | return idx | endif
+    let idx += 1
+  endwhile
+  return -1
+endfunction
+
+" Function: lh#list#find_if(list, predicate [, predicate-arguments] [, start-pos]) {{{3
+function! lh#list#find_if(list, predicate, ...)
+  " Parameters
+  let idx = 0
+  let args = []
+  if a:0 == 1
+    let idx = a:1
+  elseif a:0 != 0
+      throw "lh#list#find_if: unexpected number of arguments: lh#list#find_if(list, predicate [, start-pos])"
+  endif
+
+  " The search loop
+  while idx != len(a:list)
+    " let predicate = substitute(a:predicate, 'v:val', 'a:list['.idx.']', 'g')
+    let res = lh#function#execute(a:predicate, a:list[idx])
+    if res | return idx | endif
+    let idx += 1
+  endwhile
+  return -1
+endfunction
+
+" Function: lh#list#lower_bound(sorted_list, value  [, first[, last]]) {{{3
+function! lh#list#lower_bound(list, val, ...)
+  let first = 0
+  let last = len(a:list)
+  if a:0 >= 1     | let first = a:1
+  elseif a:0 >= 2 | let last = a:2
+  elseif a:0 > 2
+      throw "lh#list#equal_range: unexpected number of arguments: lh#list#equal_range(sorted_list, value  [, first[, last]])"
+  endif
+
+  let len = last - first
+
+  while len > 0
+    let half = len / 2
+    let middle = first + half
+    if a:list[middle] < a:val
+      let first = middle + 1
+      let len -= half + 1
+    else
+      let len = half
+    endif
+  endwhile
+  return first
+endfunction
+
+" Function: lh#list#upper_bound(sorted_list, value  [, first[, last]]) {{{3
+function! lh#list#upper_bound(list, val, ...)
+  let first = 0
+  let last = len(a:list)
+  if a:0 >= 1     | let first = a:1
+  elseif a:0 >= 2 | let last = a:2
+  elseif a:0 > 2
+      throw "lh#list#equal_range: unexpected number of arguments: lh#list#equal_range(sorted_list, value  [, first[, last]])"
+  endif
+
+  let len = last - first
+
+  while len > 0
+    let half = len / 2
+    let middle = first + half
+    if a:val < a:list[middle]
+      let len = half
+    else
+      let first = middle + 1
+      let len -= half + 1
+    endif
+  endwhile
+  return first
+endfunction
+
+" Function: lh#list#equal_range(sorted_list, value  [, first[, last]]) {{{3
+" @return [f, l], where
+"   f : First position where {value} could be inserted
+"   l : Last position where {value} could be inserted
+function! lh#list#equal_range(list, val, ...)
+  let first = 0
+  let last = len(a:list)
+
+  " Parameters
+  if a:0 >= 1     | let first = a:1
+  elseif a:0 >= 2 | let last  = a:2
+  elseif a:0 > 2
+      throw "lh#list#equal_range: unexpected number of arguments: lh#list#equal_range(sorted_list, value  [, first[, last]])"
+  endif
+
+  " The search loop ( == STLPort's equal_range)
+
+  let len = last - first
+  while len > 0
+    let half = len / 2
+    let middle = first + half
+    if a:list[middle] < a:val
+      let first = middle + 1
+      let len -= half + 1
+    elseif a:val < a:list[middle]
+      let len = half
+    else
+      let left = lh#list#lower_bound(a:list, a:val, first, middle)
+      let right = lh#list#upper_bound(a:list, a:val, middle+1, first+len)
+      return [left, right]
+    endif
+
+    " let predicate = substitute(a:predicate, 'v:val', 'a:list['.idx.']', 'g')
+    " let res = lh#function#execute(a:predicate, a:list[idx])
+  endwhile
+  return [first, first]
+endfunction
+
+" Function: lh#list#unique_sort(list [, func]) {{{3
+" See also http://vim.wikia.com/wiki/Unique_sorting
+"
+" Works like sort(), optionally taking in a comparator (just like the
+" original), except that duplicate entries will be removed.
+" todo: support another argument that act as an equality predicate
+function! lh#list#unique_sort(list, ...)
+  let dictionary = {}
+  for i in a:list
+    let dictionary[string(i)] = i
+  endfor
+  let result = []
+  " echo join(values(dictionary),"\n")
+  if ( exists( 'a:1' ) )
+    let result = sort( values( dictionary ), a:1 )
+  else
+    let result = sort( values( dictionary ) )
+  endif
+  return result
+endfunction
+
+function! lh#list#unique_sort2(list, ...)
+  let list = copy(a:list)
+  if ( exists( 'a:1' ) )
+    call sort(list, a:1 )
+  else
+    call sort(list)
+  endif
+  if len(list) <= 1 | return list | endif
+  let result = [ list[0] ]
+  let last = list[0]
+  let i = 1
+  while i < len(list)
+    if last != list[i]
+      let last = list[i]
+      call add(result, last)
+    endif
+    let i += 1
+  endwhile
+  return result
+endfunction
+
+" Function: lh#list#subset(list, indices) {{{3
+function! lh#list#subset(list, indices)
+  let result=[]
+  for e in a:indices
+    call add(result, a:list[e])
+  endfor
+  return result
+endfunction
+
+" Function: lh#list#intersect(list1, list2) {{{3
+function! lh#list#intersect(list1, list2)
+  let result = copy(a:list1)
+  call filter(result, 'index(a:list2, v:val) >= 0')
+  return result
+
+  for e in a:list1
+    if index(a:list2, e) > 0
+      call result(result, e)
+    endif
+  endfor
+endfunction
+
+" Functions }}}1
+"------------------------------------------------------------------------
+let &cpo=s:cpo_save
+"=============================================================================
+" vim600: set fdm=marker:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/lh-vim-lib/autoload/lh/menu.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,384 @@
+"=============================================================================
+" $Id: menu.vim 246 2010-09-19 22:40:58Z luc.hermitte $
+" File:		autoload/lh/menu.vim                               {{{1
+" Author:	Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
+"		<URL:http://code.google.com/p/lh-vim/>
+" Version:	2.2.1
+" Created:	13th Oct 2006
+" Last Update:	$Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $ (28th Aug 2007)
+"------------------------------------------------------------------------
+" Description:	
+" 	Defines the global function lh#menu#def_menu
+" 	Aimed at (ft)plugin writers.
+" 
+"------------------------------------------------------------------------
+" Installation:	
+" 	Drop this file into {rtp}/autoload/lh/
+" 	Requires Vim 7+
+" History:	
+" 	v2.0.0:	Moving to vim7
+" 	v2.0.1:	:ToggleXxx echoes the new value
+" 	v2.2.0: Support environment variables
+" 	        Only one :Toggle command is defined.
+" TODO:		
+" 	Should the argument to :Toggle be simplified to use the variable
+" 	name instead ?
+" }}}1
+"=============================================================================
+
+
+"=============================================================================
+let s:cpo_save=&cpo
+set cpo&vim
+"------------------------------------------------------------------------
+" ## Internal Variables {{{1
+let s:k_Toggle_cmd = 'Toggle'
+if !exists('s:toggle_commands')
+  let s:toggle_commands = {}
+endif
+
+"------------------------------------------------------------------------
+" ## Functions {{{1
+" # Debug {{{2
+function! lh#menu#verbose(level)
+  let s:verbose = a:level
+endfunction
+
+function! s:Verbose(expr)
+  if exists('s:verbose') && s:verbose
+    echomsg a:expr
+  endif
+endfunction
+
+function! lh#menu#debug(expr)
+  return eval(a:expr)
+endfunction
+
+"------------------------------------------------------------------------
+" # Common stuff       {{{2
+" Function: lh#menu#text({text})                             {{{3
+" @return a text to be used in menus where "\" and spaces have been escaped.
+function! lh#menu#text(text)
+  return escape(a:text, '\ ')
+endfunction
+
+" # Toggling menu item {{{2
+" Function: s:Fetch({Data},{key})                          {{{3
+" @param[in] Data Menu-item definition
+" @param[in] key  Table table from which the result will be fetched
+" @return the current value, or text, whose index is Data.idx_crt_value.
+function! s:Fetch(Data, key)
+  let len = len(a:Data[a:key])
+  if a:Data.idx_crt_value >= len | let a:Data.idx_crt_value = 0 | endif
+  let value = a:Data[a:key][a:Data.idx_crt_value]
+  return value
+endfunction
+
+" Function: s:Search({Data},{value})                       {{{3
+" Searches for the index of {value} in {Data.values} list. Return 0 if not
+" found.
+function! s:Search(Data, value)
+  let idx = 0
+  while idx != len(a:Data.values)
+    if a:value == a:Data.values[idx]
+      " echo a:Data.variable . "[".idx."] == " . a:value
+      return idx
+    endif
+    let idx = idx + 1
+  endwhile
+  " echo a:Data.variable . "[".-1."] == " . a:value
+  return 0 " default is first element
+endfunction
+
+" Function: s:Set({Data})                                  {{{3
+" @param[in,out] Data Menu item definition
+"
+" Sets the global variable associated to the menu item according to the item's
+" current value.
+function! s:Set(Data)
+  let value = a:Data.values[a:Data.idx_crt_value]
+  let variable = a:Data.variable
+  if variable[0] == '$' " environment variabmes
+    exe "let ".variable." = ".string(value)
+  else
+    let g:{variable} = value
+  endif
+  if has_key(a:Data, "actions")
+    let l:Action = a:Data.actions[a:Data.idx_crt_value]
+    if type(l:Action) == type(function('tr'))
+      call l:Action()
+    else
+      exe l:Action
+    endif
+  endif
+  return value
+endfunction
+
+" Function: s:MenuKey({Data})                              {{{3
+" @return the table name from which the current value name (to dsplay in the
+" menu) must be fetched. 
+" Priority is given to the optional "texts" table over the madatory "values" table.
+function! s:MenuKey(Data)
+  if has_key(a:Data, "texts")
+    let menu_id = "texts"
+  else
+    let menu_id = "values"
+  endif
+  return menu_id
+endfunction
+
+" Function: s:NextValue({Data})                            {{{3
+" Change the value of the variable to the next in the list of value.
+" The menu, and the variable are updated in consequence.
+function! s:NextValue(Data)
+  " Where the texts for values must be fetched
+  let labels_key = s:MenuKey(a:Data)
+  " Fetch the old current value 
+  let old = s:Fetch(a:Data, labels_key)
+
+  " Remove the entry from the menu
+  call s:ClearMenu(a:Data.menu, old)
+
+  " Cycle/increment the current value
+  let a:Data.idx_crt_value += 1
+  " Fetch it
+  let new = s:Fetch(a:Data,labels_key)
+  " Add the updated entry in the menu
+  call s:UpdateMenu(a:Data.menu, new, a:Data.command)
+  " Update the binded global variable
+  let value = s:Set(a:Data)
+  echo a:Data.variable.'='.value
+endfunction
+
+" Function: s:ClearMenu({Menu}, {text})                    {{{3
+" Removes a menu item
+"
+" @param[in] Menu.priority Priority of the new menu-item
+" @param[in] Menu.name     Name of the new menu-item
+" @param[in] text          Text of the previous value of the variable binded
+function! s:ClearMenu(Menu, text)
+  if has('gui_running')
+    let name = substitute(a:Menu.name, '&', '', 'g')
+    let cmd = 'unmenu '.lh#menu#text(name.'<tab>('.a:text.')')
+    silent! exe cmd
+  endif
+endfunction
+
+" Function: s:UpdateMenu({Menu}, {text}, {command})        {{{3
+" Adds a new menu item, with the text associated to the current value in
+" braces.
+"
+" @param[in] Menu.priority Priority of the new menu-item
+" @param[in] Menu.name     Name of the new menu-item
+" @param[in] text          Text of the current value of the variable binded to
+"                          the menu-item
+" @param[in] command       Toggle command to execute when the menu-item is selected
+function! s:UpdateMenu(Menu, text, command)
+  if has('gui_running')
+    let cmd = 'nnoremenu <silent> '.a:Menu.priority.' '.
+	  \ lh#menu#text(a:Menu.name.'<tab>('.a:text.')').
+	  \ ' :silent '.s:k_Toggle_cmd.' '.a:command."\<cr>"
+    silent! exe cmd
+  endif
+endfunction
+
+" Function: s:SaveData({Data})                             {{{3
+" @param Data Menu-item definition
+" Saves {Data} as s:Data{s:data_id++}. The definition will be used by
+" automatically generated commands.
+" @return s:data_id
+let s:data_id = 0
+function! s:SaveData(Data)
+  let s:Data{s:data_id} = a:Data
+  let id = s:data_id
+  let s:data_id += 1
+  return id
+endfunction
+
+" Function: lh#menu#def_toggle_item({Data})                  {{{3
+" @param Data.idx_crt_value
+" @param Data.definitions == [ {value:, menutext: } ]
+" @param Data.menu        == { name:, position: }
+"
+" Sets a toggle-able menu-item defined by {Data}.
+"
+function! lh#menu#def_toggle_item(Data)
+  " Save the menu data as an internal script variable
+  let id = s:SaveData(a:Data)
+
+  " If the index of the current value hasn't been set, fetch it from the
+  " associated variable
+  if !has_key(a:Data, "idx_crt_value")
+    " Fetch the value of the associated variable
+    let value = lh#option#get(a:Data.variable, 0, 'g')
+    " echo a:Data.variable . " <- " . value
+    " Update the index of the current value
+    let a:Data.idx_crt_value  = s:Search(a:Data, value)
+  endif
+
+  " Name of the auto-matically generated toggle command
+  let cmdName = substitute(a:Data.menu.name, '[^a-zA-Z_]', '', 'g')
+  " Lazy definition of the command
+  if 2 != exists(':'.s:k_Toggle_cmd) 
+    exe 'command! -nargs=1 -complete=custom,lh#menu#_toggle_complete '
+	  \ . s:k_Toggle_cmd . ' :call s:Toggle(<f-args>)'
+  endif
+  " silent exe 'command! -nargs=0 '.cmdName.' :call s:NextValue(s:Data'.id.')'
+  let s:toggle_commands[cmdName] = eval('s:Data'.id)
+  let a:Data["command"] = cmdName
+
+  " Add the menu entry according to the current value
+  call s:UpdateMenu(a:Data.menu, s:Fetch(a:Data, s:MenuKey(a:Data)), cmdName)
+  " Update the associated global variable
+  call s:Set(a:Data)
+endfunction
+
+
+"------------------------------------------------------------------------
+function! s:Toggle(cmdName)
+  if !has_key(s:toggle_commands, a:cmdName)
+    throw "toggle-menu: unknown toggable variable ".a:cmdName
+  endif
+  let data = s:toggle_commands[a:cmdName]
+  call s:NextValue(data)
+endfunction
+
+function! lh#menu#_toggle_complete(ArgLead, CmdLine, CursorPos)
+  return join(keys(s:toggle_commands),"\n")
+endfunction
+
+"------------------------------------------------------------------------
+" # IVN Menus          {{{2
+" Function: s:CTRL_O({cmd})                                {{{3
+" Build the command (sequence of ':ex commands') to be executed from
+" INSERT-mode.
+function! s:CTRL_O(cmd)
+  return substitute(a:cmd, '\(^\|<CR>\):', '\1\<C-O>:', 'g')
+endfunction
+
+" Function: lh#menu#is_in_visual_mode()                    {{{3
+function! lh#menu#is_in_visual_mode()
+  return exists('s:is_in_visual_mode') && s:is_in_visual_mode
+endfunction
+
+" Function: lh#menu#_CMD_and_clear_v({cmd})                 {{{3
+" Internal function that executes the command and then clears the @v buffer
+" todo: save and restore @v, 
+function! lh#menu#_CMD_and_clear_v(cmd)
+  try 
+    let s:is_in_visual_mode = 1
+    exe a:cmd
+  finally
+    let @v=''
+    silent! unlet s:is_in_visual_mode
+  endtry
+endfunction
+
+" Function: s:Build_CMD({prefix},{cmd})                    {{{3
+" build the exact command to execute regarding the mode it is dedicated
+function! s:Build_CMD(prefix, cmd)
+  if a:cmd[0] != ':' | return ' ' . a:cmd
+  endif
+  if     a:prefix[0] == "i"  | return ' ' . <SID>CTRL_O(a:cmd)
+  elseif a:prefix[0] == "n"  | return ' ' . a:cmd
+  elseif a:prefix[0] == "v" 
+    if match(a:cmd, ":VCall") == 0
+      return substitute(a:cmd, ':VCall', ' :call', ''). "\<cr>gV"
+      " gV exit select-mode if we where in it!
+    else
+      return
+	    \ " \"vy\<C-C>:call lh#menu#_CMD_and_clear_v('" . 
+	    \ substitute(a:cmd, "<CR>$", '', '') ."')\<cr>"
+    endif
+  elseif a:prefix[0] == "c"  | return " \<C-C>" . a:cmd
+  else                       | return ' ' . a:cmd
+  endif
+endfunction
+
+" Function: lh#menu#map_all({map_type}, [{map args}...)   {{{3
+" map the command to all the modes required
+function! lh#menu#map_all(map_type,...)
+  let nore   = (match(a:map_type, '[aincv]*noremap') != -1) ? "nore" : ""
+  let prefix = matchstr(substitute(a:map_type, nore, '', ''), '[aincv]*')
+  if a:1 == "<buffer>" | let i = 3 | let binding = a:1 . ' ' . a:2
+  else                 | let i = 2 | let binding = a:1
+  endif
+  let binding = '<silent> ' . binding
+  let cmd = a:{i}
+  let i +=  1
+  while i <= a:0
+    let cmd .=  ' ' . a:{i}
+    let i +=  1
+  endwhile
+  let build_cmd = nore . 'map ' . binding
+  while strlen(prefix)
+    if prefix[0] == "a" | let prefix = "incv"
+    else
+      execute prefix[0] . build_cmd . <SID>Build_CMD(prefix[0],cmd)
+      let prefix = strpart(prefix, 1)
+    endif
+  endwhile
+endfunction
+
+" Function: lh#menu#make({prefix},{code},{text},{binding},...) {{{3
+" Build the menu and map its associated binding to all the modes required
+function! lh#menu#make(prefix, code, text, binding, ...)
+  let nore   = (match(a:prefix, '[aincv]*nore') != -1) ? "nore" : ""
+  let prefix = matchstr(substitute(a:prefix, nore, '', ''), '[aincv]*')
+  let b = (a:1 == "<buffer>") ? 1 : 0
+  let i = b + 1 
+  let cmd = a:{i}
+  let i += 1
+  while i <= a:0
+    let cmd .=  ' ' . a:{i}
+    let i += 1
+  endwhile
+  let build_cmd = nore . "menu <silent> " . a:code . ' ' . lh#menu#text(a:text) 
+  if strlen(a:binding) != 0
+    let build_cmd .=  '<tab>' . 
+	  \ substitute(lh#menu#text(a:binding), '&', '\0\0', 'g')
+    if b != 0
+      call lh#menu#map_all(prefix.nore."map", ' <buffer> '.a:binding, cmd)
+    else
+      call lh#menu#map_all(prefix.nore."map", a:binding, cmd)
+    endif
+  endif
+  if has("gui_running")
+    while strlen(prefix)
+      execute <SID>BMenu(b).prefix[0].build_cmd.<SID>Build_CMD(prefix[0],cmd)
+      let prefix = strpart(prefix, 1)
+    endwhile
+  endif
+endfunction
+
+" Function: s:BMenu({b})                                   {{{3
+" If <buffermenu.vim> is installed and the menu should be local, then the
+" apropriate string is returned.
+function! s:BMenu(b)
+  let res = (a:b && exists(':Bmenu') 
+	\     && (1 == lh#option#get("want_buffermenu_or_global_disable", 1, "bg"))
+	\) ? 'B' : ''
+  " call confirm("BMenu(".a:b.")=".res, '&Ok', 1)
+  return res
+endfunction
+
+" Function: lh#menu#IVN_make(...)                          {{{3
+function! lh#menu#IVN_make(code, text, binding, i_cmd, v_cmd, n_cmd, ...)
+  " nore options
+  let nore_i = (a:0 > 0) ? ((a:1 != 0) ? 'nore' : '') : ''
+  let nore_v = (a:0 > 1) ? ((a:2 != 0) ? 'nore' : '') : ''
+  let nore_n = (a:0 > 2) ? ((a:3 != 0) ? 'nore' : '') : ''
+  " 
+  call lh#menu#make('i'.nore_i,a:code,a:text, a:binding, '<buffer>', a:i_cmd)
+  call lh#menu#make('v'.nore_v,a:code,a:text, a:binding, '<buffer>', a:v_cmd)
+  if strlen(a:n_cmd) != 0
+    call lh#menu#make('n'.nore_n,a:code,a:text, a:binding, '<buffer>', a:n_cmd)
+  endif
+endfunction
+
+"
+" Functions }}}1
+"------------------------------------------------------------------------
+let &cpo=s:cpo_save
+"=============================================================================
+" vim600: set fdm=marker:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/lh-vim-lib/autoload/lh/option.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,107 @@
+"=============================================================================
+" $Id: option.vim 246 2010-09-19 22:40:58Z luc.hermitte $
+" File:		autoload/lh/option.vim                                    {{{1
+" Author:	Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
+"		<URL:http://code.google.com/p/lh-vim/>
+" Version:	2.2.1
+" Created:	24th Jul 2004
+" Last Update:	$Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $ (07th Oct 2006)
+"------------------------------------------------------------------------
+" Description:
+" 	Defines the global function lh#option#get().
+"       Aimed at (ft)plugin writers.
+" 
+"------------------------------------------------------------------------
+" Installation:
+" 	Drop this file into {rtp}/autoload/lh/
+" 	Requires Vim 7+
+" History:	
+" 	v2.0.5
+" 	(*) lh#option#get_non_empty() manages Lists and Dictionaries
+" 	(*) lh#option#get() doesn't test emptyness anymore
+" 	v2.0.0
+" 		Code moved from {rtp}/macros/ 
+" }}}1
+"=============================================================================
+
+
+"=============================================================================
+let s:cpo_save=&cpo
+set cpo&vim
+
+"------------------------------------------------------------------------
+" ## Functions {{{1
+" # Debug {{{2
+function! lh#option#verbose(level)
+  let s:verbose = a:level
+endfunction
+
+function! s:Verbose(expr)
+  if exists('s:verbose') && s:verbose
+    echomsg a:expr
+  endif
+endfunction
+
+function! lh#option#debug(expr)
+  return eval(a:expr)
+endfunction
+
+" # Public {{{2
+" Function: lh#option#get(name, default [, scope])            {{{3
+" @return b:{name} if it exists, or g:{name} if it exists, or {default}
+" otherwise
+" The order of the variables checked can be specified through the optional
+" argument {scope}
+function! lh#option#get(name,default,...)
+  let scope = (a:0 == 1) ? a:1 : 'bg'
+  let name = a:name
+  let i = 0
+  while i != strlen(scope)
+    if exists(scope[i].':'.name)
+      " \ && (0 != strlen({scope[i]}:{name}))
+      return {scope[i]}:{name}
+    endif
+    let i += 1
+  endwhile 
+  return a:default
+endfunction
+function! lh#option#Get(name,default,...)
+  let scope = (a:0 == 1) ? a:1 : 'bg'
+  return lh#option#get(a:name, a:default, scope)
+endfunction
+
+function! s:IsEmpty(variable)
+  if     type(a:variable) == type('string') | return 0 == strlen(a:variable)
+  elseif type(a:variable) == type(42)       | return 0 == a:variable
+  elseif type(a:variable) == type([])       | return 0 == len(a:variable)
+  elseif type(a:variable) == type({})       | return 0 == len(a:variable)
+  else                                      | return false
+  endif
+endfunction
+
+" Function: lh#option#get_non_empty(name, default [, scope])            {{{3
+" @return of b:{name}, g:{name}, or {default} the first which exists and is not empty 
+" The order of the variables checked can be specified through the optional
+" argument {scope}
+function! lh#option#get_non_empty(name,default,...)
+  let scope = (a:0 == 1) ? a:1 : 'bg'
+  let name = a:name
+  let i = 0
+  while i != strlen(scope)
+    if exists(scope[i].':'.name) && !s:IsEmpty({scope[i]}:{name})
+      return {scope[i]}:{name}
+    endif
+    let i += 1
+  endwhile 
+  return a:default
+endfunction
+function! lh#option#GetNonEmpty(name,default,...)
+  let scope = (a:0 == 1) ? a:1 : 'bg'
+  return lh#option#get_non_empty(a:name, a:default, scope)
+endfunction
+
+" Functions }}}1
+"------------------------------------------------------------------------
+let &cpo=s:cpo_save
+"=============================================================================
+" vim600: set fdm=marker:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/lh-vim-lib/autoload/lh/path.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,308 @@
+"=============================================================================
+" $Id: path.vim 237 2010-06-01 00:44:35Z luc.hermitte $
+" File:		autoload/lh/path.vim                               {{{1
+" Author:	Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
+"		<URL:http://code.google.com/p/lh-vim/>
+" Version:	2.2.1
+" Created:	23rd Jan 2007
+" Last Update:	11th Feb 2008
+"------------------------------------------------------------------------
+" Description:	
+"       Functions related to the handling of pathnames
+" 
+"------------------------------------------------------------------------
+" Installation:	
+" 	Drop this file into {rtp}/autoload/lh
+" 	Requires Vim7+
+" History:	
+"	v 1.0.0 First Version
+" 	(*) Functions moved from searchInRuntimeTime  
+" 	v 2.0.1
+" 	(*) lh#path#Simplify() becomes like |simplify()| except for trailing
+" 	v 2.0.2
+" 	(*) lh#path#SelectOne() 
+" 	(*) lh#path#ToRelative() 
+" 	v 2.0.3
+" 	(*) lh#path#GlobAsList() 
+" 	v 2.0.4
+" 	(*) lh#path#StripStart()
+" 	v 2.0.5
+" 	(*) lh#path#StripStart() interprets '.' as getcwd()
+" 	v 2.2.0
+" 	(*) new functions: lh#path#common(), lh#path#to_dirname(),
+" 	    lh#path#depth(), lh#path#relative_to(), lh#path#to_regex(),
+" 	    lh#path#find()
+" 	(*) lh#path#simplify() fixed
+" 	(*) lh#path#to_relative() use simplify()
+" TODO:
+"       (*) Decide what #depth('../../bar') shall return
+"       (*) Fix #simplify('../../bar')
+" }}}1
+"=============================================================================
+
+
+"=============================================================================
+" Avoid global reinclusion {{{1
+let s:cpo_save=&cpo
+set cpo&vim
+
+"=============================================================================
+" ## Functions {{{1
+" # Debug {{{2
+let s:verbose = 0
+function! lh#path#verbose(...)
+  if a:0 > 0 | let s:verbose = a:1 | endif
+  return s:verbose
+endfunction
+
+function! s:Verbose(expr)
+  if s:verbose
+    echomsg a:expr
+  endif
+endfunction
+
+function! lh#path#debug(expr)
+  return eval(a:expr)
+endfunction
+
+"=============================================================================
+" # Public {{{2
+" Function: lh#path#simplify({pathname}) {{{3
+" Like |simplify()|, but also strip the leading './'
+" It seems unable to simplify '..\' when compiled without +shellslash
+function! lh#path#simplify(pathname)
+  let pathname = simplify(a:pathname)
+  let pathname = substitute(pathname, '^\%(\.[/\\]\)\+', '', '')
+  let pathname = substitute(pathname, '\([/\\]\)\%(\.[/\\]\)\+', '\1', 'g')
+  let pwd = getcwd().'/'
+  let pathname = substitute(pathname, '^'.lh#path#to_regex(pwd), '', 'g')
+  return pathname
+endfunction
+function! lh#path#Simplify(pathname)
+  return lh#path#simplify(a:pathname)
+endfunction
+
+" Function: lh#path#common({pathnames}) {{{3
+" Find the common leading path between all pathnames
+function! lh#path#common(pathnames)
+  " assert(len(pathnames)) > 1
+  let common = a:pathnames[0]
+  let i = 1
+  while i < len(a:pathnames)
+    let fcrt = a:pathnames[i]
+    " pathnames should not contain @
+    let common = matchstr(common.'@@'.fcrt, '^\zs\(.*[/\\]\)\ze.\{-}@@\1.*$')
+    if strlen(common) == 0
+      " No need to further checks
+      break
+    endif
+    let i += 1
+  endwhile
+  return common
+endfunction
+
+" Function: lh#path#strip_common({pathnames}) {{{3
+" Find the common leading path between all pathnames, and strip it
+function! lh#path#strip_common(pathnames)
+  " assert(len(pathnames)) > 1
+  let common = lh#path#common(a:pathnames)
+  let l = strlen(common)
+  if l == 0
+    return a:pathnames
+  else
+  let pathnames = a:pathnames
+  call map(pathnames, 'strpart(v:val, '.l.')' )
+  return pathnames
+  endif
+endfunction
+function! lh#path#StripCommon(pathnames)
+  return lh#path#strip_common(a:pathnames)
+endfunction
+
+" Function: lh#path#is_absolute_path({path}) {{{3
+function! lh#path#is_absolute_path(path)
+  return a:path =~ '^/'
+	\ . '\|^[a-zA-Z]:[/\\]'
+	\ . '\|^[/\\]\{2}'
+  "    Unix absolute path 
+  " or Windows absolute path
+  " or UNC path
+endfunction
+function! lh#path#IsAbsolutePath(path)
+  return lh#path#is_absolute_path(a:path)
+endfunction
+
+" Function: lh#path#is_url({path}) {{{3
+function! lh#path#is_url(path)
+  " todo: support UNC paths and other urls
+  return a:path =~ '^\%(https\=\|s\=ftp\|dav\|fetch\|file\|rcp\|rsynch\|scp\)://'
+endfunction
+function! lh#path#IsURL(path)
+  return lh#path#is_url(a:path)
+endfunction
+
+" Function: lh#path#select_one({pathnames},{prompt}) {{{3
+function! lh#path#select_one(pathnames, prompt)
+  if len(a:pathnames) > 1
+    let simpl_pathnames = deepcopy(a:pathnames) 
+    let simpl_pathnames = lh#path#strip_common(simpl_pathnames)
+    let simpl_pathnames = [ '&Cancel' ] + simpl_pathnames
+    " Consider guioptions+=c is case of difficulties with the gui
+    let selection = confirm(a:prompt, join(simpl_pathnames,"\n"), 1, 'Question')
+    let file = (selection == 1) ? '' : a:pathnames[selection-2]
+    return file
+  elseif len(a:pathnames) == 0
+    return ''
+  else
+    return a:pathnames[0]
+  endif
+endfunction
+function! lh#path#SelectOne(pathnames, prompt)
+  return lh#path#select_one(a:pathnames, a:prompt)
+endfunction
+
+" Function: lh#path#to_relative({pathname}) {{{3
+function! lh#path#to_relative(pathname)
+  let newpath = fnamemodify(a:pathname, ':p:.')
+  let newpath = simplify(newpath)
+  return newpath
+endfunction
+function! lh#path#ToRelative(pathname)
+  return lh#path#to_relative(a:pathname)
+endfunction
+
+" Function: lh#path#to_dirname({dirname}) {{{3
+" todo: use &shellslash
+function! lh#path#to_dirname(dirname)
+  let dirname = a:dirname . (a:dirname[-1:] =~ '[/\\]' ? '' : '/')
+  return dirname
+endfunction
+
+" Function: lh#path#depth({dirname}) {{{3
+" todo: make a choice about "negative" paths like "../../foo"
+function! lh#path#depth(dirname)
+  if empty(a:dirname) | return 0 | endif
+  let dirname = lh#path#to_dirname(a:dirname)
+  let dirname = lh#path#simplify(dirname)
+  if lh#path#is_absolute_path(dirname)
+    let dirname = matchstr(dirname, '.\{-}[/\\]\zs.*')
+  endif
+  let depth = len(substitute(dirname, '[^/\\]\+[/\\]', '§', 'g'))
+  return depth
+endfunction
+
+" Function: lh#path#relative_to({from}, {to}) {{{3
+" @param two directories
+" @return a directories delta that ends with a '/' (may depends on
+" &shellslash)
+function! lh#path#relative_to(from, to)
+  " let from = fnamemodify(a:from, ':p')
+  " let to   = fnamemodify(a:to  , ':p')
+  let from = lh#path#to_dirname(a:from)
+  let to   = lh#path#to_dirname(a:to  )
+  let [from, to] = lh#path#strip_common([from, to])
+  let nb_up =  lh#path#depth(from)
+  return repeat('../', nb_up).to
+
+  " cannot rely on :cd (as it alters things, and doesn't work with
+  " non-existant paths)
+  let pwd = getcwd()
+  exe 'cd '.a:to
+  let res = lh#path#to_relative(a:from)
+  exe 'cd '.pwd
+  return res
+endfunction
+
+" Function: lh#path#glob_as_list({pathslist}, {expr}) {{{3
+function! s:GlobAsList(pathslist, expr)
+  let sResult = globpath(a:pathslist, a:expr)
+  let lResult = split(sResult, '\n')
+  " workaround a non feature of wildignore: it does not ignore directories
+  for ignored_pattern in split(&wildignore,',')
+    if stridx(ignored_pattern,'/') != -1
+      call filter(lResult, 'v:val !~ '.string(ignored_pattern))
+    endif
+  endfor
+  return lResult
+endfunction
+
+function! lh#path#glob_as_list(pathslist, expr)
+  if type(a:expr) == type('string')
+    return s:GlobAsList(a:pathslist, a:expr)
+  elseif type(a:expr) == type([])
+    let res = []
+    for expr in a:expr
+      call extend(res, s:GlobAsList(a:pathslist, expr))
+    endfor
+    return res
+  else
+    throw "Unexpected type for a:expression"
+  endif
+endfunction
+function! lh#path#GlobAsList(pathslist, expr)
+  return lh#path#glob_as_list(a:pathslist, a:expr)
+endfunction
+
+" Function: lh#path#strip_start({pathname}, {pathslist}) {{{3
+" Strip occurrence of paths from {pathslist} in {pathname}
+" @param[in] {pathname} name to simplify
+" @param[in] {pathslist} list of pathname (can be a |string| of pathnames
+" separated by ",", of a |List|).
+function! lh#path#strip_start(pathname, pathslist)
+  if type(a:pathslist) == type('string')
+    " let strip_re = escape(a:pathslist, '\\.')
+    " let strip_re = '^' . substitute(strip_re, ',', '\\|^', 'g')
+    let pathslist = split(a:pathslist, ',')
+  elseif type(a:pathslist) == type([])
+    let pathslist = deepcopy(a:pathslist)
+  else
+    throw "Unexpected type for a:pathname"
+  endif
+
+  " apply a realpath like operation
+  let nb_paths = len(pathslist) " set before the loop
+  let i = 0
+  while i != nb_paths
+    if pathslist[i] =~ '^\.\%(/\|$\)'
+      let path2 = getcwd().pathslist[i][1:]
+      call add(pathslist, path2)
+    endif
+    let i += 1
+  endwhile
+  " replace path separators by a regex that can match them
+  call map(pathslist, 'substitute(v:val, "[\\\\/]", "[\\\\/]", "g")')
+  " echomsg string(pathslist)
+  " escape .
+  call map(pathslist, '"^".escape(v:val, ".")')
+  " build the strip regex
+  let strip_re = join(pathslist, '\|')
+  " echomsg strip_re
+  let res = substitute(a:pathname, '\%('.strip_re.'\)[/\\]\=', '', '')
+  return res
+endfunction
+function! lh#path#StripStart(pathname, pathslist)
+  return lh#path#strip_start(a:pathname, a:pathslist)
+endfunction
+
+" Function: lh#path#to_regex({pathname}) {{{3
+function! lh#path#to_regex(path)
+  let regex = substitute(a:path, '[/\\]', '[/\\\\]', 'g')
+  return regex
+endfunction
+
+" Function: lh#path#find({pathname}, {regex}) {{{3
+function! lh#path#find(paths, regex)
+  let paths = (type(a:paths) == type([]))
+	\ ? (a:paths) 
+	\ : split(a:paths,',')
+  for path in paths
+    if match(path ,a:regex) != -1
+      return path
+    endif
+  endfor
+  return ''
+endfunction
+"=============================================================================
+let &cpo=s:cpo_save
+"=============================================================================
+" vim600: set fdm=marker:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/lh-vim-lib/autoload/lh/position.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,93 @@
+"=============================================================================
+" $Id: position.vim 246 2010-09-19 22:40:58Z luc.hermitte $
+" File:		autoload/lh/position.vim                               {{{1
+" Author:	Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
+"		<URL:http://code.google.com/p/lh-vim/>
+" Version:	2.2.1
+" Created:	05th Sep 2007
+" Last Update:	$Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $ (05th Sep 2007)
+"------------------------------------------------------------------------
+" Description:	«description»
+" 
+"------------------------------------------------------------------------
+" Installation:
+" 	Drop it into {rtp}/autoload/lh/
+" 	Vim 7+ required.
+" History:	«history»
+" 	v1.0.0:
+" 		Creation
+" TODO:		
+" }}}1
+"=============================================================================
+
+
+"=============================================================================
+let s:cpo_save=&cpo
+set cpo&vim
+"------------------------------------------------------------------------
+" ## Functions {{{1
+" # Debug {{{2
+function! lh#position#verbose(level)
+  let s:verbose = a:level
+endfunction
+
+function! s:Verbose(expr)
+  if exists('s:verbose') && s:verbose
+    echomsg a:expr
+  endif
+endfunction
+
+function! lh#position#debug(expr)
+  return eval(a:expr)
+endfunction
+
+
+"------------------------------------------------------------------------
+" # Public {{{2
+" Function: lh#position#is_before {{{3
+" @param[in] positions as those returned from |getpos()|
+" @return whether lhs_pos is before rhs_pos
+function! lh#position#is_before(lhs_pos, rhs_pos)
+  if a:lhs_pos[0] != a:rhs_pos[0]
+    throw "Positions from incompatible buffers can't be ordered"
+  endif
+  "1 test lines
+  "2 test cols
+  let before 
+	\ = (a:lhs_pos[1] == a:rhs_pos[1])
+	\ ? (a:lhs_pos[2] < a:rhs_pos[2])
+	\ : (a:lhs_pos[1] < a:rhs_pos[1])
+  return before
+endfunction
+function! lh#position#IsBefore(lhs_pos, rhs_pos)
+  return lh#position#is_before(a:lhs_pos, a:rhs_pos)
+endfunction
+
+
+" Function: lh#position#char_at_mark {{{3
+" @return the character at a given mark (|mark|)
+function! lh#position#char_at_mark(mark)
+  let c = getline(a:mark)[col(a:mark)-1]
+  return c
+endfunction
+function! lh#position#CharAtMark(mark)
+return lh#position#char_at_mark(a:mark)
+endfunction
+
+" Function: lh#position#char_at_pos {{{3
+" @return the character at a given position (|getpos()|)
+function! lh#position#char_at_pos(pos)
+  let c = getline(a:pos[1])[col(a:pos[2])-1]
+  return c
+endfunction
+function! lh#position#CharAtPos(pos)
+  return  lh#position#char_at_pos(a:pos)
+endfunction
+
+
+
+" Functions }}}1
+"------------------------------------------------------------------------
+let &cpo=s:cpo_save
+"=============================================================================
+" vim600: set fdm=marker:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/lh-vim-lib/autoload/lh/syntax.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,138 @@
+"=============================================================================
+" $Id: syntax.vim 246 2010-09-19 22:40:58Z luc.hermitte $
+" File:		autoload/lh/syntax.vim                               {{{1
+" Author:	Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
+"		<URL:http://code.google.com/p/lh-vim/>
+" Version:	2.2.1
+" Created:	05th Sep 2007
+" Last Update:	$Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $ (05th Sep 2007)
+"------------------------------------------------------------------------
+" Description:	«description»
+" 
+"------------------------------------------------------------------------
+" Installation:
+" 	Drop it into {rtp}/autoload/lh/
+" 	Vim 7+ required.
+" History:	«history»
+" 	v1.0.0:
+" 		Creation ;
+" 		Functions moved from lhVimSpell
+" TODO:
+" 	function, to inject "contained", see lhVimSpell approach
+" }}}1
+"=============================================================================
+
+
+"=============================================================================
+let s:cpo_save=&cpo
+set cpo&vim
+"------------------------------------------------------------------------
+" ## Functions {{{1
+" # Debug {{{2
+function! lh#syntax#verbose(level)
+  let s:verbose = a:level
+endfunction
+
+function! s:Verbose(expr)
+  if exists('s:verbose') && s:verbose
+    echomsg a:expr
+  endif
+endfunction
+
+function! lh#syntax#debug(expr)
+  return eval(a:expr)
+endfunction
+
+" # Public {{{2
+" Functions: Show name of the syntax kind of a character {{{3
+function! lh#syntax#name_at(l,c, ...)
+  let what = a:0 > 0 ? a:1 : 0
+  return synIDattr(synID(a:l, a:c, what),'name')
+endfunction
+function! lh#syntax#NameAt(l,c, ...)
+  let what = a:0 > 0 ? a:1 : 0
+  return lh#syntax#name_at(a:l, a:c, what)
+endfunction
+
+function! lh#syntax#name_at_mark(mark, ...)
+  let what = a:0 > 0 ? a:1 : 0
+  return lh#syntax#name_at(line(a:mark), col(a:mark), what)
+endfunction
+function! lh#syntax#NameAtMark(mark, ...)
+  let what = a:0 > 0 ? a:1 : 0
+  return lh#syntax#name_at_mark(a:mark, what)
+endfunction
+
+" Functions: skip string, comment, character, doxygen {{{3
+func! lh#syntax#skip_at(l,c)
+  return lh#syntax#name_at(a:l,a:c) =~? 'string\|comment\|character\|doxygen'
+endfun
+func! lh#syntax#SkipAt(l,c)
+  return lh#syntax#skip_at(a:l,a:c)
+endfun
+
+func! lh#syntax#skip()
+  return lh#syntax#skip_at(line('.'), col('.'))
+endfun
+func! lh#syntax#Skip()
+  return lh#syntax#skip()
+endfun
+
+func! lh#syntax#skip_at_mark(mark)
+  return lh#syntax#skip_at(line(a:mark), col(a:mark))
+endfun
+func! lh#syntax#SkipAtMark(mark)
+  return lh#syntax#skip_at_mark(a:mark)
+endfun
+
+" Function: Show current syntax kind {{{3
+command! SynShow echo 'hi<'.lh#syntax#name_at_mark('.',1).'> trans<'
+      \ lh#syntax#name_at_mark('.',0).'> lo<'.
+      \ synIDattr(synIDtrans(synID(line('.'), col('.'), 1)), 'name').'>'
+
+
+" Function: lh#syntax#list_raw(name) : string                     {{{3
+function! lh#syntax#list_raw(name)
+  let a_save = @a
+  try
+    redir @a
+    exe 'silent! syn list '.a:name
+    redir END
+    let res = @a
+  finally
+    let @a = a_save
+  endtry
+  return res
+endfunction
+
+" Function: lh#syntax#list(name) : List                     {{{3
+function! lh#syntax#list(name)
+  let raw = lh#syntax#list_raw(a:name)
+  let res = [] 
+  let lines = split(raw, '\n')
+  let started = 0
+  for l in lines
+    if started
+      let li = (l =~ 'links to') ? '' : l
+    elseif l =~ 'xxx'
+      let li = matchstr(l, 'xxx\s*\zs.*')
+      let started = 1
+    else
+      let li = ''
+    endif
+    if strlen(li) != 0
+      let li = substitute(li, 'contained\S*\|transparent\|nextgroup\|skipwhite\|skipnl\|skipempty', '', 'g')
+      let kinds = split(li, '\s\+')
+      call extend(res, kinds)
+    endif
+  endfor
+  return res
+endfunction
+
+
+
+" Functions }}}1
+"------------------------------------------------------------------------
+let &cpo=s:cpo_save
+"=============================================================================
+" vim600: set fdm=marker:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/lh-vim-lib/autoload/lh/visual.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,42 @@
+"=============================================================================
+" $Id$
+" File:		autoload/lh/visual.vim                               {{{1
+" Author:	Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
+"		<URL:http://code.google.com/p/lh-vim/>
+" Version:	2.2.1
+" Created:	08th Sep 2008
+" Last Update:	$Date$
+"------------------------------------------------------------------------
+" 	Helpers functions releated to the visual mode
+" 
+"------------------------------------------------------------------------
+" 	Drop it into {rtp}/autoload/lh/
+" 	Vim 7+ required.
+" History:	
+" 	v2.0.6: First appearance
+" TODO:		«missing features»
+" }}}1
+"=============================================================================
+
+let s:cpo_save=&cpo
+set cpo&vim
+"------------------------------------------------------------------------
+" Functions {{{1
+
+" Function: lh#visual#selection()                              {{{3
+" @return the text currently selected
+function! lh#visual#selection()
+  try
+    let a_save = @a
+    normal! gv"ay
+    return @a
+  finally
+    let @a = a_save
+  endtry
+endfunction
+
+" Functions }}}1
+"------------------------------------------------------------------------
+let &cpo=s:cpo_save
+"=============================================================================
+" vim600: set fdm=marker:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/lh-vim-lib/doc/lh-vim-lib.txt	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,1252 @@
+*lh-vim-lib.txt*        Vim common libraries (v2.2.1)
+                        For Vim version 7+      Last change: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $
+
+                        By Luc Hermitte
+                        hermitte {at} free {dot} fr
+
+
+==============================================================================
+CONTENTS                                      *lhvl-contents*      {{{1
+|lhvl-presentation|     Presentation
+|lhvl-functions|        Functions
+    
+|add-local-help|        Instructions on installing this help file
+
+
+------------------------------------------------------------------------------
+PRESENTATION                                  *lhvl-presentation*  {{{1
+
+|lh-vim-lib| is a library that defines some common VimL functions I use in my
+various plugins and ftplugins.
+This library has been conceived as a suite of |autoload| plugins, and a few
+|macros| plugins. As such, it requires Vim 7+.
+
+
+==============================================================================
+FUNCTIONS                                     *lhvl-functions*     {{{1
+{{{2Functions list~
+Miscellanous functions:                                 |lhvl#misc|
+- |lh#askvim#exe()|
+- |lh#common#check_deps()|
+- |lh#common#error_msg()|
+- |lh#common#warning_msg()|
+- |lh#common#echomsg_multilines()|
+- |lh#encoding#iconv()|
+- |lh#event#register_for_one_execution_at()|
+- |lh#option#get()|
+- |lh#option#get_non_empty()|
+- |lh#position#char_at_mark()|
+- |lh#position#char_at_pos()|
+- |lh#position#is_before()|
+- |lh#visual#selection()|
+Functors related functions:                             |lhvl#function|
+- |lh#function#bind()|
+- |lh#function#execute()|
+- |lh#function#prepare()|
+Lists related functions:                                |lhvl#list|
+- |lh#list#accumulate()|
+- |lh#list#copy_if()|
+- |lh#list#Find_if()| and |lh#list#find_if()|
+- |lh#list#intersect()|
+- |lh#list#match()|
+- |lh#list#subset()|
+- |lh#list#Transform()| and |lh#list#transform()|
+- |lh#list#transform_if()|
+- |lh#list#unique_sort()| and |lh#list#unique_sort2()|
+o |lh#list#equal_range()|, 
+  |lh#list#lower_bound()| and |lh#list#upper_bound()| 
+Graphs related functions:                               |lhvl#graph|
+- |lh#graph#tsort#depth()|
+- |lh#graph#tsort#breadth()|
+Paths related functions:                                |lhvl#path|
+- |lh#path#common()|
+- |lh#path#depth()|
+- |lh#path#glob_as_list()|
+- |lh#path#is_absolute_path()|
+- |lh#path#is_url()|
+- |lh#path#select_one()|
+- |lh#path#simplify()|
+- |lh#path#strip_common()|
+- |lh#path#strip_start()|
+- |lh#path#to_dirname()|
+- |lh#path#to_relative()|
+- |lh#path#relative_to()|
+- |lh#path#to_regex()|
+Commands related functions:                             |lhvl#command|
+- |lh#command#new()| (alpha version)
+- |lh#command#Fargs2String()| (alpha version)
+- |lh#command#complete()| (alpha version)
+Menus related functions:                                |lhvl#menu|
+- |lh#menu#def_toggle_item()|
+- |lh#menu#text()|
+- |lh#menu#make()|
+- |lh#menu#IVN_make()|
+- |lh#menu#is_in_visual_mode()|
+- |lh#menu#map_all()|
+- |lh#askvim#menu()| (beta version)
+Buffers related functions:                              |lhvl#buffer|
+- |lh#buffer#list()|
+- |lh#buffer#find()|
+- |lh#buffer#jump()|
+- |lh#buffer#scratch()|
+- |lh#buffer#dialog#| functions for building interactive dialogs
+    - |lh#buffer#dialog#new()|
+    - |lh#buffer#dialog#add_help()|
+    - |lh#buffer#dialog#select()|
+    - |lh#buffer#dialog#quit()|
+    - |lh#buffer#dialog#update()|
+Syntax related functions:                               |lhvl#syntax|
+- |lh#syntax#name_at()|
+- |lh#syntax#name_at_mark()|
+- |lh#syntax#skip()|
+- |lh#syntax#skip_at()|
+- |lh#syntax#skip_at_mark()|
+- |lh#syntax#list_raw()|
+- |lh#syntax#list()|
+
+}}}2
+------------------------------------------------------------------------------
+MISCELLANOUS FUNCTIONS                                *lhvl#misc*       {{{2
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                       *lh#common#echomsgMultilines()*  {{{3
+lh#common#echomsgMultilines()({text}) (*deprecated*)~
+                                      *lh#common#echomsg_multilines()*
+lh#common#echomsg_multilines()({text})~
+@param  {text}      Message to display on several lines
+@return             Nothing
+
+This function executes |:echomsg| as many times as required as there are lines
+in the original {text}.
+This is a workaround |:echomsg| that is unable to handle correctly multi-lines
+messages.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                                *lh#common#ErrorMsg()*  {{{3
+lh#common#ErrorMsg({text}) (*deprecated*)~
+                                               *lh#common#error_msg()*
+lh#common#error_msg({text})~
+@param  {text}      Error message to display
+@return             Nothing
+
+This function displays an error message in a |confirm()| box if gvim is being
+used, or as a standard vim error message through |:echoerr| otherwise. 
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                               *lh#common#WarningMsg()* {{{3
+lh#common#WarningMsg({text}) (*deprecated*)~
+                                              *lh#common#warning_msg()*
+lh#common#warning_msg({text})~
+@param  {text}      Error message to display
+@return             Nothing
+
+This function displays a warning message highlighted with |WarningMsg| syntax.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                                *lh#common#CheckDeps()* {{{3
+lh#common#CheckDeps({symbol},{file},{path},{requester}) (*deprecated*)~
+                                               *lh#common#check_deps()*
+lh#common#check_deps({symbol},{file},{path},{requester})~
+@param  {symbol}    Symbol required, see |exists()| for symbol format.
+@param  {file}      File in which the symbol is expected to be defined
+@param  {path}      Path where the file can be found
+@param  {requester} Name of the script in need of this symbol
+@return 0/1 whether the {symbol} exists
+
+Checks if {symbol} exists in vim. If not, this function first tries
+to |:source| the {file} in which the {symbol} is expected to be defined. If the
+{symbol} is still not defined, an error message is issued (with
+|lh#common#error_msg()|, and 0 is returned.
+
+Example: >
+    if   
+          \    !lh#common#check_deps('*Cpp_CurrentScope', 
+          \                     'cpp_FindContextClass.vim', 'ftplugin/cpp/',
+          \                     'cpp#GotoFunctionImpl.vim')
+          \ || !lh#common#check_deps(':CheckOptions',
+          \                     'cpp_options-commands.vim', 'ftplugin/cpp/',
+          \                     'cpp#GotoFunctionImpl.vim')
+      let &cpo=s:cpo_save
+      finish
+    endif
+
+Note: Since the introduction of |autoload| plugins in Vim 7, this function has
+lost most of its interrest.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                                *lh#option#Get()*       {{{3
+lh#option#Get({name},{default}[,{scopes}])  (*deprecated*)~
+                                                *lh#option#get()*
+lh#option#get({name},{default}[,{scopes}])~
+@param {name}       Name of the option to fetch
+@param {default}    Default value in case the option is not defined
+@param {scopes}     Vim scopes in which the options must be searched,
+                    default="bg".
+@return             b:{name} if it exists, or g:{name} if it exists, or
+                    {default} otherwise.
+@see                For development oriented options, |lh-dev| provides a
+                    dedicated function: |lh#dev#option#get()|.
+
+This function fetches the value of an user defined option (not Vim |options|).
+The option can be either a |global-variable|, a |buffer-variable|, or even
+a|window-variable|.
+
+The order of the variables checked can be specified through the optional
+argument {scopes}. By default, buffer-local options have the priority over
+global options.
+
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                              *lh#option#GetNonEmpty()* {{{3
+lh#option#GetNonEmpty({name},{default}[,{scopes}])  (*deprecated*)~
+                                              *lh#option#get_non_empty()*
+lh#option#get_non_empty({name},{default}[,{scopes}])~
+@param {name}       Name of the option to fetch
+@param {default}    Default value in case the option is not defined, nor empty
+@param {scopes}     Vim scopes in which the options must be searched,
+                    default="bg".
+@return b:{name}    If it exists, of g:{name} if it exists, or {default}
+                    otherwise.
+
+This function works exactly like |lh#option#get()| except that a defined
+variable with an empty value will be ignored as well.
+An |expr-string| will be considered empty if its |strlen()| is 0, an
+|expr-number| when it values 0, |Lists| and |Dictionaries| when their |len()|
+is 0.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                                *lh#askvim#Exe()*       {{{3
+lh#askvim#Exe({command}) (*deprecated*)~
+                                                *lh#askvim#exe()*
+lh#askvim#exe({command})~
+@param {command}    Command to execute from vim.
+@return             What the command echoes while executed.
+@note               This function encapsultates |redir| without altering any
+                    register.
+
+Some information aren't directly accessible (yet) through vim API
+(|functions|).  However, they can be obtained by executing some commands, and
+redirecting the result of these commands.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                                *lh#askvim#menu()*      {{{3
+lh#askvim#menu({menuid},{modes})~
+@param {menuid}     Menu identifier.
+@param {modes}      List of modes
+@return             Information related to the {menuid}
+@todo               Still bugged
+
+This function provides a way to obtain information related to a menu entry in
+Vim.
+
+The format of the result being «to be stabilized»
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                               *lh#position#IsBefore()* {{{3
+lh#position#IsBefore({lhs_pos},{rhs_pos})  (*deprecated*)~
+                                               *lh#position#is_before()*
+lh#position#is_before({lhs_pos},{rhs_pos})~
+@param[in]          Positions as those returned from |getpos()|
+@return             Whether {lhs_pos} is before {rhs_pos}
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                             *lh#position#CharAtMark()* {{{3
+lh#position#CharAtMark({mark})  (*deprecated*)~
+                                             *lh#position#char_at_mark()*
+lh#position#char_at_mark({mark})~
+@return             The character at a given |mark|.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                              *lh#position#CharAtPos()* {{{3
+lh#position#CharAtPos({pos})  (*deprecated*)~
+                                              *lh#position#char_at_pos()* {{{3
+lh#position#char_at_pos({pos})~
+@return             The character at a position (see |getpos()|).
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                                *lh#visual#selection()* {{{3
+lh#visual#selection()~
+@return             The current visual selection
+@post              |registers| are not altered by this function
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                 *lh#event#RegisterForOneExecutionAt()* {{{3
+lh#event#RegisterForOneExecutionAt({event}, {cmd}, {group})  (*deprecated*)~
+                                 *lh#event#register_for_one_execution_at()*
+lh#event#register_for_one_execution_at({event}, {cmd}, {group})~
+Registers a command to be executed once (and only once) when {event} is
+triggered on the current file.
+
+@param {event}  Event that will trigger the execution of {cmd}|autocmd-events|
+@param   {cmd} |expression-command| to execute
+@param {group} |autocmd-groups| under which the internal autocommand will be
+                registered.
+@todo possibility to specify the file pattern
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                                *lh#encoding#iconv()*   {{{3
+lh#encoding#iconv({expr}, {from}, {to})~
+This function just calls |iconv()| with the same arguments. The only
+difference is that it return {expr} when we know that |iconv()| will return an
+empty string.
+
+
+------------------------------------------------------------------------------
+FUNCTORS RELATED FUNCTIONS                            *lhvl#function*   {{{2
+
+This sub-library helps defining functors-like variables, and execute them.
+
+NB: C++ developpers may be already familiar with boost.bind
+(/std(::tr1)::bind) function that inspired by feature.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+                                                      *lhvl#functor*    {{{3
+A functor is implemented as a |Dictionary| that has the following fields:
+- {execute}  is the |Funcref| that will be actually executed by
+             |lh#function#execute()|. Its only argument is a |List| of
+              arguments for {function}.
+- {function} that identifies the function to execute, 
+              internals: it could be either a |Funcref|or a |expr-string|, or
+              whatever is compatible with the {execute} |FuncRef| field.
+- {args}     will contain the binded arguments as defined by
+             |lh#function#bind()|. If you attach a {execute} function of your
+              own to a functor, you don't need to fill "args".
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+                                                *lh#function#bind()*    {{{3
+lh#function#bind({fn} [, {arguments} ...])~
+This function creates a new |lhvl#functor| based on a given function {fn}, and
+where some arguments are binded to the ones from {arguments}.
+The result is a new function-like data having for parameter v:1_, v:2_, ...
+that were specified in |lh#function#bind()| {arguments} list.
+
+Examples:~
+   See tests/lh/function.vim
+
+Let's suppose Print(...) a VimL variadic function that echoes the arguments it
+receives, i.e. >
+   call Print(1,2,"text", ['foo', 'bar'])
+will echo: >
+   1 ## 2 ## 'text' ## ['foo', 'bar']
+
+* Binding a |FuncRef|:~
+  and reverse the arguments given to it when it will be executed >
+   >:let func = lh#function#bind(function('Print'), 'v:3_', 'v:2_', 'v:1_')
+   >:echo lh#function#execute(func, 1, 'two', [3])
+   [3] ## 'two' ## 1
+
+* Binding a named function:~
+  the new function has 3 parameters and calls the named function with its 3rd
+  parameter, 42, its second and its first parameters as arguments. >
+   >:let func = lh#function#bind('Print', 'v:3_', 42, 'v:2_', 'v:1_')
+   >:echo lh#function#execute(func, 1, 'two', [3])
+   [3] ## 42 ## 'two' ## 1
+< NB: if exists('*'.func_name) is false, then the string is considered to be
+  an expression that will be evaluated as specified in the next use case.
+
+* Binding an expression:~
+  This time more complex on-the-fly computations on the |lhvl#functor|
+  parameters can be accomplished >
+   >:let func = lh#function#bind('Print(len(v:3_), 42, v:2_, v:1_)')
+   >:echo lh#function#execute(func, 1, 'two', [1,2,3])
+   3 ## 42 ## 'two' ## 1
+< NB: func["args"] is defined, but empty, and unused.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+                                                *lh#function#execute()* {{{3
+lh#function#execute({functor} [, {arguments} ...])~
+While |lh#function#bind()| defines a |lhvl#functor| that can be stored and
+used later, |lh#function#execute()| directly executes the {functor} received.
+
+Different kind of {functors} are accepted:
+- |FuncRef|, and function names, where arguments are |lh#function#execute()|
+  ones ;
+- |expr-string|, where "v:{pos}_" strings are binded on-the-fly to {arguments} ;
+- |lhvl#functor|, that will be given {arguments} as arguments.
+
+Examples:~
+   See tests/lh/function.vim
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+                                                *lh#function#prepare()* {{{3
+lh#function#prepare({function}, {arguments} ...)~
+This function expands all the elements from the {arguments} |List|, and
+prepares a |expr-string| that once evaluated will call the n-ary {function}
+with the n-{arguments}.
+The evaluation is meant to be done with |eval()|.
+>
+   >:let call = lh#function#prepare('Print', [1,2,"foo"])
+   >:echo eval(call)
+   1 ## 2 ## 'foo'
+
+
+------------------------------------------------------------------------------
+LISTS RELATED FUNCTIONS                               *lhvl#list*       {{{2
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                                *lh#list#Match()*       {{{3
+lh#list#Match({list},{pattern}[, {start-pos}])  (*deprecated*)~
+                                                *lh#list#match()*
+lh#list#match({list},{pattern}[, {start-pos}])~
+@param      {list} |List| 
+@param   {pattern} |expr-string|
+@param {start-pos}  First index to check
+@return             The lowest index, >= {start-pos}, in |List| {list} where
+                    the item matches {pattern}.
+@return             -1 if no item matches {pattern}.
+@see |index()|, |match()|
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                            *lh#list#find_if()* *lh#list#Find_if()*     {{{3
+lh#list#Find_if({list},{string-predicate} [, {pred-parameters}][, {start-pos}])~
+lh#list#find_if({list},{functor-predicate} [, {pred-parameters}][, {start-pos}])~
+@param             {list} |List| 
+@param      {*-predicate}  Predicate to evaluate
+@param {pred-parameters}] |List| of Parameters to bind to special arguments in
+                           the {predicate}.
+@param         {start-pos} First index to check
+@return                    The lowest index, >= {start-pos}, in |List| {list}
+                           where the {predicate} evals to true.
+@return                    -1 if no item matches {pattern}.
+@see |index()|, |eval()|
+
+The {string-predicate} recognizes some special arguments:
+- |v:val| is substituted with the current element being evaluated in the list
+- *v:1_* *v:2_* , ..., are substituted with the i-th elements from
+  {pred-parameters}.
+  NB: the "v:\d\+_" are 1-indexed while {pred-parameters} is indeed seen as
+  0-indexed by Vim. 
+  This particular feature permits to pass any type of variable to the
+  predicate: a |expr-string|, a |List|, a |Dictionary|, ...
+
+e.g.: >
+    :let b = { 'min': 12, 'max': 42 }
+    :let l = [ 1, 5, 48, 25, 5, 28, 6]
+    :let i = lh#list#Find_if(l, 'v:val>v:1_.min  && v:val<v:1_.max && v:val%v:2_==0', [b, 2] )
+    :echo l[i]
+    28
+
+The {functor-predicate} is a |lhvl#function|. The same example can be
+rewritten as: >
+    :let l = [ 1, 5, 48, 25, 5, 28, 6]
+    :let i = lh#list#find_if(l, 'v:1_>12  && v:1_<42 && v:1_%2==0')
+    :echo l[i]
+    28
+NB: Expect the Find_if() version to be replaced with the find_if() one.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                   *lh#list#unique_sort()* *lh#list#unique_sort2()*     {{{3
+lh#list#unique_sort({list} [, {cmp}])~
+lh#list#unique_sort2({list} [, {cmp}])~
+@param[in] {list} |List| to sort
+@param      {cmp} |Funcref| or function name that acts as a compare predicate.
+                   It seems to be required in order to not compare number with
+                   a lexicographic order (with vim 7.1-156)
+@return            A new |List| sorted with no element repeated
+@todo support an optional {equal} predicate to use in the /unique/ making
+process.
+
+The difference between the two functions is the following:
+- unique_sort() stores all the elements in a |Dictionary|, then sort the values
+  stored in the dictionary ;
+- unique_sort2() sorts all the elements from the initial |List|, and then
+  keeps only the elements that appear once.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                                *lh#list#Transform()*   {{{3
+lh#list#Transform({input},{output},{action})~
+@param[in]   {input} Input |List| to transform
+@param[out] {output} Output |List| where the transformed elements will be
+                     appended.
+@param      {action} Stringified action to apply on each element from {input}.
+                     The string "v:val" will always be replaced with the
+                     element currently transformed.
+@return {output}
+
+This function is actually returning >
+    extend(a:output, map(copy(a:input), a:action))
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                                *lh#list#transform()*   {{{3
+lh#list#transform({input},{output},{action})~
+@param[in]   {input} Input |List| to transform
+@param[out] {output} Output |List| where the transformed elements will be
+                     appended.
+@param      {action}|lhvl#functor| action to apply on each element from
+                     {input}.
+@return              {output}
+
+This function is equivalent to (|lh#list#Transform()|) >
+    extend(a:output, map(copy(a:input), a:action))
+except the action is not a string but a |lhvl#functor|.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                               *lh#list#transform_if()* {{{3
+lh#list#transform_if({input},{output},{action},{predicate})~
+@param[in]   {input} Input |List| to transform
+@param[out] {output} Output |List| where the transformed elements will be
+                     appended.
+@param      {action}|lhvl#functor| action to apply on each element from
+                     {input} that verifies the {predicate}.
+@param   {predicate} Boolean |lhvl#functor| tested on each element before
+                     transforming it.
+@return              {output}
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                               *lh#list#copy_if()*      {{{3
+lh#list#copy_if({input},{output},{predicate})~
+Appends in {output} the elements from {input} that verifies the {predicate}. 
+
+@param[in]   {input} Input |List| to transform
+@param[out] {output} Output |List| where the elements that verify the
+                     {predicate} will be appended.
+@param   {predicate} Boolean |lhvl#functor| tested on each element.
+@return              {output}
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                               *lh#list#accumulate()*   {{{3
+lh#list#accumulate({input},{transformation},{accumulator})~
+Accumulates the transformed elements from {input}.
+
+@param[in]      {input} Input |List| to transform
+@param {transformation}|lhvl#functor| applied on each element from {input}.
+@param    {accumulator}|lhvl#functor| taking the list of tranformaed elements
+                        as input
+@return                 the result of {accumulator}
+
+Examples: >
+   :let strings = [ 'foo', 'bar', 'toto' ]
+   :echo eval(lh#list#accumulate(strings, 'strlen', 'join(v:1_,  "+")'))
+   10
+
+   :let l = [ 1, 2, 'foo', ['bar']]
+   :echo lh#list#accumulate(l, 'string', 'join(v:1_, "##")')
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                               *lh#list#subset()*       {{{3
+lh#list#subset({input},{indices})~
+Returns a subset slice of the {input} list.
+
+@param[in] {input}   Input |List| from which  element will be extracted
+@param[in] {indices}|List| of indices to extract
+@return a |List| of the elements from {input} indexed by the {indices}
+
+Example: >
+    :let l = [ 1, 25, 5, 48, 25, 5, 28, 6]
+    :let indices = [ 0, 5, 7, 3 ]
+    :echo lh#list#subset(l, indices) 
+    [ 1, 5, 6, 48 ]
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                               *lh#list#intersect()*    {{{3
+lh#list#intersect({list1},{list2})~
+Returns the elements present in both input lists.
+
+@param[in] {list1}|List| 
+@param[in] {list2}|List| 
+@return a |List| of the elements in both {list1} and {list2}, the elements are
+kepts in the same order as in {list1}
+@note the algorithm is in O(len({list1})*len({list2}))
+
+Example: >
+    :let l1 = [ 1, 25, 7, 48, 26, 5, 28, 6]
+    :let l2 = [ 3, 8, 7, 25, 6 ]
+    :echo lh#list#intersect(l1, l2) 
+    [ 25, 7, 6 ]
+
+------------------------------------------------------------------------------
+GRAPHS RELATED FUNCTIONS                              *lhvl#graph*      {{{2
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                             *lh#graph#tsort#depth()*   {{{3
+                                             *lh#graph#tsort#breadth()* {{{3
+lh#graph#tsort#depth({dag}, {start-nodes})~
+lh#graph#tsort#breadth({dag}, {start-nodes})~
+These two functions implement a topological sort on the Direct Acyclic Graph.
+- depth() is a recursive implementation of a depth-first search. 
+- breadth() is a non recursive implementation of a breadth-first search.
+
+@param {dag} is a direct acyclic graph defined either:
+             - as a |Dictionnary| that associates to each node, the |List| of
+               all its successors
+             - or as a /fetch/ |function()| that returns the |List| of the
+               successors of a given node -- works only with depth() which
+               takes care of not calling this function more than once for each
+               given node.
+@param {start-nodes} is a |List| of start nodes with no incoming edge
+@throw "Tsort: cyclic graph detected:" if {dag} is not a DAG.
+@see http://en.wikipedia.org/wiki/Topological_sort
+@since Version 2.1.0
+@test tests/lh/topological-sort.vim
+
+
+------------------------------------------------------------------------------
+PATHS RELATED FUNCTIONS                               *lhvl#path*       {{{2
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                                   *lh#path#depth()*    {{{3
+lh#path#depth({dirname})~
+Returns the depth of a directory name.
+
+@param {dirname}  Pathname to simplify
+@return the depth of the simplified directory name, i.e. 
+        lh#path#depth("bar/b2/../../foo/") returns 1
+
+@todo However, it is not able to return depth of negative paths like
+      "../../foo/". I still need to decide whether the function should return
+      -1 or 3.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                                 *lh#path#dirname()*    {{{3
+lh#path#dirname({dirname})~
+Ensures the returned directory name ends with a '/' or a '\'.
+
+@todo On windows, it should take 'shellslash' into account to decide the
+      character to append.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                                *lh#path#Simplify()*    {{{3
+lh#path#Simplify({pathname})  (*deprecated*)~
+                                                *lh#path#simplify()*
+lh#path#simplify({pathname})~
+Simplifies a path by getting rid of useless '../' and './'.
+
+@param {pathname}  Pathname to simplify
+@return the simplified pathname
+
+This function works like |simplify()|, except that it also strips the leading
+"./".
+
+Note: when vim is compiled for unix, it seems unable to |simplify()| paths
+containing "..\". (It likelly works this way when vim is compiled without
+'shellslash' support)
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                                    *lh#path#common()*  {{{3
+lh#path#common({pathnames})~
+@param[in] {pathnames} |List| of pathnames to analyse
+@return the common leading path between all {pathnames}
+
+e.g.: >
+ :echo lh#path#common(['foo/bar/file','foo/file', 'foo/foo/file'])
+echoes >
+ foo/
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                                *lh#path#StripCommon()* {{{3
+lh#path#StripCommon({pathnames})  (*deprecated*)~
+                                                *lh#path#strip_common()*
+lh#path#strip_common({pathnames})~
+@param[in,out] {pathnames} |List| of pathnames to simplify
+@return the simplified pathnames
+
+This function strips all pathnames from their common leading part. The
+compuation of the common leading part is ensured by |lh#path#common()|
+thank.
+e.g.: >
+ :echo lh#path#strip_common(['foo/bar/file','foo/file', 'foo/foo/file'])
+echoes >
+ ['bar/file','file', 'foo/file']
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                                 *lh#path#StripStart()* {{{3
+lh#path#StripStart({pathname}, {pathslist})  (*deprecated*)~
+                                                 *lh#path#strip_start()*
+lh#path#strip_start({pathname}, {pathslist})~
+@param[in] {pathname}  name to simplify
+@param[in] {pathslist} list of pathname (can be a |string| of pathnames
+                       separated by ",", of a |List|).
+
+Strips {pathname} from any path from {pathslist}.
+
+e.g.: >
+ :echo lh#path#strip_start($HOME.'/.vim/template/bar.template',
+   \ ['/home/foo/.vim', '/usr/local/share/vim/'])
+ :echo lh#path#strip_start($HOME.'/.vim/template/bar.template',&rtp)
+echoes >
+ template/bar.template
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                                *lh#path#IsAbsolutePath()* {{{3
+lh#path#IsAbsolutePath({path})  (*deprecated*)~
+                                                *lh#path#is_absolute_path()*
+lh#path#is_absolute_path({path})~
+@return {path} Path to test
+@return whether the path is an absolute path
+@note Supports Unix absolute paths, Windows absolute paths, and UNC paths
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                                *lh#path#IsURL()*       {{{3
+lh#path#IsURL({path})  (*deprecated*)~
+                                                *lh#path#is_url()*
+lh#path#is_url({path})~
+@return {path} Path to test
+@return whether the path is an URL
+@note Supports http(s)://, (s)ftp://, dav://, fetch://, file://, rcp://,
+rsynch://, scp://
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                                *lh#path#SelectOne()*   {{{3
+lh#path#SelectOne({pathnames},{prompt})  (*deprecated*)~
+                                                *lh#path#select_one()*
+lh#path#select_one({pathnames},{prompt})~
+@param[in] {pathnames} |List| of pathname
+@param     {prompt}     Prompt for the dialog box
+
+@return "" if len({pathnames}) == 0
+@return {pathnames}[0] if len({pathnames}) == 1
+@return the selected pathname otherwise
+
+Asks the end-user to choose a pathname among a list of pathnames.
+The pathnames displayed will be simplified thanks to |lh#path#strip_common()|
+-- the pathname returned is the "full" original pathname matching the
+simplified pathname selected.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                                *lh#path#ToRelative()*  {{{3
+lh#path#ToRelative({pathname})  (*deprecated*)~
+                                                *lh#path#to_relative()*
+lh#path#to_relative({pathname})~
+@param {pathname} Pathname to convert
+@return the simplified {pathname} in its relative form as it would be seen
+        from the current directory.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                                *lh#path#relative_to()*  {{{3
+lh#path#relative_to({from}, {to})~
+Returns the relative directory that indentifies {to} from {from} location.
+@param {from} origin directory
+@param {to}   destination directory
+@return the simplified pathname {to} in its relative form as it would be seen
+        from the {from} directory.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                                *lh#path#GlobAsList()*  {{{3
+lh#path#GlobAsList({pathslist}, {expr})  (*deprecated*)~
+                                                *lh#path#glob_as_list()*
+lh#path#glob_as_list({pathslist}, {expr})~
+@return |globpath()|'s result, but formatted as a list of matching pathnames.
+In case {expr} is a |List|, |globpath()| is applied on each expression in
+{expr}.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                                    *lh#path#find()*    {{{3
+lh#path#find({pathslist}, {regex})~
+@param[in] {pathslist} List of paths which can be received as a |List| or as a
+                       string made of coma separated paths.
+@return the path that matches the given {regex}
+
+e.g.: >
+ let expected_win = $HOME . '/vimfiles'
+ let expected_nix = $HOME . '/.vim'
+ let what =  lh#path#to_regex($HOME.'/').'\(vimfiles\|.vim\)'
+ let z = lh#path#find(&rtp,what)
+ if has('win16')||has('win32')||has('win64')
+   Assert z == expected_win
+ else
+   Assert z == expected_nix
+ endif
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                                *lh#path#to_regex()*    {{{3
+lh#path#to_regex({pathname})~
+Transforms the {pathname} to separate each node-name by the string '[/\\]' 
+
+The rationale behind this function is to build system independant regex
+pattern to use on pathnames as sometimes pathnames are built by appending
+'/stuff/like/this' without taking 'shellslash' into account.
+
+e.g.: >
+ echo lh#path#to_regex('/home/luc/').'\(vimfiles\|.vim\)'
+echoes >
+ [/\\]home[/\\]luc[/\\]\(vimfiles\|.vim\)
+
+
+------------------------------------------------------------------------------
+MENUS RELATED FUNCTIONS                               *lhvl#menu*       {{{2
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                             *lh#menu#def_toggle_item()*  {{{3
+lh#menu#def_toggle_item({Data})~
+@param[in,out] {Data} Definition of a |menu| item.
+
+This function defines a |menu| entry that will be associated to a
+|global-variable| whose values can be cycled and explored from the menu. This
+global variable can be seen as an enumerate whose value can be cyclically
+updated through a menu.
+
+{Data} is a |Dictionary| whose keys are:
+- "variable": name of the |global-variable| to bind to the menu entry
+  Mandatory.
+- "values": associated values of string or integers (|List|)
+  Mandatory.
+- "menu": describes where the menu entry must be placed (|Dictionary|)
+    - "priority": complete priority of the entry (see |sub-menu-priority|)
+    - "name": complete name of the entry -- ampersand (&) can be used to define
+      shortcut keys
+  Mandatory.
+- "idx_crt_value": index of the current value for the option (|expr-number|)
+  This is also an internal variable that will be automatically updated to
+  keep the index of the current value of the "variable" in "values".
+  Optional ; default value is 1, or the associated index of the initial value
+  of the variable (in "values") before the function call.
+- "texts": texts to display according to the variable value (|List|)
+  Optional, "values" will be used by default. This option is to be used to
+  distinguish the short encoded value, from the long self explanatory name.
+
+Warning:
+    If the variable is changed by hand without using the menu, then the menu
+    and the variable will be out of synch. Unless the command |lhvl-:Toggle|
+    is used to change the value of the options (and keep the menu
+    synchronized).
+
+Examples:
+   See tests/lh/test-toggle-menu.vim
+
+                                                            *lhvl-:Toggle*
+:Toggle {variable-name}~
+@param {variable-name} must be a |global-variable| name used as "variable" in
+the definition of a toggable menu item thanks to |lh#menu#def_toggle_item()|.
+
+This command supports autocompletion on the {variable-name}.
+
+Todo:
+    Propose a *lhvl-:Set{vaName}* command.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                                      *lh#menu#text()*  {{{3
+lh#menu#text({text})~
+@param[in] {text} Text to send to |:menu| commands
+@return a text to be used in menus where "\" and spaces have been escaped.
+
+This helper function transforms a regular text into a text that can be
+directly used with |:menu| commands.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                                      *lh#menu#make()*  {{{3
+option: *[gb]:want_buffermenu_or_global_disable*
+If Michael Geddes's |buffer-menu| plugin is installed, this option tells
+whether we want to take advantage of it to define menus or to ignore it.
+
+lh#menu#make({modes}, {menu-priority}, {menu-text}, {key-binding}, [<buffer>,]  {action})~
+Creates a menu entry and its associated mappings for several modes at once.
+
+@param[in] {modes} Vim modes the menus and maps will be provided for
+@param[in] {menu-priority} |sub-menu-priority| for the new menu entry
+@param[in] {menu-text}      Name of the new menu entry
+@param[in] {key-binding}    Sequence of keys to execute the associated action
+@param[in] "<buffer>"       If the string "<buffer>" is provided, then the 
+                            associated mapping will be a |map-<buffer>|, and
+                            the menu will be available to the current buffer
+                            only. See |[gb]:want_buffermenu_or_global_disable|
+                            When "<buffer>" is set, the call to lh#menu#make()
+                            must be done in the buffer-zone from a |ftplugin|,
+                            or from a |local_vimrc|.
+@param[in] {action}         Action to execute when {key-binding} is typed, or
+                            when the menu entry is selected.
+@todo support select ('s') and visual-not-select ('x') modes
+
+First example:~
+The following call will add the menu "LaTeX.Run LaTeX once <C-L><C-O>", with
+the priority (placement) 50.305, for the NORMAL, INSERT and COMMAND modes. The
+action associated first saves all the changed buffers and then invokes LaTeX.
+The same action is also binded to <C-L><C-O> for the same modes, with the
+nuance that the maps will be local to the buffer.
+>
+  call lh#menu#make("nic", '50.305', '&LaTeX.Run LaTeX &once', "<C-L><C-O>",
+          \ '<buffer>', ":wa<CR>:call TKMakeDVIfile(1)<CR>")
+
+Second example:~
+This example demonstrates an hidden, but useful, behavior: if the mode is the
+visual one, then the register v is filled with the text of the visual area.
+This text can then be used in the function called. Here, it will be proposed
+as a default name for the section to insert:
+>
+  function! TKinsertSec()
+    " ...
+    if (strlen(@v) != 0) && (visualmode() == 'v')
+      let SecName = input("name of ".SecType.": ", @v)
+    else
+      let SecName = input("name of ".SecType.": ")
+    endif
+    " ...
+  endfunction
+  
+  call lh#menu#make("vnic", '50.360.100', '&LaTeX.&Insert.&Section',
+          \ "<C-L><C-S>", '<buffer>', ":call TKinsertSec()<CR>")
+
+We have to be cautious to one little thing, there is a side effect: the visual
+mode vanishes when we enter the function. If you don't want this to happen,
+use the non-existant command: |:VCall|.
+
+Third example:~
+If it is known that a function will be called only under |VISUAL-mode|, and
+that we don't want of the previous behavior, we can explicitly invoke the
+function with |:VCall| -- command that doesn't actually exist. Check
+lh-tex/ftplugin/tex/tex-set.vim |s:MapMenu4Env| for such an example.
+
+Fourth thing: actually, lh#menu#make() is not restricted to commands. The
+action can be anything that could come at the right hand side of any |:map| or
+|:menu| action. But this time, you have to be cautious with the modes you
+dedicate your map to. I won't give any related example ; this is the
+underlying approach in |lh#menu#IVN_make()|. 
+
+
+                                                    *lh#menu#make()_modes*
+Implementation details:~
+The actual creation of the mappings is delegated to |lh#menu#map_all()|. 
+If the {action} to execute doesn't start with ':', it is left untransformed,
+otherwise it is adapted depending on each {mode}:
+- INSERT-mode: each recognized |:command| call is prepended with |i_CTRL-O| 
+- NORMAL-mode: the {action} is used as it is
+- VISUAL-mode: ":Vcall" is replaced by "\<cr>gV", otherwise the selection is
+  recorded into @v register, the {action} command is executed after a
+  |v_CTRL-C|, and eventually @v is cleared. 
+  The use is @v is deprecated, rely instead on |lh#menu#is_in_visual_mode()|
+  and on |lh#selection#visual()|.
+- COMMAND-mode: the {action} is prepended with |c_CTRL-C|.
+
+Examples:
+   See tests/lh/test-menu-map.vim
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                                  *lh#menu#IVN_make()*  {{{3
+Mappings & menus inserting text~
+lh#menu#IVN_make(<priority>, {text}, {key}, {IM-action}, {VM-action}, {NM-action} [, {nore-IM}, {nore-VM}, {nore-NM}])~
+
+lh#menu#IVN_MenuMake() accepts three different actions for the three modes:
+INSERT, VISUAL and NORMAL. The mappings defined will be relative to the
+current buffer -- this function is addressed to ftplugins writers. The last
+arguments specify whether the inner mappings and abbreviations embedded within
+the actions should be expanded or not ; i.e. are we defining
+«noremaps/noremenus» ?
+
+You will find very simple examples of what could be done at the end of
+menu-map.vim. Instead, I'll show here an extract of my TeX ftplugin: it
+defines complex functions that will help to define very simply the different
+mappings I use. You could find another variation on this theme in
+ftplugin/html/html_set.vim.
+
+>
+  :MapMenu 50.370.300 &LaTeX.&Fonts.&Emphasize ]em emph
+  call <SID>MapMenu4Env("50.370.200", '&LaTeX.&Environments.&itemize',
+        \ ']ei', 'itemize', '\item ')
+  
+
+The first command binds ]em to \emph{} for the three different modes. In
+INSERT mode, the cursor is positioned between the curly brackets, and a marker
+is added after the closing bracket -- cf. my bracketing system. In VISUAL
+mode, the curly brackets are added around the visual area. In NORMAL mode, the
+area is considered to be the current word.
+
+The second call binds for the three modes: ]ei to:
+>
+      \begin{itemize}
+          \item
+      \end{itemize}
+    
+The definition of the different functions and commands involved just follows.
+>
+  command -nargs=1 -buffer MapMenu :call <SID>MapMenu(<f-args>)
+  
+  function! s:MapMenu(code,text,binding, tex_cmd, ...)
+    let _2visual = (a:0 > 0) ? a:1 : "viw"
+    " If the tex_cmd starts with an alphabetic character, then suppose the
+    " command must begin with a '\'.
+    let texc = ((a:tex_cmd[0] =~ '\a') ? '\' : "") . a:tex_cmd
+    call lh#menu#IVN_make(a:code, a:text.'     --  ' . texc .'{}', a:binding,
+          \ texc.'{',
+          \ '<ESC>`>a}<ESC>`<i' . texc . '{<ESC>%l',
+          \ ( (_2visual=='0') ? "" : _2visual.a:binding),
+          \ 0, 1, 0)
+  endfunction
+
+  " a function and its map to close a "}", and that works whatever the
+  " activation states of the brackets and marking features are.
+  function! s:Close()
+    if strlen(maparg('{')) == 0                    | exe "normal a} \<esc>"
+    elseif exists("b:usemarks") && (b:usemarks==1) | exe "normal ˇjump! "
+    else                                           | exe "normal a "
+    endif
+  endfunction
+
+  imap <buffer> ˇclose! <c-o>:call <SID>Close()<cr>
+
+  function! s:MapMenu4Env(code,text,binding, tex_env, middle, ...)
+    let _2visual = (a:0 > 0) ? a:1 : "vip"
+    let b = "'" . '\begin{' . a:tex_env . '}' . "'"
+    let e = "'" . '\end{' . a:tex_env . '}' . "'"
+    call IVN_MenuMake(a:code, a:text, a:binding,
+          \ '\begin{'.a:tex_env.'ˇclose!<CR>'.a:middle.' <CR>\end{'.a:tex_env.'}<C-F><esc>ks',
+          \ ':VCall MapAroundVisualLines('.b. ',' .e.',1,1)',
+          \ _2visual.a:binding,
+          \ 0, 1, 0)
+  endfunction
+
+Examples:
+   See tests/lh/test-menu-map.vim
+
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                         *lh#menu#is_in_visual_mode()*  {{{3
+lh#menu#is_in_visual_mode()~
+@return a boolean that tells whether the {action} used in
+|lh#menu#is_in_visual_mode()| has been invoked from the VISUAL-mode.
+
+NB: this function deprecates the test on @v.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                                   *lh#menu#map_all()*  {{{3
+lh#menu#map_all({map-type}[, {map-args...}])~
+This function is a helper function that defines several mappings at once as
+|:amenu| would do.
+
+@param {map-type}     String of the form "[aincv]*(nore)?map" that tells the
+                      mode on which mappings should be defined, and whether
+                      the mappings shall be |:noremap|.
+@param {map-args...}  Rest of the parameters that defines the mapping
+
+
+The action to execute will be corrected depending on the current mode. See
+|lh#menu#make()_modes| for more details.
+
+
+------------------------------------------------------------------------------
+COMMANDS RELATED FUNCTIONS                            *lhvl#command*    {{{2
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                                *lh#command#new()*      {{{3
+Highly Experimental.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                       *lh#command#Fargs2String()*      {{{3
+lh#command#Fargs2String({aList})~
+@param[in,out] aList list of params from <f-args>
+@see tests/lh/test-Fargs2String.vim
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                            *lh#command#complete()*     {{{3
+lh#command#complete({argLead}, {cmdLine}, {cursorPos})~
+Under developpement
+
+
+------------------------------------------------------------------------------
+BUFFERS RELATED FUNCTIONS                             *lhvl#buffer*     {{{2
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                                *lh#buffer#list()*      {{{3
+lh#buffer#list()~
+@return The |List| of |buflisted| buffers.
+
+e.g.: >
+ echo lh#list#transform(lh#buffer#list(), [], "bufname")
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                                *lh#buffer#Find()*      {{{3
+lh#buffer#Find({filename})  (*deprecated*)~
+                                                *lh#buffer#find()*
+lh#buffer#find({filename})~
+Searchs for a window where the buffer is opened.
+
+@param {filename}
+@return The number of the first window found, in which {filename} is opened.
+
+If {filename} is opened in a window, jump to this window. Otherwise, return
+-1.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                                *lh#buffer#Jump()*      {{{3
+lh#buffer#Jump({filename}, {cmd})  (*deprecated*)~
+                                                *lh#buffer#jump()*
+lh#buffer#jump({filename}, {cmd})~
+Jumps to the window where the buffer is opened, or open the buffer in a new
+windows if none match.
+
+@param {filename}
+@param {cmd}
+@return Nothing.
+
+If {filename} is opened in a window, jump to this window. 
+Otherwise, execute {cmd} with {filename} as a parameter. Typical values for
+the command will be "sp" or "vsp". (see |:split|, |:vsplit|).
+
+N.B.: While it is not the rationale behind this function, other commands that
+does not open the buffer may be used in the {cmd} parameter.
+
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                                *lh#buffer#Scratch()*   {{{3
+lh#buffer#Scratch({bname},{where})  (*deprecated*)~
+                                      *scratch* *lh#buffer#scratch()*
+lh#buffer#scratch({bname},{where})~
+Split-opens a new scratch buffer.
+
+@param {bname} Name for the new scratch buffer
+@param {where} Where the new scratch buffer will be opened ('', or 'v')
+@post          The buffer has the following properties set: 
+                   'bt'=nofile, 'bh'=wipe, 'nobl', 'noswf', 'ro'
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                             *lhvl-dialog*      *lh#buffer#dialog#*     {{{3
+Functions for building interactive dialogs~
+Unlike other |lh-vim-lib| functions which can be used independently from each
+others, all the lh#buffer#dialog#*() functions constitute a coherent framework
+to define interactive dialogs.
+
+For the moment it only supports the selection of one or several items in a
+list.
+
+From a end-user point of view, a list of items is displayed in a (|scratch|)
+buffer. If enabled, the user can select (/tag) one or several items, and then
+validate its choice. He can always abort and quit the dialog. A few other
+features are also supported: a help message can be shown, the list may be
+colored, etc.
+
+
+The items displayed can be of any kind (function signatures, email addresses,
+suggested spellings, ...), as well as the validating action.  The
+help-header can be customized, as well as colours, other mappings, ...
+
+However the list displaying + selection aspect is almost hardcoded. 
+
+
+How it works~
+------------
+Scripts have to call the function                    *lh#buffer#dialog#new()*
+  lh#buffer#dialog#new(bname, title, where, support-tagging, action, choices)~
+with:
+- {bname} being the name the |scratch| buffer will receive.
+- {title} the title that appears at the first line of the scratch buffer.
+  I usually use it to display the name of the "client" script, its version,
+  and its purpose/what to do.
+- {where} are |:split| options (like "bot below") used to open the scratch
+  buffer.
+- {support-tagging} is a boolean (0/1) option to enable the multi-selection.
+- {action} is the name of the callback function (more
+  advanced calling mechanisms latter may be supported later with
+  |lhvl-functions|).
+- {choices} is the |List| of exact strings to display.
+
+The #new function builds and returns a |Dictionary|, it also opens and fills
+the scratch buffer, and put us within its context -- i.e. any |:map-<buffer>|
+or other buffer-related definitions will done in the new scratch buffer.
+
+Thus, if we want to add other mappings, and set a syntax highlighting for the
+new buffer, it is done at this point (see the *s:PostInit()* function in my
+"client" scripts like |lh-tags|).
+At this point, I also add all the high level information to the
+dictionary (for instance, the list of function signatures is nice, but
+it does not provides enough information (the corresponding file, the
+command to jump to the definition/declaration, the scope, ...)
+
+The dictionary returned is filled with the following information:
+- buffer ids,
+- where was the cursor at the time of the creation of the new scratch buffer,
+- name of the callback function.
+
+
+Regarding the callback function: *lhvl-dialog-select-callback*
+- It ca not be a |script-local| function, only global and autoload functions
+  are supported.
+- When called, we are still within the scratch buffer context.
+- It must accept a |List| of numbers as its first parameter: the index (+1) of
+  the items selected.
+- The number 0, when in the list, means "aborted". In that case, the
+  callback function is expected to call |lh#buffer#dialog#quit()| that will
+  terminate the scratch buffer (with |:quit|), and jump back to where we were
+  when #new was called, and display a little "Abort" message.
+- We can terminate the dialog with just :quit if we don't need to jump
+  back anywhere. For instance, lh-tags callback function first
+  terminates the dialog, then jumps to the file where the selected tag
+  comes from.
+
+- It's completely asynchronous: the callback function does not return anything
+  to anyone, but instead applies transformations in other places.
+  This aspect is very important. I don't see how this kind of feature can work
+  if not asynchronously in vim.
+
+How to customize it:
+- *lh#buffer#dialog#quit()* can be explicitly called, from a registered select
+  callback (|lhvl-dialog-select-callback|), in order to terminate the dialog.
+- *lh#buffer#dialog#add_help()* can be used to complete the help/usage message
+  in both its short and long form.
+- *lh#buffer#dialog#update()* can be called after the list of items has been
+  altered in order to refresh what is displayed. The rationale behind this
+  feature is to support sorting, filtering, items expansion, etc. See
+ |lh-tags| implementation for an example.
+- *lh#buffer#dialog#select()* can be used in new mappings in order to handle
+  differently the selected items.
+ |lh-tags| uses this function to map 'o' to the split-opening of the selected
+  items.
+  NB: the way this feature is supported may change in future releases.
+
+Limitations:
+This script is a little bit experimental (even if it the result of almost 10
+years of evolution), and it is a little bit cumbersome.
+- it is defined to support only one callback -- see the hacks in |lh-tags| to
+  workaround this limitation.
+- it is defined to display list of items, and to select one or several items
+  in the end.
+- and of course, it requires many other functions from |lh-vim-lib|, but
+  nothing else.
+
+------------------------------------------------------------------------------
+SYNTAX RELATED FUNCTIONS                              *lhvl#syntax*     {{{2
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                                *lh#syntax#NameAt()*    {{{3
+lh#syntax#NameAt({lnum},{col}[,{trans}])  (*deprecated*)~
+                                                *lh#syntax#name_at()*
+lh#syntax#name_at({lnum},{col}[,{trans}])~
+@param {lnum}  line of the character
+@param {col}   column of the character
+@param {trans} see |synID()|, default=0
+@return the syntax kind of the given character at {lnum}, {col}
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                               *lh#syntax#NameAtMark()* {{{3
+lh#syntax#NameAtMark({mark}[,{trans}])  (*deprecated*)~
+                                               *lh#syntax#name_at_mark()* {{{3
+lh#syntax#name_at_mark({mark}[,{trans}])~
+@param {mark}  position of the character
+@param {trans} see |synID()|, default=0
+@return the syntax kind of the character at the given |mark|.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+       *lh#syntax#Skip()* *lh#syntax#SkipAt()* *lh#syntax#SkipAtMark()* {{{3
+lh#syntax#Skip()  (*deprecated*)~
+lh#syntax#SkipAt({lnum},{col})  (*deprecated*)~
+lh#syntax#SkipAtMark({mark})  (*deprecated*)~
+       *lh#syntax#skip()* *lh#syntax#skip_at()* *lh#syntax#skip_at_mark()*
+lh#syntax#skip()~
+lh#syntax#skip_at({lnum},{col})~
+lh#syntax#skip_at_mark({mark})~
+
+Functions to be used with |searchpair()| functions in order to search for a
+pair of elements, without taking comments, strings, characters and doxygen
+(syntax) contexts into account while searching.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                               *lh#syntax#list_raw()*   {{{3
+lh#syntax#list_raw({name})~
+@param {group-name} 
+@return the result of "syn list {group-name}" as a string
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+                                                *lh#syntax#list()*      {{{3
+lh#syntax#list()~
+@param {group-name} 
+@return the result of "syn list {group-name}" as a list. 
+
+This function tries to interpret the result of the raw list of syntax
+elements. 
+
+
+------------------------------------------------------------------------------
+                                                                     }}}1
+==============================================================================
+ © Luc Hermitte, 2001-2010, <http://code.google.com/p/lh-vim/>       {{{1
+ $Id: lh-vim-lib.txt 246 2010-09-19 22:40:58Z luc.hermitte $
+ VIM: let b:VS_language = 'american' 
+ vim:ts=8:sw=4:tw=80:fo=tcq2:ft=help:
+ vim600:fdm=marker:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/lh-vim-lib/lh-vim-lib.README	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,17 @@
+			   ------------------
+			    lh-vim-lib 2.2.1
+			   ------------------
+
+lh-vim-lib is a library plugin for vim v7+. It is just a collection of
+functions that are meant to be used by script writers.
+
+Audience      : Vim script writers
+Requirements  : Vim 7.1
+Required by   : Just a few other plugins for the moment
+Author        : Luc Hermitte
+License       : GPL2
+More Help At  : http://code.google.com/p/lh-vim/wiki/lhVimLib
+Vim script#214: http://www.vim.org/scripts/script.php?script_id=214
+Repository    :
+	svn checkout http://lh-vim.googlecode.com/svn/vim-lib/trunk lh-vim-lib
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/lh-vim-lib/macros/menu-map.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,83 @@
+"===========================================================================
+" $Id: menu-map.vim 246 2010-09-19 22:40:58Z luc.hermitte $
+" File:		macros/menu-map.vim
+" Author:	Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
+" 		<URL:http://code.google.com/p/lh-vim/>
+"
+" Purpose:	Define functions to build mappings and menus at the same time
+"
+" Version:	2.2.1
+" Last Update:  $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $ (02nd Dec 2006)
+"
+" Last Changes: {{{
+" 	Version 2.0.0:
+" 		Moved to vim7, 
+" 		Functions moved to {rtp}/autoload/
+" 	Version 1.6.2: 
+" 		(*) Silent mappings and menus
+" 	Version 1.6. : 
+" 		(*) Uses has('gui_running') instead of has('gui') to check if
+" 		we can generate the menu.
+" 	Version 1.5. : 
+" 		(*) visual mappings launched from select-mode don't end with
+" 		    text still selected -- applied to :VCalls
+" 	Version 1.4. : 
+" 		(*) address obfuscated for spammers
+" 		(*) support the local option 
+" 		    b:want_buffermenu_or_global_disable if we don't want
+" 		    buffermenu to be used systematically.
+" 		    0 -> buffer menu not used
+" 		    1 -> buffer menu used
+" 		    2 -> the VimL developper will use a global disable.
+" 		    cf.:   tex-maps.vim:: s:SimpleMenu()
+" 		       and texmenus.vim
+" 	Version 1.3. :
+"		(*) add continuation lines support ; cf 'cpoptions'
+" 	Version 1.2. :
+" 		(*) Code folded.
+" 		(*) Take advantage of buffermenu.vim if present for local
+" 		    menus.
+" 		(*) If non gui is available, the menus won't be defined
+" 	Version 1.1. :
+"               (*) Bug corrected : 
+"                   vnore(map\|menu) does not imply v+n(map\|menu) any more
+" }}}
+"
+" Inspired By:	A function from Benji Fisher
+"
+" TODO:		(*) no menu if no gui.
+"
+"===========================================================================
+
+if exists("g:loaded_menu_map") | finish | endif
+let g:loaded_menu_map = 1  
+
+"" line continuation used here ??
+let s:cpo_save = &cpo
+set cpo&vim
+
+"=========================================================================
+" Commands {{{
+command! -nargs=+ -bang      MAP      map<bang> <args>
+command! -nargs=+           IMAP     imap       <args>
+command! -nargs=+           NMAP     nmap       <args>
+command! -nargs=+           CMAP     cmap       <args>
+command! -nargs=+           VMAP     vmap       <args>
+command! -nargs=+           AMAP
+      \       call lh#menu#map_all('amap', <f-args>)
+
+command! -nargs=+ -bang  NOREMAP  noremap<bang> <args>
+command! -nargs=+       INOREMAP inoremap       <args>
+command! -nargs=+       NNOREMAP nnoremap       <args>
+command! -nargs=+       CNOREMAP cnoremap       <args>
+command! -nargs=+       VNOREMAP vnoremap       <args>
+command! -nargs=+       ANOREMAP
+      \       call lh#menu#map_all('anoremap', <f-args>)
+" }}}
+
+" End !
+let &cpo = s:cpo_save
+finish
+
+"=========================================================================
+" vim600: set fdm=marker:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/lh-vim-lib/mkVba/mk-lh-vim-lib.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,53 @@
+"=============================================================================
+" $Id: mk-lh-vim-lib.vim 246 2010-09-19 22:40:58Z luc.hermitte $
+" File:		mk-lh-lib.vim
+" Author:	Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
+"		<URL:http://code.google.com/p/lh-vim/>
+" Version:	2.2.1
+let s:version = '2.2.1'
+" Created:	06th Nov 2007
+" Last Update:	$Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $
+"------------------------------------------------------------------------
+cd <sfile>:p:h
+try 
+  let save_rtp = &rtp
+  let &rtp = expand('<sfile>:p:h:h').','.&rtp
+  exe '22,$MkVimball! lh-vim-lib-'.s:version
+  set modifiable
+  set buftype=
+finally
+  let &rtp = save_rtp
+endtry
+finish
+autoload/lh/askvim.vim
+autoload/lh/buffer.vim
+autoload/lh/buffer/dialog.vim
+autoload/lh/command.vim
+autoload/lh/common.vim
+autoload/lh/encoding.vim
+autoload/lh/env.vim
+autoload/lh/event.vim
+autoload/lh/graph/tsort.vim
+autoload/lh/list.vim
+autoload/lh/menu.vim
+autoload/lh/option.vim
+autoload/lh/path.vim
+autoload/lh/position.vim
+autoload/lh/syntax.vim
+autoload/lh/visual.vim
+doc/lh-vim-lib.txt
+macros/menu-map.vim
+mkVba/mk-lh-vim-lib.vim
+plugin/let.vim
+plugin/lhvl.vim
+plugin/ui-functions.vim
+plugin/words_tools.vim
+tests/lh/function.vim
+tests/lh/list.vim
+tests/lh/path.vim
+tests/lh/test-Fargs2String.vim
+tests/lh/test-askmenu.vim
+tests/lh/test-command.vim
+tests/lh/test-menu-map.vim
+tests/lh/test-toggle-menu.vim
+tests/lh/topological-sort.vim
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/lh-vim-lib/plugin/let.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,54 @@
+"=============================================================================
+" $Id: let.vim 239 2010-06-01 00:48:43Z luc.hermitte $
+" File:         plugin/let.vim                                    {{{1
+" Author:       Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
+"		<URL:http://code.google.com/p/lh-vim/>
+" Version:      2.2.1
+" Created:      31st May 2010
+" Last Update:  $Date: 2010-05-31 20:48:43 -0400 (Mon, 31 May 2010) $
+"------------------------------------------------------------------------
+" Description:
+"       Defines a command :LetIfUndef that sets a variable if undefined
+" 
+"------------------------------------------------------------------------
+" Installation:
+"       Drop this file into {rtp}/plugin
+"       Requires Vim7+
+" History:      
+" 	v2.2.1: first version of this command into lh-vim-lib
+" TODO: 
+" }}}1
+"=============================================================================
+
+" Avoid global reinclusion {{{1
+let s:k_version = 221
+if &cp || (exists("g:loaded_let")
+      \ && (g:loaded_let >= s:k_version)
+      \ && !exists('g:force_reload_let'))
+  finish
+endif
+let g:loaded_let = s:k_version
+let s:cpo_save=&cpo
+set cpo&vim
+" Avoid global reinclusion }}}1
+"------------------------------------------------------------------------
+" Commands and Mappings {{{1
+command! -nargs=+ LetIfUndef call s:LetIfUndef(<f-args>)
+" Commands and Mappings }}}1
+"------------------------------------------------------------------------
+" Functions {{{1
+" Note: most functions are best placed into
+" autoload/«your-initials»/«let».vim
+" Keep here only the functions are are required when the plugin is loaded,
+" like functions that help building a vim-menu for this plugin.
+function! s:LetIfUndef(var, value)
+  if !exists(a:var)
+    let {a:var} = eval(a:value)
+  endif
+endfunction
+
+" Functions }}}1
+"------------------------------------------------------------------------
+let &cpo=s:cpo_save
+"=============================================================================
+" vim600: set fdm=marker:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/lh-vim-lib/plugin/lhvl.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,45 @@
+"=============================================================================
+" $Id: lhvl.vim 245 2010-09-19 22:40:10Z luc.hermitte $
+" File:		plugin/lhvl.vim                                   {{{1
+" Author:	Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
+"		<URL:http://code.google.com/p/lh-vim/>
+" Version:	2.2.1
+" Created:	27th Apr 2010
+" Last Update:	$Date: 2010-09-19 18:40:10 -0400 (Sun, 19 Sep 2010) $
+"------------------------------------------------------------------------
+" Description:	
+"       Non-function resources from lh-vim-lib
+" 
+"------------------------------------------------------------------------
+" Installation:	
+"       Drop the file into {rtp}/plugin
+" History:	
+"       v2.2.1  first version
+" TODO:		«missing features»
+" }}}1
+"=============================================================================
+
+" Avoid global reinclusion {{{1
+let s:k_version = 221
+if &cp || (exists("g:loaded_lhvl")
+      \ && (g:loaded_lhvl >= s:k_version)
+      \ && !exists('g:force_reload_lhvl'))
+  finish
+endif
+let g:loaded_lhvl = s:k_version
+let s:cpo_save=&cpo
+set cpo&vim
+" Avoid global reinclusion }}}1
+"------------------------------------------------------------------------
+" Commands and Mappings {{{1
+" Moved from lh-cpp
+command! PopSearch :call histdel('search', -1)| let @/=histget('search',-1)
+
+" Commands and Mappings }}}1
+"------------------------------------------------------------------------
+" Functions {{{1
+" Functions }}}1
+"------------------------------------------------------------------------
+let &cpo=s:cpo_save
+"=============================================================================
+" vim600: set fdm=marker:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/lh-vim-lib/plugin/ui-functions.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,480 @@
+"=============================================================================
+" File:         plugin/ui-functions.vim                                  {{{1
+" Author:       Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
+"               <URL:http://code.google.com/p/lh-vim/>
+" URL: http://hermitte.free.fr/vim/ressources/vimfiles/plugin/ui-functions.vim
+" 
+" Version:      2.2.1
+" Created:      18th nov 2002
+" Last Update:  28th Nov 2007
+"------------------------------------------------------------------------
+" Description:  Functions for the interaction with a User Interface.
+"               The UI can be graphical or textual.
+"               At first, this was designed to ease the syntax of
+"               mu-template's templates.
+"
+" Option:       {{{2
+"       {[bg]:ui_type} 
+"               = "g\%[ui]", 
+"               = "t\%[ext]" ; the call must not be |:silent|
+"               = "f\%[te]"
+" }}}2
+"------------------------------------------------------------------------
+" Installation: Drop this into one of your {rtp}/plugin/ directories.
+" History:      {{{2
+"    v0.01 Initial Version
+"    v0.02
+"       (*) Code "factorisations" 
+"       (*) Help on <F1> enhanced.
+"       (*) Small changes regarding the parameter accepted
+"       (*) Function SWITCH
+"    v0.03
+"       (*) Small bug fix with INPUT()
+"    v0.04
+"       (*) New function: WHICH()
+"    v0.05
+"       (*) In vim7e, inputdialog() returns a trailing '\n'. INPUT() strips the
+"           NL character.
+"    v0.06
+"       (*) :s/echoerr/throw/ => vim7 only
+"    v2.2.0
+"       (*) menu to switch the ui_type
+" 
+" TODO:         {{{2
+"       (*) Save the hl-User1..9 before using them
+"       (*) Possibility other than &statusline:
+"           echohl User1 |echon "bla"|echohl User2|echon "bli"|echohl None
+"       (*) Wraps too long choices-line (length > term-width)
+"       (*) Add to the documentation: "don't use CTRL-C to abort !!"
+"       (*) Look if I need to support 'wildmode'
+"       (*) 3rd mode: return string for FTE
+"       (*) 4th mode: interaction in a scratch buffer
+"
+" }}}1
+"=============================================================================
+" Avoid reinclusion {{{1
+" 
+if exists("g:loaded_ui_functions") && !exists('g:force_reload_ui_functions')
+  finish 
+endif
+let g:loaded_ui_functions = 1
+let s:cpo_save=&cpo
+set cpo&vim
+" }}}1
+"------------------------------------------------------------------------
+" External functions {{{1
+" Function: IF(var, then, else) {{{2
+function! IF(var,then, else)
+  let o = s:Opt_type() " {{{3
+  if     o =~ 'g\%[ui]\|t\%[ext]' " {{{4
+    return a:var ? a:then : a:else
+  elseif o =~ 'f\%[te]'           " {{{4
+    return s:if_fte(a:var, a:then, a:else)
+  else                    " {{{4
+    throw "UI-Fns::IF(): Unkonwn user-interface style (".o.")"
+  endif
+  " }}}3
+endfunction
+
+" Function: SWITCH(var, case, action [, case, action] [default_action]) {{{2
+function! SWITCH(var, ...)
+  let o = s:Opt_type() " {{{3
+  if     o =~ 'g\%[ui]\|t\%[ext]' " {{{4
+    let explicit_def = ((a:0 % 2) == 1)
+    let default      = explicit_def ? a:{a:0} : ''
+    let i = a:0 - 1 - explicit_def
+    while i > 0
+      if a:var == a:{i}
+        return a:{i+1}
+      endif
+      let i = i - 2
+    endwhile
+    return default
+  elseif o =~ 'f\%[te]'           " {{{4
+    return s:if_fte(a:var, a:then, a:else)
+  else                    " {{{4
+    throw "UI-Fns::SWITCH(): Unkonwn user-interface style (".o.")"
+  endif
+  " }}}3
+endfunction
+
+" Function: CONFIRM(text [, choices [, default [, type]]]) {{{2
+function! CONFIRM(text, ...)
+  " 1- Check parameters {{{3
+  if a:0 > 4 " {{{4
+    throw "UI-Fns::CONFIRM(): too many parameters"
+    return 0
+  endif
+  " build the parameters string {{{4
+  let i = 1
+  while i <= a:0
+    if i == 1 | let params = 'a:{1}'
+    else      | let params = params. ',a:{'.i.'}'
+    endif
+    let i = i + 1
+  endwhile
+  " 2- Choose the correct way to execute according to the option {{{3
+  let o = s:Opt_type()
+  if     o =~ 'g\%[ui]'  " {{{4
+    exe 'return confirm(a:text,'.params.')'
+  elseif o =~ 't\%[ext]' " {{{4
+    if !has('gui_running') && has('dialog_con')
+      exe 'return confirm(a:text,'.params.')'
+    else
+      exe 'return s:confirm_text("none", a:text,'.params.')'
+    endif
+  elseif o =~ 'f\%[te]'  " {{{4
+      exe 'return s:confirm_fte(a:text,'.params.')'
+  else               " {{{4
+    throw "UI-Fns::CONFIRM(): Unkonwn user-interface style (".o.")"
+  endif
+  " }}}3
+endfunction
+
+" Function: INPUT(prompt [, default ]) {{{2
+function! INPUT(prompt, ...)
+  " 1- Check parameters {{{3
+  if a:0 > 4 " {{{4
+    throw "UI-Fns::INPUT(): too many parameters"
+    return 0
+  endif
+  " build the parameters string {{{4
+  let i = 1 | let params = ''
+  while i <= a:0
+    if i == 1 | let params = 'a:{1}'
+    else      | let params = params. ',a:{'.i.'}'
+    endif
+    let i = i + 1
+  endwhile
+  " 2- Choose the correct way to execute according to the option {{{3
+  let o = s:Opt_type()
+  if     o =~ 'g\%[ui]'  " {{{4
+    exe 'return matchstr(inputdialog(a:prompt,'.params.'), ".\\{-}\\ze\\n\\=$")'
+  elseif o =~ 't\%[ext]' " {{{4
+    exe 'return input(a:prompt,'.params.')'
+  elseif o =~ 'f\%[te]'  " {{{4
+      exe 'return s:input_fte(a:prompt,'.params.')'
+  else               " {{{4
+    throw "UI-Fns::INPUT(): Unkonwn user-interface style (".o.")"
+  endif
+  " }}}3
+endfunction
+
+" Function: COMBO(prompt, choice [, ... ]) {{{2
+function! COMBO(prompt, ...)
+  " 1- Check parameters {{{3
+  if a:0 > 4 " {{{4
+    throw "UI-Fns::COMBO(): too many parameters"
+    return 0
+  endif
+  " build the parameters string {{{4
+  let i = 1
+  while i <= a:0
+    if i == 1 | let params = 'a:{1}'
+    else      | let params = params. ',a:{'.i.'}'
+    endif
+    let i = i + 1
+  endwhile
+  " 2- Choose the correct way to execute according to the option {{{3
+  let o = s:Opt_type()
+  if     o =~ 'g\%[ui]'  " {{{4
+    exe 'return confirm(a:prompt,'.params.')'
+  elseif o =~ 't\%[ext]' " {{{4
+    exe 'return s:confirm_text("combo", a:prompt,'.params.')'
+  elseif o =~ 'f\%[te]'  " {{{4
+    exe 'return s:combo_fte(a:prompt,'.params.')'
+  else               " {{{4
+    throw "UI-Fns::COMBO(): Unkonwn user-interface style (".o.")"
+  endif
+  " }}}3
+endfunction
+
+" Function: WHICH(function, prompt, choice [, ... ]) {{{2
+function! WHICH(fn, prompt, ...)
+  " 1- Check parameters {{{3
+  " build the parameters string {{{4
+  let i = 1
+  while i <= a:0
+    if i == 1 | let params = 'a:{1}'
+    else      | let params = params. ',a:{'.i.'}'
+    endif
+    let i = i + 1
+  endwhile
+  " 2- Execute the function {{{3
+  exe 'let which = '.a:fn.'(a:prompt,'.params.')'
+  if     0 >= which | return ''
+  elseif 1 == which
+    return substitute(matchstr(a:{1}, '^.\{-}\ze\%(\n\|$\)'), '&', '', 'g')
+  else
+    return substitute(
+          \ matchstr(a:{1}, '^\%(.\{-}\n\)\{'.(which-1).'}\zs.\{-}\ze\%(\n\|$\)')
+          \ , '&', '', 'g')
+  endif
+  " }}}3
+endfunction
+
+" Function: CHECK(prompt, choice [, ... ]) {{{2
+function! CHECK(prompt, ...)
+  " 1- Check parameters {{{3
+  if a:0 > 4 " {{{4
+    throw "UI-Fns::CHECK(): too many parameters"
+    return 0
+  endif
+  " build the parameters string {{{4
+  let i = 1
+  while i <= a:0
+    if i == 1 | let params = 'a:{1}'
+    else      | let params = params. ',a:{'.i.'}'
+    endif
+    let i = i + 1
+  endwhile
+  " 2- Choose the correct way to execute according to the option {{{3
+  let o = s:Opt_type()
+  if     o =~ 'g\%[ui]'  " {{{4
+    exe 'return s:confirm_text("check", a:prompt,'.params.')'
+  elseif o =~ 't\%[ext]' " {{{4
+    exe 'return s:confirm_text("check", a:prompt,'.params.')'
+  elseif o =~ 'f\%[te]'  " {{{4
+      exe 'return s:check_fte(a:prompt,'.params.')'
+  else               " {{{4
+    throw "UI-Fns::CHECK(): Unkonwn user-interface style (".o.")"
+  endif
+  " }}}3
+endfunction
+
+" }}}1
+"------------------------------------------------------------------------
+" Options setting {{{1
+let s:OptionData = {
+      \ "variable": "ui_type",
+      \ "idx_crt_value": 1,
+      \ "values": ['gui', 'text', 'fte'],
+      \ "menu": { "priority": '500.2700', "name": '&Plugin.&LH.&UI type'}
+      \}
+
+call lh#menu#def_toggle_item(s:OptionData)
+
+" }}}1
+"------------------------------------------------------------------------
+" Internal functions {{{1
+function! s:Option(name, default) " {{{2
+  if     exists('b:ui_'.a:name) | return b:ui_{a:name}
+  elseif exists('g:ui_'.a:name) | return g:ui_{a:name}
+  else                          | return a:default
+  endif
+endfunction
+
+
+function! s:Opt_type() " {{{2
+  return s:Option('type', 'gui')
+endfunction
+
+"
+" Function: s:status_line(current, hl [, choices] ) {{{2
+"     a:current: current item
+"     a:hl     : Generic, Warning, Error
+function! s:status_line(current, hl, ...)
+  " Highlightning {{{3
+  if     a:hl == "Generic"  | let hl = '%1*'
+  elseif a:hl == "Warning"  | let hl = '%2*'
+  elseif a:hl == "Error"    | let hl = '%3*'
+  elseif a:hl == "Info"     | let hl = '%4*'
+  elseif a:hl == "Question" | let hl = '%5*'
+  else                      | let hl = '%1*'
+  endif
+  
+  " Build the string {{{3
+  let sl_choices = '' | let i = 1
+  while i <= a:0
+    if i == a:current
+      let sl_choices = sl_choices . ' '. hl . 
+            \ substitute(a:{i}, '&\(.\)', '%6*\1'.hl, '') . '%* '
+    else
+      let sl_choices = sl_choices . ' ' . 
+            \ substitute(a:{i}, '&\(.\)', '%6*\1%*', '') . ' '
+    endif
+    let i = i + 1
+  endwhile
+  " }}}3
+  return sl_choices
+endfunction
+
+
+" Function: s:confirm_text(box, text [, choices [, default [, type]]]) {{{2
+function! s:confirm_text(box, text, ...)
+  let help = "/<esc>/<s-tab>/<tab>/<left>/<right>/<cr>/<F1>"
+  " 1- Retrieve the parameters       {{{3
+  let choices = ((a:0>=1) ? a:1 : '&Ok')
+  let default = ((a:0>=2) ? a:2 : (('check' == a:box) ? 0 : 1))
+  let type    = ((a:0>=3) ? a:3 : 'Generic')
+  if     'none'  == a:box | let prefix = ''
+  elseif 'combo' == a:box | let prefix = '( )_'
+  elseif 'check' == a:box | let prefix = '[ ]_'
+    let help = '/ '.help
+  else                    | let prefix = ''
+  endif
+
+
+  " 2- Retrieve the proposed choices {{{3
+  " Prepare the hot keys
+  let i = 0
+  while i != 26
+    let hotkey_{nr2char(i+65)} = 0
+    let i += 1
+  endwhile
+  let hotkeys = '' | let help_k = '/'
+  " Parse the choices
+  let i = 0
+  while choices != ""
+    let i = i + 1
+    let item    = matchstr(choices, "^.\\{-}\\ze\\(\n\\|$\\)")
+    let choices = matchstr(choices, "\n\\zs.*$")
+    " exe 'anoremenu ]'.a:text.'.'.item.' :let s:choice ='.i.'<cr>'
+    if ('check' == a:box) && (strlen(default)>=i) && (1 == default[i-1])
+      " let choice_{i} = '[X]' . substitute(item, '&', '', '')
+      let choice_{i} = '[X]_' . item
+    else
+      " let choice_{i} = prefix . substitute(item, '&', '', '')
+      let choice_{i} = prefix . item
+    endif
+    if i == 1
+      let list_choices = 'choice_{1}'
+    else
+      let list_choices = list_choices . ',choice_{'.i.'}'
+    endif
+    " Update the hotkey.
+    let key = toupper(matchstr(choice_{i}, '&\zs.\ze'))
+    let hotkey_{key} = i
+    let hotkeys = hotkeys . tolower(key) . toupper(key)
+    let help_k = help_k . tolower(key)
+  endwhile
+  let nb_choices = i
+  if default > nb_choices | let default = nb_choices | endif
+
+  " 3- Run an interactive text menu  {{{3
+  " Note: emenu can not be used through ":exe" {{{4
+  " let wcm = &wcm
+  " set wcm=<tab>
+  " exe ':emenu ]'.a:text.'.'."<tab>"
+  " let &wcm = wcm
+  " 3.1- Preparations for the statusline {{{4
+  " save the statusline
+  let sl = &l:statusline
+  " Color schemes for selected item {{{5
+  :hi User1 term=inverse,bold cterm=inverse,bold ctermfg=Yellow 
+        \ guifg=Black guibg=Yellow
+  :hi User2 term=inverse,bold cterm=inverse,bold ctermfg=LightRed
+        \ guifg=Black guibg=LightRed
+  :hi User3 term=inverse,bold cterm=inverse,bold ctermfg=Red 
+        \ guifg=Black guibg=Red
+  :hi User4 term=inverse,bold cterm=inverse,bold ctermfg=Cyan
+        \ guifg=Black guibg=Cyan
+  :hi User5 term=inverse,bold cterm=inverse,bold ctermfg=LightYellow
+        \ guifg=Black guibg=LightYellow
+  :hi User6 term=inverse,bold cterm=inverse,bold ctermfg=LightGray
+        \ guifg=DarkRed guibg=LightGray
+  " }}}5
+
+  " 3.2- Interactive loop                {{{4
+  let help =  "\r-- Keys available (".help_k.help.")"
+  " item selected at the start
+  let i = ('check' != a:box) ? default : 1
+  let direction = 0 | let toggle = 0
+  while 1
+    if 'combo' == a:box
+      let choice_{i} = substitute(choice_{i}, '^( )', '(*)', '')
+    endif
+    " Colored statusline
+    " Note: unfortunately the 'statusline' is a global option, {{{
+    " not a local one. I the hope that may change, as it does not provokes any
+    " error, I use '&l:statusline'. }}}
+    exe 'let &l:statusline=s:status_line(i, type,'. list_choices .')'
+    if has(':redrawstatus')
+      redrawstatus!
+    else
+      redraw!
+    endif
+    " Echo the current selection
+    echo "\r". a:text.' '.substitute(choice_{i}, '&', '', '')
+    " Wait the user to hit a key
+    let key=getchar()
+    let complType=nr2char(key)
+    " If the key hit matched awaited keys ...
+    if -1 != stridx(" \<tab>\<esc>\<enter>".hotkeys,complType) ||
+          \ (key =~ "\<F1>\\|\<right>\\|\<left>\\|\<s-tab>")
+      if key           == "\<F1>"                       " Help      {{{5
+        redraw!
+        echohl StatusLineNC
+        echo help
+        echohl None
+        let key=getchar()
+        let complType=nr2char(key)
+      endif
+      " TODO: support CTRL-D
+      if     complType == "\<enter>"                    " Validate  {{{5
+        break
+      elseif complType == " "                           " check box {{{5
+        let toggle = 1
+      elseif complType == "\<esc>"                      " Abort     {{{5
+        let i = -1 | break
+      elseif complType == "\<tab>" || key == "\<right>" " Next      {{{5
+        let direction = 1
+      elseif key =~ "\<left>\\|\<s-tab>"                " Previous  {{{5
+        let direction = -1
+      elseif -1 != stridx(hotkeys, complType )          " Hotkeys     {{{5
+        if '' == complType  | continue | endif
+        let direction = hotkey_{toupper(complType)} - i
+        let toggle = 1
+      " else
+      endif
+      " }}}5
+    endif
+    if direction != 0 " {{{5
+      if 'combo' == a:box
+        let choice_{i} = substitute(choice_{i}, '^(\*)', '( )', '')
+      endif
+      let i = i + direction
+      if     i > nb_choices | let i = 1 
+      elseif i == 0         | let i = nb_choices
+      endif
+      let direction = 0
+    endif
+    if toggle == 1    " {{{5
+      if 'check' == a:box
+        let choice_{i} = ((choice_{i}[1] == ' ')? '[X]' : '[ ]') 
+              \ . strpart(choice_{i}, 3)
+      endif
+      let toggle = 0
+    endif
+  endwhile " }}}4
+  " 4- Terminate                     {{{3
+  " Clear screen
+  redraw!
+
+  " Restore statusline
+  let &l:statusline=sl
+  " Return
+  if (i == -1) || ('check' != a:box)
+    return i
+  else
+    let r = '' | let i = 1
+    while i <= nb_choices
+      let r = r . ((choice_{i}[1] == 'X') ? '1' : '0')
+      let i = i + 1
+    endwhile
+    return r
+  endif
+endfunction
+" }}}1
+"------------------------------------------------------------------------
+" Functions that insert fte statements {{{1
+" Function: s:if_fte(var, then, else) {{{2
+" Function: s:confirm_fte(text, [, choices [, default [, type]]]) {{{2
+" Function: s:input_fte(prompt [, default]) {{{2
+" Function: s:combo_fte(prompt, choice [, ...]) {{{2
+" Function: s:check_fte(prompt, choice [, ...]) {{{2
+" }}}1
+"------------------------------------------------------------------------
+let &cpo=s:cpo_save
+"=============================================================================
+" vim600: set fdm=marker:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/lh-vim-lib/plugin/words_tools.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,104 @@
+" File:		plugin/words_tools.vim
+" Author:	Luc Hermitte <hermitte {at} free {dot} fr>
+" 		<URL:http://code.google.com/p/lh-vim/>
+" URL: http://hermitte.free.fr/vim/ressources/vim_dollar/plugin/words_tools.vim
+"
+" Last Update:	14th nov 2002
+" Purpose:	Define functions better than expand("<cword>")
+"
+" Note:		They are expected to be used in insert mode (thanks to <c-r>
+"               or <c-o>)
+"
+"===========================================================================
+
+" Return the current keyword, uses spaces to delimitate {{{1
+function! GetNearestKeyword()
+  let c = col ('.')-1
+  let ll = getline('.')
+  let ll1 = strpart(ll,0,c)
+  let ll1 = matchstr(ll1,'\k*$')
+  let ll2 = strpart(ll,c,strlen(ll)-c+1)
+  let ll2 = matchstr(ll2,'^\k*')
+  " let ll2 = strpart(ll2,0,match(ll2,'$\|\s'))
+  return ll1.ll2
+endfunction
+
+" Return the current word, uses spaces to delimitate {{{1
+function! GetNearestWord()
+  let c = col ('.')-1
+  let l = line('.')
+  let ll = getline(l)
+  let ll1 = strpart(ll,0,c)
+  let ll1 = matchstr(ll1,'\S*$')
+  let ll2 = strpart(ll,c,strlen(ll)-c+1)
+  let ll2 = strpart(ll2,0,match(ll2,'$\|\s'))
+  ""echo ll1.ll2
+  return ll1.ll2
+endfunction
+
+" Return the word before the cursor, uses spaces to delimitate {{{1
+" Rem : <cword> is the word under or after the cursor
+function! GetCurrentWord()
+  let c = col ('.')-1
+  let l = line('.')
+  let ll = getline(l)
+  let ll1 = strpart(ll,0,c)
+  let ll1 = matchstr(ll1,'\S*$')
+  if strlen(ll1) == 0
+    return ll1
+  else
+    let ll2 = strpart(ll,c,strlen(ll)-c+1)
+    let ll2 = strpart(ll2,0,match(ll2,'$\|\s'))
+    return ll1.ll2
+  endif
+endfunction
+
+" Return the keyword before the cursor, uses \k to delimitate {{{1
+" Rem : <cword> is the word under or after the cursor
+function! GetCurrentKeyword()
+  let c = col ('.')-1
+  let l = line('.')
+  let ll = getline(l)
+  let ll1 = strpart(ll,0,c)
+  let ll1 = matchstr(ll1,'\k*$')
+  if strlen(ll1) == 0
+    return ll1
+  else
+    let ll2 = strpart(ll,c,strlen(ll)-c+1)
+    let ll2 = matchstr(ll2,'^\k*')
+    " let ll2 = strpart(ll2,0,match(ll2,'$\|\s'))
+    return ll1.ll2
+  endif
+endfunction
+
+" Extract the word before the cursor,  {{{1
+" use keyword definitions, skip latter spaces (see "bla word_accepted ")
+function! GetPreviousWord()
+  let lig = getline(line('.'))
+  let lig = strpart(lig,0,col('.')-1)
+  return matchstr(lig, '\<\k*\>\s*$')
+endfunction
+
+" GetLikeCTRL_W() retrieves the characters that i_CTRL-W deletes. {{{1
+" Initial need by Hari Krishna Dara <hari_vim@yahoo.com>
+" Last ver:
+" Pb: "if strlen(w) ==  " --> ") ==  " instead of just "==  ".
+" There still exists a bug regarding the last char of a line. VIM bug ?
+function! GetLikeCTRL_W()
+  let lig = getline(line('.'))
+  let lig = strpart(lig,0,col('.')-1)
+  " treat ending spaces apart.
+  let s = matchstr(lig, '\s*$')
+  let lig = strpart(lig, 0, strlen(lig)-strlen(s))
+  " First case : last characters belong to a "word"
+  let w = matchstr(lig, '\<\k\+\>$')
+  if strlen(w) == 0
+    " otherwise, they belong to a "non word" (without any space)
+    let w = substitute(lig, '.*\(\k\|\s\)', '', 'g')
+  endif
+  return w . s
+endfunction
+
+" }}}1
+"========================================================================
+" vim60: set fdm=marker:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/lh-vim-lib/tests/lh/function.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,284 @@
+"=============================================================================
+" $Id: function.vim 246 2010-09-19 22:40:58Z luc.hermitte $
+" File:		tests/lh/function.vim                                   {{{1
+" Author:	Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
+"		<URL:http://code.google.com/p/lh-vim/>
+" Version:	2.2.1
+" Created:	03rd Nov 2008
+" Last Update:	$Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $
+"------------------------------------------------------------------------
+" Description:	
+" 	Tests for autoload/lh/function.vim
+" 
+"------------------------------------------------------------------------
+" Installation:	«install details»
+" History:	«history»
+" TODO:		«missing features»
+" }}}1
+"=============================================================================
+
+UTSuite [lh-vim-lib] Testing lh#function plugin
+
+runtime autoload/lh/function.vim
+
+let s:cpo_save=&cpo
+set cpo&vim
+"------------------------------------------------------------------------
+function! Test(...)
+  let nb = len(a:000)
+  " echo "test(".nb.':' .join(a:000, ' -- ')')'
+  let i =0
+  while i!= len(a:000)
+    echo "Test: type(".i.")=".type(a:000[i]).' --> '. string(a:000[i])
+    let i += 1
+  endwhile
+endfunction
+
+function! Print(...)
+  let res = lh#list#accumulate([1,2,'foo'], 'string', 'join(v:1_, " ## ")')
+  return res
+endfunction
+
+function! Id(...)
+  return copy(a:000)
+endfunction
+
+function! s:TestId()
+  let r = Id(1, 'string', [0], [[1]], {'ffo':42}, function('exists'), 1.2)
+  Assert! len(r) == 7
+  Assert! should#be#number (r[0])
+  Assert! should#be#string (r[1])
+  Assert! should#be#list   (r[2])
+  Assert! should#be#list   (r[3])
+  Assert! should#be#dict   (r[4])
+  Assert! should#be#funcref(r[5])
+  Assert! should#be#float  (r[6])
+  Assert r[0] == 1
+  Assert r[1] == 'string'
+  Assert r[2] == [0]
+  Assert r[3] == [[1]]
+  Assert r[4].ffo == 42
+  Assert r[5] == function('exists')
+  Assert r[6] == 1.2
+endfunction
+
+function! s:Test_bind()
+  " lh#function#bind + lh#function#execute
+  let rev4 = lh#function#bind(function('Id'), 'v:4_', 42, 'v:3_', 'v:2_', 'v:1_')
+  let r = lh#function#execute(rev4, 1,'two','three', [4,5])
+  Assert! len(r) == 5
+  Assert! should#be#list   (r[0])
+  Assert! should#be#number (r[1])
+  Assert! should#be#string (r[2])
+  Assert! should#be#string (r[3])
+  Assert! should#be#number (r[4])
+
+  Assert r[0] == [4,5]
+  Assert r[1] == 42
+  Assert r[2] == 'three'
+  Assert r[3] == 'two'
+  Assert r[4] == 1
+endfunction
+
+function! s:Test_bind_compound_vars()
+  " lh#function#bind + lh#function#execute
+  let rev4 = lh#function#bind(function('Id'), 'v:4_', 'v:1_ . v:2_', 'v:3_', 'v:2_', 'v:1_')
+  let r = lh#function#execute(rev4, 1,'two','three', [4,5])
+  Assert! len(r) == 5
+  Assert! should#be#list   (r[0])
+  Assert! should#be#string (r[1])
+  Assert! should#be#string (r[2])
+  Assert! should#be#string (r[3])
+  Assert! should#be#number (r[4])
+
+  Assert r[0] == [4,5]
+  Assert r[1] == '1two'
+  Assert r[2] == 'three'
+  Assert r[3] == 'two'
+  Assert r[4] == 1
+endfunction
+
+
+function! s:Test_execute_func_string_name()
+  " function name as string
+  let r = lh#function#execute('Id', 1,'two',3)
+  Assert! len(r) == 3
+  Assert! should#be#number (r[0])
+  Assert! should#be#string (r[1])
+  Assert! should#be#number (r[2])
+  Assert r[0] == 1
+  Assert r[1] == 'two'
+  Assert r[2] == 3
+endfunction
+
+function! s:Test_execute_string_expr()
+  " exp as binded-string
+  let r = lh#function#execute('Id(12,len(v:2_).v:2_, 42, v:3_, v:1_)', 1,'two',3)
+  Assert! len(r) == 5
+  Assert! should#be#number (r[0])
+  Assert! should#be#string (r[1])
+  Assert! should#be#number (r[2])
+  Assert! should#be#number (r[3])
+  Assert! should#be#number (r[4])
+  Assert r[0] == 12
+  Assert r[1] == len('two').'two'
+  Assert r[2] == 42
+  Assert r[3] == 3
+  Assert r[4] == 1
+endfunction
+
+function! s:Test_execute_func()
+  " calling a function() + bind
+  let r = lh#function#execute(function('Id'), 1,'two','v:1_',['a',42])
+  Assert! len(r) == 4
+  Assert! should#be#number (r[0])
+  Assert! should#be#string (r[1])
+  Assert! should#be#string (r[2])
+  Assert! should#be#list   (r[3])
+  Assert r[0] == 1
+  Assert r[1] == 'two'
+  Assert r[2] == 'v:1_'
+  Assert r[3] == ['a', 42]
+endfunction
+"------------------------------------------------------------------------
+function! s:Test_bind_func_string_name_AND_execute()
+  " function name as string
+  let rev3 = lh#function#bind('Id', 'v:3_', 12, 'v:2_', 'v:1_')
+  let r = lh#function#execute(rev3, 1,'two',3)
+
+  Assert! len(r) == 4
+  Assert! should#be#number (r[0])
+  Assert! should#be#number (r[1])
+  Assert! should#be#string (r[2])
+  Assert! should#be#number (r[3])
+  Assert r[0] == 3
+  Assert r[1] == 12
+  Assert r[2] == 'two'
+  Assert r[3] == 1
+endfunction
+
+function! s:Test_bind_string_expr_AND_execute()
+" expressions as string
+  let rev3 = lh#function#bind('Id(12,len(v:2_).v:2_, 42, v:3_, v:1_)')
+  let r = lh#function#execute(rev3, 1,'two',3)
+  Assert! len(r) == 5
+  Assert! should#be#number (r[0])
+  Assert! should#be#string (r[1])
+  Assert! should#be#number (r[2])
+  Assert! should#be#number (r[3])
+  Assert! should#be#number (r[4])
+  Assert r[0] == 12
+  Assert r[1] == len('two').'two'
+  Assert r[2] == 42
+  Assert r[3] == 3
+  Assert r[4] == 1
+endfunction
+
+function! s:Test_double_bind_func_name()
+  let f1 = lh#function#bind('Id', 1, 2, 'v:1_', 4, 'v:2_')
+  " Comment "f1=".string(f1)
+  let r = lh#function#execute(f1, 3, 5)
+  Assert! len(r) == 5
+  let i = 0
+  while i != len(r)
+    Assert! should#be#number (r[i])
+    Assert r[i] == i+1
+    let i += 1
+  endwhile
+
+  " f2
+  let f2 = lh#function#bind(f1, 'v:1_', 5)
+  " Comment "f2=f1(v:1_, 5)=".string(f2)
+  let r = lh#function#execute(f2, 3)
+  Assert! len(r) == 5
+  let i = 0
+  while i != len(r)
+    Assert! should#be#number (r[i])
+    " echo "?? ".(r[i])."==".(i+1)
+    Assert r[i] == i+1
+    let i += 1
+  endwhile
+endfunction
+
+function! s:Test_double_bind_func()
+  let f1 = lh#function#bind(function('Id'), 1, 2, 'v:1_', 4, 'v:2_')
+  " Comment "f1=".string(f1)
+  let r = lh#function#execute(f1, 3, 5)
+  Assert! len(r) == 5
+  let i = 0
+  while i != len(r)
+    Assert! should#be#number (r[i])
+    Assert r[i] == i+1
+    let i += 1
+  endwhile
+
+  " f2
+  let f2 = lh#function#bind(f1, 'v:1_', 5)
+  " Comment "f2=f1(v:1_, 5)=".string(f2)
+  let r = lh#function#execute(f2, 3)
+  Assert! len(r) == 5
+  let i = 0
+  while i != len(r)
+    Assert! should#be#number (r[i])
+    Assert r[i] == i+1
+    let i += 1
+  endwhile
+endfunction
+
+function! s:Test_double_bind_func_cplx()
+  let s:bar = "bar"
+  let f1 = lh#function#bind(function('Id'), 1, 2, 'v:1_', 4, 'v:2_', 'v:3_', 'v:4_', 'v:5_', 'v:6_', 'v:7_')
+  " Comment "f1=".string(f1)
+  let f2 = lh#function#bind(f1, 'v:1_', 5, 'foo', s:bar, 'len(s:bar.v:1_)+v:1_', [1,2], '[v:1_, v:2_]')
+  " Comment "f2=f1(v:1_, 5)=".string(f2)
+
+  let r = lh#function#execute(f2, 42, "foo")
+  Assert! 0 && "not ready"
+  Comment "2bcpl# ".string(r)
+endfunction
+
+function! s:Test_double_bind_expr()
+  let f1 = lh#function#bind('Id(1, 2, v:1_, v:3_, v:2_)')
+  Comment "2be# f1=".string(f1)
+  let r = lh#function#execute(f1, 3, 5, 4)
+  Comment "2be# ".string(r)
+  Assert! len(r) == 5
+  let i = 0
+  while i != len(r)
+    Assert! should#be#number (r[i])
+    Assert r[i] == i+1
+    let i += 1
+  endwhile
+
+  " f2
+  let f2 = lh#function#bind(f1, 'v:1_', '"foo"', [])
+  Comment "2be# f2=f1(v:1_, 5)=".string(f2)
+  let r = lh#function#execute(f2, 3)
+  Comment "2be# ".string(r)
+  Assert! len(r) == 5
+  let i = 0
+  while i != len(r)-2
+    Assert! should#be#number (r[i])
+    Assert r[i] == i+1
+    let i += 1
+  endwhile
+
+  Assert! should#be#list (r[-2])
+  Assert r[-2] == []
+  Assert! should#be#string (r[-1])
+  Assert r[-1] == 'foo'
+endfunction
+
+"todo: write double-binded tests for all kind of binded parameters:
+" 'len(g:bar)'
+" 42
+" []
+" v:1_ + len(v:2_.v:3_)
+" '"foo"'
+" v:1_
+
+"------------------------------------------------------------------------
+
+let &cpo=s:cpo_save
+"=============================================================================
+" vim600: set fdm=marker:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/lh-vim-lib/tests/lh/list.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,165 @@
+"=============================================================================
+" $Id: list.vim 238 2010-06-01 00:47:16Z luc.hermitte $
+" File:		tests/lh/list.vim                                      {{{1
+" Author:	Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
+"		<URL:http://code.google.com/p/lh-vim/>
+" Version:	2.2.1
+" Created:	19th Nov 2008
+" Last Update:	$Date: 2010-05-31 20:47:16 -0400 (Mon, 31 May 2010) $
+"------------------------------------------------------------------------
+" Description:	
+" 	Tests for autoload/lh/list.vim
+" 
+"------------------------------------------------------------------------
+" Installation:	«install details»
+" History:	«history»
+" TODO:		«missing features»
+" }}}1
+"=============================================================================
+
+UTSuite [lh-vim-lib] Testing lh#list functions
+
+runtime autoload/lh/function.vim
+runtime autoload/lh/list.vim
+let s:cpo_save=&cpo
+set cpo&vim
+"------------------------------------------------------------------------
+" Find_if
+function! s:Test_Find_If_string_predicate()
+    :let b = { 'min': 12, 'max': 42 }
+    :let l = [ 1, 5, 48, 25, 5, 28, 6]
+    :let i = lh#list#Find_if(l, 'v:val>v:1_.min  && v:val<v:1_.max && v:val%v:2_==0', [b, 2] )
+    " echo i . '/' . len(l)
+    Assert i == 5
+    Assert l[i] == 28
+    " :echo l[i]
+endfunction
+
+function! s:Test_Find_If_functor_predicate()
+    :let l = [ 1, 5, 48, 25, 5, 28, 6]
+    :let i = lh#list#find_if(l, 'v:1_>12  && v:1_<42 && v:1_%2==0')
+    " echo i . '/' . len(l)
+    Assert i == 5
+    Assert l[i] == 28
+    " :echo l[i]
+endfunction
+
+function! s:Test_find_if_double_bind()
+    :let b = { 'min': 12, 'max': 42 }
+    :let l = [ 1, 5, 48, 25, 5, 28, 6]
+    :let f = lh#function#bind( 'v:3_>v:1_.min  && v:3_<v:1_.max && v:3_%v:2_==0') 
+    :let p = lh#function#bind(f, b,2,'v:1_') 
+    :let i = lh#list#find_if(l, p)
+    :echo l[i]
+endfunction
+" double bind is not yet operational
+UTIgnore Test_find_if_double_bind
+
+"------------------------------------------------------------------------
+" Unique Sorting
+function! CmpNumbers(lhs, rhs)
+  if     a:lhs < a:rhs  | return -1
+  elseif a:lhs == a:rhs | return 0
+  else              | return +1
+  endif
+endfunction
+
+function! s:Test_sort()
+    :let l = [ 1, 5, 48, 25, 5, 28, 6]
+    :let expected = [ 1, 5, 6, 25, 28, 48]
+    :let s = lh#list#unique_sort(l, "CmpNumbers") 
+    " Comment string(s)
+    Assert s == expected
+endfunction
+
+function! s:Test_sort2()
+    :let l = [ 1, 5, 48, 25, 5, 28, 6]
+    :let expected = [ 1, 5, 6, 25, 28, 48]
+    :let s = lh#list#unique_sort2(l, "CmpNumbers") 
+    " Comment string(s)
+    Assert s == expected
+endfunction
+
+"------------------------------------------------------------------------
+" Searchs
+function! s:TestBinarySearches()
+  let v1 = [ -3, -2, -1, -1, 0, 0, 1, 2, 3, 4, 6 ]
+  let i = lh#list#lower_bound(v1, 3)
+  Assert v1[i] == 3
+  let i = lh#list#upper_bound(v1, 3)
+  Assert v1[i] == 4
+  let r = lh#list#equal_range(v1, 3)
+  Assert v1[r[0]:r[1]-1] == [3]
+
+  let i = lh#list#lower_bound(v1, -1)
+  Assert v1[i] == -1
+  let i = lh#list#upper_bound(v1, -1)
+  Assert v1[i] == 0
+  let r = lh#list#equal_range(v1, -1)
+  Assert v1[r[0]:r[1]-1] == [-1, -1]
+
+  let i = lh#list#lower_bound(v1, 5)
+  Assert v1[i] == 6
+  let i = lh#list#upper_bound(v1, 5)
+  Assert v1[i] == 6
+  let r = lh#list#equal_range(v1, 5)
+  Assert v1[r[0]:r[1]-1] == []
+
+  Assert len(v1) == lh#list#lower_bound(v1, 10)
+  Assert len(v1) == lh#list#upper_bound(v1, 10)
+  Assert [len(v1), len(v1)] == lh#list#equal_range(v1, 10)
+endfunction
+
+"------------------------------------------------------------------------
+" accumulate
+
+function! s:Test_accumulate_len_strings()
+  let strings = [ 'foo', 'bar', 'toto' ]
+  let len = eval(lh#list#accumulate(strings, 'strlen', 'join(v:1_,  "+")'))
+  Assert len == 3+3+4
+endfunction
+
+function! s:Test_accumulate_join()
+  let ll = [ 1, 2, 'foo', ['bar'] ]
+  let res = lh#list#accumulate(ll, 'string', 'join(v:1_,  " ## ")')
+  Assert res == "1 ## 2 ## 'foo' ## ['bar']"
+  " This test will fail because it seems :for each loop cannot iterate on
+  " heterogeneous containers
+endfunction
+
+"------------------------------------------------------------------------
+" Copy_if
+function! s:Test_copy_if()
+    :let l = [ 1, 25, 5, 48, 25, 5, 28, 6]
+    :let expected = [ 25, 48, 25, 28, 6]
+    :let s = lh#list#copy_if(l, [], "v:1_ > 5") 
+    " Comment string(s)
+    Assert s == expected
+endfunction
+
+"------------------------------------------------------------------------
+" subset
+function! s:Test_subset()
+    :let l = [ 1, 25, 5, 48, 25, 5, 28, 6]
+    :let indices = [ 0, 5, 7, 3 ]
+    :let expected = [ 1, 5, 6, 48 ]
+    :let s = lh#list#subset(l, indices) 
+    " Comment string(s)
+    Assert s == expected
+endfunction
+
+"------------------------------------------------------------------------
+" intersect
+function! s:Test_intersect()
+    :let l1 = [ 1, 25, 7, 48, 26, 5, 28, 6]
+    :let l2 = [ 3, 8, 7, 25, 6 ]
+    :let expected = [ 25, 7, 6 ]
+    :let s = lh#list#intersect(l1, l2) 
+    " Comment string(s)
+    Assert s == expected
+endfunction
+
+"------------------------------------------------------------------------
+let &cpo=s:cpo_save
+"=============================================================================
+" vim600: set fdm=marker:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/lh-vim-lib/tests/lh/path.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,173 @@
+"=============================================================================
+" $Id: path.vim 246 2010-09-19 22:40:58Z luc.hermitte $
+" File:		tests/lh/path.vim                                      {{{1
+" Author:	Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
+"		<URL:http://code.google.com/p/lh-vim/>
+" Version:	2.2.1
+" Created:	28th May 2009
+" Last Update:	$Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $
+"------------------------------------------------------------------------
+" Description:
+" 	Tests for autoload/lh/path.vim
+" 
+"------------------------------------------------------------------------
+" Installation:	«install details»
+" History:	«history»
+" TODO:		«missing features»
+" }}}1
+"=============================================================================
+
+UTSuite [lh-vim-lib] Testing lh#path functions
+
+runtime autoload/lh/path.vim
+let s:cpo_save=&cpo
+set cpo&vim
+"------------------------------------------------------------------------
+function! s:Test_simplify()
+  Assert lh#path#simplify('a/b/c') == 'a/b/c'
+  Assert lh#path#simplify('a/b/./c') == 'a/b/c'
+  Assert lh#path#simplify('./a/b/./c') == 'a/b/c'
+  Assert lh#path#simplify('./a/../b/./c') == 'b/c'
+  Assert lh#path#simplify('../a/../b/./c') == '../b/c'
+  Assert lh#path#simplify('a\b\c') == 'a\b\c'
+  Assert lh#path#simplify('a\b\.\c') == 'a\b\c'
+  Assert lh#path#simplify('.\a\b\.\c') == 'a\b\c'
+  if exists('+shellslash')
+    Assert lh#path#simplify('.\a\..\b\.\c') == 'b\c'
+    Assert lh#path#simplify('..\a\..\b\.\c') == '..\b\c'
+  endif
+endfunction
+
+function! s:Test_strip_common()
+  let paths = ['foo/bar/file', 'foo/file', 'foo/foo/file']
+  let expected = [ 'bar/file', 'file', 'foo/file']
+  Assert lh#path#strip_common(paths) == expected
+endfunction
+
+function! s:Test_common()
+  Assert 'foo/' == lh#path#common(['foo/bar/dir', 'foo'])
+  Assert 'foo/bar/' == lh#path#common(['foo/bar/dir', 'foo/bar'])
+  Assert 'foo/' == lh#path#common(['foo/bar/dir', 'foo/bar2'])
+endfunction
+
+function! s:Test_strip_start()
+  let expected = 'template/bar.template'
+  Assert lh#path#strip_start($HOME.'/.vim/template/bar.template',
+	\ [ $HOME.'/.vim', $HOME.'/vimfiles', '/usr/local/share/vim' ]) 
+	\ == expected
+
+  Assert lh#path#strip_start($HOME.'/vimfiles/template/bar.template',
+	\ [ $HOME.'/.vim', $HOME.'/vimfiles', '/usr/local/share/vim' ]) 
+	\ == expected
+
+  Assert lh#path#strip_start('/usr/local/share/vim/template/bar.template',
+	\ [ $HOME.'/.vim', $HOME.'/vimfiles', '/usr/local/share/vim' ]) 
+	\ == expected
+endfunction
+
+function! s:Test_IsAbsolutePath()
+  " nix paths
+  Assert lh#path#is_absolute_path('/usr/local')
+  Assert lh#path#is_absolute_path($HOME)
+  Assert ! lh#path#is_absolute_path('./usr/local')
+  Assert ! lh#path#is_absolute_path('.usr/local')
+
+  " windows paths
+  Assert lh#path#is_absolute_path('e:\usr\local')
+  Assert ! lh#path#is_absolute_path('.\usr\local')
+  Assert ! lh#path#is_absolute_path('.usr\local')
+
+  " UNC paths
+  Assert lh#path#is_absolute_path('\\usr\local')
+  Assert lh#path#is_absolute_path('//usr/local')
+endfunction
+
+function! s:Test_IsURL()
+  " nix paths
+  Assert ! lh#path#is_url('/usr/local')
+  Assert ! lh#path#is_url($HOME)
+  Assert ! lh#path#is_url('./usr/local')
+  Assert ! lh#path#is_url('.usr/local')
+
+  " windows paths
+  Assert ! lh#path#is_url('e:\usr\local')
+  Assert ! lh#path#is_url('.\usr\local')
+  Assert ! lh#path#is_url('.usr\local')
+
+  " UNC paths
+  Assert ! lh#path#is_url('\\usr\local')
+  Assert ! lh#path#is_url('//usr/local')
+
+  " URLs
+  Assert lh#path#is_url('http://www.usr/local')
+  Assert lh#path#is_url('https://www.usr/local')
+  Assert lh#path#is_url('ftp://www.usr/local')
+  Assert lh#path#is_url('sftp://www.usr/local')
+  Assert lh#path#is_url('dav://www.usr/local')
+  Assert lh#path#is_url('fetch://www.usr/local')
+  Assert lh#path#is_url('file://www.usr/local')
+  Assert lh#path#is_url('rcp://www.usr/local')
+  Assert lh#path#is_url('rsynch://www.usr/local')
+  Assert lh#path#is_url('scp://www.usr/local')
+endfunction
+
+function! s:Test_ToRelative()
+  let pwd = getcwd()
+  Assert lh#path#to_relative(pwd.'/foo/bar') == 'foo/bar'
+  Assert lh#path#to_relative(pwd.'/./foo') == 'foo'
+  Assert lh#path#to_relative(pwd.'/foo/../bar') == 'bar'
+
+  " Does not work yet as it returns an absolute path it that case
+  Assert lh#path#to_relative(pwd.'/../bar') == '../bar'
+endfunction
+
+function! s:Test_relative_path()
+  Assert lh#path#relative_to('foo/bar/dir', 'foo') == '../../'
+  Assert lh#path#relative_to('foo', 'foo/bar/dir') == 'bar/dir/'
+  Assert lh#path#relative_to('foo/bar', 'foo/bar2/dir') == '../bar2/dir/'
+
+  let pwd = getcwd()
+  Assert lh#path#relative_to(pwd ,pwd.'/../bar') == '../bar/'
+endfunction
+
+function! s:Test_search_vimfiles()
+  let expected_win = $HOME . '/vimfiles'
+  let expected_nix = $HOME . '/.vim'
+  let what =  lh#path#to_regex($HOME.'/').'\(vimfiles\|.vim\)'
+  " Comment what
+  let z = lh#path#find(&rtp,what)
+  if has('win16')||has('win32')||has('win64')
+    Assert z == expected_win
+  else
+    Assert z == expected_nix
+  endif
+endfunction
+
+function! s:Test_path_depth()
+  Assert 0 == lh#path#depth('.')
+  Assert 0 == lh#path#depth('./')
+  Assert 0 == lh#path#depth('.\')
+  Assert 1 == lh#path#depth('toto')
+  Assert 1 == lh#path#depth('toto/')
+  Assert 1 == lh#path#depth('toto\')
+  Assert 1 == lh#path#depth('toto/.')
+  Assert 1 == lh#path#depth('toto\.')
+  Assert 1 == lh#path#depth('toto/./.')
+  Assert 1 == lh#path#depth('toto\.\.')
+  Assert 0 == lh#path#depth('toto/..')
+  if exists('+shellslash')
+    Assert 0 == lh#path#depth('toto\..')
+  endif
+  Assert 2 == lh#path#depth('toto/titi/')
+  Assert 2 == lh#path#depth('toto\titi\')
+  Assert 2 == lh#path#depth('/toto/titi/')
+  Assert 2 == lh#path#depth('c:/toto/titi/')
+  Assert 2 == lh#path#depth('c:\toto/titi/')
+" todo: make a choice about "negative" paths like "../../foo"
+  Assert -1 == lh#path#depth('../../foo')
+endfunction
+
+"------------------------------------------------------------------------
+let &cpo=s:cpo_save
+"=============================================================================
+" vim600: set fdm=marker:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/lh-vim-lib/tests/lh/test-Fargs2String.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,83 @@
+"=============================================================================
+" $Id: test-Fargs2String.vim 246 2010-09-19 22:40:58Z luc.hermitte $
+" File:		tests/lh/test-Fargs2String.vim                           {{{1
+" Author:	Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
+"		<URL:http://code.google.com/p/lh-vim/>
+" Version:	2.2.1
+" Created:	16th Apr 2007
+" Last Update:	$Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $
+"------------------------------------------------------------------------
+" Description:	Tests for lh-vim-lib . lh#command#Fargs2String
+" 
+"------------------------------------------------------------------------
+" Installation:	
+" 	Relies on the version «patched by myself|1?» of vim_units
+" History:	«history»
+" TODO:		«missing features»
+" }}}1
+"=============================================================================
+
+function! s:TestEmpty()
+  let empty = []
+  let res = lh#command#Fargs2String(empty)
+  call VUAssertEquals(len(empty), 0, 'Expected empty', 22)
+  call VUAssertEquals(res, '', 'Expected empty result', 23)
+endfunction
+
+function! s:TestSimpleText1()
+  let expected = 'text'
+  let one = [ expected ]
+  let res = lh#command#Fargs2String(one)
+  call VUAssertEquals(len(one), 0, 'Expected empty', 27)
+  call VUAssertEquals(res, expected, 'Expected a simple result', 28)
+endfunction
+
+function! s:TestSimpleTextN()
+  let expected = 'text'
+  let list = [ expected , 'stuff1', 'stuff2']
+  let res = lh#command#Fargs2String(list)
+  call VUAssertEquals(len(list), 2, 'Expected not empty', 38)
+  call VUAssertEquals(res, expected, 'Expected a simple result', 39)
+endfunction
+
+function! s:TestComposedN()
+  let expected = '"a several tokens string"'
+  let list = [ '"a', 'several', 'tokens', 'string"', 'stuff1', 'stuff2']
+  let res = lh#command#Fargs2String(list)
+  call VUAssertEquals(len(list), 2, 'Expected not empty', 46)
+  call VUAssertEquals(res, expected, 'Expected a composed string', 47)
+  call VUAssertEquals(list, ['stuff1', 'stuff2'], 'Expected a list', 48)
+  call VUAssertNotSame(list, ['stuff1', 'stuff2'], 'Expected different lists', 49)
+endfunction
+
+function! s:TestComposed1()
+  let expected = '"string"'
+  let list = [ '"string"', 'stuff1', 'stuff2']
+  let res = lh#command#Fargs2String(list)
+  call VUAssertEquals(len(list), 2, 'Expected not empty', 56)
+  call VUAssertEquals(res, expected, 'Expected a string', 57)
+  call VUAssertEquals(list, ['stuff1', 'stuff2'], 'Expected a list', 58)
+  call VUAssertNotSame(list, ['stuff1', 'stuff2'], 'Expected different lists', 59)
+endfunction
+
+function! s:TestInvalidString()
+  let expected = '"a string'
+  let list = [ '"a', 'string']
+  let res = lh#command#Fargs2String(list)
+  call VUAssertEquals(len(list), 0, 'Expected empty', 66)
+  call VUAssertEquals(res, expected, 'Expected an invalid string', 67)
+endfunction
+
+function! AllTests()
+  call s:TestEmpty()
+  call s:TestSimpleText1()
+  call s:TestSimpleTextN()
+  call s:TestComposed1()
+  call s:TestComposedN()
+endfunction
+
+" call VURunnerRunTest('AllTests')
+VURun % AllTests
+
+"=============================================================================
+" vim600: set fdm=marker:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/lh-vim-lib/tests/lh/test-askmenu.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,65 @@
+"=============================================================================
+" $Id: test-askmenu.vim 246 2010-09-19 22:40:58Z luc.hermitte $
+" File:		test-buffer-menu.vim                                      {{{1
+" Author:	Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
+"		<URL:http://code.google.com/p/lh-vim/>
+" Version:	2.2.1
+" Created:	18th Apr 2007
+" Last Update:	$Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $
+"------------------------------------------------------------------------
+" Description:	
+" 	Test units for buffermenu.vim
+" 
+"------------------------------------------------------------------------
+" Installation:	Requires:
+" 	(*) Vim 7.0+
+" 	(*) vim_units.vim v0.2/1.0?
+" 	    Vimscript # «???»
+" 	(*) lh-vim-lib (lh#ask#menu)
+"
+" User Manual:
+" 	Source this file.
+"
+" History:	
+" (*) 17th Apr 2007: First version 
+" TODO:		«missing features»
+" }}}1
+"=============================================================================
+
+
+
+"=============================================================================
+let s:cpo_save=&cpo
+"------------------------------------------------------------------------
+" Functions {{{1
+
+function! TestAskMenu()
+  imenu          42.40.10 &LH-Tests.&Menu.&ask.i       iask
+  inoremenu      42.40.10 &LH-Tests.&Menu.&ask.inore   inoreask
+  nmenu          42.40.10 &LH-Tests.&Menu.&ask.n       nask
+  nnoremenu      42.40.10 &LH-Tests.&Menu.&ask.nnore   nnoreask
+  nmenu <script> 42.40.10 &LH-Tests.&Menu.&ask.nscript nscriptask
+  nnoremenu <script> 42.40.10 &LH-Tests.&Menu.&ask.nnnscript nnscriptask
+
+  vmenu          42.40.10 &LH-Tests.&Menu.&ask.v     vask
+  vnoremenu      42.40.10 &LH-Tests.&Menu.&ask.vnore vnoreask
+
+  call s:CheckInMode('i', 'i')
+
+endfunction
+
+function! s:CheckInMode(mode, name)
+  let g:menu = lh#askvim#menu('LH-Tests.Menu.ask.'.a:name, a:mode)
+  let g:name = a:name
+  " VUAssert 55 Equals g:menu.name     g:name     "Name mismatch"
+  " VUAssert 56 Equals g:menu.priority '42.40.10' "Priority mismatch"
+  " VUAssert 57 Fail "parce qu'il le faut bien"
+  echomsg "name= ".g:menu.name
+  echomsg "prio= ".g:menu.priority
+endfunction
+
+" Functions }}}1
+"------------------------------------------------------------------------
+let &cpo=s:cpo_save
+"=============================================================================
+" vim600: set fdm=marker:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/lh-vim-lib/tests/lh/test-command.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,69 @@
+" $Id: test-command.vim 156 2010-05-07 00:54:36Z luc.hermitte $
+" Tests for lh-vim-lib . lh#command
+
+" FindFilter(filter):                            Helper {{{3
+function! s:FindFilter(filter)
+  let filter = a:filter . '.vim'
+  let result =globpath(&rtp, "compiler/BTW-".filter) . "\n" .
+	\ globpath(&rtp, "compiler/BTW_".filter). "\n" .
+	\ globpath(&rtp, "compiler/BTW/".filter)
+  let result = substitute(result, '\n\n', '\n', 'g')
+  let result = substitute(result, '^\n', '', 'g')
+  return result
+endfunction
+
+function! s:ComplFilter(filter)
+  let files = s:FindFilter('*')
+  let files = substitute(files,
+	\ '\(^\|\n\).\{-}compiler[\\/]BTW[-_\\/]\(.\{-}\)\.vim\>\ze\%(\n\|$\)',
+	\ '\1\2', 'g')
+  return files
+endfunction
+
+function! s:Add()
+endfunction
+
+let s:v1 = 'v1'
+let s:v2 = 2
+
+function! s:Foo(i)
+  return a:i*a:i
+endfunction
+
+function! s:echo(params)
+  echo s:{join(a:params, '')}
+endfunction
+
+function! Echo(params)
+  " echo "Echo(".string(a:params).')'
+  let expr = 's:'.join(a:params, '')
+  " echo expr
+  exe 'echo '.expr
+endfunction
+
+let TBTWcommand = {
+      \ "name"      : "TBT",
+      \ "arg_type"  : "sub_commands",
+      \ "arguments" :
+      \     [
+      \       { "name"      : "echo",
+      \		"arg_type"  : "function",
+      \         "arguments" : "v1,v2",
+      \         "action": function("\<sid>echo") },
+      \       { "name"      : "Echo",
+      \		"arg_type"  : "function",
+      \         "arguments" : "v1,v2",
+      \         "action": function("Echo") },
+      \       { "name"  : "help" },
+      \       { "name"  : "add",
+      \         "arguments": function("s:ComplFilter"),
+      \         "action" : function("s:Add") }
+      \     ]
+      \ }
+
+call lh#command#new(TBTWcommand)
+
+nnoremap µ :call lh#command#new(TBTWcommand)<cr>
+
+"=============================================================================
+" vim600: set fdm=marker:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/lh-vim-lib/tests/lh/test-menu-map.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,54 @@
+"=============================================================================
+" $Id: test-menu-map.vim 246 2010-09-19 22:40:58Z luc.hermitte $
+" File:		tests/lh/test-menu-map.vim                               {{{1
+" Author:	Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
+"		<URL:http://code.google.com/p/lh-vim/>
+" Version:	2.2.1
+" Created:	05th Dec 2006
+" Last Update:	$Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $
+"------------------------------------------------------------------------
+" Description:	Tests for lh-vim-lib . lh#menu#
+" 
+"------------------------------------------------------------------------
+" Installation:	«install details»
+" History:	«history»
+" TODO:		«missing features»
+" }}}1
+"=============================================================================
+
+
+" let g:want_buffermenu_or_global_disable = 1
+" let b:want_buffermenu_or_global_disable = 1
+" echo lh#option#get("want_buffermenu_or_global_disable", 1, "bg")
+
+" Call a command (':Command')
+call lh#menu#make("nic", '42.50.340',
+      \ '&LH-Tests.&Menu-Make.Build Ta&gs', "<C-L>g",
+      \ '<buffer>',
+      \ ":echo 'TeXtags'<CR>")
+
+" With '{' expanding to '{}××', or '{}' regarding the mode
+call lh#menu#IVN_make('42.50.360.200',
+      \ '&LH-Tests.&Menu-Make.&Insert.\toto{}', ']toto',
+      \ '\\toto{',
+      \ '{%i\\toto<ESC>%l',
+      \ "viw]toto")
+
+" Noremap for the visual maps
+call lh#menu#IVN_make('42.50.360.200',
+      \ '&LH-Tests.&Menu-Make.&Insert.\titi{}', ']titi',
+      \ '\\titi{',
+      \ '<ESC>`>a}<ESC>`<i\\titi{<ESC>%l',
+      \ "viw]titi",
+      \ 0, 1, 0)
+
+" Noremap for the insert and visual maps
+call lh#menu#IVN_make('42.50.360.200',
+      \ '&LH-Tests.&Menu-Make.&Insert.<tata></tata>', ']tata',
+      \ '<tata></tata><esc>?<<CR>i', 
+      \ '<ESC>`>a</tata><ESC>`<i<tata><ESC>/<\\/tata>/e1<CR>',
+      \ "viw]tata", 
+      \ 1, 1, 0)
+
+"=============================================================================
+" vim600: set fdm=marker:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/lh-vim-lib/tests/lh/test-toggle-menu.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,84 @@
+"=============================================================================
+" $Id: test-toggle-menu.vim 246 2010-09-19 22:40:58Z luc.hermitte $
+" File:         tests/lh/topological-sort.vim                            {{{1
+" Author:       Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
+"               <URL:http://code.google.com/p/lh-vim/>
+" Version:      2.2.1
+" Created:      17th Apr 2007
+" Last Update:  $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $
+"------------------------------------------------------------------------
+" Description:  
+"       Tests for lh-vim-lib . lh#menu#def_toggle_item()
+"
+"------------------------------------------------------------------------
+" Installation: «install details»
+" History:      «history»
+" TODO:         «missing features»
+" }}}1
+"=============================================================================
+
+source autoload/lh/menu.vim
+
+let Data = {
+      \ "variable": "bar",
+      \ "idx_crt_value": 1,
+      \ "values": [ 'a', 'b', 'c', 'd' ],
+      \ "menu": { "priority": '42.50.10', "name": '&LH-Tests.&TogMenu.&bar'}
+      \}
+
+call lh#menu#def_toggle_item(Data)
+
+let Data2 = {
+      \ "variable": "foo",
+      \ "idx_crt_value": 3,
+      \ "texts": [ 'un', 'deux', 'trois', 'quatre' ],
+      \ "values": [ 1, 2, 3, 4 ],
+      \ "menu": { "priority": '42.50.11', "name": '&LH-Tests.&TogMenu.&foo'}
+      \}
+
+call lh#menu#def_toggle_item(Data2)
+
+" No default
+let Data3 = {
+      \ "variable": "nodef",
+      \ "texts": [ 'one', 'two', 'three', 'four' ],
+      \ "values": [ 1, 2, 3, 4 ],
+      \ "menu": { "priority": '42.50.12', "name": '&LH-Tests.&TogMenu.&nodef'}
+      \}
+call lh#menu#def_toggle_item(Data3)
+
+" No default
+let g:def = 2
+let Data4 = {
+      \ "variable": "def",
+      \ "values": [ 1, 2, 3, 4 ],
+      \ "menu": { "priority": '42.50.13', "name": '&LH-Tests.&TogMenu.&def'}
+      \}
+call lh#menu#def_toggle_item(Data4)
+
+" What follows does not work because we can't build an exportable FuncRef on top
+" of a script local function
+" finish
+
+function! s:getSNR()
+  if !exists("s:SNR")
+    let s:SNR=matchstr(expand("<sfile>"), "<SNR>\\d\\+_\\zegetSNR$")
+  endif
+  return s:SNR 
+endfunction
+
+function! s:Yes()
+  echomsg "Yes"
+endfunction
+
+function! s:No()
+  echomsg "No"
+endfunction
+let Data4 = {
+      \ "variable": "yesno",
+      \ "values": [ 1, 2 ],
+      \ "text": [ "No", "Yes" ],
+      \ "actions": [ function(s:getSNR()."No"), function(s:getSNR()."Yes") ],
+      \ "menu": { "priority": '42.50.20', "name": '&LH-Tests.&TogMenu.&yesno'}
+      \}
+call lh#menu#def_toggle_item(Data4)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/lh-vim-lib/tests/lh/topological-sort.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,120 @@
+"=============================================================================
+" $Id: topological-sort.vim 246 2010-09-19 22:40:58Z luc.hermitte $
+" File:         tests/lh/topological-sort.vim                            {{{1
+" Author:       Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
+"               <URL:http://code.google.com/p/lh-vim/>
+" Version:      2.2.1
+" Created:      17th Apr 2008
+" Last Update:  $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $
+"------------------------------------------------------------------------
+" Description:  «description»
+"
+"------------------------------------------------------------------------
+" Installation: «install details»
+" History:      «history»
+" TODO:         «missing features»
+" }}}1
+"=============================================================================
+
+let s:cpo_save=&cpo
+set cpo&vim
+"------------------------------------------------------------------------
+UTSuite [lh-vim-lib] topological sort
+
+" Fully defineds DAGs {{{1
+
+" A Direct Acyclic Graph {{{2
+let s:dag1 = {}
+let s:dag1[7] = [11, 8]
+let s:dag1[5] = [11]
+let s:dag1[3] = [8, 10]
+let s:dag1[11] = [2, 9, 10]
+let s:dag1[8] = [9]
+
+" A Direct Cyclic Graph {{{2
+let s:dcg1 = deepcopy(s:dag1)
+let s:dcg1[9] = [11]
+
+" Check routine: are the elements correctly sorted? {{{2
+function! s:DoTestOrder(elements)
+  Assert! len(a:elements) == 8
+  Assert index(a:elements, 7) < index(a:elements, 11)
+  Assert index(a:elements, 7) < index(a:elements, 8)
+  Assert index(a:elements, 5) < index(a:elements, 11)
+  Assert index(a:elements, 3) < index(a:elements, 8)
+  Assert index(a:elements, 3) < index(a:elements, 10)
+  Assert index(a:elements, 11) < index(a:elements, 2)
+  Assert index(a:elements, 11) < index(a:elements, 9)
+  Assert index(a:elements, 11) < index(a:elements, 10)
+  Assert index(a:elements, 8) < index(a:elements, 9)
+endfunction
+
+" Test DAG1 {{{2
+function! s:TestDAG_depth()
+  let res = lh#graph#tsort#depth(s:dag1, [3, 5,7])
+  call s:DoTestOrder(res)
+  echo "D(s:dag1)=".string(res)
+endfunction
+
+function! s:TestDAG_breadth()
+  let res = lh#graph#tsort#breadth(s:dag1, [3, 5,7])
+  call s:DoTestOrder(res)
+  echo "B(s:dag1)=".string(res)
+endfunction
+
+" Test DCG1 {{{2
+function! s:TestDCG_depth()
+  let expr = 'lh#graph#tsort#depth('.string(s:dcg1).', [3, 5,7])'
+  Assert should#throw(expr, 'Tsort: cyclic graph detected')
+endfunction
+
+function! s:TestDCG_breadth()
+  let expr = 'lh#graph#tsort#breadth('.string(s:dcg1).', [3, 5,7])'
+  Assert should#throw(expr, 'Tsort: cyclic graph detected')
+endfunction
+
+" Lazzy Evaluated DAGs {{{1
+
+" Emulated lazzyness {{{2
+" The time-consumings evaluation function
+let s:called = 0
+function! Fetch(node)
+  let s:called += 1
+  return has_key(s:dag1, a:node) ? (s:dag1[a:node]) : []
+endfunction
+
+" Test Fetch on a DAG {{{2
+function! s:TestDAG_fetch()
+  let s:called = 0
+  let res = lh#graph#tsort#depth(function('Fetch'), [3,5,7])
+  call s:DoTestOrder(res)
+  echo "D(fetch)=".string(res)
+  echo "Fetch has been evaluated ".s:called." times / ".len(res)
+  Assert s:called == len(res)
+endfunction
+
+
+" Setup/Teardown functions {{{1
+" display the test name before each assertion
+function! s:Setup()
+  if exists('g:UT_print_test')
+    let s:old_print_test = g:UT_print_test
+  endif
+  let g:UT_print_test = 1
+endfunction
+
+function! s:Teardown()
+  if exists('s:old_print_test')
+    let g:UT_print_test = s:old_print_test 
+    unlet s:old_print_test
+  else
+    unlet g:UT_print_test
+  endif
+endfunction
+
+
+" }}}1
+let &cpo=s:cpo_save
+"=============================================================================
+" vim600: set fdm=marker:
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/ut/UT.README	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,16 @@
+			  --------------------
+			       UT v0.0.3
+			  --------------------
+
+UT is a Unit Testing Framework for Vim
+
+Audience      : Vim script maintainers
+Requirements  : Vim 7, lh-vim-lib v2.2.0 ;
+	        takes advantage of BuildtoolsWrappers if installed.
+Required by   : Only lh-vim
+Maintainer    : Luc Hermitte
+License       : GPL 2 (see http://www.gnu.org/licenses/gpl.txt)
+More Help At  : http://code.google.com/p/lh-vim/wiki/UT
+Vim script#???: http://www.vim.org/scripts/script.php?script_id=???
+Repository    :
+	svn checkout http://lh-vim.googlecode.com/svn/UT/trunk UT
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/ut/autoload/lh/UT.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,442 @@
+"=============================================================================
+" $Id: UT.vim 193 2010-05-17 23:10:03Z luc.hermitte $
+" File:         autoload/lh/UT.vim                                {{{1
+" Author:       Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
+"               <URL:http://code.google.com/p/lh-vim/>
+" Version:      0.0.3
+" Created:      11th Feb 2009
+" Last Update:  $Date: 2010-05-17 19:10:03 -0400 (Mon, 17 May 2010) $
+"------------------------------------------------------------------------
+" Description:  Yet Another Unit Testing Framework for Vim 
+" 
+"------------------------------------------------------------------------
+" Installation: 
+" 	Drop this file into {rtp}/autoload/lh/
+" History:      
+" 	Strongly inspired by Tom Link's tAssert plugin: all its functions are
+" 	compatible with this framework.
+"
+" Features:
+" - Assertion failures are reported in the quickfix window
+" - Assertion syntax is simple, check Tom Link's suite, it's the same
+" - Supports banged :Assert! to stop processing a given test on failed
+"   assertions
+" - All the s:Test* functions of a suite are executed (almost) independently
+"   (i.e., a critical :Assert! failure will stop the Test of the function, and
+"   lh#UT will proceed to the next s:Test function
+" - Lightweight and simple to use: there is only one command defined, all the
+"   other definitions are kept in an autoload plugin.
+" - A suite == a file
+" - Several s:TestXxx() per suite
+" - +optional s:Setup(), s:Teardown()
+" - Supports :Comment's ; :Comment takes an expression to evaluate
+" - s:LocalFunctions(), s:variables, and l:variables are supported
+" - Takes advantage of BuildToolsWrapper's :Copen command if installed
+" - Count successful tests (and not successful assertions)
+" - Short-cuts to run the Unit Tests associated to a given vim script
+"   Relies on: Let-Modeline/local_vimrc/Project to set g:UTfiles (space
+"   separated list of glob-able paths), and on lh-vim-lib#path
+" - Command to exclude, or specify the tests to play => UTPlay, UTIgnore
+" - Option g:UT_print_test to display, on assertion failure, the current test
+"   name with the assertion failed.
+"
+" TODO:         
+" - Always execute s:Teardown() -- move its call to a :finally bloc
+" - Test in UTF-8 (because of <SNR>_ injection)
+" - test under windows (where paths have spaces, etc)
+" - What about s:/SNR pollution ? The tmpfile is reused, and there is no
+"   guaranty a script will clean its own place
+" - add &efm for viml errors like the one produced by :Assert 0 + [0]
+"   and take into account the offset introduced by lines injected at the top of
+"   the file
+" - simplify s:errors functions
+" - merge with Tom Link tAssert plugin? (the UI is quite different)
+" - :AssertEquals that shows the name of both expressions and their values as
+"   well -- a correct distinction of both parameters will be tricky with
+"   regexes ; using functions will loose either the name, or the value in case
+"   of local/script variables use ; we need macros /ŕ la C/...
+" - Support Embedded comments like for instance: 
+"   Assert 1 == 1 " 1 must value 1
+" - Ways to test buffers produced
+" }}}1
+"=============================================================================
+
+let s:cpo_save=&cpo
+set cpo&vim
+"------------------------------------------------------------------------
+
+" ## Functions {{{1
+"------------------------------------------------------------------------
+" # Debug {{{2
+function! lh#UT#verbose(level)
+  let s:verbose = a:level
+endfunction
+
+function! s:Verbose(expr, ...)
+  let lvl = a:0>0 ? a:1 : 1
+  if exists('s:verbose') && s:verbose >= lvl
+    echomsg a:expr
+  endif
+endfunction
+
+function! lh#UT#debug(expr)
+  return eval(a:expr)
+endfunction
+
+"------------------------------------------------------------------------
+" # Internal functions {{{2
+"------------------------------------------------------------------------
+ 
+" Sourcing a script doesn't imply a new entry with its name in :scriptnames
+" As a consequence, the easiest thing to do is to reuse the same file over and
+" over in a given vim session.
+" This approach should be fine as long as there are less than 26 VimL testing vim
+" sessions opened simultaneously.
+let s:tempfile = tempname()
+
+"------------------------------------------------------------------------
+" s:errors
+let s:errors = {
+      \ 'qf'                    : [],
+      \ 'crt_suite'             : {},
+      \ 'nb_asserts'            : 0,
+      \ 'nb_successful_asserts' : 0,
+      \ 'nb_success'            : 0,
+      \ 'suites'                : []
+      \ }
+
+function! s:errors.clear() dict
+  let self.qf                    = []
+  let self.nb_asserts            = 0
+  let self.nb_successful_asserts = 0
+  let self.nb_success            = 0
+  let self.nb_tests              = 0
+  let self.suites                = []
+  let self.crt_suite             = {}
+endfunction
+
+function! s:errors.display() dict
+  let g:errors = self.qf
+  cexpr self.qf
+
+  " Open the quickfix window
+  if exists(':Copen')
+    " Defined in lh-BTW, make the windows as big as the number of errors, not
+    " opened if there is no error
+    Copen
+  else
+    copen
+  endif
+endfunction
+
+function! s:errors.set_current_SNR(SNR)
+  let self.crt_suite.snr = a:SNR
+endfunction
+
+function! s:errors.get_current_SNR()
+  return self.crt_suite.snr
+endfunction
+
+function! s:errors.add(FILE, LINE, message) dict
+  let msg = a:FILE.':'.a:LINE.':'
+  if lh#option#get('UT_print_test', 0, 'g') && has_key(s:errors, 'crt_test')
+    let msg .= '['. s:errors.crt_test.name .'] '
+  endif
+  let msg.= a:message
+  call add(self.qf, msg)
+endfunction
+
+function! s:errors.add_test(test_name) dict
+  call self.add_test(a:test_name)
+endfunction
+
+function! s:errors.set_test_failed() dict
+  if has_key(self, 'crt_test') 
+    let self.crt_test.failed = 1
+  endif
+endfunction
+
+"------------------------------------------------------------------------
+" Tests wrapper functions
+
+function! s:RunOneTest(file) dict
+  try
+    let s:errors.crt_test = self
+    if has_key(s:errors.crt_suite, 'setup')
+      let F = function(s:errors.get_current_SNR().'Setup')
+      call F()
+    endif
+    let F = function(s:errors.get_current_SNR(). self.name)
+    call F()
+    if has_key(s:errors.crt_suite, 'teardown')
+      let F = function(s:errors.get_current_SNR().'Teardown')
+      call F()
+    endif
+  catch /Assert: abort/
+    call s:errors.add(a:file, 
+          \ matchstr(v:exception, '.*(\zs\d\+\ze)'),
+          \ 'Test <'. self.name .'> execution aborted on critical assertion failure')
+  catch /.*/
+    let throwpoint = substitute(v:throwpoint, escape(s:tempfile, '.\'), a:file, 'g')
+    let msg = throwpoint . ': '.v:exception
+    call s:errors.add(a:file, 0, msg)
+  finally
+    unlet s:errors.crt_test
+  endtry
+endfunction
+
+function! s:AddTest(test_name) dict
+  let test = {
+        \ 'name'   : a:test_name,
+        \ 'run'    : function('s:RunOneTest'),
+        \ 'failed' : 0
+        \ }
+  call add(self.tests, test)
+endfunction
+
+"------------------------------------------------------------------------
+" Suites wrapper functions
+
+function! s:ConcludeSuite() dict
+  call s:errors.add(self.file,0,  'SUITE<'. self.name.'> '. s:errors.nb_success .'/'. s:errors.nb_tests . ' tests successfully executed.')
+  " call add(s:errors.qf, 'SUITE<'. self.name.'> '. s:rrors.nb_success .'/'. s:errors.nb_tests . ' tests successfully executed.')
+endfunction
+
+function! s:PlayTests(...) dict
+  call s:Verbose('Execute tests: '.join(a:000, ', '))
+  call filter(self.tests, 'index(a:000, v:val.name) >= 0')
+  call s:Verbose('Keeping tests: '.join(self.tests, ', '))
+endfunction
+
+function! s:IgnoreTests(...) dict
+  call s:Verbose('Ignoring tests: '.join(a:000, ', '))
+  call filter(self.tests, 'index(a:000, v:val.name) < 0')
+  call s:Verbose('Keeping tests: '.join(self.tests, ', '))
+endfunction
+
+function! s:errors.new_suite(file) dict
+  let suite = {
+        \ 'scriptname'      : s:tempfile,
+        \ 'file'            : a:file,
+        \ 'tests'           : [],
+        \ 'snr'             : '',
+        \ 'add_test'        : function('s:AddTest'),
+        \ 'conclude'        : function('s:ConcludeSuite'),
+        \ 'play'            : function('s:PlayTests'),
+        \ 'ignore'          : function('s:IgnoreTests'),
+        \ 'nb_tests_failed' : 0
+        \ }
+  call add(self.suites, suite)
+  let self.crt_suite = suite
+  return suite
+endfunction
+
+function! s:errors.set_suite(suite_name) dict
+  let a = s:Decode(a:suite_name)
+  call s:Verbose('SUITE <- '. a.expr, 1)
+  call s:Verbose('SUITE NAME: '. a:suite_name, 2)
+  " call self.add(a.file, a.line, 'SUITE <'. a.expr .'>')
+  call self.add(a.file,0, 'SUITE <'. a.expr .'>')
+  let self.crt_suite.name = a.expr
+  " let self.crt_suite.file = a.file
+endfunction
+
+"------------------------------------------------------------------------
+function! s:Decode(expression)
+  let filename = s:errors.crt_suite.file
+  let expr = a:expression
+  let line = matchstr(expr, '^\d\+')
+  " echo filename.':'.line
+  let expr = strpart(expr, strlen(line)+1)
+  let res = { 'file':filename, 'line':line, 'expr':expr}
+  call s:Verbose('decode:'. (res.file) .':'. (res.line) .':'. (res.expr), 2)
+  return res
+endfunction
+
+function! lh#UT#callback_decode(expression)
+  return s:Decode(a:expression)
+endfunction
+
+"------------------------------------------------------------------------
+let s:k_commands = '\%(Assert\|UTSuite\|Comment\)'
+let s:k_local_evaluate = [
+      \ 'command! -bang -nargs=1 Assert '.
+      \ 'let s:a = lh#UT#callback_decode(<q-args>) |'.
+      \ 'let s:ok = !empty(eval(s:a.expr))  |'.
+      \ 'exe "UTAssert<bang> ".s:ok." ".(<f-args>)|'
+      \]
+let s:k_getSNR   = [
+      \ 'function! s:getSNR()',
+      \ '  if !exists("s:SNR")',
+      \ '    let s:SNR=matchstr(expand("<sfile>"), "<SNR>\\d\\+_\\zegetSNR$")',
+      \ '  endif',
+      \ '  return s:SNR', 
+      \ 'endfunction',
+      \ 'call lh#UT#callback_set_SNR(s:getSNR())',
+      \ ''
+      \ ]
+
+function! s:PrepareFile(file)
+  if !filereadable(a:file)
+    call s:errors.add('-', 0, a:file . " can not be read")
+    return 
+  endif
+  let file = escape(a:file, ' \')
+
+  let lines = readfile(a:file)
+  let need_to_know_SNR = 0
+  let suite = s:errors.new_suite(a:file)
+
+  let no = 0
+  let last_line = len(lines)
+  while no < last_line
+    if lines[no] =~ '^\s*'.s:k_commands.'\>'
+      let lines[no] = substitute(lines[no], '^\s*'.s:k_commands.'!\= \zs', (no+1).' ', '')
+
+    elseif lines[no] =~ '^\s*function!\=\s\+s:Test'
+      let test_name = matchstr(lines[no], '^\s*function!\=\s\+s:\zsTest\S\{-}\ze(')
+      call suite.add_test(test_name)
+    elseif lines[no] =~ '^\s*function!\=\s\+s:Teardown'
+      let suite.teardown = 1
+    elseif lines[no] =~ '^\s*function!\=\s\+s:Setup'
+      let suite.setup = 1
+    endif
+    if lines[no] =~ '^\s*function!\=\s\+s:'
+      let need_to_know_SNR = 1
+    endif
+    let no += 1
+  endwhile
+
+  " Inject s:getSNR() in the script if there is a s:Function in the Test script
+  if need_to_know_SNR
+    call extend(lines, s:k_getSNR, 0)
+    let last_line += len(s:k_getSNR)
+  endif
+
+  " Inject local evualation of expressions in the script
+  " => takes care of s:variables, s:Functions(), and l:variables
+  call extend(lines, s:k_local_evaluate, 0)
+
+  call writefile(lines, suite.scriptname)
+  let g:lines=lines
+endfunction
+
+function! s:RunOneFile(file)
+  try 
+    call s:PrepareFile(a:file)
+    exe 'source '.s:tempfile
+
+    let s:errors.nb_tests = len(s:errors.crt_suite.tests)
+    if !empty(s:errors.crt_suite.tests)
+      call s:Verbose('Executing tests: '.join(s:errors.crt_suite.tests, ', '))
+      for test in s:errors.crt_suite.tests
+        call test.run(a:file)
+        let s:errors.nb_success += 1 - test.failed
+      endfor
+    endif
+
+  catch /Assert: abort/
+    call s:errors.add(a:file, 
+          \ matchstr(v:exception, '.*(\zs\d\+\ze)'),
+          \ 'Suite <'. s:errors.crt_suite .'> execution aborted on critical assertion failure')
+  catch /.*/
+    let throwpoint = substitute(v:throwpoint, escape(s:tempfile, '.\'), a:file, 'g')
+    let msg = throwpoint . ': '.v:exception
+    call s:errors.add(a:file, 0, msg)
+  finally
+    call s:errors.crt_suite.conclude()
+    " Never! the name must not be used by other Vim sessions
+    " call delete(s:tempfile)
+  endtry
+endfunction
+
+"------------------------------------------------------------------------
+function! s:StripResultAndDecode(expr)
+  " Function needed because of an odd degenerescence of vim: commands
+  " eventually loose their '\'
+  return s:Decode(matchstr(a:expr, '^\d\+\s\+\zs.*')) 
+endfunction
+
+function! s:GetResult(expr)
+  " Function needed because of an odd degenerescence of vim: commands
+  " eventually loose their '\'
+  return matchstr(a:expr, '^\d\+\ze\s\+.*') 
+endfunction
+
+function! s:DefineCommands()
+  " NB: variables are already interpreted, make it a function
+  " command! -nargs=1 Assert call s:Assert(<q-args>)
+  command! -bang -nargs=1 UTAssert 
+        \ let s:a = s:StripResultAndDecode(<q-args>)                |
+        \ let s:ok = s:GetResult(<q-args>)                         |
+        \ let s:errors.nb_asserts += 1                                            |
+        \ if ! s:ok                                                               |
+        \    call s:errors.set_test_failed()                                      |
+        \    call s:errors.add(s:a.file, s:a.line, 'assertion failed: '.s:a.expr) |
+        \    if '<bang>' == '!'                                                   |
+        \       throw "Assert: abort (".s:a.line.")"                              |
+        \    endif                                                                |
+        \ else                                                                    |
+        \    let s:errors.nb_successful_asserts += 1                              |
+        \ endif
+
+  command! -nargs=1 Comment
+        \ let s:a = s:Decode(<q-args>)                                            |
+        \ call s:errors.add(s:a.file, s:a.line, eval(s:a.expr))
+  command! -nargs=1 UTSuite call s:errors.set_suite(<q-args>)
+
+  command! -nargs=+ UTPlay   call s:errors.crt_suite.play(<f-args>)
+  command! -nargs=+ UTIgnore call s:errors.crt_suite.ignore(<f-args>)
+endfunction
+
+function! s:UnDefineCommands()
+  silent! delcommand Assert
+  silent! delcommand UTAssert
+  silent! command! -nargs=* UTSuite :echoerr "Use :UTRun and not :source on this script"<bar>finish
+  silent! delcommand UTPlay
+  silent! delcommand UTIgnore
+endfunction
+"------------------------------------------------------------------------
+" # callbacks {{{2
+function! lh#UT#callback_set_SNR(SNR)
+  call s:errors.set_current_SNR(a:SNR)
+endfunction
+
+" # Main function {{{2
+function! lh#UT#run(bang,...)
+  " 1- clear the errors table
+  let must_keep = a:bang == "!"
+  if ! must_keep
+    call s:errors.clear()
+  endif
+
+  try 
+    " 2- define commands
+    call s:DefineCommands()
+
+    " 3- run every test
+    let rtp = '.,'.&rtp
+    let files = []
+    for file in a:000
+      let lFile = lh#path#glob_as_list(rtp, file)
+      if len(lFile) > 0
+	call add(files, lFile[0])
+      endif
+    endfor
+
+    for file in files
+      call s:RunOneFile(file)
+    endfor
+  finally
+    call s:UnDefineCommands()
+    call s:errors.display()
+  endtry
+
+  " 3- Open the quickfix
+endfunction
+
+"------------------------------------------------------------------------
+let &cpo=s:cpo_save
+"=============================================================================
+" vim600: set fdm=marker:
+" VIM: let g:UTfiles='tests/lh/UT*.vim'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/ut/autoload/should/be.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,68 @@
+"=============================================================================
+" $Id: be.vim 193 2010-05-17 23:10:03Z luc.hermitte $
+" File:		autoload/should/be.vim                            {{{1
+" Author:	Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
+"		<URL:http://hermitte.free.fr/vim/>
+" Version:	0.0.3
+" Created:	23rd Feb 2009
+" Last Update:	$Date: 2010-05-17 19:10:03 -0400 (Mon, 17 May 2010) $
+"------------------------------------------------------------------------
+" Description:	
+" 	UT & tAssert API
+" 
+"------------------------------------------------------------------------
+" Installation:	
+" 	Drop this file into {rtp}/autoload/should
+" History:	
+" 	
+" TODO:		«missing features»
+" }}}1
+"=============================================================================
+
+let s:cpo_save=&cpo
+set cpo&vim
+"------------------------------------------------------------------------
+
+" ## Functions {{{1
+" # Debug {{{2
+function! should#be#verbose(level)
+  let s:verbose = a:level
+endfunction
+
+function! s:Verbose(expr)
+  if exists('s:verbose') && s:verbose
+    echomsg a:expr
+  endif
+endfunction
+
+function! should#be#debug(expr)
+  return eval(a:expr)
+endfunction
+
+
+" # Convinience functions for tAssert/UT {{{2
+function! should#be#list(var)
+  return type(a:var) == type([])
+endfunction
+function! should#be#number(var)
+  return type(a:var) == type(42)
+endfunction
+function! should#be#string(var)
+  return type(a:var) == type('')
+endfunction
+function! should#be#dict(var)
+  return type(a:var) == type({})
+endfunction
+function! should#be#float(var)
+  return type(a:var) == type(0.1)
+endfunction
+function! should#be#funcref(var)
+  return type(a:var) == type(function('exists'))
+endfunction
+
+
+
+"------------------------------------------------------------------------
+let &cpo=s:cpo_save
+"=============================================================================
+" vim600: set fdm=marker:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/ut/doc/UT.txt	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,165 @@
+*UT.txt*                Unit Testing Framework for Vim (v0.0.3)
+                        For Vim version 7+.    Last change: $Date: 2010-05-17 19:10:03 -0400 (Mon, 17 May 2010) $
+
+                        By Luc Hermitte
+                        hermitte {at} free {dot} fr
+
+
+------------------------------------------------------------------------------
+CONTENTS                                            *UT-contents*      {{{1
+    |UT-presentation| Presentation
+    |UT-usage|        Usage
+    |UT-API|          UT API
+    |UT-examples|     Examples
+    |UT-todo|         Bugs to fix and futur enhancements to come
+    |UT-design|       Design choices
+    |UT-others|       Other tests related plugins for vim
+    |add-local-help|  Instructions on installing this file
+
+
+------------------------------------------------------------------------------
+PRESENTATION                                        *UT-presentation*  {{{1
+UT is another Test Unit Framework for Vim, which main particularity is to fill
+the |quickfix| window with the assertion failures.
+
+Features~
+- Assertion failures are reported in the |quickfix| window
+- Assertion syntax is simple, check Tom Link's suite, it's the same
+- Supports banged ":Assert!" to stop processing a given test on failed
+  assertions
+- All the |s:Test()| functions of a suite are executed (almost)
+  independently (i.e., a critical ":Assert!" failure will stop the Test of
+  the function, and |lh#UT| will proceed to the next |s:Test()| function
+- Lightweight and simple to use: there is only one command defined, all the
+  other definitions are kept in an autoload plugin.
+- A suite == a file
+- Several |s:Test()| functions per suite
+- +optional |s:Setup()|, |s:Teardown()|
+- Supports |:Comments|
+- |local-function|s, |script-variable|s, and |local-variable|s are supported
+- Takes advantage of |BuildToolsWrapper|'s |:Copen| command if installed
+- Counts successful tests and not successful assertions
+- Short-cuts to run the Unit Tests associated to a given vim script; Relies
+  on: |Let-Modeline|, |local_vimrc|/|project.vim| to set |g:UTfiles| (space
+  separated list of glob-able paths), and on |lhvl#path|.
+- Command to exclude, or specify the tests to play => |:UTPlay|, |UTIgnore|
+
+Requirements~
+This suite requires Vim 7.1 and |lh-vim-lib| v2.2.0+.
+
+
+------------------------------------------------------------------------------
+USAGE                                               *UT-usage*         {{{1
+First, create a new vim script, it will be a Unit Testing Suite.
+
+                                                    *:UTSuite*
+One of the first lines must contain >
+  UTSuite Some intelligible name for the suite
+<
+                                                    *:Assert*
+Then you are free to directly assert anything you wish as long as it is a
+valid vim |expression|, e.g. >
+    Assert 1 > 2
+    Assert 1 > 0
+    Assert s:foo > s:Bar(g:var + 28) / strlen("foobar")
+or to define as many independent tests as you wish.
+
+                                                    *:Comment*
+Comments may be added to the |quickfix| report thanks to the |:Comment|
+fake command.
+                                                    *s:Test()*
+A test is a function with a name starting with |s:Test|. Even if a test
+critically fails, the next test will be executed, e.g. >
+    function s:Test1()
+      let var = SomeFucntion()
+      Assert! type(var) == type(0)
+      Assert var < 42
+      Assert! var > 0 
+
+      " Some other code that won't be executed if the previous assertion failed
+      let i = var / 42.0
+      Comment This comment may never be displayed if {var} is negative or not a number
+    endfunction
+
+    function s:Test2()
+      Assert s:what != Ever()
+    endfunction
+<
+                                                    *s:Setup()* *s:Teardown()*
+If you wish to see a set-up function executed before each test, define the
+|s:Setup()| function.
+
+If you wish to see a clean-up function executed after each test, define the
+|s:Teardown()| function.
+
+                                                    *:UTRun*
+Finally run |:UTRun| on your test script (filename), and ... debug your failed
+assertions from the |quickfix| window.
+
+
+------------------------------------------------------------------------------
+UT API                                               *UT-API*          {{{1
+
+*should#be#dict()*    returns whether the parameter is a |Dictionary|
+*should#be#float()*   returns whether the parameter is a |float|
+*should#be#funcref()* returns whether the parameter is a |Funcref|
+*should#be#list()*    returns whether the parameter is a |List|
+*should#be#number()*  returns whether the parameter is a |expr-number|
+*should#be#string()*  returns whether the parameter is a |expr-string|
+
+
+------------------------------------------------------------------------------
+EXAMPLES                                             *UT-examples*     {{{1
+See:
+- {rtp}/tests/lh/UT.vim tests/lh/UT.vim for a classical test,
+- {rtp}/tests/lh/UT-fixtures.vim tests/lh/UT-fixtures.vim for a test with
+  fixtures.
+
+
+------------------------------------------------------------------------------
+TO DO                                                *UT-todo*         {{{1
+- Add |'efm'| for VimL errors like the one produced by >
+    :Assert 0 + [0]
+- Check UT works fine under windows (where paths have spaces, etc), and on
+  UTF-8 files
+- Simplify "s:errors" functions
+- Merge with Tom Link's tAssert plugin? (the UI is quite different)
+- |:AssertEquals| that shows the name of both expressions and their values as
+  well -- a correct distinction of both parameters will be tricky with regexes
+  ; using functions will loose either the name, or the value in case of
+  local/script variables use ; we need macros /ŕ la C/...
+- Support Embedded comments like for instance: >
+    Assert 1 == 1 " 1 must value 1
+- Ways to test buffers produced
+- Always execute |s:Teardown()| -- move its call to a |:finally| bloc
+- Find a way to prevent the potential script scope pollution
+
+
+------------------------------------------------------------------------------
+DESIGN CHOICES                                       *UT-design*       {{{1
+The assertions supported by this plugin are expected to be made in a Unit
+Testing file, they are not to be used in regular VimL scripts as a /Design by
+Contract/ tool. Check Thomas Link's plugin, it is much more suited for that
+kind of assertions.
+
+In order to be able to produce the |quickfix| entries, the plugin first parses
+the Unit Test file to complete all |:Assert| occurrences with extra
+information about the line number where the assertion is made.
+
+
+------------------------------------------------------------------------------
+OTHER TESTS RELATED PLUGINS FOR VIM                  *UT-others*       {{{1
+You may also want to have a look at:
+- Tom Link's |tAssert| plugin
+  http://www.vim.org/scripts/script.php?script_id=1730 
+- Staale Flock's |vimUnit| plugin
+  http://www.vim.org/scripts/script.php?script_id=1125 
+- Meikel Brandmeyer's |vimTAP| plugin
+  http://www.vim.org/scripts/script.php?script_id=2213 
+
+
+------------------------------------------------------------------------------
+ © Luc Hermitte, 2010, http://code.google.com/p/lh-vim/
+ $Id: UT.txt 193 2010-05-17 23:10:03Z luc.hermitte $
+ VIM: let b:VS_language = 'american' 
+ vim:ts=8:sw=4:tw=80:fo=tcq2:isk=!-~,^*,^\|,^\":ft=help:fdm=marker:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/ut/ftplugin/vim/vim_UT.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,67 @@
+"=============================================================================
+" $Id: vim_UT.vim 193 2010-05-17 23:10:03Z luc.hermitte $
+" File:		ftplugin/vim/vim_UT.vim                              {{{1
+" Author:	Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
+"		<URL:http://code.google.com/p/lh-vim/>
+let s:k_version = 003
+" Version:	0.0.3
+" Created:	20th Feb 2009
+" Last Update:	$Date: 2010-05-17 19:10:03 -0400 (Mon, 17 May 2010) $
+"------------------------------------------------------------------------
+" Description:	Yet Another Unit Testing Framework for Vim 
+" - Defines <F7> as :UTRun {targets=g:UTfiles}
+" 
+"------------------------------------------------------------------------
+" Installation:	«install details»
+" History:	«history»
+" TODO:		«missing features»
+" }}}1
+"=============================================================================
+
+" Buffer-local Definitions {{{1
+" Avoid local reinclusion {{{2
+if &cp || (exists("b:loaded_ftplug_vim_UT") && !exists('g:force_reload_ftplug_vim_UT'))
+  finish
+endif
+let b:loaded_ftplug_vim_UT = s:k_version
+let s:cpo_save=&cpo
+set cpo&vim
+" Avoid local reinclusion }}}2
+
+"------------------------------------------------------------------------
+" Local mappings {{{2
+
+nnoremap <buffer> <silent> <Plug>UTMake :call <sid>UTMake()<cr>
+
+let s:key = lh#option#get('UTMake_key', '<F7>')
+exe 'imap <buffer> '.s:key.' <c-\><c-n><Plug>UTMake'
+exe 'vmap <buffer> '.s:key.' <c-\><c-n><Plug>UTMake'
+exe 'nmap <buffer> '.s:key.' <Plug>UTMake'
+
+"=============================================================================
+" Global Definitions {{{1
+" Avoid global reinclusion {{{2
+if &cp || (exists("g:loaded_ftplug_vim_UT") && !exists('g:force_reload_ftplug_vim_UT'))
+  let &cpo=s:cpo_save
+  finish
+endif
+let g:loaded_ftplug_vim_UT = s:k_version
+" Avoid global reinclusion }}}2
+"------------------------------------------------------------------------
+" Functions {{{2
+
+function! s:UTMake()
+  let files = lh#option#get('UTfiles', '%')
+  echo 'update|source '.expand('%').'|UTRun '.files
+  update
+  so%
+  exe 'UTRun '.files
+endfunction
+
+
+" Functions }}}2
+"------------------------------------------------------------------------
+let &cpo=s:cpo_save
+"=============================================================================
+" vim600: set fdm=marker:
+" VIM: let g:UTfiles='tests/lh/UT*.vim'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/ut/mkVba/mk-UT.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,32 @@
+"=============================================================================
+" $Id: mk-UT.vim 194 2010-05-17 23:26:14Z luc.hermitte $
+" File:		mk-UT.vim
+" Author:	Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
+"		<URL:http://hermitte.free.fr/vim/>
+" Version:	0.0.3
+let s:version = '0.0.3'
+" Created:	19th Feb 2009
+" Last Update:	$Date: 2010-05-17 19:26:14 -0400 (Mon, 17 May 2010) $
+"------------------------------------------------------------------------
+cd <sfile>:p:h
+try 
+  let save_rtp = &rtp
+  let &rtp = expand('<sfile>:p:h:h').','.&rtp
+  exe '22,$MkVimball! UT-'.s:version
+  set modifiable
+  set buftype=
+finally
+  let &rtp = save_rtp
+endtry
+finish
+UT.README
+autoload/lh/UT.vim
+autoload/should.vim
+autoload/should/be.vim
+doc/UT.txt
+ftplugin/vim/vim_UT.vim
+mkVba/mk-UT.vim
+plugin/UT.vim
+tests/lh/UT-fixtures.vim
+tests/lh/UT.vim
+tests/lh/assert.vim
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/ut/plugin/UT.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,48 @@
+"=============================================================================
+" $Id: UT.vim 193 2010-05-17 23:10:03Z luc.hermitte $
+" File:		plugin/UT.vim                                        {{{1
+" Author:	Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
+"		<URL:http://code.google.com/p/lh-vim/>
+let s:k_version = 003
+" Version:	0.0.3
+" Created:	11th Feb 2009
+" Last Update:	$Date: 2010-05-17 19:10:03 -0400 (Mon, 17 May 2010) $
+"------------------------------------------------------------------------
+" Description:	Yet Another Unit Testing Framework for Vim 
+" 
+"------------------------------------------------------------------------
+" Installation:	
+" 	Drop the file into {rtp}/plugin/lh/
+" History:	
+" 	Strongly inspired by Tom Link's tAssert
+" TODO:		«missing features»
+" }}}1
+"=============================================================================
+
+" Avoid global reinclusion {{{1
+if &cp || (exists("g:loaded_UT") && !exists('g:force_reload_UT'))
+  finish
+endif
+let g:loaded_UT = s:k_version
+let s:cpo_save=&cpo
+set cpo&vim
+" Avoid global reinclusion }}}1
+"------------------------------------------------------------------------
+" Commands and Mappings {{{1
+
+" Real commands (used to call UT files)
+"command! UTRun {filenames}
+command! -bang -nargs=+ -complete=file UTRun :call lh#UT#run("<bang>",<f-args>)
+
+" Fake commands (used in UT files)
+"command UTSuite {expression} [#{comments}]
+command! -nargs=* UTSuite :echoerr "Use :UTRun and not :source on this script"<bar>finish
+"command Assert {expression} [#{comments}]
+
+
+" Commands and Mappings }}}1
+"------------------------------------------------------------------------
+let &cpo=s:cpo_save
+"=============================================================================
+" vim600: set fdm=marker:
+" VIM: let g:UTfiles='tests/lh/UT*.vim'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/ut/tests/lh/UT-fixtures.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,58 @@
+"=============================================================================
+" $Id: UT-fixtures.vim 193 2010-05-17 23:10:03Z luc.hermitte $
+" File:		tests/lh/UT-fixtures.vim                                  {{{1
+" Author:	Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
+"		<URL:http://hermitte.free.fr/vim/>
+" Version:	0.0.1
+" Created:	11th Feb 2009
+" Last Update:	$Date: 2010-05-17 19:10:03 -0400 (Mon, 17 May 2010) $
+"------------------------------------------------------------------------
+" Description:	UnitTests for the UT plugin. 
+" - Test fixtures
+" 
+"------------------------------------------------------------------------
+" Installation:	«install details»
+" History:	«history»
+" TODO:		«missing features»
+" }}}1
+"=============================================================================
+
+let s:cpo_save=&cpo
+set cpo&vim
+"------------------------------------------------------------------------
+UTSuite [lh#UT] Testing fixtures
+
+let s:v1 = 0
+let s:v2 = 0
+
+function! s:Setup()
+  Assert! exists('s:v1')
+  Assert! exists('s:v2')
+  let s:v1 += 1
+  let s:v2 += 1
+endfunction
+
+function! s:Teardown()
+  let s:v1 = 0
+endfunction
+
+function! s:TestSetup()
+  Comment "First test weither s:v1 and g:v2 are set to 1"
+  " Assert0 s:v1 == 1
+  Assert s:v1 == 1
+  Assert s:v2 == 1
+endfunction
+
+function! s:TestTeardown()
+  Comment "Second test weither only s:v1 is incremented, while g:v2 is set to 1"
+  Assert s:v1 == 1
+  Assert s:v2 == 2
+endfunction
+
+" UTPlay TestTeardown
+UTIgnore TestTeardown
+
+"------------------------------------------------------------------------
+let &cpo=s:cpo_save
+"=============================================================================
+" vim600: set fdm=marker:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/bundled/ut/tests/lh/UT.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,73 @@
+"=============================================================================
+" $Id: UT.vim 193 2010-05-17 23:10:03Z luc.hermitte $
+" File:		tests/lh/UT.vim                                      {{{1
+" Author:	Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
+"		<URL:http://hermitte.free.fr/vim/>
+" Version:	0.0.1
+" Created:	11th Feb 2009
+" Last Update:	$Date: 2010-05-17 19:10:03 -0400 (Mon, 17 May 2010) $
+"------------------------------------------------------------------------
+" Description:	UnitTests for the UT plugin. 
+" - Tests global assertions
+" - Tests assertions definied in tests (functions s:Test)
+" 
+"------------------------------------------------------------------------
+" Installation:	«install details»
+" History:	«history»
+" TODO:		«missing features»
+" }}}1
+"=============================================================================
+
+let s:cpo_save=&cpo
+set cpo&vim
+"------------------------------------------------------------------------
+UTSuite [lh#UT] Testing global and local assertions
+
+Assert 1 == 1
+Assert 1 != 42
+Assert 1 < 20
+Assert 1 > 20
+
+let st = "string"
+Assert st =~ 'str'
+Assert st !~ 'str'
+Assert st == 'str'
+Assert st != 'str'
+Assert st == 0
+" Assert 0 + [0]
+
+function! s:One()
+  return 1
+endfunction
+Assert s:One() == 1
+
+"------------------------------------------------------------------------
+function! s:TestOK()
+  Comment "TestOK"
+  Assert! 1 == 1
+  Assert 1 == 1
+  Assert repeat('1', 5) == '11111'
+  Assert! repeat('1', 5) == '11111'
+endfunction
+
+"------------------------------------------------------------------------
+function! s:TestCriticalNOK()
+  Comment "TestCriticalNOK"
+  Assert! 1 == 0
+  Assert repeat('1', 5) == '1111'
+endfunction
+
+"------------------------------------------------------------------------
+function! s:TestNOK()
+  Comment "TestNOK"
+  Assert 0 == 1
+  Assert repeat('1', 5) == '1111'
+endfunction
+
+function! s:Foo()
+endfunction
+"------------------------------------------------------------------------
+"------------------------------------------------------------------------
+let &cpo=s:cpo_save
+"=============================================================================
+" vim600: set fdm=marker:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/run-tests.sh	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+
+set -e
+
+vim -u vimrc_test -c ":UTRun $1"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-toggle.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,131 @@
+let s:cpo_save=&cpo
+set cpo&vim
+
+UTSuite [Gundo] Testing Toggling
+
+function! s:Setup()"{{{
+    exec 'edit test'
+    exec bufwinnr(bufnr('test')) . 'wincmd w'
+endfunction"}}}
+function! s:Teardown()"{{{
+    if bufwinnr(bufnr('__Gundo__')) != -1
+        exec bufwinnr(bufnr('__Gundo__')) . 'wincmd w'
+        quit
+    endif
+    if bufwinnr(bufnr('__Gundo_Preview__')) != -1
+        exec bufwinnr(bufnr('__Gundo_Preview__')) . 'wincmd w'
+        quit
+    endif
+    if bufnr('__Gundo__') != -1
+        exec 'bwipeout ' . bufnr('__Gundo__')
+    endif
+    if bufnr('__Gundo_Preview__') != -1
+        exec 'bwipeout ' . bufnr('__Gundo_Preview__')
+    endif
+    if bufnr('test') != -1
+        exec 'bwipeout ' . bufnr('test')
+    endif
+    if bufnr('test2') != -1
+        exec 'bwipeout ' . bufnr('test2')
+    endif
+endfunction"}}}
+function! s:Goto(buffername)"{{{
+    exec bufwinnr(bufnr(a:buffername)) . 'wincmd w'
+endfunction"}}}
+
+function! s:TestToggleBasic()"{{{
+    " Make sure we're starting from scratch.
+    Assert bufnr('__Gundo__') == -1
+    Assert bufnr('__Gundo_Preview__') == -1
+    Assert bufwinnr(bufnr('__Gundo__')) == -1
+    Assert bufwinnr(bufnr('__Gundo_Preview__')) == -1
+
+    " Open Gundo
+    GundoToggle
+
+    " Buffers and windows should exist.
+    Assert bufnr('__Gundo__') != -1
+    Assert bufnr('__Gundo_Preview__') != -1
+    Assert bufwinnr(bufnr('__Gundo__')) != -1
+    Assert bufwinnr(bufnr('__Gundo_Preview__')) != -1
+
+    " We should be in the Gundo pane.
+    Assert expand('%') == '__Gundo__'
+
+    " Close Gundo
+    GundoToggle
+
+    " Windows should have been closed, but buffers should remain.
+    Assert bufnr('__Gundo__') != -1
+    Assert bufnr('__Gundo_Preview__') != -1
+    Assert bufwinnr(bufnr('__Gundo__')) == -1
+    Assert bufwinnr(bufnr('__Gundo_Preview__')) == -1
+endfunction"}}}
+
+function! s:TestToggleWhenMoved()"{{{
+    " Make sure we're starting from scratch.
+    Assert bufnr('__Gundo__') == -1
+    Assert bufnr('__Gundo_Preview__') == -1
+    Assert bufwinnr(bufnr('__Gundo__')) == -1
+    Assert bufwinnr(bufnr('__Gundo_Preview__')) == -1
+
+    " Open Gundo
+    GundoToggle
+
+    call s:Goto('test')
+    Assert expand('%') == 'test'
+
+    " Close Gundo
+    GundoToggle
+
+    " Windows should have been closed, but buffers should remain.
+    Assert bufnr('__Gundo__') != -1
+    Assert bufnr('__Gundo_Preview__') != -1
+    Assert bufwinnr(bufnr('__Gundo__')) == -1
+    Assert bufwinnr(bufnr('__Gundo_Preview__')) == -1
+
+    " Open Gundo
+    GundoToggle
+
+    call s:Goto('__Gundo_Preview__')
+    Assert expand('%') == '__Gundo_Preview__'
+
+    " Close Gundo
+    GundoToggle
+
+    " Windows should have been closed, but buffers should remain.
+    Assert bufnr('__Gundo__') != -1
+    Assert bufnr('__Gundo_Preview__') != -1
+    Assert bufwinnr(bufnr('__Gundo__')) == -1
+    Assert bufwinnr(bufnr('__Gundo_Preview__')) == -1
+endfunction"}}}
+
+function! s:TestToggleReturnToTarget()"{{{
+    " Make sure we're starting from scratch.
+    Assert bufnr('__Gundo__') == -1
+    Assert bufnr('__Gundo_Preview__') == -1
+    Assert bufwinnr(bufnr('__Gundo__')) == -1
+    Assert bufwinnr(bufnr('__Gundo_Preview__')) == -1
+
+    exec 'new test2'
+    call s:Goto('test')
+
+    " Toggle Gundo
+    GundoToggle
+    GundoToggle
+
+    " We should be returned to test
+    Assert expand('%') == 'test'
+
+    " Move to test2
+    call s:Goto('test2')
+
+    " Toggle Gundo
+    GundoToggle
+    GundoToggle
+
+    " We should be returned to test2
+    Assert expand('%') == 'test2'
+endfunction"}}}
+
+let &cpo=s:cpo_save
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/vim_test/autoload/lh	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,1 @@
+/Users/sjl/src/gundo.vim/tests/bundled/lh-vim-lib/autoload/lh
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/vim_test/colors/desert.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,108 @@
+" Vim color file
+" Maintainer:	Hans Fugal <hans@fugal.net>
+" Last Change:	$Date: 2004/06/13 19:30:30 $
+" Last Change:	$Date: 2004/06/13 19:30:30 $
+" URL:		http://hans.fugal.net/vim/colors/desert.vim
+" Version:	$Id: desert.vim,v 1.1 2004/06/13 19:30:30 vimboss Exp $
+
+" cool help screens
+" :he group-name
+" :he highlight-groups
+" :he cterm-colors
+
+set background=dark
+if version > 580
+    " no guarantees for version 5.8 and below, but this makes it stop
+    " complaining
+    hi clear
+    if exists("syntax_on")
+	syntax reset
+    endif
+endif
+let g:colors_name="desert"
+
+hi Normal	guifg=White guibg=grey20
+
+" highlight groups
+hi Cursor	guibg=khaki guifg=slategrey
+"hi CursorIM
+"hi Directory
+"hi DiffAdd
+"hi DiffChange
+"hi DiffDelete
+"hi DiffText
+"hi ErrorMsg
+hi VertSplit	guibg=#c2bfa5 guifg=grey50 gui=none
+hi Folded	guibg=grey30 guifg=gold
+hi FoldColumn	guibg=grey30 guifg=tan
+hi IncSearch	guifg=slategrey guibg=khaki
+"hi LineNr
+hi ModeMsg	guifg=goldenrod
+hi MoreMsg	guifg=SeaGreen
+hi NonText	guifg=LightBlue guibg=grey30
+hi Question	guifg=springgreen
+hi Search	guibg=peru guifg=wheat
+hi SpecialKey	guifg=yellowgreen
+hi StatusLine	guibg=#c2bfa5 guifg=black gui=none
+hi StatusLineNC	guibg=#c2bfa5 guifg=grey50 gui=none
+hi Title	guifg=indianred
+hi Visual	gui=none guifg=khaki guibg=olivedrab
+"hi VisualNOS
+hi WarningMsg	guifg=salmon
+"hi WildMenu
+"hi Menu
+"hi Scrollbar
+"hi Tooltip
+
+" syntax highlighting groups
+hi Comment	guifg=SkyBlue
+hi Constant	guifg=#ffa0a0
+hi Identifier	guifg=palegreen
+hi Statement	guifg=khaki
+hi PreProc	guifg=indianred
+hi Type		guifg=darkkhaki
+hi Special	guifg=navajowhite
+"hi Underlined
+hi Ignore	guifg=grey40
+"hi Error
+hi Todo		guifg=orangered guibg=yellow2
+
+" color terminal definitions
+hi SpecialKey	ctermfg=darkgreen
+hi NonText	cterm=bold ctermfg=darkblue
+hi Directory	ctermfg=darkcyan
+hi ErrorMsg	cterm=bold ctermfg=7 ctermbg=1
+hi IncSearch	cterm=NONE ctermfg=yellow ctermbg=green
+hi Search	cterm=NONE ctermfg=grey ctermbg=blue
+hi MoreMsg	ctermfg=darkgreen
+hi ModeMsg	cterm=NONE ctermfg=brown
+hi LineNr	ctermfg=3
+hi Question	ctermfg=green
+hi StatusLine	cterm=bold,reverse
+hi StatusLineNC cterm=reverse
+hi VertSplit	cterm=reverse
+hi Title	ctermfg=5
+hi Visual	cterm=reverse
+hi VisualNOS	cterm=bold,underline
+hi WarningMsg	ctermfg=1
+hi WildMenu	ctermfg=0 ctermbg=3
+hi Folded	ctermfg=darkgrey ctermbg=NONE
+hi FoldColumn	ctermfg=darkgrey ctermbg=NONE
+hi DiffAdd	ctermbg=4
+hi DiffChange	ctermbg=5
+hi DiffDelete	cterm=bold ctermfg=4 ctermbg=6
+hi DiffText	cterm=bold ctermbg=1
+hi Comment	ctermfg=darkcyan
+hi Constant	ctermfg=brown
+hi Special	ctermfg=5
+hi Identifier	ctermfg=6
+hi Statement	ctermfg=3
+hi PreProc	ctermfg=5
+hi Type		ctermfg=2
+hi Underlined	cterm=underline ctermfg=5
+hi Ignore	cterm=bold ctermfg=7
+hi Ignore	ctermfg=darkgrey
+hi Error	cterm=bold ctermfg=7 ctermbg=1
+
+
+"vim: sw=4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/vim_test/ftplugin/vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,1 @@
+/Users/sjl/src/gundo.vim/tests/bundled/ut/ftplugin/vim
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/vim_test/macros/menu-map.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,1 @@
+/Users/sjl/src/gundo.vim/tests/bundled/lh-vim-lib/macros/menu-map.vim
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/vim_test/plugin/UT.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,1 @@
+/Users/sjl/src/gundo.vim/tests/bundled/ut/plugin/UT.vim
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/vim_test/plugin/gundo.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,1 @@
+/Users/sjl/src/gundo.vim/plugin/gundo.vim
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/vim_test/plugin/let.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,1 @@
+/Users/sjl/src/gundo.vim/tests/bundled/lh-vim-lib/plugin/let.vim
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/vim_test/plugin/lhvl.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,1 @@
+/Users/sjl/src/gundo.vim/tests/bundled/lh-vim-lib/plugin/lhvl.vim
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/vim_test/plugin/ui-functions.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,1 @@
+/Users/sjl/src/gundo.vim/tests/bundled/lh-vim-lib/plugin/ui-functions.vim
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/vim_test/plugin/words_tools.vim	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,1 @@
+/Users/sjl/src/gundo.vim/tests/bundled/lh-vim-lib/plugin/words_tools.vim
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/vimrc_test	Wed Nov 10 19:52:08 2010 -0500
@@ -0,0 +1,5 @@
+set nocompatible
+set runtimepath=vim_test
+filetype plugin on
+nnoremap q :qa!<cr>
+color desert