aboutsummaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorSilvio Rhatto <rhatto@riseup.net>2013-01-13 16:59:21 -0200
committerSilvio Rhatto <rhatto@riseup.net>2013-01-13 16:59:21 -0200
commit64d36fd195250d50f92ef0c4b4952bee720f8e2c (patch)
tree39e995718ac4f0583e9364b4619609fb4aaa6418 /modules
parent414774ceb5d9e60ede446ec1d89a5086429cc0bf (diff)
downloaddotfiles-64d36fd195250d50f92ef0c4b4952bee720f8e2c.tar.gz
dotfiles-64d36fd195250d50f92ef0c4b4952bee720f8e2c.tar.bz2
Adding more vim stuff
Diffstat (limited to 'modules')
-rw-r--r--modules/vim/vim/after/ftplugin/asp_snippets.vim17
-rw-r--r--modules/vim/vim/after/plugin/snipMate.vim35
-rw-r--r--modules/vim/vim/autoload/pathogen.vim245
-rw-r--r--modules/vim/vim/autoload/snipMate.vim433
m---------modules/vim/vim/bundle/nerdtree0
-rw-r--r--modules/vim/vim/doc/NERD_tree.txt1222
-rw-r--r--modules/vim/vim/doc/bufexplorer.txt442
-rw-r--r--modules/vim/vim/doc/git-vim.txt95
-rw-r--r--modules/vim/vim/doc/indexer.txt211
-rw-r--r--modules/vim/vim/doc/project.txt710
-rw-r--r--modules/vim/vim/doc/snipMate.txt286
-rwxr-xr-xmodules/vim/vim/doc/taglist.txt1501
-rw-r--r--modules/vim/vim/doc/tags300
-rw-r--r--modules/vim/vim/doc/vcscommand.txt835
-rw-r--r--modules/vim/vim/filetype.vim23
-rw-r--r--modules/vim/vim/ftplugin/html_snip_helper.vim10
-rw-r--r--modules/vim/vim/plugin/Rename.vim27
-rw-r--r--modules/vim/vim/plugin/bufexplorer.vim869
-rw-r--r--modules/vim/vim/plugin/git.vim372
-rw-r--r--modules/vim/vim/plugin/indexer.vim.disabled672
-rw-r--r--modules/vim/vim/plugin/project.vim1293
-rw-r--r--modules/vim/vim/plugin/snipMate.vim247
-rw-r--r--modules/vim/vim/plugin/startshell_mapping.vim.disabled36
-rw-r--r--modules/vim/vim/plugin/taglist.vim4546
-rw-r--r--modules/vim/vim/plugin/vcsbzr.vim262
-rw-r--r--modules/vim/vim/plugin/vcscommand.vim1427
-rw-r--r--modules/vim/vim/plugin/vcscvs.vim449
-rw-r--r--modules/vim/vim/plugin/vcsgit.vim247
-rw-r--r--modules/vim/vim/plugin/vcshg.vim273
-rw-r--r--modules/vim/vim/plugin/vcssvk.vim257
-rw-r--r--modules/vim/vim/plugin/vcssvn.vim284
-rw-r--r--modules/vim/vim/snippets/_.snippets7
-rw-r--r--modules/vim/vim/snippets/autoit.snippets66
-rw-r--r--modules/vim/vim/snippets/c.snippets110
-rw-r--r--modules/vim/vim/snippets/cpp.snippets30
-rw-r--r--modules/vim/vim/snippets/html.snippets190
-rw-r--r--modules/vim/vim/snippets/java.snippets78
-rw-r--r--modules/vim/vim/snippets/javascript.snippets74
-rw-r--r--modules/vim/vim/snippets/mako.snippets54
-rw-r--r--modules/vim/vim/snippets/objc.snippets184
-rw-r--r--modules/vim/vim/snippets/perl.snippets91
-rw-r--r--modules/vim/vim/snippets/php.snippets9397
-rw-r--r--modules/vim/vim/snippets/python.snippets86
-rw-r--r--modules/vim/vim/snippets/ruby.snippets420
-rw-r--r--modules/vim/vim/snippets/sh.snippets28
-rw-r--r--modules/vim/vim/snippets/snippet.snippets7
-rw-r--r--modules/vim/vim/snippets/tcl.snippets92
-rw-r--r--modules/vim/vim/snippets/tex.snippets115
-rw-r--r--modules/vim/vim/snippets/vim.snippets32
-rw-r--r--modules/vim/vim/snippets/zsh.snippets58
-rw-r--r--modules/vim/vim/syntax/CVSAnnotate.vim45
-rw-r--r--modules/vim/vim/syntax/SVKAnnotate.vim42
-rw-r--r--modules/vim/vim/syntax/SVNAnnotate.vim40
-rw-r--r--modules/vim/vim/syntax/cvsannotate.vim45
-rw-r--r--modules/vim/vim/syntax/git-diff.vim8
-rw-r--r--modules/vim/vim/syntax/git-log.vim3
-rw-r--r--modules/vim/vim/syntax/git-status.vim18
-rw-r--r--modules/vim/vim/syntax/gitannotate.vim44
-rw-r--r--modules/vim/vim/syntax/hgannotate.vim40
-rw-r--r--modules/vim/vim/syntax/ikiwiki.vim71
-rw-r--r--modules/vim/vim/syntax/mkd.vim86
-rw-r--r--modules/vim/vim/syntax/nginx.vim664
-rw-r--r--modules/vim/vim/syntax/puppet.vim87
-rw-r--r--modules/vim/vim/syntax/remind.vim79
-rw-r--r--modules/vim/vim/syntax/rest.vim169
-rw-r--r--modules/vim/vim/syntax/snippet.vim19
-rw-r--r--modules/vim/vim/syntax/svkannotate.vim42
-rw-r--r--modules/vim/vim/syntax/svnannotate.vim40
-rw-r--r--modules/vim/vim/syntax/vcscommit.vim31
69 files changed, 30318 insertions, 0 deletions
diff --git a/modules/vim/vim/after/ftplugin/asp_snippets.vim b/modules/vim/vim/after/ftplugin/asp_snippets.vim
new file mode 100644
index 0000000..4fdc8a8
--- /dev/null
+++ b/modules/vim/vim/after/ftplugin/asp_snippets.vim
@@ -0,0 +1,17 @@
+if !exists('loaded_snippet') || &cp
+ finish
+endif
+
+let st = g:snip_start_tag
+let et = g:snip_end_tag
+let cd = g:snip_elem_delim
+
+exec "Snippet rr Response.Redirect(".st."to".et.")".st.et.""
+exec "Snippet app Application(\"".st.et."\")".st.et.""
+exec "Snippet forin For ".st."var".et." in ".st."array".et."<CR>".st.et."<CR>Next<CR>".st.et.""
+exec "Snippet ifelse If ".st."condition".et." Then<CR>".st.et."<CR>Else<CR>".st.et."<CR>End if<CR>".st.et.""
+exec "Snippet rw Response.Write ".st.et.""
+exec "Snippet sess Session(\"".st.et."\")".st.et.""
+exec "Snippet rf Request.Form(\"".st.et."\")".st.et.""
+exec "Snippet rq Request.QueryString(\"".st.et."\")".st.et.""
+exec "Snippet while While ".st."NOT".et." ".st."condition".et."<CR>".st.et."<CR>Wend<CR>".st.et.""
diff --git a/modules/vim/vim/after/plugin/snipMate.vim b/modules/vim/vim/after/plugin/snipMate.vim
new file mode 100644
index 0000000..03e79ae
--- /dev/null
+++ b/modules/vim/vim/after/plugin/snipMate.vim
@@ -0,0 +1,35 @@
+" These are the mappings for snipMate.vim. Putting it here ensures that it
+" will be mapped after other plugins such as supertab.vim.
+if !exists('loaded_snips') || exists('s:did_snips_mappings')
+ finish
+endif
+let s:did_snips_mappings = 1
+
+ino <silent> <tab> <c-r>=TriggerSnippet()<cr>
+snor <silent> <tab> <esc>i<right><c-r>=TriggerSnippet()<cr>
+ino <silent> <s-tab> <c-r>=BackwardsSnippet()<cr>
+snor <silent> <s-tab> <esc>i<right><c-r>=BackwardsSnippet()<cr>
+ino <silent> <c-r><tab> <c-r>=ShowAvailableSnips()<cr>
+
+" The default mappings for these are annoying & sometimes break snipMate.
+" You can change them back if you want, I've put them here for convenience.
+snor <bs> b<bs>
+snor <right> <esc>a
+snor <left> <esc>bi
+snor ' b<bs>'
+snor ` b<bs>`
+snor % b<bs>%
+snor U b<bs>U
+snor ^ b<bs>^
+snor \ b<bs>\
+snor <c-x> b<bs><c-x>
+
+" By default load snippets in snippets_dir
+if empty(snippets_dir)
+ finish
+endif
+
+call GetSnippets(snippets_dir, '_') " Get global snippets
+
+au FileType * if &ft != 'help' | call GetSnippets(snippets_dir, &ft) | endif
+" vim:noet:sw=4:ts=4:ft=vim
diff --git a/modules/vim/vim/autoload/pathogen.vim b/modules/vim/vim/autoload/pathogen.vim
new file mode 100644
index 0000000..df4f22d
--- /dev/null
+++ b/modules/vim/vim/autoload/pathogen.vim
@@ -0,0 +1,245 @@
+" pathogen.vim - path option manipulation
+" Maintainer: Tim Pope <http://tpo.pe/>
+" Version: 2.0
+
+" Install in ~/.vim/autoload (or ~\vimfiles\autoload).
+"
+" For management of individually installed plugins in ~/.vim/bundle (or
+" ~\vimfiles\bundle), adding `call pathogen#infect()` to your .vimrc
+" prior to `filetype plugin indent on` is the only other setup necessary.
+"
+" The API is documented inline below. For maximum ease of reading,
+" :set foldmethod=marker
+
+if exists("g:loaded_pathogen") || &cp
+ finish
+endif
+let g:loaded_pathogen = 1
+
+" Point of entry for basic default usage. Give a directory name to invoke
+" pathogen#runtime_append_all_bundles() (defaults to "bundle"), or a full path
+" to invoke pathogen#runtime_prepend_subdirectories(). Afterwards,
+" pathogen#cycle_filetype() is invoked.
+function! pathogen#infect(...) abort " {{{1
+ let source_path = a:0 ? a:1 : 'bundle'
+ if source_path =~# '[\\/]'
+ call pathogen#runtime_prepend_subdirectories(source_path)
+ else
+ call pathogen#runtime_append_all_bundles(source_path)
+ endif
+ call pathogen#cycle_filetype()
+endfunction " }}}1
+
+" Split a path into a list.
+function! pathogen#split(path) abort " {{{1
+ if type(a:path) == type([]) | return a:path | endif
+ let split = split(a:path,'\\\@<!\%(\\\\\)*\zs,')
+ return map(split,'substitute(v:val,''\\\([\\,]\)'',''\1'',"g")')
+endfunction " }}}1
+
+" Convert a list to a path.
+function! pathogen#join(...) abort " {{{1
+ if type(a:1) == type(1) && a:1
+ let i = 1
+ let space = ' '
+ else
+ let i = 0
+ let space = ''
+ endif
+ let path = ""
+ while i < a:0
+ if type(a:000[i]) == type([])
+ let list = a:000[i]
+ let j = 0
+ while j < len(list)
+ let escaped = substitute(list[j],'[,'.space.']\|\\[\,'.space.']\@=','\\&','g')
+ let path .= ',' . escaped
+ let j += 1
+ endwhile
+ else
+ let path .= "," . a:000[i]
+ endif
+ let i += 1
+ endwhile
+ return substitute(path,'^,','','')
+endfunction " }}}1
+
+" Convert a list to a path with escaped spaces for 'path', 'tag', etc.
+function! pathogen#legacyjoin(...) abort " {{{1
+ return call('pathogen#join',[1] + a:000)
+endfunction " }}}1
+
+" Remove duplicates from a list.
+function! pathogen#uniq(list) abort " {{{1
+ let i = 0
+ let seen = {}
+ while i < len(a:list)
+ if (a:list[i] ==# '' && exists('empty')) || has_key(seen,a:list[i])
+ call remove(a:list,i)
+ elseif a:list[i] ==# ''
+ let i += 1
+ let empty = 1
+ else
+ let seen[a:list[i]] = 1
+ let i += 1
+ endif
+ endwhile
+ return a:list
+endfunction " }}}1
+
+" \ on Windows unless shellslash is set, / everywhere else.
+function! pathogen#separator() abort " {{{1
+ return !exists("+shellslash") || &shellslash ? '/' : '\'
+endfunction " }}}1
+
+" Convenience wrapper around glob() which returns a list.
+function! pathogen#glob(pattern) abort " {{{1
+ let files = split(glob(a:pattern),"\n")
+ return map(files,'substitute(v:val,"[".pathogen#separator()."/]$","","")')
+endfunction "}}}1
+
+" Like pathogen#glob(), only limit the results to directories.
+function! pathogen#glob_directories(pattern) abort " {{{1
+ return filter(pathogen#glob(a:pattern),'isdirectory(v:val)')
+endfunction "}}}1
+
+" Turn filetype detection off and back on again if it was already enabled.
+function! pathogen#cycle_filetype() " {{{1
+ if exists('g:did_load_filetypes')
+ filetype off
+ filetype on
+ endif
+endfunction " }}}1
+
+" Checks if a bundle is 'disabled'. A bundle is considered 'disabled' if
+" its 'basename()' is included in g:pathogen_disabled[]' or ends in a tilde.
+function! pathogen#is_disabled(path) " {{{1
+ if a:path =~# '\~$'
+ return 1
+ elseif !exists("g:pathogen_disabled")
+ return 0
+ endif
+ let sep = pathogen#separator()
+ return index(g:pathogen_disabled, strpart(a:path, strridx(a:path, sep)+1)) != -1
+endfunction "}}}1
+
+" Prepend all subdirectories of path to the rtp, and append all 'after'
+" directories in those subdirectories.
+function! pathogen#runtime_prepend_subdirectories(path) " {{{1
+ let sep = pathogen#separator()
+ let before = filter(pathogen#glob_directories(a:path.sep."*"), '!pathogen#is_disabled(v:val)')
+ let after = filter(pathogen#glob_directories(a:path.sep."*".sep."after"), '!pathogen#is_disabled(v:val[0:-7])')
+ let rtp = pathogen#split(&rtp)
+ let path = expand(a:path)
+ call filter(rtp,'v:val[0:strlen(path)-1] !=# path')
+ let &rtp = pathogen#join(pathogen#uniq(before + rtp + after))
+ return &rtp
+endfunction " }}}1
+
+" For each directory in rtp, check for a subdirectory named dir. If it
+" exists, add all subdirectories of that subdirectory to the rtp, immediately
+" after the original directory. If no argument is given, 'bundle' is used.
+" Repeated calls with the same arguments are ignored.
+function! pathogen#runtime_append_all_bundles(...) " {{{1
+ let sep = pathogen#separator()
+ let name = a:0 ? a:1 : 'bundle'
+ if "\n".s:done_bundles =~# "\\M\n".name."\n"
+ return ""
+ endif
+ let s:done_bundles .= name . "\n"
+ let list = []
+ for dir in pathogen#split(&rtp)
+ if dir =~# '\<after$'
+ let list += filter(pathogen#glob_directories(substitute(dir,'after$',name,'').sep.'*[^~]'.sep.'after'), '!pathogen#is_disabled(v:val[0:-7])') + [dir]
+ else
+ let list += [dir] + filter(pathogen#glob_directories(dir.sep.name.sep.'*[^~]'), '!pathogen#is_disabled(v:val)')
+ endif
+ endfor
+ let &rtp = pathogen#join(pathogen#uniq(list))
+ return 1
+endfunction
+
+let s:done_bundles = ''
+" }}}1
+
+" Invoke :helptags on all non-$VIM doc directories in runtimepath.
+function! pathogen#helptags() " {{{1
+ let sep = pathogen#separator()
+ for dir in pathogen#split(&rtp)
+ if (dir.sep)[0 : strlen($VIMRUNTIME)] !=# $VIMRUNTIME.sep && filewritable(dir.sep.'doc') == 2 && !empty(glob(dir.sep.'doc'.sep.'*')) && (!filereadable(dir.sep.'doc'.sep.'tags') || filewritable(dir.sep.'doc'.sep.'tags'))
+ helptags `=dir.'/doc'`
+ endif
+ endfor
+endfunction " }}}1
+
+command! -bar Helptags :call pathogen#helptags()
+
+" Like findfile(), but hardcoded to use the runtimepath.
+function! pathogen#runtime_findfile(file,count) "{{{1
+ let rtp = pathogen#join(1,pathogen#split(&rtp))
+ return fnamemodify(findfile(a:file,rtp,a:count),':p')
+endfunction " }}}1
+
+" Backport of fnameescape().
+function! pathogen#fnameescape(string) " {{{1
+ if exists('*fnameescape')
+ return fnameescape(a:string)
+ elseif a:string ==# '-'
+ return '\-'
+ else
+ return substitute(escape(a:string," \t\n*?[{`$\\%#'\"|!<"),'^[+>]','\\&','')
+ endif
+endfunction " }}}1
+
+function! s:find(count,cmd,file,lcd) " {{{1
+ let rtp = pathogen#join(1,pathogen#split(&runtimepath))
+ let file = pathogen#runtime_findfile(a:file,a:count)
+ if file ==# ''
+ return "echoerr 'E345: Can''t find file \"".a:file."\" in runtimepath'"
+ elseif a:lcd
+ let path = file[0:-strlen(a:file)-2]
+ execute 'lcd `=path`'
+ return a:cmd.' '.pathogen#fnameescape(a:file)
+ else
+ return a:cmd.' '.pathogen#fnameescape(file)
+ endif
+endfunction " }}}1
+
+function! s:Findcomplete(A,L,P) " {{{1
+ let sep = pathogen#separator()
+ let cheats = {
+ \'a': 'autoload',
+ \'d': 'doc',
+ \'f': 'ftplugin',
+ \'i': 'indent',
+ \'p': 'plugin',
+ \'s': 'syntax'}
+ if a:A =~# '^\w[\\/]' && has_key(cheats,a:A[0])
+ let request = cheats[a:A[0]].a:A[1:-1]
+ else
+ let request = a:A
+ endif
+ let pattern = substitute(request,'\'.sep,'*'.sep,'g').'*'
+ let found = {}
+ for path in pathogen#split(&runtimepath)
+ let path = expand(path, ':p')
+ let matches = split(glob(path.sep.pattern),"\n")
+ call map(matches,'isdirectory(v:val) ? v:val.sep : v:val')
+ call map(matches,'expand(v:val, ":p")[strlen(path)+1:-1]')
+ for match in matches
+ let found[match] = 1
+ endfor
+ endfor
+ return sort(keys(found))
+endfunction " }}}1
+
+command! -bar -bang -range=1 -nargs=1 -complete=customlist,s:Findcomplete Ve :execute s:find(<count>,'edit<bang>',<q-args>,0)
+command! -bar -bang -range=1 -nargs=1 -complete=customlist,s:Findcomplete Vedit :execute s:find(<count>,'edit<bang>',<q-args>,0)
+command! -bar -bang -range=1 -nargs=1 -complete=customlist,s:Findcomplete Vopen :execute s:find(<count>,'edit<bang>',<q-args>,1)
+command! -bar -bang -range=1 -nargs=1 -complete=customlist,s:Findcomplete Vsplit :execute s:find(<count>,'split',<q-args>,<bang>1)
+command! -bar -bang -range=1 -nargs=1 -complete=customlist,s:Findcomplete Vvsplit :execute s:find(<count>,'vsplit',<q-args>,<bang>1)
+command! -bar -bang -range=1 -nargs=1 -complete=customlist,s:Findcomplete Vtabedit :execute s:find(<count>,'tabedit',<q-args>,<bang>1)
+command! -bar -bang -range=1 -nargs=1 -complete=customlist,s:Findcomplete Vpedit :execute s:find(<count>,'pedit',<q-args>,<bang>1)
+command! -bar -bang -range=1 -nargs=1 -complete=customlist,s:Findcomplete Vread :execute s:find(<count>,'read',<q-args>,<bang>1)
+
+" vim:set ft=vim ts=8 sw=2 sts=2:
diff --git a/modules/vim/vim/autoload/snipMate.vim b/modules/vim/vim/autoload/snipMate.vim
new file mode 100644
index 0000000..dcd28f6
--- /dev/null
+++ b/modules/vim/vim/autoload/snipMate.vim
@@ -0,0 +1,433 @@
+fun! Filename(...)
+ let filename = expand('%:t:r')
+ if filename == '' | return a:0 == 2 ? a:2 : '' | endif
+ return !a:0 || a:1 == '' ? filename : substitute(a:1, '$1', filename, 'g')
+endf
+
+fun s:RemoveSnippet()
+ unl! g:snipPos s:curPos s:snipLen s:endCol s:endLine s:prevLen
+ \ s:lastBuf s:oldWord
+ if exists('s:update')
+ unl s:startCol s:origWordLen s:update
+ if exists('s:oldVars') | unl s:oldVars s:oldEndCol | endif
+ endif
+ aug! snipMateAutocmds
+endf
+
+fun snipMate#expandSnip(snip, col)
+ let lnum = line('.') | let col = a:col
+
+ let snippet = s:ProcessSnippet(a:snip)
+ " Avoid error if eval evaluates to nothing
+ if snippet == '' | return '' | endif
+
+ " Expand snippet onto current position with the tab stops removed
+ let snipLines = split(substitute(snippet, '$\d\+\|${\d\+.\{-}}', '', 'g'), "\n", 1)
+
+ let line = getline(lnum)
+ let afterCursor = strpart(line, col - 1)
+ " Keep text after the cursor
+ if afterCursor != "\t" && afterCursor != ' '
+ let line = strpart(line, 0, col - 1)
+ let snipLines[-1] .= afterCursor
+ else
+ let afterCursor = ''
+ " For some reason the cursor needs to move one right after this
+ if line != '' && col == 1 && &ve != 'all' && &ve != 'onemore'
+ let col += 1
+ endif
+ endif
+
+ call setline(lnum, line.snipLines[0])
+
+ " Autoindent snippet according to previous indentation
+ let indent = matchend(line, '^.\{-}\ze\(\S\|$\)') + 1
+ call append(lnum, map(snipLines[1:], "'".strpart(line, 0, indent - 1)."'.v:val"))
+
+ " Open any folds snippet expands into
+ if &fen | sil! exe lnum.','.(lnum + len(snipLines) - 1).'foldopen' | endif
+
+ let [g:snipPos, s:snipLen] = s:BuildTabStops(snippet, lnum, col - indent, indent)
+
+ if s:snipLen
+ aug snipMateAutocmds
+ au CursorMovedI * call s:UpdateChangedSnip(0)
+ au InsertEnter * call s:UpdateChangedSnip(1)
+ aug END
+ let s:lastBuf = bufnr(0) " Only expand snippet while in current buffer
+ let s:curPos = 0
+ let s:endCol = g:snipPos[s:curPos][1]
+ let s:endLine = g:snipPos[s:curPos][0]
+
+ call cursor(g:snipPos[s:curPos][0], g:snipPos[s:curPos][1])
+ let s:prevLen = [line('$'), col('$')]
+ if g:snipPos[s:curPos][2] != -1 | return s:SelectWord() | endif
+ else
+ unl g:snipPos s:snipLen
+ " Place cursor at end of snippet if no tab stop is given
+ let newlines = len(snipLines) - 1
+ call cursor(lnum + newlines, indent + len(snipLines[-1]) - len(afterCursor)
+ \ + (newlines ? 0: col - 1))
+ endif
+ return ''
+endf
+
+" Prepare snippet to be processed by s:BuildTabStops
+fun s:ProcessSnippet(snip)
+ let snippet = a:snip
+ " Evaluate eval (`...`) expressions.
+ " Using a loop here instead of a regex fixes a bug with nested "\=".
+ if stridx(snippet, '`') != -1
+ while match(snippet, '`.\{-}`') != -1
+ let snippet = substitute(snippet, '`.\{-}`',
+ \ substitute(eval(matchstr(snippet, '`\zs.\{-}\ze`')),
+ \ "\n\\%$", '', ''), '')
+ endw
+ let snippet = substitute(snippet, "\r", "\n", 'g')
+ endif
+
+ " Place all text after a colon in a tab stop after the tab stop
+ " (e.g. "${#:foo}" becomes "${:foo}foo").
+ " This helps tell the position of the tab stops later.
+ let snippet = substitute(snippet, '${\d\+:\(.\{-}\)}', '&\1', 'g')
+
+ " Update the a:snip so that all the $# become the text after
+ " the colon in their associated ${#}.
+ " (e.g. "${1:foo}" turns all "$1"'s into "foo")
+ let i = 1
+ while stridx(snippet, '${'.i) != -1
+ let s = matchstr(snippet, '${'.i.':\zs.\{-}\ze}')
+ if s != ''
+ let snippet = substitute(snippet, '$'.i, s.'&', 'g')
+ endif
+ let i += 1
+ endw
+
+ if &et " Expand tabs to spaces if 'expandtab' is set.
+ return substitute(snippet, '\t', repeat(' ', &sts ? &sts : &sw), 'g')
+ endif
+ return snippet
+endf
+
+" Counts occurences of haystack in needle
+fun s:Count(haystack, needle)
+ let counter = 0
+ let index = stridx(a:haystack, a:needle)
+ while index != -1
+ let index = stridx(a:haystack, a:needle, index+1)
+ let counter += 1
+ endw
+ return counter
+endf
+
+" Builds a list of a list of each tab stop in the snippet containing:
+" 1.) The tab stop's line number.
+" 2.) The tab stop's column number
+" (by getting the length of the string between the last "\n" and the
+" tab stop).
+" 3.) The length of the text after the colon for the current tab stop
+" (e.g. "${1:foo}" would return 3). If there is no text, -1 is returned.
+" 4.) If the "${#:}" construct is given, another list containing all
+" the matches of "$#", to be replaced with the placeholder. This list is
+" composed the same way as the parent; the first item is the line number,
+" and the second is the column.
+fun s:BuildTabStops(snip, lnum, col, indent)
+ let snipPos = []
+ let i = 1
+ let withoutVars = substitute(a:snip, '$\d\+', '', 'g')
+ while stridx(a:snip, '${'.i) != -1
+ let beforeTabStop = matchstr(withoutVars, '^.*\ze${'.i.'\D')
+ let withoutOthers = substitute(withoutVars, '${\('.i.'\D\)\@!\d\+.\{-}}', '', 'g')
+
+ let j = i - 1
+ call add(snipPos, [0, 0, -1])
+ let snipPos[j][0] = a:lnum + s:Count(beforeTabStop, "\n")
+ let snipPos[j][1] = a:indent + len(matchstr(withoutOthers, '.*\(\n\|^\)\zs.*\ze${'.i.'\D'))
+ if snipPos[j][0] == a:lnum | let snipPos[j][1] += a:col | endif
+
+ " Get all $# matches in another list, if ${#:name} is given
+ if stridx(withoutVars, '${'.i.':') != -1
+ let snipPos[j][2] = len(matchstr(withoutVars, '${'.i.':\zs.\{-}\ze}'))
+ let dots = repeat('.', snipPos[j][2])
+ call add(snipPos[j], [])
+ let withoutOthers = substitute(a:snip, '${\d\+.\{-}}\|$'.i.'\@!\d\+', '', 'g')
+ while match(withoutOthers, '$'.i.'\(\D\|$\)') != -1
+ let beforeMark = matchstr(withoutOthers, '^.\{-}\ze'.dots.'$'.i.'\(\D\|$\)')
+ call add(snipPos[j][3], [0, 0])
+ let snipPos[j][3][-1][0] = a:lnum + s:Count(beforeMark, "\n")
+ let snipPos[j][3][-1][1] = a:indent + (snipPos[j][3][-1][0] > a:lnum
+ \ ? len(matchstr(beforeMark, '.*\n\zs.*'))
+ \ : a:col + len(beforeMark))
+ let withoutOthers = substitute(withoutOthers, '$'.i.'\ze\(\D\|$\)', '', '')
+ endw
+ endif
+ let i += 1
+ endw
+ return [snipPos, i - 1]
+endf
+
+fun snipMate#jumpTabStop(backwards)
+ let leftPlaceholder = exists('s:origWordLen')
+ \ && s:origWordLen != g:snipPos[s:curPos][2]
+ if leftPlaceholder && exists('s:oldEndCol')
+ let startPlaceholder = s:oldEndCol + 1
+ endif
+
+ if exists('s:update')
+ call s:UpdatePlaceholderTabStops()
+ else
+ call s:UpdateTabStops()
+ endif
+
+ " Don't reselect placeholder if it has been modified
+ if leftPlaceholder && g:snipPos[s:curPos][2] != -1
+ if exists('startPlaceholder')
+ let g:snipPos[s:curPos][1] = startPlaceholder
+ else
+ let g:snipPos[s:curPos][1] = col('.')
+ let g:snipPos[s:curPos][2] = 0
+ endif
+ endif
+
+ let s:curPos += a:backwards ? -1 : 1
+ " Loop over the snippet when going backwards from the beginning
+ if s:curPos < 0 | let s:curPos = s:snipLen - 1 | endif
+
+ if s:curPos == s:snipLen
+ let sMode = s:endCol == g:snipPos[s:curPos-1][1]+g:snipPos[s:curPos-1][2]
+ call s:RemoveSnippet()
+ return sMode ? "\<tab>" : TriggerSnippet()
+ endif
+
+ call cursor(g:snipPos[s:curPos][0], g:snipPos[s:curPos][1])
+
+ let s:endLine = g:snipPos[s:curPos][0]
+ let s:endCol = g:snipPos[s:curPos][1]
+ let s:prevLen = [line('$'), col('$')]
+
+ return g:snipPos[s:curPos][2] == -1 ? '' : s:SelectWord()
+endf
+
+fun s:UpdatePlaceholderTabStops()
+ let changeLen = s:origWordLen - g:snipPos[s:curPos][2]
+ unl s:startCol s:origWordLen s:update
+ if !exists('s:oldVars') | return | endif
+ " Update tab stops in snippet if text has been added via "$#"
+ " (e.g., in "${1:foo}bar$1${2}").
+ if changeLen != 0
+ let curLine = line('.')
+
+ for pos in g:snipPos
+ if pos == g:snipPos[s:curPos] | continue | endif
+ let changed = pos[0] == curLine && pos[1] > s:oldEndCol
+ let changedVars = 0
+ let endPlaceholder = pos[2] - 1 + pos[1]
+ " Subtract changeLen from each tab stop that was after any of
+ " the current tab stop's placeholders.
+ for [lnum, col] in s:oldVars
+ if lnum > pos[0] | break | endif
+ if pos[0] == lnum
+ if pos[1] > col || (pos[2] == -1 && pos[1] == col)
+ let changed += 1
+ elseif col < endPlaceholder
+ let changedVars += 1
+ endif
+ endif
+ endfor
+ let pos[1] -= changeLen * changed
+ let pos[2] -= changeLen * changedVars " Parse variables within placeholders
+ " e.g., "${1:foo} ${2:$1bar}"
+
+ if pos[2] == -1 | continue | endif
+ " Do the same to any placeholders in the other tab stops.
+ for nPos in pos[3]
+ let changed = nPos[0] == curLine && nPos[1] > s:oldEndCol
+ for [lnum, col] in s:oldVars
+ if lnum > nPos[0] | break | endif
+ if nPos[0] == lnum && nPos[1] > col
+ let changed += 1
+ endif
+ endfor
+ let nPos[1] -= changeLen * changed
+ endfor
+ endfor
+ endif
+ unl s:endCol s:oldVars s:oldEndCol
+endf
+
+fun s:UpdateTabStops()
+ let changeLine = s:endLine - g:snipPos[s:curPos][0]
+ let changeCol = s:endCol - g:snipPos[s:curPos][1]
+ if exists('s:origWordLen')
+ let changeCol -= s:origWordLen
+ unl s:origWordLen
+ endif
+ let lnum = g:snipPos[s:curPos][0]
+ let col = g:snipPos[s:curPos][1]
+ " Update the line number of all proceeding tab stops if <cr> has
+ " been inserted.
+ if changeLine != 0
+ let changeLine -= 1
+ for pos in g:snipPos
+ if pos[0] >= lnum
+ if pos[0] == lnum | let pos[1] += changeCol | endif
+ let pos[0] += changeLine
+ endif
+ if pos[2] == -1 | continue | endif
+ for nPos in pos[3]
+ if nPos[0] >= lnum
+ if nPos[0] == lnum | let nPos[1] += changeCol | endif
+ let nPos[0] += changeLine
+ endif
+ endfor
+ endfor
+ elseif changeCol != 0
+ " Update the column of all proceeding tab stops if text has
+ " been inserted/deleted in the current line.
+ for pos in g:snipPos
+ if pos[1] >= col && pos[0] == lnum
+ let pos[1] += changeCol
+ endif
+ if pos[2] == -1 | continue | endif
+ for nPos in pos[3]
+ if nPos[0] > lnum | break | endif
+ if nPos[0] == lnum && nPos[1] >= col
+ let nPos[1] += changeCol
+ endif
+ endfor
+ endfor
+ endif
+endf
+
+fun s:SelectWord()
+ let s:origWordLen = g:snipPos[s:curPos][2]
+ let s:oldWord = strpart(getline('.'), g:snipPos[s:curPos][1] - 1,
+ \ s:origWordLen)
+ let s:prevLen[1] -= s:origWordLen
+ if !empty(g:snipPos[s:curPos][3])
+ let s:update = 1
+ let s:endCol = -1
+ let s:startCol = g:snipPos[s:curPos][1] - 1
+ endif
+ if !s:origWordLen | return '' | endif
+ let l = col('.') != 1 ? 'l' : ''
+ if &sel == 'exclusive'
+ return "\<esc>".l.'v'.s:origWordLen."l\<c-g>"
+ endif
+ return s:origWordLen == 1 ? "\<esc>".l.'gh'
+ \ : "\<esc>".l.'v'.(s:origWordLen - 1)."l\<c-g>"
+endf
+
+" This updates the snippet as you type when text needs to be inserted
+" into multiple places (e.g. in "${1:default text}foo$1bar$1",
+" "default text" would be highlighted, and if the user types something,
+" UpdateChangedSnip() would be called so that the text after "foo" & "bar"
+" are updated accordingly)
+"
+" It also automatically quits the snippet if the cursor is moved out of it
+" while in insert mode.
+fun s:UpdateChangedSnip(entering)
+ if exists('g:snipPos') && bufnr(0) != s:lastBuf
+ call s:RemoveSnippet()
+ elseif exists('s:update') " If modifying a placeholder
+ if !exists('s:oldVars') && s:curPos + 1 < s:snipLen
+ " Save the old snippet & word length before it's updated
+ " s:startCol must be saved too, in case text is added
+ " before the snippet (e.g. in "foo$1${2}bar${1:foo}").
+ let s:oldEndCol = s:startCol
+ let s:oldVars = deepcopy(g:snipPos[s:curPos][3])
+ endif
+ let col = col('.') - 1
+
+ if s:endCol != -1
+ let changeLen = col('$') - s:prevLen[1]
+ let s:endCol += changeLen
+ else " When being updated the first time, after leaving select mode
+ if a:entering | return | endif
+ let s:endCol = col - 1
+ endif
+
+ " If the cursor moves outside the snippet, quit it
+ if line('.') != g:snipPos[s:curPos][0] || col < s:startCol ||
+ \ col - 1 > s:endCol
+ unl! s:startCol s:origWordLen s:oldVars s:update
+ return s:RemoveSnippet()
+ endif
+
+ call s:UpdateVars()
+ let s:prevLen[1] = col('$')
+ elseif exists('g:snipPos')
+ if !a:entering && g:snipPos[s:curPos][2] != -1
+ let g:snipPos[s:curPos][2] = -2
+ endif
+
+ let col = col('.')
+ let lnum = line('.')
+ let changeLine = line('$') - s:prevLen[0]
+
+ if lnum == s:endLine
+ let s:endCol += col('$') - s:prevLen[1]
+ let s:prevLen = [line('$'), col('$')]
+ endif
+ if changeLine != 0
+ let s:endLine += changeLine
+ let s:endCol = col
+ endif
+
+ " Delete snippet if cursor moves out of it in insert mode
+ if (lnum == s:endLine && (col > s:endCol || col < g:snipPos[s:curPos][1]))
+ \ || lnum > s:endLine || lnum < g:snipPos[s:curPos][0]
+ call s:RemoveSnippet()
+ endif
+ endif
+endf
+
+" This updates the variables in a snippet when a placeholder has been edited.
+" (e.g., each "$1" in "${1:foo} $1bar $1bar")
+fun s:UpdateVars()
+ let newWordLen = s:endCol - s:startCol + 1
+ let newWord = strpart(getline('.'), s:startCol, newWordLen)
+ if newWord == s:oldWord || empty(g:snipPos[s:curPos][3])
+ return
+ endif
+
+ let changeLen = g:snipPos[s:curPos][2] - newWordLen
+ let curLine = line('.')
+ let startCol = col('.')
+ let oldStartSnip = s:startCol
+ let updateTabStops = changeLen != 0
+ let i = 0
+
+ for [lnum, col] in g:snipPos[s:curPos][3]
+ if updateTabStops
+ let start = s:startCol
+ if lnum == curLine && col <= start
+ let s:startCol -= changeLen
+ let s:endCol -= changeLen
+ endif
+ for nPos in g:snipPos[s:curPos][3][(i):]
+ " This list is in ascending order, so quit if we've gone too far.
+ if nPos[0] > lnum | break | endif
+ if nPos[0] == lnum && nPos[1] > col
+ let nPos[1] -= changeLen
+ endif
+ endfor
+ if lnum == curLine && col > start
+ let col -= changeLen
+ let g:snipPos[s:curPos][3][i][1] = col
+ endif
+ let i += 1
+ endif
+
+ " "Very nomagic" is used here to allow special characters.
+ call setline(lnum, substitute(getline(lnum), '\%'.col.'c\V'.
+ \ escape(s:oldWord, '\'), escape(newWord, '\&'), ''))
+ endfor
+ if oldStartSnip != s:startCol
+ call cursor(0, startCol + s:startCol - oldStartSnip)
+ endif
+
+ let s:oldWord = newWord
+ let g:snipPos[s:curPos][2] = newWordLen
+endf
+" vim:noet:sw=4:ts=4:ft=vim
diff --git a/modules/vim/vim/bundle/nerdtree b/modules/vim/vim/bundle/nerdtree
new file mode 160000
+Subproject c3b63d2fd9c929359231363bcabc880ba29eb96
diff --git a/modules/vim/vim/doc/NERD_tree.txt b/modules/vim/vim/doc/NERD_tree.txt
new file mode 100644
index 0000000..2e2278c
--- /dev/null
+++ b/modules/vim/vim/doc/NERD_tree.txt
@@ -0,0 +1,1222 @@
+*NERD_tree.txt* A tree explorer plugin that owns your momma!
+
+
+
+ omg its ... ~
+
+ ________ ________ _ ____________ ____ __________ ____________~
+ /_ __/ / / / ____/ / | / / ____/ __ \/ __ \ /_ __/ __ \/ ____/ ____/~
+ / / / /_/ / __/ / |/ / __/ / /_/ / / / / / / / /_/ / __/ / __/ ~
+ / / / __ / /___ / /| / /___/ _, _/ /_/ / / / / _, _/ /___/ /___ ~
+ /_/ /_/ /_/_____/ /_/ |_/_____/_/ |_/_____/ /_/ /_/ |_/_____/_____/ ~
+
+
+ Reference Manual~
+
+
+
+
+==============================================================================
+CONTENTS *NERDTree-contents*
+
+ 1.Intro...................................|NERDTree|
+ 2.Functionality provided..................|NERDTreeFunctionality|
+ 2.1.Global commands...................|NERDTreeGlobalCommands|
+ 2.2.Bookmarks.........................|NERDTreeBookmarks|
+ 2.2.1.The bookmark table..........|NERDTreeBookmarkTable|
+ 2.2.2.Bookmark commands...........|NERDTreeBookmarkCommands|
+ 2.2.3.Invalid bookmarks...........|NERDTreeInvalidBookmarks|
+ 2.3.NERD tree mappings................|NERDTreeMappings|
+ 2.4.The NERD tree menu................|NERDTreeMenu|
+ 3.Options.................................|NERDTreeOptions|
+ 3.1.Option summary....................|NERDTreeOptionSummary|
+ 3.2.Option details....................|NERDTreeOptionDetails|
+ 4.The NERD tree API.......................|NERDTreeAPI|
+ 4.1.Key map API.......................|NERDTreeKeymapAPI|
+ 4.2.Menu API..........................|NERDTreeMenuAPI|
+ 5.About...................................|NERDTreeAbout|
+ 6.Changelog...............................|NERDTreeChangelog|
+ 7.Credits.................................|NERDTreeCredits|
+ 8.License.................................|NERDTreeLicense|
+
+==============================================================================
+1. Intro *NERDTree*
+
+What is this "NERD tree"??
+
+The NERD tree allows you to explore your filesystem and to open files and
+directories. It presents the filesystem to you in the form of a tree which you
+manipulate with the keyboard and/or mouse. It also allows you to perform
+simple filesystem operations.
+
+The following features and functionality are provided by the NERD tree:
+ * Files and directories are displayed in a hierarchical tree structure
+ * Different highlighting is provided for the following types of nodes:
+ * files
+ * directories
+ * sym-links
+ * windows .lnk files
+ * read-only files
+ * executable files
+ * Many (customisable) mappings are provided to manipulate the tree:
+ * Mappings to open/close/explore directory nodes
+ * Mappings to open files in new/existing windows/tabs
+ * Mappings to change the current root of the tree
+ * Mappings to navigate around the tree
+ * ...
+ * Directories and files can be bookmarked.
+ * Most NERD tree navigation can also be done with the mouse
+ * Filtering of tree content (can be toggled at runtime)
+ * custom file filters to prevent e.g. vim backup files being displayed
+ * optional displaying of hidden files (. files)
+ * files can be "turned off" so that only directories are displayed
+ * The position and size of the NERD tree window can be customised
+ * The order in which the nodes in the tree are listed can be customised.
+ * A model of your filesystem is created/maintained as you explore it. This
+ has several advantages:
+ * All filesystem information is cached and is only re-read on demand
+ * If you revisit a part of the tree that you left earlier in your
+ session, the directory nodes will be opened/closed as you left them
+ * The script remembers the cursor position and window position in the NERD
+ tree so you can toggle it off (or just close the tree window) and then
+ reopen it (with NERDTreeToggle) the NERD tree window will appear exactly
+ as you left it
+ * You can have a separate NERD tree for each tab, share trees across tabs,
+ or a mix of both.
+ * By default the script overrides the default file browser (netw), so if
+ you :edit a directory a (slighly modified) NERD tree will appear in the
+ current window
+ * A programmable menu system is provided (simulates right clicking on a
+ node)
+ * one default menu plugin is provided to perform basic filesytem
+ operations (create/delete/move/copy files/directories)
+ * There's an API for adding your own keymappings
+
+
+==============================================================================
+2. Functionality provided *NERDTreeFunctionality*
+
+------------------------------------------------------------------------------
+2.1. Global Commands *NERDTreeGlobalCommands*
+
+:NERDTree [<start-directory> | <bookmark>] *:NERDTree*
+ Opens a fresh NERD tree. The root of the tree depends on the argument
+ given. There are 3 cases: If no argument is given, the current directory
+ will be used. If a directory is given, that will be used. If a bookmark
+ name is given, the corresponding directory will be used. For example: >
+ :NERDTree /home/marty/vim7/src
+ :NERDTree foo (foo is the name of a bookmark)
+<
+:NERDTreeFromBookmark <bookmark> *:NERDTreeFromBookmark*
+ Opens a fresh NERD tree with the root initialized to the dir for
+ <bookmark>. This only reason to use this command over :NERDTree is for
+ the completion (which is for bookmarks rather than directories).
+
+:NERDTreeToggle [<start-directory> | <bookmark>] *:NERDTreeToggle*
+ If a NERD tree already exists for this tab, it is reopened and rendered
+ again. If no NERD tree exists for this tab then this command acts the
+ same as the |:NERDTree| command.
+
+:NERDTreeMirror *:NERDTreeMirror*
+ Shares an existing NERD tree, from another tab, in the current tab.
+ Changes made to one tree are reflected in both as they are actually the
+ same buffer.
+
+ If only one other NERD tree exists, that tree is automatically mirrored. If
+ more than one exists, the script will ask which tree to mirror.
+
+:NERDTreeClose *:NERDTreeClose*
+ Close the NERD tree in this tab.
+
+:NERDTreeFind *:NERDTreeFind*
+ Find the current file in the tree. If no tree exists for the current tab,
+ or the file is not under the current root, then initialize a new tree where
+ the root is the directory of the current file.
+
+------------------------------------------------------------------------------
+2.2. Bookmarks *NERDTreeBookmarks*
+
+Bookmarks in the NERD tree are a way to tag files or directories of interest.
+For example, you could use bookmarks to tag all of your project directories.
+
+------------------------------------------------------------------------------
+2.2.1. The Bookmark Table *NERDTreeBookmarkTable*
+
+If the bookmark table is active (see |NERDTree-B| and
+|'NERDTreeShowBookmarks'|), it will be rendered above the tree. You can double
+click bookmarks or use the |NERDTree-o| mapping to activate them. See also,
+|NERDTree-t| and |NERDTree-T|
+
+------------------------------------------------------------------------------
+2.2.2. Bookmark commands *NERDTreeBookmarkCommands*
+
+Note that the following commands are only available in the NERD tree buffer.
+
+:Bookmark <name>
+ Bookmark the current node as <name>. If there is already a <name>
+ bookmark, it is overwritten. <name> must not contain spaces.
+
+:BookmarkToRoot <bookmark>
+ Make the directory corresponding to <bookmark> the new root. If a treenode
+ corresponding to <bookmark> is already cached somewhere in the tree then
+ the current tree will be used, otherwise a fresh tree will be opened.
+ Note that if <bookmark> points to a file then its parent will be used
+ instead.
+
+:RevealBookmark <bookmark>
+ If the node is cached under the current root then it will be revealed
+ (i.e. directory nodes above it will be opened) and the cursor will be
+ placed on it.
+
+:OpenBookmark <bookmark>
+ <bookmark> must point to a file. The file is opened as though |NERDTree-o|
+ was applied. If the node is cached under the current root then it will be
+ revealed and the cursor will be placed on it.
+
+:ClearBookmarks [<bookmarks>]
+ Remove all the given bookmarks. If no bookmarks are given then remove all
+ bookmarks on the current node.
+
+:ClearAllBookmarks
+ Remove all bookmarks.
+
+:ReadBookmarks
+ Re-read the bookmarks in the |'NERDTreeBookmarksFile'|.
+
+See also |:NERDTree| and |:NERDTreeFromBookmark|.
+
+------------------------------------------------------------------------------
+2.2.3. Invalid Bookmarks *NERDTreeInvalidBookmarks*
+
+If invalid bookmarks are detected, the script will issue an error message and
+the invalid bookmarks will become unavailable for use.
+
+These bookmarks will still be stored in the bookmarks file (see
+|'NERDTreeBookmarksFile'|), down the bottom. There will always be a blank line
+after the valid bookmarks but before the invalid ones.
+
+Each line in the bookmarks file represents one bookmark. The proper format is:
+<bookmark name><space><full path to the bookmark location>
+
+After you have corrected any invalid bookmarks, either restart vim, or go
+:ReadBookmarks from the NERD tree window.
+
+------------------------------------------------------------------------------
+2.3. NERD tree Mappings *NERDTreeMappings*
+
+Default Description~ help-tag~
+Key~
+
+o.......Open files, directories and bookmarks....................|NERDTree-o|
+go......Open selected file, but leave cursor in the NERDTree.....|NERDTree-go|
+t.......Open selected node/bookmark in a new tab.................|NERDTree-t|
+T.......Same as 't' but keep the focus on the current tab........|NERDTree-T|
+i.......Open selected file in a split window.....................|NERDTree-i|
+gi......Same as i, but leave the cursor on the NERDTree..........|NERDTree-gi|
+s.......Open selected file in a new vsplit.......................|NERDTree-s|
+gs......Same as s, but leave the cursor on the NERDTree..........|NERDTree-gs|
+O.......Recursively open the selected directory..................|NERDTree-O|
+x.......Close the current nodes parent...........................|NERDTree-x|
+X.......Recursively close all children of the current node.......|NERDTree-X|
+e.......Edit the current dif.....................................|NERDTree-e|
+
+<CR>...............same as |NERDTree-o|.
+double-click.......same as the |NERDTree-o| map.
+middle-click.......same as |NERDTree-i| for files, same as
+ |NERDTree-e| for dirs.
+
+D.......Delete the current bookmark .............................|NERDTree-D|
+
+P.......Jump to the root node....................................|NERDTree-P|
+p.......Jump to current nodes parent.............................|NERDTree-p|
+K.......Jump up inside directories at the current tree depth.....|NERDTree-K|
+J.......Jump down inside directories at the current tree depth...|NERDTree-J|
+<C-J>...Jump down to the next sibling of the current directory...|NERDTree-C-J|
+<C-K>...Jump up to the previous sibling of the current directory.|NERDTree-C-K|
+
+C.......Change the tree root to the selected dir.................|NERDTree-C|
+u.......Move the tree root up one directory......................|NERDTree-u|
+U.......Same as 'u' except the old root node is left open........|NERDTree-U|
+r.......Recursively refresh the current directory................|NERDTree-r|
+R.......Recursively refresh the current root.....................|NERDTree-R|
+m.......Display the NERD tree menu...............................|NERDTree-m|
+cd......Change the CWD to the dir of the selected node...........|NERDTree-cd|
+
+I.......Toggle whether hidden files displayed....................|NERDTree-I|
+f.......Toggle whether the file filters are used.................|NERDTree-f|
+F.......Toggle whether files are displayed.......................|NERDTree-F|
+B.......Toggle whether the bookmark table is displayed...........|NERDTree-B|
+
+q.......Close the NERDTree window................................|NERDTree-q|
+A.......Zoom (maximize/minimize) the NERDTree window.............|NERDTree-A|
+?.......Toggle the display of the quick help.....................|NERDTree-?|
+
+------------------------------------------------------------------------------
+ *NERDTree-o*
+Default key: o
+Map option: NERDTreeMapActivateNode
+Applies to: files and directories.
+
+If a file node is selected, it is opened in the previous window.
+
+If a directory is selected it is opened or closed depending on its current
+state.
+
+If a bookmark that links to a directory is selected then that directory
+becomes the new root.
+
+If a bookmark that links to a file is selected then that file is opened in the
+previous window.
+
+------------------------------------------------------------------------------
+ *NERDTree-go*
+Default key: go
+Map option: None
+Applies to: files.
+
+If a file node is selected, it is opened in the previous window, but the
+cursor does not move.
+
+The key combo for this mapping is always "g" + NERDTreeMapActivateNode (see
+|NERDTree-o|).
+
+------------------------------------------------------------------------------
+ *NERDTree-t*
+Default key: t
+Map option: NERDTreeMapOpenInTab
+Applies to: files and directories.
+
+Opens the selected file in a new tab. If a directory is selected, a fresh
+NERD Tree for that directory is opened in a new tab.
+
+If a bookmark which points to a directory is selected, open a NERD tree for
+that directory in a new tab. If the bookmark points to a file, open that file
+in a new tab.
+
+------------------------------------------------------------------------------
+ *NERDTree-T*
+Default key: T
+Map option: NERDTreeMapOpenInTabSilent
+Applies to: files and directories.
+
+The same as |NERDTree-t| except that the focus is kept in the current tab.
+
+------------------------------------------------------------------------------
+ *NERDTree-i*
+Default key: i
+Map option: NERDTreeMapOpenSplit
+Applies to: files.
+
+Opens the selected file in a new split window and puts the cursor in the new
+window.
+
+------------------------------------------------------------------------------
+ *NERDTree-gi*
+Default key: gi
+Map option: None
+Applies to: files.
+
+The same as |NERDTree-i| except that the cursor is not moved.
+
+The key combo for this mapping is always "g" + NERDTreeMapOpenSplit (see
+|NERDTree-i|).
+
+------------------------------------------------------------------------------
+ *NERDTree-s*
+Default key: s
+Map option: NERDTreeMapOpenVSplit
+Applies to: files.
+
+Opens the selected file in a new vertically split window and puts the cursor in
+the new window.
+
+------------------------------------------------------------------------------
+ *NERDTree-gs*
+Default key: gs
+Map option: None
+Applies to: files.
+
+The same as |NERDTree-s| except that the cursor is not moved.
+
+The key combo for this mapping is always "g" + NERDTreeMapOpenVSplit (see
+|NERDTree-s|).
+
+------------------------------------------------------------------------------
+ *NERDTree-O*
+Default key: O
+Map option: NERDTreeMapOpenRecursively
+Applies to: directories.
+
+Recursively opens the selelected directory.
+
+All files and directories are cached, but if a directory would not be
+displayed due to file filters (see |'NERDTreeIgnore'| |NERDTree-f|) or the
+hidden file filter (see |'NERDTreeShowHidden'|) then its contents are not
+cached. This is handy, especially if you have .svn directories.
+
+------------------------------------------------------------------------------
+ *NERDTree-x*
+Default key: x
+Map option: NERDTreeMapCloseDir
+Applies to: files and directories.
+
+Closes the parent of the selected node.
+
+------------------------------------------------------------------------------
+ *NERDTree-X*
+Default key: X
+Map option: NERDTreeMapCloseChildren
+Applies to: directories.
+
+Recursively closes all children of the selected directory.
+
+Tip: To quickly "reset" the tree, use |NERDTree-P| with this mapping.
+
+------------------------------------------------------------------------------
+ *NERDTree-e*
+Default key: e
+Map option: NERDTreeMapOpenExpl
+Applies to: files and directories.
+
+|:edit|s the selected directory, or the selected file's directory. This could
+result in a NERD tree or a netrw being opened, depending on
+|'NERDTreeHijackNetrw'|.
+
+------------------------------------------------------------------------------
+ *NERDTree-D*
+Default key: D
+Map option: NERDTreeMapDeleteBookmark
+Applies to: lines in the bookmarks table
+
+Deletes the currently selected bookmark.
+
+------------------------------------------------------------------------------
+ *NERDTree-P*
+Default key: P
+Map option: NERDTreeMapJumpRoot
+Applies to: no restrictions.
+
+Jump to the tree root.
+
+------------------------------------------------------------------------------
+ *NERDTree-p*
+Default key: p
+Map option: NERDTreeMapJumpParent
+Applies to: files and directories.
+
+Jump to the parent node of the selected node.
+
+------------------------------------------------------------------------------
+ *NERDTree-K*
+Default key: K
+Map option: NERDTreeMapJumpFirstChild
+Applies to: files and directories.
+
+Jump to the first child of the current nodes parent.
+
+If the cursor is already on the first node then do the following:
+ * loop back thru the siblings of the current nodes parent until we find an
+ open dir with children
+ * go to the first child of that node
+
+------------------------------------------------------------------------------
+ *NERDTree-J*
+Default key: J
+Map option: NERDTreeMapJumpLastChild
+Applies to: files and directories.
+
+Jump to the last child of the current nodes parent.
+
+If the cursor is already on the last node then do the following:
+ * loop forward thru the siblings of the current nodes parent until we find
+ an open dir with children
+ * go to the last child of that node
+
+------------------------------------------------------------------------------
+ *NERDTree-C-J*
+Default key: <C-J>
+Map option: NERDTreeMapJumpNextSibling
+Applies to: files and directories.
+
+Jump to the next sibling of the selected node.
+
+------------------------------------------------------------------------------
+ *NERDTree-C-K*
+Default key: <C-K>
+Map option: NERDTreeMapJumpPrevSibling
+Applies to: files and directories.
+
+Jump to the previous sibling of the selected node.
+
+------------------------------------------------------------------------------
+ *NERDTree-C*
+Default key: C
+Map option: NERDTreeMapChdir
+Applies to: directories.
+
+Make the selected directory node the new tree root. If a file is selected, its
+parent is used.
+
+------------------------------------------------------------------------------
+ *NERDTree-u*
+Default key: u
+Map option: NERDTreeMapUpdir
+Applies to: no restrictions.
+
+Move the tree root up a dir (like doing a "cd ..").
+
+------------------------------------------------------------------------------
+ *NERDTree-U*
+Default key: U
+Map option: NERDTreeMapUpdirKeepOpen
+Applies to: no restrictions.
+
+Like |NERDTree-u| except that the old tree root is kept open.
+
+------------------------------------------------------------------------------
+ *NERDTree-r*
+Default key: r
+Map option: NERDTreeMapRefresh
+Applies to: files and directories.
+
+If a dir is selected, recursively refresh that dir, i.e. scan the filesystem
+for changes and represent them in the tree.
+
+If a file node is selected then the above is done on it's parent.
+
+------------------------------------------------------------------------------
+ *NERDTree-R*
+Default key: R
+Map option: NERDTreeMapRefreshRoot
+Applies to: no restrictions.
+
+Recursively refresh the tree root.
+
+------------------------------------------------------------------------------
+ *NERDTree-m*
+Default key: m
+Map option: NERDTreeMapMenu
+Applies to: files and directories.
+
+Display the NERD tree menu. See |NERDTreeMenu| for details.
+
+------------------------------------------------------------------------------
+ *NERDTree-cd*
+Default key: cd
+Map option: NERDTreeMapChdir
+Applies to: files and directories.
+
+Change vims current working directory to that of the selected node.
+
+------------------------------------------------------------------------------
+ *NERDTree-I*
+Default key: I
+Map option: NERDTreeMapToggleHidden
+Applies to: no restrictions.
+
+Toggles whether hidden files (i.e. "dot files") are displayed.
+
+------------------------------------------------------------------------------
+ *NERDTree-f*
+Default key: f
+Map option: NERDTreeMapToggleFilters
+Applies to: no restrictions.
+
+Toggles whether file filters are used. See |'NERDTreeIgnore'| for details.
+
+------------------------------------------------------------------------------
+ *NERDTree-F*
+Default key: F
+Map option: NERDTreeMapToggleFiles
+Applies to: no restrictions.
+
+Toggles whether file nodes are displayed.
+
+------------------------------------------------------------------------------
+ *NERDTree-B*
+Default key: B
+Map option: NERDTreeMapToggleBookmarks
+Applies to: no restrictions.
+
+Toggles whether the bookmarks table is displayed.
+
+------------------------------------------------------------------------------
+ *NERDTree-q*
+Default key: q
+Map option: NERDTreeMapQuit
+Applies to: no restrictions.
+
+Closes the NERDtree window.
+
+------------------------------------------------------------------------------
+ *NERDTree-A*
+Default key: A
+Map option: NERDTreeMapToggleZoom
+Applies to: no restrictions.
+
+Maximize (zoom) and minimize the NERDtree window.
+
+------------------------------------------------------------------------------
+ *NERDTree-?*
+Default key: ?
+Map option: NERDTreeMapHelp
+Applies to: no restrictions.
+
+Toggles whether the quickhelp is displayed.
+
+------------------------------------------------------------------------------
+2.3. The NERD tree menu *NERDTreeMenu*
+
+The NERD tree has a menu that can be programmed via the an API (see
+|NERDTreeMenuAPI|). The idea is to simulate the "right click" menus that most
+file explorers have.
+
+The script comes with two default menu plugins: exec_menuitem.vim and
+fs_menu.vim. fs_menu.vim adds some basic filesystem operations to the menu for
+creating/deleting/moving/copying files and dirs. exec_menuitem.vim provides a
+menu item to execute executable files.
+
+Related tags: |NERDTree-m| |NERDTreeApi|
+
+==============================================================================
+3. Customisation *NERDTreeOptions*
+
+
+------------------------------------------------------------------------------
+3.1. Customisation summary *NERDTreeOptionSummary*
+
+The script provides the following options that can customise the behaviour the
+NERD tree. These options should be set in your vimrc.
+
+|'loaded_nerd_tree'| Turns off the script.
+
+|'NERDChristmasTree'| Tells the NERD tree to make itself colourful
+ and pretty.
+
+|'NERDTreeAutoCenter'| Controls whether the NERD tree window centers
+ when the cursor moves within a specified
+ distance to the top/bottom of the window.
+|'NERDTreeAutoCenterThreshold'| Controls the sensitivity of autocentering.
+
+|'NERDTreeCaseSensitiveSort'| Tells the NERD tree whether to be case
+ sensitive or not when sorting nodes.
+
+|'NERDTreeChDirMode'| Tells the NERD tree if/when it should change
+ vim's current working directory.
+
+|'NERDTreeHighlightCursorline'| Tell the NERD tree whether to highlight the
+ current cursor line.
+
+|'NERDTreeHijackNetrw'| Tell the NERD tree whether to replace the netrw
+ autocommands for exploring local directories.
+
+|'NERDTreeIgnore'| Tells the NERD tree which files to ignore.
+
+|'NERDTreeBookmarksFile'| Where the bookmarks are stored.
+
+|'NERDTreeMouseMode'| Tells the NERD tree how to handle mouse
+ clicks.
+
+|'NERDTreeQuitOnOpen'| Closes the tree window after opening a file.
+
+|'NERDTreeShowBookmarks'| Tells the NERD tree whether to display the
+ bookmarks table on startup.
+
+|'NERDTreeShowFiles'| Tells the NERD tree whether to display files
+ in the tree on startup.
+
+|'NERDTreeShowHidden'| Tells the NERD tree whether to display hidden
+ files on startup.
+
+|'NERDTreeShowLineNumbers'| Tells the NERD tree whether to display line
+ numbers in the tree window.
+
+|'NERDTreeSortOrder'| Tell the NERD tree how to sort the nodes in
+ the tree.
+
+|'NERDTreeStatusline'| Set a statusline for NERD tree windows.
+
+|'NERDTreeWinPos'| Tells the script where to put the NERD tree
+ window.
+
+|'NERDTreeWinSize'| Sets the window size when the NERD tree is
+ opened.
+
+------------------------------------------------------------------------------
+3.2. Customisation details *NERDTreeOptionDetails*
+
+To enable any of the below options you should put the given line in your
+~/.vimrc
+
+ *'loaded_nerd_tree'*
+If this plugin is making you feel homicidal, it may be a good idea to turn it
+off with this line in your vimrc: >
+ let loaded_nerd_tree=1
+<
+------------------------------------------------------------------------------
+ *'NERDChristmasTree'*
+Values: 0 or 1.
+Default: 1.
+
+If this option is set to 1 then some extra syntax highlighting elements are
+added to the nerd tree to make it more colourful.
+
+Set it to 0 for a more vanilla looking tree.
+
+------------------------------------------------------------------------------
+ *'NERDTreeAutoCenter'*
+Values: 0 or 1.
+Default: 1
+
+If set to 1, the NERD tree window will center around the cursor if it moves to
+within |'NERDTreeAutoCenterThreshold'| lines of the top/bottom of the window.
+
+This is ONLY done in response to tree navigation mappings,
+i.e. |NERDTree-J| |NERDTree-K| |NERDTree-C-J| |NERDTree-C-K| |NERDTree-p|
+|NERDTree-P|
+
+The centering is done with a |zz| operation.
+
+------------------------------------------------------------------------------
+ *'NERDTreeAutoCenterThreshold'*
+Values: Any natural number.
+Default: 3
+
+This option controls the "sensitivity" of the NERD tree auto centering. See
+|'NERDTreeAutoCenter'| for details.
+
+------------------------------------------------------------------------------
+ *'NERDTreeCaseSensitiveSort'*
+Values: 0 or 1.
+Default: 0.
+
+By default the NERD tree does not sort nodes case sensitively, i.e. nodes
+could appear like this: >
+ bar.c
+ Baz.c
+ blarg.c
+ boner.c
+ Foo.c
+<
+But, if you set this option to 1 then the case of the nodes will be taken into
+account. The above nodes would then be sorted like this: >
+ Baz.c
+ Foo.c
+ bar.c
+ blarg.c
+ boner.c
+<
+------------------------------------------------------------------------------
+ *'NERDTreeChDirMode'*
+
+Values: 0, 1 or 2.
+Default: 0.
+
+Use this option to tell the script when (if at all) to change the current
+working directory (CWD) for vim.
+
+If it is set to 0 then the CWD is never changed by the NERD tree.
+
+If set to 1 then the CWD is changed when the NERD tree is first loaded to the
+directory it is initialized in. For example, if you start the NERD tree with >
+ :NERDTree /home/marty/foobar
+<
+then the CWD will be changed to /home/marty/foobar and will not be changed
+again unless you init another NERD tree with a similar command.
+
+If the option is set to 2 then it behaves the same as if set to 1 except that
+the CWD is changed whenever the tree root is changed. For example, if the CWD
+is /home/marty/foobar and you make the node for /home/marty/foobar/baz the new
+root then the CWD will become /home/marty/foobar/baz.
+
+------------------------------------------------------------------------------
+ *'NERDTreeHighlightCursorline'*
+Values: 0 or 1.
+Default: 1.
+
+If set to 1, the current cursor line in the NERD tree buffer will be
+highlighted. This is done using the |'cursorline'| option.
+
+------------------------------------------------------------------------------
+ *'NERDTreeHijackNetrw'*
+Values: 0 or 1.
+Default: 1.
+
+If set to 1, doing a >
+ :edit <some directory>
+<
+will open up a "secondary" NERD tree instead of a netrw in the target window.
+
+Secondary NERD trees behaves slighly different from a regular trees in the
+following respects:
+ 1. 'o' will open the selected file in the same window as the tree,
+ replacing it.
+ 2. you can have as many secondary tree as you want in the same tab.
+
+------------------------------------------------------------------------------
+ *'NERDTreeIgnore'*
+Values: a list of regular expressions.
+Default: ['\~$'].
+
+This option is used to specify which files the NERD tree should ignore. It
+must be a list of regular expressions. When the NERD tree is rendered, any
+files/dirs that match any of the regex's in 'NERDTreeIgnore' wont be
+displayed.
+
+For example if you put the following line in your vimrc: >
+ let NERDTreeIgnore=['\.vim$', '\~$']
+<
+then all files ending in .vim or ~ will be ignored.
+
+Note: to tell the NERD tree not to ignore any files you must use the following
+line: >
+ let NERDTreeIgnore=[]
+<
+
+The file filters can be turned on and off dynamically with the |NERDTree-f|
+mapping.
+
+------------------------------------------------------------------------------
+ *'NERDTreeBookmarksFile'*
+Values: a path
+Default: $HOME/.NERDTreeBookmarks
+
+This is where bookmarks are saved. See |NERDTreeBookmarkCommands|.
+
+------------------------------------------------------------------------------
+ *'NERDTreeMouseMode'*
+Values: 1, 2 or 3.
+Default: 1.
+
+If set to 1 then a double click on a node is required to open it.
+If set to 2 then a single click will open directory nodes, while a double
+click will still be required for file nodes.
+If set to 3 then a single click will open any node.
+
+Note: a double click anywhere on a line that a tree node is on will
+activate it, but all single-click activations must be done on name of the node
+itself. For example, if you have the following node: >
+ | | |-application.rb
+<
+then (to single click activate it) you must click somewhere in
+'application.rb'.
+
+------------------------------------------------------------------------------
+ *'NERDTreeQuitOnOpen'*
+
+Values: 0 or 1.
+Default: 0
+
+If set to 1, the NERD tree window will close after opening a file with the
+|NERDTree-o|, |NERDTree-i|, |NERDTree-t| and |NERDTree-T| mappings.
+
+------------------------------------------------------------------------------
+ *'NERDTreeShowBookmarks'*
+Values: 0 or 1.
+Default: 0.
+
+If this option is set to 1 then the bookmarks table will be displayed.
+
+This option can be toggled dynamically, per tree, with the |NERDTree-B|
+mapping.
+
+------------------------------------------------------------------------------
+ *'NERDTreeShowFiles'*
+Values: 0 or 1.
+Default: 1.
+
+If this option is set to 1 then files are displayed in the NERD tree. If it is
+set to 0 then only directories are displayed.
+
+This option can be toggled dynamically, per tree, with the |NERDTree-F|
+mapping and is useful for drastically shrinking the tree when you are
+navigating to a different part of the tree.
+
+------------------------------------------------------------------------------
+ *'NERDTreeShowHidden'*
+Values: 0 or 1.
+Default: 0.
+
+This option tells vim whether to display hidden files by default. This option
+can be dynamically toggled, per tree, with the |NERDTree-I| mapping. Use one
+of the follow lines to set this option: >
+ let NERDTreeShowHidden=0
+ let NERDTreeShowHidden=1
+<
+
+------------------------------------------------------------------------------
+ *'NERDTreeShowLineNumbers'*
+Values: 0 or 1.
+Default: 0.
+
+This option tells vim whether to display line numbers for the NERD tree
+window. Use one of the follow lines to set this option: >
+ let NERDTreeShowLineNumbers=0
+ let NERDTreeShowLineNumbers=1
+<
+
+------------------------------------------------------------------------------
+ *'NERDTreeSortOrder'*
+Values: a list of regular expressions.
+Default: ['\/$', '*', '\.swp$', '\.bak$', '\~$']
+
+This option is set to a list of regular expressions which are used to
+specify the order of nodes under their parent.
+
+For example, if the option is set to: >
+ ['\.vim$', '\.c$', '\.h$', '*', 'foobar']
+<
+then all .vim files will be placed at the top, followed by all .c files then
+all .h files. All files containing the string 'foobar' will be placed at the
+end. The star is a special flag: it tells the script that every node that
+doesnt match any of the other regexps should be placed here.
+
+If no star is present in 'NERDTreeSortOrder' then one is automatically
+appended to the array.
+
+The regex '\/$' should be used to match directory nodes.
+
+After this sorting is done, the files in each group are sorted alphabetically.
+
+Other examples: >
+ (1) ['*', '\/$']
+ (2) []
+ (3) ['\/$', '\.rb$', '\.php$', '*', '\.swp$', '\.bak$', '\~$']
+<
+1. Directories will appear last, everything else will appear above.
+2. Everything will simply appear in alphabetical order.
+3. Dirs will appear first, then ruby and php. Swap files, bak files and vim
+ backup files will appear last with everything else preceding them.
+
+------------------------------------------------------------------------------
+ *'NERDTreeStatusline'*
+Values: Any valid statusline setting.
+Default: %{b:NERDTreeRoot.path.strForOS(0)}
+
+Tells the script what to use as the |'statusline'| setting for NERD tree
+windows.
+
+Note that the statusline is set using |:let-&| not |:set| so escaping spaces
+isn't necessary.
+
+Setting this option to -1 will will deactivate it so that your global
+statusline setting is used instead.
+
+------------------------------------------------------------------------------
+ *'NERDTreeWinPos'*
+Values: "left" or "right"
+Default: "left".
+
+This option is used to determine where NERD tree window is placed on the
+screen.
+
+This option makes it possible to use two different explorer plugins
+simultaneously. For example, you could have the taglist plugin on the left of
+the window and the NERD tree on the right.
+
+------------------------------------------------------------------------------
+ *'NERDTreeWinSize'*
+Values: a positive integer.
+Default: 31.
+
+This option is used to change the size of the NERD tree when it is loaded.
+
+==============================================================================
+4. The NERD tree API *NERDTreeAPI*
+
+The NERD tree script allows you to add custom key mappings and menu items via
+a set of API calls. Any scripts that use this API should be placed in
+~/.vim/nerdtree_plugin/ (*nix) or ~/vimfiles/nerdtree_plugin (windows).
+
+The script exposes some prototype objects that can be used to manipulate the
+tree and/or get information from it: >
+ g:NERDTreePath
+ g:NERDTreeDirNode
+ g:NERDTreeFileNode
+ g:NERDTreeBookmark
+<
+See the code/comments in NERD_tree.vim to find how to use these objects. The
+following code conventions are used:
+ * class members start with a capital letter
+ * instance members start with a lower case letter
+ * private members start with an underscore
+
+See this blog post for more details:
+ http://got-ravings.blogspot.com/2008/09/vim-pr0n-prototype-based-objects.html
+
+------------------------------------------------------------------------------
+4.1. Key map API *NERDTreeKeymapAPI*
+
+NERDTreeAddKeyMap({options}) *NERDTreeAddKeyMap()*
+ Adds a new keymapping for all NERD tree buffers.
+ {options} must be a dictionary, and must contain the following keys:
+ "key" - the trigger key for the new mapping
+ "callback" - the function the new mapping will be bound to
+ "quickhelpText" - the text that will appear in the quickhelp (see
+ |NERDTree-?|)
+
+ Example: >
+ call NERDTreeAddKeyMap({
+ \ 'key': 'b',
+ \ 'callback': 'NERDTreeEchoCurrentNode',
+ \ 'quickhelpText': 'echo full path of current node' })
+
+ function! NERDTreeEchoCurrentNode()
+ let n = g:NERDTreeFileNode.GetSelected()
+ if n != {}
+ echomsg 'Current node: ' . n.path.str()
+ endif
+ endfunction
+<
+ This code should sit in a file like ~/.vim/nerdtree_plugin/mymapping.vim.
+ It adds a (rather useless) mapping on 'b' which echos the full path to the
+ current node.
+
+------------------------------------------------------------------------------
+4.2. Menu API *NERDTreeMenuAPI*
+
+NERDTreeAddSubmenu({options}) *NERDTreeAddSubmenu()*
+ Creates and returns a new submenu.
+
+ {options} must be a dictionary and must contain the following keys:
+ "text" - the text of the submenu that the user will see
+ "shortcut" - a shortcut key for the submenu (need not be unique)
+
+ The following keys are optional:
+ "isActiveCallback" - a function that will be called to determine whether
+ this submenu item will be displayed or not. The callback function must return
+ 0 or 1.
+ "parent" - the parent submenu of the new submenu (returned from a previous
+ invocation of NERDTreeAddSubmenu()). If this key is left out then the new
+ submenu will sit under the top level menu.
+
+ See below for an example.
+
+NERDTreeAddMenuItem({options}) *NERDTreeAddMenuItem()*
+ Adds a new menu item to the NERD tree menu (see |NERDTreeMenu|).
+
+ {options} must be a dictionary and must contain the
+ following keys:
+ "text" - the text of the menu item which the user will see
+ "shortcut" - a shortcut key for the menu item (need not be unique)
+ "callback" - the function that will be called when the user activates the
+ menu item.
+
+ The following keys are optional:
+ "isActiveCallback" - a function that will be called to determine whether
+ this menu item will be displayed or not. The callback function must return
+ 0 or 1.
+ "parent" - if the menu item belongs under a submenu then this key must be
+ specified. This value for this key will be the object that
+ was returned when the submenu was created with |NERDTreeAddSubmenu()|.
+
+ See below for an example.
+
+NERDTreeAddMenuSeparator([{options}]) *NERDTreeAddMenuSeparator()*
+ Adds a menu separator (a row of dashes).
+
+ {options} is an optional dictionary that may contain the following keys:
+ "isActiveCallback" - see description in |NERDTreeAddMenuItem()|.
+
+Below is an example of the menu API in action. >
+ call NERDTreeAddMenuSeparator()
+
+ call NERDTreeAddMenuItem({
+ \ 'text': 'a (t)op level menu item',
+ \ 'shortcut': 't',
+ \ 'callback': 'SomeFunction' })
+
+ let submenu = NERDTreeAddSubmenu({
+ \ 'text': 'a (s)ub menu',
+ \ 'shortcut': 's' })
+
+ call NERDTreeAddMenuItem({
+ \ 'text': '(n)ested item 1',
+ \ 'shortcut': 'n',
+ \ 'callback': 'SomeFunction',
+ \ 'parent': submenu })
+
+ call NERDTreeAddMenuItem({
+ \ 'text': '(n)ested item 2',
+ \ 'shortcut': 'n',
+ \ 'callback': 'SomeFunction',
+ \ 'parent': submenu })
+<
+This will create the following menu: >
+ --------------------
+ a (t)op level menu item
+ a (s)ub menu
+<
+Where selecting "a (s)ub menu" will lead to a second menu: >
+ (n)ested item 1
+ (n)ested item 2
+<
+When any of the 3 concrete menu items are selected the function "SomeFunction"
+will be called.
+
+------------------------------------------------------------------------------
+NERDTreeRender() *NERDTreeRender()*
+ Re-renders the NERD tree buffer. Useful if you change the state of the
+ tree and you want to it to be reflected in the UI.
+
+==============================================================================
+5. About *NERDTreeAbout*
+
+The author of the NERD tree is a terrible terrible monster called Martyzilla
+who gobbles up small children with milk and sugar for breakfast.
+
+He can be reached at martin.grenfell at gmail dot com. He would love to hear
+from you, so feel free to send him suggestions and/or comments about this
+plugin. Don't be shy --- the worst he can do is slaughter you and stuff you in
+the fridge for later ;)
+
+The latest stable versions can be found at
+ http://www.vim.org/scripts/script.php?script_id=1658
+
+The latest dev versions are on github
+ http://github.com/scrooloose/nerdtree
+
+
+==============================================================================
+6. Changelog *NERDTreeChangelog*
+
+4.1.0
+ features:
+ - NERDTreeFind to reveal the node for the current buffer in the tree,
+ see |NERDTreeFind|. This effectively merges the FindInNERDTree plugin (by
+ Doug McInnes) into the script.
+ - make NERDTreeQuitOnOpen apply to the t/T keymaps too. Thanks to Stefan
+ Ritter and Rémi Prévost.
+ - truncate the root node if wider than the tree window. Thanks to Victor
+ Gonzalez.
+
+ bugfixes:
+ - really fix window state restoring
+ - fix some win32 path escaping issues. Thanks to Stephan Baumeister, Ricky,
+ jfilip1024, and Chris Chambers
+
+4.0.0
+ - add a new programmable menu system (see :help NERDTreeMenu).
+ - add new APIs to add menus/menu-items to the menu system as well as
+ custom key mappings to the NERD tree buffer (see :help NERDTreeAPI).
+ - removed the old API functions
+ - added a mapping to maximize/restore the size of nerd tree window, thanks
+ to Guillaume Duranceau for the patch. See :help NERDTree-A for details.
+
+ - fix a bug where secondary nerd trees (netrw hijacked trees) and
+ NERDTreeQuitOnOpen didnt play nicely, thanks to Curtis Harvey.
+ - fix a bug where the script ignored directories whose name ended in a dot,
+ thanks to Aggelos Orfanakos for the patch.
+ - fix a bug when using the x mapping on the tree root, thanks to Bryan
+ Venteicher for the patch.
+ - fix a bug where the cursor position/window size of the nerd tree buffer
+ wasnt being stored on closing the window, thanks to Richard Hart.
+ - fix a bug where NERDTreeMirror would mirror the wrong tree
+
+3.1.1
+ - fix a bug where a non-listed no-name buffer was getting created every
+ time the tree windows was created, thanks to Derek Wyatt and owen1
+ - make <CR> behave the same as the 'o' mapping
+ - some helptag fixes in the doc, thanks strull
+ - fix a bug when using :set nohidden and opening a file where the previous
+ buf was modified. Thanks iElectric
+ - other minor fixes
+
+3.1.0
+ New features:
+ - add mappings to open files in a vsplit, see :help NERDTree-s and :help
+ NERDTree-gs
+ - make the statusline for the nerd tree window default to something
+ hopefully more useful. See :help 'NERDTreeStatusline'
+ Bugfixes:
+ - make the hijack netrw functionality work when vim is started with "vim
+ <some dir>" (thanks to Alf Mikula for the patch).
+ - fix a bug where the CWD wasnt being changed for some operations even when
+ NERDTreeChDirMode==2 (thanks to Lucas S. Buchala)
+ - add -bar to all the nerd tree :commands so they can chain with other
+ :commands (thanks to tpope)
+ - fix bugs when ignorecase was set (thanks to nach)
+ - fix a bug with the relative path code (thanks to nach)
+ - fix a bug where doing a :cd would cause :NERDTreeToggle to fail (thanks nach)
+
+
+3.0.1
+ Bugfixes:
+ - fix bugs with :NERDTreeToggle and :NERDTreeMirror when 'hidden
+ was not set
+ - fix a bug where :NERDTree <path> would fail if <path> was relative and
+ didnt start with a ./ or ../ Thanks to James Kanze.
+ - make the q mapping work with secondary (:e <dir> style) trees,
+ thanks to jamessan
+ - fix a bunch of small bugs with secondary trees
+
+ More insane refactoring.
+
+3.0.0
+ - hijack netrw so that doing an :edit <directory> will put a NERD tree in
+ the window rather than a netrw browser. See :help 'NERDTreeHijackNetrw'
+ - allow sharing of trees across tabs, see :help :NERDTreeMirror
+ - remove "top" and "bottom" as valid settings for NERDTreeWinPos
+ - change the '<tab>' mapping to 'i'
+ - change the 'H' mapping to 'I'
+ - lots of refactoring
+
+==============================================================================
+7. Credits *NERDTreeCredits*
+
+Thanks to the following people for testing, bug reports, ideas etc. Without
+you I probably would have got bored of the hacking the NERD tree and
+just downloaded pr0n instead.
+
+ Tim Carey-Smith (halorgium)
+ Vigil
+ Nick Brettell
+ Thomas Scott Urban
+ Terrance Cohen
+ Yegappan Lakshmanan
+ Jason Mills
+ Michael Geddes (frogonwheels)
+ Yu Jun
+ Michael Madsen
+ AOYAMA Shotaro
+ Zhang Weiwu
+ Niels Aan de Brugh
+ Olivier Yiptong
+ Zhang Shuhan
+ Cory Echols
+ Piotr Czachur
+ Yuan Jiang
+ Matan Nassau
+ Maxim Kim
+ Charlton Wang
+ Matt Wozniski (godlygeek)
+ knekk
+ Sean Chou
+ Ryan Penn
+ Simon Peter Nicholls
+ Michael Foobar
+ Tomasz Chomiuk
+ Denis Pokataev
+ Tim Pope (tpope)
+ James Kanze
+ James Vega (jamessan)
+ Frederic Chanal (nach)
+ Alf Mikula
+ Lucas S. Buchala
+ Curtis Harvey
+ Guillaume Duranceau
+ Richard Hart (hates)
+ Doug McInnes
+ Stefan Ritter
+ Rémi Prévost
+ Victor Gonzalez
+ Stephan Baumeister
+ Ricky
+ jfilip1024
+ Chris Chambers
+
+==============================================================================
+8. License *NERDTreeLicense*
+
+The NERD tree is released under the wtfpl.
+See http://sam.zoy.org/wtfpl/COPYING.
diff --git a/modules/vim/vim/doc/bufexplorer.txt b/modules/vim/vim/doc/bufexplorer.txt
new file mode 100644
index 0000000..9af0682
--- /dev/null
+++ b/modules/vim/vim/doc/bufexplorer.txt
@@ -0,0 +1,442 @@
+*bufexplorer.txt* Buffer Explorer Last Change: 19 Nov 2008
+
+Buffer Explorer *buffer-explorer* *bufexplorer*
+ Version 7.2.2
+
+Plugin for easily exploring (or browsing) Vim |:buffers|.
+
+|bufexplorer-usage| Usage
+|bufexplorer-installation| Installation
+|bufexplorer-customization| Customization
+|bufexplorer-changelog| Change Log
+|bufexplorer-todo| Todo
+|bufexplorer-credits| Credits
+
+For Vim version 7.0 and above.
+This plugin is only available if 'compatible' is not set.
+
+{Vi does not have any of this}
+
+==============================================================================
+INSTALLATION *bufexplorer-installation*
+
+To install:
+ - Download the bufexplorer.zip.
+ - Extract the zip archive into your runtime directory.
+ The archive contains plugin/bufexplorer.vim, and doc/bufexplorer.txt.
+ - Start Vim or goto an existing instance of Vim.
+ - Execute the following command:
+>
+ :helptag <your runtime directory/doc
+<
+ This will generate all the help tags for any file located in the doc
+ directory.
+
+==============================================================================
+USAGE *bufexplorer-usage*
+
+To start exploring in the current window, use: >
+ \be OR :BufExplorer
+To start exploring in a newly split horizontal window, use: >
+ \bs or :HSBufExplorer
+To start exploring in a newly split vertical window, use: >
+ \bv or :VSBufExplorer
+
+If you would like to use something other than '\', you may simply change the
+leader (see |mapleader|).
+
+Note: If the current buffer is modified when bufexplorer started, the current
+ window is always split and the new bufexplorer is displayed in that new
+ window.
+
+Commands to use once exploring:
+
+ <enter> Opens the buffer that is under the cursor into the current
+ window.
+ <F1> Toggle help information.
+ <leftmouse> Opens the buffer that is under the cursor into the current
+ window.
+ <shift-enter> Opens the buffer that is under the cursor in another tab.
+ d |:wipeout| the buffer under the cursor from the list.
+ When a buffers is wiped, it will not be shown when unlisted
+ buffer are displayed.
+ D |:delete| the buffer under the cursor from the list.
+ The buffer's 'buflisted' is cleared. This allows for the buffer
+ to be displayed again using the 'show unlisted' command.
+ f Toggles whether you are taken to the active window when
+ selecting a buffer or not.
+ p Toggles the showing of a split filename/pathname.
+ q Quit exploring.
+ r Reverses the order the buffers are listed in.
+ R Toggles relative path/absolute path.
+ s Selects the order the buffers are listed in. Either by buffer
+ number, file name, file extension, most recently used (MRU), or
+ full path.
+ t Opens the buffer that is under the cursor in another tab.
+ u Toggles the showing of "unlisted" buffers.
+
+Once invoked, Buffer Explorer displays a sorted list (MRU is the default
+sort method) of all the buffers that are currently opened. You are then
+able to move the cursor to the line containing the buffer's name you are
+wanting to act upon. Once you have selected the buffer you would like,
+you can then either open it, close it(delete), resort the list, reverse
+the sort, quit exploring and so on...
+
+===============================================================================
+CUSTOMIZATION *bufexplorer-customization*
+
+ *g:bufExplorerDefaultHelp*
+To control whether the default help is displayed or not, use: >
+ let g:bufExplorerDefaultHelp=0 " Do not show default help.
+ let g:bufExplorerDefaultHelp=1 " Show default help.
+The default is to show the default help.
+
+ *g:bufExplorerDetailedHelp*
+To control whether detailed help is display by, use: >
+ let g:bufExplorerDetailedHelp=0 " Do not show detailed help.
+ let g:bufExplorerDetailedHelp=1 " Show detailed help.
+The default is NOT to show detailed help.
+
+ *g:bufExplorerFindActive*
+To control whether you are taken to the active window when selecting a buffer,
+use: >
+ let g:bufExplorerFindActive=0 " Do not go to active window.
+ let g:bufExplorerFindActive=1 " Go to active window.
+The default is to be taken to the active window.
+
+ *g:bufExplorerReverseSort*
+To control whether to sort the buffer in reverse order or not, use: >
+ let g:bufExplorerReverseSort=0 " Do not sort in reverse order.
+ let g:bufExplorerReverseSort=1 " Sort in reverse order.
+The default is NOT to sort in reverse order.
+
+ *g:bufExplorerShowDirectories*
+Directories usually show up in the list from using a command like ":e .".
+To control whether to show directories in the buffer list or not, use: >
+ let g:bufExplorerShowDirectories=1 " Show directories.
+ let g:bufExplorerShowDirectories=0 " Don't show directories.
+The default is to show directories.
+
+ *g:bufExplorerShowRelativePath*
+To control whether to show absolute paths or relative to the current
+directory, use: >
+ let g:bufExplorerShowRelativePath=0 " Show absolute paths.
+ let g:bufExplorerShowRelativePath=1 " Show relative paths.
+The default is to show absolute paths.
+
+ *g:bufExplorerShowUnlisted*
+To control whether to show unlisted buffer or not, use: >
+ let g:bufExplorerShowUnlisted=0 " Do not show unlisted buffers.
+ let g:bufExplorerShowUnlisted=1 " Show unlisted buffers.
+The default is to NOT show unlisted buffers.
+
+ *g:bufExplorerSortBy*
+To control what field the buffers are sorted by, use: >
+ let g:bufExplorerSortBy='extension' " Sort by file extension.
+ let g:bufExplorerSortBy='fullpath' " Sort by full file path name.
+ let g:bufExplorerSortBy='mru' " Sort by most recently used.
+ let g:bufExplorerSortBy='name' " Sort by the buffer's name.
+ let g:bufExplorerSortBy='number' " Sort by the buffer's number.
+The default is to sort by mru.
+
+ *g:bufExplorerSplitBelow*
+To control where the new split window will be placed above or below the
+current window, use: >
+ let g:bufExplorerSplitBelow=1 " Split new window below current.
+ let g:bufExplorerSplitBelow=0 " Split new window above current.
+The default is to use what ever is set by the global &splitbelow
+variable.
+
+ *g:bufExplorerSplitOutPathName*
+To control whether to split out the path and file name or not, use: >
+ let g:bufExplorerSplitOutPathName=1 " Split the path and file name.
+ let g:bufExplorerSplitOutPathName=0 " Don't split the path and file
+ " name.
+The default is to split the path and file name.
+
+ *g:bufExplorerSplitRight*
+To control where the new vsplit window will be placed to the left or right of
+current window, use: >
+ let g:bufExplorerSplitRight=0 " Split left.
+ let g:bufExplorerSplitRight=1 " Split right.
+The default is to use the global &splitright.
+
+===============================================================================
+CHANGE LOG *bufexplorer-changelog*
+
+7.2.2 - Fix:
+ * Thanks to David L. Dight for spotting and fixing an issue when
+ using ctrl^. bufexplorer would incorrectly handle the previous
+ buffer so that when ctrl^ was pressed the incorrect file was opened.
+7.2.1 - Fix:
+ * Thanks to Dimitar for spotting and fixing a feature that was
+ inadvertently left out of the previous version. The feature was
+ when bufexplorer was used together with WinManager, you could use
+ the tab key to open a buffer in a split window.
+7.2.0 - Enhancements:
+ * For all those missing the \bs and \bv commands, these have now
+ returned. Thanks to Phil O'Connell for asking for the return of
+ these missing features and helping test out this version.
+ Fixes:
+ * Fixed problem with the bufExplorerFindActive code not working
+ correctly.
+ * Fixed an incompatibility between bufexplorer and netrw that caused
+ buffers to be incorrectly removed from the MRU list.
+7.1.7 - Fixes:
+ * TaCahiroy fixed several issues related to opening a buffer in a
+ tab.
+7.1.6 - Fixes:
+ * Removed ff=unix from modeline in bufexplorer.txt. Found by Bill
+ McCarthy.
+7.1.5 - Fixes:
+ * Could not open unnamed buffers. Fixed by TaCahiroy.
+7.1.4 - Fixes:
+ * Sometimes when a file's path has 'white space' in it, extra buffers
+ would be created containing each piece of the path. i.e:
+ opening c:\document and settings\test.txt would create a buffer
+ named "and" and a buffer named "Documents". This was reported and
+ fixed by TaCa Yoss.
+7.1.3 - Fixes:
+ * Added code to allow only one instance of the plugin to run at a
+ time. Thanks Dennis Hostetler.
+7.1.2 - Fixes:
+ * Fixed a jumplist issue spotted by JiangJun. I overlooked the
+ 'jumplist' and with a couple calls to 'keepjumps', everything is
+ fine again.
+ * Went back to just having a plugin file, no autoload file. By having
+ the autoload, WinManager was no longer working and without really
+ digging into the cause, it was easier to go back to using just a
+ plugin file.
+7.1.1 - Fixes:
+ * A problem spotted by Thomas Arendsen Hein.
+ When running Vim (7.1.94), error E493 was being thrown.
+ Enhancements:
+ * Added 'D' for 'delete' buffer as the 'd' command was a 'wipe'
+ buffer.
+7.1.0 - Another 'major' update, some by Dave Larson, some by me.
+ * Making use of 'autoload' now to make the plugin load quicker.
+ * Removed '\bs' and '\bv'. These are now controlled by the user. The
+ user can issue a ':sp' or ':vs' to create a horizontal or vertical
+ split window and then issue a '\be'
+ * Added handling of tabs.
+7.0.17 - Fixed issue with 'drop' command.
+ Various enhancements and improvements.
+7.0.16 - Fixed issue reported by Liu Jiaping on non Windows systems, which was
+ ...
+ Open file1, open file2, modify file1, open bufexplorer, you get the
+ following error:
+
+ --------8<--------
+ Error detected while processing function
+ <SNR>14_StartBufExplorer..<SNR>14_SplitOpen:
+ line 4:
+ E37: No write since last change (add ! to override)
+
+ But the worse thing is, when I want to save the current buffer and
+ type ':w', I get another error message:
+ E382: Cannot write, 'buftype' option is set
+ --------8<--------
+
+7.0.15 - Thanks to Mark Smithfield for suggesting bufexplorer needed to handle
+ the ':args' command.
+7.0.14 - Thanks to Randall Hansen for removing the requirement of terminal
+ versions to be recompiled with 'gui' support so the 'drop' command
+ would work. The 'drop' command is really not needed in terminal
+ versions.
+7.0.13 - Fixed integration with WinManager.
+ Thanks to Dave Eggum for another update.
+ - Fix: The detailed help didn't display the mapping for toggling
+ the split type, even though the split type is displayed.
+ - Fixed incorrect description in the detailed help for toggling
+ relative or full paths.
+ - Deprecated s:ExtractBufferNbr(). Vim's str2nr() does the same
+ thing.
+ - Created a s:Set() function that sets a variable only if it hasn't
+ already been defined. It's useful for initializing all those
+ default settings.
+ - Removed checks for repetitive command definitions. They were
+ unnecessary.
+ - Made the help highlighting a little more fancy.
+ - Minor reverse compatibility issue: Changed ambiguous setting
+ names to be more descriptive of what they do (also makes the code
+ easier to follow):
+ Changed bufExplorerSortDirection to bufExplorerReverseSort
+ Changed bufExplorerSplitType to bufExplorerSplitVertical
+ Changed bufExplorerOpenMode to bufExplorerUseCurrentWindow
+ - When the BufExplorer window closes, all the file-local marks are
+ now deleted. This may have the benefit of cleaning up some of the
+ jumplist.
+ - Changed the name of the parameter for StartBufExplorer from
+ "split" to "open". The parameter is a string which specifies how
+ the buffer will be open, not if it is split or not.
+ - Deprecated DoAnyMoreBuffersExist() - it is a one line function
+ only used in one spot.
+ - Created four functions (SplitOpen(), RebuildBufferList(),
+ UpdateHelpStatus() and ReSortListing()) all with one purpose - to
+ reduce repeated code.
+ - Changed the name of AddHeader() to CreateHelp() to be more
+ descriptive of what it does. It now returns an array instead of
+ updating the window directly. This has the benefit of making the
+ code more efficient since the text the function returns is used a
+ little differently in the two places the function is called.
+ - Other minor simplifications.
+7.0.12 - MAJOR Update.
+ This version will ONLY run with Vim version 7.0 or greater.
+ Dave Eggum has made some 'significant' updates to this latest
+ version:
+ - Added BufExplorerGetAltBuf() global function to be used in the
+ user’s rulerformat.
+ - Added g:bufExplorerSplitRight option.
+ - Added g:bufExplorerShowRelativePath option with mapping.
+ - Added current line highlighting.
+ - The split type can now be changed whether bufexplorer is opened
+ in split mode or not.
+ - Various major and minor bug fixes and speed improvements.
+ - Sort by extension.
+ Other improvements/changes:
+ - Changed the help key from '?' to <F1> to be more 'standard'.
+ - Fixed splitting of vertical bufexplorer window.
+ Hopefully I have not forgot something :)
+7.0.11 - Fixed a couple of highlighting bugs, reported by David Eggum. He also
+ changed passive voice to active on a couple of warning messages.
+7.0.10 - Fixed bug report by Xiangjiang Ma. If the 'ssl' option is set,
+ the slash character used when displaying the path was incorrect.
+7.0.9 - Martin Grenfell found and eliminated an annoying bug in the
+ bufexplorer/winmanager integration. The bug was were an
+ annoying message would be displayed when a window was split or
+ a new file was opened in a new window. Thanks Martin!
+7.0.8 - Thanks to Mike Li for catching a bug in the WinManager integration.
+ The bug was related to the incorrect displaying of the buffer
+ explorer's window title.
+7.0.7 - Thanks to Jeremy Cowgar for adding a new enhancement. This
+ enhancement allows the user to press 'S', that is capital S, which
+ will open the buffer under the cursor in a newly created split
+ window.
+7.0.6 - Thanks to Larry Zhang for finding a bug in the "split" buffer code.
+ If you force set g:bufExplorerSplitType='v' in your vimrc, and if you
+ tried to do a \bs to split the bufexplorer window, it would always
+ split horizontal, not vertical. He also found that I had a typeo in
+ that the variable g:bufExplorerSplitVertSize was all lower case in
+ the documentation which was incorrect.
+7.0.5 - Thanks to Mun Johl for pointing out a bug that if a buffer was
+ modified, the '+' was not showing up correctly.
+7.0.4 - Fixed a problem discovered first by Xiangjiang Ma. Well since I've
+ been using vim 7.0 and not 6.3, I started using a function (getftype)
+ that is not in 6.3. So for backward compatibility, I conditionaly use
+ this function now. Thus, the g:bufExplorerShowDirectories feature is
+ only available when using vim 7.0 and above.
+7.0.3 - Thanks to Erwin Waterlander for finding a problem when the last
+ buffer was deleted. This issue got me to rewrite the buffer display
+ logic (which I've wanted to do for sometime now).
+ Also great thanks to Dave Eggum for coming up with idea for
+ g:bufExplorerShowDirectories. Read the above information about this
+ feature.
+7.0.2 - Thanks to Thomas Arendsen Hein for finding a problem when a user
+ has the default help turned off and then brought up the explorer. An
+ E493 would be displayed.
+7.0.1 - Thanks to Erwin Waterlander for finding a couple problems.
+ The first problem allowed a modified buffer to be deleted. Opps! The
+ second problem occurred when several files were opened, BufExplorer
+ was started, the current buffer was deleted using the 'd' option, and
+ then BufExplorer was exited. The deleted buffer was still visible
+ while it is not in the buffers list. Opps again!
+7.0.0 - Thanks to Shankar R. for suggesting to add the ability to set
+ the fixed width (g:bufExplorerSplitVertSize) of a new window
+ when opening bufexplorer vertically and fixed height
+ (g:bufExplorerSplitHorzSize) of a new window when opening
+ bufexplorer horizontally. By default, the windows are normally
+ split to use half the existing width or height.
+6.3.0 - Added keepjumps so that the jumps list would not get cluttered with
+ bufexplorer related stuff.
+6.2.3 - Thanks to Jay Logan for finding a bug in the vertical split position
+ of the code. When selecting that the window was to be split
+ vertically by doing a '\bv', from then on, all splits, i.e. '\bs',
+ were split vertically, even though g:bufExplorerSplitType was not set
+ to 'v'.
+6.2.2 - Thanks to Patrik Modesto for adding a small improvement. For some
+ reason his bufexplorer window was always showing up folded. He added
+ 'setlocal nofoldenable' and it was fixed.
+6.2.1 - Thanks goes out to Takashi Matsuo for added the 'fullPath' sorting
+ logic and option.
+6.2.0 - Thanks goes out to Simon Johann-Ganter for spotting and fixing a
+ problem in that the last search pattern is overridden by the search
+ pattern for blank lines.
+6.1.6 - Thanks to Artem Chuprina for finding a pesky bug that has been around
+ for sometime now. The <esc> key mapping was causing the buffer
+ explored to close prematurely when vim was run in an xterm. The <esc>
+ key mapping is now removed.
+6.1.5 - Thanks to Khorev Sergey. Added option to show default help or not.
+6.1.4 - Thanks goes out to Valery Kondakoff for suggesting the addition of
+ setlocal nonumber and foldcolumn=0. This allows for line numbering
+ and folding to be turned off temporarily while in the explorer.
+6.1.3 - Added folding. Did some code cleanup. Added the ability to force the
+ newly split window to be temporarily vertical, which was suggested by
+ Thomas Glanzmann.
+6.1.2 - Now pressing the <esc> key will quit, just like 'q'.
+ Added folds to hide winmanager configuration.
+ If anyone had the 'C' option in their cpoptions they would receive
+ a E10 error on startup of BufExplorer. cpo is now saved, updated and
+ restored. Thanks to Charles E Campbell, Jr.
+ Attempted to make sure there can only be one BufExplorer window open
+ at a time.
+6.1.1 - Thanks to Brian D. Goodwin for adding toupper to FileNameCmp. This
+ way buffers sorted by name will be in the correct order regardless of
+ case.
+6.0.16 - Thanks to Andre Pang for the original patch/idea to get bufexplorer
+ to work in insertmode/modeless mode (evim). Added Initialize
+ and Cleanup autocommands to handle commands that need to be
+ performed when starting or leaving bufexplorer.
+6.0.15 - Srinath Avadhanulax added a patch for winmanager.vim.
+6.0.14 - Fix a few more bug that I thought I already had fixed. Thanks
+ to Eric Bloodworth for adding 'Open Mode/Edit in Place'. Added
+ vertical splitting.
+6.0.13 - Thanks to Charles E Campbell, Jr. for pointing out some embarrassing
+ typos that I had in the documentation. I guess I need to run
+ the spell checker more :o)
+6.0.12 - Thanks to Madoka Machitani, for the tip on adding the augroup command
+ around the MRUList autocommands.
+6.0.11 - Fixed bug report by Xiangjiang Ma. '"=' was being added to the
+ search history which messed up hlsearch.
+6.0.10 - Added the necessary hooks so that the Srinath Avadhanula's
+ winmanager.vim script could more easily integrate with this script.
+ Tried to improve performance.
+6.0.9 - Added MRU (Most Recently Used) sort ordering.
+6.0.8 - Was not resetting the showcmd command correctly.
+ Added nifty help file.
+6.0.7 - Thanks to Brett Carlane for some great enhancements. Some are added,
+ some are not, yet. Added highlighting of current and alternate
+ filenames. Added splitting of path/filename toggle. Reworked
+ ShowBuffers().
+ Changed my email address.
+6.0.6 - Copyright notice added. Needed this so that it could be distributed
+ with Debian Linux. Fixed problem with the SortListing() function
+ failing when there was only one buffer to display.
+6.0.5 - Fixed problems reported by David Pascoe, in that you where unable to
+ hit 'd' on a buffer that belonged to a files that no longer existed
+ and that the 'yank' buffer was being overridden by the help text when
+ the bufexplorer was opened.
+6.0.4 - Thanks to Charles Campbell, Jr. for making this plugin more plugin
+ *compliant*, adding default keymappings of <Leader>be and <Leader>bs
+ as well as fixing the 'w:sortDirLabel not being defined' bug.
+6.0.3 - Added sorting capabilities. Sort taken from explorer.vim.
+6.0.2 - Can't remember.
+6.0.1 - Initial release.
+
+===============================================================================
+TODO *bufexplorer-todo*
+
+- The issuing of a ':bd' command does not always remove the buffer number from
+ the MRU list.
+
+===============================================================================
+CREDITS *bufexplorer-credits*
+
+Author: Jeff Lanzarotta <delux256-vim at yahoo dot com>
+
+Credit must go out to Bram Moolenaar and all the Vim developers for
+making the world's best editor (IMHO). I also want to thank everyone who
+helped and gave me suggestions. I wouldn't want to leave anyone out so I
+won't list names.
+
+===============================================================================
+vim:tw=78:noet:wrap:ts=8:ft=help:norl:
diff --git a/modules/vim/vim/doc/git-vim.txt b/modules/vim/vim/doc/git-vim.txt
new file mode 100644
index 0000000..5fba807
--- /dev/null
+++ b/modules/vim/vim/doc/git-vim.txt
@@ -0,0 +1,95 @@
+*git-vim.txt* Git Bindings for Vim
+
+==============================================================================
+CONTENTS *git-vim-contents*
+
+ 1. Introduction.............................|git-vim|
+ 2. Commands.................................|git-vim-commands|
+ 3. Keymaps..................................|git-vim-keymaps|
+ 4. License..................................|git-vim-license|
+
+==============================================================================
+1. Introduction *git-vim*
+
+Git-vim provides:
+
+* Plugin files for calling git functions from inside Vim
+* Syntax files for git displays
+
+==============================================================================
+2. Commands *git-vim-commands*
+
+:GitAdd <file>
+ git-add <file> or current file if not specified.
+
+:GitCommit <args>
+ git-commit.
+
+:GitStatus
+ Show git-status of current file or repository.
+
+:GitLog
+ Show git-log of current file or repository.
+
+:GitCheckout <args>
+ git-checkout. Completes git commits.
+
+:GitDiff <args>
+ git-diff. Completes git commits.
+
+:GitPull <args>
+ git-pull.
+
+:GitPullRebase
+ git-pull —rebase.
+
+:GitPush <args>
+ git-push. Defaults to +git push origin <current-branch>+.
+
+:GitCatFile <args>
+ git-cat-file.
+
+:Git <args>
+ Does any git command.
+
+:GitVimDiffMerge
+ Experimental. Call this command on unmerged file to enter vimdiff mode.
+
+:GitVimDiffMergeDone
+ Call this command after merging.
+
+==============================================================================
+3. Keymaps *git-vim-keymaps*
+
+<Leader>gd
+ :GitDiff
+
+<Leader>gD
+ :GitDiff —cached
+
+<Leader>gs
+ :GitStatus
+
+<Leader>gl
+ :GitLog
+
+<Leader>ga
+ :GitAdd
+
+<Leader>gA
+ :GitAdd <cfile>
+
+<Leader>gc
+ :GitCommit
+
+In the git-status buffer:
+
+<Enter>
+ :GitAdd <cfile>
+
+==============================================================================
+4. License *git-vim-license*
+
+The MIT License
+
+ vim:tw=78:ts=8:ft=help
diff --git a/modules/vim/vim/doc/indexer.txt b/modules/vim/vim/doc/indexer.txt
new file mode 100644
index 0000000..330b486
--- /dev/null
+++ b/modules/vim/vim/doc/indexer.txt
@@ -0,0 +1,211 @@
+*indexer.txt* Plugin for automatically index project files using ctags
+ For Vim 7.x version
+
+
+
+ By Dmitry Frank
+ dimon.frank email-at-sign gmail.com
+
+
+ *indexer* *indexer-plugin*
+ Contents:
+
+ Options.....................|indexer-options|
+ Commands...................|indexer-commands|
+
+You can use this plugin to automatically index your project files
+using ctags. This can be very useful when it's used together with plugins
+omnicppcomplete (for c, c++ development), code_complete.vim
+and other plugins that using tags.
+You also will able to jump from function call to its definition
+just by pressing Ctrl-] or g]
+
+This plugin can work as add-on for project.tar.gz plugin.
+Indexer reads project file, parses it and builds tags for all files
+in project. But it can also work without this plugin.
+
+Actually, if you using project.vim plugin and you projects file is
+default (~/.vimprojects), then setting indexer up is very easily:
+you can just copy indexer.vim to your plugins directory, start Vim
+and open any file from your project.
+The indexer plugin will detect that opened file from project
+and automatically start ctags for each file in this project.
+It also set &path and &tags options for Vim.
+
+If you are using project.vim but you have another projects file,
+you should set option g:indexer_projectsSettingsFilename in your
+vimrc. See |indexer-options| for details
+
+If you don't use project.vim then you can use ".indexer_files" to
+define projects to index.
+Default location of this file is "~/.indexer_files". You can change
+it by modifying variable g:indexer_indexerListFilename
+
+Note that this file overrides "~/.vimprojects". If both files exists
+only "~/.indexer_files" will be used.
+
+Syntax of this file is very easy. Propably the best way to explain it
+is show an example.
+
+Example file "~/.indexer_files" >
+ [CoolProject]
+
+ /home/user/myproject/src/*.c
+ /home/user/myproject/src/*.h
+ /home/user/myproject/inc/*.h
+
+ [AnotherProject]
+
+ /home/user/myproject2**/*.c
+ /home/user/myproject2**/*.h
+
+
+I think, there's all obvious:
+there's two projects: CoolProject and AnotherProject.
+in CoolProject there's all *.c files in "myproject/src" and all header
+files in "myproject/inc". in AnotherProject there's both *.c and *.h
+files in "myproject2" and all subdirectories recursively.
+( "**" means recursively )
+It's able to use environment variables in your paths.
+
+You can define the same AnotherProject simplier:
+ >
+ [AnotherProject]
+
+ /home/user/myproject2**/*.[ch]
+
+And, finally, it can autodetect project root. So, you can move your
+project to another place in filesystem, and all files will indexed anyway.
+More detailed see in options, variable "g:indexer_lookForProjectDir".
+
+========================================================================
+OPTIONS *indexer-options*
+
+You can set these variables in your vimrc file before the plugin is loaded to
+change its default behavior
+
+g:indexer_lookForProjectDir (default: 1)
+
+ if on, then plugin will recursively-up search for ".vimprj" directory.
+ If it will be found, then plugin will source all "*.vim" files in it,
+ and also will set environment variable $INDEXER_PROJECT_ROOT to
+ directory in which is ".vimprj" directory.
+
+ Your directory tree example:
+
+ | home
+ | | user
+ | | | myproject
+ | | | | src
+ | | | | |-file1.c
+ | | | | |-file2.c
+ | | | | |-file3.c
+ | | | | |
+ | | | | inc
+ | | | | |-file1.h
+ | | | | |-file2.h
+ | | | | |-file3.h
+ | | | | |
+ | | | | .vimprj
+ | | | | |-conf.vim
+
+ For example, you typing: >
+ $ gvim /home/user/myproject/src/file1.c
+----
+
+ Then indexer will detect your /home/user/myproject/.vimprj directory
+ and source all files *.vim from it,
+ and set $INDEXER_PROJECT_ROOT="/home/user/myproject"
+
+ so, you can define any settings that are individual for
+ your project, such as another .vimprojects file, or any other.
+
+ This is great for people like me, that likes when ALL project files
+ is in only one directory.
+
+ When i need to copy project to another computer i just copying the
+ whole folder, and all is done. I using $INDEXER_PROJECT_ROOT variable
+ in my .vimprojects file, so that i can put project in any place in
+ filesystem, and all files will be indexed, because
+ $INDEXER_PROJECT_ROOT will be always my real project root.
+
+g:indexer_dirNameForSearch (default: ".vimprj")
+
+ directory name with project settings for search (".vimprj" by default)
+
+g:indexer_recurseUpCount (default: 10)
+
+ count of recurse-up for search ".vimprj" directory
+
+g:indexer_indexerListFilename (default: "~/.indexer_files")
+
+ indexer filename. If this file exists then projects file are ignored.
+
+g:indexer_projectsSettingsFilename (default: "~/.vimprojects")
+
+ project filename. (the project file that plugin project.vim using)
+
+g:indexer_projectName (default: '')
+
+ if you don't wand to index any project, you can define one name.
+ If it is empty, then indexes any found projects.
+ By default is empty.
+
+g:indexer_enableWhenProjectDirFound (default: 1)
+
+ If this option is set, then if gvim started from project directory, this project
+ will be indexed. Otherwise project will be indexed only if there's file
+ from this project opened
+
+g:indexer_tagsDirname (default: "~/.vimtags")
+
+ directory to save tags file. (this is directory because there's propably
+ several files in next versions)
+
+ Note: If ".vimprj" directory is found, then this option is ignored and tags
+ directory becomes ".vimprj/tags"
+
+g:indexer_ctagsCommandLineOptions
+
+ ctags command line options. By default is:
+ "--c++-kinds=+p+l --fields=+iaS --extra=+q"
+
+g:indexer_ctagsJustAppendTagsAtFileSave (default: 1)
+
+ when there's project file saving, we need to update tags.
+ If this option is on, then ctags will be started just for
+ current file with "-a" key, otherwise tags for all project
+ files will be rebuild.
+
+ There is different sides:
+ If just append tags, then old tags will not be removed until
+ you rebuild all tags by typing ":IndexerRebuild" or just restart
+ Vim. If rebuild tags every time, it would take long time
+ (depending on project size, of course)
+
+ By default this option is on.
+
+========================================================================
+COMMANDS *indexer-commands*
+
+:IndexerInfo
+
+ prints information about current state of plugin, such as projects file
+ using, files not found, and other.
+
+ The first thing you should do if plugin doesn't work is type this command :)
+
+:IndexerFiles
+
+ prints list of indexed files
+
+:IndexerRebuild
+
+ rebuild tags for all files in project
+
+:IndexerFilesAvail
+
+ prints list of all available files that has been read from projects file
+
+
+ vim:ft=help:tw=78:
diff --git a/modules/vim/vim/doc/project.txt b/modules/vim/vim/doc/project.txt
new file mode 100644
index 0000000..8f85c23
--- /dev/null
+++ b/modules/vim/vim/doc/project.txt
@@ -0,0 +1,710 @@
+*project.txt* Plugin for managing multiple projects with multiple sources
+ For Vim version 6.x and Vim version 7.x.
+ Last Change: Fri 13 Oct 2006 10:20:13 AM EDT
+
+
+ By Aric Blumer
+ aricvim email-at-sign charter.net
+
+ *project* *project-plugin*
+ Contents:
+
+ Commands...................|project-invoking|
+ Inheritance.............|project-inheritance|
+ Mappings...................|project-mappings|
+ Adding Mappings.....|project-adding-mappings|
+ Settings...................|project-settings|
+ Example File................|project-example|
+ Tips...........................|project-tips|
+
+
+You can use this plugin's basic functionality to set up a list of
+frequently-accessed files for easy navigation. The list of files will be
+displayed in a window on the left side of the Vim window, and you can press
+<Return> or double-click on filenames in the list to open the files. I find
+this easier to use than having to navigate a directory hierarchy with the
+|file-explorer|.
+
+You can also instruct the Plugin to change to a directory and to run Vim
+scripts when you select a file. These scripts can, for example, modify the
+environment to include compilers in $PATH. This makes it very easy to use
+quickfix with multiple projects that use different environments.
+
+Other features include:
+ o Loading/Unloading all the files in a Project (\l, \L, \w, and \W)
+ o Grepping all the files in a Project (\g and \G)
+ o Running a user-specified script on a file (can be used to launch an
+ external program on the file) (\1 through \9)
+ o Running a user-specified script on all the files in a Project
+ (\f1-\f9 and \F1-\F9)
+ o High degree of user-configurability
+ o Also works with |netrw| using the XXXX://... notation where XXXX is
+ ftp, rcp, scp, or http.
+
+All of this is specified within a simple text file and a few global variables
+in your vimrc file.
+
+You must set 'nocompatible' in your |vimrc| file to use this plugin. You can
+stop the plugin from being loaded by setting the "loaded_project" variable: >
+ :let loaded_project = 1
+
+
+==============================================================================
+COMMANDS *project-invoking*
+
+You can use the plugin by placing it in your plugin directory (e.g.,
+~/.vim/plugin). See |add-global-plugin|. When you start vim the next time, you
+then enter the command >
+ :Project
+or >
+ :Project {file}
+
+If you do not specify the filename, $HOME/.vimprojects is used.
+
+To have Vim come up with the Project Window enabled automatically (say, from a
+GUI launcher), run Vim like this: [g]vim +Project
+
+Note that you can invoke :Project on only one file at a time. If you wish to
+change the Project File, do a :bwipe in the Project Buffer, then re-invoke the
+Plugin as described above.
+
+Several Projects can be kept and displayed in the same file, each in a fold
+delimited by { and } (see |fold.txt|). There can be any number of nested
+folds to provide you with a Project hierarchy. Any line without a { or a } in
+the file is considered to be a filename. Blank lines are ignored, and any
+text after a # is ignored.
+
+Because the plugin uses standard Vim folds, you can use any of the
+|fold-commands|. You can double-click on the first line of a fold to open and
+close it. You can select a file to open by putting the cursor on its name and
+pressing <Return> or by double-clicking on it. The plugin will create a new
+window to the right or use the |CTRL-W_p| equivalent if it exists.
+
+ *project-syntax*
+Each Project Entry has this form:
+
+project_entry ::=
+ <Description>={projpath} [{options}] {
+ [ filename ]
+ [ project_entry ]
+ }
+
+{options} is one or more of the following (on the same line):
+ CD={path}
+ in={filename}
+ out={filename}
+ filter="{pat}"
+ flags={flag}
+
+Note that a project_entry can reside within a project_entry. This allows you
+to set up a hierarchy within your Project.
+
+The <Description> will be displayed in the foldtext and cannot contain "=".
+There can be no space character directly on either side of the =.
+
+The {projpath} is the path in which the files listed in the Project's fold
+will be found, and it may contain environment variables. If the path is a
+relative path, then the plugin constructs the whole path from the Project's
+parent, grandparent, etc., all the way up the hierarchy. An outermost
+project_entry must have an absolute path. See the |project-inheritance|
+example below. {projpath} may contain spaces, but they must be escaped like
+normal Vim escapes. Here are two examples of the same directory:
+>
+ Example=/my/directory/with\ spaces {
+ }
+ Example="/my/directory/with spaces" {
+ }
+
+I recommend this for Windows®: >
+
+ Example="c:\My Documents" {
+ }
+
+But Vim is smart enough to do this, too: >
+
+ Example=c:\My\ Documents {
+ }
+
+CD= provides the directory that Vim will change to when you select a file in
+that fold (using |:cd|). This allows you, for example, to enter |:make| to use
+the local Makefile. A CD=. means that Vim will make {projpath} or its
+inherited equivalent the current working directory. When CD is omitted, the
+directory is not changed. There can be no space on either side of the =. The
+value of CD can also be a relative path from a parent's CD. See the
+|project-inheritance| example below. This directive is ignored for |netrw|
+projects. Spaces are allowed in the path as for {projpath}.
+
+in= and out= provide the means to run arbitrary Vim scripts whenever you enter
+or leave a file's buffer (see the |BufEnter| and |BufLeave| autocommand
+events). The idea is to have a Vim script that sets up or tears down the
+environment for the Project like this:
+
+in.vim: >
+ let $PROJECT_HOME='~/my_project'
+ " Put the compiler in $PATH
+ if $PATH !~ '/path/to/my/compiler'
+ let $PATH=$PATH.':/path/to/my/compiler'
+ endif
+
+out.vim: >
+ " Remove compiler from $PATH
+ if $PATH =~ '/path/to/my/compiler'
+ let $PATH=substitute($PATH, ':/path/to/my/compiler', '', 'g')
+ endif
+
+Then you can use :make with the proper environment depending on what file you
+are currently editing. If the path to the script is relative, then it is
+relative from {projpath}. These directives are inherited by Subprojects
+unless the Subproject specifies its own. For use with |netrw| projects, the
+paths specified for in= and out= must be absolute and local.
+
+filter= specifies a |glob()| file pattern. It is used to regenerate the list
+of files in a Project fold when using the \r (<LocalLeader>r) map in the
+Project Window. The filter value must be in quotes because it can contain
+multiple file patterns. If filter is omitted, then the * pattern is used.
+There can be no space on either side of the =. A Subproject will inherit the
+filter of its parent unless it specifies its own filter.
+
+flags= provides the means to enable/disable features for a particular fold.
+The general mnemonic scheme is for lower case to turn something off and upper
+case to turn something on. {flag} can contain any of the following
+characters:
+
+ flag Description ~
+
+ l Turn off recursion for this fold for \L. Subfolds are also
+ blocked from the recursion.
+
+ r Turn off refresh. When present, do not refresh this fold when
+ \r or \R is used. This does not affect subfold recursion.
+
+ S Turn on sorting for refresh and create.
+
+ s Turn off sorting for refresh and create.
+
+ T Turn on top gravity. Forces folds to the top of the current
+ fold when refreshing. It has the same affect as the 'T' flag
+ in g:proj_flags, but controls the feature on a per-fold basis.
+
+ t Turn off top gravity. Forces folds to the bottom of the
+ current fold when refreshing.
+
+ w Turn off recursion for this fold for \W. Subfolds are also
+ blocked from the recursion.
+
+
+Flags are not inherited by Subprojects.
+
+Any text outside a fold is ignored.
+
+
+==============================================================================
+INHERITANCE *project-inheritance*
+
+It's best to show inheritance by comparing these two Project Files:
+>
+ Parent=~/my_project CD=. filter="Make* *.mk" flags=r {
+ Child1=c_code {
+ }
+ Child2=include CD=. filter="*.h" {
+ }
+ }
+
+Child1's path is "~/my_project/c_code" because ~/my_project is inherited. It
+also inherits the CD from Parent. Since Parent has CD=., the Parent's cwd is
+"~/my_project". Child1 therefore inherits a CD of "~/my_project". Finally,
+Child1 inherits the filter from Parent. The flags are not inherited.
+
+Child2 only inherits the "~/my_project" from Parent.
+
+Thus, the example above is exactly equivalent to this:
+>
+ Parent=~/my_project CD=. filter="Make* *.mk" flags=r {
+ Child1=~/my_project/c_code CD=~/my_project filter="Make* *.mk" {
+ }
+ Child2=~/my_project/include CD=~/my_project/include filter="*.h" {
+ }
+ }
+
+(For a real Project, Child1 would not want to inherit its parent's filter, but
+this example shows the concept.) You can always enter \i to display what the
+cursor's project inherits.
+
+
+==============================================================================
+MAPPINGS *project-mappings*
+
+Map Action ~
+
+\r Refreshes the Project fold that the cursor is in by placing in the
+ fold all the files that match the filter. The Project is refreshed
+ using an indent of one space for every foldlevel in the hierarchy.
+
+ You may place a "# pragma keep" (without the quotes) at the end of a
+ line, and the file entry on that line will not be removed when you
+ refresh. This is useful, for example, when you have . as an entry so
+ you can easily browse the directory.
+
+ Note that this mapping is actually <LocalLeader>r, and the default of
+ |<LocalLeader>| is \.
+
+ This does not work for Projects using |netrw|.
+
+\R Executes \r recursively in the current fold and all folds below.
+ This does not work for Projects using |netrw|.
+
+\c Creates a Project fold entry. It asks for the description, the path
+ to the files, the CD parameter, and the filename |glob()| pattern.
+ From this information, it will create the Project Entry below the
+ cursor.
+
+ This does not work for Projects using |netrw|.
+
+\C Creates a Project fold entry like \c, but recursively includes all the
+ subdirectories.
+
+<Return>
+ Select a file to open in the |CTRL-W_p| window or in a new window. If
+ the cursor is on a fold, open or close it.
+
+<S-Return>
+\s
+ Same as <Return> but horizontally split the target window.
+ <LocalLeader>s is provided for those terminals that don't recognize
+ <S-Return>.
+
+\S
+ Load all files in a project by doing horizontal splits.
+
+<C-Return>
+\o
+ Same as <Return> but ensure that the opened file is the only other
+ window. <LocalLeader>o is provided for those terminals that don't
+ recognize <C-Return>.
+
+<M-Return>
+\v
+ Same as <Return> but only display the file--the cursor stays in the
+ Project Window.
+
+<2-LeftMouse>
+ (Double-click) If on a closed fold, open it. If on an open fold
+ boundary, close it. If on a filename, open the file in the |CTRL-W_p|
+ window or in a new window.
+
+<S-2-LeftMouse>
+ Same as <S-Return>.
+
+<C-2-LeftMouse>
+ Same as <C-Return>.
+
+<RightMouse>
+ Increase the width of the Project Window by g:proj_window_increment or
+ toggle between a width of
+ g:proj_window_width + g:proj_window_increment
+ and
+ g:proj_window_width.
+
+ Whether you toggle or monotonically increase the width is determined
+ by the 't' flag of the g:proj_flags variable (see |project-flags|).
+
+ Note that a Right Mouse click will not automatically place the cursor
+ in the Project Window if it is in a different window. The window will
+ go back to the g:proj_window_width width when you leave the window.
+
+<space> Same as <RightMouse>
+
+<CTRL-Up>
+\<Up>
+ Move the text or fold under the cursor up one row. This may not work
+ in a terminal because the terminal is unaware of this key combination.
+ <LocalLeader><Up> is provided for those terminals that don't recognize
+ <C-Up>.
+
+
+<CTRL-Down>
+\<Down>
+ Move the text or fold under the cursor down one row. This may not work
+ in a terminal because the terminal is unaware of this key combination.
+ <LocalLeader><Down> is provided for those terminals that don't
+ recognize <C-Down>.
+
+\i Show in the status line the completely resolved and inherited
+ parameters for the fold the cursor is in. This is intended for
+ debugging your relative path and inherited parameters for manually
+ entered Projects.
+
+\I Show in the status line the completely resolved filename. Uses the
+ Project_GetFname(line('.')) function.
+
+\1 - \9
+ Run the command specified in g:proj_run{x} where {x} is the number
+ of the key. See the documentation of g:proj_run1 below.
+
+\f1-\f9
+ Run the command specified in g:proj_run_fold{x} where {x} is the
+ number of the key. The command is run on the files at the current
+ Project level. See the |project-settings| below.
+
+\F1-\F9
+ Run the command specified in g:proj_run_fold{x} where {x} is the
+ number of the key. The command is run on the files at the current
+ Project level and all Subprojects. See the |project-settings| below.
+
+\0 Display the commands that are defined for \1 through \9.
+
+\f0 Display the commands that are defined for \f1 through \f9 and \F1
+ through \F0. Same as \F0.
+
+\l Load all the files in the current Project level into Vim. While files
+ are being loaded, you may press any key to stop.
+
+\L Load all the files in the current Project and all Subprojects into
+ Vim. Use this mapping with caution--I wouldn't suggest using \L to
+ load a Project with thousands of files. (BTW, my Project file has more
+ than 5,300 files in it!) While files are being loaded, you may press
+ any key to stop.
+
+\w Wipe all the files in the current Project level from Vim. (If files
+ are modified, they will be saved first.) While files are being wiped,
+ you may press any key to stop.
+
+\W Wipe all the files in the current Project and all Subprojects from
+ Vim. (If files are modified, they will be saved first.) While files
+ are being wiped, you may press any key to stop.
+
+\g Grep all the files in the current Project level.
+
+\G Grep all the files in the current Project level and all Subprojects.
+
+\e Set up the Environment for the Project File as though you had selected
+ it with <Return>. This allows you to do a \e and a :make without
+ having to open any files in the project.
+
+\E Explore (using |file-explorer|) the directory of the project the
+ cursor is in. Does not work with netrw.
+
+<F12> When the 'g' flag is present in g:proj_flags (see |project-flags|)
+ this key toggles the Project Window open and closed. You may remap
+ this toggle function by putting the following in your vimrc and
+ replacing <Leader>P with whatever key combination you wish:
+
+ nmap <silent> <Leader>P <Plug>ToggleProject
+
+Note that the Project Plugin remaps :help because the Help Window and the
+Project Window get into a fight over placement. The mapping avoids the
+problem.
+
+==============================================================================
+ADDING MAPPINGS *project-adding-mappings*
+
+You can add your own mappings or change the mappings of the plugin by placing
+them in the file $HOME/.vimproject_mappings. This file, if it exists, will be
+sourced when the plugin in loaded. Here is an example that will count the
+number of entries in a project when you press \K (Kount, C is taken :-): >
+
+ function! s:Wc()
+ let b:loadcount=0
+ function! SpawnExec(infoline, fname, lineno, data)
+ let b:loadcount = b:loadcount + 1
+ if getchar(0) != 0 | let b:stop_everything=1 | endif
+ endfunction
+ call Project_ForEach(1, line('.'), "*SpawnExec", 0, '')
+ delfunction SpawnExec
+ echon b:loadcount." Files\r"
+ unlet b:loadcount
+ if exists("b:stop_everything")
+ unlet b:stop_everything
+ echon "Aborted.\r"
+ endif
+ endfunction
+
+ nnoremap <buffer> <silent> <LocalLeader>K :call <SID>Wc()<CR>
+
+Here's another example of how I integrated the use of perforce with the plugin
+in my $HOME/.vimproject_mappings:
+>
+ function! s:DoP4(cmd)
+ let name=Project_GetFname(line('.'))
+ let dir=substitute(name, '\(.*\)/.*', '\1', 'g')
+ exec 'cd '.dir
+ exec "!".a:cmd.' '.Project_GetFname(line('.'))
+ cd -
+ endfunction
+
+ nmap <buffer> <silent> \pa :call <SID>DoP4("p4add")<CR>
+ nmap <buffer> <silent> \pe :call <SID>DoP4("p4edit")<CR>
+<
+(Note that I CD to the directory the file is in so I can pick of the $P4CONFIG
+file. See the perforce documentation.)
+
+This creates the mappings \pe to check out the file for edit and \pa to add
+the file to the depot.
+
+Here is another example where I remap the <Return> mapping to use an external
+program to launch a special kind of file (in this case, it launches ee to view
+a jpg file). It is a bit contrived, but it works.
+>
+ let s:sid = substitute(maparg('<Return>', 'n'), '.*\(<SNR>.\{-}\)_.*', '\1', '')
+ function! s:LaunchOrWhat()
+ let fname=Project_GetFname(line('.'))
+ if fname =~ '\.jpg$'
+ exec 'silent! !ee "'.fname.'"&'
+ else
+ call {s:sid}_DoFoldOrOpenEntry('', 'e')
+ endif
+ endfunction
+ nnoremap <buffer> <silent> <Return> \|:call <SID>LaunchOrWhat()<CR>
+<
+If the file ends in .jpg, the external program is launched, otherwise the
+original mapping of <Return> is run.
+
+==============================================================================
+SETTINGS *project-settings*
+
+You can set these variables in your vimrc file before the plugin is loaded to
+change its default behavior
+
+g:proj_window_width
+ The width of the Project Window that the plugin attempts to maintain.
+ Default: 24
+
+ The Project Plugin is not always successful in keeping the window
+ where I want it with the size specified here, but it does a decent
+ job.
+
+g:proj_window_increment
+ The increment by which to increase the width of the Project Window
+ when pressing <space> or clicking the <LeftMouse>. Default: 100
+ (See |project-mappings|.)
+
+ *project-flags*
+g:proj_flags
+ Default: "imst"
+ Various flags to control the behavior of the Project Plugin. This
+ variable can contain any of the following character flags.
+
+ flag Description ~
+
+ b When present, use the |browse()| when selecting directories
+ for \c and \C. This is off by default for Windows, because
+ the windows browser does not allow you to select directories.
+
+ c When present, the Project Window will automatically close when
+ you select a file.
+
+ F Float the Project Window. That is, turn off automatic
+ resizing and placement. This allows placement between other
+ windows that wish to share similar placement at the side of
+ the screen. It is also particularly helpful for external
+ window managers.
+
+ g When present, the mapping for <F12> will be created to toggle
+ the Project Window open and closed.
+
+ i When present, display the filename and the current working
+ directory in the command line when a file is selected for
+ opening.
+
+ l When present, the Project Plugin will use the |:lcd| command
+ rather than |:cd| to change directories when you select a file
+ to open. This flag is really obsolete and not of much use
+ because of L below.
+
+ L Similar to l, but install a BufEnter/Leave |:autocommand| to
+ ensure that the current working directory is changed to the
+ one specified in the fold CD specification whenever that
+ buffer is active. (|:lcd| only changes the CWD for a window,
+ not a buffer.)
+
+ m Turn on mapping of the |CTRL-W_o| and |CTRL-W_CTRL_O| normal
+ mode commands to make the current buffer the only visible
+ buffer, but keep the Project Window visible, too.
+
+ n When present, numbers will be turned on for the project
+ window.
+
+ s When present, the Project Plugin will use syntax highlighting
+ in the Project Window.
+
+ S Turn on sorting for refresh and create.
+
+ t When present, toggle the size of the window rather than just
+ increase the size when pressing <space> or right-clicking.
+ See the entry for <RightMouse> in |project-mappings|.
+
+ T When present, put Subproject folds at the top of the fold when
+ refreshing.
+
+ v When present, use :vimgrep rather than :grep when using \G.
+
+g:proj_run1 ... g:proj_run9
+ Contains a Vim command to execute on the file. See the
+ mappings of \1 to \9 above.
+
+ %f is replaced with the full path and filename
+ %F is replaced with the full path and filename with spaces
+ quoted
+ %n is replaced with the filename alone
+ %N is replaced with the filename alone with spaces quoted
+ %h is replaced with the home directory
+ %H is replaced with the home directory with spaces quoted
+ %r is replaced with the directory relative to the CD path
+ %R is replaced with the directory relative to the CD path
+ with spaces quoted
+ %d is replaced with the CD directory.
+ %D is replaced with the CD directory.with spaces quoted
+ %% is replaced with a single % that is not used in
+ expansion.
+
+ (Deprecated: %s is also replaced with the full path and
+ filename for backward compatibility.)
+
+ For example, gvim will be launched on the file under the
+ cursor when you enter \3 if the following is in your vimrc
+ file: >
+ let g:proj_run3='silent !gvim %f'
+< Here are a few other examples: >
+ let g:proj_run1='!p4 edit %f'
+ let g:proj_run2='!p4 add %f'
+ let g:proj_run4="echo 'Viewing %f'|sil !xterm -e less %f &"
+<
+ On Windows systems you will want to put the %f, %h, and %d in
+ single quotes to avoid \ escaping.
+
+g:proj_run_fold1 ... g:proj_run_fold9
+ Contains a Vim command to execute on the files in a fold. See
+ the mappings of \f1 to \f9 and \F1 to \F9 above.
+
+ %f is the filename, %h is replaced with the project home
+ directory, and %d is replaced with the CD directory. Multiple
+ filenames can be handled in two ways:
+
+ The first (default) way is to have %f replaced with all the
+ absolute filenames, and the command is run once. The second
+ is to have the command run for each of the non-absolute
+ filenames (%f is replaced with one filename at a time). To
+ select the second behavior, put an '*' character at the
+ beginning of the g:proj_run_fold{x} variable. (The '*' is
+ stripped before the command is run.)
+
+ For example, note the difference between the following: >
+ let g:proj_run_fold3="*echo '%h/%f'"
+ let g:proj_run_fold4="echo '%f'"
+<
+ Note that on Windows systems, you will want the %f, %h, and %c
+ within single quotes, or the \ in the paths will cause
+ problems. The alternative is to put them in |escape()|.
+
+
+==============================================================================
+PROJECT EXAMPLE FILE *project-example*
+
+Here is an example ~/.vimprojects file: >
+
+ 1 My Project=~/c/project CD=. in=in.vim out=out.vim flags=r {
+ 2 Makefile
+ 3 in.vim
+ 4 out.vim
+ 5 GUI Files=. filter="gui*.c gui*.h" {
+ 6 gui_window.c
+ 7 gui_dialog.c
+ 8 gui_list.c
+ 9 gui.h # Header file
+ 10 }
+ 11 Database Files=. filter="data*.c data*.h" {
+ 12 data_read.c
+ 13 data_write.c
+ 14 data.h
+ 15 }
+ 16 OS-Specific Files {
+ 17 Win32=. filter="os_win32*.c os_win32*.h" {
+ 18 os_win32_gui.c
+ 19 os_win32_io.c
+ 20 }
+ 21 Unix=. filter="os_unix*.c os_unix*.h" {
+ 22 os_unix_gui.c
+ 23 os_unix_io.c
+ 24 }
+ 25 }
+ 26 }
+
+(Don't type in the line numbers, of course.)
+
+
+==============================================================================
+TIPS ON USING PROJECT PLUGIN *project-tips*
+
+1. You can create a Project Entry by entering this: >
+
+ Label=~/wherever CD=. filter="*.c *.h" {
+ }
+<
+ Then you can put the cursor in the fold and press \r. The script will fill
+ in the files (C files in this case) from this directory for you. This is
+ equivalent to \c without any dialogs.
+
+2. You can edit the Project File at any time to add, remove, or reorder files
+ in the Project list.
+
+3. If the Project Window ever gets closed, you can just enter >
+ :Project
+< to bring it back again. (You don't need to give it the filename; the
+ plugin remembers.)
+
+ If you have the 'm' flag set in g:proj_flags, then you get the Project
+ Window to show up again by pressing |CTRL-W_o|. This, of course, will
+ close any other windows that may be open that the cursor is not in.
+
+4. Adding files to a Project is very easy. To add, for example, the 'more.c'
+ file to the Project, just insert the filename in the Project Entry then
+ hit <Return> on it.
+
+5. When |quickfix| loads files, it is not equivalent to pressing <Return> on
+ a filename, so the directory will not be changed and the scripts will not
+ be run. (If I could make this otherwise, I would.) The solution is to use
+ the \L key to load all of the files in the Project before running
+ quickfix.
+
+6. If the Project window gets a bit cluttered with folds partially
+ open/closed, you can press |zM| to close everything and tidy it up.
+
+7. For advanced users, I am exporting the function Project_GetAllFnames()
+ which returns all the filenames within a fold and optionally all its
+ Subprojects. Also, I export Project_ForEach() for running a function for
+ each filename in the project. See the code for examples on how to use
+ these. Finally, I export Project_GetFname(line_number) so that you can
+ write your own mappings and get the filename for it.
+
+8. Some people have asked how to do a global mapping to take the cursor to
+ the Project window. One of my goals for the plugin is for it to be as
+ self-contained as possible, so I'm not going to add it by default. But you
+ can put this in your vimrc:
+>
+ nmap <silent> <Leader>P :Project<CR>
+
+<
+9. You can put the . entry in a project, and it will launch the
+ |file-explorer| plugin on the directory. To avoid removal when you
+ refresh, make the entry look like this:
+>
+ . # pragma keep
+<
+==============================================================================
+THANKS
+
+ The following people have sent me patches to help with the Project
+ Plugin development:
+
+ Tomas Zellerin
+ Lawrence Kesteloot
+ Dave Eggum
+ A Harrison
+ Thomas Link
+ Richard Bair
+ Eric Arnold
+ Peter Jones
+ Eric Van Dewoestine
+
+
+ vim:ts=8 sw=8 noexpandtab tw=78 ft=help:
diff --git a/modules/vim/vim/doc/snipMate.txt b/modules/vim/vim/doc/snipMate.txt
new file mode 100644
index 0000000..704d44a
--- /dev/null
+++ b/modules/vim/vim/doc/snipMate.txt
@@ -0,0 +1,286 @@
+*snipMate.txt* Plugin for using TextMate-style snippets in Vim.
+
+snipMate *snippet* *snippets* *snipMate*
+Last Change: July 13, 2009
+
+|snipMate-description| Description
+|snipMate-syntax| Snippet syntax
+|snipMate-usage| Usage
+|snipMate-settings| Settings
+|snipMate-features| Features
+|snipMate-disadvantages| Disadvantages to TextMate
+|snipMate-contact| Contact
+
+For Vim version 7.0 or later.
+This plugin only works if 'compatible' is not set.
+{Vi does not have any of these features.}
+
+==============================================================================
+DESCRIPTION *snipMate-description*
+
+snipMate.vim implements some of TextMate's snippets features in Vim. A
+snippet is a piece of often-typed text that you can insert into your
+document using a trigger word followed by a <tab>.
+
+For instance, in a C file using the default installation of snipMate.vim, if
+you type "for<tab>" in insert mode, it will expand a typical for loop in C: >
+
+ for (i = 0; i < count; i++) {
+
+ }
+
+
+To go to the next item in the loop, simply <tab> over to it; if there is
+repeated code, such as the "i" variable in this example, you can simply
+start typing once it's highlighted and all the matches specified in the
+snippet will be updated. To go in reverse, use <shift-tab>.
+
+==============================================================================
+SYNTAX *snippet-syntax*
+
+Snippets can be defined in two ways. They can be in their own file, named
+after their trigger in 'snippets/<filetype>/<trigger>.snippet', or they can be
+defined together in a 'snippets/<filetype>.snippets' file. Note that dotted
+'filetype' syntax is supported -- e.g., you can use >
+
+ :set ft=html.eruby
+
+to activate snippets for both HTML and eRuby for the current file.
+
+The syntax for snippets in *.snippets files is the following: >
+
+ snippet trigger
+ expanded text
+ more expanded text
+
+Note that the first hard tab after the snippet trigger is required, and not
+expanded in the actual snippet. The syntax for *.snippet files is the same,
+only without the trigger declaration and starting indentation.
+
+Also note that snippets must be defined using hard tabs. They can be expanded
+to spaces later if desired (see |snipMate-indenting|).
+
+"#" is used as a line-comment character in *.snippets files; however, they can
+only be used outside of a snippet declaration. E.g.: >
+
+ # this is a correct comment
+ snippet trigger
+ expanded text
+ snippet another_trigger
+ # this isn't a comment!
+ expanded text
+<
+This should hopefully be obvious with the included syntax highlighting.
+
+ *snipMate-${#}*
+Tab stops ~
+
+By default, the cursor is placed at the end of a snippet. To specify where the
+cursor is to be placed next, use "${#}", where the # is the number of the tab
+stop. E.g., to place the cursor first on the id of a <div> tag, and then allow
+the user to press <tab> to go to the middle of it:
+ >
+ snippet div
+ <div id="${1}">
+ ${2}
+ </div>
+<
+ *snipMate-placeholders* *snipMate-${#:}* *snipMate-$#*
+Placeholders ~
+
+Placeholder text can be supplied using "${#:text}", where # is the number of
+the tab stop. This text then can be copied throughout the snippet using "$#",
+given # is the same number as used before. So, to make a C for loop: >
+
+ snippet for
+ for (${2:i}; $2 < ${1:count}; $1++) {
+ ${4}
+ }
+
+This will cause "count" to first be selected and change if the user starts
+typing. When <tab> is pressed, the "i" in ${2}'s position will be selected;
+all $2 variables will default to "i" and automatically be updated if the user
+starts typing.
+NOTE: "$#" syntax is used only for variables, not for tab stops as in TextMate.
+
+Variables within variables are also possible. For instance: >
+
+ snippet opt
+ <option value="${1:option}">${2:$1}</option>
+
+Will, as usual, cause "option" to first be selected and update all the $1
+variables if the user starts typing. Since one of these variables is inside of
+${2}, this text will then be used as a placeholder for the next tab stop,
+allowing the user to change it if he wishes.
+
+To copy a value throughout a snippet without supplying default text, simply
+use the "${#:}" construct without the text; e.g.: >
+
+ snippet foo
+ ${1:}bar$1
+< *snipMate-commands*
+Interpolated Vim Script ~
+
+Snippets can also contain Vim script commands that are executed (via |eval()|)
+when the snippet is inserted. Commands are given inside backticks (`...`); for
+TextMates's functionality, use the |system()| function. E.g.: >
+
+ snippet date
+ `system("date +%Y-%m-%d")`
+
+will insert the current date, assuming you are on a Unix system. Note that you
+can also (and should) use |strftime()| for this example.
+
+Filename([{expr}] [, {defaultText}]) *snipMate-filename* *Filename()*
+
+Since the current filename is used often in snippets, a default function
+has been defined for it in snipMate.vim, appropriately called Filename().
+
+With no arguments, the default filename without an extension is returned;
+the first argument specifies what to place before or after the filename,
+and the second argument supplies the default text to be used if the file
+has not been named. "$1" in the first argument is replaced with the filename;
+if you only want the filename to be returned, the first argument can be left
+blank. Examples: >
+
+ snippet filename
+ `Filename()`
+ snippet filename_with_default
+ `Filename('', 'name')`
+ snippet filename_foo
+ `filename('$1_foo')`
+
+The first example returns the filename if it the file has been named, and an
+empty string if it hasn't. The second returns the filename if it's been named,
+and "name" if it hasn't. The third returns the filename followed by "_foo" if
+it has been named, and an empty string if it hasn't.
+
+ *multi_snip*
+To specify that a snippet can have multiple matches in a *.snippets file, use
+this syntax: >
+
+ snippet trigger A description of snippet #1
+ expand this text
+ snippet trigger A description of snippet #2
+ expand THIS text!
+
+In this example, when "trigger<tab>" is typed, a numbered menu containing all
+of the descriptions of the "trigger" will be shown; when the user presses the
+corresponding number, that snippet will then be expanded.
+
+To create a snippet with multiple matches using *.snippet files,
+simply place all the snippets in a subdirectory with the trigger name:
+'snippets/<filetype>/<trigger>/<name>.snippet'.
+
+==============================================================================
+USAGE *snipMate-usage*
+
+ *'snippets'* *g:snippets_dir*
+Snippets are by default looked for any 'snippets' directory in your
+'runtimepath'. Typically, it is located at '~/.vim/snippets/' on *nix or
+'$HOME\vimfiles\snippets\' on Windows. To change that location or add another
+one, change the g:snippets_dir variable in your |.vimrc| to your preferred
+directory, or use the |ExtractSnips()|function. This will be used by the
+|globpath()| function, and so accepts the same syntax as it (e.g.,
+comma-separated paths).
+
+ExtractSnipsFile({directory}, {filetype}) *ExtractSnipsFile()* *.snippets*
+
+ExtractSnipsFile() extracts the specified *.snippets file for the given
+filetype. A .snippets file contains multiple snippet declarations for the
+filetype. It is further explained above, in |snippet-syntax|.
+
+ExtractSnips({directory}, {filetype}) *ExtractSnips()* *.snippet*
+
+ExtractSnips() extracts *.snippet files from the specified directory and
+defines them as snippets for the given filetype. The directory tree should
+look like this: 'snippets/<filetype>/<trigger>.snippet'. If the snippet has
+multiple matches, it should look like this:
+'snippets/<filetype>/<trigger>/<name>.snippet' (see |multi_snip|).
+
+ *ResetSnippets()*
+The ResetSnippets() function removes all snippets from memory. This is useful
+to put at the top of a snippet setup file for if you would like to |:source|
+it multiple times.
+
+ *list-snippets* *i_CTRL-R_<Tab>*
+If you would like to see what snippets are available, simply type <c-r><tab>
+in the current buffer to show a list via |popupmenu-completion|.
+
+==============================================================================
+SETTINGS *snipMate-settings* *g:snips_author*
+
+The g:snips_author string (similar to $TM_FULLNAME in TextMate) should be set
+to your name; it can then be used in snippets to automatically add it. E.g.: >
+
+ let g:snips_author = 'Hubert Farnsworth'
+ snippet name
+ `g:snips_author`
+<
+ *snipMate-expandtab* *snipMate-indenting*
+If you would like your snippets to be expanded using spaces instead of tabs,
+just enable 'expandtab' and set 'softtabstop' to your preferred amount of
+spaces. If 'softtabstop' is not set, 'shiftwidth' is used instead.
+
+ *snipMate-remap*
+snipMate does not come with a setting to customize the trigger key, but you
+can remap it easily in the two lines it's defined in the 'after' directory
+under 'plugin/snipMate.vim'. For instance, to change the trigger key
+to CTRL-J, just change this: >
+
+ ino <tab> <c-r>=TriggerSnippet()<cr>
+ snor <tab> <esc>i<right><c-r>=TriggerSnippet()<cr>
+
+to this: >
+ ino <c-j> <c-r>=TriggerSnippet()<cr>
+ snor <c-j> <esc>i<right><c-r>=TriggerSnippet()<cr>
+
+==============================================================================
+FEATURES *snipMate-features*
+
+snipMate.vim has the following features among others:
+ - The syntax of snippets is very similar to TextMate's, allowing
+ easy conversion.
+ - The position of the snippet is kept transparently (i.e. it does not use
+ markers/placeholders written to the buffer), which allows you to escape
+ out of an incomplete snippet, something particularly useful in Vim.
+ - Variables in snippets are updated as-you-type.
+ - Snippets can have multiple matches.
+ - Snippets can be out of order. For instance, in a do...while loop, the
+ condition can be added before the code.
+ - [New] File-based snippets are supported.
+ - [New] Triggers after non-word delimiters are expanded, e.g. "foo"
+ in "bar.foo".
+ - [New] <shift-tab> can now be used to jump tab stops in reverse order.
+
+==============================================================================
+DISADVANTAGES *snipMate-disadvantages*
+
+snipMate.vim currently has the following disadvantages to TextMate's snippets:
+ - There is no $0; the order of tab stops must be explicitly stated.
+ - Placeholders within placeholders are not possible. E.g.: >
+
+ '<div${1: id="${2:some_id}}">${3}</div>'
+<
+ In TextMate this would first highlight ' id="some_id"', and if
+ you hit delete it would automatically skip ${2} and go to ${3}
+ on the next <tab>, but if you didn't delete it it would highlight
+ "some_id" first. You cannot do this in snipMate.vim.
+ - Regex cannot be performed on variables, such as "${1/.*/\U&}"
+ - Placeholders cannot span multiple lines.
+ - Activating snippets in different scopes of the same file is
+ not possible.
+
+Perhaps some of these features will be added in a later release.
+
+==============================================================================
+CONTACT *snipMate-contact* *snipMate-author*
+
+To contact the author (Michael Sanders), please email:
+ msanders42+snipmate <at> gmail <dot> com
+
+I greatly appreciate any suggestions or improvements offered for the script.
+
+==============================================================================
+
+vim:tw=78:ts=8:ft=help:norl:
diff --git a/modules/vim/vim/doc/taglist.txt b/modules/vim/vim/doc/taglist.txt
new file mode 100755
index 0000000..6a62b39
--- /dev/null
+++ b/modules/vim/vim/doc/taglist.txt
@@ -0,0 +1,1501 @@
+*taglist.txt* Plugin for browsing source code
+
+Author: Yegappan Lakshmanan (yegappan AT yahoo DOT com)
+For Vim version 6.0 and above
+Last change: 2007 May 24
+
+1. Overview |taglist-intro|
+2. Taglist on the internet |taglist-internet|
+3. Requirements |taglist-requirements|
+4. Installation |taglist-install|
+5. Usage |taglist-using|
+6. Options |taglist-options|
+7. Commands |taglist-commands|
+8. Global functions |taglist-functions|
+9. Extending |taglist-extend|
+10. FAQ |taglist-faq|
+11. License |taglist-license|
+12. Todo |taglist-todo|
+
+==============================================================================
+ *taglist-intro*
+1. Overview~
+
+The "Tag List" plugin is a source code browser plugin for Vim. This plugin
+allows you to efficiently browse through source code files for different
+programming languages. The "Tag List" plugin provides the following features:
+
+ * Displays the tags (functions, classes, structures, variables, etc.)
+ defined in a file in a vertically or horizontally split Vim window.
+ * In GUI Vim, optionally displays the tags in the Tags drop-down menu and
+ in the popup menu.
+ * Automatically updates the taglist window as you switch between
+ files/buffers. As you open new files, the tags defined in the new files
+ are added to the existing file list and the tags defined in all the
+ files are displayed grouped by the filename.
+ * When a tag name is selected from the taglist window, positions the
+ cursor at the definition of the tag in the source file.
+ * Automatically highlights the current tag name.
+ * Groups the tags by their type and displays them in a foldable tree.
+ * Can display the prototype and scope of a tag.
+ * Can optionally display the tag prototype instead of the tag name in the
+ taglist window.
+ * The tag list can be sorted either by name or by chronological order.
+ * Supports the following language files: Assembly, ASP, Awk, Beta, C,
+ C++, C#, Cobol, Eiffel, Erlang, Fortran, HTML, Java, Javascript, Lisp,
+ Lua, Make, Pascal, Perl, PHP, Python, Rexx, Ruby, Scheme, Shell, Slang,
+ SML, Sql, TCL, Verilog, Vim and Yacc.
+ * Can be easily extended to support new languages. Support for
+ existing languages can be modified easily.
+ * Provides functions to display the current tag name in the Vim status
+ line or the window title bar.
+ * The list of tags and files in the taglist can be saved and
+ restored across Vim sessions.
+ * Provides commands to get the name and prototype of the current tag.
+ * Runs in both console/terminal and GUI versions of Vim.
+ * Works with the winmanager plugin. Using the winmanager plugin, you
+ can use Vim plugins like the file explorer, buffer explorer and the
+ taglist plugin at the same time like an IDE.
+ * Can be used in both Unix and MS-Windows systems.
+
+==============================================================================
+ *taglist-internet*
+2. Taglist on the internet~
+
+The home page of the taglist plugin is at:
+>
+ http://vim-taglist.sourceforge.net/
+<
+You can subscribe to the taglist mailing list to post your questions or
+suggestions for improvement or to send bug reports. Visit the following page
+for subscribing to the mailing list:
+>
+ http://groups.yahoo.com/group/taglist
+<
+==============================================================================
+ *taglist-requirements*
+3. Requirements~
+
+The taglist plugin requires the following:
+
+ * Vim version 6.0 and above
+ * Exuberant ctags 5.0 and above
+
+The taglist plugin will work on all the platforms where the exuberant ctags
+utility and Vim are supported (this includes MS-Windows and Unix based
+systems).
+
+The taglist plugin relies on the exuberant ctags utility to dynamically
+generate the tag listing. The exuberant ctags utility must be installed in
+your system to use this plugin. The exuberant ctags utility is shipped with
+most of the Linux distributions. You can download the exuberant ctags utility
+from
+>
+ http://ctags.sourceforge.net
+<
+The taglist plugin doesn't use or create a tags file and there is no need to
+create a tags file to use this plugin. The taglist plugin will not work with
+the GNU ctags or the Unix ctags utility.
+
+This plugin relies on the Vim "filetype" detection mechanism to determine the
+type of the current file. You have to turn on the Vim filetype detection by
+adding the following line to your .vimrc file:
+>
+ filetype on
+<
+The taglist plugin will not work if you run Vim in the restricted mode (using
+the -Z command-line argument).
+
+The taglist plugin uses the Vim system() function to invoke the exuberant
+ctags utility. If Vim is compiled without the system() function then you
+cannot use the taglist plugin. Some of the Linux distributions (Suse) compile
+Vim without the system() function for security reasons.
+
+==============================================================================
+ *taglist-install*
+4. Installation~
+
+1. Download the taglist.zip file and unzip the files to the $HOME/.vim or the
+ $HOME/vimfiles or the $VIM/vimfiles directory. After this step, you should
+ have the following two files (the directory structure should be preserved):
+
+ plugin/taglist.vim - main taglist plugin file
+ doc/taglist.txt - documentation (help) file
+
+ Refer to the |add-plugin|and |'runtimepath'| Vim help pages for more
+ details about installing Vim plugins.
+2. Change to the $HOME/.vim/doc or $HOME/vimfiles/doc or $VIM/vimfiles/doc
+ directory, start Vim and run the ":helptags ." command to process the
+ taglist help file. Without this step, you cannot jump to the taglist help
+ topics.
+3. If the exuberant ctags utility is not present in one of the directories in
+ the PATH environment variable, then set the 'Tlist_Ctags_Cmd' variable to
+ point to the location of the exuberant ctags utility (not to the directory)
+ in the .vimrc file.
+4. If you are running a terminal/console version of Vim and the terminal
+ doesn't support changing the window width then set the
+ 'Tlist_Inc_Winwidth' variable to 0 in the .vimrc file.
+5. Restart Vim.
+6. You can now use the ":TlistToggle" command to open/close the taglist
+ window. You can use the ":help taglist" command to get more information
+ about using the taglist plugin.
+
+To uninstall the taglist plugin, remove the plugin/taglist.vim and
+doc/taglist.txt files from the $HOME/.vim or $HOME/vimfiles directory.
+
+==============================================================================
+ *taglist-using*
+5. Usage~
+
+The taglist plugin can be used in several different ways.
+
+1. You can keep the taglist window open during the entire editing session. On
+ opening the taglist window, the tags defined in all the files in the Vim
+ buffer list will be displayed in the taglist window. As you edit files, the
+ tags defined in them will be added to the taglist window. You can select a
+ tag from the taglist window and jump to it. The current tag will be
+ highlighted in the taglist window. You can close the taglist window when
+ you no longer need the window.
+2. You can configure the taglist plugin to process the tags defined in all the
+ edited files always. In this configuration, even if the taglist window is
+ closed and the taglist menu is not displayed, the taglist plugin will
+ processes the tags defined in newly edited files. You can then open the
+ taglist window only when you need to select a tag and then automatically
+ close the taglist window after selecting the tag.
+3. You can configure the taglist plugin to display only the tags defined in
+ the current file in the taglist window. By default, the taglist plugin
+ displays the tags defined in all the files in the Vim buffer list. As you
+ switch between files, the taglist window will be refreshed to display only
+ the tags defined in the current file.
+4. In GUI Vim, you can use the Tags pull-down and popup menu created by the
+ taglist plugin to display the tags defined in the current file and select a
+ tag to jump to it. You can use the menu without opening the taglist window.
+ By default, the Tags menu is disabled.
+5. You can configure the taglist plugin to display the name of the current tag
+ in the Vim window status line or in the Vim window title bar. For this to
+ work without the taglist window or menu, you need to configure the taglist
+ plugin to process the tags defined in a file always.
+6. You can save the tags defined in multiple files to a taglist session file
+ and load it when needed. You can also configure the taglist plugin to not
+ update the taglist window when editing new files. You can then manually add
+ files to the taglist window.
+
+Opening the taglist window~
+You can open the taglist window using the ":TlistOpen" or the ":TlistToggle"
+commands. The ":TlistOpen" command opens the taglist window and jumps to it.
+The ":TlistToggle" command opens or closes (toggle) the taglist window and the
+cursor remains in the current window. If the 'Tlist_GainFocus_On_ToggleOpen'
+variable is set to 1, then the ":TlistToggle" command opens the taglist window
+and moves the cursor to the taglist window.
+
+You can map a key to invoke these commands. For example, the following command
+creates a normal mode mapping for the <F8> key to toggle the taglist window.
+>
+ nnoremap <silent> <F8> :TlistToggle<CR>
+<
+Add the above mapping to your ~/.vimrc or $HOME/_vimrc file.
+
+To automatically open the taglist window on Vim startup, set the
+'Tlist_Auto_Open' variable to 1.
+
+You can also open the taglist window on startup using the following command
+line:
+>
+ $ vim +TlistOpen
+<
+Closing the taglist window~
+You can close the taglist window from the taglist window by pressing 'q' or
+using the Vim ":q" command. You can also use any of the Vim window commands to
+close the taglist window. Invoking the ":TlistToggle" command when the taglist
+window is opened, closes the taglist window. You can also use the
+":TlistClose" command to close the taglist window.
+
+To automatically close the taglist window when a tag or file is selected, you
+can set the 'Tlist_Close_On_Select' variable to 1. To exit Vim when only the
+taglist window is present, set the 'Tlist_Exit_OnlyWindow' variable to 1.
+
+Jumping to a tag or a file~
+You can select a tag in the taglist window either by pressing the <Enter> key
+or by double clicking the tag name using the mouse. To jump to a tag on a
+single mouse click set the 'Tlist_Use_SingleClick' variable to 1.
+
+If the selected file is already opened in a window, then the cursor is moved
+to that window. If the file is not currently opened in a window then the file
+is opened in the window used by the taglist plugin to show the previously
+selected file. If there are no usable windows, then the file is opened in a
+new window. The file is not opened in special windows like the quickfix
+window, preview window and windows containing buffer with the 'buftype' option
+set.
+
+To jump to the tag in a new window, press the 'o' key. To open the file in the
+previous window (Ctrl-W_p) use the 'P' key. You can press the 'p' key to jump
+to the tag but still keep the cursor in the taglist window (preview).
+
+To open the selected file in a tab, use the 't' key. If the file is already
+present in a tab then the cursor is moved to that tab otherwise the file is
+opened in a new tab. To jump to a tag in a new tab press Ctrl-t. The taglist
+window is automatically opened in the newly created tab.
+
+Instead of jumping to a tag, you can open a file by pressing the <Enter> key
+or by double clicking the file name using the mouse.
+
+In the taglist window, you can use the [[ or <Backspace> key to jump to the
+beginning of the previous file. You can use the ]] or <Tab> key to jump to the
+beginning of the next file. When you reach the first or last file, the search
+wraps around and the jumps to the next/previous file.
+
+Highlighting the current tag~
+The taglist plugin automatically highlights the name of the current tag in the
+taglist window. The Vim |CursorHold| autocmd event is used for this. If the
+current tag name is not visible in the taglist window, then the taglist window
+contents are scrolled to make that tag name visible. You can also use the
+":TlistHighlightTag" command to force the highlighting of the current tag.
+
+The tag name is highlighted if no activity is performed for |'updatetime'|
+milliseconds. The default value for this Vim option is 4 seconds. To avoid
+unexpected problems, you should not set the |'updatetime'| option to a very
+low value.
+
+To disable the automatic highlighting of the current tag name in the taglist
+window, set the 'Tlist_Auto_Highlight_Tag' variable to zero.
+
+When entering a Vim buffer/window, the taglist plugin automatically highlights
+the current tag in that buffer/window. If you like to disable the automatic
+highlighting of the current tag when entering a buffer, set the
+'Tlist_Highlight_Tag_On_BufEnter' variable to zero.
+
+Adding files to the taglist~
+When the taglist window is opened, all the files in the Vim buffer list are
+processed and the supported files are added to the taglist. When you edit a
+file in Vim, the taglist plugin automatically processes this file and adds it
+to the taglist. If you close the taglist window, the tag information in the
+taglist is retained.
+
+To process files even when the taglist window is not open, set the
+'Tlist_Process_File_Always' variable to 1.
+
+You can manually add multiple files to the taglist without opening them using
+the ":TlistAddFiles" and the ":TlistAddFilesRecursive" commands.
+
+For example, to add all the C files in the /my/project/dir directory to the
+taglist, you can use the following command:
+>
+ :TlistAddFiles /my/project/dir/*.c
+<
+Note that when adding several files with a large number of tags or a large
+number of files, it will take several seconds to several minutes for the
+taglist plugin to process all the files. You should not interrupt the taglist
+plugin by pressing <CTRL-C>.
+
+You can recursively add multiple files from a directory tree using the
+":TlistAddFilesRecursive" command:
+>
+ :TlistAddFilesRecursive /my/project/dir *.c
+<
+This command takes two arguments. The first argument specifies the directory
+from which to recursively add the files. The second optional argument
+specifies the wildcard matching pattern for selecting the files to add. The
+default pattern is * and all the files are added.
+
+Displaying tags for only one file~
+The taglist window displays the tags for all the files in the Vim buffer list
+and all the manually added files. To display the tags for only the current
+active buffer, set the 'Tlist_Show_One_File' variable to 1.
+
+Removing files from the taglist~
+You can remove a file from the taglist window, by pressing the 'd' key when the
+cursor is on one of the tags listed for the file in the taglist window. The
+removed file will no longer be displayed in the taglist window in the current
+Vim session. To again display the tags for the file, open the file in a Vim
+window and then use the ":TlistUpdate" command or use ":TlistAddFiles" command
+to add the file to the taglist.
+
+When a buffer is removed from the Vim buffer list using the ":bdelete" or the
+":bwipeout" command, the taglist is updated to remove the stored information
+for this buffer.
+
+Updating the tags displayed for a file~
+The taglist plugin keeps track of the modification time of a file. When the
+modification time changes (the file is modified), the taglist plugin
+automatically updates the tags listed for that file. The modification time of
+a file is checked when you enter a window containing that file or when you
+load that file.
+
+You can also update or refresh the tags displayed for a file by pressing the
+"u" key in the taglist window. If an existing file is modified, after the file
+is saved, the taglist plugin automatically updates the tags displayed for the
+file.
+
+You can also use the ":TlistUpdate" command to update the tags for the current
+buffer after you made some changes to it. You should save the modified buffer
+before you update the taglist window. Otherwise the listed tags will not
+include the new tags created in the buffer.
+
+If you have deleted the tags displayed for a file in the taglist window using
+the 'd' key, you can again display the tags for that file using the
+":TlistUpdate" command.
+
+Controlling the taglist updates~
+To disable the automatic processing of new files or modified files, you can
+set the 'Tlist_Auto_Update' variable to zero. When this variable is set to
+zero, the taglist is updated only when you use the ":TlistUpdate" command or
+the ":TlistAddFiles" or the ":TlistAddFilesRecursive" commands. You can use
+this option to control which files are added to the taglist.
+
+You can use the ":TlistLock" command to lock the taglist contents. After this
+command is executed, new files are not automatically added to the taglist.
+When the taglist is locked, you can use the ":TlistUpdate" command to add the
+current file or the ":TlistAddFiles" or ":TlistAddFilesRecursive" commands to
+add new files to the taglist. To unlock the taglist, use the ":TlistUnlock"
+command.
+
+Displaying the tag prototype~
+To display the prototype of the tag under the cursor in the taglist window,
+press the space bar. If you place the cursor on a tag name in the taglist
+window, then the tag prototype is displayed at the Vim status line after
+|'updatetime'| milliseconds. The default value for the |'updatetime'| Vim
+option is 4 seconds.
+
+You can get the name and prototype of a tag without opening the taglist window
+and the taglist menu using the ":TlistShowTag" and the ":TlistShowPrototype"
+commands. These commands will work only if the current file is already present
+in the taglist. To use these commands without opening the taglist window, set
+the 'Tlist_Process_File_Always' variable to 1.
+
+You can use the ":TlistShowTag" command to display the name of the tag at or
+before the specified line number in the specified file. If the file name and
+line number are not supplied, then this command will display the name of the
+current tag. For example,
+>
+ :TlistShowTag
+ :TlistShowTag myfile.java 100
+<
+You can use the ":TlistShowPrototype" command to display the prototype of the
+tag at or before the specified line number in the specified file. If the file
+name and the line number are not supplied, then this command will display the
+prototype of the current tag. For example,
+>
+ :TlistShowPrototype
+ :TlistShowPrototype myfile.c 50
+<
+In the taglist window, when the mouse is moved over a tag name, the tag
+prototype is displayed in a balloon. This works only in GUI versions where
+balloon evaluation is supported.
+
+Taglist window contents~
+The taglist window contains the tags defined in various files in the taglist
+grouped by the filename and by the tag type (variable, function, class, etc.).
+For tags with scope information (like class members, structures inside
+structures, etc.), the scope information is displayed in square brackets "[]"
+after the tag name.
+
+The contents of the taglist buffer/window are managed by the taglist plugin.
+The |'filetype'| for the taglist buffer is set to 'taglist'. The Vim
+|'modifiable'| option is turned off for the taglist buffer. You should not
+manually edit the taglist buffer, by setting the |'modifiable'| flag. If you
+manually edit the taglist buffer contents, then the taglist plugin will be out
+of sync with the taglist buffer contents and the plugin will no longer work
+correctly. To redisplay the taglist buffer contents again, close the taglist
+window and reopen it.
+
+Opening and closing the tag and file tree~
+In the taglist window, the tag names are displayed as a foldable tree using
+the Vim folding support. You can collapse the tree using the '-' key or using
+the Vim |zc| fold command. You can open the tree using the '+' key or using
+the Vim |zo| fold command. You can open all the folds using the '*' key or
+using the Vim |zR| fold command. You can also use the mouse to open/close the
+folds. You can close all the folds using the '=' key. You should not manually
+create or delete the folds in the taglist window.
+
+To automatically close the fold for the inactive files/buffers and open only
+the fold for the current buffer in the taglist window, set the
+'Tlist_File_Fold_Auto_Close' variable to 1.
+
+Sorting the tags for a file~
+The tags displayed in the taglist window can be sorted either by their name or
+by their chronological order. The default sorting method is by the order in
+which the tags appear in a file. You can change the default sort method by
+setting the 'Tlist_Sort_Type' variable to either "name" or "order". You can
+sort the tags by their name by pressing the "s" key in the taglist window. You
+can again sort the tags by their chronological order using the "s" key. Each
+file in the taglist window can be sorted using different order.
+
+Zooming in and out of the taglist window~
+You can press the 'x' key in the taglist window to maximize the taglist
+window width/height. The window will be maximized to the maximum possible
+width/height without closing the other existing windows. You can again press
+'x' to restore the taglist window to the default width/height.
+
+ *taglist-session*
+Taglist Session~
+A taglist session refers to the group of files and their tags stored in the
+taglist in a Vim session.
+
+You can save and restore a taglist session (and all the displayed tags) using
+the ":TlistSessionSave" and ":TlistSessionLoad" commands.
+
+To save the information about the tags and files in the taglist to a file, use
+the ":TlistSessionSave" command and specify the filename:
+>
+ :TlistSessionSave <file name>
+<
+To load a saved taglist session, use the ":TlistSessionLoad" command: >
+
+ :TlistSessionLoad <file name>
+<
+When you load a taglist session file, the tags stored in the file will be
+added to the tags already stored in the taglist.
+
+The taglist session feature can be used to save the tags for large files or a
+group of frequently used files (like a project). By using the taglist session
+file, you can minimize the amount to time it takes to load/refresh the taglist
+for multiple files.
+
+You can create more than one taglist session file for multiple groups of
+files.
+
+Displaying the tag name in the Vim status line or the window title bar~
+You can use the Tlist_Get_Tagname_By_Line() function provided by the taglist
+plugin to display the current tag name in the Vim status line or the window
+title bar. Similarly, you can use the Tlist_Get_Tag_Prototype_By_Line()
+function to display the current tag prototype in the Vim status line or the
+window title bar.
+
+For example, the following command can be used to display the current tag name
+in the status line:
+>
+ :set statusline=%<%f%=%([%{Tlist_Get_Tagname_By_Line()}]%)
+<
+The following command can be used to display the current tag name in the
+window title bar:
+>
+ :set title titlestring=%<%f\ %([%{Tlist_Get_Tagname_By_Line()}]%)
+<
+Note that the current tag name can be displayed only after the file is
+processed by the taglist plugin. For this, you have to either set the
+'Tlist_Process_File_Always' variable to 1 or open the taglist window or use
+the taglist menu. For more information about configuring the Vim status line,
+refer to the documentation for the Vim |'statusline'| option.
+
+Changing the taglist window highlighting~
+The following Vim highlight groups are defined and used to highlight the
+various entities in the taglist window:
+
+ TagListTagName - Used for tag names
+ TagListTagScope - Used for tag scope
+ TagListTitle - Used for tag titles
+ TagListComment - Used for comments
+ TagListFileName - Used for filenames
+
+By default, these highlight groups are linked to the standard Vim highlight
+groups. If you want to change the colors used for these highlight groups,
+prefix the highlight group name with 'My' and define it in your .vimrc or
+.gvimrc file: MyTagListTagName, MyTagListTagScope, MyTagListTitle,
+MyTagListComment and MyTagListFileName. For example, to change the colors
+used for tag names, you can use the following command:
+>
+ :highlight MyTagListTagName guifg=blue ctermfg=blue
+<
+Controlling the taglist window~
+To use a horizontally split taglist window, instead of a vertically split
+window, set the 'Tlist_Use_Horiz_Window' variable to 1.
+
+To use a vertically split taglist window on the rightmost side of the Vim
+window, set the 'Tlist_Use_Right_Window' variable to 1.
+
+You can specify the width of the vertically split taglist window, by setting
+the 'Tlist_WinWidth' variable. You can specify the height of the horizontally
+split taglist window, by setting the 'Tlist_WinHeight' variable.
+
+When opening a vertically split taglist window, the Vim window width is
+increased to accommodate the new taglist window. When the taglist window is
+closed, the Vim window is reduced. To disable this, set the
+'Tlist_Inc_Winwidth' variable to zero.
+
+To reduce the number of empty lines in the taglist window, set the
+'Tlist_Compact_Format' variable to 1.
+
+To not display the Vim fold column in the taglist window, set the
+'Tlist_Enable_Fold_Column' variable to zero.
+
+To display the tag prototypes instead of the tag names in the taglist window,
+set the 'Tlist_Display_Prototype' variable to 1.
+
+To not display the scope of the tags next to the tag names, set the
+'Tlist_Display_Tag_Scope' variable to zero.
+
+ *taglist-keys*
+Taglist window key list~
+The following table lists the description of the keys that can be used
+in the taglist window.
+
+ Key Description~
+
+ <CR> Jump to the location where the tag under cursor is
+ defined.
+ o Jump to the location where the tag under cursor is
+ defined in a new window.
+ P Jump to the tag in the previous (Ctrl-W_p) window.
+ p Display the tag definition in the file window and
+ keep the cursor in the taglist window itself.
+ t Jump to the tag in a new tab. If the file is already
+ opened in a tab, move to that tab.
+ Ctrl-t Jump to the tag in a new tab.
+ <Space> Display the prototype of the tag under the cursor.
+ For file names, display the full path to the file,
+ file type and the number of tags. For tag types, display the
+ tag type and the number of tags.
+ u Update the tags listed in the taglist window
+ s Change the sort order of the tags (by name or by order)
+ d Remove the tags for the file under the cursor
+ x Zoom-in or Zoom-out the taglist window
+ + Open a fold
+ - Close a fold
+ * Open all folds
+ = Close all folds
+ [[ Jump to the beginning of the previous file
+ <Backspace> Jump to the beginning of the previous file
+ ]] Jump to the beginning of the next file
+ <Tab> Jump to the beginning of the next file
+ q Close the taglist window
+ <F1> Display help
+
+The above keys will work in both the normal mode and the insert mode.
+
+ *taglist-menu*
+Taglist menu~
+When using GUI Vim, the taglist plugin can display the tags defined in the
+current file in the drop-down menu and the popup menu. By default, this
+feature is turned off. To turn on this feature, set the 'Tlist_Show_Menu'
+variable to 1.
+
+You can jump to a tag by selecting the tag name from the menu. You can use the
+taglist menu independent of the taglist window i.e. you don't need to open the
+taglist window to get the taglist menu.
+
+When you switch between files/buffers, the taglist menu is automatically
+updated to display the tags defined in the current file/buffer.
+
+The tags are grouped by their type (variables, functions, classes, methods,
+etc.) and displayed as a separate sub-menu for each type. If all the tags
+defined in a file are of the same type (e.g. functions), then the sub-menu is
+not used.
+
+If the number of items in a tag type submenu exceeds the value specified by
+the 'Tlist_Max_Submenu_Items' variable, then the submenu will be split into
+multiple submenus. The default setting for 'Tlist_Max_Submenu_Items' is 25.
+The first and last tag names in the submenu are used to form the submenu name.
+The menu items are prefixed by alpha-numeric characters for easy selection by
+keyboard.
+
+If the popup menu support is enabled (the |'mousemodel'| option contains
+"popup"), then the tags menu is added to the popup menu. You can access
+the popup menu by right clicking on the GUI window.
+
+You can regenerate the tags menu by selecting the 'Tags->Refresh menu' entry.
+You can sort the tags listed in the menu either by name or by order by
+selecting the 'Tags->Sort menu by->Name/Order' menu entry.
+
+You can tear-off the Tags menu and keep it on the side of the Vim window
+for quickly locating the tags.
+
+Using the taglist plugin with the winmanager plugin~
+You can use the taglist plugin with the winmanager plugin. This will allow you
+to use the file explorer, buffer explorer and the taglist plugin at the same
+time in different windows. To use the taglist plugin with the winmanager
+plugin, set 'TagList' in the 'winManagerWindowLayout' variable. For example,
+to use the file explorer plugin and the taglist plugin at the same time, use
+the following setting: >
+
+ let winManagerWindowLayout = 'FileExplorer|TagList'
+<
+Getting help~
+If you have installed the taglist help file (this file), then you can use the
+Vim ":help taglist-<keyword>" command to get help on the various taglist
+topics.
+
+You can press the <F1> key in the taglist window to display the help
+information about using the taglist window. If you again press the <F1> key,
+the help information is removed from the taglist window.
+
+ *taglist-debug*
+Debugging the taglist plugin~
+You can use the ":TlistDebug" command to enable logging of the debug messages
+from the taglist plugin. To display the logged debug messages, you can use the
+":TlistMessages" command. To disable the logging of the debug messages, use
+the ":TlistUndebug" command.
+
+You can specify a file name to the ":TlistDebug" command to log the debug
+messages to a file. Otherwise, the debug messages are stored in a script-local
+variable. In the later case, to minimize memory usage, only the last 3000
+characters from the debug messages are stored.
+
+==============================================================================
+ *taglist-options*
+6. Options~
+
+A number of Vim variables control the behavior of the taglist plugin. These
+variables are initialized to a default value. By changing these variables you
+can change the behavior of the taglist plugin. You need to change these
+settings only if you want to change the behavior of the taglist plugin. You
+should use the |:let| command in your .vimrc file to change the setting of any
+of these variables.
+
+The configurable taglist variables are listed below. For a detailed
+description of these variables refer to the text below this table.
+
+|'Tlist_Auto_Highlight_Tag'| Automatically highlight the current tag in the
+ taglist.
+|'Tlist_Auto_Open'| Open the taglist window when Vim starts.
+|'Tlist_Auto_Update'| Automatically update the taglist to include
+ newly edited files.
+|'Tlist_Close_On_Select'| Close the taglist window when a file or tag is
+ selected.
+|'Tlist_Compact_Format'| Remove extra information and blank lines from
+ the taglist window.
+|'Tlist_Ctags_Cmd'| Specifies the path to the ctags utility.
+|'Tlist_Display_Prototype'| Show prototypes and not tags in the taglist
+ window.
+|'Tlist_Display_Tag_Scope'| Show tag scope next to the tag name.
+|'Tlist_Enable_Fold_Column'| Show the fold indicator column in the taglist
+ window.
+|'Tlist_Exit_OnlyWindow'| Close Vim if the taglist is the only window.
+|'Tlist_File_Fold_Auto_Close'| Close tag folds for inactive buffers.
+|'Tlist_GainFocus_On_ToggleOpen'|
+ Jump to taglist window on open.
+|'Tlist_Highlight_Tag_On_BufEnter'|
+ On entering a buffer, automatically highlight
+ the current tag.
+|'Tlist_Inc_Winwidth'| Increase the Vim window width to accommodate
+ the taglist window.
+|'Tlist_Max_Submenu_Items'| Maximum number of items in a tags sub-menu.
+|'Tlist_Max_Tag_Length'| Maximum tag length used in a tag menu entry.
+|'Tlist_Process_File_Always'| Process files even when the taglist window is
+ closed.
+|'Tlist_Show_Menu'| Display the tags menu.
+|'Tlist_Show_One_File'| Show tags for the current buffer only.
+|'Tlist_Sort_Type'| Sort method used for arranging the tags.
+|'Tlist_Use_Horiz_Window'| Use a horizontally split window for the
+ taglist window.
+|'Tlist_Use_Right_Window'| Place the taglist window on the right side.
+|'Tlist_Use_SingleClick'| Single click on a tag jumps to it.
+|'Tlist_WinHeight'| Horizontally split taglist window height.
+|'Tlist_WinWidth'| Vertically split taglist window width.
+
+ *'Tlist_Auto_Highlight_Tag'*
+Tlist_Auto_Highlight_Tag~
+The taglist plugin will automatically highlight the current tag in the taglist
+window. If you want to disable this, then you can set the
+'Tlist_Auto_Highlight_Tag' variable to zero. Note that even though the current
+tag highlighting is disabled, the tags for a new file will still be added to
+the taglist window.
+>
+ let Tlist_Auto_Highlight_Tag = 0
+<
+With the above variable set to 1, you can use the ":TlistHighlightTag" command
+to highlight the current tag.
+
+ *'Tlist_Auto_Open'*
+Tlist_Auto_Open~
+To automatically open the taglist window, when you start Vim, you can set the
+'Tlist_Auto_Open' variable to 1. By default, this variable is set to zero and
+the taglist window will not be opened automatically on Vim startup.
+>
+ let Tlist_Auto_Open = 1
+<
+The taglist window is opened only when a supported type of file is opened on
+Vim startup. For example, if you open text files, then the taglist window will
+not be opened.
+
+ *'Tlist_Auto_Update'*
+Tlist_Auto_Update~
+When a new file is edited, the tags defined in the file are automatically
+processed and added to the taglist. To stop adding new files to the taglist,
+set the 'Tlist_Auto_Update' variable to zero. By default, this variable is set
+to 1.
+>
+ let Tlist_Auto_Update = 0
+<
+With the above variable set to 1, you can use the ":TlistUpdate" command to
+add the tags defined in the current file to the taglist.
+
+ *'Tlist_Close_On_Select'*
+Tlist_Close_On_Select~
+If you want to close the taglist window when a file or tag is selected, then
+set the 'Tlist_Close_On_Select' variable to 1. By default, this variable is
+set zero and when you select a tag or file from the taglist window, the window
+is not closed.
+>
+ let Tlist_Close_On_Select = 1
+<
+ *'Tlist_Compact_Format'*
+Tlist_Compact_Format~
+By default, empty lines are used to separate different tag types displayed for
+a file and the tags displayed for different files in the taglist window. If
+you want to display as many tags as possible in the taglist window, you can
+set the 'Tlist_Compact_Format' variable to 1 to get a compact display.
+>
+ let Tlist_Compact_Format = 1
+<
+ *'Tlist_Ctags_Cmd'*
+Tlist_Ctags_Cmd~
+The 'Tlist_Ctags_Cmd' variable specifies the location (path) of the exuberant
+ctags utility. If exuberant ctags is present in any one of the directories in
+the PATH environment variable, then there is no need to set this variable.
+
+The exuberant ctags tool can be installed under different names. When the
+taglist plugin starts up, if the 'Tlist_Ctags_Cmd' variable is not set, it
+checks for the names exuberant-ctags, exctags, ctags, ctags.exe and tags in
+the PATH environment variable. If any one of the named executable is found,
+then the Tlist_Ctags_Cmd variable is set to that name.
+
+If exuberant ctags is not present in one of the directories specified in the
+PATH environment variable, then set this variable to point to the location of
+the ctags utility in your system. Note that this variable should point to the
+fully qualified exuberant ctags location and NOT to the directory in which
+exuberant ctags is installed. If the exuberant ctags tool is not found in
+either PATH or in the specified location, then the taglist plugin will not be
+loaded. Examples:
+>
+ let Tlist_Ctags_Cmd = 'd:\tools\ctags.exe'
+ let Tlist_Ctags_Cmd = '/usr/local/bin/ctags'
+<
+ *'Tlist_Display_Prototype'*
+Tlist_Display_Prototype~
+By default, only the tag name will be displayed in the taglist window. If you
+like to see tag prototypes instead of names, set the 'Tlist_Display_Prototype'
+variable to 1. By default, this variable is set to zero and only tag names
+will be displayed.
+>
+ let Tlist_Display_Prototype = 1
+<
+ *'Tlist_Display_Tag_Scope'*
+Tlist_Display_Tag_Scope~
+By default, the scope of a tag (like a C++ class) will be displayed in
+square brackets next to the tag name. If you don't want the tag scopes
+to be displayed, then set the 'Tlist_Display_Tag_Scope' to zero. By default,
+this variable is set to 1 and the tag scopes will be displayed.
+>
+ let Tlist_Display_Tag_Scope = 0
+<
+ *'Tlist_Enable_Fold_Column'*
+Tlist_Enable_Fold_Column~
+By default, the Vim fold column is enabled and displayed in the taglist
+window. If you wish to disable this (for example, when you are working with a
+narrow Vim window or terminal), you can set the 'Tlist_Enable_Fold_Column'
+variable to zero.
+>
+ let Tlist_Enable_Fold_Column = 1
+<
+ *'Tlist_Exit_OnlyWindow'*
+Tlist_Exit_OnlyWindow~
+If you want to exit Vim if only the taglist window is currently opened, then
+set the 'Tlist_Exit_OnlyWindow' variable to 1. By default, this variable is
+set to zero and the Vim instance will not be closed if only the taglist window
+is present.
+>
+ let Tlist_Exit_OnlyWindow = 1
+<
+ *'Tlist_File_Fold_Auto_Close'*
+Tlist_File_Fold_Auto_Close~
+By default, the tags tree displayed in the taglist window for all the files is
+opened. You can close/fold the tags tree for the files manually. To
+automatically close the tags tree for inactive files, you can set the
+'Tlist_File_Fold_Auto_Close' variable to 1. When this variable is set to 1,
+the tags tree for the current buffer is automatically opened and for all the
+other buffers is closed.
+>
+ let Tlist_File_Fold_Auto_Close = 1
+<
+ *'Tlist_GainFocus_On_ToggleOpen'*
+Tlist_GainFocus_On_ToggleOpen~
+When the taglist window is opened using the ':TlistToggle' command, this
+option controls whether the cursor is moved to the taglist window or remains
+in the current window. By default, this option is set to 0 and the cursor
+remains in the current window. When this variable is set to 1, the cursor
+moves to the taglist window after opening the taglist window.
+>
+ let Tlist_GainFocus_On_ToggleOpen = 1
+<
+ *'Tlist_Highlight_Tag_On_BufEnter'*
+Tlist_Highlight_Tag_On_BufEnter~
+When you enter a Vim buffer/window, the current tag in that buffer/window is
+automatically highlighted in the taglist window. If the current tag name is
+not visible in the taglist window, then the taglist window contents are
+scrolled to make that tag name visible. If you like to disable the automatic
+highlighting of the current tag when entering a buffer, you can set the
+'Tlist_Highlight_Tag_On_BufEnter' variable to zero. The default setting for
+this variable is 1.
+>
+ let Tlist_Highlight_Tag_On_BufEnter = 0
+<
+ *'Tlist_Inc_Winwidth'*
+Tlist_Inc_Winwidth~
+By default, when the width of the window is less than 100 and a new taglist
+window is opened vertically, then the window width is increased by the value
+set in the 'Tlist_WinWidth' variable to accommodate the new window. The value
+of this variable is used only if you are using a vertically split taglist
+window.
+
+If your terminal doesn't support changing the window width from Vim (older
+version of xterm running in a Unix system) or if you see any weird problems in
+the screen due to the change in the window width or if you prefer not to
+adjust the window width then set the 'Tlist_Inc_Winwidth' variable to zero.
+CAUTION: If you are using the MS-Windows version of Vim in a MS-DOS command
+window then you must set this variable to zero, otherwise the system may hang
+due to a Vim limitation (explained in :help win32-problems)
+>
+ let Tlist_Inc_Winwidth = 0
+<
+ *'Tlist_Max_Submenu_Items'*
+Tlist_Max_Submenu_Items~
+If a file contains too many tags of a particular type (function, variable,
+class, etc.), greater than that specified by the 'Tlist_Max_Submenu_Items'
+variable, then the menu for that tag type will be split into multiple
+sub-menus. The default setting for the 'Tlist_Max_Submenu_Items' variable is
+25. This can be changed by setting the 'Tlist_Max_Submenu_Items' variable:
+>
+ let Tlist_Max_Submenu_Items = 20
+<
+The name of the submenu is formed using the names of the first and the last
+tag entries in that submenu.
+
+ *'Tlist_Max_Tag_Length'*
+Tlist_Max_Tag_Length~
+Only the first 'Tlist_Max_Tag_Length' characters from the tag names will be
+used to form the tag type submenu name. The default value for this variable is
+10. Change the 'Tlist_Max_Tag_Length' setting if you want to include more or
+less characters:
+>
+ let Tlist_Max_Tag_Length = 10
+<
+ *'Tlist_Process_File_Always'*
+Tlist_Process_File_Always~
+By default, the taglist plugin will generate and process the tags defined in
+the newly opened files only when the taglist window is opened or when the
+taglist menu is enabled. When the taglist window is closed, the taglist plugin
+will stop processing the tags for newly opened files.
+
+You can set the 'Tlist_Process_File_Always' variable to 1 to generate the list
+of tags for new files even when the taglist window is closed and the taglist
+menu is disabled.
+>
+ let Tlist_Process_File_Always = 1
+<
+To use the ":TlistShowTag" and the ":TlistShowPrototype" commands without the
+taglist window and the taglist menu, you should set this variable to 1.
+
+ *'Tlist_Show_Menu'*
+Tlist_Show_Menu~
+When using GUI Vim, you can display the tags defined in the current file in a
+menu named "Tags". By default, this feature is turned off. To turn on this
+feature, set the 'Tlist_Show_Menu' variable to 1:
+>
+ let Tlist_Show_Menu = 1
+<
+ *'Tlist_Show_One_File'*
+Tlist_Show_One_File~
+By default, the taglist plugin will display the tags defined in all the loaded
+buffers in the taglist window. If you prefer to display the tags defined only
+in the current buffer, then you can set the 'Tlist_Show_One_File' to 1. When
+this variable is set to 1, as you switch between buffers, the taglist window
+will be refreshed to display the tags for the current buffer and the tags for
+the previous buffer will be removed.
+>
+ let Tlist_Show_One_File = 1
+<
+ *'Tlist_Sort_Type'*
+Tlist_Sort_Type~
+The 'Tlist_Sort_Type' variable specifies the sort order for the tags in the
+taglist window. The tags can be sorted either alphabetically by their name or
+by the order of their appearance in the file (chronological order). By
+default, the tag names will be listed by the order in which they are defined
+in the file. You can change the sort type (from name to order or from order to
+name) by pressing the "s" key in the taglist window. You can also change the
+default sort order by setting 'Tlist_Sort_Type' to "name" or "order":
+>
+ let Tlist_Sort_Type = "name"
+<
+ *'Tlist_Use_Horiz_Window'*
+Tlist_Use_Horiz_Window~
+Be default, the tag names are displayed in a vertically split window. If you
+prefer a horizontally split window, then set the 'Tlist_Use_Horiz_Window'
+variable to 1. If you are running MS-Windows version of Vim in a MS-DOS
+command window, then you should use a horizontally split window instead of a
+vertically split window. Also, if you are using an older version of xterm in a
+Unix system that doesn't support changing the xterm window width, you should
+use a horizontally split window.
+>
+ let Tlist_Use_Horiz_Window = 1
+<
+ *'Tlist_Use_Right_Window'*
+Tlist_Use_Right_Window~
+By default, the vertically split taglist window will appear on the left hand
+side. If you prefer to open the window on the right hand side, you can set the
+'Tlist_Use_Right_Window' variable to 1:
+>
+ let Tlist_Use_Right_Window = 1
+<
+ *'Tlist_Use_SingleClick'*
+Tlist_Use_SingleClick~
+By default, when you double click on the tag name using the left mouse
+button, the cursor will be positioned at the definition of the tag. You
+can set the 'Tlist_Use_SingleClick' variable to 1 to jump to a tag when
+you single click on the tag name using the mouse. By default this variable
+is set to zero.
+>
+ let Tlist_Use_SingleClick = 1
+<
+Due to a bug in Vim, if you set 'Tlist_Use_SingleClick' to 1 and try to resize
+the taglist window using the mouse, then Vim will crash. This problem is fixed
+in Vim 6.3 and above. In the meantime, instead of resizing the taglist window
+using the mouse, you can use normal Vim window resizing commands to resize the
+taglist window.
+
+ *'Tlist_WinHeight'*
+Tlist_WinHeight~
+The default height of the horizontally split taglist window is 10. This can be
+changed by modifying the 'Tlist_WinHeight' variable:
+>
+ let Tlist_WinHeight = 20
+<
+The |'winfixheight'| option is set for the taglist window, to maintain the
+height of the taglist window, when new Vim windows are opened and existing
+windows are closed.
+
+ *'Tlist_WinWidth'*
+Tlist_WinWidth~
+The default width of the vertically split taglist window is 30. This can be
+changed by modifying the 'Tlist_WinWidth' variable:
+>
+ let Tlist_WinWidth = 20
+<
+Note that the value of the |'winwidth'| option setting determines the minimum
+width of the current window. If you set the 'Tlist_WinWidth' variable to a
+value less than that of the |'winwidth'| option setting, then Vim will use the
+value of the |'winwidth'| option.
+
+When new Vim windows are opened and existing windows are closed, the taglist
+plugin will try to maintain the width of the taglist window to the size
+specified by the 'Tlist_WinWidth' variable.
+
+==============================================================================
+ *taglist-commands*
+7. Commands~
+
+The taglist plugin provides the following ex-mode commands:
+
+|:TlistAddFiles| Add multiple files to the taglist.
+|:TlistAddFilesRecursive|
+ Add files recursively to the taglist.
+|:TlistClose| Close the taglist window.
+|:TlistDebug| Start logging of taglist debug messages.
+|:TlistLock| Stop adding new files to the taglist.
+|:TlistMessages| Display the logged taglist plugin debug messages.
+|:TlistOpen| Open and jump to the taglist window.
+|:TlistSessionSave| Save the information about files and tags in the
+ taglist to a session file.
+|:TlistSessionLoad| Load the information about files and tags stored
+ in a session file to taglist.
+|:TlistShowPrototype| Display the prototype of the tag at or before the
+ specified line number.
+|:TlistShowTag| Display the name of the tag defined at or before the
+ specified line number.
+|:TlistHighlightTag| Highlight the current tag in the taglist window.
+|:TlistToggle| Open or close (toggle) the taglist window.
+|:TlistUndebug| Stop logging of taglist debug messages.
+|:TlistUnlock| Start adding new files to the taglist.
+|:TlistUpdate| Update the tags for the current buffer.
+
+ *:TlistAddFiles*
+:TlistAddFiles {file(s)} [file(s) ...]
+ Add one or more specified files to the taglist. You can
+ specify multiple filenames using wildcards. To specify a
+ file name with space character, you should escape the space
+ character with a backslash.
+ Examples:
+>
+ :TlistAddFiles *.c *.cpp
+ :TlistAddFiles file1.html file2.html
+<
+ If you specify a large number of files, then it will take some
+ time for the taglist plugin to process all of them. The
+ specified files will not be edited in a Vim window and will
+ not be added to the Vim buffer list.
+
+ *:TlistAddFilesRecursive*
+:TlistAddFilesRecursive {directory} [ {pattern} ]
+ Add files matching {pattern} recursively from the specified
+ {directory} to the taglist. If {pattern} is not specified,
+ then '*' is assumed. To specify the current directory, use "."
+ for {directory}. To specify a directory name with space
+ character, you should escape the space character with a
+ backslash.
+ Examples:
+>
+ :TlistAddFilesRecursive myproject *.java
+ :TlistAddFilesRecursive smallproject
+<
+ If large number of files are present in the specified
+ directory tree, then it will take some time for the taglist
+ plugin to process all of them.
+
+ *:TlistClose*
+:TlistClose Close the taglist window. This command can be used from any
+ one of the Vim windows.
+
+ *:TlistDebug*
+:TlistDebug [filename]
+ Start logging of debug messages from the taglist plugin.
+ If {filename} is specified, then the debug messages are stored
+ in the specified file. Otherwise, the debug messages are
+ stored in a script local variable. If the file {filename} is
+ already present, then it is overwritten.
+
+ *:TlistLock*
+:TlistLock
+ Lock the taglist and don't process new files. After this
+ command is executed, newly edited files will not be added to
+ the taglist.
+
+ *:TlistMessages*
+:TlistMessages
+ Display the logged debug messages from the taglist plugin
+ in a window. This command works only when logging to a
+ script-local variable.
+
+ *:TlistOpen*
+:TlistOpen Open and jump to the taglist window. Creates the taglist
+ window, if the window is not opened currently. After executing
+ this command, the cursor is moved to the taglist window. When
+ the taglist window is opened for the first time, all the files
+ in the buffer list are processed and the tags defined in them
+ are displayed in the taglist window.
+
+ *:TlistSessionSave*
+:TlistSessionSave {filename}
+ Saves the information about files and tags in the taglist to
+ the specified file. This command can be used to save and
+ restore the taglist contents across Vim sessions.
+
+ *:TlistSessionLoad*
+:TlistSessionLoad {filename}
+ Load the information about files and tags stored in the
+ specified session file to the taglist.
+
+ *:TlistShowPrototype*
+:TlistShowPrototype [filename] [linenumber]
+ Display the prototype of the tag at or before the specified
+ line number. If the file name and the line number are not
+ specified, then the current file name and line number are
+ used. A tag spans multiple lines starting from the line where
+ it is defined to the line before the next tag. This command
+ displays the prototype for the tag for any line number in this
+ range.
+
+ *:TlistShowTag*
+:TlistShowTag [filename] [linenumber]
+ Display the name of the tag defined at or before the specified
+ line number. If the file name and the line number are not
+ specified, then the current file name and line number are
+ used. A tag spans multiple lines starting from the line where
+ it is defined to the line before the next tag. This command
+ displays the tag name for any line number in this range.
+
+ *:TlistHighlightTag*
+:TlistHighlightTag
+ Highlight the current tag in the taglist window. By default,
+ the taglist plugin periodically updates the taglist window to
+ highlight the current tag. This command can be used to force
+ the taglist plugin to highlight the current tag.
+
+ *:TlistToggle*
+:TlistToggle Open or close (toggle) the taglist window. Opens the taglist
+ window, if the window is not opened currently. Closes the
+ taglist window, if the taglist window is already opened. When
+ the taglist window is opened for the first time, all the files
+ in the buffer list are processed and the tags are displayed in
+ the taglist window. After executing this command, the cursor
+ is not moved from the current window to the taglist window.
+
+ *:TlistUndebug*
+:TlistUndebug
+ Stop logging of debug messages from the taglist plugin.
+
+ *:TlistUnlock*
+:TlistUnlock
+ Unlock the taglist and start processing newly edited files.
+
+ *:TlistUpdate*
+:TlistUpdate Update the tags information for the current buffer. This
+ command can be used to re-process the current file/buffer and
+ get the tags information. As the taglist plugin uses the file
+ saved in the disk (instead of the file displayed in a Vim
+ buffer), you should save a modified buffer before you update
+ the taglist. Otherwise the listed tags will not include the
+ new tags created in the buffer. You can use this command even
+ when the taglist window is not opened.
+
+==============================================================================
+ *taglist-functions*
+8. Global functions~
+
+The taglist plugin provides several global functions that can be used from
+other Vim plugins to interact with the taglist plugin. These functions are
+described below.
+
+|Tlist_Update_File_Tags()| Update the tags for the specified file
+|Tlist_Get_Tag_Prototype_By_Line()| Return the prototype of the tag at or
+ before the specified line number in the
+ specified file.
+|Tlist_Get_Tagname_By_Line()| Return the name of the tag at or
+ before the specified line number in
+ the specified file.
+|Tlist_Set_App()| Set the name of the application
+ controlling the taglist window.
+
+ *Tlist_Update_File_Tags()*
+Tlist_Update_File_Tags({filename}, {filetype})
+ Update the tags for the file {filename}. The second argument
+ specifies the Vim filetype for the file. If the taglist plugin
+ has not processed the file previously, then the exuberant
+ ctags tool is invoked to generate the tags for the file.
+
+ *Tlist_Get_Tag_Prototype_By_Line()*
+Tlist_Get_Tag_Prototype_By_Line([{filename}, {linenumber}])
+ Return the prototype of the tag at or before the specified
+ line number in the specified file. If the filename and line
+ number are not specified, then the current buffer name and the
+ current line number are used.
+
+ *Tlist_Get_Tagname_By_Line()*
+Tlist_Get_Tagname_By_Line([{filename}, {linenumber}])
+ Return the name of the tag at or before the specified line
+ number in the specified file. If the filename and line number
+ are not specified, then the current buffer name and the
+ current line number are used.
+
+ *Tlist_Set_App()*
+Tlist_Set_App({appname})
+ Set the name of the plugin that controls the taglist plugin
+ window and buffer. This can be used to integrate the taglist
+ plugin with other Vim plugins.
+
+ For example, the winmanager plugin and the Cream package use
+ this function and specify the appname as "winmanager" and
+ "cream" respectively.
+
+ By default, the taglist plugin is a stand-alone plugin and
+ controls the taglist window and buffer. If the taglist window
+ is controlled by an external plugin, then the appname should
+ be set appropriately.
+
+==============================================================================
+ *taglist-extend*
+9. Extending~
+
+The taglist plugin supports all the languages supported by the exuberant ctags
+tool, which includes the following languages: Assembly, ASP, Awk, Beta, C,
+C++, C#, Cobol, Eiffel, Erlang, Fortran, HTML, Java, Javascript, Lisp, Lua,
+Make, Pascal, Perl, PHP, Python, Rexx, Ruby, Scheme, Shell, Slang, SML, Sql,
+TCL, Verilog, Vim and Yacc.
+
+You can extend the taglist plugin to add support for new languages and also
+modify the support for the above listed languages.
+
+You should NOT make modifications to the taglist plugin script file to add
+support for new languages. You will lose these changes when you upgrade to the
+next version of the taglist plugin. Instead you should follow the below
+described instructions to extend the taglist plugin.
+
+You can extend the taglist plugin by setting variables in the .vimrc or _vimrc
+file. The name of these variables depends on the language name and is
+described below.
+
+Modifying support for an existing language~
+To modify the support for an already supported language, you have to set the
+tlist_xxx_settings variable in the ~/.vimrc or $HOME/_vimrc file. Replace xxx
+with the Vim filetype name for the language file. For example, to modify the
+support for the perl language files, you have to set the tlist_perl_settings
+variable. To modify the support for java files, you have to set the
+tlist_java_settings variable.
+
+To determine the filetype name used by Vim for a file, use the following
+command in the buffer containing the file:
+
+ :set filetype
+
+The above command will display the Vim filetype for the current buffer.
+
+The format of the value set in the tlist_xxx_settings variable is
+
+ <language_name>;flag1:name1;flag2:name2;flag3:name3
+
+The different fields in the value are separated by the ';' character.
+
+The first field 'language_name' is the name used by exuberant ctags to refer
+to this language file. This name can be different from the file type name used
+by Vim. For example, for C++, the language name used by ctags is 'c++' but the
+filetype name used by Vim is 'cpp'. To get the list of language names
+supported by exuberant ctags, use the following command:
+
+ $ ctags --list-maps=all
+
+The remaining fields follow the format "flag:name". The sub-field 'flag' is
+the language specific flag used by exuberant ctags to generate the
+corresponding tags. For example, for the C language, to list only the
+functions, the 'f' flag is used. To get the list of flags supported by
+exuberant ctags for the various languages use the following command:
+
+ $ ctags --list-kinds=all
+
+The sub-field 'name' specifies the title text to use for displaying the tags
+of a particular type. For example, 'name' can be set to 'functions'. This
+field can be set to any text string name.
+
+For example, to list only the classes and functions defined in a C++ language
+file, add the following line to your .vimrc file:
+
+ let tlist_cpp_settings = 'c++;c:class;f:function'
+
+In the above setting, 'cpp' is the Vim filetype name and 'c++' is the name
+used by the exuberant ctags tool. 'c' and 'f' are the flags passed to
+exuberant ctags to list C++ classes and functions and 'class' is the title
+used for the class tags and 'function' is the title used for the function tags
+in the taglist window.
+
+For example, to display only functions defined in a C file and to use "My
+Functions" as the title for the function tags, use
+
+ let tlist_c_settings = 'c;f:My Functions'
+
+When you set the tlist_xxx_settings variable, you will override the default
+setting used by the taglist plugin for the 'xxx' language. You cannot add to
+the default options used by the taglist plugin for a particular file type. To
+add to the options used by the taglist plugin for a language, copy the option
+values from the taglist plugin file to your .vimrc file and modify it.
+
+Adding support for a new language~
+If you want to add support for a new language to the taglist plugin, you need
+to first extend the exuberant ctags tool. For more information about extending
+exuberant ctags, visit the following page:
+
+ http://ctags.sourceforge.net/EXTENDING.html
+
+To add support for a new language, set the tlist_xxx_settings variable in the
+~/.vimrc file appropriately as described above. Replace 'xxx' in the variable
+name with the Vim filetype name for the new language.
+
+For example, to extend the taglist plugin to support the latex language, you
+can use the following line (assuming, you have already extended exuberant
+ctags to support the latex language):
+
+ let tlist_tex_settings='latex;b:bibitem;c:command;l:label'
+
+With the above line, when you edit files of filetype "tex" in Vim, the taglist
+plugin will invoke the exuberant ctags tool passing the "latex" filetype and
+the flags b, c and l to generate the tags. The text heading 'bibitem',
+'command' and 'label' will be used in the taglist window for the tags which
+are generated for the flags b, c and l respectively.
+
+==============================================================================
+ *taglist-faq*
+10. Frequently Asked Questions~
+
+Q. The taglist plugin doesn't work. The taglist window is empty and the tags
+ defined in a file are not displayed.
+A. Are you using Vim version 6.0 and above? The taglist plugin relies on the
+ features supported by Vim version 6.0 and above. You can use the following
+ command to get the Vim version:
+>
+ $ vim --version
+<
+ Are you using exuberant ctags version 5.0 and above? The taglist plugin
+ relies on the features supported by exuberant ctags and will not work with
+ GNU ctags or the Unix ctags utility. You can use the following command to
+ determine whether the ctags installed in your system is exuberant ctags:
+>
+ $ ctags --version
+<
+ Is exuberant ctags present in one of the directories in your PATH? If not,
+ you need to set the Tlist_Ctags_Cmd variable to point to the location of
+ exuberant ctags. Use the following Vim command to verify that this is setup
+ correctly:
+>
+ :echo system(Tlist_Ctags_Cmd . ' --version')
+<
+ The above command should display the version information for exuberant
+ ctags.
+
+ Did you turn on the Vim filetype detection? The taglist plugin relies on
+ the filetype detected by Vim and passes the filetype to the exuberant ctags
+ utility to parse the tags. Check the output of the following Vim command:
+>
+ :filetype
+<
+ The output of the above command should contain "filetype detection:ON".
+ To turn on the filetype detection, add the following line to the .vimrc or
+ _vimrc file:
+>
+ filetype on
+<
+ Is your version of Vim compiled with the support for the system() function?
+ The following Vim command should display 1:
+>
+ :echo exists('*system')
+<
+ In some Linux distributions (particularly Suse Linux), the default Vim
+ installation is built without the support for the system() function. The
+ taglist plugin uses the system() function to invoke the exuberant ctags
+ utility. You need to rebuild Vim after enabling the support for the
+ system() function. If you use the default build options, the system()
+ function will be supported.
+
+ Do you have the |'shellslash'| option set? You can try disabling the
+ |'shellslash'| option. When the taglist plugin invokes the exuberant ctags
+ utility with the path to the file, if the incorrect slashes are used, then
+ you will see errors.
+
+ Check the shell related Vim options values using the following command:
+>
+ :set shell? shellcmdflag? shellpipe?
+ :set shellquote? shellredir? shellxquote?
+<
+ If these options are set in your .vimrc or _vimrc file, try removing those
+ lines.
+
+ Are you using a Unix shell in a MS-Windows environment? For example,
+ the Unix shell from the MKS-toolkit. Do you have the SHELL environment
+ set to point to this shell? You can try resetting the SHELL environment
+ variable.
+
+ If you are using a Unix shell on MS-Windows, you should try to use
+ exuberant ctags that is compiled for Unix-like environments so that
+ exuberant ctags will understand path names with forward slash characters.
+
+ Is your filetype supported by the exuberant ctags utility? The file types
+ supported by the exuberant ctags utility are listed in the ctags help. If a
+ file type is not supported, you have to extend exuberant ctags. You can use
+ the following command to list the filetypes supported by exuberant ctags:
+>
+ ctags --list-languages
+<
+ Run the following command from the shell prompt and check whether the tags
+ defined in your file are listed in the output from exuberant ctags:
+>
+ ctags -f - --format=2 --excmd=pattern --fields=nks <filename>
+<
+ If you see your tags in the output from the above command, then the
+ exuberant ctags utility is properly parsing your file.
+
+ Do you have the .ctags or _ctags or the ctags.cnf file in your home
+ directory for specifying default options or for extending exuberant ctags?
+ If you do have this file, check the options in this file and make sure
+ these options are not interfering with the operation of the taglist plugin.
+
+ If you are using MS-Windows, check the value of the TEMP and TMP
+ environment variables. If these environment variables are set to a path
+ with space characters in the name, then try using the DOS 8.3 short name
+ for the path or set them to a path without the space characters in the
+ name. For example, if the temporary directory name is "C:\Documents and
+ Settings\xyz\Local Settings\Temp", then try setting the TEMP variable to
+ the following:
+>
+ set TEMP=C:\DOCUMEN~1\xyz\LOCALS~1\Temp
+<
+ If exuberant ctags is installed in a directory with space characters in the
+ name, then try adding the directory to the PATH environment variable or try
+ setting the 'Tlist_Ctags_Cmd' variable to the shortest path name to ctags
+ or try copying the exuberant ctags to a path without space characters in
+ the name. For example, if exuberant ctags is installed in the directory
+ "C:\Program Files\Ctags", then try setting the 'Tlist_Ctags_Cmd' variable
+ as below:
+>
+ let Tlist_Ctags_Cmd='C:\Progra~1\Ctags\ctags.exe'
+<
+ If you are using a cygwin compiled version of exuberant ctags on MS-Windows,
+ make sure that either you have the cygwin compiled sort utility installed
+ and available in your PATH or compile exuberant ctags with internal sort
+ support. Otherwise, when exuberant ctags sorts the tags output by invoking
+ the sort utility, it may end up invoking the MS-Windows version of
+ sort.exe, thereby resulting in failure.
+
+Q. When I try to open the taglist window, I am seeing the following error
+ message. How do I fix this problem?
+
+ Taglist: Failed to generate tags for /my/path/to/file
+ ctags: illegal option -- -^@usage: ctags [-BFadtuwvx] [-f tagsfile] file ...
+
+A. The taglist plugin will work only with the exuberant ctags tool. You
+ cannot use the GNU ctags or the Unix ctags program with the taglist plugin.
+ You will see an error message similar to the one shown above, if you try
+ use a non-exuberant ctags program with Vim. To fix this problem, either add
+ the exuberant ctags tool location to the PATH environment variable or set
+ the 'Tlist_Ctags_Cmd' variable.
+
+Q. A file has more than one tag with the same name. When I select a tag name
+ from the taglist window, the cursor is positioned at the incorrect tag
+ location.
+A. The taglist plugin uses the search pattern generated by the exuberant ctags
+ utility to position the cursor at the location of a tag definition. If a
+ file has more than one tag with the same name and same prototype, then the
+ search pattern will be the same. In this case, when searching for the tag
+ pattern, the cursor may be positioned at the incorrect location.
+
+Q. I have made some modifications to my file and introduced new
+ functions/classes/variables. I have not yet saved my file. The taglist
+ plugin is not displaying the new tags when I update the taglist window.
+A. The exuberant ctags utility will process only files that are present in the
+ disk. To list the tags defined in a file, you have to save the file and
+ then update the taglist window.
+
+Q. I have created a ctags file using the exuberant ctags utility for my source
+ tree. How do I configure the taglist plugin to use this tags file?
+A. The taglist plugin doesn't use a tags file stored in disk. For every opened
+ file, the taglist plugin invokes the exuberant ctags utility to get the
+ list of tags dynamically. The Vim system() function is used to invoke
+ exuberant ctags and get the ctags output. This function internally uses a
+ temporary file to store the output. This file is deleted after the output
+ from the command is read. So you will never see the file that contains the
+ output of exuberant ctags.
+
+Q. When I set the |'updatetime'| option to a low value (less than 1000) and if
+ I keep pressing a key with the taglist window open, the current buffer
+ contents are changed. Why is this?
+A. The taglist plugin uses the |CursorHold| autocmd to highlight the current
+ tag. The CursorHold autocmd triggers for every |'updatetime'| milliseconds.
+ If the |'updatetime'| option is set to a low value, then the CursorHold
+ autocmd will be triggered frequently. As the taglist plugin changes
+ the focus to the taglist window to highlight the current tag, this could
+ interfere with the key movement resulting in changing the contents of
+ the current buffer. The workaround for this problem is to not set the
+ |'updatetime'| option to a low value.
+
+==============================================================================
+ *taglist-license*
+11. License~
+Permission is hereby granted to use and distribute the taglist plugin, with or
+without modifications, provided that this copyright notice is copied with it.
+Like anything else that's free, taglist.vim is provided *as is* and comes with
+no warranty of any kind, either expressed or implied. In no event will the
+copyright holder be liable for any damamges resulting from the use of this
+software.
+
+==============================================================================
+ *taglist-todo*
+12. Todo~
+
+1. Group tags according to the scope and display them. For example,
+ group all the tags belonging to a C++/Java class
+2. Support for displaying tags in a modified (not-yet-saved) file.
+3. Automatically open the taglist window only for selected filetypes.
+ For other filetypes, close the taglist window.
+4. When using the shell from the MKS toolkit, the taglist plugin
+ doesn't work.
+5. The taglist plugin doesn't work with files edited remotely using the
+ netrw plugin. The exuberant ctags utility cannot process files over
+ scp/rcp/ftp, etc.
+
+==============================================================================
+
+vim:tw=78:ts=8:noet:ft=help:
diff --git a/modules/vim/vim/doc/tags b/modules/vim/vim/doc/tags
new file mode 100644
index 0000000..1992ce7
--- /dev/null
+++ b/modules/vim/vim/doc/tags
@@ -0,0 +1,300 @@
+'NERDChristmasTree' NERD_tree.txt /*'NERDChristmasTree'*
+'NERDTreeAutoCenter' NERD_tree.txt /*'NERDTreeAutoCenter'*
+'NERDTreeAutoCenterThreshold' NERD_tree.txt /*'NERDTreeAutoCenterThreshold'*
+'NERDTreeBookmarksFile' NERD_tree.txt /*'NERDTreeBookmarksFile'*
+'NERDTreeCaseSensitiveSort' NERD_tree.txt /*'NERDTreeCaseSensitiveSort'*
+'NERDTreeChDirMode' NERD_tree.txt /*'NERDTreeChDirMode'*
+'NERDTreeHighlightCursorline' NERD_tree.txt /*'NERDTreeHighlightCursorline'*
+'NERDTreeHijackNetrw' NERD_tree.txt /*'NERDTreeHijackNetrw'*
+'NERDTreeIgnore' NERD_tree.txt /*'NERDTreeIgnore'*
+'NERDTreeMouseMode' NERD_tree.txt /*'NERDTreeMouseMode'*
+'NERDTreeQuitOnOpen' NERD_tree.txt /*'NERDTreeQuitOnOpen'*
+'NERDTreeShowBookmarks' NERD_tree.txt /*'NERDTreeShowBookmarks'*
+'NERDTreeShowFiles' NERD_tree.txt /*'NERDTreeShowFiles'*
+'NERDTreeShowHidden' NERD_tree.txt /*'NERDTreeShowHidden'*
+'NERDTreeShowLineNumbers' NERD_tree.txt /*'NERDTreeShowLineNumbers'*
+'NERDTreeSortOrder' NERD_tree.txt /*'NERDTreeSortOrder'*
+'NERDTreeStatusline' NERD_tree.txt /*'NERDTreeStatusline'*
+'NERDTreeWinPos' NERD_tree.txt /*'NERDTreeWinPos'*
+'NERDTreeWinSize' NERD_tree.txt /*'NERDTreeWinSize'*
+'Tlist_Auto_Highlight_Tag' taglist.txt /*'Tlist_Auto_Highlight_Tag'*
+'Tlist_Auto_Open' taglist.txt /*'Tlist_Auto_Open'*
+'Tlist_Auto_Update' taglist.txt /*'Tlist_Auto_Update'*
+'Tlist_Close_On_Select' taglist.txt /*'Tlist_Close_On_Select'*
+'Tlist_Compact_Format' taglist.txt /*'Tlist_Compact_Format'*
+'Tlist_Ctags_Cmd' taglist.txt /*'Tlist_Ctags_Cmd'*
+'Tlist_Display_Prototype' taglist.txt /*'Tlist_Display_Prototype'*
+'Tlist_Display_Tag_Scope' taglist.txt /*'Tlist_Display_Tag_Scope'*
+'Tlist_Enable_Fold_Column' taglist.txt /*'Tlist_Enable_Fold_Column'*
+'Tlist_Exit_OnlyWindow' taglist.txt /*'Tlist_Exit_OnlyWindow'*
+'Tlist_File_Fold_Auto_Close' taglist.txt /*'Tlist_File_Fold_Auto_Close'*
+'Tlist_GainFocus_On_ToggleOpen' taglist.txt /*'Tlist_GainFocus_On_ToggleOpen'*
+'Tlist_Highlight_Tag_On_BufEnter' taglist.txt /*'Tlist_Highlight_Tag_On_BufEnter'*
+'Tlist_Inc_Winwidth' taglist.txt /*'Tlist_Inc_Winwidth'*
+'Tlist_Max_Submenu_Items' taglist.txt /*'Tlist_Max_Submenu_Items'*
+'Tlist_Max_Tag_Length' taglist.txt /*'Tlist_Max_Tag_Length'*
+'Tlist_Process_File_Always' taglist.txt /*'Tlist_Process_File_Always'*
+'Tlist_Show_Menu' taglist.txt /*'Tlist_Show_Menu'*
+'Tlist_Show_One_File' taglist.txt /*'Tlist_Show_One_File'*
+'Tlist_Sort_Type' taglist.txt /*'Tlist_Sort_Type'*
+'Tlist_Use_Horiz_Window' taglist.txt /*'Tlist_Use_Horiz_Window'*
+'Tlist_Use_Right_Window' taglist.txt /*'Tlist_Use_Right_Window'*
+'Tlist_Use_SingleClick' taglist.txt /*'Tlist_Use_SingleClick'*
+'Tlist_WinHeight' taglist.txt /*'Tlist_WinHeight'*
+'Tlist_WinWidth' taglist.txt /*'Tlist_WinWidth'*
+'loaded_nerd_tree' NERD_tree.txt /*'loaded_nerd_tree'*
+'snippets' snipMate.txt /*'snippets'*
+.snippet snipMate.txt /*.snippet*
+.snippets snipMate.txt /*.snippets*
+:CVSEdit vcscommand.txt /*:CVSEdit*
+:CVSEditors vcscommand.txt /*:CVSEditors*
+:CVSUnedit vcscommand.txt /*:CVSUnedit*
+:CVSWatch vcscommand.txt /*:CVSWatch*
+:CVSWatchAdd vcscommand.txt /*:CVSWatchAdd*
+:CVSWatchOff vcscommand.txt /*:CVSWatchOff*
+:CVSWatchOn vcscommand.txt /*:CVSWatchOn*
+:CVSWatchRemove vcscommand.txt /*:CVSWatchRemove*
+:CVSWatchers vcscommand.txt /*:CVSWatchers*
+:NERDTree NERD_tree.txt /*:NERDTree*
+:NERDTreeClose NERD_tree.txt /*:NERDTreeClose*
+:NERDTreeFind NERD_tree.txt /*:NERDTreeFind*
+:NERDTreeFromBookmark NERD_tree.txt /*:NERDTreeFromBookmark*
+:NERDTreeMirror NERD_tree.txt /*:NERDTreeMirror*
+:NERDTreeToggle NERD_tree.txt /*:NERDTreeToggle*
+:TlistAddFiles taglist.txt /*:TlistAddFiles*
+:TlistAddFilesRecursive taglist.txt /*:TlistAddFilesRecursive*
+:TlistClose taglist.txt /*:TlistClose*
+:TlistDebug taglist.txt /*:TlistDebug*
+:TlistHighlightTag taglist.txt /*:TlistHighlightTag*
+:TlistLock taglist.txt /*:TlistLock*
+:TlistMessages taglist.txt /*:TlistMessages*
+:TlistOpen taglist.txt /*:TlistOpen*
+:TlistSessionLoad taglist.txt /*:TlistSessionLoad*
+:TlistSessionSave taglist.txt /*:TlistSessionSave*
+:TlistShowPrototype taglist.txt /*:TlistShowPrototype*
+:TlistShowTag taglist.txt /*:TlistShowTag*
+:TlistToggle taglist.txt /*:TlistToggle*
+:TlistUndebug taglist.txt /*:TlistUndebug*
+:TlistUnlock taglist.txt /*:TlistUnlock*
+:TlistUpdate taglist.txt /*:TlistUpdate*
+:VCSAdd vcscommand.txt /*:VCSAdd*
+:VCSAnnotate vcscommand.txt /*:VCSAnnotate*
+:VCSBlame vcscommand.txt /*:VCSBlame*
+:VCSCommit vcscommand.txt /*:VCSCommit*
+:VCSDelete vcscommand.txt /*:VCSDelete*
+:VCSDiff vcscommand.txt /*:VCSDiff*
+:VCSGotoOriginal vcscommand.txt /*:VCSGotoOriginal*
+:VCSInfo vcscommand.txt /*:VCSInfo*
+:VCSLock vcscommand.txt /*:VCSLock*
+:VCSLog vcscommand.txt /*:VCSLog*
+:VCSRemove vcscommand.txt /*:VCSRemove*
+:VCSRevert vcscommand.txt /*:VCSRevert*
+:VCSReview vcscommand.txt /*:VCSReview*
+:VCSStatus vcscommand.txt /*:VCSStatus*
+:VCSUnlock vcscommand.txt /*:VCSUnlock*
+:VCSUpdate vcscommand.txt /*:VCSUpdate*
+:VCSVimDiff vcscommand.txt /*:VCSVimDiff*
+ExtractSnips() snipMate.txt /*ExtractSnips()*
+ExtractSnipsFile() snipMate.txt /*ExtractSnipsFile()*
+Filename() snipMate.txt /*Filename()*
+NERDTree NERD_tree.txt /*NERDTree*
+NERDTree-? NERD_tree.txt /*NERDTree-?*
+NERDTree-A NERD_tree.txt /*NERDTree-A*
+NERDTree-B NERD_tree.txt /*NERDTree-B*
+NERDTree-C NERD_tree.txt /*NERDTree-C*
+NERDTree-C-J NERD_tree.txt /*NERDTree-C-J*
+NERDTree-C-K NERD_tree.txt /*NERDTree-C-K*
+NERDTree-D NERD_tree.txt /*NERDTree-D*
+NERDTree-F NERD_tree.txt /*NERDTree-F*
+NERDTree-I NERD_tree.txt /*NERDTree-I*
+NERDTree-J NERD_tree.txt /*NERDTree-J*
+NERDTree-K NERD_tree.txt /*NERDTree-K*
+NERDTree-O NERD_tree.txt /*NERDTree-O*
+NERDTree-P NERD_tree.txt /*NERDTree-P*
+NERDTree-R NERD_tree.txt /*NERDTree-R*
+NERDTree-T NERD_tree.txt /*NERDTree-T*
+NERDTree-U NERD_tree.txt /*NERDTree-U*
+NERDTree-X NERD_tree.txt /*NERDTree-X*
+NERDTree-cd NERD_tree.txt /*NERDTree-cd*
+NERDTree-contents NERD_tree.txt /*NERDTree-contents*
+NERDTree-e NERD_tree.txt /*NERDTree-e*
+NERDTree-f NERD_tree.txt /*NERDTree-f*
+NERDTree-gi NERD_tree.txt /*NERDTree-gi*
+NERDTree-go NERD_tree.txt /*NERDTree-go*
+NERDTree-gs NERD_tree.txt /*NERDTree-gs*
+NERDTree-i NERD_tree.txt /*NERDTree-i*
+NERDTree-m NERD_tree.txt /*NERDTree-m*
+NERDTree-o NERD_tree.txt /*NERDTree-o*
+NERDTree-p NERD_tree.txt /*NERDTree-p*
+NERDTree-q NERD_tree.txt /*NERDTree-q*
+NERDTree-r NERD_tree.txt /*NERDTree-r*
+NERDTree-s NERD_tree.txt /*NERDTree-s*
+NERDTree-t NERD_tree.txt /*NERDTree-t*
+NERDTree-u NERD_tree.txt /*NERDTree-u*
+NERDTree-x NERD_tree.txt /*NERDTree-x*
+NERDTreeAPI NERD_tree.txt /*NERDTreeAPI*
+NERDTreeAbout NERD_tree.txt /*NERDTreeAbout*
+NERDTreeAddKeyMap() NERD_tree.txt /*NERDTreeAddKeyMap()*
+NERDTreeAddMenuItem() NERD_tree.txt /*NERDTreeAddMenuItem()*
+NERDTreeAddMenuSeparator() NERD_tree.txt /*NERDTreeAddMenuSeparator()*
+NERDTreeAddSubmenu() NERD_tree.txt /*NERDTreeAddSubmenu()*
+NERDTreeBookmarkCommands NERD_tree.txt /*NERDTreeBookmarkCommands*
+NERDTreeBookmarkTable NERD_tree.txt /*NERDTreeBookmarkTable*
+NERDTreeBookmarks NERD_tree.txt /*NERDTreeBookmarks*
+NERDTreeChangelog NERD_tree.txt /*NERDTreeChangelog*
+NERDTreeCredits NERD_tree.txt /*NERDTreeCredits*
+NERDTreeFunctionality NERD_tree.txt /*NERDTreeFunctionality*
+NERDTreeGlobalCommands NERD_tree.txt /*NERDTreeGlobalCommands*
+NERDTreeInvalidBookmarks NERD_tree.txt /*NERDTreeInvalidBookmarks*
+NERDTreeKeymapAPI NERD_tree.txt /*NERDTreeKeymapAPI*
+NERDTreeLicense NERD_tree.txt /*NERDTreeLicense*
+NERDTreeMappings NERD_tree.txt /*NERDTreeMappings*
+NERDTreeMenu NERD_tree.txt /*NERDTreeMenu*
+NERDTreeMenuAPI NERD_tree.txt /*NERDTreeMenuAPI*
+NERDTreeOptionDetails NERD_tree.txt /*NERDTreeOptionDetails*
+NERDTreeOptionSummary NERD_tree.txt /*NERDTreeOptionSummary*
+NERDTreeOptions NERD_tree.txt /*NERDTreeOptions*
+NERDTreeRender() NERD_tree.txt /*NERDTreeRender()*
+NERD_tree.txt NERD_tree.txt /*NERD_tree.txt*
+ResetSnippets() snipMate.txt /*ResetSnippets()*
+Tlist_Get_Tag_Prototype_By_Line() taglist.txt /*Tlist_Get_Tag_Prototype_By_Line()*
+Tlist_Get_Tagname_By_Line() taglist.txt /*Tlist_Get_Tagname_By_Line()*
+Tlist_Set_App() taglist.txt /*Tlist_Set_App()*
+Tlist_Update_File_Tags() taglist.txt /*Tlist_Update_File_Tags()*
+VCSCommandCVSDiffOpt vcscommand.txt /*VCSCommandCVSDiffOpt*
+VCSCommandCVSExec vcscommand.txt /*VCSCommandCVSExec*
+VCSCommandCommitOnWrite vcscommand.txt /*VCSCommandCommitOnWrite*
+VCSCommandDeleteOnHide vcscommand.txt /*VCSCommandDeleteOnHide*
+VCSCommandDiffSplit vcscommand.txt /*VCSCommandDiffSplit*
+VCSCommandDisableAll vcscommand.txt /*VCSCommandDisableAll*
+VCSCommandDisableExtensionMappings vcscommand.txt /*VCSCommandDisableExtensionMappings*
+VCSCommandDisableMappings vcscommand.txt /*VCSCommandDisableMappings*
+VCSCommandDisableMenu vcscommand.txt /*VCSCommandDisableMenu*
+VCSCommandEdit vcscommand.txt /*VCSCommandEdit*
+VCSCommandEnableBufferSetup vcscommand.txt /*VCSCommandEnableBufferSetup*
+VCSCommandMapPrefix vcscommand.txt /*VCSCommandMapPrefix*
+VCSCommandMappings vcscommand.txt /*VCSCommandMappings*
+VCSCommandMenuPriority vcscommand.txt /*VCSCommandMenuPriority*
+VCSCommandMenuRoot vcscommand.txt /*VCSCommandMenuRoot*
+VCSCommandResultBufferNameExtension vcscommand.txt /*VCSCommandResultBufferNameExtension*
+VCSCommandResultBufferNameFunction vcscommand.txt /*VCSCommandResultBufferNameFunction*
+VCSCommandSVKExec vcscommand.txt /*VCSCommandSVKExec*
+VCSCommandSVNDiffExt vcscommand.txt /*VCSCommandSVNDiffExt*
+VCSCommandSVNDiffOpt vcscommand.txt /*VCSCommandSVNDiffOpt*
+VCSCommandSVNExec vcscommand.txt /*VCSCommandSVNExec*
+VCSCommandSplit vcscommand.txt /*VCSCommandSplit*
+VCSCommandVCSTypeOverride vcscommand.txt /*VCSCommandVCSTypeOverride*
+b:VCSCommandCommand vcscommand.txt /*b:VCSCommandCommand*
+b:VCSCommandOriginalBuffer vcscommand.txt /*b:VCSCommandOriginalBuffer*
+b:VCSCommandSourceFile vcscommand.txt /*b:VCSCommandSourceFile*
+b:VCSCommandVCSType vcscommand.txt /*b:VCSCommandVCSType*
+bufexplorer bufexplorer.txt /*bufexplorer*
+bufexplorer-changelog bufexplorer.txt /*bufexplorer-changelog*
+bufexplorer-credits bufexplorer.txt /*bufexplorer-credits*
+bufexplorer-customization bufexplorer.txt /*bufexplorer-customization*
+bufexplorer-installation bufexplorer.txt /*bufexplorer-installation*
+bufexplorer-todo bufexplorer.txt /*bufexplorer-todo*
+bufexplorer-usage bufexplorer.txt /*bufexplorer-usage*
+bufexplorer.txt bufexplorer.txt /*bufexplorer.txt*
+buffer-explorer bufexplorer.txt /*buffer-explorer*
+cvscommand-changes vcscommand.txt /*cvscommand-changes*
+g:bufExplorerDefaultHelp bufexplorer.txt /*g:bufExplorerDefaultHelp*
+g:bufExplorerDetailedHelp bufexplorer.txt /*g:bufExplorerDetailedHelp*
+g:bufExplorerFindActive bufexplorer.txt /*g:bufExplorerFindActive*
+g:bufExplorerReverseSort bufexplorer.txt /*g:bufExplorerReverseSort*
+g:bufExplorerShowDirectories bufexplorer.txt /*g:bufExplorerShowDirectories*
+g:bufExplorerShowRelativePath bufexplorer.txt /*g:bufExplorerShowRelativePath*
+g:bufExplorerShowUnlisted bufexplorer.txt /*g:bufExplorerShowUnlisted*
+g:bufExplorerSortBy bufexplorer.txt /*g:bufExplorerSortBy*
+g:bufExplorerSplitBelow bufexplorer.txt /*g:bufExplorerSplitBelow*
+g:bufExplorerSplitOutPathName bufexplorer.txt /*g:bufExplorerSplitOutPathName*
+g:bufExplorerSplitRight bufexplorer.txt /*g:bufExplorerSplitRight*
+g:snippets_dir snipMate.txt /*g:snippets_dir*
+g:snips_author snipMate.txt /*g:snips_author*
+git-vim git-vim.txt /*git-vim*
+git-vim-commands git-vim.txt /*git-vim-commands*
+git-vim-contents git-vim.txt /*git-vim-contents*
+git-vim-keymaps git-vim.txt /*git-vim-keymaps*
+git-vim-license git-vim.txt /*git-vim-license*
+git-vim.txt git-vim.txt /*git-vim.txt*
+i_CTRL-R_<Tab> snipMate.txt /*i_CTRL-R_<Tab>*
+indexer indexer.txt /*indexer*
+indexer-commands indexer.txt /*indexer-commands*
+indexer-options indexer.txt /*indexer-options*
+indexer-plugin indexer.txt /*indexer-plugin*
+indexer.txt indexer.txt /*indexer.txt*
+list-snippets snipMate.txt /*list-snippets*
+multi_snip snipMate.txt /*multi_snip*
+project project.txt /*project*
+project-adding-mappings project.txt /*project-adding-mappings*
+project-example project.txt /*project-example*
+project-flags project.txt /*project-flags*
+project-inheritance project.txt /*project-inheritance*
+project-invoking project.txt /*project-invoking*
+project-mappings project.txt /*project-mappings*
+project-plugin project.txt /*project-plugin*
+project-settings project.txt /*project-settings*
+project-syntax project.txt /*project-syntax*
+project-tips project.txt /*project-tips*
+project.txt project.txt /*project.txt*
+snipMate snipMate.txt /*snipMate*
+snipMate-$# snipMate.txt /*snipMate-$#*
+snipMate-${#:} snipMate.txt /*snipMate-${#:}*
+snipMate-${#} snipMate.txt /*snipMate-${#}*
+snipMate-author snipMate.txt /*snipMate-author*
+snipMate-commands snipMate.txt /*snipMate-commands*
+snipMate-contact snipMate.txt /*snipMate-contact*
+snipMate-description snipMate.txt /*snipMate-description*
+snipMate-disadvantages snipMate.txt /*snipMate-disadvantages*
+snipMate-expandtab snipMate.txt /*snipMate-expandtab*
+snipMate-features snipMate.txt /*snipMate-features*
+snipMate-filename snipMate.txt /*snipMate-filename*
+snipMate-indenting snipMate.txt /*snipMate-indenting*
+snipMate-placeholders snipMate.txt /*snipMate-placeholders*
+snipMate-remap snipMate.txt /*snipMate-remap*
+snipMate-settings snipMate.txt /*snipMate-settings*
+snipMate-usage snipMate.txt /*snipMate-usage*
+snipMate.txt snipMate.txt /*snipMate.txt*
+snippet snipMate.txt /*snippet*
+snippet-syntax snipMate.txt /*snippet-syntax*
+snippets snipMate.txt /*snippets*
+taglist-commands taglist.txt /*taglist-commands*
+taglist-debug taglist.txt /*taglist-debug*
+taglist-extend taglist.txt /*taglist-extend*
+taglist-faq taglist.txt /*taglist-faq*
+taglist-functions taglist.txt /*taglist-functions*
+taglist-install taglist.txt /*taglist-install*
+taglist-internet taglist.txt /*taglist-internet*
+taglist-intro taglist.txt /*taglist-intro*
+taglist-keys taglist.txt /*taglist-keys*
+taglist-license taglist.txt /*taglist-license*
+taglist-menu taglist.txt /*taglist-menu*
+taglist-options taglist.txt /*taglist-options*
+taglist-requirements taglist.txt /*taglist-requirements*
+taglist-session taglist.txt /*taglist-session*
+taglist-todo taglist.txt /*taglist-todo*
+taglist-using taglist.txt /*taglist-using*
+taglist.txt taglist.txt /*taglist.txt*
+vcscommand vcscommand.txt /*vcscommand*
+vcscommand-buffer-management vcscommand.txt /*vcscommand-buffer-management*
+vcscommand-buffer-variables vcscommand.txt /*vcscommand-buffer-variables*
+vcscommand-bugs vcscommand.txt /*vcscommand-bugs*
+vcscommand-commands vcscommand.txt /*vcscommand-commands*
+vcscommand-config vcscommand.txt /*vcscommand-config*
+vcscommand-contents vcscommand.txt /*vcscommand-contents*
+vcscommand-customize vcscommand.txt /*vcscommand-customize*
+vcscommand-events vcscommand.txt /*vcscommand-events*
+vcscommand-install vcscommand.txt /*vcscommand-install*
+vcscommand-intro vcscommand.txt /*vcscommand-intro*
+vcscommand-manual vcscommand.txt /*vcscommand-manual*
+vcscommand-mappings vcscommand.txt /*vcscommand-mappings*
+vcscommand-mappings-override vcscommand.txt /*vcscommand-mappings-override*
+vcscommand-naming vcscommand.txt /*vcscommand-naming*
+vcscommand-options vcscommand.txt /*vcscommand-options*
+vcscommand-ssh vcscommand.txt /*vcscommand-ssh*
+vcscommand-ssh-config vcscommand.txt /*vcscommand-ssh-config*
+vcscommand-ssh-env vcscommand.txt /*vcscommand-ssh-env*
+vcscommand-ssh-other vcscommand.txt /*vcscommand-ssh-other*
+vcscommand-ssh-wrapper vcscommand.txt /*vcscommand-ssh-wrapper*
+vcscommand-statusline vcscommand.txt /*vcscommand-statusline*
+vcscommand.txt vcscommand.txt /*vcscommand.txt*
diff --git a/modules/vim/vim/doc/vcscommand.txt b/modules/vim/vim/doc/vcscommand.txt
new file mode 100644
index 0000000..5e0c4c0
--- /dev/null
+++ b/modules/vim/vim/doc/vcscommand.txt
@@ -0,0 +1,835 @@
+*vcscommand.txt* vcscommand
+Copyright (c) Bob Hiestand
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+IN THE SOFTWARE.
+
+For instructions on installing this file, type
+ :help add-local-help
+inside Vim.
+
+Author: Bob Hiestand <bob.hiestand@gmail.com>
+Credits: Benji Fisher's excellent MatchIt documentation
+
+==============================================================================
+1. Contents *vcscommand-contents*
+
+ Installation : |vcscommand-install|
+ vcscommand Intro : |vcscommand|
+ vcscommand Manual : |vcscommand-manual|
+ Customization : |vcscommand-customize|
+ SSH "integration" : |vcscommand-ssh|
+ Changes from cvscommand : |cvscommand-changes|
+ Bugs : |vcscommand-bugs|
+
+==============================================================================
+
+2. vcscommand Installation *vcscommand-install*
+
+The vcscommand plugin comprises five files: vcscommand.vim, vcssvn.vim,
+vcscvs.vim, vcssvk.vim and vcscommand.txt (this file). In order to install
+the plugin, place the vcscommand.vim, vcssvn.vim, vcssvk.vim, and vcscvs.vim
+files into a plugin directory in your runtime path (please see
+|add-global-plugin| and |'runtimepath'|.
+
+This help file can be included in the VIM help system by copying it into a
+'doc' directory in your runtime path and then executing the |:helptags|
+command, specifying the full path of the 'doc' directory. Please see
+|add-local-help| for more details.
+
+vcscommand may be customized by setting variables, creating maps, and
+specifying event handlers. Please see |vcscommand-customize| for more
+details.
+
+==============================================================================
+
+3. vcscommand Intro *vcscommand*
+ *vcscommand-intro*
+
+The vcscommand plugin provides global ex commands for manipulating
+version-controlled source files, currently those controlled either by CVS or
+Subversion. In general, each command operates on the current buffer and
+accomplishes a separate source control function, such as update, commit, log,
+and others (please see |vcscommand-commands| for a list of all available
+commands). The results of each operation are displayed in a scratch buffer.
+Several buffer variables are defined for those scratch buffers (please see
+|vcscommand-buffer-variables|).
+
+The notion of "current file" means either the current buffer, or, in the case
+of a directory buffer (such as Explorer or netrw buffers), the directory (and
+all subdirectories) represented by the the buffer.
+
+For convenience, any vcscommand invoked on a vcscommand scratch buffer acts as
+though it was invoked on the original file and splits the screen so that the
+output appears in a new window.
+
+Many of the commands accept revisions as arguments. By default, most operate
+on the most recent revision on the current branch if no revision is specified.
+
+Each vcscommand is mapped to a key sequence starting with the |<Leader>|
+keystroke. The default mappings may be overridden by supplying different
+mappings before the plugin is loaded, such as in the vimrc, in the standard
+fashion for plugin mappings. For examples, please see
+|vcscommand-mappings-override|.
+
+The vcscommand plugin may be configured in several ways. For more details,
+please see |vcscommand-customize|.
+
+==============================================================================
+
+4. vcscommand Manual *vcscommand-manual*
+
+4.1 vcscommand commands *vcscommand-commands*
+
+vcscommand defines the following commands:
+
+|:VCSAdd|
+|:VCSAnnotate|
+|:VCSBlame|
+|:VCSCommit|
+|:VCSDelete|
+|:VCSDiff|
+|:VCSGotoOriginal|
+|:VCSLog|
+|:VCSRemove|
+|:VCSRevert|
+|:VCSReview|
+|:VCSStatus|
+|:VCSUpdate|
+|:VCSVimDiff|
+
+The following commands are specific to CVS files:
+
+|:CVSEdit|
+|:CVSEditors|
+|:CVSUnedit|
+|:CVSWatch|
+|:CVSWatchAdd|
+|:CVSWatchOn|
+|:CVSWatchOff|
+|:CVSWatchRemove|
+|:CVSWatchers|
+
+:VCSAdd *:VCSAdd*
+
+This command adds the current file to source control. Please note, this does
+not commit the newly-added file. All parameters to the command are passed to
+the underlying VCS.
+
+:VCSAnnotate[!] *:VCSAnnotate*
+
+This command displays the current file with each line annotated with the
+version in which it was most recently changed. If an argument is given, the
+argument is used as a revision number to display. If not given an argument,
+it uses the most recent version of the file (on the current branch, if under
+CVS control). Additionally, if the current buffer is a VCSAnnotate buffer
+already, the version number on the current line is used.
+
+If '!' is used, the view of the annotated buffer is split so that the
+annotation is in a separate window from the content, and each is highlighted
+separately.
+
+For CVS buffers, the 'VCSCommandCVSAnnotateParent' option, if set to non-zero,
+will cause the above behavior to change. Instead of annotating the version on
+the current line, the parent revision is used instead, crossing branches if
+necessary.
+
+With no arguments the cursor will jump to the line in the annotated buffer
+corresponding to the current line in the source buffer.
+
+:VCSBlame[!] *:VCSBlame*
+
+Alias for |:VCSAnnotate|.
+
+:VCSCommit[!] *:VCSCommit*
+
+This command commits changes to the current file to source control.
+
+If called with arguments, the arguments are the log message.
+
+If '!' is used, an empty log message is committed.
+
+If called with no arguments, this is a two-step command. The first step opens
+a buffer to accept a log message. When that buffer is written, it is
+automatically closed and the file is committed using the information from that
+log message. The commit can be abandoned if the log message buffer is deleted
+or wiped before being written.
+
+Alternatively, the mapping that is used to invoke :VCSCommit (by default
+|<Leader>|cc, please see |vcscommand-mappings|) can be used in the log message
+buffer in Normal mode to immediately commit. This is useful if the
+|VCSCommandCommitOnWrite| variable is set to 0 to disable the normal
+commit-on-write behavior.
+
+:VCSDelete *:VCSDelete*
+
+Deletes the current file and removes it from source control. All parameters
+to the command are passed to the underlying VCS.
+
+:VCSDiff *:VCSDiff*
+
+With no arguments, this displays the differences between the current file and
+its parent version under source control in a new scratch buffer.
+
+With one argument, the diff is performed on the current file against the
+specified revision.
+
+With two arguments, the diff is performed between the specified revisions of
+the current file.
+
+For CVS, this command uses the |VCSCommandCVSDiffOpt| variable to specify diff
+options. If that variable does not exist, a plugin-specific default is used.
+If you wish to have no options, then set it to the empty string.
+
+For SVN, this command uses the |VCSCommandSVNDiffOpt| variable to specify diff
+options. If that variable does not exist, the SVN default is used.
+Additionally, |VCSCommandSVNDiffExt| can be used to select an external diff
+application.
+
+:VCSGotoOriginal *:VCSGotoOriginal*
+
+This command jumps to the source buffer if the current buffer is a VCS scratch
+buffer.
+
+:VCSGotoOriginal!
+
+Like ":VCSGotoOriginal" but also executes :bufwipeout on all VCS scrach
+buffers associated with the original file.
+
+:VCSInfo *:VCSInfo*
+
+This command displays extended information about the current file in a new
+scratch buffer.
+
+:VCSLock *:VCSLock*
+
+This command locks the current file in order to prevent other users from
+concurrently modifying it. The exact semantics of this command depend on the
+underlying VCS. This does nothing in CVS. All parameters are passed to the
+underlying VCS.
+
+:VCSLog *:VCSLog*
+
+Displays the version history of the current file in a new scratch buffer. If
+there is one parameter supplied, it is taken as as a revision parameters to be
+passed through to the underlying VCS. Otherwise, all parameters are passed to
+the underlying VCS.
+
+:VCSRemove *:VCSRemove*
+
+Alias for |:VCSDelete|.
+
+:VCSRevert *:VCSRevert*
+
+This command replaces the current file with the most recent version from the
+repository in order to wipe out any undesired changes.
+
+:VCSReview *:VCSReview*
+
+Displays a particular version of the current file in a new scratch buffer. If
+no argument is given, the most recent version of the file on the current
+branch is retrieved.
+
+:VCSStatus *:VCSStatus*
+
+Displays versioning information about the current file in a new scratch
+buffer. All parameters are passed to the underlying VCS.
+
+
+:VCSUnlock *:VCSUnlock*
+
+Unlocks the current file in order to allow other users from concurrently
+modifying it. The exact semantics of this command depend on the underlying
+VCS. All parameters are passed to the underlying VCS.
+
+:VCSUpdate *:VCSUpdate*
+
+Updates the current file with any relevant changes from the repository. This
+intentionally does not automatically reload the current buffer, though vim
+should prompt the user to do so if the underlying file is altered by this
+command.
+
+:VCSVimDiff *:VCSVimDiff*
+
+Uses vimdiff to display differences between versions of the current file.
+
+If no revision is specified, the most recent version of the file on the
+current branch is used. With one argument, that argument is used as the
+revision as above. With two arguments, the differences between the two
+revisions is displayed using vimdiff.
+
+With either zero or one argument, the original buffer is used to perform the
+vimdiff. When the scratch buffer is closed, the original buffer will be
+returned to normal mode.
+
+Once vimdiff mode is started using the above methods, additional vimdiff
+buffers may be added by passing a single version argument to the command.
+There may be up to 4 vimdiff buffers total.
+
+Using the 2-argument form of the command resets the vimdiff to only those 2
+versions. Additionally, invoking the command on a different file will close
+the previous vimdiff buffers.
+
+:CVSEdit *:CVSEdit*
+
+This command performs "cvs edit" on the current file. Yes, the output buffer
+in this case is almost completely useless.
+
+:CVSEditors *:CVSEditors*
+
+This command performs "cvs edit" on the current file.
+
+:CVSUnedit *:CVSUnedit*
+
+Performs "cvs unedit" on the current file. Again, yes, the output buffer here
+is basically useless.
+
+:CVSWatch *:CVSWatch*
+
+This command takes an argument which must be one of [on|off|add|remove]. The
+command performs "cvs watch" with the given argument on the current file.
+
+:CVSWatchAdd *:CVSWatchAdd*
+
+This command is an alias for ":CVSWatch add"
+
+:CVSWatchOn *:CVSWatchOn*
+
+This command is an alias for ":CVSWatch on"
+
+:CVSWatchOff *:CVSWatchOff*
+
+This command is an alias for ":CVSWatch off"
+
+:CVSWatchRemove *:CVSWatchRemove*
+
+This command is an alias for ":CVSWatch remove"
+
+:CVSWatchers *:CVSWatchers*
+
+This command performs "cvs watchers" on the current file.
+
+4.2 Mappings *vcscommand-mappings*
+
+By default, a mapping is defined for each command. These mappings execute the
+default (no-argument) form of each command.
+
+|<Leader>|ca VCSAdd
+|<Leader>|cn VCSAnnotate
+|<Leader>|cN VCSAnnotate!
+|<Leader>|cc VCSCommit
+|<Leader>|cD VCSDelete
+|<Leader>|cd VCSDiff
+|<Leader>|cg VCSGotoOriginal
+|<Leader>|cG VCSGotoOriginal!
+|<Leader>|ci VCSInfo
+|<Leader>|cl VCSLog
+|<Leader>|cL VCSLock
+|<Leader>|cr VCSReview
+|<Leader>|cs VCSStatus
+|<Leader>|cu VCSUpdate
+|<Leader>|cU VCSUnlock
+|<Leader>|cv VCSVimDiff
+
+Only for CVS buffers:
+
+|<Leader>|ce CVSEdit
+|<Leader>|cE CVSEditors
+|<Leader>|ct CVSUnedit
+|<Leader>|cwv CVSWatchers
+|<Leader>|cwa CVSWatchAdd
+|<Leader>|cwn CVSWatchOn
+|<Leader>|cwf CVSWatchOff
+|<Leader>|cwf CVSWatchRemove
+
+ *vcscommand-mappings-override*
+
+The default mappings can be overridden by user-provided instead by mapping to
+<Plug>CommandName. This is especially useful when these mappings collide with
+other existing mappings (vim will warn of this during plugin initialization,
+but will not clobber the existing mappings).
+
+There are three methods for controlling mapping:
+
+First, maps can be overriden for individual commands. For instance, to
+override the default mapping for :VCSAdd to set it to '\add', add the
+following to the vimrc:
+
+nmap \add <Plug>VCSAdd
+
+Second, the default map prefix ('<Leader>c') can be overridden by defining the
+|VCSCommandMapPrefix| variable.
+
+Third, the entire set of default maps can be overridden by defining the
+|VCSCommandMappings| variable.
+
+
+4.3 Automatic buffer variables *vcscommand-buffer-variables*
+
+Several buffer variables are defined in each vcscommand result buffer. These
+may be useful for additional customization in callbacks defined in the event
+handlers (please see |vcscommand-events|).
+
+The following variables are automatically defined:
+
+b:VCSCommandOriginalBuffer *b:VCSCommandOriginalBuffer*
+
+This variable is set to the buffer number of the source file.
+
+b:VCSCommandCommand *b:VCSCommandCommand*
+
+This variable is set to the name of the vcscommand that created the result
+buffer.
+
+b:VCSCommandSourceFile *b:VCSCommandSourceFile*
+
+This variable is set to the name of the original file under source control.
+
+b:VCSCommandVCSType *b:VCSCommandVCSType*
+
+This variable is set to the type of the source control. This variable is also
+set on the original file itself.
+==============================================================================
+
+5. Configuration and customization *vcscommand-customize*
+ *vcscommand-config*
+
+The vcscommand plugin can be configured in several ways: by setting
+configuration variables (see |vcscommand-options|) or by defining vcscommand
+event handlers (see |vcscommand-events|). Additionally, the vcscommand plugin
+supports a customized status line (see |vcscommand-statusline| and
+|vcscommand-buffer-management|).
+
+5.1 vcscommand configuration variables *vcscommand-options*
+
+Several variables affect the plugin's behavior. These variables are checked
+at time of execution, and may be defined at the window, buffer, or global
+level and are checked in that order of precedence.
+
+
+The following variables are available:
+
+|VCSCommandCommitOnWrite|
+|VCSCommandCVSDiffOpt|
+|VCSCommandCVSExec|
+|VCSCommandDeleteOnHide|
+|VCSCommandDiffSplit|
+|VCSCommandDisableAll|
+|VCSCommandDisableMappings|
+|VCSCommandDisableExtensionMappings|
+|VCSCommandDisableMenu|
+|VCSCommandEdit|
+|VCSCommandEnableBufferSetup|
+|VCSCommandMappings|
+|VCSCommandMapPrefix|
+|VCSCommandMenuPriority|
+|VCSCommandMenuRoot|
+|VCSCommandResultBufferNameExtension|
+|VCSCommandResultBufferNameFunction|
+|VCSCommandSplit|
+|VCSCommandSVKExec|
+|VCSCommandSVNDiffExt|
+|VCSCommandSVNDiffOpt|
+|VCSCommandSVNExec|
+|VCSCommandVCSTypeOverride|
+
+VCSCommandCommitOnWrite *VCSCommandCommitOnWrite*
+
+This variable, if set to a non-zero value, causes the pending commit
+to take place immediately as soon as the log message buffer is written.
+If set to zero, only the VCSCommit mapping will cause the pending commit to
+occur. If not set, it defaults to 1.
+
+VCSCommandCVSExec *VCSCommandCVSExec*
+
+This variable controls the executable used for all CVS commands If not set,
+it defaults to "cvs".
+
+VCSCommandDeleteOnHide *VCSCommandDeleteOnHide*
+
+This variable, if set to a non-zero value, causes the temporary result buffers
+to automatically delete themselves when hidden.
+
+VCSCommandCVSDiffOpt *VCSCommandCVSDiffOpt*
+
+This variable, if set, determines the options passed to the diff command of
+CVS. If not set, it defaults to 'u'.
+
+VCSCommandDiffSplit *VCSCommandDiffSplit*
+
+This variable overrides the |VCSCommandSplit| variable, but only for buffers
+created with |:VCSVimDiff|.
+
+VCSCommandDisableAll *VCSCommandDisableAll*
+
+This variable, if set, prevents the plugin or any extensions from loading at
+all. This is useful when a single runtime distribution is used on multiple
+systems with varying versions.
+
+VCSCommandDisableMappings *VCSCommandDisableMappings*
+
+This variable, if set to a non-zero value, prevents the default command
+mappings from being set. This supercedes
+|VCSCommandDisableExtensionMappings|.
+
+VCSCommandDisableExtensionMappings *VCSCommandDisableExtensionMappings*
+
+This variable, if set to a non-zero value, prevents the default command
+mappings from being set for commands specific to an individual VCS.
+
+VCSCommandEdit *VCSCommandEdit*
+
+This variable controls whether the original buffer is replaced ('edit') or
+split ('split'). If not set, it defaults to 'split'.
+
+VCSCommandDisableMenu *VCSCommandDisableMenu*
+
+This variable, if set to a non-zero value, prevents the default command menu
+from being set.
+
+VCSCommandEnableBufferSetup *VCSCommandEnableBufferSetup*
+
+This variable, if set to a non-zero value, activates VCS buffer management
+mode see (|vcscommand-buffer-management|). This mode means that the
+'VCSCommandBufferInfo' variable is filled with version information if the file
+is VCS-controlled. This is useful for displaying version information in the
+status bar.
+
+VCSCommandMappings *VCSCommandMappings*
+
+This variable, if set, overrides the default mappings used for shortcuts. It
+should be a List of 2-element Lists, each containing a shortcut and function
+name pair. The value of the '|VCSCommandMapPrefix|' variable will be added to
+each shortcut.
+
+VCSCommandMapPrefix *VCSCommandMapPrefix*
+
+This variable, if set, overrides the default mapping prefix ('<Leader>c').
+This allows customization of the mapping space used by the vcscommand
+shortcuts.
+
+VCSCommandMenuPriority *VCSCommandMenuPriority*
+
+This variable, if set, overrides the default menu priority '' (empty)
+
+VCSCommandMenuRoot *VCSCommandMenuRoot*
+
+This variable, if set, overrides the default menu root 'Plugin.VCS'
+
+VCSCommandResultBufferNameExtension *VCSCommandResultBufferNameExtension*
+
+This variable, if set to a non-blank value, is appended to the name of the VCS
+command output buffers. For example, '.vcs'. Using this option may help
+avoid problems caused by autocommands dependent on file extension.
+
+VCSCommandResultBufferNameFunction *VCSCommandResultBufferNameFunction*
+
+This variable, if set, specifies a custom function for naming VCS command
+output buffers. This function is expected to return the new buffer name, and
+will be passed the following arguments:
+
+ command - name of the VCS command being executed (such as 'Log' or
+ 'Diff').
+
+ originalBuffer - buffer number of the source file.
+
+ vcsType - type of VCS controlling this file (such as 'CVS' or 'SVN').
+
+ statusText - extra text associated with the VCS action (such as version
+ numbers).
+
+VCSCommandSplit *VCSCommandSplit*
+
+This variable controls the orientation of the various window splits that
+may occur.
+
+If set to 'horizontal', the resulting windows will be on stacked on top of
+one another. If set to 'vertical', the resulting windows will be
+side-by-side. If not set, it defaults to 'horizontal' for all but
+VCSVimDiff windows. VCSVimDiff windows default to the user's 'diffopt'
+setting, if set, otherwise 'vertical'.
+
+VCSCommandSVKExec *VCSCommandSVKExec*
+
+This variable controls the executable used for all SVK commands If not set,
+it defaults to "svk".
+
+VCSCommandSVNDiffExt *VCSCommandSVNDiffExt*
+
+This variable, if set, is passed to SVN via the --diff-cmd command to select
+an external application for performing the diff.
+
+VCSCommandSVNDiffOpt *VCSCommandSVNDiffOpt*
+
+This variable, if set, determines the options passed with the '-x' parameter
+to the SVN diff command. If not set, no options are passed.
+
+VCSCommandSVNExec *VCSCommandSVNExec*
+
+This variable controls the executable used for all SVN commands If not set,
+it defaults to "svn".
+
+VCSCommandVCSTypeOverride *VCSCommandVCSTypeOverride*
+
+This variable allows the VCS type detection to be overridden on a path-by-path
+basis. The value of this variable is expected to be a List of Lists. Each
+item in the high-level List is a List containing two elements. The first
+element is a regular expression that will be matched against the full file
+name of a given buffer. If it matches, the second element will be used as the
+VCS type.
+
+5.2 VCSCommand events *vcscommand-events*
+
+For additional customization, vcscommand can trigger user-defined events.
+Event handlers are provided by defining User event autocommands (see
+|autocommand|, |User|) in the vcscommand group with patterns matching the
+event name.
+
+For instance, the following could be added to the vimrc to provide a 'q'
+mapping to quit a vcscommand scratch buffer:
+
+augroup VCSCommand
+ au User VCSBufferCreated silent! nmap <unique> <buffer> q :bwipeout<cr>
+augroup END
+
+The following hooks are available:
+
+VCSBufferCreated This event is fired just after a vcscommand
+ result buffer is created and populated. It is
+ executed within the context of the vcscommand
+ buffer. The vcscommand buffer variables may
+ be useful for handlers of this event (please
+ see |vcscommand-buffer-variables|).
+
+VCSBufferSetup This event is fired just after vcscommand buffer
+ setup occurs, if enabled.
+
+VCSPluginInit This event is fired when the vcscommand plugin
+ first loads.
+
+VCSPluginFinish This event is fired just after the vcscommand
+ plugin loads.
+
+VCSVimDiffFinish This event is fired just after the VCSVimDiff
+ command executes to allow customization of,
+ for instance, window placement and focus.
+
+Additionally, there is another hook which is used internally to handle loading
+the multiple scripts in order. This hook should probably not be used by an
+end user without a good idea of how it works. Among other things, any events
+associated with this hook are cleared after they are executed (during
+vcscommand.vim script initialization).
+
+VCSLoadExtensions This event is fired just before the
+ VCSPluginFinish. It is used internally to
+ execute any commands from the VCS
+ implementation plugins that needs to be
+ deferred until the primary plugin is
+ initialized.
+
+5.3 vcscommand buffer naming *vcscommand-naming*
+
+vcscommand result buffers use the following naming convention:
+[{VCS type} {VCS command} {Source file name}]
+
+If additional buffers are created that would otherwise conflict, a
+distinguishing number is added:
+
+[{VCS type} {VCS command} {Source file name}] (1,2, etc)
+
+5.4 vcscommand status line support *vcscommand-statusline*
+
+It is intended that the user will customize the |'statusline'| option to
+include vcscommand result buffer attributes. A sample function that may be
+used in the |'statusline'| option is provided by the plugin,
+VCSCommandGetStatusLine(). In order to use that function in the status line, do
+something like the following:
+
+set statusline=%<%f\ %{VCSCommandGetStatusLine()}\ %h%m%r%=%l,%c%V\ %P
+
+of which %{VCSCommandGetStatusLine()} is the relevant portion.
+
+The sample VCSCommandGetStatusLine() function handles both vcscommand result
+buffers and VCS-managed files if vcscommand buffer management is enabled
+(please see |vcscommand-buffer-management|).
+
+5.5 vcscommand buffer management *vcscommand-buffer-management*
+
+The vcscommand plugin can operate in buffer management mode, which means that
+it attempts to set a buffer variable ('VCSCommandBufferInfo') upon entry into
+a buffer. This is rather slow because it means that the VCS will be invoked
+at each entry into a buffer (during the |BufEnter| autocommand).
+
+This mode is disabled by default. In order to enable it, set the
+|VCSCommandEnableBufferSetup| variable to a true (non-zero) value. Enabling
+this mode simply provides the buffer variable mentioned above. The user must
+explicitly include information from the variable in the |'statusline'| option
+if they are to appear in the status line (but see |vcscommand-statusline| for
+a simple way to do that).
+
+The 'VCSCommandBufferInfo' variable is a list which contains, in order, the
+revision of the current file, the latest revision of the file in the
+repository, and (for CVS) the name of the branch. If those values cannot be
+determined, the list is a single element: 'Unknown'.
+
+==============================================================================
+
+6. SSH "integration" *vcscommand-ssh*
+
+The following instructions are intended for use in integrating the
+vcscommand.vim plugin with an SSH-based CVS environment.
+
+Familiarity with SSH and CVS are assumed.
+
+These instructions assume that the intent is to have a message box pop up in
+order to allow the user to enter a passphrase. If, instead, the user is
+comfortable using certificate-based authentication, then only instructions
+6.1.1 and 6.1.2 (and optionally 6.1.4) need to be followed; ssh should then
+work transparently.
+
+6.1 Environment settings *vcscommand-ssh-env*
+
+6.1.1 CVSROOT should be set to something like:
+
+ :ext:user@host:/path_to_repository
+
+6.1.2 CVS_RSH should be set to:
+
+ ssh
+
+ Together, those settings tell CVS to use ssh as the transport when
+ performing CVS calls.
+
+6.1.3 SSH_ASKPASS should be set to the password-dialog program. In my case,
+ running gnome, it's set to:
+
+ /usr/libexec/openssh/gnome-ssh-askpass
+
+ This tells SSH how to get passwords if no input is available.
+
+6.1.4 OPTIONAL. You may need to set SSH_SERVER to the location of the cvs
+ executable on the remote (server) machine.
+
+6.2 CVS wrapper program *vcscommand-ssh-wrapper*
+
+Now you need to convince SSH to use the password-dialog program. This means
+you need to execute SSH (and therefore CVS) without standard input. The
+following script is a simple perl wrapper that dissasociates the CVS command
+from the current terminal. Specific steps to do this may vary from system to
+system; the following example works for me on linux.
+
+#!/usr/bin/perl -w
+use strict;
+use POSIX qw(setsid);
+open STDIN, '/dev/null';
+fork and do {wait; exit;};
+setsid;
+exec('cvs', @ARGV);
+
+6.3 Configuring vcscommand.vim *vcscommand-ssh-config*
+
+At this point, you should be able to use your wrapper script to invoke CVS with
+various commands, and get the password dialog. All that's left is to make CVS
+use your newly-created wrapper script.
+
+6.3.1 Tell vcscommand.vim what CVS executable to use. The easiest way to do this
+ is globally, by putting the following in your .vimrc:
+
+ let VCSCommandCVSExec=/path/to/cvs/wrapper/script
+
+6.4 Where to go from here *vcscommand-ssh-other*
+
+The script given above works even when non-SSH CVS connections are used,
+except possibly when interactively entering the message for CVS commit log
+(depending on the editor you use... VIM works fine). Since the vcscommand.vim
+plugin handles that message without a terminal, the wrapper script can be used
+all the time.
+
+This allows mixed-mode operation, where some work is done with SSH-based CVS
+repositories, and others with pserver or local access.
+
+It is possible, though beyond the scope of the plugin, to dynamically set the
+CVS executable based on the CVSROOT for the file being edited. The user
+events provided (such as VCSBufferCreated and VCSBufferSetup) can be used to
+set a buffer-local value (b:VCSCommandCVSExec) to override the CVS executable
+on a file-by-file basis. Alternatively, much the same can be done (less
+automatically) by the various project-oriented plugins out there.
+
+It is highly recommended for ease-of-use that certificates with no passphrase
+or ssh-agent are employed so that the user is not given the password prompt
+too often.
+
+==============================================================================
+
+7. Changes from cvscommand *cvscommand-changes*
+
+1. Require Vim 7 in order to leverage several convenient features; also
+because I wanted to play with Vim 7.
+
+2. Renamed commands to start with 'VCS' instead of 'CVS'. The exceptions are
+the 'CVSEdit' and 'CVSWatch' family of commands, which are specific to CVS.
+
+3. Renamed options, events to start with 'VCSCommand'.
+
+4. Removed option to jump to the parent version of the current line in an
+annotated buffer, as opposed to the version on the current line. This made
+little sense in the branching scheme used by subversion, where jumping to a
+parent branch required finding a different location in the repository. It
+didn't work consistently in CVS anyway.
+
+5. Removed option to have nameless scratch buffers.
+
+6. Changed default behavior of scratch buffers to split the window instead of
+displaying in the current window. This may still be overridden using the
+'VCSCommandEdit' option.
+
+7. Split plugin into multiple plugins.
+
+8. Added 'VCSLock' and 'VCSUnlock' commands. These are implemented for
+subversion but not for CVS. These were not kept specific to subversion as they
+seemed more general in nature and more likely to be supported by any future VCS
+supported by this plugin.
+
+9. Changed name of buffer variables set by commands.
+
+'b:cvsOrigBuffNR' became 'b:VCSCommandOriginalBuffer'
+'b:cvscmd' became 'b:VCSCommandCommand'
+
+10. Added new automatic variables to command result buffers.
+
+'b:VCSCommandSourceFile'
+'b:VCSCommandVCSType'
+
+==============================================================================
+
+8. Known bugs *vcscommand-bugs*
+
+Please let me know if you run across any.
+
+CVSUnedit may, if a file is changed from the repository, provide prompt text
+to determine whether the changes should be thrown away. Currently, that text
+shows up in the CVS result buffer as information; there is no way for the user
+to actually respond to the prompt and the CVS unedit command does nothing. If
+this really bothers anyone, please let me know.
+
+VCSVimDiff, when using the original (real) source buffer as one of the diff
+buffers, uses some hacks to try to restore the state of the original buffer
+when the scratch buffer containing the other version is destroyed. There may
+still be bugs in here, depending on many configuration details.
+
+vim:tw=78:ts=8:ft=help
diff --git a/modules/vim/vim/filetype.vim b/modules/vim/vim/filetype.vim
new file mode 100644
index 0000000..2b958bc
--- /dev/null
+++ b/modules/vim/vim/filetype.vim
@@ -0,0 +1,23 @@
+" Vim support file to detect file types
+
+if exists("did_load_filetypes")
+ finish
+endif
+
+" markdown filetype file
+
+augroup markdown
+ au! BufRead,BufNewFile *.mkd setfiletype mkd
+augroup END
+
+" detect puppet filetypes
+
+augroup filetypedetect
+ au! BufRead,BufNewFile *.pp setfiletype puppet
+augroup END
+
+" detect drupal modules
+
+augroup filetypedetect
+ au! BufRead,BufNewFile *.module setfiletype php
+augroup END
diff --git a/modules/vim/vim/ftplugin/html_snip_helper.vim b/modules/vim/vim/ftplugin/html_snip_helper.vim
new file mode 100644
index 0000000..2e54570
--- /dev/null
+++ b/modules/vim/vim/ftplugin/html_snip_helper.vim
@@ -0,0 +1,10 @@
+" Helper function for (x)html snippets
+if exists('s:did_snip_helper') || &cp || !exists('loaded_snips')
+ finish
+endif
+let s:did_snip_helper = 1
+
+" Automatically closes tag if in xhtml
+fun! Close()
+ return stridx(&ft, 'xhtml') == -1 ? '' : ' /'
+endf
diff --git a/modules/vim/vim/plugin/Rename.vim b/modules/vim/vim/plugin/Rename.vim
new file mode 100644
index 0000000..b56c516
--- /dev/null
+++ b/modules/vim/vim/plugin/Rename.vim
@@ -0,0 +1,27 @@
+" Rename.vim - Rename a buffer within Vim and on the disk
+"
+" Copyright June 2007 by Christian J. Robinson <infynity@onewest.net>
+"
+" Distributed under the terms of the Vim license. See ":help license".
+"
+" Usage:
+"
+" :Rename[!] {newname}
+
+command! -nargs=* -complete=file -bang Rename :call Rename("<args>", "<bang>")
+
+function! Rename(name, bang)
+ let l:curfile = expand("%:p")
+ let v:errmsg = ""
+ silent! exe "saveas" . a:bang . " " . a:name
+ if v:errmsg =~# '^$\|^E329'
+ if expand("%:p") !=# l:curfile && filewritable(expand("%:p"))
+ silent exe "bwipe! " . l:curfile
+ if delete(l:curfile)
+ echoerr "Could not delete " . l:curfile
+ endif
+ endif
+ else
+ echoerr v:errmsg
+ endif
+endfunction
diff --git a/modules/vim/vim/plugin/bufexplorer.vim b/modules/vim/vim/plugin/bufexplorer.vim
new file mode 100644
index 0000000..fb7aea9
--- /dev/null
+++ b/modules/vim/vim/plugin/bufexplorer.vim
@@ -0,0 +1,869 @@
+"=============================================================================
+" Copyright: Copyright (C) 2001-2008 Jeff Lanzarotta
+" Permission is hereby granted to use and distribute this code,
+" with or without modifications, provided that this copyright
+" notice is copied with it. Like anything else that's free,
+" bufexplorer.vim is provided *as is* and comes with no
+" warranty of any kind, either expressed or implied. In no
+" event will the copyright holder be liable for any damages
+" resulting from the use of this software.
+" Name Of File: bufexplorer.vim
+" Description: Buffer Explorer Vim Plugin
+" Maintainer: Jeff Lanzarotta (delux256-vim at yahoo dot com)
+" Last Changed: Wednesday, 19 Nov 2008
+" Version: See g:bufexplorer_version for version number.
+" Usage: This file should reside in the plugin directory and be
+" automatically sourced.
+"
+" You may use the default keymappings of
+"
+" <Leader>be - Opens BufExplorer
+" <Leader>bs - Opens horizontally split window BufExplorer
+" <Leader>bv - Opens vertically split window BufExplorer
+"
+" Or you can use
+"
+" ":BufExplorer" - Opens BufExplorer
+" ":HSBufExplorer" - Opens horizontally window BufExplorer
+" ":VSBufExplorer" - Opens vertically split window BufExplorer
+"
+" For more help see supplied documentation.
+" History: See supplied documentation.
+"=============================================================================
+
+" Exit quickly if already running or when 'compatible' is set. {{{1
+if exists("g:bufexplorer_version") || &cp
+ finish
+endif
+"1}}}
+
+" Version number
+let g:bufexplorer_version = "7.2.2"
+
+" Check for Vim version 700 or greater {{{1
+if v:version < 700
+ echo "Sorry, bufexplorer ".g:bufexplorer_version."\nONLY runs with Vim 7.0 and greater."
+ finish
+endif
+
+" Public Interface {{{1
+nmap <silent> <unique> <Leader>be :BufExplorer<CR>
+nmap <silent> <unique> <Leader>bs :HSBufExplorer<CR>
+nmap <silent> <unique> <Leader>bv :VSBufExplorer<CR>
+
+" Create commands {{{1
+command BufExplorer :call StartBufExplorer(has ("gui") ? "drop" : "hide edit")
+command HSBufExplorer :call HorizontalSplitBufExplorer()
+command VSBufExplorer :call VerticalSplitBufExplorer()
+
+" Set {{{1
+function s:Set(var, default)
+ if !exists(a:var)
+ if type(a:default)
+ exec "let" a:var "=" string(a:default)
+ else
+ exec "let" a:var "=" a:default
+ endif
+
+ return 1
+ endif
+
+ return 0
+endfunction
+
+" Default values {{{1
+call s:Set("g:bufExplorerDefaultHelp", 1) " Show default help?
+call s:Set("g:bufExplorerDetailedHelp", 0) " Show detailed help?
+call s:Set("g:bufExplorerFindActive", 1) " When selecting an active buffer, take you to the window where it is active?
+call s:Set("g:bufExplorerReverseSort", 0) " sort reverse?
+call s:Set("g:bufExplorerShowDirectories", 1) " (Dir's are added by commands like ':e .')
+call s:Set("g:bufExplorerShowRelativePath", 0) " Show listings with relative or absolute paths?
+call s:Set("g:bufExplorerShowUnlisted", 0) " Show unlisted buffers?
+call s:Set("g:bufExplorerSortBy", "mru") " Sorting methods are in s:sort_by:
+call s:Set("g:bufExplorerSplitOutPathName", 1) " Split out path and file name?
+call s:Set("g:bufExplorerSplitRight", &splitright) " Should vertical splits be on the right or left of current window?
+call s:Set("g:bufExplorerSplitBelow", &splitbelow) " Should horizontal splits be below or above current window?
+
+" Global variables {{{1
+let s:MRUList = []
+let s:running = 0
+let s:sort_by = ["number", "name", "fullpath", "mru", "extension"]
+let s:tabSpace = []
+let s:types = {"fullname": ':p', "path": ':p:h', "relativename": ':~:.', "relativepath": ':~:.:h', "shortname": ':t'}
+let s:originBuffer = 0
+let s:splitMode = ""
+
+" Setup the autocommands that handle the MRUList and other stuff. {{{1
+autocmd VimEnter * call s:Setup()
+
+" Setup {{{1
+function s:Setup()
+ " Build initial MRUList.
+ let s:MRUList = range(1, bufnr('$'))
+ let s:tabSpace = []
+ " Now that the MRUList is created, add the other autocmds.
+ autocmd BufEnter,BufNew * call s:ActivateBuffer()
+ autocmd BufWipeOut * call s:DeactivateBuffer(1)
+ autocmd BufDelete * call s:DeactivateBuffer(0)
+
+ autocmd BufWinEnter \[BufExplorer\] call s:Initialize()
+ autocmd BufWinLeave \[BufExplorer\] call s:Cleanup()
+endfunction
+
+" ActivateBuffer {{{1
+function s:ActivateBuffer()
+ let b = bufnr("%")
+ let l = get(s:tabSpace, tabpagenr(), [])
+
+ if empty(l) || index(l, b) == -1
+ call add(l, b)
+ let s:tabSpace[tabpagenr()] = l
+ endif
+
+ call s:MRUPush(b)
+endfunction
+
+" DeactivateBuffer {{{1
+function s:DeactivateBuffer(remove)
+ "echom "afile:" expand("<afile>")
+ "echom "bufnr, afile:" bufnr(expand("<afile>"))
+ "echom "buffers:" string(tabpagebuflist())
+ "echom "MRU before:" string(s:MRUList)
+
+ let _bufnr = bufnr(expand("<afile>"))
+ let _buftype = getbufvar(_bufnr, "&buftype")
+
+ if empty(_buftype) || _buftype == "nofile" || !buflisted(_bufnr) || empty(bufname(_bufnr)) || fnamemodify(bufname(_bufnr), ":t") == "[BufExplorer]"
+ return
+ end
+
+ if a:remove
+ call s:MRUPop(bufnr(expand("<afile>")))
+ end
+endfunction
+
+" MRUPop {{{1
+function s:MRUPop(buf)
+ call filter(s:MRUList, 'v:val != '.a:buf)
+endfunction
+
+" MRUPush {{{1
+function s:MRUPush(buf)
+ " Skip temporary buffer with buftype set. Don't add the BufExplorer window to the
+ " list.
+ if !empty(getbufvar(a:buf, "&buftype")) ||
+ \ !buflisted(a:buf) || empty(bufname(a:buf)) ||
+ \ fnamemodify(bufname(a:buf), ":t") == "[BufExplorer]"
+ return
+ end
+ " Remove the buffer number from the list if it already exists.
+ call s:MRUPop(a:buf)
+ " Add the buffer number to the head of the list.
+ call insert(s:MRUList,a:buf)
+endfunction
+
+" Initialize {{{1
+function s:Initialize()
+ let s:_insertmode = &insertmode
+ set noinsertmode
+
+ let s:_showcmd = &showcmd
+ set noshowcmd
+
+ let s:_cpo = &cpo
+ set cpo&vim
+
+ let s:_report = &report
+ let &report = 10000
+
+ let s:_list = &list
+ set nolist
+
+ setlocal nonumber
+ setlocal foldcolumn=0
+ setlocal nofoldenable
+ setlocal cursorline
+ setlocal nospell
+
+ set nobuflisted
+
+ let s:running = 1
+endfunction
+
+" Cleanup {{{1
+function s:Cleanup()
+ let &insertmode = s:_insertmode
+ let &showcmd = s:_showcmd
+ let &cpo = s:_cpo
+ let &report = s:_report
+ let &list = s:_list
+ let s:running = 0
+ let s:splitMode = ""
+
+ delmarks!
+endfunction
+
+" HorizontalSplitBufExplorer {{{1
+function HorizontalSplitBufExplorer()
+ let s:splitMode = "sp"
+ exec "BufExplorer"
+endfunction
+
+" VerticalSplitBufExplorer {{{1
+function VerticalSplitBufExplorer()
+ let s:splitMode = "vsp"
+ exec "BufExplorer"
+endfunction
+
+" StartBufExplorer {{{1
+function StartBufExplorer(open)
+ let name = '[BufExplorer]'
+
+ if !has("win32")
+ " On non-Windows boxes, escape the name so that is shows up correctly.
+ let name = escape(name, "[]")
+ endif
+ " Make sure there is only one explorer open at a time.
+ if s:running == 1
+ " Go to the open buffer.
+ if has("gui")
+ exec "drop" name
+ endif
+
+ return
+ endif
+
+ let s:originBuffer = bufnr("%")
+ silent let s:raw_buffer_listing = s:GetBufferInfo()
+
+ let copy = copy(s:raw_buffer_listing)
+
+ if (g:bufExplorerShowUnlisted == 0)
+ call filter(copy, 'v:val.attributes !~ "u"')
+ endif
+
+ if (!empty(copy))
+ call filter(copy, 'v:val.shortname !~ "\\\[No Name\\\]"')
+ endif
+
+ if len(copy) <= 1
+ echo "\r"
+ call s:Warning("Sorry, there are no more buffers to explore")
+
+ return
+ endif
+ " We may have to split the current window.
+ if (s:splitMode != "")
+ " Save off the original settings.
+ let [_splitbelow, _splitright] = [&splitbelow, &splitright]
+ " Set the setting to ours.
+ let [&splitbelow, &splitright] = [g:bufExplorerSplitBelow, g:bufExplorerSplitRight]
+ " Do it.
+ exe s:splitMode
+ " Restore the original settings.
+ let [&splitbelow, &splitright] = [_splitbelow, _splitright]
+ endif
+
+ if !exists("b:displayMode") || b:displayMode != "winmanager"
+ " Do not use keepalt when opening bufexplorer to allow the buffer that we are
+ " leaving to become the new alternate buffer
+ exec "silent keepjumps ".a:open." ".name
+ endif
+
+ call s:DisplayBufferList()
+endfunction
+
+" DisplayBufferList {{{1
+function s:DisplayBufferList()
+ setlocal bufhidden=delete
+ setlocal buftype=nofile
+ setlocal modifiable
+ setlocal noswapfile
+ setlocal nowrap
+
+ call s:SetupSyntax()
+ call s:MapKeys()
+ call setline(1, s:CreateHelp())
+ call s:BuildBufferList()
+ call cursor(s:firstBufferLine, 1)
+
+ if !g:bufExplorerResize
+ normal! zz
+ endif
+
+ setlocal nomodifiable
+endfunction
+
+" MapKeys {{{1
+function s:MapKeys()
+ if exists("b:displayMode") && b:displayMode == "winmanager"
+ nnoremap <buffer> <silent> <tab> :call <SID>SelectBuffer("tab")<cr>
+ endif
+
+ nnoremap <buffer> <silent> <F1> :call <SID>ToggleHelp()<cr>
+ nnoremap <buffer> <silent> <2-leftmouse> :call <SID>SelectBuffer()<cr>
+ nnoremap <buffer> <silent> <cr> :call <SID>SelectBuffer()<cr>
+ nnoremap <buffer> <silent> t :call <SID>SelectBuffer("tab")<cr>
+ nnoremap <buffer> <silent> <s-cr> :call <SID>SelectBuffer("tab")<cr>
+ nnoremap <buffer> <silent> d :call <SID>RemoveBuffer("wipe")<cr>
+ nnoremap <buffer> <silent> D :call <SID>RemoveBuffer("delete")<cr>
+ nnoremap <buffer> <silent> m :call <SID>MRUListShow()<cr>
+ nnoremap <buffer> <silent> p :call <SID>ToggleSplitOutPathName()<cr>
+ nnoremap <buffer> <silent> q :call <SID>Close()<cr>
+ nnoremap <buffer> <silent> r :call <SID>SortReverse()<cr>
+ nnoremap <buffer> <silent> R :call <SID>ToggleShowRelativePath()<cr>
+ nnoremap <buffer> <silent> s :call <SID>SortSelect()<cr>
+ nnoremap <buffer> <silent> u :call <SID>ToggleShowUnlisted()<cr>
+ nnoremap <buffer> <silent> f :call <SID>ToggleFindActive()<cr>
+
+ for k in ["G", "n", "N", "L", "M", "H"]
+ exec "nnoremap <buffer> <silent>" k ":keepjumps normal!" k."<cr>"
+ endfor
+endfunction
+
+" SetupSyntax {{{1
+function s:SetupSyntax()
+ if has("syntax")
+ syn match bufExplorerHelp "^\".*" contains=bufExplorerSortBy,bufExplorerMapping,bufExplorerTitle,bufExplorerSortType,bufExplorerToggleSplit,bufExplorerToggleOpen
+ syn match bufExplorerOpenIn "Open in \w\+ window" contained
+ syn match bufExplorerSplit "\w\+ split" contained
+ syn match bufExplorerSortBy "Sorted by .*" contained contains=bufExplorerOpenIn,bufExplorerSplit
+ syn match bufExplorerMapping "\" \zs.\+\ze :" contained
+ syn match bufExplorerTitle "Buffer Explorer.*" contained
+ syn match bufExplorerSortType "'\w\{-}'" contained
+ syn match bufExplorerBufNbr /^\s*\d\+/
+ syn match bufExplorerToggleSplit "toggle split type" contained
+ syn match bufExplorerToggleOpen "toggle open mode" contained
+
+ syn match bufExplorerModBuf /^\s*\d\+.\{4}+.*/
+ syn match bufExplorerLockedBuf /^\s*\d\+.\{3}[\-=].*/
+ syn match bufExplorerHidBuf /^\s*\d\+.\{2}h.*/
+ syn match bufExplorerActBuf /^\s*\d\+.\{2}a.*/
+ syn match bufExplorerCurBuf /^\s*\d\+.%.*/
+ syn match bufExplorerAltBuf /^\s*\d\+.#.*/
+ syn match bufExplorerUnlBuf /^\s*\d\+u.*/
+
+ hi def link bufExplorerBufNbr Number
+ hi def link bufExplorerMapping NonText
+ hi def link bufExplorerHelp Special
+ hi def link bufExplorerOpenIn Identifier
+ hi def link bufExplorerSortBy String
+ hi def link bufExplorerSplit NonText
+ hi def link bufExplorerTitle NonText
+ hi def link bufExplorerSortType bufExplorerSortBy
+ hi def link bufExplorerToggleSplit bufExplorerSplit
+ hi def link bufExplorerToggleOpen bufExplorerOpenIn
+
+ hi def link bufExplorerActBuf Identifier
+ hi def link bufExplorerAltBuf String
+ hi def link bufExplorerCurBuf Type
+ hi def link bufExplorerHidBuf Constant
+ hi def link bufExplorerLockedBuf Special
+ hi def link bufExplorerModBuf Exception
+ hi def link bufExplorerUnlBuf Comment
+ endif
+endfunction
+
+" ToggleHelp {{{1
+function s:ToggleHelp()
+ let g:bufExplorerDetailedHelp = !g:bufExplorerDetailedHelp
+
+ setlocal modifiable
+ " Save position.
+ normal! ma
+ " Remove old header.
+ if (s:firstBufferLine > 1)
+ exec "keepjumps 1,".(s:firstBufferLine - 1) "d _"
+ endif
+
+ call append(0, s:CreateHelp())
+
+ silent! normal! g`a
+ delmarks a
+
+ setlocal nomodifiable
+
+ if exists("b:displayMode") && b:displayMode == "winmanager"
+ call WinManagerForceReSize("BufExplorer")
+ end
+endfunction
+
+" GetHelpStatus {{{1
+function s:GetHelpStatus()
+ let ret = '" Sorted by '.((g:bufExplorerReverseSort == 1) ? "reverse " : "").g:bufExplorerSortBy
+ let ret .= ' | '.((g:bufExplorerFindActive == 0) ? "Don't " : "")."Locate buffer"
+ let ret .= ((g:bufExplorerShowUnlisted == 0) ? "" : " | Show unlisted")
+ let ret .= ' | '.((g:bufExplorerShowRelativePath == 0) ? "Absolute" : "Relative")
+ let ret .= ' '.((g:bufExplorerSplitOutPathName == 0) ? "Full" : "Split")." path"
+
+ return ret
+endfunction
+
+" CreateHelp {{{1
+function s:CreateHelp()
+ if g:bufExplorerDefaultHelp == 0 && g:bufExplorerDetailedHelp == 0
+ let s:firstBufferLine = 1
+ return []
+ endif
+
+ let header = []
+
+ if g:bufExplorerDetailedHelp == 1
+ call add(header, '" Buffer Explorer ('.g:bufexplorer_version.')')
+ call add(header, '" --------------------------')
+ call add(header, '" <F1> : toggle this help')
+ call add(header, '" <enter> or Mouse-Double-Click : open buffer under cursor')
+ call add(header, '" <shift-enter> or t : open buffer in another tab')
+ call add(header, '" d : wipe buffer')
+ call add(header, '" D : delete buffer')
+ call add(header, '" p : toggle spliting of file and path name')
+ call add(header, '" q : quit')
+ call add(header, '" r : reverse sort')
+ call add(header, '" R : toggle showing relative or full paths')
+ call add(header, '" u : toggle showing unlisted buffers')
+ call add(header, '" s : select sort field '.string(s:sort_by).'')
+ call add(header, '" f : toggle find active buffer')
+ else
+ call add(header, '" Press <F1> for Help')
+ endif
+
+ call add(header, s:GetHelpStatus())
+ call add(header, '"=')
+
+ let s:firstBufferLine = len(header) + 1
+
+ return header
+endfunction
+
+" GetBufferInfo {{{1
+function s:GetBufferInfo()
+ redir => bufoutput
+ buffers!
+ redir END
+
+ let [all, allwidths, listedwidths] = [[], {}, {}]
+
+ for n in keys(s:types)
+ let allwidths[n] = []
+ let listedwidths[n] = []
+ endfor
+
+ for buf in split(bufoutput, '\n')
+ let bits = split(buf, '"')
+ let b = {"attributes": bits[0], "line": substitute(bits[2], '\s*', '', '')}
+
+ for [key, val] in items(s:types)
+ let b[key] = fnamemodify(bits[1], val)
+ endfor
+
+ if getftype(b.fullname) == "dir" && g:bufExplorerShowDirectories == 1
+ let b.shortname = "<DIRECTORY>"
+ end
+
+ call add(all, b)
+
+ for n in keys(s:types)
+ call add(allwidths[n], len(b[n]))
+
+ if b.attributes !~ "u"
+ call add(listedwidths[n], len(b[n]))
+ endif
+ endfor
+ endfor
+
+ let [s:allpads, s:listedpads] = [{}, {}]
+
+ for n in keys(s:types)
+ let s:allpads[n] = repeat(' ', max(allwidths[n]))
+ let s:listedpads[n] = repeat(' ', max(listedwidths[n]))
+ endfor
+
+ return all
+endfunction
+
+" BuildBufferList {{{1
+function s:BuildBufferList()
+ let lines = []
+ " Loop through every buffer.
+ for buf in s:raw_buffer_listing
+ if (!g:bufExplorerShowUnlisted && buf.attributes =~ "u")
+ " Skip unlisted buffers if we are not to show them.
+ continue
+ endif
+
+ let line = buf.attributes." "
+
+ if g:bufExplorerSplitOutPathName
+ let type = (g:bufExplorerShowRelativePath) ? "relativepath" : "path"
+ let path = buf[type]
+ let pad = (g:bufExplorerShowUnlisted) ? s:allpads.shortname : s:listedpads.shortname
+ let line .= buf.shortname." ".strpart(pad.path, len(buf.shortname))
+ else
+ let type = (g:bufExplorerShowRelativePath) ? "relativename" : "fullname"
+ let path = buf[type]
+ let line .= path
+ endif
+
+ let pads = (g:bufExplorerShowUnlisted) ? s:allpads : s:listedpads
+
+ if !empty(pads[type])
+ let line .= strpart(pads[type], len(path))." "
+ endif
+
+ let line .= buf.line
+
+ call add(lines, line)
+ endfor
+
+ call setline(s:firstBufferLine, lines)
+
+ call s:SortListing()
+endfunction
+
+" SelectBuffer {{{1
+function s:SelectBuffer(...)
+ " Sometimes messages are not cleared when we get here so it looks like an error has
+ " occurred when it really has not.
+ echo ""
+ " Are we on a line with a file name?
+ if line('.') < s:firstBufferLine
+ exec "normal! \<cr>"
+ return
+ endif
+
+ let _bufNbr = str2nr(getline('.'))
+
+ if exists("b:displayMode") && b:displayMode == "winmanager"
+ let bufname = expand("#"._bufNbr.":p")
+
+ if (a:0 == 1) && (a:1 == "tab")
+ call WinManagerFileEdit(bufname, 1)
+ else
+ call WinManagerFileEdit(bufname, 0)
+ endif
+
+ return
+ end
+
+ if bufexists(_bufNbr)
+ if bufnr("#") == _bufNbr
+ return s:Close()
+ endif
+
+ if (a:0 == 1) && (a:1 == "tab")
+ " Restore [BufExplorer] buffer.
+ exec "keepjumps silent buffer!".s:originBuffer
+
+ let tabNbr = s:GetTabNbr(_bufNbr)
+
+ if tabNbr == 0
+ " _bufNbr is not opened in any tabs. Open a new tab with the selected buffer in it.
+ exec "999tab split +buffer" . _bufNbr
+ else
+ " The _bufNbr is already opened in tab(s), go to that tab.
+ exec tabNbr . "tabnext"
+ " Focus window.
+ exec s:GetWinNbr(tabNbr, _bufNbr) . "wincmd w"
+ endif
+ else
+ if bufloaded(_bufNbr) && g:bufExplorerFindActive
+ call s:Close()
+
+ let tabNbr = s:GetTabNbr(_bufNbr)
+
+ if tabNbr != 0
+ " The buffer is located in a tab. Go to that tab number.
+ exec tabNbr . "tabnext"
+ else
+ let bufname = expand("#"._bufNbr.":p")
+ exec bufname ? "drop ".escape(bufname, " ") : "buffer "._bufNbr
+ endif
+ endif
+ " Switch to the buffer.
+ exec "keepalt keepjumps silent b!" _bufNbr
+ endif
+ " Make the buffer 'listed' again.
+ call setbufvar(_bufNbr, "&buflisted", "1")
+ else
+ call s:Error("Sorry, that buffer no longer exists, please select another")
+ call s:DeleteBuffer(_bufNbr, "wipe")
+ endif
+endfunction
+
+" RemoveBuffer {{{1
+function s:RemoveBuffer(mode)
+ " Are we on a line with a file name?
+ if line('.') < s:firstBufferLine
+ return
+ endif
+ " Do not allow this buffer to be deleted if it is the last one.
+ if len(s:MRUList) == 1
+ call s:Error("Sorry, you are not allowed to delete the last buffer")
+ return
+ endif
+ " These commands are to temporarily suspend the activity of winmanager.
+ if exists("b:displayMode") && b:displayMode == "winmanager"
+ call WinManagerSuspendAUs()
+ end
+
+ let _bufNbr = str2nr(getline('.'))
+
+ if getbufvar(_bufNbr, '&modified') == 1
+ call s:Error("Sorry, no write since last change for buffer "._bufNbr.", unable to delete")
+ return
+ else
+ " Okay, everything is good, delete or wipe the buffer.
+ call s:DeleteBuffer(_bufNbr, a:mode)
+ endif
+ " Reactivate winmanager autocommand activity.
+ if exists("b:displayMode") && b:displayMode == "winmanager"
+ call WinManagerForceReSize("BufExplorer")
+ call WinManagerResumeAUs()
+ end
+endfunction
+
+" DeleteBuffer {{{1
+function s:DeleteBuffer(buf, mode)
+ " This routine assumes that the buffer to be removed is on the current line.
+ try
+ if a:mode == "wipe"
+ exe "silent bw" a:buf
+ else
+ exe "silent bd" a:buf
+ end
+
+ setlocal modifiable
+ normal! "_dd
+ setlocal nomodifiable
+ " Delete the buffer from the raw buffer list.
+ call filter(s:raw_buffer_listing, 'v:val.attributes !~ " '.a:buf.' "')
+ catch
+ call s:Error(v:exception)
+ endtry
+endfunction
+
+" Close {{{1
+function s:Close()
+ " Get only the listed buffers.
+ let listed = filter(copy(s:MRUList), "buflisted(v:val)")
+ " If we needed to split the main window, close the split one.
+ if (s:splitMode != "")
+ exec "wincmd c"
+ end
+
+ for b in reverse(listed[0:1])
+ exec "keepjumps silent b ".b
+ endfor
+endfunction
+
+" ToggleSplitOutPathName {{{1
+function s:ToggleSplitOutPathName()
+ let g:bufExplorerSplitOutPathName = !g:bufExplorerSplitOutPathName
+ call s:RebuildBufferList()
+ call s:UpdateHelpStatus()
+endfunction
+
+" ToggleShowRelativePath {{{1
+function s:ToggleShowRelativePath()
+ let g:bufExplorerShowRelativePath = !g:bufExplorerShowRelativePath
+ call s:RebuildBufferList()
+ call s:UpdateHelpStatus()
+endfunction
+
+" ToggleShowUnlisted {{{1
+function s:ToggleShowUnlisted()
+ let g:bufExplorerShowUnlisted = !g:bufExplorerShowUnlisted
+ let num_bufs = s:RebuildBufferList(g:bufExplorerShowUnlisted == 0)
+ call s:UpdateHelpStatus()
+endfunction
+
+" ToggleFindActive {{{1
+function s:ToggleFindActive()
+ let g:bufExplorerFindActive = !g:bufExplorerFindActive
+ call s:UpdateHelpStatus()
+endfunction
+
+" RebuildBufferList {{{1
+function s:RebuildBufferList(...)
+ setlocal modifiable
+
+ let curPos = getpos('.')
+
+ if a:0
+ " Clear the list first.
+ exec "keepjumps ".s:firstBufferLine.',$d "_'
+ endif
+
+ let num_bufs = s:BuildBufferList()
+
+ call setpos('.', curPos)
+
+ setlocal nomodifiable
+
+ return num_bufs
+endfunction
+
+" UpdateHelpStatus {{{1
+function s:UpdateHelpStatus()
+ setlocal modifiable
+
+ let text = s:GetHelpStatus()
+ call setline(s:firstBufferLine - 2, text)
+
+ setlocal nomodifiable
+endfunction
+
+" MRUCmp {{{1
+function s:MRUCmp(line1, line2)
+ return index(s:MRUList, str2nr(a:line1)) - index(s:MRUList, str2nr(a:line2))
+endfunction
+
+" SortReverse {{{1
+function s:SortReverse()
+ let g:bufExplorerReverseSort = !g:bufExplorerReverseSort
+
+ call s:ReSortListing()
+endfunction
+
+" SortSelect {{{1
+function s:SortSelect()
+ let g:bufExplorerSortBy = get(s:sort_by, index(s:sort_by, g:bufExplorerSortBy) + 1, s:sort_by[0])
+
+ call s:ReSortListing()
+endfunction
+
+" ReSortListing {{{1
+function s:ReSortListing()
+ setlocal modifiable
+
+ let curPos = getpos('.')
+
+ call s:SortListing()
+ call s:UpdateHelpStatus()
+
+ call setpos('.', curPos)
+
+ setlocal nomodifiable
+endfunction
+
+" SortListing {{{1
+function s:SortListing()
+ let sort = s:firstBufferLine.",$sort".((g:bufExplorerReverseSort == 1) ? "!": "")
+
+ if g:bufExplorerSortBy == "number"
+ " Easiest case.
+ exec sort 'n'
+ elseif g:bufExplorerSortBy == "name"
+ if g:bufExplorerSplitOutPathName
+ exec sort 'ir /\d.\{7}\zs\f\+\ze/'
+ else
+ exec sort 'ir /\zs[^\/\\]\+\ze\s*line/'
+ endif
+ elseif g:bufExplorerSortBy == "fullpath"
+ if g:bufExplorerSplitOutPathName
+ " Sort twice - first on the file name then on the path.
+ exec sort 'ir /\d.\{7}\zs\f\+\ze/'
+ endif
+
+ exec sort 'ir /\zs\f\+\ze\s\+line/'
+ elseif g:bufExplorerSortBy == "extension"
+ exec sort 'ir /\.\zs\w\+\ze\s/'
+ elseif g:bufExplorerSortBy == "mru"
+ let l = getline(s:firstBufferLine, "$")
+
+ call sort(l, "<SID>MRUCmp")
+
+ if g:bufExplorerReverseSort
+ call reverse(l)
+ endif
+
+ call setline(s:firstBufferLine, l)
+ endif
+endfunction
+
+" MRUListShow {{{1
+function s:MRUListShow()
+ echomsg "MRUList=".string(s:MRUList)
+endfunction
+
+" Error {{{1
+function s:Error(msg)
+ echohl ErrorMsg | echo a:msg | echohl none
+endfunction
+
+" Warning {{{1
+function s:Warning(msg)
+ echohl WarningMsg | echo a:msg | echohl none
+endfunction
+
+" GetTabNbr {{{1
+function s:GetTabNbr(bufNbr)
+ " Searching buffer bufno, in tabs.
+ for i in range(tabpagenr("$"))
+ if index(tabpagebuflist(i + 1), a:bufNbr) != -1
+ return i + 1
+ endif
+ endfor
+
+ return 0
+endfunction
+
+" GetWinNbr" {{{1
+function s:GetWinNbr(tabNbr, bufNbr)
+ " window number in tabpage.
+ return index(tabpagebuflist(a:tabNbr), a:bufNbr) + 1
+endfunction
+
+" Winmanager Integration {{{1
+let g:BufExplorer_title = "\[Buf\ List\]"
+call s:Set("g:bufExplorerResize", 1)
+call s:Set("g:bufExplorerMaxHeight", 25) " Handles dynamic resizing of the window.
+
+" Function to start display. Set the mode to 'winmanager' for this buffer.
+" This is to figure out how this plugin was called. In a standalone fashion
+" or by winmanager.
+function BufExplorer_Start()
+ let b:displayMode = "winmanager"
+ call StartBufExplorer("e")
+endfunction
+
+" Returns whether the display is okay or not.
+function BufExplorer_IsValid()
+ return 0
+endfunction
+
+" Handles dynamic refreshing of the window.
+function BufExplorer_Refresh()
+ let b:displayMode = "winmanager"
+ call StartBufExplorer("e")
+endfunction
+
+function BufExplorer_ReSize()
+ if !g:bufExplorerResize
+ return
+ end
+
+ let nlines = min([line("$"), g:bufExplorerMaxHeight])
+
+ exe nlines." wincmd _"
+
+ " The following lines restore the layout so that the last file line is also
+ " the last window line. Sometimes, when a line is deleted, although the
+ " window size is exactly equal to the number of lines in the file, some of
+ " the lines are pushed up and we see some lagging '~'s.
+ let pres = getpos(".")
+
+ exe $
+
+ let _scr = &scrolloff
+ let &scrolloff = 0
+
+ normal! z-
+
+ let &scrolloff = _scr
+
+ call setpos(".", pres)
+endfunction
+"1}}}
+
+" vim:ft=vim foldmethod=marker sw=2
diff --git a/modules/vim/vim/plugin/git.vim b/modules/vim/vim/plugin/git.vim
new file mode 100644
index 0000000..bd0b053
--- /dev/null
+++ b/modules/vim/vim/plugin/git.vim
@@ -0,0 +1,372 @@
+" Author: motemen <motemen@gmail.com>
+" License: The MIT License
+" URL: http://github.com/motemen/git-vim/
+
+if !exists('g:git_command_edit')
+ let g:git_command_edit = 'new'
+endif
+
+if !exists('g:git_bufhidden')
+ let g:git_bufhidden = ''
+endif
+
+if !exists('g:git_bin')
+ let g:git_bin = 'git'
+endif
+
+if !exists('g:git_author_highlight')
+ let g:git_author_highlight = { }
+endif
+
+if !exists('g:git_highlight_blame')
+ let g:git_highlight_blame = 0
+endif
+
+if !exists('g:git_no_map_default') || !g:git_no_map_default
+ nnoremap <Leader>gd :GitDiff<Enter>
+ nnoremap <Leader>gD :GitDiff --cached<Enter>
+ nnoremap <Leader>gs :GitStatus<Enter>
+ nnoremap <Leader>gl :GitLog<Enter>
+ nnoremap <Leader>ga :GitAdd<Enter>
+ nnoremap <Leader>gA :GitAdd <cfile><Enter>
+ nnoremap <Leader>gc :GitCommit<Enter>
+ nnoremap <Leader>gp :GitPullRebase<Enter>
+endif
+
+" Ensure b:git_dir exists.
+function! s:GetGitDir()
+ if !exists('b:git_dir')
+ let b:git_dir = s:SystemGit('rev-parse --git-dir')
+ if !v:shell_error
+ let b:git_dir = fnamemodify(split(b:git_dir, "\n")[0], ':p') . '/'
+ endif
+ endif
+ return b:git_dir
+endfunction
+
+" Returns current git branch.
+" Call inside 'statusline' or 'titlestring'.
+function! GitBranch()
+ let git_dir = <SID>GetGitDir()
+
+ if strlen(git_dir) && filereadable(git_dir . '/HEAD')
+ let lines = readfile(git_dir . '/HEAD')
+ if !len(lines)
+ return ''
+ else
+ return matchstr(lines[0], 'refs/heads/\zs.\+$')
+ endif
+ else
+ return ''
+ endif
+endfunction
+
+" List all git local branches.
+function! ListGitBranches(arg_lead, cmd_line, cursor_pos)
+ let branches = split(s:SystemGit('branch'), '\n')
+ if v:shell_error
+ return []
+ endif
+
+ return map(branches, 'matchstr(v:val, ''^[* ] \zs.*'')')
+endfunction
+
+" List all git commits.
+function! ListGitCommits(arg_lead, cmd_line, cursor_pos)
+ let commits = split(s:SystemGit('log --pretty=format:%h'))
+ if v:shell_error
+ return []
+ endif
+
+ let commits = ['HEAD'] + ListGitBranches(a:arg_lead, a:cmd_line, a:cursor_pos) + commits
+
+ if a:cmd_line =~ '^GitDiff'
+ " GitDiff accepts <commit>..<commit>
+ if a:arg_lead =~ '\.\.'
+ let pre = matchstr(a:arg_lead, '.*\.\.\ze')
+ let commits = map(commits, 'pre . v:val')
+ endif
+ endif
+
+ return filter(commits, 'match(v:val, ''\v'' . a:arg_lead) == 0')
+endfunction
+
+" Show diff.
+function! GitDiff(args)
+ let git_output = s:SystemGit('diff ' . a:args . ' -- ' . s:Expand('%'))
+ if !strlen(git_output)
+ echo "No output from git command"
+ return
+ endif
+
+ call <SID>OpenGitBuffer(git_output)
+ setlocal filetype=git-diff
+endfunction
+
+" Show Status.
+function! GitStatus()
+ let git_output = s:SystemGit('status')
+ call <SID>OpenGitBuffer(git_output)
+ setlocal filetype=git-status
+ nnoremap <buffer> <Enter> :GitAdd <cfile><Enter>:call <SID>RefreshGitStatus()<Enter>
+ nnoremap <buffer> - :silent !git reset HEAD -- =expand('<cfile>')<Enter><Enter>:call <SID>RefreshGitStatus()<Enter>
+endfunction
+
+function! s:RefreshGitStatus()
+ let pos_save = getpos('.')
+ GitStatus
+ call setpos('.', pos_save)
+endfunction
+
+" Show Log.
+function! GitLog(args)
+ let git_output = s:SystemGit('log ' . a:args . ' -- ' . s:Expand('%'))
+ call <SID>OpenGitBuffer(git_output)
+ setlocal filetype=git-log
+endfunction
+
+" Add file to index.
+function! GitAdd(expr)
+ let file = s:Expand(strlen(a:expr) ? a:expr : '%')
+
+ call GitDoCommand('add ' . file)
+endfunction
+
+" Commit.
+function! GitCommit(args)
+ let git_dir = <SID>GetGitDir()
+
+ let args = a:args
+
+ if args !~ '\v\k@<!(-a|--all)>' && s:SystemGit('diff --cached --stat') =~ '^\(\s\|\n\)*$'
+ let args .= ' -a'
+ endif
+
+ " Create COMMIT_EDITMSG file
+ let editor_save = $EDITOR
+ let $EDITOR = ''
+ let git_output = s:SystemGit('commit ' . args)
+ let $EDITOR = editor_save
+
+ let cur_dir = getcwd()
+ execute printf('%s %sCOMMIT_EDITMSG', g:git_command_edit, git_dir)
+ execute printf("lcd %s", cur_dir)
+
+ setlocal filetype=git-status bufhidden=wipe
+ augroup GitCommit
+ autocmd BufWritePre <buffer> g/^#\|^\s*$/d | setlocal fileencoding=utf-8
+ execute printf("autocmd BufEnter <buffer> lcd %s", cur_dir)
+ execute printf("autocmd BufWritePost <buffer> call GitDoCommand('commit %s -F ' . expand('%%')) | autocmd! GitCommit * <buffer>", args)
+ augroup END
+endfunction
+
+" Checkout.
+function! GitCheckout(args)
+ call GitDoCommand('checkout ' . a:args)
+endfunction
+
+" Push.
+function! GitPush(args)
+" call GitDoCommand('push ' . a:args)
+ " Wanna see progress...
+ let args = a:args
+ if args =~ '^\s*$'
+ let args = 'origin ' . GitBranch()
+ endif
+ execute '!' g:git_bin 'push' args
+endfunction
+
+" Pull.
+function! GitPull(args)
+" call GitDoCommand('pull ' . a:args)
+ " Wanna see progress...
+ execute '!' g:git_bin 'pull' a:args
+endfunction
+
+" Show commit, tree, blobs.
+function! GitCatFile(file)
+ let file = s:Expand(a:file)
+ let git_output = s:SystemGit('cat-file -p ' . file)
+ if !strlen(git_output)
+ echo "No output from git command"
+ return
+ endif
+
+ call <SID>OpenGitBuffer(git_output)
+endfunction
+
+" Show revision and author for each line.
+function! GitBlame(...)
+ let l:git_blame_width = 20
+ let git_output = s:SystemGit('blame -- ' . expand('%'))
+ if !strlen(git_output)
+ echo "No output from git command"
+ return
+ endif
+
+ if strlen(a:1)
+ let l:git_blame_width = a:1
+ endif
+
+ setlocal noscrollbind
+
+ " :/
+ let git_command_edit_save = g:git_command_edit
+ let g:git_command_edit = 'leftabove vnew'
+ call <SID>OpenGitBuffer(git_output)
+ let g:git_command_edit = git_command_edit_save
+
+ setlocal modifiable
+ silent %s/\d\d\d\d\zs \+\d\+).*//
+ exe 'vertical resize ' . git_blame_width
+ setlocal nomodifiable
+ setlocal nowrap scrollbind
+
+ if g:git_highlight_blame
+ call s:DoHighlightGitBlame()
+ endif
+
+ wincmd p
+ setlocal nowrap scrollbind
+
+ syncbind
+endfunction
+
+
+
+
+" Experimental
+function! s:DoHighlightGitBlame()
+ for l in range(1, line('$'))
+ let line = getline(l)
+ let [commit, author] = matchlist(line, '\(\x\+\) (\(.\{-}\)\s* \d\d\d\d-\d\d-\d\d')[1:2]
+ call s:LoadSyntaxRuleFor({ 'author': author })
+ endfor
+endfunction
+
+function! s:LoadSyntaxRuleFor(params)
+ let author = a:params.author
+ let name = 'gitBlameAuthor_' . substitute(author, '\s', '_', 'g')
+ if (!hlID(name))
+ if has_key(g:git_author_highlight, author)
+ execute 'highlight' name g:git_author_highlight[author]
+ else
+ let [n1, n2] = [0, 1]
+ for c in split(author, '\zs')
+ let n1 = (n1 + char2nr(c)) % 8
+ let n2 = (n2 + char2nr(c) * 3) % 8
+ endfor
+ if n1 == n2
+ let n1 = (n2 + 1) % 8
+ endif
+ execute 'highlight' name printf('ctermfg=%d ctermbg=%d', n1, n2)
+ endif
+ execute 'syntax match' name '"\V\^\x\+ (' . escape(author, '\') . '\.\*"'
+ endif
+endfunction
+
+function! GitDoCommand(args)
+ let git_output = s:SystemGit(a:args)
+ let git_output = substitute(git_output, '\n*$', '', '')
+ if v:shell_error
+ echohl Error
+ echo git_output
+ echohl None
+ else
+ echo git_output
+ endif
+endfunction
+
+function! s:SystemGit(args)
+ " workardound for MacVim, on which shell does not inherit environment
+ " variables
+ if has('mac') && &shell =~ 'sh$'
+ return system('EDITOR="" '. g:git_bin . ' ' . a:args)
+ else
+ return system(g:git_bin . ' ' . a:args)
+ endif
+endfunction
+
+" Show vimdiff for merge. (experimental)
+function! GitVimDiffMerge()
+ let file = s:Expand('%')
+ let filetype = &filetype
+ let t:git_vimdiff_original_bufnr = bufnr('%')
+ let t:git_vimdiff_buffers = []
+
+ topleft new
+ setlocal buftype=nofile
+ file `=':2:' . file`
+ call add(t:git_vimdiff_buffers, bufnr('%'))
+ execute 'silent read!git show :2:' . file
+ 0d
+ diffthis
+ let &filetype = filetype
+
+ rightbelow vnew
+ setlocal buftype=nofile
+ file `=':3:' . file`
+ call add(t:git_vimdiff_buffers, bufnr('%'))
+ execute 'silent read!git show :3:' . file
+ 0d
+ diffthis
+ let &filetype = filetype
+endfunction
+
+function! GitVimDiffMergeDone()
+ if exists('t:git_vimdiff_original_bufnr') && exists('t:git_vimdiff_buffers')
+ if getbufline(t:git_vimdiff_buffers[0], 1, '$') == getbufline(t:git_vimdiff_buffers[1], 1, '$')
+ execute 'sbuffer ' . t:git_vimdiff_original_bufnr
+ 0put=getbufline(t:git_vimdiff_buffers[0], 1, '$')
+ normal! jdG
+ update
+ execute 'bdelete ' . t:git_vimdiff_buffers[0]
+ execute 'bdelete ' . t:git_vimdiff_buffers[1]
+ close
+ else
+ echohl Error
+ echo 'There still remains conflict'
+ echohl None
+ endif
+ endif
+endfunction
+
+function! s:OpenGitBuffer(content)
+ if exists('b:is_git_msg_buffer') && b:is_git_msg_buffer
+ enew!
+ else
+ execute g:git_command_edit
+ endif
+
+ setlocal buftype=nofile readonly modifiable
+ execute 'setlocal bufhidden=' . g:git_bufhidden
+
+ silent put=a:content
+ keepjumps 0d
+ setlocal nomodifiable
+
+ let b:is_git_msg_buffer = 1
+endfunction
+
+function! s:Expand(expr)
+ if has('win32')
+ return substitute(expand(a:expr), '\', '/', 'g')
+ else
+ return expand(a:expr)
+ endif
+endfunction
+
+command! -nargs=1 -complete=customlist,ListGitCommits GitCheckout call GitCheckout(<q-args>)
+command! -nargs=* -complete=customlist,ListGitCommits GitDiff call GitDiff(<q-args>)
+command! GitStatus call GitStatus()
+command! -nargs=? GitAdd call GitAdd(<q-args>)
+command! -nargs=* GitLog call GitLog(<q-args>)
+command! -nargs=* GitCommit call GitCommit(<q-args>)
+command! -nargs=1 GitCatFile call GitCatFile(<q-args>)
+command! -nargs=? GitBlame call GitBlame(<q-args>)
+command! -nargs=+ Git call GitDoCommand(<q-args>)
+command! GitVimDiffMerge call GitVimDiffMerge()
+command! GitVimDiffMergeDone call GitVimDiffMergeDone()
+command! -nargs=* GitPull call GitPull(<q-args>)
+command! GitPullRebase call GitPull('--rebase')
+command! -nargs=* GitPush call GitPush(<q-args>)
diff --git a/modules/vim/vim/plugin/indexer.vim.disabled b/modules/vim/vim/plugin/indexer.vim.disabled
new file mode 100644
index 0000000..28c9472
--- /dev/null
+++ b/modules/vim/vim/plugin/indexer.vim.disabled
@@ -0,0 +1,672 @@
+"=============================================================================
+" File: indexer.vim
+" Author: Dmitry Frank (dimon.frank@gmail.com)
+" Last Change: 26 Sep 2010
+" Version: 1.8
+"=============================================================================
+" See documentation in accompanying help file
+" You may use this code in whatever way you see fit.
+
+
+" s:ParsePath(sPath)
+" changing '\' to '/' or vice versa depending on OS (MS Windows or not) also calls simplify()
+function! s:ParsePath(sPath)
+ if (has('win32') || has('win64'))
+ let l:sPath = substitute(a:sPath, '/', '\', 'g')
+ else
+ let l:sPath = substitute(a:sPath, '\', '/', 'g')
+ endif
+ let l:sPath = simplify(l:sPath)
+
+ " removing last "/" or "\"
+ let l:sLastSymb = strpart(l:sPath, (strlen(l:sPath) - 1), 1)
+ if (l:sLastSymb == '/' || l:sLastSymb == '\')
+ let l:sPath = strpart(l:sPath, 0, (strlen(l:sPath) - 1))
+ endif
+ return l:sPath
+endfunction
+
+" s:Trim(sString)
+" trims spaces from begin and end of string
+function! s:Trim(sString)
+ return substitute(substitute(a:sString, '^\s\+', '', ''), '\s\+$', '', '')
+endfunction
+
+" s:IsAbsolutePath(path) <<<
+" this function from project.vim is written by Aric Blumer.
+" Returns true if filename has an absolute path.
+function! s:IsAbsolutePath(path)
+ if a:path =~ '^ftp:' || a:path =~ '^rcp:' || a:path =~ '^scp:' || a:path =~ '^http:'
+ return 2
+ endif
+ let path=expand(a:path) " Expand any environment variables that might be in the path
+ if path[0] == '/' || path[0] == '~' || path[0] == '\\' || path[1] == ':'
+ return 1
+ endif
+ return 0
+endfunction " >>>
+
+
+
+function! s:GetDirsAndFilesFromIndexerList(aLines, projectName, dExistsResult)
+ let l:aLines = a:aLines
+ let l:dResult = a:dExistsResult
+ let l:boolInNeededProject = (a:projectName == '' ? 1 : 0)
+ let l:boolInProjectsParentSection = 0
+ let l:sProjectsParentFilter = ''
+
+ let l:sCurProjName = ''
+
+ for l:sLine in l:aLines
+
+ " if line is not empty
+ if l:sLine !~ '^\s*$' && l:sLine !~ '^\s*\#.*$'
+
+ " look for project name [PrjName]
+ let myMatch = matchlist(l:sLine, '^\s*\[\([^\]]\+\)\]')
+
+ if (len(myMatch) > 0)
+
+ " check for PROJECTS_PARENT section
+
+ if (strpart(myMatch[1], 0, 15) == 'PROJECTS_PARENT')
+ " this is projects parent section
+ let l:sProjectsParentFilter = ''
+ let filterMatch = matchlist(myMatch[1], 'filter="\([^"]\+\)"')
+ if (len(filterMatch) > 0)
+ let l:sProjectsParentFilter = filterMatch[1]
+ endif
+ let l:boolInProjectsParentSection = 1
+ else
+ let l:boolInProjectsParentSection = 0
+
+
+ if (a:projectName != '')
+ if (myMatch[1] == a:projectName)
+ let l:boolInNeededProject = 1
+ else
+ let l:boolInNeededProject = 0
+ endif
+ endif
+
+ if l:boolInNeededProject
+ let l:sCurProjName = myMatch[1]
+ let l:dResult[l:sCurProjName] = { 'files': [], 'paths': [], 'not_exist': [] }
+ endif
+ endif
+ else
+
+ if l:boolInProjectsParentSection
+ " parsing one project parent
+
+ let l:lFilter = split(l:sProjectsParentFilter, ' ')
+ if (len(l:lFilter) == 0)
+ let l:lFilter = ['*']
+ endif
+ " removing \/* from end of path
+ let l:projectsParent = substitute(<SID>Trim(l:sLine), '[\\/*]\+$', '', '')
+
+ " creating list of projects
+ let l:lProjects = split(expand(l:projectsParent.'/*'), '\n')
+ let l:lIndexerFilesList = []
+ for l:sPrj in l:lProjects
+ if (isdirectory(l:sPrj))
+ call add(l:lIndexerFilesList, '['.substitute(l:sPrj, '^.*[\\/]\([^\\/]\+\)$', '\1', '').']')
+ for l:sCurFilter in l:lFilter
+ call add(l:lIndexerFilesList, l:sPrj.'/**/'.l:sCurFilter)
+ endfor
+ call add(l:lIndexerFilesList, '')
+ endif
+ endfor
+ " parsing this list
+ let l:dResult = <SID>GetDirsAndFilesFromIndexerList(l:lIndexerFilesList, a:projectName, l:dResult)
+
+ elseif l:boolInNeededProject
+ " looks like there's path
+ if l:sCurProjName == ''
+ let l:sCurProjName = 'noname'
+ let l:dResult[l:sCurProjName] = { 'files': [], 'paths': [], 'not_exist': [] }
+ endif
+ if (!g:indexer_ctagsDontSpecifyFilesIfPossible && s:indexer_projectName != '')
+ " adding every file.
+ let l:dResult[l:sCurProjName].files = <SID>ConcatLists(l:dResult[l:sCurProjName].files, split(expand(substitute(<SID>Trim(l:sLine), '\\\*\*', '**', 'g')), '\n'))
+ else
+ " adding just paths. (much more faster)
+ let l:dResult[l:sCurProjName].paths = <SID>ConcatLists(l:dResult[l:sCurProjName].paths, [<SID>ParsePath(expand(substitute(substitute(substitute(l:sLine, '^\(.*\)[\\/][^\\/]\+$', '\1', 'g'), '^\([^*]\+\).*$', '\1', ''), '[\\/]$', '', '')))])
+ endif
+ endif
+
+ endif
+ endif
+
+ endfor
+
+ " build paths
+ if (!g:indexer_ctagsDontSpecifyFilesIfPossible && s:indexer_projectName != '')
+ for l:sKey in keys(l:dResult)
+ let l:lPaths = []
+ for l:sFile in l:dResult[l:sKey].files
+ let l:sPath = substitute(l:sFile, '^\(.*\)[\\/][^\\/]\+$', '\1', 'g')
+ call add(l:lPaths, l:sPath)
+ endfor
+
+ let l:dResult[l:sKey].paths = <SID>ConcatLists(l:dResult[l:sKey].paths, l:lPaths)
+
+ endfor
+ endif
+
+ return l:dResult
+endfunction
+
+" getting dictionary with files, paths and non-existing files from indexer
+" project file
+function! s:GetDirsAndFilesFromIndexerFile(indexerFile, projectName)
+ let l:aLines = readfile(a:indexerFile)
+ let l:dResult = {}
+ let l:dResult = <SID>GetDirsAndFilesFromIndexerList(l:aLines, a:projectName, l:dResult)
+ return l:dResult
+endfunction
+
+" getting dictionary with files, paths and non-existing files from
+" project.vim's project file
+function! s:GetDirsAndFilesFromProjectFile(projectFile, projectName)
+ let l:aLines = readfile(a:projectFile)
+ " if projectName is empty, then we should add files from whole projectFile
+ let l:boolInNeededProject = (a:projectName == '' ? 1 : 0)
+
+ let l:iOpenedBraces = 0 " current count of opened { }
+ let l:iOpenedBracesAtProjectStart = 0
+ let l:aPaths = [] " paths stack
+ let l:sLastFoundPath = ''
+
+ let l:dResult = {}
+ let l:sCurProjName = ''
+
+ for l:sLine in l:aLines
+ " ignoring comments
+ if l:sLine =~ '^#' | continue | endif
+
+ let l:sLine = substitute(l:sLine, '#.\+$', '' ,'')
+ " searching for closing brace { }
+ let sTmpLine = l:sLine
+ while (sTmpLine =~ '}')
+ let l:iOpenedBraces = l:iOpenedBraces - 1
+
+ " if projectName is defined and there was last brace closed, then we
+ " are finished parsing needed project
+ if (l:iOpenedBraces <= l:iOpenedBracesAtProjectStart) && a:projectName != ''
+ let l:boolInNeededProject = 0
+ " TODO: total break
+ endif
+ call remove(l:aPaths, len(l:aPaths) - 1)
+
+ let sTmpLine = substitute(sTmpLine, '}', '', '')
+ endwhile
+
+ " searching for blabla=qweqwe
+ let myMatch = matchlist(l:sLine, '\s*\(.\{-}\)=\(.\{-}\)\\\@<!\(\s\|$\)')
+ if (len(myMatch) > 0)
+ " now we found start of project folder or subfolder
+ "
+ if !l:boolInNeededProject
+ if (a:projectName != '' && myMatch[1] == a:projectName)
+ let l:iOpenedBracesAtProjectStart = l:iOpenedBraces
+ let l:boolInNeededProject = 1
+ endif
+ endif
+
+ if l:boolInNeededProject && (l:iOpenedBraces == l:iOpenedBracesAtProjectStart)
+ let l:sCurProjName = myMatch[1]
+ let l:dResult[myMatch[1]] = { 'files': [], 'paths': [], 'not_exist': [] }
+ endif
+
+ let l:sLastFoundPath = myMatch[2]
+ " ADDED! Jkooij
+ " Strip the path of surrounding " characters, if there are any
+ let l:sLastFoundPath = substitute(l:sLastFoundPath, "\"\\(.*\\)\"", "\\1", "g")
+ let l:sLastFoundPath = expand(l:sLastFoundPath) " Expand any environment variables that might be in the path
+ let l:sLastFoundPath = s:ParsePath(l:sLastFoundPath)
+
+ endif
+
+ " searching for opening brace { }
+ let sTmpLine = l:sLine
+ while (sTmpLine =~ '{')
+
+ if (s:IsAbsolutePath(l:sLastFoundPath) || len(l:aPaths) == 0)
+ call add(l:aPaths, s:ParsePath(l:sLastFoundPath))
+ else
+ call add(l:aPaths, s:ParsePath(l:aPaths[len(l:aPaths) - 1].'/'.l:sLastFoundPath))
+ endif
+
+ let l:iOpenedBraces = l:iOpenedBraces + 1
+
+ if (l:boolInNeededProject && l:iOpenedBraces > l:iOpenedBracesAtProjectStart && isdirectory(l:aPaths[len(l:aPaths) - 1]))
+ call add(l:dResult[l:sCurProjName].paths, l:aPaths[len(l:aPaths) - 1])
+ endif
+
+ let sTmpLine = substitute(sTmpLine, '{', '', '')
+ endwhile
+
+ " searching for filename
+ if (l:sLine =~ '^[^={}]*$' && l:sLine !~ '^\s*$')
+ " here we found something like filename
+ "
+ if (l:boolInNeededProject && (!g:indexer_enableWhenProjectDirFound || s:indexer_projectName != '') && l:iOpenedBraces > l:iOpenedBracesAtProjectStart)
+ " we are in needed project
+ "let l:sCurFilename = expand(s:ParsePath(l:aPaths[len(l:aPaths) - 1].'/'.s:Trim(l:sLine)))
+ " CHANGED! Jkooij
+ " expand() will change slashes based on 'shellslash' flag,
+ " so call s:ParsePath() on expand() result for consistent slashes
+ let l:sCurFilename = s:ParsePath(expand(l:aPaths[len(l:aPaths) - 1].'/'.s:Trim(l:sLine)))
+ if (filereadable(l:sCurFilename))
+ " file readable! adding it
+ call add(l:dResult[l:sCurProjName].files, l:sCurFilename)
+ elseif (!isdirectory(l:sCurFilename))
+ call add(l:dResult[l:sCurProjName].not_exist, l:sCurFilename)
+ endif
+ endif
+
+ endif
+
+ endfor
+
+ return l:dResult
+endfunction
+
+" returns whether or not file exists in list
+function! s:IsFileExistsInList(aList, sFilename)
+ let l:sFilename = s:ParsePath(a:sFilename)
+ if (index(a:aList, l:sFilename, 0, 1)) >= 0
+ return 1
+ endif
+ return 0
+endfunction
+
+" updating tags using ctags.
+" if boolAppend then just appends existing tags file with new tags from
+" current file (%)
+function! s:UpdateTags(boolAppend)
+
+ " one tags file
+
+ let l:sTagsFileWOPath = substitute(join(g:indexer_indexedProjects, '_'), '\s', '_', 'g')
+ let l:sTagsFile = s:tagsDirname.'/'.l:sTagsFileWOPath
+ if !isdirectory(s:tagsDirname)
+ call mkdir(s:tagsDirname, "p")
+ endif
+
+ let l:sSavedFile = <SID>ParsePath(expand('%:p'))
+ if (<SID>IsFileExistsInList(s:lNotExistFiles, l:sSavedFile))
+ " moving file from non-existing list to existing list
+ call remove(s:lNotExistFiles, index(s:lNotExistFiles, l:sSavedFile))
+ call add(s:lFileList, l:sSavedFile)
+ endif
+
+ let l:sRecurseCode = ''
+
+ if (a:boolAppend && filereadable(l:sTagsFile))
+ let l:sAppendCode = '-a'
+ if (<SID>IsFileExistsInList(s:lFileList, l:sSavedFile))
+ " saved file are in file list
+ let l:sFiles = l:sSavedFile
+ else
+ let l:sFiles = ''
+ endif
+
+ else
+ let l:sAppendCode = ''
+ let l:sFiles = ''
+ let l:sFile = ''
+ if (g:indexer_ctagsDontSpecifyFilesIfPossible && s:sMode == 'IndexerFile')
+ let l:sRecurseCode = '-R'
+ for l:sPath in s:lPathList
+ let l:sFiles = l:sFiles.' "'.l:sPath.'"'
+ endfor
+ else
+ for l:sFile in s:lFileList
+ let l:sFiles = l:sFiles.' "'.l:sFile.'"'
+ endfor
+ endif
+ endif
+
+ if l:sFiles != ''
+ "if (has('win32') || has('win64'))
+ let l:sTagsFile = '"'.l:sTagsFile.'"'
+ "endif
+
+ if (has('win32') || has('win64'))
+ let l:cmd = 'ctags -f '.l:sTagsFile.' '.l:sRecurseCode.' '.l:sAppendCode.' '.g:indexer_ctagsCommandLineOptions.' '.l:sFiles
+ else
+ let l:cmd = 'ctags -f '.l:sTagsFile.' '.l:sRecurseCode.' '.l:sAppendCode.' '.g:indexer_ctagsCommandLineOptions.' '.l:sFiles.' &'
+ endif
+
+ let l:resp = system(l:cmd)
+ exec 'set tags='.substitute(s:tagsDirname.'/'.l:sTagsFileWOPath, ' ', '\\\\\\ ', 'g')
+ endif
+
+ "multiple files, calls from bat file
+ "exec 'set tags='
+ "let l:lLines = []
+ "for l:sFile in s:lFileList
+ "let l:sTagFile = s:tagsDirname.'/'.substitute(l:sFile, '[\\/:]', '_', 'g')
+ "call add(l:lLines, 'ctags -f '.l:sTagFile.' '.g:indexer_ctagsCommandLineOptions.' '.l:sFile)
+ "exec 'set tags+='.l:sTagFile
+ "endfor
+ "call writefile(l:lLines, s:tagsDirname.'/maketags.bat')
+
+ "let l:cmd = s:tagsDirname.'/maketags.bat'
+ "let l:resp = system(l:cmd)
+endfunction
+
+function! s:ApplyProjectSettings(dParse)
+ " paths for Vim
+ set path=.
+ for l:sPath in a:dParse.paths
+ if isdirectory(l:sPath)
+ exec 'set path+='.substitute(l:sPath, ' ', '\\ ', 'g')
+ endif
+ endfor
+
+ let s:lFileList = a:dParse.files
+ let s:lPathList = a:dParse.paths
+ let s:lNotExistFiles = a:dParse.not_exist
+
+ augroup Indexer_SavSrcFile
+ autocmd! Indexer_SavSrcFile BufWritePost
+ augroup END
+ " collect extensions of files in project to make autocmd on save these
+ " files
+ let l:sExtsList = ''
+ let l:lFullList = s:lFileList + s:lNotExistFiles
+ for l:lFile in l:lFullList
+ let l:sExt = substitute(l:lFile, '^.*\([.\\/][^.\\/]\+\)$', '\1', '')
+ if strpart(l:sExt, 0, 1) != '.'
+ let l:sExt = strpart(l:sExt, 1)
+ endif
+ if (stridx(l:sExtsList, l:sExt) == -1)
+ if (l:sExtsList != '')
+ let l:sExtsList = l:sExtsList.','
+ endif
+ let l:sExtsList = l:sExtsList.'*'.l:sExt
+ endif
+ endfor
+
+ " defining autocmd at source files save
+ exec 'autocmd Indexer_SavSrcFile BufWritePost '.l:sExtsList.' call <SID>UpdateTags('.(g:indexer_ctagsJustAppendTagsAtFileSave ? '1' : '0').')'
+
+ " start full tags update
+ call <SID>UpdateTags(0)
+endfunction
+
+" concatenates two lists preventing duplicates
+function! s:ConcatLists(lExistingList, lAddingList)
+ let l:lResList = a:lExistingList
+ for l:sItem in a:lAddingList
+ if (index(l:lResList, l:sItem) == -1)
+ call add(l:lResList, l:sItem)
+ endif
+ endfor
+ return l:lResList
+endfunction
+
+function! s:GetDirsAndFilesFromAvailableFile()
+ if (filereadable(g:indexer_indexerListFilename))
+ " read all projects from proj file
+ let s:sMode = 'IndexerFile'
+ let s:dParseAll = s:GetDirsAndFilesFromIndexerFile(g:indexer_indexerListFilename, s:indexer_projectName)
+ elseif (filereadable(g:indexer_projectsSettingsFilename))
+ let s:sMode = 'ProjectFile'
+ let s:dParseAll = s:GetDirsAndFilesFromProjectFile(g:indexer_projectsSettingsFilename, s:indexer_projectName)
+ else
+ let s:sMode = ''
+ let s:dParseAll = {}
+ endif
+endfunction
+
+function! s:ParseProjectSettingsFile()
+ call <SID>GetDirsAndFilesFromAvailableFile()
+
+ " let's found what files we should to index.
+ " now we will search for project directory up by dir tree
+ let l:i = 0
+ let l:sCurPath = ''
+ while (g:indexer_enableWhenProjectDirFound && s:indexer_projectName == '' && l:i < 10)
+ for l:sKey in keys(s:dParseAll)
+ if (<SID>IsFileExistsInList(s:dParseAll[l:sKey].paths, expand('%:p:h').l:sCurPath))
+ let s:indexer_projectName = l:sKey
+ if !(s:sMode == 'IndexerFile' && g:indexer_ctagsDontSpecifyFilesIfPossible)
+ call <SID>GetDirsAndFilesFromAvailableFile()
+ else
+ call add(g:indexer_indexedProjects, l:sKey)
+ endif
+ break
+ endif
+ endfor
+ let l:sCurPath = l:sCurPath.'/..'
+ let l:i = l:i + 1
+ endwhile
+
+ if !(s:sMode == 'IndexerFile' && g:indexer_ctagsDontSpecifyFilesIfPossible)
+ let s:iTotalFilesAvailableCnt = 0
+ if (!s:boolIndexingModeOn)
+ for l:sKey in keys(s:dParseAll)
+ let s:iTotalFilesAvailableCnt = s:iTotalFilesAvailableCnt + len(s:dParseAll[l:sKey].files)
+
+ if ((g:indexer_enableWhenProjectDirFound && <SID>IsFileExistsInList(s:dParseAll[l:sKey].paths, expand('%:p:h'))) || (<SID>IsFileExistsInList(s:dParseAll[l:sKey].files, expand('%:p'))))
+ " user just opened file from project l:sKey. We should add it to
+ " result lists
+
+ " adding name of this project to g:indexer_indexedProjects
+ call add(g:indexer_indexedProjects, l:sKey)
+
+ endif
+ endfor
+ endif
+ endif
+
+ " build final list of files, paths and non-existing files
+ let l:dParse = { 'files':[], 'paths':[], 'not_exist':[] }
+ for l:sKey in g:indexer_indexedProjects
+ let l:dParse.files = <SID>ConcatLists(l:dParse.files, s:dParseAll[l:sKey].files)
+ let l:dParse.paths = <SID>ConcatLists(l:dParse.paths, s:dParseAll[l:sKey].paths)
+ let l:dParse.not_exist = <SID>ConcatLists(l:dParse.not_exist, s:dParseAll[l:sKey].not_exist)
+ endfor
+
+ if (s:boolIndexingModeOn)
+ call <SID>ApplyProjectSettings(l:dParse)
+ else
+ if (len(l:dParse.files) > 0 || len(l:dParse.paths) > 0)
+
+ let s:boolIndexingModeOn = 1
+
+ " creating auto-refresh index at project file save
+ augroup Indexer_SavPrjFile
+ autocmd! Indexer_SavPrjFile BufWritePost
+ augroup END
+
+ if (filereadable(g:indexer_indexerListFilename))
+ let l:sIdxFile = substitute(g:indexer_indexerListFilename, '^.*[\\/]\([^\\/]\+\)$', '\1', '')
+ exec 'autocmd Indexer_SavPrjFile BufWritePost '.l:sIdxFile.' call <SID>ParseProjectSettingsFile()'
+ elseif (filereadable(g:indexer_projectsSettingsFilename))
+ let l:sPrjFile = substitute(g:indexer_projectsSettingsFilename, '^.*[\\/]\([^\\/]\+\)$', '\1', '')
+ exec 'autocmd Indexer_SavPrjFile BufWritePost '.l:sPrjFile.' call <SID>ParseProjectSettingsFile()'
+ endif
+
+ call <SID>ApplyProjectSettings(l:dParse)
+
+ let l:iNonExistingCnt = len(s:lNotExistFiles)
+ if (l:iNonExistingCnt > 0)
+ if l:iNonExistingCnt < 100
+ echo "Indexer Warning: project loaded, but there's ".l:iNonExistingCnt." non-existing files: \n\n".join(s:lNotExistFiles, "\n")
+ else
+ echo "Indexer Warning: project loaded, but there's ".l:iNonExistingCnt." non-existing files. Type :IndexerInfo for details."
+ endif
+ endif
+ else
+ " there's no project started.
+ " we should define autocmd to detect if file from project will be opened later
+ augroup Indexer_LoadFile
+ autocmd! Indexer_LoadFile BufReadPost
+ autocmd Indexer_LoadFile BufReadPost * call <SID>IndexerInit()
+ augroup END
+ endif
+ endif
+endfunction
+
+function! s:IndexerInfo()
+ if (s:sMode == '')
+ echo '* Filelist: not found'
+ elseif (s:sMode == 'IndexerFile')
+ echo '* Filelist: indexer file: '.g:indexer_indexerListFilename
+ elseif (s:sMode == 'ProjectFile')
+ echo '* Filelist: project file: '.g:indexer_projectsSettingsFilename
+ else
+ echo '* Filelist: Unknown'
+ endif
+ echo '* Projects indexed: '.join(g:indexer_indexedProjects, ', ')
+ if !(s:sMode == 'IndexerFile' && g:indexer_ctagsDontSpecifyFilesIfPossible)
+ echo "* Files indexed: there's ".len(s:lFileList).' files. Type :IndexerFiles to list'
+ echo "* Files not found: there's ".len(s:lNotExistFiles).' non-existing files. '.join(s:lNotExistFiles, ', ')
+ endif
+
+ echo '* Paths: '.&path
+ echo '* Tags file: '.&tags
+ echo '* Project root: '.($INDEXER_PROJECT_ROOT != '' ? $INDEXER_PROJECT_ROOT : 'not found').' (Project root is a directory which contains "'.g:indexer_dirNameForSearch.'" directory)'
+endfunction
+
+function! s:IndexerFilesList()
+ echo "* Files indexed: ".join(s:lFileList, ', ')
+endfunction
+
+function! s:IndexerInit()
+
+ augroup Indexer_LoadFile
+ autocmd! Indexer_LoadFile BufReadPost
+ augroup END
+
+ " actual tags dirname. If .vimprj directory will be found then this tags
+ " dirname will be /path/to/dir/.vimprj/tags
+ let s:tagsDirname = g:indexer_tagsDirname
+ let g:indexer_indexedProjects = []
+ let s:sMode = ''
+ let s:lFileList = []
+ let s:lNotExistFiles = []
+
+ let s:boolIndexingModeOn = 0
+
+ if g:indexer_lookForProjectDir
+ " need to look for .vimprj directory
+
+ let l:i = 0
+ let l:sCurPath = ''
+ let $INDEXER_PROJECT_ROOT = ''
+ while (l:i < g:indexer_recurseUpCount)
+ if (isdirectory(expand('%:p:h').l:sCurPath.'/'.g:indexer_dirNameForSearch))
+ let $INDEXER_PROJECT_ROOT = simplify(expand('%:p:h').l:sCurPath)
+ exec 'cd '.substitute($INDEXER_PROJECT_ROOT, ' ', '\\ ', 'g')
+ break
+ endif
+ let l:sCurPath = l:sCurPath.'/..'
+ let l:i = l:i + 1
+ endwhile
+
+ if $INDEXER_PROJECT_ROOT != ''
+ " project root was found.
+ "
+ " set directory for tags in .vimprj dir
+ let s:tagsDirname = $INDEXER_PROJECT_ROOT.'/'.g:indexer_dirNameForSearch.'/tags'
+
+ " sourcing all *vim files in .vimprj dir
+ let l:lSourceFilesList = split(glob($INDEXER_PROJECT_ROOT.'/'.g:indexer_dirNameForSearch.'/*vim'), '\n')
+ let l:sThisFile = expand('%:p')
+ for l:sFile in l:lSourceFilesList
+ if (l:sFile != l:sThisFile)
+ exec 'source '.l:sFile
+ endif
+ endfor
+ endif
+
+ endif
+
+ call s:ParseProjectSettingsFile()
+
+endfunction
+
+
+
+
+
+
+" --------- init variables --------
+if !exists('g:indexer_lookForProjectDir')
+ let g:indexer_lookForProjectDir = 1
+endif
+
+if !exists('g:indexer_dirNameForSearch')
+ let g:indexer_dirNameForSearch = '.vimprj'
+endif
+
+if !exists('g:indexer_recurseUpCount')
+ let g:indexer_recurseUpCount = 10
+endif
+
+if !exists('g:indexer_indexerListFilename')
+ let g:indexer_indexerListFilename = $HOME.'/.indexer_files'
+endif
+
+if !exists('g:indexer_projectsSettingsFilename')
+ let g:indexer_projectsSettingsFilename = $HOME.'/.vimprojects'
+endif
+
+if !exists('g:indexer_projectName')
+ let g:indexer_projectName = ''
+endif
+
+if !exists('g:indexer_enableWhenProjectDirFound')
+ let g:indexer_enableWhenProjectDirFound = '1'
+endif
+
+if !exists('g:indexer_tagsDirname')
+ let g:indexer_tagsDirname = $HOME.'/.vimtags'
+endif
+
+if !exists('g:indexer_ctagsCommandLineOptions')
+ let g:indexer_ctagsCommandLineOptions = '--c++-kinds=+p+l --fields=+iaS --extra=+q'
+endif
+
+if !exists('g:indexer_ctagsJustAppendTagsAtFileSave')
+ let g:indexer_ctagsJustAppendTagsAtFileSave = 1
+endif
+
+if !exists('g:indexer_ctagsDontSpecifyFilesIfPossible')
+ let g:indexer_ctagsDontSpecifyFilesIfPossible = '0'
+endif
+
+let s:indexer_projectName = g:indexer_projectName
+
+
+" -------- init commands ---------
+
+if exists(':IndexerInfo') != 2
+ command -nargs=? -complete=file IndexerInfo call <SID>IndexerInfo()
+endif
+if exists(':IndexerFiles') != 2
+ command -nargs=? -complete=file IndexerFiles call <SID>IndexerFilesList()
+endif
+if exists(':IndexerRebuild') != 2
+ command -nargs=? -complete=file IndexerRebuild call <SID>UpdateTags(0)
+endif
+
+
+
+
+
+
+augroup Indexer_LoadFile
+ autocmd! Indexer_LoadFile BufReadPost
+ autocmd Indexer_LoadFile BufReadPost * call <SID>IndexerInit()
+augroup END
+
+call <SID>IndexerInit()
+
diff --git a/modules/vim/vim/plugin/project.vim b/modules/vim/vim/plugin/project.vim
new file mode 100644
index 0000000..47bd379
--- /dev/null
+++ b/modules/vim/vim/plugin/project.vim
@@ -0,0 +1,1293 @@
+"=============================================================================
+" File: project.vim
+" Author: Aric Blumer (Aric.Blumer at aricvim@charter.net)
+" Last Change: Fri 13 Oct 2006 09:47:08 AM EDT
+" Version: 1.4.1
+"=============================================================================
+" See documentation in accompanying help file
+" You may use this code in whatever way you see fit.
+
+if exists('loaded_project') || &cp
+ finish
+endif
+let loaded_project=1
+
+function! s:Project(filename) " <<<
+ " Initialization <<<
+ if exists("g:proj_running")
+ if strlen(a:filename) != 0
+ call confirm('Project already loaded; ignoring filename "'.a:filename."\".\n".'See ":help project-invoking" for information about changing project files.', "&OK", 1)
+ endif
+ let filename=bufname(g:proj_running)
+ else
+ if strlen(a:filename) == 0
+ let filename ='~/.vimprojects' " Default project filename
+ else
+ let filename = a:filename
+ endif
+ endif
+ if !exists('g:proj_window_width')
+ let g:proj_window_width=24 " Default project window width
+ endif
+ if !exists('g:proj_window_increment')
+ let g:proj_window_increment=100 " Project Window width increment
+ endif
+ if !exists('g:proj_flags')
+ if has("win32") || has("mac")
+ let g:proj_flags='imst' " Project default flags for windows/mac
+ else
+ let g:proj_flags='imstb' " Project default flags for everything else
+ endif
+ endif
+ if !exists("g:proj_running") || (bufwinnr(g:proj_running) == -1) " Open the Project Window
+ exec 'silent vertical new '.filename
+ if match(g:proj_flags, '\CF') == -1 " We're floating
+ silent! wincmd H
+ exec 'vertical resize '.g:proj_window_width
+ endif
+ setlocal nomodeline
+ else
+ silent! 99wincmd h
+ if bufwinnr(g:proj_running) == -1
+ vertical split
+ let v:errmsg="nothing"
+ silent! bnext
+ if 'nothing' != v:errmsg
+ enew
+ endif
+ endif
+ return
+ endif
+ " Process the flags
+ let b:proj_cd_cmd='cd'
+ if match(g:proj_flags, '\Cl') != -1
+ let b:proj_cd_cmd = 'lcd'
+ endif
+
+ let b:proj_locate_command='silent! wincmd H'
+ let b:proj_resize_command='exec ''vertical resize ''.g:proj_window_width'
+ if match(g:proj_flags, '\CF') != -1 " Set the resize commands to nothing
+ let b:proj_locate_command=''
+ let b:proj_resize_command=''
+ endif
+
+ let g:proj_last_buffer = -1
+ ">>>
+ " ProjFoldText() <<<
+ " The foldtext function for displaying just the description.
+ function! ProjFoldText()
+ let line=substitute(getline(v:foldstart),'^[ \t#]*\([^=]*\).*', '\1', '')
+ let line=strpart(' ', 0, (v:foldlevel - 1)).substitute(line,'\s*{\+\s*', '', '')
+ return line
+ endfunction ">>>
+ " s:DoSetup() <<<
+ " Ensure everything is set up
+ function! s:DoSetup()
+ setlocal foldenable foldmethod=marker foldmarker={,} commentstring=%s foldcolumn=0 nonumber noswapfile shiftwidth=1
+ setlocal foldtext=ProjFoldText() nobuflisted nowrap
+ setlocal winwidth=1
+ if match(g:proj_flags, '\Cn') != -1
+ setlocal number
+ endif
+ endfunction ">>>
+ call s:DoSetup()
+ " Syntax Stuff <<<
+ if match(g:proj_flags, '\Cs')!=-1 && has('syntax') && exists('g:syntax_on') && !has('syntax_items')
+ syntax match projectDescriptionDir '^\s*.\{-}=\s*\(\\ \|\f\|:\|"\)\+' contains=projectDescription,projectWhiteError
+ syntax match projectDescription '\<.\{-}='he=e-1,me=e-1 contained nextgroup=projectDirectory contains=projectWhiteError
+ syntax match projectDescription '{\|}'
+ syntax match projectDirectory '=\(\\ \|\f\|:\)\+' contained
+ syntax match projectDirectory '=".\{-}"' contained
+ syntax match projectScriptinout '\<in\s*=\s*\(\\ \|\f\|:\|"\)\+' contains=projectDescription,projectWhiteError
+ syntax match projectScriptinout '\<out\s*=\s*\(\\ \|\f\|:\|"\)\+' contains=projectDescription,projectWhiteError
+ syntax match projectComment '#.*'
+ syntax match projectCD '\<CD\s*=\s*\(\\ \|\f\|:\|"\)\+' contains=projectDescription,projectWhiteError
+ syntax match projectFilterEntry '\<filter\s*=.*"' contains=projectWhiteError,projectFilterError,projectFilter,projectFilterRegexp
+ syntax match projectFilter '\<filter='he=e-1,me=e-1 contained nextgroup=projectFilterRegexp,projectFilterError,projectWhiteError
+ syntax match projectFlagsEntry '\<flags\s*=\( \|[^ ]*\)' contains=projectFlags,projectWhiteError
+ syntax match projectFlags '\<flags' contained nextgroup=projectFlagsValues,projectWhiteError
+ syntax match projectFlagsValues '=[^ ]* 'hs=s+1,me=e-1 contained contains=projectFlagsError
+ syntax match projectFlagsError '[^rtTsSwl= ]\+' contained
+ syntax match projectWhiteError '=\s\+'hs=s+1 contained
+ syntax match projectWhiteError '\s\+='he=e-1 contained
+ syntax match projectFilterError '=[^"]'hs=s+1 contained
+ syntax match projectFilterRegexp '=".*"'hs=s+1 contained
+ syntax match projectFoldText '^[^=]\+{'
+
+ highlight def link projectDescription Identifier
+ highlight def link projectScriptinout Identifier
+ highlight def link projectFoldText Identifier
+ highlight def link projectComment Comment
+ highlight def link projectFilter Identifier
+ highlight def link projectFlags Identifier
+ highlight def link projectDirectory Constant
+ highlight def link projectFilterRegexp String
+ highlight def link projectFlagsValues String
+ highlight def link projectWhiteError Error
+ highlight def link projectFlagsError Error
+ highlight def link projectFilterError Error
+ endif ">>>
+ " s:SortR(start, end) <<<
+ " Sort lines. SortR() is called recursively.
+ " from ":help eval-examples" by Robert Webb, slightly modified
+ function! s:SortR(start, end)
+ if (a:start >= a:end)
+ return
+ endif
+ let partition = a:start - 1
+ let middle = partition
+ let partStr = getline((a:start + a:end) / 2)
+ let i = a:start
+ while (i <= a:end)
+ let str = getline(i)
+ if str < partStr
+ let result = -1
+ elseif str > partStr
+ let result = 1
+ else
+ let result = 0
+ endif
+ if (result <= 0)
+ let partition = partition + 1
+ if (result == 0)
+ let middle = partition
+ endif
+ if (i != partition)
+ let str2 = getline(partition)
+ call setline(i, str2)
+ call setline(partition, str)
+ endif
+ endif
+ let i = i + 1
+ endwhile
+ if (middle != partition)
+ let str = getline(middle)
+ let str2 = getline(partition)
+ call setline(middle, str2)
+ call setline(partition, str)
+ endif
+ call s:SortR(a:start, partition - 1)
+ call s:SortR(partition + 1, a:end)
+ endfunc ">>>
+ " s:IsAbsolutePath(path) <<<
+ " Returns true if filename has an absolute path.
+ function! s:IsAbsolutePath(path)
+ if a:path =~ '^ftp:' || a:path =~ '^rcp:' || a:path =~ '^scp:' || a:path =~ '^http:'
+ return 2
+ endif
+ if a:path =~ '\$'
+ let path=expand(a:path) " Expand any environment variables that might be in the path
+ else
+ let path=a:path
+ endif
+ if path[0] == '/' || path[0] == '~' || path[0] == '\\' || path[1] == ':'
+ return 1
+ endif
+ return 0
+ endfunction " >>>
+ " s:DoSetupAndSplit() <<<
+ " Call DoSetup to ensure the settings are correct. Split to the next
+ " file.
+ function! s:DoSetupAndSplit()
+ call s:DoSetup() " Ensure that all the settings are right
+ let n = winnr() " Determine if there is a CTRL_W-p window
+ silent! wincmd p
+ if n == winnr()
+ silent! wincmd l
+ endif
+ if n == winnr()
+ " If n == winnr(), then there is no CTRL_W-p window
+ " So we have to create a new one
+ if bufnr('%') == g:proj_running
+ exec 'silent vertical new'
+ else
+ exec 'silent vertical split | silent! bnext'
+ endif
+ wincmd p " Go back to the Project Window and ensure it is the right width
+ exec b:proj_locate_command
+ exec b:proj_resize_command
+ wincmd p
+ endif
+ endfunction ">>>
+ " s:DoSetupAndSplit_au() <<<
+ " Same as above but ensure that the Project window is the current
+ " window. Only called from an autocommand
+ function! s:DoSetupAndSplit_au()
+ if winbufnr(0) != g:proj_running
+ return
+ endif
+ call s:DoSetup() " Ensure that all the settings are right
+ if winbufnr(2) == -1 " We're the only window right now.
+ exec 'silent vertical split | bnext'
+ if bufnr('%') == g:proj_running
+ enew
+ endif
+ if bufnr('%') == g:proj_last_buffer | bnext | bprev | bnext | endif
+ wincmd p " Go back to the Project Window and ensure it is the right width
+ exec b:proj_locate_command
+ exec b:proj_resize_command
+ elseif(winnr() != 1)
+ exec b:proj_locate_command
+ exec b:proj_resize_command
+ endif
+ endfunction
+ function! s:RecordPrevBuffer_au()
+ let g:proj_last_buffer = bufnr('%')
+ endfunction ">>>
+ " s:RecursivelyConstructDirectives(lineno) <<<
+ " Construct the inherited directives
+ function! s:RecursivelyConstructDirectives(lineno)
+ let lineno=s:FindFoldTop(a:lineno)
+ let foldlineno = lineno
+ let foldlev=foldlevel(lineno)
+ let parent_infoline = ''
+ if foldlev > 1
+ while foldlevel(lineno) >= foldlev " Go to parent fold
+ if lineno < 1
+ echoerr 'Some kind of fold error. Check your syntax.'
+ return
+ endif
+ let lineno = lineno - 1
+ endwhile
+ let parent_infoline = s:RecursivelyConstructDirectives(lineno)
+ endif
+ let parent_home = s:GetHome(parent_infoline, '')
+ let parent_c_d = s:GetCd(parent_infoline, parent_home)
+ let parent_scriptin = s:GetScriptin(parent_infoline, parent_home)
+ let parent_scriptout = s:GetScriptout(parent_infoline, parent_home)
+ let parent_filter = s:GetFilter(parent_infoline, '*')
+ let infoline = getline(foldlineno)
+ " Extract the home directory of this fold
+ let home=s:GetHome(infoline, parent_home)
+ if home != ''
+ if (foldlevel(foldlineno) == 1) && !s:IsAbsolutePath(home)
+ call confirm('Outermost Project Fold must have absolute path! Or perhaps the path does not exist.', "&OK", 1)
+ let home = '~' " Some 'reasonable' value
+ endif
+ endif
+ " Extract any CD information
+ let c_d = s:GetCd(infoline, home)
+ if c_d != ''
+ if (foldlevel(foldlineno) == 1) && !s:IsAbsolutePath(c_d)
+ call confirm('Outermost Project Fold must have absolute CD path! Or perhaps the path does not exist.', "&OK", 1)
+ let c_d = '.' " Some 'reasonable' value
+ endif
+ else
+ let c_d=parent_c_d
+ endif
+ " Extract scriptin
+ let scriptin = s:GetScriptin(infoline, home)
+ if scriptin == ''
+ let scriptin = parent_scriptin
+ endif
+ " Extract scriptout
+ let scriptout = s:GetScriptout(infoline, home)
+ if scriptout == ''
+ let scriptout = parent_scriptout
+ endif
+ " Extract filter
+ let filter = s:GetFilter(infoline, parent_filter)
+ if filter == '' | let filter = parent_filter | endif
+ return s:ConstructInfo(home, c_d, scriptin, scriptout, '', filter)
+ endfunction ">>>
+ " s:ConstructInfo(home, c_d, scriptin, scriptout, flags, filter) <<<
+ function! s:ConstructInfo(home, c_d, scriptin, scriptout, flags, filter)
+ let retval='Directory='.a:home
+ if a:c_d[0] != ''
+ let retval=retval.' CD='.a:c_d
+ endif
+ if a:scriptin[0] != ''
+ let retval=retval.' in='.a:scriptin
+ endif
+ if a:scriptout[0] != ''
+ let retval=retval.' out='.a:scriptout
+ endif
+ if a:filter[0] != ''
+ let retval=retval.' filter="'.a:filter.'"'
+ endif
+ return retval
+ endfunction ">>>
+ " s:OpenEntry(line, precmd, editcmd) <<<
+ " Get the filename under the cursor, and open a window with it.
+ function! s:OpenEntry(line, precmd, editcmd, dir)
+ silent exec a:precmd
+ if (a:editcmd[0] != '')
+ if a:dir
+ let fname='.'
+ else
+ if (foldlevel(a:line) == 0) && (a:editcmd[0] != '')
+ return 0 " If we're outside a fold, do nothing
+ endif
+ let fname=substitute(getline(a:line), '\s*#.*', '', '') " Get rid of comments and whitespace before comment
+ let fname=substitute(fname, '^\s*\(.*\)', '\1', '') " Get rid of leading whitespace
+ if strlen(fname) == 0
+ return 0 " The line is blank. Do nothing.
+ endif
+ endif
+ else
+ let fname='.'
+ endif
+ let infoline = s:RecursivelyConstructDirectives(a:line)
+ let retval=s:OpenEntry2(a:line, infoline, fname, a:editcmd)
+ call s:DisplayInfo()
+ return retval
+ endfunction
+ ">>>
+ " s:OpenEntry2(line, infoline, precmd, editcmd) <<<
+ " Get the filename under the cursor, and open a window with it.
+ function! s:OpenEntry2(line, infoline, fname, editcmd)
+ let fname=escape(a:fname, ' %#') " Thanks to Thomas Link for cluing me in on % and #
+ let home=s:GetHome(a:infoline, '').'/'
+ if home=='/'
+ echoerr 'Project structure error. Check your syntax.'
+ return
+ endif
+ "Save the cd command
+ let cd_cmd = b:proj_cd_cmd
+ if a:editcmd[0] != '' " If editcmd is '', then just set up the environment in the Project Window
+ call s:DoSetupAndSplit()
+ " If it is an absolute path, don't prepend home
+ if !s:IsAbsolutePath(fname)
+ let fname=home.fname
+ endif
+ if s:IsAbsolutePath(fname) == 2
+ exec a:editcmd.' '.fname
+ else
+ silent exec 'silent '.a:editcmd.' '.fname
+ endif
+ else " only happens in the Project File
+ exec 'au! BufEnter,BufLeave '.expand('%:p')
+ endif
+ " Extract any CD information
+ let c_d = s:GetCd(a:infoline, home)
+ if c_d != '' && (s:IsAbsolutePath(home) != 2)
+ if match(g:proj_flags, '\CL') != -1
+ call s:SetupAutoCommand(c_d)
+ endif
+ if !isdirectory(glob(c_d))
+ call confirm("From this fold's entry,\nCD=".'"'.c_d.'" is not a valid directory.', "&OK", 1)
+ else
+ silent exec cd_cmd.' '.c_d
+ endif
+ endif
+ " Extract any scriptin information
+ let scriptin = s:GetScriptin(a:infoline, home)
+ if scriptin != ''
+ if !filereadable(glob(scriptin))
+ call confirm('"'.scriptin.'" not found. Ignoring.', "&OK", 1)
+ else
+ call s:SetupScriptAutoCommand('BufEnter', scriptin)
+ exec 'source '.scriptin
+ endif
+ endif
+ let scriptout = s:GetScriptout(a:infoline, home)
+ if scriptout != ''
+ if !filereadable(glob(scriptout))
+ call confirm('"'.scriptout.'" not found. Ignoring.', "&OK", 1)
+ else
+ call s:SetupScriptAutoCommand('BufLeave', scriptout)
+ endif
+ endif
+ return 1
+ endfunction
+ ">>>
+ " s:DoFoldOrOpenEntry(cmd0, cmd1) <<<
+ " Used for double clicking. If the mouse is on a fold, open/close it. If
+ " not, try to open the file.
+ function! s:DoFoldOrOpenEntry(cmd0, cmd1)
+ if getline('.')=~'{\|}' || foldclosed('.') != -1
+ normal! za
+ else
+ call s:DoEnsurePlacementSize_au()
+ call s:OpenEntry(line('.'), a:cmd0, a:cmd1, 0)
+ if (match(g:proj_flags, '\Cc') != -1)
+ let g:proj_mywinnumber = winbufnr(0)
+ Project
+ hide
+ if(g:proj_mywinnumber != winbufnr(0))
+ wincmd p
+ endif
+ wincmd =
+ endif
+ endif
+ endfunction ">>>
+ " s:VimDirListing(filter, padding, separator, filevariable, filecount, dirvariable, dircount) <<<
+ function! s:VimDirListing(filter, padding, separator, filevariable, filecount, dirvariable, dircount)
+ let end = 0
+ let files=''
+ let filter = a:filter
+ " Chop up the filter
+ " Apparently glob() cannot take something like this: glob('*.c *.h')
+ let while_var = 1
+ while while_var
+ let end = stridx(filter, ' ')
+ if end == -1
+ let end = strlen(filter)
+ let while_var = 0
+ endif
+ let single=glob(strpart(filter, 0, end))
+ if strlen(single) != 0
+ let files = files.single."\010"
+ endif
+ let filter = strpart(filter, end + 1)
+ endwhile
+ " files now contains a list of everything in the directory. We need to
+ " weed out the directories.
+ let fnames=files
+ let {a:filevariable}=''
+ let {a:dirvariable}=''
+ let {a:filecount}=0
+ let {a:dircount}=0
+ while strlen(fnames) > 0
+ let fname = substitute(fnames, '\(\(\f\|[ :\[\]]\)*\).*', '\1', '')
+ let fnames = substitute(fnames, '\(\f\|[ :\[\]]\)*.\(.*\)', '\2', '')
+ if isdirectory(glob(fname))
+ let {a:dirvariable}={a:dirvariable}.a:padding.fname.a:separator
+ let {a:dircount}={a:dircount} + 1
+ else
+ let {a:filevariable}={a:filevariable}.a:padding.fname.a:separator
+ let {a:filecount}={a:filecount} + 1
+ endif
+ endwhile
+ endfunction ">>>
+ " s:GenerateEntry(recursive, name, absolute_dir, dir, c_d, filter_directive, filter, foldlev, sort) <<<
+ function! s:GenerateEntry(recursive, line, name, absolute_dir, dir, c_d, filter_directive, filter, foldlev, sort)
+ let line=a:line
+ if a:dir =~ '\\ '
+ let dir='"'.substitute(a:dir, '\\ ', ' ', 'g').'"'
+ else
+ let dir=a:dir
+ endif
+ let spaces=strpart(' ', 0, a:foldlev)
+ let c_d=(strlen(a:c_d) > 0) ? 'CD='.a:c_d.' ' : ''
+ let c_d=(strlen(a:filter_directive) > 0) ? c_d.'filter="'.a:filter_directive.'" ': c_d
+ call append(line, spaces.'}')
+ call append(line, spaces.a:name.'='.dir.' '.c_d.'{')
+ if a:recursive
+ exec 'cd '.a:absolute_dir
+ call s:VimDirListing("*", '', "\010", 'b:files', 'b:filecount', 'b:dirs', 'b:dircount')
+ cd -
+ let dirs=b:dirs
+ let dcount=b:dircount
+ unlet b:files b:filecount b:dirs b:dircount
+ while dcount > 0
+ let dname = substitute(dirs, '\(\( \|\f\|:\)*\).*', '\1', '')
+ let edname = escape(dname, ' ')
+ let dirs = substitute(dirs, '\( \|\f\|:\)*.\(.*\)', '\2', '')
+ let line=s:GenerateEntry(1, line + 1, dname, a:absolute_dir.'/'.edname, edname, '', '', a:filter, a:foldlev+1, a:sort)
+ let dcount=dcount-1
+ endwhile
+ endif
+ return line+1
+ endfunction " >>>
+ " s:DoEntryFromDir(line, name, absolute_dir, dir, c_d, filter_directive, filter, foldlev, sort) <<<
+ " Generate the fold from the directory hierarchy (if recursive), then
+ " fill it in with RefreshEntriesFromDir()
+ function! s:DoEntryFromDir(recursive, line, name, absolute_dir, dir, c_d, filter_directive, filter, foldlev, sort)
+ call s:GenerateEntry(a:recursive, a:line, a:name, escape(a:absolute_dir, ' '), escape(a:dir, ' '), escape(a:c_d, ' '), a:filter_directive, a:filter, a:foldlev, a:sort)
+ normal! j
+ call s:RefreshEntriesFromDir(1)
+ endfunction ">>>
+ " s:CreateEntriesFromDir(recursive) <<<
+ " Prompts user for information and then calls s:DoEntryFromDir()
+ function! s:CreateEntriesFromDir(recursive)
+ " Save a mark for the current cursor position
+ normal! mk
+ let line=line('.')
+ let name = inputdialog('Enter the Name of the Entry: ')
+ if strlen(name) == 0
+ return
+ endif
+ let foldlev=foldlevel(line)
+ if (foldclosed(line) != -1) || (getline(line) =~ '}')
+ let foldlev=foldlev - 1
+ endif
+ let absolute = (foldlev <= 0)?'Absolute ': ''
+ let home=''
+ let filter='*'
+ if (match(g:proj_flags, '\Cb') != -1) && has('browse')
+ " Note that browse() is inconsistent: On Win32 you can't select a
+ " directory, and it gives you a relative path.
+ let dir = browse(0, 'Enter the '.absolute.'Directory to Load: ', '', '')
+ let dir = fnamemodify(dir, ':p')
+ else
+ let dir = inputdialog('Enter the '.absolute.'Directory to Load: ', '')
+ endif
+ if (dir[strlen(dir)-1] == '/') || (dir[strlen(dir)-1] == '\\')
+ let dir=strpart(dir, 0, strlen(dir)-1) " Remove trailing / or \
+ endif
+ let dir = substitute(dir, '^\~', $HOME, 'g')
+ if (foldlev > 0)
+ let parent_directive=s:RecursivelyConstructDirectives(line)
+ let filter = s:GetFilter(parent_directive, '*')
+ let home=s:GetHome(parent_directive, '')
+ if home[strlen(home)-1] != '/' && home[strlen(home)-1] != '\\'
+ let home=home.'/'
+ endif
+ unlet parent_directive
+ if s:IsAbsolutePath(dir)
+ " It is not a relative path Try to make it relative
+ let hend=matchend(dir, '\C'.glob(home))
+ if hend != -1
+ let dir=strpart(dir, hend) " The directory can be a relative path
+ else
+ let home=""
+ endif
+ endif
+ endif
+ if strlen(home.dir) == 0
+ return
+ endif
+ if !isdirectory(home.dir)
+ if has("unix")
+ silent exec '!mkdir '.home.dir.' > /dev/null'
+ else
+ call confirm('"'.home.dir.'" is not a valid directory.', "&OK", 1)
+ return
+ endif
+ endif
+ let c_d = inputdialog('Enter the CD parameter: ', '')
+ let filter_directive = inputdialog('Enter the File Filter: ', '')
+ if strlen(filter_directive) != 0
+ let filter = filter_directive
+ endif
+ " If I'm on a closed fold, go to the bottom of it
+ if foldclosedend(line) != -1
+ let line = foldclosedend(line)
+ endif
+ let foldlev = foldlevel(line)
+ " If we're at the end of a fold . . .
+ if getline(line) =~ '}'
+ let foldlev = foldlev - 1 " . . . decrease the indentation by 1.
+ endif
+ " Do the work
+ call s:DoEntryFromDir(a:recursive, line, name, home.dir, dir, c_d, filter_directive, filter, foldlev, 0)
+ " Restore the cursor position
+ normal! `k
+ endfunction ">>>
+ " s:RefreshEntriesFromDir(recursive) <<<
+ " Finds metadata at the top of the fold, and then replaces all files
+ " with the contents of the directory. Works recursively if recursive is 1.
+ function! s:RefreshEntriesFromDir(recursive)
+ if foldlevel('.') == 0
+ echo 'Nothing to refresh.'
+ return
+ endif
+ " Open the fold.
+ if getline('.') =~ '}'
+ normal! zo[z
+ else
+ normal! zo]z[z
+ endif
+ let just_a_fold=0
+ let infoline = s:RecursivelyConstructDirectives(line('.'))
+ let immediate_infoline = getline('.')
+ if strlen(substitute(immediate_infoline, '[^=]*=\(\(\f\|:\|\\ \)*\).*', '\1', '')) == strlen(immediate_infoline)
+ let just_a_fold = 1
+ endif
+ " Extract the home directory of the fold
+ let home = s:GetHome(infoline, '')
+ if home == ''
+ " No Match. This means that this is just a label with no
+ " directory entry.
+ if a:recursive == 0
+ return " We're done--nothing to do
+ endif
+ " Mark that it is just a fold, so later we don't delete filenames
+ " that aren't there.
+ let just_a_fold = 1
+ endif
+ if just_a_fold == 0
+ " Extract the filter between quotes (we don't care what CD is).
+ let filter = s:GetFilter(infoline, '*')
+ " Extract the description (name) of the fold
+ let name = substitute(infoline, '^[#\t ]*\([^=]*\)=.*', '\1', '')
+ if strlen(name) == strlen(infoline)
+ return " If there's no name, we're done.
+ endif
+ if (home == '') || (name == '')
+ return
+ endif
+ " Extract the flags
+ let flags = s:GetFlags(immediate_infoline)
+ let sort = (match(g:proj_flags, '\CS') != -1)
+ if flags != ''
+ if match(flags, '\Cr') != -1
+ " If the flags do not contain r (refresh), then treat it just
+ " like a fold
+ let just_a_fold = 1
+ endif
+ if match(flags, '\CS') != -1
+ let sort = 1
+ endif
+ if match(flags, '\Cs') != -1
+ let sort = 0
+ endif
+ else
+ let flags=''
+ endif
+ endif
+ " Move to the first non-fold boundary line
+ normal! j
+ " Delete filenames until we reach the end of the fold
+ while getline('.') !~ '}'
+ if line('.') == line('$')
+ break
+ endif
+ if getline('.') !~ '{'
+ " We haven't reached a sub-fold, so delete what's there.
+ if (just_a_fold == 0) && (getline('.') !~ '^\s*#') && (getline('.') !~ '#.*pragma keep')
+ d _
+ else
+ " Skip lines only in a fold and comment lines
+ normal! j
+ endif
+ else
+ " We have reached a sub-fold. If we're doing recursive, then
+ " call this function again. If not, find the end of the fold.
+ if a:recursive == 1
+ call s:RefreshEntriesFromDir(1)
+ normal! ]zj
+ else
+ if foldclosed('.') == -1
+ normal! zc
+ endif
+ normal! j
+ endif
+ endif
+ endwhile
+ if just_a_fold == 0
+ " We're not just in a fold, and we have deleted all the filenames.
+ " Now it is time to regenerate what is in the directory.
+ if !isdirectory(glob(home))
+ call confirm('"'.home.'" is not a valid directory.', "&OK", 1)
+ else
+ let foldlev=foldlevel('.')
+ " T flag. Thanks Tomas Z.
+ if (match(flags, '\Ct') != -1) || ((match(g:proj_flags, '\CT') == -1) && (match(flags, '\CT') == -1))
+ " Go to the top of the fold (force other folds to the
+ " bottom)
+ normal! [z
+ normal! j
+ " Skip any comments
+ while getline('.') =~ '^\s*#'
+ normal! j
+ endwhile
+ endif
+ normal! k
+ let cwd=getcwd()
+ let spaces=strpart(' ', 0, foldlev)
+ exec 'cd '.home
+ if match(g:proj_flags, '\Ci') != -1
+ echon home."\r"
+ endif
+ call s:VimDirListing(filter, spaces, "\n", 'b:files', 'b:filecount', 'b:dirs', 'b:dircount')
+ if b:filecount > 0
+ normal! mk
+ silent! put =b:files
+ normal! `kj
+ if sort
+ call s:SortR(line('.'), line('.') + b:filecount - 1)
+ endif
+ else
+ normal! j
+ endif
+ unlet b:files b:filecount b:dirs b:dircount
+ exec 'cd '.cwd
+ endif
+ endif
+ " Go to the top of the refreshed fold.
+ normal! [z
+ endfunction ">>>
+ " s:MoveUp() <<<
+ " Moves the entity under the cursor up a line.
+ function! s:MoveUp()
+ let lineno=line('.')
+ if lineno == 1
+ return
+ endif
+ let fc=foldclosed('.')
+ let a_reg=@a
+ if lineno == line('$')
+ normal! "add"aP
+ else
+ normal! "addk"aP
+ endif
+ let @a=a_reg
+ if fc != -1
+ normal! zc
+ endif
+ endfunction ">>>
+ " s:MoveDown() <<<
+ " Moves the entity under the cursor down a line.
+ function! s:MoveDown()
+ let fc=foldclosed('.')
+ let a_reg=@a
+ normal! "add"ap
+ let @a=a_reg
+ if (fc != -1) && (foldclosed('.') == -1)
+ normal! zc
+ endif
+ endfunction " >>>
+ " s:DisplayInfo() <<<
+ " Displays filename and current working directory when i (info) is in
+ " the flags.
+ function! s:DisplayInfo()
+ if match(g:proj_flags, '\Ci') != -1
+ echo 'file: '.expand('%').', cwd: '.getcwd().', lines: '.line('$')
+ endif
+ endfunction ">>>
+ " s:SetupAutoCommand(cwd) <<<
+ " Sets up an autocommand to ensure that the cwd is set to the one
+ " desired for the fold regardless. :lcd only does this on a per-window
+ " basis, not a per-buffer basis.
+ function! s:SetupAutoCommand(cwd)
+ if !exists("b:proj_has_autocommand")
+ let b:proj_cwd_save = escape(getcwd(), ' ')
+ let b:proj_has_autocommand = 1
+ let bufname=escape(substitute(expand('%:p', 0), '\\', '/', 'g'), ' ')
+ exec 'au BufEnter '.bufname." let b:proj_cwd_save=escape(getcwd(), ' ') | cd ".a:cwd
+ exec 'au BufLeave '.bufname.' exec "cd ".b:proj_cwd_save'
+ exec 'au BufWipeout '.bufname.' au! * '.bufname
+ endif
+ endfunction ">>>
+ " s:SetupScriptAutoCommand(bufcmd, script) <<<
+ " Sets up an autocommand to run the scriptin script.
+ function! s:SetupScriptAutoCommand(bufcmd, script)
+ if !exists("b:proj_has_".a:bufcmd)
+ let b:proj_has_{a:bufcmd} = 1
+ exec 'au '.a:bufcmd.' '.escape(substitute(expand('%:p', 0), '\\', '/', 'g'), ' ').' source '.a:script
+ endif
+ endfunction " >>>
+ " s:DoEnsurePlacementSize_au() <<<
+ " Ensure that the Project window is on the left of the window and has
+ " the correct size. Only called from an autocommand
+ function! s:DoEnsurePlacementSize_au()
+ if (winbufnr(0) != g:proj_running) || (winnr() != 1)
+ if exists("g:proj_doinghelp")
+ if g:proj_doinghelp > 0
+ let g:proj_doinghelp = g:proj_doinghelp - 1
+ return
+ endif
+ unlet g:proj_doinghelp
+ return
+ endif
+ exec b:proj_locate_command
+ endif
+ exec b:proj_resize_command
+ endfunction ">>>
+ " s:Spawn(number) <<<
+ " Spawn an external command on the file
+ function! s:Spawn(number)
+ echo | if exists("g:proj_run".a:number)
+ let fname=getline('.')
+ if fname!~'{\|}'
+ let fname=substitute(fname, '\s*#.*', '', '')
+ let fname=substitute(fname, '^\s*\(.*\)\s*', '\1', '')
+ if fname == '' | return | endif
+ let parent_infoline = s:RecursivelyConstructDirectives(line('.'))
+ let home=expand(s:GetHome(parent_infoline, ''))
+ let c_d=expand(s:GetCd(parent_infoline, ''))
+ let command=substitute(g:proj_run{a:number}, '%%', "\010", 'g')
+ let command=substitute(command, '%f', escape(home.'/'.fname, '\'), 'g')
+ let command=substitute(command, '%F', substitute(escape(home.'/'.fname, '\'), ' ', '\\\\ ', 'g'), 'g')
+ let command=substitute(command, '%s', escape(home.'/'.fname, '\'), 'g')
+ let command=substitute(command, '%n', escape(fname, '\'), 'g')
+ let command=substitute(command, '%N', substitute(fname, ' ', '\\\\ ', 'g'), 'g')
+ let command=substitute(command, '%h', escape(home, '\'), 'g')
+ let command=substitute(command, '%H', substitute(escape(home, '\'), ' ', '\\\\ ', 'g'), 'g')
+ if c_d != ''
+ if c_d == home
+ let percent_r='.'
+ else
+ let percent_r=substitute(home, escape(c_d.'/', '\'), '', 'g')
+ endif
+ else
+ let percent_r=home
+ endif
+ let command=substitute(command, '%r', percent_r, 'g')
+ let command=substitute(command, '%R', substitute(percent_r, ' ', '\\\\ ', 'g'), 'g')
+ let command=substitute(command, '%d', escape(c_d, '\'), 'g')
+ let command=substitute(command, '%D', substitute(escape(c_d, '\'), ' ', '\\\\ ', 'g'), 'g')
+ let command=substitute(command, "\010", '%', 'g')
+ exec command
+ endif
+ endif
+ endfunction ">>>
+ " s:ListSpawn(varnamesegment) <<<
+ " List external commands
+ function! s:ListSpawn(varnamesegment)
+ let number = 1
+ while number < 10
+ if exists("g:proj_run".a:varnamesegment.number)
+ echohl LineNr | echo number.':' | echohl None | echon ' '.substitute(escape(g:proj_run{a:varnamesegment}{number}, '\'), "\n", '\\n', 'g')
+ else
+ echohl LineNr | echo number.':' | echohl None
+ endif
+ let number=number + 1
+ endwhile
+ endfunction ">>>
+ " s:FindFoldTop(line) <<<
+ " Return the line number of the directive line
+ function! s:FindFoldTop(line)
+ let lineno=a:line
+ if getline(lineno) =~ '}'
+ let lineno = lineno - 1
+ endif
+ while getline(lineno) !~ '{' && lineno > 1
+ if getline(lineno) =~ '}'
+ let lineno=s:FindFoldTop(lineno)
+ endif
+ let lineno = lineno - 1
+ endwhile
+ return lineno
+ endfunction ">>>
+ " s:FindFoldBottom(line) <<<
+ " Return the line number of the directive line
+ function! s:FindFoldBottom(line)
+ let lineno=a:line
+ if getline(lineno) =~ '{'
+ let lineno=lineno + 1
+ endif
+ while getline(lineno) !~ '}' && lineno < line('$')
+ if getline(lineno) =~ '{'
+ let lineno=s:FindFoldBottom(lineno)
+ endif
+ let lineno = lineno + 1
+ endwhile
+ return lineno
+ endfunction ">>>
+ " s:LoadAll(recurse, line) <<<
+ " Load all files in a project
+ function! s:LoadAll(recurse, line)
+ let b:loadcount=0
+ function! s:SpawnExec(infoline, fname, lineno, data)
+ if s:OpenEntry2(a:lineno, a:infoline, a:fname, 'e')
+ wincmd p
+ let b:loadcount=b:loadcount+1
+ echon b:loadcount."\r"
+ if getchar(0) != 0
+ let b:stop_everything=1
+ endif
+ endif
+ endfunction
+ call Project_ForEach(a:recurse, line('.'), "*<SID>SpawnExec", 0, '^\(.*l\)\@!')
+ delfunction s:SpawnExec
+ echon b:loadcount." Files Loaded\r"
+ unlet b:loadcount
+ if exists("b:stop_everything") | unlet b:stop_everything | endif
+ endfunction ">>>
+ " s:WipeAll(recurse, line) <<<
+ " Wipe all files in a project
+ function! s:WipeAll(recurse, line)
+ let b:wipecount=0
+ let b:totalcount=0
+ function! s:SpawnExec(home, c_d, fname, lineno, data)
+ let fname=escape(a:fname, ' ')
+ if s:IsAbsolutePath(fname)
+ let fname=fnamemodify(fname, ':n') " :n is coming, won't break anything now
+ else
+ let fname=fnamemodify(a:home.'/'.fname, ':n') " :n is coming, won't break anything now
+ endif
+ let b:totalcount=b:totalcount+1
+ let fname=substitute(fname, '^\~', $HOME, 'g')
+ if bufloaded(substitute(fname, '\\ ', ' ', 'g'))
+ if getbufvar(fname.'\>', '&modified') == 1
+ exec 'sb '.fname
+ wincmd L
+ w
+ wincmd p
+ endif
+ let b:wipecount=b:wipecount+1
+ exec 'bwipe! '.fname
+ endif
+ if b:totalcount % 5 == 0
+ echon b:wipecount.' of '.b:totalcount."\r"
+ redraw
+ endif
+ if getchar(0) != 0
+ let b:stop_everything=1
+ endif
+ endfunction
+ call Project_ForEach(a:recurse, line('.'), "<SID>SpawnExec", 0, '^\(.*w\)\@!')
+ delfunction s:SpawnExec
+ echon b:wipecount.' of '.b:totalcount." Files Wiped\r"
+ unlet b:wipecount b:totalcount
+ if exists("b:stop_everything") | unlet b:stop_everything | endif
+ endfunction ">>>
+ " s:LoadAllSplit(recurse, line) <<<
+ " Load all files in a project using split windows.
+ " Contributed by A. Harrison
+ function! s:LoadAllSplit(recurse, line)
+ let b:loadcount=0
+ function! s:SpawnExec(infoline, fname, lineno, data)
+ let winNr = winnr() "get ProjectWindow number
+ if s:OpenEntry2(a:lineno, a:infoline, a:fname, 'sp')
+ exec winNr."wincmd w"
+ let b:loadcount=b:loadcount+1
+ echon b:loadcount."\r"
+ if getchar(0) != 0
+ let b:stop_everything=1
+ endif
+ endif
+ endfunction
+ call Project_ForEach(a:recurse, line('.'), "*<SID>SpawnExec", 0, '^\(.*l\)\@!')
+ delfunction s:SpawnExec
+ echon b:loadcount." Files Loaded\r"
+ unlet b:loadcount
+ if exists("b:stop_everything") | unlet b:stop_everything | endif
+ endfunction ">>>
+ " s:GrepAll(recurse, lineno, pattern) <<<
+ " Grep all files in a project, optionally recursively
+ function! s:GrepAll(recurse, lineno, pattern)
+ cunmap <buffer> help
+ let pattern=(a:pattern[0] == '')?input("GREP options and pattern: "):a:pattern
+ cnoremap <buffer> help let g:proj_doinghelp = 1<CR>:help
+ if pattern[0] == ''
+ return
+ endif
+ let b:escape_spaces=1
+ let fnames=Project_GetAllFnames(a:recurse, a:lineno, ' ')
+ unlet b:escape_spaces
+ cclose " Make sure grep window is closed
+ call s:DoSetupAndSplit()
+ if match(g:proj_flags, '\Cv') == -1
+ silent! exec 'silent! grep '.pattern.' '.fnames
+ if v:shell_error != 0
+ echo 'GREP error. Perhaps there are too many filenames.'
+ else
+ copen
+ endif
+ else
+ silent! exec 'silent! vimgrep '.pattern.' '.fnames
+ copen
+ endif
+ endfunction ">>>
+ " GetXXX Functions <<<
+ function! s:GetHome(info, parent_home)
+ " Thanks to Adam Montague for pointing out the need for @ in urls.
+ let home=substitute(a:info, '^[^=]*=\(\(\\ \|\f\|:\|@\)\+\).*', '\1', '')
+ if strlen(home) == strlen(a:info)
+ let home=substitute(a:info, '.\{-}"\(.\{-}\)".*', '\1', '')
+ if strlen(home) != strlen(a:info) | let home=escape(home, ' ') | endif
+ endif
+ if strlen(home) == strlen(a:info)
+ let home=a:parent_home
+ elseif home=='.'
+ let home=a:parent_home
+ elseif !s:IsAbsolutePath(home)
+ let home=a:parent_home.'/'.home
+ endif
+ return home
+ endfunction
+ function! s:GetFilter(info, parent_filter)
+ let filter = substitute(a:info, '.*\<filter="\([^"]*\).*', '\1', '')
+ if strlen(filter) == strlen(a:info) | let filter = a:parent_filter | endif
+ return filter
+ endfunction
+ function! s:GetCd(info, home)
+ let c_d=substitute(a:info, '.*\<CD=\(\(\\ \|\f\|:\)\+\).*', '\1', '')
+ if strlen(c_d) == strlen(a:info)
+ let c_d=substitute(a:info, '.*\<CD="\(.\{-}\)".*', '\1', '')
+ if strlen(c_d) != strlen(a:info) | let c_d=escape(c_d, ' ') | endif
+ endif
+ if strlen(c_d) == strlen(a:info)
+ let c_d=''
+ elseif c_d == '.'
+ let c_d = a:home
+ elseif !s:IsAbsolutePath(c_d)
+ let c_d = a:home.'/'.c_d
+ endif
+ return c_d
+ endfunction
+ function! s:GetScriptin(info, home)
+ let scriptin = substitute(a:info, '.*\<in=\(\(\\ \|\f\|:\)\+\).*', '\1', '')
+ if strlen(scriptin) == strlen(a:info)
+ let scriptin=substitute(a:info, '.*\<in="\(.\{-}\)".*', '\1', '')
+ if strlen(scriptin) != strlen(a:info) | let scriptin=escape(scriptin, ' ') | endif
+ endif
+ if strlen(scriptin) == strlen(a:info) | let scriptin='' | else
+ if !s:IsAbsolutePath(scriptin) | let scriptin=a:home.'/'.scriptin | endif | endif
+ return scriptin
+ endfunction
+ function! s:GetScriptout(info, home)
+ let scriptout = substitute(a:info, '.*\<out=\(\(\\ \|\f\|:\)\+\).*', '\1', '')
+ if strlen(scriptout) == strlen(a:info)
+ let scriptout=substitute(a:info, '.*\<out="\(.\{-}\)".*', '\1', '')
+ if strlen(scriptout) != strlen(a:info) | let scriptout=escape(scriptout, ' ') | endif
+ endif
+ if strlen(scriptout) == strlen(a:info) | let scriptout='' | else
+ if !s:IsAbsolutePath(scriptout) | let scriptout=a:home.'/'.scriptout | endif | endif
+ return scriptout
+ endfunction
+ function! s:GetFlags(info)
+ let flags=substitute(a:info, '.*\<flags=\([^ {]*\).*', '\1', '')
+ if (strlen(flags) == strlen(a:info))
+ let flags=''
+ endif
+ return flags
+ endfunction ">>>
+ " Project_GetAllFnames(recurse, lineno, separator) <<<
+ " Grep all files in a project, optionally recursively
+ function! Project_GetAllFnames(recurse, lineno, separator)
+ let b:fnamelist=''
+ function! s:SpawnExec(home, c_d, fname, lineno, data)
+ if exists('b:escape_spaces')
+ let fname=escape(a:fname, ' ')
+ else
+ let fname=a:fname
+ endif
+ if !s:IsAbsolutePath(a:fname)
+ let fname=a:home.'/'.fname
+ endif
+ let b:fnamelist=b:fnamelist.a:data.fname
+ endfunction
+ call Project_ForEach(a:recurse, line('.'), "<SID>SpawnExec", a:separator, '')
+ delfunction s:SpawnExec
+ let retval=b:fnamelist
+ unlet b:fnamelist
+ return retval
+ endfunction ">>>
+ " Project_GetAllFnames(recurse, lineno, separator) <<<
+ " Grep all files in a project, optionally recursively
+ function! Project_GetFname(line)
+ if (foldlevel(a:line) == 0)
+ return ''
+ endif
+ let fname=substitute(getline(a:line), '\s*#.*', '', '') " Get rid of comments and whitespace before comment
+ let fname=substitute(fname, '^\s*\(.*\)', '\1', '') " Get rid of leading whitespace
+ if strlen(fname) == 0
+ return '' " The line is blank. Do nothing.
+ endif
+ if s:IsAbsolutePath(fname)
+ return fname
+ endif
+ let infoline = s:RecursivelyConstructDirectives(a:line)
+ return s:GetHome(infoline, '').'/'.fname
+ endfunction ">>>
+ " Project_ForEach(recurse, lineno, cmd, data, match) <<<
+ " Grep all files in a project, optionally recursively
+ function! Project_ForEach(recurse, lineno, cmd, data, match)
+ let info=s:RecursivelyConstructDirectives(a:lineno)
+ let lineno=s:FindFoldTop(a:lineno) + 1
+ let flags=s:GetFlags(getline(lineno - 1))
+ if (flags == '') || (a:match=='') || (match(flags, a:match) != -1)
+ call s:Project_ForEachR(a:recurse, lineno, info, a:cmd, a:data, a:match)
+ endif
+ endfunction
+ function! s:Project_ForEachR(recurse, lineno, info, cmd, data, match)
+ let home=s:GetHome(a:info, '')
+ let c_d=s:GetCd(a:info, home)
+ let scriptin = s:GetScriptin(a:info, home)
+ let scriptout = s:GetScriptout(a:info, home)
+ let filter = s:GetFilter(a:info, '')
+ let lineno = a:lineno
+ let curline=getline(lineno)
+ while (curline !~ '}') && (curline < line('$'))
+ if exists("b:stop_everything") && b:stop_everything | return 0 | endif
+ if curline =~ '{'
+ if a:recurse
+ let flags=s:GetFlags(curline)
+ if (flags == '') || (a:match=='') || (match(flags, a:match) != -1)
+ let this_home=s:GetHome(curline, home)
+ let this_cd=s:GetCd(curline, this_home)
+ if this_cd=='' | let this_cd=c_d | endif
+ let this_scriptin=s:GetScriptin(curline, this_home)
+ if this_scriptin == '' | let this_scriptin=scriptin | endif
+ let this_scriptout=s:GetScriptin(curline, this_home)
+ if this_scriptout == '' | let this_scriptout=scriptout | endif
+ let this_filter=s:GetFilter(curline, filter)
+ let lineno=s:Project_ForEachR(1, lineno+1,
+ \s:ConstructInfo(this_home, this_cd, this_scriptin, this_scriptout, flags, this_filter), a:cmd, a:data, a:match)
+ else
+ let lineno=s:FindFoldBottom(lineno)
+ endif
+ else
+ let lineno=s:FindFoldBottom(lineno)
+ endif
+ else
+ let fname=substitute(curline, '\s*#.*', '', '')
+ let fname=substitute(fname, '^\s*\(.*\)', '\1', '')
+ if (strlen(fname) != strlen(curline)) && (fname[0] != '')
+ if a:cmd[0] == '*'
+ call {strpart(a:cmd, 1)}(a:info, fname, lineno, a:data)
+ else
+ call {a:cmd}(home, c_d, fname, lineno, a:data)
+ endif
+ endif
+ endif
+ let lineno=lineno + 1
+ let curline=getline(lineno)
+ endwhile
+ return lineno
+ endfunction ">>>
+ " s:SpawnAll(recurse, number) <<<
+ " Spawn an external command on the files of a project
+ function! s:SpawnAll(recurse, number)
+ echo | if exists("g:proj_run_fold".a:number)
+ if g:proj_run_fold{a:number}[0] == '*'
+ function! s:SpawnExec(home, c_d, fname, lineno, data)
+ let command=substitute(strpart(g:proj_run_fold{a:data}, 1), '%s', escape(a:fname, ' \'), 'g')
+ let command=substitute(command, '%f', escape(a:fname, '\'), 'g')
+ let command=substitute(command, '%h', escape(a:home, '\'), 'g')
+ let command=substitute(command, '%d', escape(a:c_d, '\'), 'g')
+ let command=substitute(command, '%F', substitute(escape(a:fname, '\'), ' ', '\\\\ ', 'g'), 'g')
+ exec command
+ endfunction
+ call Project_ForEach(a:recurse, line('.'), "<SID>SpawnExec", a:number, '.')
+ delfunction s:SpawnExec
+ else
+ let info=s:RecursivelyConstructDirectives(line('.'))
+ let home=s:GetHome(info, '')
+ let c_d=s:GetCd(info, '')
+ let b:escape_spaces=1
+ let fnames=Project_GetAllFnames(a:recurse, line('.'), ' ')
+ unlet b:escape_spaces
+ let command=substitute(g:proj_run_fold{a:number}, '%f', substitute(escape(fnames, '\'), '\\ ', ' ', 'g'), 'g')
+ let command=substitute(command, '%s', escape(fnames, '\'), 'g')
+ let command=substitute(command, '%h', escape(home, '\'), 'g')
+ let command=substitute(command, '%d', escape(c_d, '\'), 'g')
+ let command=substitute(command, '%F', escape(fnames, '\'), 'g')
+ exec command
+ if v:shell_error != 0
+ echo 'Shell error. Perhaps there are too many filenames.'
+ endif
+ endif
+ endif
+ endfunction ">>>
+ if !exists("g:proj_running")
+ " s:DoProjectOnly(void) <<<
+ " Make the file window the only one.
+ function! s:DoProjectOnly()
+ if winbufnr(0) != g:proj_running
+ let lzsave=&lz
+ set lz
+ only
+ Project
+ silent! wincmd p
+ let &lz=lzsave
+ unlet lzsave
+ endif
+ endfunction
+ " >>>
+
+ " Mappings <<<
+ nnoremap <buffer> <silent> <Return> \|:call <SID>DoFoldOrOpenEntry('', 'e')<CR>
+ nnoremap <buffer> <silent> <S-Return> \|:call <SID>DoFoldOrOpenEntry('', 'sp')<CR>
+ nnoremap <buffer> <silent> <C-Return> \|:call <SID>DoFoldOrOpenEntry('silent! only', 'e')<CR>
+ nnoremap <buffer> <silent> <LocalLeader>T \|:call <SID>DoFoldOrOpenEntry('', 'tabe')<CR>
+ nmap <buffer> <silent> <LocalLeader>s <S-Return>
+ nnoremap <buffer> <silent> <LocalLeader>S \|:call <SID>LoadAllSplit(0, line('.'))<CR>
+ nmap <buffer> <silent> <LocalLeader>o <C-Return>
+ nnoremap <buffer> <silent> <LocalLeader>i :echo <SID>RecursivelyConstructDirectives(line('.'))<CR>
+ nnoremap <buffer> <silent> <LocalLeader>I :echo Project_GetFname(line('.'))<CR>
+ nmap <buffer> <silent> <M-CR> <Return><C-W>p
+ nmap <buffer> <silent> <LocalLeader>v <M-CR>
+ nnoremap <buffer> <silent> <LocalLeader>l \|:call <SID>LoadAll(0, line('.'))<CR>
+ nnoremap <buffer> <silent> <LocalLeader>L \|:call <SID>LoadAll(1, line('.'))<CR>
+ nnoremap <buffer> <silent> <LocalLeader>w \|:call <SID>WipeAll(0, line('.'))<CR>
+ nnoremap <buffer> <silent> <LocalLeader>W \|:call <SID>WipeAll(1, line('.'))<CR>
+ nnoremap <buffer> <silent> <LocalLeader>W \|:call <SID>WipeAll(1, line('.'))<CR>
+ nnoremap <buffer> <silent> <LocalLeader>g \|:call <SID>GrepAll(0, line('.'), "")<CR>
+ nnoremap <buffer> <silent> <LocalLeader>G \|:call <SID>GrepAll(1, line('.'), "")<CR>
+ nnoremap <buffer> <silent> <2-LeftMouse> \|:call <SID>DoFoldOrOpenEntry('', 'e')<CR>
+ nnoremap <buffer> <silent> <S-2-LeftMouse> \|:call <SID>DoFoldOrOpenEntry('', 'sp')<CR>
+ nnoremap <buffer> <silent> <M-2-LeftMouse> <M-CR>
+ nnoremap <buffer> <silent> <S-LeftMouse> <LeftMouse>
+ nmap <buffer> <silent> <C-2-LeftMouse> <C-Return>
+ nnoremap <buffer> <silent> <C-LeftMouse> <LeftMouse>
+ nnoremap <buffer> <silent> <3-LeftMouse> <Nop>
+ nmap <buffer> <silent> <RightMouse> <space>
+ nmap <buffer> <silent> <2-RightMouse> <space>
+ nmap <buffer> <silent> <3-RightMouse> <space>
+ nmap <buffer> <silent> <4-RightMouse> <space>
+ nnoremap <buffer> <silent> <space> \|:silent exec 'vertical resize '.(match(g:proj_flags, '\Ct')!=-1 && winwidth('.') > g:proj_window_width?(g:proj_window_width):(winwidth('.') + g:proj_window_increment))<CR>
+ nnoremap <buffer> <silent> <C-Up> \|:silent call <SID>MoveUp()<CR>
+ nnoremap <buffer> <silent> <C-Down> \|:silent call <SID>MoveDown()<CR>
+ nmap <buffer> <silent> <LocalLeader><Up> <C-Up>
+ nmap <buffer> <silent> <LocalLeader><Down> <C-Down>
+ let k=1
+ while k < 10
+ exec 'nnoremap <buffer> <LocalLeader>'.k.' \|:call <SID>Spawn('.k.')<CR>'
+ exec 'nnoremap <buffer> <LocalLeader>f'.k.' \|:call <SID>SpawnAll(0, '.k.')<CR>'
+ exec 'nnoremap <buffer> <LocalLeader>F'.k.' \|:call <SID>SpawnAll(1, '.k.')<CR>'
+ let k=k+1
+ endwhile
+ nnoremap <buffer> <LocalLeader>0 \|:call <SID>ListSpawn("")<CR>
+ nnoremap <buffer> <LocalLeader>f0 \|:call <SID>ListSpawn("_fold")<CR>
+ nnoremap <buffer> <LocalLeader>F0 \|:call <SID>ListSpawn("_fold")<CR>
+ nnoremap <buffer> <silent> <LocalLeader>c :call <SID>CreateEntriesFromDir(0)<CR>
+ nnoremap <buffer> <silent> <LocalLeader>C :call <SID>CreateEntriesFromDir(1)<CR>
+ nnoremap <buffer> <silent> <LocalLeader>r :call <SID>RefreshEntriesFromDir(0)<CR>
+ nnoremap <buffer> <silent> <LocalLeader>R :call <SID>RefreshEntriesFromDir(1)<CR>
+ " For Windows users: same as \R
+ nnoremap <buffer> <silent> <F5> :call <SID>RefreshEntriesFromDir(1)<CR>
+ nnoremap <buffer> <silent> <LocalLeader>e :call <SID>OpenEntry(line('.'), '', '', 0)<CR>
+ nnoremap <buffer> <silent> <LocalLeader>E :call <SID>OpenEntry(line('.'), '', 'e', 1)<CR>
+ " The :help command stomps on the Project Window. Try to avoid that.
+ " This is not perfect, but it is alot better than without the mappings.
+ cnoremap <buffer> help let g:proj_doinghelp = 1<CR>:help
+ nnoremap <buffer> <F1> :let g:proj_doinghelp = 1<CR><F1>
+ " This is to avoid changing the buffer, but it is not fool-proof.
+ nnoremap <buffer> <silent> <C-^> <Nop>
+ "nnoremap <script> <Plug>ProjectOnly :let lzsave=&lz<CR>:set lz<CR><C-W>o:Project<CR>:silent! wincmd p<CR>:let &lz=lzsave<CR>:unlet lzsave<CR>
+ nnoremap <script> <Plug>ProjectOnly :call <SID>DoProjectOnly()<CR>
+ if match(g:proj_flags, '\Cm') != -1
+ if !hasmapto('<Plug>ProjectOnly')
+ nmap <silent> <unique> <C-W>o <Plug>ProjectOnly
+ nmap <silent> <unique> <C-W><C-O> <C-W>o
+ endif
+ endif " >>>
+ if filereadable(glob('~/.vimproject_mappings')) | source ~/.vimproject_mappings | endif
+ " Autocommands <<<
+ " Autocommands to clean up if we do a buffer wipe
+ " These don't work unless we substitute \ for / for Windows
+ let bufname=escape(substitute(expand('%:p', 0), '\\', '/', 'g'), ' ')
+ exec 'au BufWipeout '.bufname.' au! * '.bufname
+ exec 'au BufWipeout '.bufname.' unlet g:proj_running'
+ exec 'au BufWipeout '.bufname.' nunmap <C-W>o'
+ exec 'au BufWipeout '.bufname.' nunmap <C-W><C-O>'
+ " Autocommands to keep the window the specified size
+ exec 'au WinLeave '.bufname.' call s:DoEnsurePlacementSize_au()'
+ exec 'au BufEnter '.bufname.' call s:DoSetupAndSplit_au()'
+ au WinLeave * call s:RecordPrevBuffer_au()
+ " >>>
+ setlocal buflisted
+ let g:proj_running = bufnr(bufname.'\>')
+ if g:proj_running == -1
+ call confirm('Project/Vim error. Please Enter :Project again and report this bug.', "&OK", 1)
+ unlet g:proj_running
+ endif
+ setlocal nobuflisted
+ endif
+endfunction " >>>
+
+if exists(':Project') != 2
+ command -nargs=? -complete=file Project call <SID>Project('<args>')
+endif
+" Toggle Mapping
+if !exists("*<SID>DoToggleProject()") "<<<
+ function! s:DoToggleProject()
+ if !exists('g:proj_running') || bufwinnr(g:proj_running) == -1
+ Project
+ else
+ let g:proj_mywindow = winnr()
+ Project
+ hide
+ if(winnr() != g:proj_mywindow)
+ wincmd p
+ endif
+ unlet g:proj_mywindow
+ endif
+ endfunction
+endif ">>>
+nnoremap <script> <Plug>ToggleProject :call <SID>DoToggleProject()<CR>
+if exists('g:proj_flags') && (match(g:proj_flags, '\Cg') != -1)
+ if !hasmapto('<Plug>ToggleProject')
+ nmap <silent> <F12> <Plug>ToggleProject
+ endif
+endif
+
+finish
+
+" vim600: set foldmethod=marker foldmarker=<<<,>>> foldlevel=1:
diff --git a/modules/vim/vim/plugin/snipMate.vim b/modules/vim/vim/plugin/snipMate.vim
new file mode 100644
index 0000000..3efee2a
--- /dev/null
+++ b/modules/vim/vim/plugin/snipMate.vim
@@ -0,0 +1,247 @@
+" File: snipMate.vim
+" Author: Michael Sanders
+" Last Updated: July 13, 2009
+" Version: 0.83
+" Description: snipMate.vim implements some of TextMate's snippets features in
+" Vim. A snippet is a piece of often-typed text that you can
+" insert into your document using a trigger word followed by a "<tab>".
+"
+" For more help see snipMate.txt; you can do this by using:
+" :helptags ~/.vim/doc
+" :h snipMate.txt
+
+if exists('loaded_snips') || &cp || version < 700
+ finish
+endif
+let loaded_snips = 1
+if !exists('snips_author') | let snips_author = 'Me' | endif
+
+au BufRead,BufNewFile *.snippets\= set ft=snippet
+au FileType snippet setl noet fdm=indent
+
+let s:snippets = {} | let s:multi_snips = {}
+
+if !exists('snippets_dir')
+ let snippets_dir = substitute(globpath(&rtp, 'snippets/'), "\n", ',', 'g')
+endif
+
+fun! MakeSnip(scope, trigger, content, ...)
+ let multisnip = a:0 && a:1 != ''
+ let var = multisnip ? 's:multi_snips' : 's:snippets'
+ if !has_key({var}, a:scope) | let {var}[a:scope] = {} | endif
+ if !has_key({var}[a:scope], a:trigger)
+ let {var}[a:scope][a:trigger] = multisnip ? [[a:1, a:content]] : a:content
+ elseif multisnip | let {var}[a:scope][a:trigger] += [[a:1, a:content]]
+ else
+ echom 'Warning in snipMate.vim: Snippet '.a:trigger.' is already defined.'
+ \ .' See :h multi_snip for help on snippets with multiple matches.'
+ endif
+endf
+
+fun! ExtractSnips(dir, ft)
+ for path in split(globpath(a:dir, '*'), "\n")
+ if isdirectory(path)
+ let pathname = fnamemodify(path, ':t')
+ for snipFile in split(globpath(path, '*.snippet'), "\n")
+ call s:ProcessFile(snipFile, a:ft, pathname)
+ endfor
+ elseif fnamemodify(path, ':e') == 'snippet'
+ call s:ProcessFile(path, a:ft)
+ endif
+ endfor
+endf
+
+" Processes a single-snippet file; optionally add the name of the parent
+" directory for a snippet with multiple matches.
+fun s:ProcessFile(file, ft, ...)
+ let keyword = fnamemodify(a:file, ':t:r')
+ if keyword == '' | return | endif
+ try
+ let text = join(readfile(a:file), "\n")
+ catch /E484/
+ echom "Error in snipMate.vim: couldn't read file: ".a:file
+ endtry
+ return a:0 ? MakeSnip(a:ft, a:1, text, keyword)
+ \ : MakeSnip(a:ft, keyword, text)
+endf
+
+fun! ExtractSnipsFile(file, ft)
+ if !filereadable(a:file) | return | endif
+ let text = readfile(a:file)
+ let inSnip = 0
+ for line in text + ["\n"]
+ if inSnip && (line[0] == "\t" || line == '')
+ let content .= strpart(line, 1)."\n"
+ continue
+ elseif inSnip
+ call MakeSnip(a:ft, trigger, content[:-2], name)
+ let inSnip = 0
+ endif
+
+ if line[:6] == 'snippet'
+ let inSnip = 1
+ let trigger = strpart(line, 8)
+ let name = ''
+ let space = stridx(trigger, ' ') + 1
+ if space " Process multi snip
+ let name = strpart(trigger, space)
+ let trigger = strpart(trigger, 0, space - 1)
+ endif
+ let content = ''
+ endif
+ endfor
+endf
+
+fun! ResetSnippets()
+ let s:snippets = {} | let s:multi_snips = {} | let g:did_ft = {}
+endf
+
+let g:did_ft = {}
+fun! GetSnippets(dir, filetypes)
+ for ft in split(a:filetypes, '\.')
+ if has_key(g:did_ft, ft) | continue | endif
+ call s:DefineSnips(a:dir, ft, ft)
+ if ft == 'objc' || ft == 'cpp' || ft == 'cs'
+ call s:DefineSnips(a:dir, 'c', ft)
+ elseif ft == 'xhtml'
+ call s:DefineSnips(a:dir, 'html', 'xhtml')
+ endif
+ let g:did_ft[ft] = 1
+ endfor
+endf
+
+" Define "aliasft" snippets for the filetype "realft".
+fun s:DefineSnips(dir, aliasft, realft)
+ for path in split(globpath(a:dir, a:aliasft.'/')."\n".
+ \ globpath(a:dir, a:aliasft.'-*/'), "\n")
+ call ExtractSnips(path, a:realft)
+ endfor
+ for path in split(globpath(a:dir, a:aliasft.'.snippets')."\n".
+ \ globpath(a:dir, a:aliasft.'-*.snippets'), "\n")
+ call ExtractSnipsFile(path, a:realft)
+ endfor
+endf
+
+fun! TriggerSnippet()
+ if exists('g:SuperTabMappingForward')
+ if g:SuperTabMappingForward == "<tab>"
+ let SuperTabKey = "\<c-n>"
+ elseif g:SuperTabMappingBackward == "<tab>"
+ let SuperTabKey = "\<c-p>"
+ endif
+ endif
+
+ if pumvisible() " Update snippet if completion is used, or deal with supertab
+ if exists('SuperTabKey')
+ call feedkeys(SuperTabKey) | return ''
+ endif
+ call feedkeys("\<esc>a", 'n') " Close completion menu
+ call feedkeys("\<tab>") | return ''
+ endif
+
+ if exists('g:snipPos') | return snipMate#jumpTabStop(0) | endif
+
+ let word = matchstr(getline('.'), '\S\+\%'.col('.').'c')
+ for scope in [bufnr('%')] + split(&ft, '\.') + ['_']
+ let [trigger, snippet] = s:GetSnippet(word, scope)
+ " If word is a trigger for a snippet, delete the trigger & expand
+ " the snippet.
+ if snippet != ''
+ let col = col('.') - len(trigger)
+ sil exe 's/\V'.escape(trigger, '/.').'\%#//'
+ return snipMate#expandSnip(snippet, col)
+ endif
+ endfor
+
+ if exists('SuperTabKey')
+ call feedkeys(SuperTabKey)
+ return ''
+ endif
+ return "\<tab>"
+endf
+
+fun! BackwardsSnippet()
+ if exists('g:snipPos') | return snipMate#jumpTabStop(1) | endif
+
+ if exists('g:SuperTabMappingForward')
+ if g:SuperTabMappingBackward == "<s-tab>"
+ let SuperTabKey = "\<c-p>"
+ elseif g:SuperTabMappingForward == "<s-tab>"
+ let SuperTabKey = "\<c-n>"
+ endif
+ endif
+ if exists('SuperTabKey')
+ call feedkeys(SuperTabKey)
+ return ''
+ endif
+ return "\<s-tab>"
+endf
+
+" Check if word under cursor is snippet trigger; if it isn't, try checking if
+" the text after non-word characters is (e.g. check for "foo" in "bar.foo")
+fun s:GetSnippet(word, scope)
+ let word = a:word | let snippet = ''
+ while snippet == ''
+ if exists('s:snippets["'.a:scope.'"]["'.escape(word, '\"').'"]')
+ let snippet = s:snippets[a:scope][word]
+ elseif exists('s:multi_snips["'.a:scope.'"]["'.escape(word, '\"').'"]')
+ let snippet = s:ChooseSnippet(a:scope, word)
+ if snippet == '' | break | endif
+ else
+ if match(word, '\W') == -1 | break | endif
+ let word = substitute(word, '.\{-}\W', '', '')
+ endif
+ endw
+ if word == '' && a:word != '.' && stridx(a:word, '.') != -1
+ let [word, snippet] = s:GetSnippet('.', a:scope)
+ endif
+ return [word, snippet]
+endf
+
+fun s:ChooseSnippet(scope, trigger)
+ let snippet = []
+ let i = 1
+ for snip in s:multi_snips[a:scope][a:trigger]
+ let snippet += [i.'. '.snip[0]]
+ let i += 1
+ endfor
+ if i == 2 | return s:multi_snips[a:scope][a:trigger][0][1] | endif
+ let num = inputlist(snippet) - 1
+ return num == -1 ? '' : s:multi_snips[a:scope][a:trigger][num][1]
+endf
+
+fun! ShowAvailableSnips()
+ let line = getline('.')
+ let col = col('.')
+ let word = matchstr(getline('.'), '\S\+\%'.col.'c')
+ let words = [word]
+ if stridx(word, '.')
+ let words += split(word, '\.', 1)
+ endif
+ let matchlen = 0
+ let matches = []
+ for scope in [bufnr('%')] + split(&ft, '\.') + ['_']
+ let triggers = has_key(s:snippets, scope) ? keys(s:snippets[scope]) : []
+ if has_key(s:multi_snips, scope)
+ let triggers += keys(s:multi_snips[scope])
+ endif
+ for trigger in triggers
+ for word in words
+ if word == ''
+ let matches += [trigger] " Show all matches if word is empty
+ elseif trigger =~ '^'.word
+ let matches += [trigger]
+ let len = len(word)
+ if len > matchlen | let matchlen = len | endif
+ endif
+ endfor
+ endfor
+ endfor
+
+ " This is to avoid a bug with Vim when using complete(col - matchlen, matches)
+ " (Issue#46 on the Google Code snipMate issue tracker).
+ call setline(line('.'), substitute(line, repeat('.', matchlen).'\%'.col.'c', '', ''))
+ call complete(col, matches)
+ return ''
+endf
+" vim:noet:sw=4:ts=4:ft=vim
diff --git a/modules/vim/vim/plugin/startshell_mapping.vim.disabled b/modules/vim/vim/plugin/startshell_mapping.vim.disabled
new file mode 100644
index 0000000..e9704f4
--- /dev/null
+++ b/modules/vim/vim/plugin/startshell_mapping.vim.disabled
@@ -0,0 +1,36 @@
+"plugin from http://got-ravings.blogspot.com/2010/07/vim-pr0n-sample-nerd-tree-plugins.html
+"guard against sourcing the script twice
+if exists("g:loaded_nerdtree_start_shell_mapping")
+ finish
+endif
+let g:loaded_nerdtree_start_shell_mapping = 1
+
+"bind 'S' to NERDTreeStartShell()
+call NERDTreeAddKeyMap({
+ \ 'key': 'S',
+ \ 'callback': 'NERDTreeStartShell',
+ \ 'quickhelpText': 'start a :shell in this dir' })
+
+"change to the dir of the current node and start a :shell
+function! NERDTreeStartShell()
+
+ "grab the currently selected dir node (returns
+ "the parent dir if a file is selected)
+ let n = g:NERDTreeDirNode.GetSelected()
+
+ "save the cwd so we can restore it after the :shell exits
+ let oldCWD = getcwd()
+
+ try
+
+ ":lcd to to the selected dir and :shell out
+ exec 'lcd ' . n.path.str({'format': 'Cd'})
+ redraw!
+ shell
+
+ "make sure we restore the cwd to its original state
+ finally
+ exec 'lcd ' . oldCWD
+ endtry
+
+endfunction
diff --git a/modules/vim/vim/plugin/taglist.vim b/modules/vim/vim/plugin/taglist.vim
new file mode 100644
index 0000000..59901f6
--- /dev/null
+++ b/modules/vim/vim/plugin/taglist.vim
@@ -0,0 +1,4546 @@
+" File: taglist.vim
+" Author: Yegappan Lakshmanan (yegappan AT yahoo DOT com)
+" Version: 4.5
+" Last Modified: September 21, 2007
+" Copyright: Copyright (C) 2002-2007 Yegappan Lakshmanan
+" Permission is hereby granted to use and distribute this code,
+" with or without modifications, provided that this copyright
+" notice is copied with it. Like anything else that's free,
+" taglist.vim is provided *as is* and comes with no warranty of any
+" kind, either expressed or implied. In no event will the copyright
+" holder be liable for any damamges resulting from the use of this
+" software.
+"
+" The "Tag List" plugin is a source code browser plugin for Vim and provides
+" an overview of the structure of the programming language files and allows
+" you to efficiently browse through source code files for different
+" programming languages. You can visit the taglist plugin home page for more
+" information:
+"
+" http://vim-taglist.sourceforge.net
+"
+" You can subscribe to the taglist mailing list to post your questions
+" or suggestions for improvement or to report bugs. Visit the following
+" page for subscribing to the mailing list:
+"
+" http://groups.yahoo.com/group/taglist/
+"
+" For more information about using this plugin, after installing the
+" taglist plugin, use the ":help taglist" command.
+"
+" Installation
+" ------------
+" 1. Download the taglist.zip file and unzip the files to the $HOME/.vim
+" or the $HOME/vimfiles or the $VIM/vimfiles directory. This should
+" unzip the following two files (the directory structure should be
+" preserved):
+"
+" plugin/taglist.vim - main taglist plugin file
+" doc/taglist.txt - documentation (help) file
+"
+" Refer to the 'add-plugin', 'add-global-plugin' and 'runtimepath'
+" Vim help pages for more details about installing Vim plugins.
+" 2. Change to the $HOME/.vim/doc or $HOME/vimfiles/doc or
+" $VIM/vimfiles/doc directory, start Vim and run the ":helptags ."
+" command to process the taglist help file.
+" 3. If the exuberant ctags utility is not present in your PATH, then set the
+" Tlist_Ctags_Cmd variable to point to the location of the exuberant ctags
+" utility (not to the directory) in the .vimrc file.
+" 4. If you are running a terminal/console version of Vim and the
+" terminal doesn't support changing the window width then set the
+" 'Tlist_Inc_Winwidth' variable to 0 in the .vimrc file.
+" 5. Restart Vim.
+" 6. You can now use the ":TlistToggle" command to open/close the taglist
+" window. You can use the ":help taglist" command to get more
+" information about using the taglist plugin.
+"
+" ****************** Do not modify after this line ************************
+
+" Line continuation used here
+let s:cpo_save = &cpo
+set cpo&vim
+
+if !exists('loaded_taglist')
+ " First time loading the taglist plugin
+ "
+ " To speed up the loading of Vim, the taglist plugin uses autoload
+ " mechanism to load the taglist functions.
+ " Only define the configuration variables, user commands and some
+ " auto-commands and finish sourcing the file
+
+ " The taglist plugin requires the built-in Vim system() function. If this
+ " function is not available, then don't load the plugin.
+ if !exists('*system')
+ echomsg 'Taglist: Vim system() built-in function is not available. ' .
+ \ 'Plugin is not loaded.'
+ let loaded_taglist = 'no'
+ let &cpo = s:cpo_save
+ finish
+ endif
+
+ " Location of the exuberant ctags tool
+ if !exists('Tlist_Ctags_Cmd')
+ if executable('exuberant-ctags')
+ " On Debian Linux, exuberant ctags is installed
+ " as exuberant-ctags
+ let Tlist_Ctags_Cmd = 'exuberant-ctags'
+ elseif executable('exctags')
+ " On Free-BSD, exuberant ctags is installed as exctags
+ let Tlist_Ctags_Cmd = 'exctags'
+ elseif executable('ctags')
+ let Tlist_Ctags_Cmd = 'ctags'
+ elseif executable('ctags.exe')
+ let Tlist_Ctags_Cmd = 'ctags.exe'
+ elseif executable('tags')
+ let Tlist_Ctags_Cmd = 'tags'
+ else
+ echomsg 'Taglist: Exuberant ctags (http://ctags.sf.net) ' .
+ \ 'not found in PATH. Plugin is not loaded.'
+ " Skip loading the plugin
+ let loaded_taglist = 'no'
+ let &cpo = s:cpo_save
+ finish
+ endif
+ endif
+
+
+ " Automatically open the taglist window on Vim startup
+ if !exists('Tlist_Auto_Open')
+ let Tlist_Auto_Open = 0
+ endif
+
+ " When the taglist window is toggle opened, move the cursor to the
+ " taglist window
+ if !exists('Tlist_GainFocus_On_ToggleOpen')
+ let Tlist_GainFocus_On_ToggleOpen = 0
+ endif
+
+ " Process files even when the taglist window is not open
+ if !exists('Tlist_Process_File_Always')
+ let Tlist_Process_File_Always = 0
+ endif
+
+ if !exists('Tlist_Show_Menu')
+ let Tlist_Show_Menu = 0
+ endif
+
+ " Tag listing sort type - 'name' or 'order'
+ if !exists('Tlist_Sort_Type')
+ let Tlist_Sort_Type = 'order'
+ endif
+
+ " Tag listing window split (horizontal/vertical) control
+ if !exists('Tlist_Use_Horiz_Window')
+ let Tlist_Use_Horiz_Window = 0
+ endif
+
+ " Open the vertically split taglist window on the left or on the right
+ " side. This setting is relevant only if Tlist_Use_Horiz_Window is set to
+ " zero (i.e. only for vertically split windows)
+ if !exists('Tlist_Use_Right_Window')
+ let Tlist_Use_Right_Window = 0
+ endif
+
+ " Increase Vim window width to display vertically split taglist window.
+ " For MS-Windows version of Vim running in a MS-DOS window, this must be
+ " set to 0 otherwise the system may hang due to a Vim limitation.
+ if !exists('Tlist_Inc_Winwidth')
+ if (has('win16') || has('win95')) && !has('gui_running')
+ let Tlist_Inc_Winwidth = 0
+ else
+ let Tlist_Inc_Winwidth = 1
+ endif
+ endif
+
+ " Vertically split taglist window width setting
+ if !exists('Tlist_WinWidth')
+ let Tlist_WinWidth = 30
+ endif
+
+ " Horizontally split taglist window height setting
+ if !exists('Tlist_WinHeight')
+ let Tlist_WinHeight = 10
+ endif
+
+ " Display tag prototypes or tag names in the taglist window
+ if !exists('Tlist_Display_Prototype')
+ let Tlist_Display_Prototype = 0
+ endif
+
+ " Display tag scopes in the taglist window
+ if !exists('Tlist_Display_Tag_Scope')
+ let Tlist_Display_Tag_Scope = 1
+ endif
+
+ " Use single left mouse click to jump to a tag. By default this is disabled.
+ " Only double click using the mouse will be processed.
+ if !exists('Tlist_Use_SingleClick')
+ let Tlist_Use_SingleClick = 0
+ endif
+
+ " Control whether additional help is displayed as part of the taglist or
+ " not. Also, controls whether empty lines are used to separate the tag
+ " tree.
+ if !exists('Tlist_Compact_Format')
+ let Tlist_Compact_Format = 0
+ endif
+
+ " Exit Vim if only the taglist window is currently open. By default, this is
+ " set to zero.
+ if !exists('Tlist_Exit_OnlyWindow')
+ let Tlist_Exit_OnlyWindow = 0
+ endif
+
+ " Automatically close the folds for the non-active files in the taglist
+ " window
+ if !exists('Tlist_File_Fold_Auto_Close')
+ let Tlist_File_Fold_Auto_Close = 0
+ endif
+
+ " Close the taglist window when a tag is selected
+ if !exists('Tlist_Close_On_Select')
+ let Tlist_Close_On_Select = 0
+ endif
+
+ " Automatically update the taglist window to display tags for newly
+ " edited files
+ if !exists('Tlist_Auto_Update')
+ let Tlist_Auto_Update = 1
+ endif
+
+ " Automatically highlight the current tag
+ if !exists('Tlist_Auto_Highlight_Tag')
+ let Tlist_Auto_Highlight_Tag = 1
+ endif
+
+ " Automatically highlight the current tag on entering a buffer
+ if !exists('Tlist_Highlight_Tag_On_BufEnter')
+ let Tlist_Highlight_Tag_On_BufEnter = 1
+ endif
+
+ " Enable fold column to display the folding for the tag tree
+ if !exists('Tlist_Enable_Fold_Column')
+ let Tlist_Enable_Fold_Column = 1
+ endif
+
+ " Display the tags for only one file in the taglist window
+ if !exists('Tlist_Show_One_File')
+ let Tlist_Show_One_File = 0
+ endif
+
+ if !exists('Tlist_Max_Submenu_Items')
+ let Tlist_Max_Submenu_Items = 20
+ endif
+
+ if !exists('Tlist_Max_Tag_Length')
+ let Tlist_Max_Tag_Length = 10
+ endif
+
+ " Do not change the name of the taglist title variable. The winmanager
+ " plugin relies on this name to determine the title for the taglist
+ " plugin.
+ let TagList_title = "__Tag_List__"
+
+ " Taglist debug messages
+ let s:tlist_msg = ''
+
+ " Define the taglist autocommand to automatically open the taglist window
+ " on Vim startup
+ if g:Tlist_Auto_Open
+ autocmd VimEnter * nested call s:Tlist_Window_Check_Auto_Open()
+ endif
+
+ " Refresh the taglist
+ if g:Tlist_Process_File_Always
+ autocmd BufEnter * call s:Tlist_Refresh()
+ endif
+
+ if g:Tlist_Show_Menu
+ autocmd GUIEnter * call s:Tlist_Menu_Init()
+ endif
+
+ " When the taglist buffer is created when loading a Vim session file,
+ " the taglist buffer needs to be initialized. The BufFilePost event
+ " is used to handle this case.
+ autocmd BufFilePost __Tag_List__ call s:Tlist_Vim_Session_Load()
+
+ " Define the user commands to manage the taglist window
+ command! -nargs=0 -bar TlistToggle call s:Tlist_Window_Toggle()
+ command! -nargs=0 -bar TlistOpen call s:Tlist_Window_Open()
+ " For backwards compatiblity define the Tlist command
+ command! -nargs=0 -bar Tlist TlistToggle
+ command! -nargs=+ -complete=file TlistAddFiles
+ \ call s:Tlist_Add_Files(<f-args>)
+ command! -nargs=+ -complete=dir TlistAddFilesRecursive
+ \ call s:Tlist_Add_Files_Recursive(<f-args>)
+ command! -nargs=0 -bar TlistClose call s:Tlist_Window_Close()
+ command! -nargs=0 -bar TlistUpdate call s:Tlist_Update_Current_File()
+ command! -nargs=0 -bar TlistHighlightTag call s:Tlist_Window_Highlight_Tag(
+ \ fnamemodify(bufname('%'), ':p'), line('.'), 2, 1)
+ " For backwards compatiblity define the TlistSync command
+ command! -nargs=0 -bar TlistSync TlistHighlightTag
+ command! -nargs=* -complete=buffer TlistShowPrototype
+ \ echo Tlist_Get_Tag_Prototype_By_Line(<f-args>)
+ command! -nargs=* -complete=buffer TlistShowTag
+ \ echo Tlist_Get_Tagname_By_Line(<f-args>)
+ command! -nargs=* -complete=file TlistSessionLoad
+ \ call s:Tlist_Session_Load(<q-args>)
+ command! -nargs=* -complete=file TlistSessionSave
+ \ call s:Tlist_Session_Save(<q-args>)
+ command! -bar TlistLock let Tlist_Auto_Update=0
+ command! -bar TlistUnlock let Tlist_Auto_Update=1
+
+ " Commands for enabling/disabling debug and to display debug messages
+ command! -nargs=? -complete=file -bar TlistDebug
+ \ call s:Tlist_Debug_Enable(<q-args>)
+ command! -nargs=0 -bar TlistUndebug call s:Tlist_Debug_Disable()
+ command! -nargs=0 -bar TlistMessages call s:Tlist_Debug_Show()
+
+ " Define autocommands to autoload the taglist plugin when needed.
+
+ " Trick to get the current script ID
+ map <SID>xx <SID>xx
+ let s:tlist_sid = substitute(maparg('<SID>xx'), '<SNR>\(\d\+_\)xx$',
+ \ '\1', '')
+ unmap <SID>xx
+
+ exe 'autocmd FuncUndefined *' . s:tlist_sid . 'Tlist_* source ' .
+ \ escape(expand('<sfile>'), ' ')
+ exe 'autocmd FuncUndefined *' . s:tlist_sid . 'Tlist_Window_* source ' .
+ \ escape(expand('<sfile>'), ' ')
+ exe 'autocmd FuncUndefined *' . s:tlist_sid . 'Tlist_Menu_* source ' .
+ \ escape(expand('<sfile>'), ' ')
+ exe 'autocmd FuncUndefined Tlist_* source ' .
+ \ escape(expand('<sfile>'), ' ')
+ exe 'autocmd FuncUndefined TagList_* source ' .
+ \ escape(expand('<sfile>'), ' ')
+
+ let loaded_taglist = 'fast_load_done'
+
+ if g:Tlist_Show_Menu && has('gui_running')
+ call s:Tlist_Menu_Init()
+ endif
+
+ " restore 'cpo'
+ let &cpo = s:cpo_save
+ finish
+endif
+
+if !exists('s:tlist_sid')
+ " Two or more versions of taglist plugin are installed. Don't
+ " load this version of the plugin.
+ finish
+endif
+
+unlet! s:tlist_sid
+
+if loaded_taglist != 'fast_load_done'
+ " restore 'cpo'
+ let &cpo = s:cpo_save
+ finish
+endif
+
+" Taglist plugin functionality is available
+let loaded_taglist = 'available'
+
+"------------------- end of user configurable options --------------------
+
+" Default language specific settings for supported file types and tag types
+"
+" Variable name format:
+"
+" s:tlist_def_{vim_ftype}_settings
+"
+" vim_ftype - Filetype detected by Vim
+"
+" Value format:
+"
+" <ctags_ftype>;<flag>:<name>;<flag>:<name>;...
+"
+" ctags_ftype - File type supported by exuberant ctags
+" flag - Flag supported by exuberant ctags to generate a tag type
+" name - Name of the tag type used in the taglist window to display the
+" tags of this type
+"
+
+" assembly language
+let s:tlist_def_asm_settings = 'asm;d:define;l:label;m:macro;t:type'
+
+" aspperl language
+let s:tlist_def_aspperl_settings = 'asp;f:function;s:sub;v:variable'
+
+" aspvbs language
+let s:tlist_def_aspvbs_settings = 'asp;f:function;s:sub;v:variable'
+
+" awk language
+let s:tlist_def_awk_settings = 'awk;f:function'
+
+" beta language
+let s:tlist_def_beta_settings = 'beta;f:fragment;s:slot;v:pattern'
+
+" c language
+let s:tlist_def_c_settings = 'c;d:macro;g:enum;s:struct;u:union;t:typedef;' .
+ \ 'v:variable;f:function'
+
+" c++ language
+let s:tlist_def_cpp_settings = 'c++;n:namespace;v:variable;d:macro;t:typedef;' .
+ \ 'c:class;g:enum;s:struct;u:union;f:function'
+
+" c# language
+let s:tlist_def_cs_settings = 'c#;d:macro;t:typedef;n:namespace;c:class;' .
+ \ 'E:event;g:enum;s:struct;i:interface;' .
+ \ 'p:properties;m:method'
+
+" cobol language
+let s:tlist_def_cobol_settings = 'cobol;d:data;f:file;g:group;p:paragraph;' .
+ \ 'P:program;s:section'
+
+" eiffel language
+let s:tlist_def_eiffel_settings = 'eiffel;c:class;f:feature'
+
+" erlang language
+let s:tlist_def_erlang_settings = 'erlang;d:macro;r:record;m:module;f:function'
+
+" expect (same as tcl) language
+let s:tlist_def_expect_settings = 'tcl;c:class;f:method;p:procedure'
+
+" fortran language
+let s:tlist_def_fortran_settings = 'fortran;p:program;b:block data;' .
+ \ 'c:common;e:entry;i:interface;k:type;l:label;m:module;' .
+ \ 'n:namelist;t:derived;v:variable;f:function;s:subroutine'
+
+" HTML language
+let s:tlist_def_html_settings = 'html;a:anchor;f:javascript function'
+
+" java language
+let s:tlist_def_java_settings = 'java;p:package;c:class;i:interface;' .
+ \ 'f:field;m:method'
+
+" javascript language
+let s:tlist_def_javascript_settings = 'javascript;f:function'
+
+" lisp language
+let s:tlist_def_lisp_settings = 'lisp;f:function'
+
+" lua language
+let s:tlist_def_lua_settings = 'lua;f:function'
+
+" makefiles
+let s:tlist_def_make_settings = 'make;m:macro'
+
+" pascal language
+let s:tlist_def_pascal_settings = 'pascal;f:function;p:procedure'
+
+" perl language
+let s:tlist_def_perl_settings = 'perl;c:constant;l:label;p:package;s:subroutine'
+
+" php language
+let s:tlist_def_php_settings = 'php;c:class;d:constant;v:variable;f:function'
+
+" python language
+let s:tlist_def_python_settings = 'python;c:class;m:member;f:function'
+
+" rexx language
+let s:tlist_def_rexx_settings = 'rexx;s:subroutine'
+
+" ruby language
+let s:tlist_def_ruby_settings = 'ruby;c:class;f:method;F:function;' .
+ \ 'm:singleton method'
+
+" scheme language
+let s:tlist_def_scheme_settings = 'scheme;s:set;f:function'
+
+" shell language
+let s:tlist_def_sh_settings = 'sh;f:function'
+
+" C shell language
+let s:tlist_def_csh_settings = 'sh;f:function'
+
+" Z shell language
+let s:tlist_def_zsh_settings = 'sh;f:function'
+
+" slang language
+let s:tlist_def_slang_settings = 'slang;n:namespace;f:function'
+
+" sml language
+let s:tlist_def_sml_settings = 'sml;e:exception;c:functor;s:signature;' .
+ \ 'r:structure;t:type;v:value;f:function'
+
+" sql language
+let s:tlist_def_sql_settings = 'sql;c:cursor;F:field;P:package;r:record;' .
+ \ 's:subtype;t:table;T:trigger;v:variable;f:function;p:procedure'
+
+" tcl language
+let s:tlist_def_tcl_settings = 'tcl;c:class;f:method;m:method;p:procedure'
+
+" vera language
+let s:tlist_def_vera_settings = 'vera;c:class;d:macro;e:enumerator;' .
+ \ 'f:function;g:enum;m:member;p:program;' .
+ \ 'P:prototype;t:task;T:typedef;v:variable;' .
+ \ 'x:externvar'
+
+"verilog language
+let s:tlist_def_verilog_settings = 'verilog;m:module;c:constant;P:parameter;' .
+ \ 'e:event;r:register;t:task;w:write;p:port;v:variable;f:function'
+
+" vim language
+let s:tlist_def_vim_settings = 'vim;a:autocmds;v:variable;f:function'
+
+" yacc language
+let s:tlist_def_yacc_settings = 'yacc;l:label'
+
+"------------------- end of language specific options --------------------
+
+" Vim window size is changed by the taglist plugin or not
+let s:tlist_winsize_chgd = -1
+" Taglist window is maximized or not
+let s:tlist_win_maximized = 0
+" Name of files in the taglist
+let s:tlist_file_names=''
+" Number of files in the taglist
+let s:tlist_file_count = 0
+" Number of filetypes supported by taglist
+let s:tlist_ftype_count = 0
+" Is taglist part of other plugins like winmanager or cream?
+let s:tlist_app_name = "none"
+" Are we displaying brief help text
+let s:tlist_brief_help = 1
+" List of files removed on user request
+let s:tlist_removed_flist = ""
+" Index of current file displayed in the taglist window
+let s:tlist_cur_file_idx = -1
+" Taglist menu is empty or not
+let s:tlist_menu_empty = 1
+
+" An autocommand is used to refresh the taglist window when entering any
+" buffer. We don't want to refresh the taglist window if we are entering the
+" file window from one of the taglist functions. The 'Tlist_Skip_Refresh'
+" variable is used to skip the refresh of the taglist window and is set
+" and cleared appropriately.
+let s:Tlist_Skip_Refresh = 0
+
+" Tlist_Window_Display_Help()
+function! s:Tlist_Window_Display_Help()
+ if s:tlist_app_name == "winmanager"
+ " To handle a bug in the winmanager plugin, add a space at the
+ " last line
+ call setline('$', ' ')
+ endif
+
+ if s:tlist_brief_help
+ " Add the brief help
+ call append(0, '" Press <F1> to display help text')
+ else
+ " Add the extensive help
+ call append(0, '" <enter> : Jump to tag definition')
+ call append(1, '" o : Jump to tag definition in new window')
+ call append(2, '" p : Preview the tag definition')
+ call append(3, '" <space> : Display tag prototype')
+ call append(4, '" u : Update tag list')
+ call append(5, '" s : Select sort field')
+ call append(6, '" d : Remove file from taglist')
+ call append(7, '" x : Zoom-out/Zoom-in taglist window')
+ call append(8, '" + : Open a fold')
+ call append(9, '" - : Close a fold')
+ call append(10, '" * : Open all folds')
+ call append(11, '" = : Close all folds')
+ call append(12, '" [[ : Move to the start of previous file')
+ call append(13, '" ]] : Move to the start of next file')
+ call append(14, '" q : Close the taglist window')
+ call append(15, '" <F1> : Remove help text')
+ endif
+endfunction
+
+" Tlist_Window_Toggle_Help_Text()
+" Toggle taglist plugin help text between the full version and the brief
+" version
+function! s:Tlist_Window_Toggle_Help_Text()
+ if g:Tlist_Compact_Format
+ " In compact display mode, do not display help
+ return
+ endif
+
+ " Include the empty line displayed after the help text
+ let brief_help_size = 1
+ let full_help_size = 16
+
+ setlocal modifiable
+
+ " Set report option to a huge value to prevent informational messages
+ " while deleting the lines
+ let old_report = &report
+ set report=99999
+
+ " Remove the currently highlighted tag. Otherwise, the help text
+ " might be highlighted by mistake
+ match none
+
+ " Toggle between brief and full help text
+ if s:tlist_brief_help
+ let s:tlist_brief_help = 0
+
+ " Remove the previous help
+ exe '1,' . brief_help_size . ' delete _'
+
+ " Adjust the start/end line numbers for the files
+ call s:Tlist_Window_Update_Line_Offsets(0, 1, full_help_size - brief_help_size)
+ else
+ let s:tlist_brief_help = 1
+
+ " Remove the previous help
+ exe '1,' . full_help_size . ' delete _'
+
+ " Adjust the start/end line numbers for the files
+ call s:Tlist_Window_Update_Line_Offsets(0, 0, full_help_size - brief_help_size)
+ endif
+
+ call s:Tlist_Window_Display_Help()
+
+ " Restore the report option
+ let &report = old_report
+
+ setlocal nomodifiable
+endfunction
+
+" Taglist debug support
+let s:tlist_debug = 0
+
+" File for storing the debug messages
+let s:tlist_debug_file = ''
+
+" Tlist_Debug_Enable
+" Enable logging of taglist debug messages.
+function! s:Tlist_Debug_Enable(...)
+ let s:tlist_debug = 1
+
+ " Check whether a valid file name is supplied.
+ if a:1 != ''
+ let s:tlist_debug_file = fnamemodify(a:1, ':p')
+
+ " Empty the log file
+ exe 'redir! > ' . s:tlist_debug_file
+ redir END
+
+ " Check whether the log file is present/created
+ if !filewritable(s:tlist_debug_file)
+ call s:Tlist_Warning_Msg('Taglist: Unable to create log file '
+ \ . s:tlist_debug_file)
+ let s:tlist_debug_file = ''
+ endif
+ endif
+endfunction
+
+" Tlist_Debug_Disable
+" Disable logging of taglist debug messages.
+function! s:Tlist_Debug_Disable(...)
+ let s:tlist_debug = 0
+ let s:tlist_debug_file = ''
+endfunction
+
+" Tlist_Debug_Show
+" Display the taglist debug messages in a new window
+function! s:Tlist_Debug_Show()
+ if s:tlist_msg == ''
+ call s:Tlist_Warning_Msg('Taglist: No debug messages')
+ return
+ endif
+
+ " Open a new window to display the taglist debug messages
+ new taglist_debug.txt
+ " Delete all the lines (if the buffer already exists)
+ silent! %delete _
+ " Add the messages
+ silent! put =s:tlist_msg
+ " Move the cursor to the first line
+ normal! gg
+endfunction
+
+" Tlist_Log_Msg
+" Log the supplied debug message along with the time
+function! s:Tlist_Log_Msg(msg)
+ if s:tlist_debug
+ if s:tlist_debug_file != ''
+ exe 'redir >> ' . s:tlist_debug_file
+ silent echon strftime('%H:%M:%S') . ': ' . a:msg . "\n"
+ redir END
+ else
+ " Log the message into a variable
+ " Retain only the last 3000 characters
+ let len = strlen(s:tlist_msg)
+ if len > 3000
+ let s:tlist_msg = strpart(s:tlist_msg, len - 3000)
+ endif
+ let s:tlist_msg = s:tlist_msg . strftime('%H:%M:%S') . ': ' .
+ \ a:msg . "\n"
+ endif
+ endif
+endfunction
+
+" Tlist_Warning_Msg()
+" Display a message using WarningMsg highlight group
+function! s:Tlist_Warning_Msg(msg)
+ echohl WarningMsg
+ echomsg a:msg
+ echohl None
+endfunction
+
+" Last returned file index for file name lookup.
+" Used to speed up file lookup
+let s:tlist_file_name_idx_cache = -1
+
+" Tlist_Get_File_Index()
+" Return the index of the specified filename
+function! s:Tlist_Get_File_Index(fname)
+ if s:tlist_file_count == 0 || a:fname == ''
+ return -1
+ endif
+
+ " If the new filename is same as the last accessed filename, then
+ " return that index
+ if s:tlist_file_name_idx_cache != -1 &&
+ \ s:tlist_file_name_idx_cache < s:tlist_file_count
+ if s:tlist_{s:tlist_file_name_idx_cache}_filename == a:fname
+ " Same as the last accessed file
+ return s:tlist_file_name_idx_cache
+ endif
+ endif
+
+ " First, check whether the filename is present
+ let s_fname = a:fname . "\n"
+ let i = stridx(s:tlist_file_names, s_fname)
+ if i == -1
+ let s:tlist_file_name_idx_cache = -1
+ return -1
+ endif
+
+ " Second, compute the file name index
+ let nl_txt = substitute(strpart(s:tlist_file_names, 0, i), "[^\n]", '', 'g')
+ let s:tlist_file_name_idx_cache = strlen(nl_txt)
+ return s:tlist_file_name_idx_cache
+endfunction
+
+" Last returned file index for line number lookup.
+" Used to speed up file lookup
+let s:tlist_file_lnum_idx_cache = -1
+
+" Tlist_Window_Get_File_Index_By_Linenum()
+" Return the index of the filename present in the specified line number
+" Line number refers to the line number in the taglist window
+function! s:Tlist_Window_Get_File_Index_By_Linenum(lnum)
+ call s:Tlist_Log_Msg('Tlist_Window_Get_File_Index_By_Linenum (' . a:lnum . ')')
+
+ " First try to see whether the new line number is within the range
+ " of the last returned file
+ if s:tlist_file_lnum_idx_cache != -1 &&
+ \ s:tlist_file_lnum_idx_cache < s:tlist_file_count
+ if a:lnum >= s:tlist_{s:tlist_file_lnum_idx_cache}_start &&
+ \ a:lnum <= s:tlist_{s:tlist_file_lnum_idx_cache}_end
+ return s:tlist_file_lnum_idx_cache
+ endif
+ endif
+
+ let fidx = -1
+
+ if g:Tlist_Show_One_File
+ " Displaying only one file in the taglist window. Check whether
+ " the line is within the tags displayed for that file
+ if s:tlist_cur_file_idx != -1
+ if a:lnum >= s:tlist_{s:tlist_cur_file_idx}_start
+ \ && a:lnum <= s:tlist_{s:tlist_cur_file_idx}_end
+ let fidx = s:tlist_cur_file_idx
+ endif
+
+ endif
+ else
+ " Do a binary search in the taglist
+ let left = 0
+ let right = s:tlist_file_count - 1
+
+ while left < right
+ let mid = (left + right) / 2
+
+ if a:lnum >= s:tlist_{mid}_start && a:lnum <= s:tlist_{mid}_end
+ let s:tlist_file_lnum_idx_cache = mid
+ return mid
+ endif
+
+ if a:lnum < s:tlist_{mid}_start
+ let right = mid - 1
+ else
+ let left = mid + 1
+ endif
+ endwhile
+
+ if left >= 0 && left < s:tlist_file_count
+ \ && a:lnum >= s:tlist_{left}_start
+ \ && a:lnum <= s:tlist_{left}_end
+ let fidx = left
+ endif
+ endif
+
+ let s:tlist_file_lnum_idx_cache = fidx
+
+ return fidx
+endfunction
+
+" Tlist_Exe_Cmd_No_Acmds
+" Execute the specified Ex command after disabling autocommands
+function! s:Tlist_Exe_Cmd_No_Acmds(cmd)
+ let old_eventignore = &eventignore
+ set eventignore=all
+ exe a:cmd
+ let &eventignore = old_eventignore
+endfunction
+
+" Tlist_Skip_File()
+" Check whether tag listing is supported for the specified file
+function! s:Tlist_Skip_File(filename, ftype)
+ " Skip buffers with no names and buffers with filetype not set
+ if a:filename == '' || a:ftype == ''
+ return 1
+ endif
+
+ " Skip files which are not supported by exuberant ctags
+ " First check whether default settings for this filetype are available.
+ " If it is not available, then check whether user specified settings are
+ " available. If both are not available, then don't list the tags for this
+ " filetype
+ let var = 's:tlist_def_' . a:ftype . '_settings'
+ if !exists(var)
+ let var = 'g:tlist_' . a:ftype . '_settings'
+ if !exists(var)
+ return 1
+ endif
+ endif
+
+ " Skip files which are not readable or files which are not yet stored
+ " to the disk
+ if !filereadable(a:filename)
+ return 1
+ endif
+
+ return 0
+endfunction
+
+" Tlist_User_Removed_File
+" Returns 1 if a file is removed by a user from the taglist
+function! s:Tlist_User_Removed_File(filename)
+ return stridx(s:tlist_removed_flist, a:filename . "\n") != -1
+endfunction
+
+" Tlist_Update_Remove_List
+" Update the list of user removed files from the taglist
+" add == 1, add the file to the removed list
+" add == 0, delete the file from the removed list
+function! s:Tlist_Update_Remove_List(filename, add)
+ if a:add
+ let s:tlist_removed_flist = s:tlist_removed_flist . a:filename . "\n"
+ else
+ let idx = stridx(s:tlist_removed_flist, a:filename . "\n")
+ let text_before = strpart(s:tlist_removed_flist, 0, idx)
+ let rem_text = strpart(s:tlist_removed_flist, idx)
+ let next_idx = stridx(rem_text, "\n")
+ let text_after = strpart(rem_text, next_idx + 1)
+
+ let s:tlist_removed_flist = text_before . text_after
+ endif
+endfunction
+
+" Tlist_FileType_Init
+" Initialize the ctags arguments and tag variable for the specified
+" file type
+function! s:Tlist_FileType_Init(ftype)
+ call s:Tlist_Log_Msg('Tlist_FileType_Init (' . a:ftype . ')')
+ " If the user didn't specify any settings, then use the default
+ " ctags args. Otherwise, use the settings specified by the user
+ let var = 'g:tlist_' . a:ftype . '_settings'
+ if exists(var)
+ " User specified ctags arguments
+ let settings = {var} . ';'
+ else
+ " Default ctags arguments
+ let var = 's:tlist_def_' . a:ftype . '_settings'
+ if !exists(var)
+ " No default settings for this file type. This filetype is
+ " not supported
+ return 0
+ endif
+ let settings = s:tlist_def_{a:ftype}_settings . ';'
+ endif
+
+ let msg = 'Taglist: Invalid ctags option setting - ' . settings
+
+ " Format of the option that specifies the filetype and ctags arugments:
+ "
+ " <language_name>;flag1:name1;flag2:name2;flag3:name3
+ "
+
+ " Extract the file type to pass to ctags. This may be different from the
+ " file type detected by Vim
+ let pos = stridx(settings, ';')
+ if pos == -1
+ call s:Tlist_Warning_Msg(msg)
+ return 0
+ endif
+ let ctags_ftype = strpart(settings, 0, pos)
+ if ctags_ftype == ''
+ call s:Tlist_Warning_Msg(msg)
+ return 0
+ endif
+ " Make sure a valid filetype is supplied. If the user didn't specify a
+ " valid filetype, then the ctags option settings may be treated as the
+ " filetype
+ if ctags_ftype =~ ':'
+ call s:Tlist_Warning_Msg(msg)
+ return 0
+ endif
+
+ " Remove the file type from settings
+ let settings = strpart(settings, pos + 1)
+ if settings == ''
+ call s:Tlist_Warning_Msg(msg)
+ return 0
+ endif
+
+ " Process all the specified ctags flags. The format is
+ " flag1:name1;flag2:name2;flag3:name3
+ let ctags_flags = ''
+ let cnt = 0
+ while settings != ''
+ " Extract the flag
+ let pos = stridx(settings, ':')
+ if pos == -1
+ call s:Tlist_Warning_Msg(msg)
+ return 0
+ endif
+ let flag = strpart(settings, 0, pos)
+ if flag == ''
+ call s:Tlist_Warning_Msg(msg)
+ return 0
+ endif
+ " Remove the flag from settings
+ let settings = strpart(settings, pos + 1)
+
+ " Extract the tag type name
+ let pos = stridx(settings, ';')
+ if pos == -1
+ call s:Tlist_Warning_Msg(msg)
+ return 0
+ endif
+ let name = strpart(settings, 0, pos)
+ if name == ''
+ call s:Tlist_Warning_Msg(msg)
+ return 0
+ endif
+ let settings = strpart(settings, pos + 1)
+
+ let cnt = cnt + 1
+
+ let s:tlist_{a:ftype}_{cnt}_name = flag
+ let s:tlist_{a:ftype}_{cnt}_fullname = name
+ let ctags_flags = ctags_flags . flag
+ endwhile
+
+ let s:tlist_{a:ftype}_ctags_args = '--language-force=' . ctags_ftype .
+ \ ' --' . ctags_ftype . '-types=' . ctags_flags
+ let s:tlist_{a:ftype}_count = cnt
+ let s:tlist_{a:ftype}_ctags_flags = ctags_flags
+
+ " Save the filetype name
+ let s:tlist_ftype_{s:tlist_ftype_count}_name = a:ftype
+ let s:tlist_ftype_count = s:tlist_ftype_count + 1
+
+ return 1
+endfunction
+
+" Tlist_Detect_Filetype
+" Determine the filetype for the specified file using the filetypedetect
+" autocmd.
+function! s:Tlist_Detect_Filetype(fname)
+ " Ignore the filetype autocommands
+ let old_eventignore = &eventignore
+ set eventignore=FileType
+
+ " Save the 'filetype', as this will be changed temporarily
+ let old_filetype = &filetype
+
+ " Run the filetypedetect group of autocommands to determine
+ " the filetype
+ exe 'doautocmd filetypedetect BufRead ' . a:fname
+
+ " Save the detected filetype
+ let ftype = &filetype
+
+ " Restore the previous state
+ let &filetype = old_filetype
+ let &eventignore = old_eventignore
+
+ return ftype
+endfunction
+
+" Tlist_Get_Buffer_Filetype
+" Get the filetype for the specified buffer
+function! s:Tlist_Get_Buffer_Filetype(bnum)
+ let buf_ft = getbufvar(a:bnum, '&filetype')
+
+ if bufloaded(a:bnum)
+ " For loaded buffers, the 'filetype' is already determined
+ return buf_ft
+ endif
+
+ " For unloaded buffers, if the 'filetype' option is set, return it
+ if buf_ft != ''
+ return buf_ft
+ endif
+
+ " Skip non-existent buffers
+ if !bufexists(a:bnum)
+ return ''
+ endif
+
+ " For buffers whose filetype is not yet determined, try to determine
+ " the filetype
+ let bname = bufname(a:bnum)
+
+ return s:Tlist_Detect_Filetype(bname)
+endfunction
+
+" Tlist_Discard_TagInfo
+" Discard the stored tag information for a file
+function! s:Tlist_Discard_TagInfo(fidx)
+ call s:Tlist_Log_Msg('Tlist_Discard_TagInfo (' .
+ \ s:tlist_{a:fidx}_filename . ')')
+ let ftype = s:tlist_{a:fidx}_filetype
+
+ " Discard information about the tags defined in the file
+ let i = 1
+ while i <= s:tlist_{a:fidx}_tag_count
+ let fidx_i = 's:tlist_' . a:fidx . '_' . i
+ unlet! {fidx_i}_tag
+ unlet! {fidx_i}_tag_name
+ unlet! {fidx_i}_tag_type
+ unlet! {fidx_i}_ttype_idx
+ unlet! {fidx_i}_tag_proto
+ unlet! {fidx_i}_tag_searchpat
+ unlet! {fidx_i}_tag_linenum
+ let i = i + 1
+ endwhile
+
+ let s:tlist_{a:fidx}_tag_count = 0
+
+ " Discard information about tag type groups
+ let i = 1
+ while i <= s:tlist_{ftype}_count
+ let ttype = s:tlist_{ftype}_{i}_name
+ if s:tlist_{a:fidx}_{ttype} != ''
+ let fidx_ttype = 's:tlist_' . a:fidx . '_' . ttype
+ let {fidx_ttype} = ''
+ let {fidx_ttype}_offset = 0
+ let cnt = {fidx_ttype}_count
+ let {fidx_ttype}_count = 0
+ let j = 1
+ while j <= cnt
+ unlet! {fidx_ttype}_{j}
+ let j = j + 1
+ endwhile
+ endif
+ let i = i + 1
+ endwhile
+
+ " Discard the stored menu command also
+ let s:tlist_{a:fidx}_menu_cmd = ''
+endfunction
+
+" Tlist_Window_Update_Line_Offsets
+" Update the line offsets for tags for files starting from start_idx
+" and displayed in the taglist window by the specified offset
+function! s:Tlist_Window_Update_Line_Offsets(start_idx, increment, offset)
+ let i = a:start_idx
+
+ while i < s:tlist_file_count
+ if s:tlist_{i}_visible
+ " Update the start/end line number only if the file is visible
+ if a:increment
+ let s:tlist_{i}_start = s:tlist_{i}_start + a:offset
+ let s:tlist_{i}_end = s:tlist_{i}_end + a:offset
+ else
+ let s:tlist_{i}_start = s:tlist_{i}_start - a:offset
+ let s:tlist_{i}_end = s:tlist_{i}_end - a:offset
+ endif
+ endif
+ let i = i + 1
+ endwhile
+endfunction
+
+" Tlist_Discard_FileInfo
+" Discard the stored information for a file
+function! s:Tlist_Discard_FileInfo(fidx)
+ call s:Tlist_Log_Msg('Tlist_Discard_FileInfo (' .
+ \ s:tlist_{a:fidx}_filename . ')')
+ call s:Tlist_Discard_TagInfo(a:fidx)
+
+ let ftype = s:tlist_{a:fidx}_filetype
+
+ let i = 1
+ while i <= s:tlist_{ftype}_count
+ let ttype = s:tlist_{ftype}_{i}_name
+ unlet! s:tlist_{a:fidx}_{ttype}
+ unlet! s:tlist_{a:fidx}_{ttype}_offset
+ unlet! s:tlist_{a:fidx}_{ttype}_count
+ let i = i + 1
+ endwhile
+
+ unlet! s:tlist_{a:fidx}_filename
+ unlet! s:tlist_{a:fidx}_sort_type
+ unlet! s:tlist_{a:fidx}_filetype
+ unlet! s:tlist_{a:fidx}_mtime
+ unlet! s:tlist_{a:fidx}_start
+ unlet! s:tlist_{a:fidx}_end
+ unlet! s:tlist_{a:fidx}_valid
+ unlet! s:tlist_{a:fidx}_visible
+ unlet! s:tlist_{a:fidx}_tag_count
+ unlet! s:tlist_{a:fidx}_menu_cmd
+endfunction
+
+" Tlist_Window_Remove_File_From_Display
+" Remove the specified file from display
+function! s:Tlist_Window_Remove_File_From_Display(fidx)
+ call s:Tlist_Log_Msg('Tlist_Window_Remove_File_From_Display (' .
+ \ s:tlist_{a:fidx}_filename . ')')
+ " If the file is not visible then no need to remove it
+ if !s:tlist_{a:fidx}_visible
+ return
+ endif
+
+ " Remove the tags displayed for the specified file from the window
+ let start = s:tlist_{a:fidx}_start
+ " Include the empty line after the last line also
+ if g:Tlist_Compact_Format
+ let end = s:tlist_{a:fidx}_end
+ else
+ let end = s:tlist_{a:fidx}_end + 1
+ endif
+
+ setlocal modifiable
+ exe 'silent! ' . start . ',' . end . 'delete _'
+ setlocal nomodifiable
+
+ " Correct the start and end line offsets for all the files following
+ " this file, as the tags for this file are removed
+ call s:Tlist_Window_Update_Line_Offsets(a:fidx + 1, 0, end - start + 1)
+endfunction
+
+" Tlist_Remove_File
+" Remove the file under the cursor or the specified file index
+" user_request - User requested to remove the file from taglist
+function! s:Tlist_Remove_File(file_idx, user_request)
+ let fidx = a:file_idx
+
+ if fidx == -1
+ let fidx = s:Tlist_Window_Get_File_Index_By_Linenum(line('.'))
+ if fidx == -1
+ return
+ endif
+ endif
+ call s:Tlist_Log_Msg('Tlist_Remove_File (' .
+ \ s:tlist_{fidx}_filename . ', ' . a:user_request . ')')
+
+ let save_winnr = winnr()
+ let winnum = bufwinnr(g:TagList_title)
+ if winnum != -1
+ " Taglist window is open, remove the file from display
+
+ if save_winnr != winnum
+ let old_eventignore = &eventignore
+ set eventignore=all
+ exe winnum . 'wincmd w'
+ endif
+
+ call s:Tlist_Window_Remove_File_From_Display(fidx)
+
+ if save_winnr != winnum
+ exe save_winnr . 'wincmd w'
+ let &eventignore = old_eventignore
+ endif
+ endif
+
+ let fname = s:tlist_{fidx}_filename
+
+ if a:user_request
+ " As the user requested to remove the file from taglist,
+ " add it to the removed list
+ call s:Tlist_Update_Remove_List(fname, 1)
+ endif
+
+ " Remove the file name from the taglist list of filenames
+ let idx = stridx(s:tlist_file_names, fname . "\n")
+ let text_before = strpart(s:tlist_file_names, 0, idx)
+ let rem_text = strpart(s:tlist_file_names, idx)
+ let next_idx = stridx(rem_text, "\n")
+ let text_after = strpart(rem_text, next_idx + 1)
+ let s:tlist_file_names = text_before . text_after
+
+ call s:Tlist_Discard_FileInfo(fidx)
+
+ " Shift all the file variables by one index
+ let i = fidx + 1
+
+ while i < s:tlist_file_count
+ let j = i - 1
+
+ let s:tlist_{j}_filename = s:tlist_{i}_filename
+ let s:tlist_{j}_sort_type = s:tlist_{i}_sort_type
+ let s:tlist_{j}_filetype = s:tlist_{i}_filetype
+ let s:tlist_{j}_mtime = s:tlist_{i}_mtime
+ let s:tlist_{j}_start = s:tlist_{i}_start
+ let s:tlist_{j}_end = s:tlist_{i}_end
+ let s:tlist_{j}_valid = s:tlist_{i}_valid
+ let s:tlist_{j}_visible = s:tlist_{i}_visible
+ let s:tlist_{j}_tag_count = s:tlist_{i}_tag_count
+ let s:tlist_{j}_menu_cmd = s:tlist_{i}_menu_cmd
+
+ let k = 1
+ while k <= s:tlist_{j}_tag_count
+ let s:tlist_{j}_{k}_tag = s:tlist_{i}_{k}_tag
+ let s:tlist_{j}_{k}_tag_name = s:tlist_{i}_{k}_tag_name
+ let s:tlist_{j}_{k}_tag_type = s:Tlist_Get_Tag_Type_By_Tag(i, k)
+ let s:tlist_{j}_{k}_ttype_idx = s:tlist_{i}_{k}_ttype_idx
+ let s:tlist_{j}_{k}_tag_proto = s:Tlist_Get_Tag_Prototype(i, k)
+ let s:tlist_{j}_{k}_tag_searchpat = s:Tlist_Get_Tag_SearchPat(i, k)
+ let s:tlist_{j}_{k}_tag_linenum = s:Tlist_Get_Tag_Linenum(i, k)
+ let k = k + 1
+ endwhile
+
+ let ftype = s:tlist_{i}_filetype
+
+ let k = 1
+ while k <= s:tlist_{ftype}_count
+ let ttype = s:tlist_{ftype}_{k}_name
+ let s:tlist_{j}_{ttype} = s:tlist_{i}_{ttype}
+ let s:tlist_{j}_{ttype}_offset = s:tlist_{i}_{ttype}_offset
+ let s:tlist_{j}_{ttype}_count = s:tlist_{i}_{ttype}_count
+ if s:tlist_{j}_{ttype} != ''
+ let l = 1
+ while l <= s:tlist_{j}_{ttype}_count
+ let s:tlist_{j}_{ttype}_{l} = s:tlist_{i}_{ttype}_{l}
+ let l = l + 1
+ endwhile
+ endif
+ let k = k + 1
+ endwhile
+
+ " As the file and tag information is copied to the new index,
+ " discard the previous information
+ call s:Tlist_Discard_FileInfo(i)
+
+ let i = i + 1
+ endwhile
+
+ " Reduce the number of files displayed
+ let s:tlist_file_count = s:tlist_file_count - 1
+
+ if g:Tlist_Show_One_File
+ " If the tags for only one file is displayed and if we just
+ " now removed that file, then invalidate the current file idx
+ if s:tlist_cur_file_idx == fidx
+ let s:tlist_cur_file_idx = -1
+ endif
+ endif
+endfunction
+
+" Tlist_Window_Goto_Window
+" Goto the taglist window
+function! s:Tlist_Window_Goto_Window()
+ let winnum = bufwinnr(g:TagList_title)
+ if winnum != -1
+ if winnr() != winnum
+ call s:Tlist_Exe_Cmd_No_Acmds(winnum . 'wincmd w')
+ endif
+ endif
+endfunction
+
+" Tlist_Window_Create
+" Create a new taglist window. If it is already open, jump to it
+function! s:Tlist_Window_Create()
+ call s:Tlist_Log_Msg('Tlist_Window_Create()')
+ " If the window is open, jump to it
+ let winnum = bufwinnr(g:TagList_title)
+ if winnum != -1
+ " Jump to the existing window
+ if winnr() != winnum
+ exe winnum . 'wincmd w'
+ endif
+ return
+ endif
+
+ " If used with winmanager don't open windows. Winmanager will handle
+ " the window/buffer management
+ if s:tlist_app_name == "winmanager"
+ return
+ endif
+
+ " Create a new window. If user prefers a horizontal window, then open
+ " a horizontally split window. Otherwise open a vertically split
+ " window
+ if g:Tlist_Use_Horiz_Window
+ " Open a horizontally split window
+ let win_dir = 'botright'
+ " Horizontal window height
+ let win_size = g:Tlist_WinHeight
+ else
+ if s:tlist_winsize_chgd == -1
+ " Open a vertically split window. Increase the window size, if
+ " needed, to accomodate the new window
+ if g:Tlist_Inc_Winwidth &&
+ \ &columns < (80 + g:Tlist_WinWidth)
+ " Save the original window position
+ let s:tlist_pre_winx = getwinposx()
+ let s:tlist_pre_winy = getwinposy()
+
+ " one extra column is needed to include the vertical split
+ let &columns= &columns + g:Tlist_WinWidth + 1
+
+ let s:tlist_winsize_chgd = 1
+ else
+ let s:tlist_winsize_chgd = 0
+ endif
+ endif
+
+ if g:Tlist_Use_Right_Window
+ " Open the window at the rightmost place
+ let win_dir = 'botright vertical'
+ else
+ " Open the window at the leftmost place
+ let win_dir = 'topleft vertical'
+ endif
+ let win_size = g:Tlist_WinWidth
+ endif
+
+ " If the tag listing temporary buffer already exists, then reuse it.
+ " Otherwise create a new buffer
+ let bufnum = bufnr(g:TagList_title)
+ if bufnum == -1
+ " Create a new buffer
+ let wcmd = g:TagList_title
+ else
+ " Edit the existing buffer
+ let wcmd = '+buffer' . bufnum
+ endif
+
+ " Create the taglist window
+ exe 'silent! ' . win_dir . ' ' . win_size . 'split ' . wcmd
+
+ " Save the new window position
+ let s:tlist_winx = getwinposx()
+ let s:tlist_winy = getwinposy()
+
+ " Initialize the taglist window
+ call s:Tlist_Window_Init()
+endfunction
+
+" Tlist_Window_Zoom
+" Zoom (maximize/minimize) the taglist window
+function! s:Tlist_Window_Zoom()
+ if s:tlist_win_maximized
+ " Restore the window back to the previous size
+ if g:Tlist_Use_Horiz_Window
+ exe 'resize ' . g:Tlist_WinHeight
+ else
+ exe 'vert resize ' . g:Tlist_WinWidth
+ endif
+ let s:tlist_win_maximized = 0
+ else
+ " Set the window size to the maximum possible without closing other
+ " windows
+ if g:Tlist_Use_Horiz_Window
+ resize
+ else
+ vert resize
+ endif
+ let s:tlist_win_maximized = 1
+ endif
+endfunction
+
+" Tlist_Ballon_Expr
+" When the mouse cursor is over a tag in the taglist window, display the
+" tag prototype (balloon)
+function! Tlist_Ballon_Expr()
+ " Get the file index
+ let fidx = s:Tlist_Window_Get_File_Index_By_Linenum(v:beval_lnum)
+ if fidx == -1
+ return ''
+ endif
+
+ " Get the tag output line for the current tag
+ let tidx = s:Tlist_Window_Get_Tag_Index(fidx, v:beval_lnum)
+ if tidx == 0
+ return ''
+ endif
+
+ " Get the tag search pattern and display it
+ return s:Tlist_Get_Tag_Prototype(fidx, tidx)
+endfunction
+
+" Tlist_Window_Check_Width
+" Check the width of the taglist window. For horizontally split windows, the
+" 'winfixheight' option is used to fix the height of the window. For
+" vertically split windows, Vim doesn't support the 'winfixwidth' option. So
+" need to handle window width changes from this function.
+function! s:Tlist_Window_Check_Width()
+ let tlist_winnr = bufwinnr(g:TagList_title)
+ if tlist_winnr == -1
+ return
+ endif
+
+ let width = winwidth(tlist_winnr)
+ if width != g:Tlist_WinWidth
+ call s:Tlist_Log_Msg("Tlist_Window_Check_Width: Changing window " .
+ \ "width from " . width . " to " . g:Tlist_WinWidth)
+ let save_winnr = winnr()
+ if save_winnr != tlist_winnr
+ call s:Tlist_Exe_Cmd_No_Acmds(tlist_winnr . 'wincmd w')
+ endif
+ exe 'vert resize ' . g:Tlist_WinWidth
+ if save_winnr != tlist_winnr
+ call s:Tlist_Exe_Cmd_No_Acmds('wincmd p')
+ endif
+ endif
+endfunction
+
+" Tlist_Window_Exit_Only_Window
+" If the 'Tlist_Exit_OnlyWindow' option is set, then exit Vim if only the
+" taglist window is present.
+function! s:Tlist_Window_Exit_Only_Window()
+ " Before quitting Vim, delete the taglist buffer so that
+ " the '0 mark is correctly set to the previous buffer.
+ if v:version < 700
+ if winbufnr(2) == -1
+ bdelete
+ quit
+ endif
+ else
+ if winbufnr(2) == -1
+ if tabpagenr('$') == 1
+ " Only one tag page is present
+ bdelete
+ quit
+ else
+ " More than one tab page is present. Close only the current
+ " tab page
+ close
+ endif
+ endif
+ endif
+endfunction
+
+" Tlist_Window_Init
+" Set the default options for the taglist window
+function! s:Tlist_Window_Init()
+ call s:Tlist_Log_Msg('Tlist_Window_Init()')
+
+ " The 'readonly' option should not be set for the taglist buffer.
+ " If Vim is started as "view/gview" or if the ":view" command is
+ " used, then the 'readonly' option is set for all the buffers.
+ " Unset it for the taglist buffer
+ setlocal noreadonly
+
+ " Set the taglist buffer filetype to taglist
+ setlocal filetype=taglist
+
+ " Define taglist window element highlighting
+ syntax match TagListComment '^" .*'
+ syntax match TagListFileName '^[^" ].*$'
+ syntax match TagListTitle '^ \S.*$'
+ syntax match TagListTagScope '\s\[.\{-\}\]$'
+
+ " Define the highlighting only if colors are supported
+ if has('gui_running') || &t_Co > 2
+ " Colors to highlight various taglist window elements
+ " If user defined highlighting group exists, then use them.
+ " Otherwise, use default highlight groups.
+ if hlexists('MyTagListTagName')
+ highlight link TagListTagName MyTagListTagName
+ else
+ highlight default link TagListTagName Search
+ endif
+ " Colors to highlight comments and titles
+ if hlexists('MyTagListComment')
+ highlight link TagListComment MyTagListComment
+ else
+ highlight clear TagListComment
+ highlight default link TagListComment Comment
+ endif
+ if hlexists('MyTagListTitle')
+ highlight link TagListTitle MyTagListTitle
+ else
+ highlight clear TagListTitle
+ highlight default link TagListTitle Title
+ endif
+ if hlexists('MyTagListFileName')
+ highlight link TagListFileName MyTagListFileName
+ else
+ highlight clear TagListFileName
+ highlight default TagListFileName guibg=Grey ctermbg=darkgray
+ \ guifg=white ctermfg=white
+ endif
+ if hlexists('MyTagListTagScope')
+ highlight link TagListTagScope MyTagListTagScope
+ else
+ highlight clear TagListTagScope
+ highlight default link TagListTagScope Identifier
+ endif
+ else
+ highlight default TagListTagName term=reverse cterm=reverse
+ endif
+
+ " Folding related settings
+ setlocal foldenable
+ setlocal foldminlines=0
+ setlocal foldmethod=manual
+ setlocal foldlevel=9999
+ if g:Tlist_Enable_Fold_Column
+ setlocal foldcolumn=3
+ else
+ setlocal foldcolumn=0
+ endif
+ setlocal foldtext=v:folddashes.getline(v:foldstart)
+
+ if s:tlist_app_name != "winmanager"
+ " Mark buffer as scratch
+ silent! setlocal buftype=nofile
+ if s:tlist_app_name == "none"
+ silent! setlocal bufhidden=delete
+ endif
+ silent! setlocal noswapfile
+ " Due to a bug in Vim 6.0, the winbufnr() function fails for unlisted
+ " buffers. So if the taglist buffer is unlisted, multiple taglist
+ " windows will be opened. This bug is fixed in Vim 6.1 and above
+ if v:version >= 601
+ silent! setlocal nobuflisted
+ endif
+ endif
+
+ silent! setlocal nowrap
+
+ " If the 'number' option is set in the source window, it will affect the
+ " taglist window. So forcefully disable 'number' option for the taglist
+ " window
+ silent! setlocal nonumber
+
+ " Use fixed height when horizontally split window is used
+ if g:Tlist_Use_Horiz_Window
+ if v:version >= 602
+ set winfixheight
+ endif
+ endif
+ if !g:Tlist_Use_Horiz_Window && v:version >= 700
+ set winfixwidth
+ endif
+
+ " Setup balloon evaluation to display tag prototype
+ if v:version >= 700 && has('balloon_eval')
+ setlocal balloonexpr=Tlist_Ballon_Expr()
+ set ballooneval
+ endif
+
+ " Setup the cpoptions properly for the maps to work
+ let old_cpoptions = &cpoptions
+ set cpoptions&vim
+
+ " Create buffer local mappings for jumping to the tags and sorting the list
+ nnoremap <buffer> <silent> <CR>
+ \ :call <SID>Tlist_Window_Jump_To_Tag('useopen')<CR>
+ nnoremap <buffer> <silent> o
+ \ :call <SID>Tlist_Window_Jump_To_Tag('newwin')<CR>
+ nnoremap <buffer> <silent> p
+ \ :call <SID>Tlist_Window_Jump_To_Tag('preview')<CR>
+ nnoremap <buffer> <silent> P
+ \ :call <SID>Tlist_Window_Jump_To_Tag('prevwin')<CR>
+ if v:version >= 700
+ nnoremap <buffer> <silent> t
+ \ :call <SID>Tlist_Window_Jump_To_Tag('checktab')<CR>
+ nnoremap <buffer> <silent> <C-t>
+ \ :call <SID>Tlist_Window_Jump_To_Tag('newtab')<CR>
+ endif
+ nnoremap <buffer> <silent> <2-LeftMouse>
+ \ :call <SID>Tlist_Window_Jump_To_Tag('useopen')<CR>
+ nnoremap <buffer> <silent> s
+ \ :call <SID>Tlist_Change_Sort('cmd', 'toggle', '')<CR>
+ nnoremap <buffer> <silent> + :silent! foldopen<CR>
+ nnoremap <buffer> <silent> - :silent! foldclose<CR>
+ nnoremap <buffer> <silent> * :silent! %foldopen!<CR>
+ nnoremap <buffer> <silent> = :silent! %foldclose<CR>
+ nnoremap <buffer> <silent> <kPlus> :silent! foldopen<CR>
+ nnoremap <buffer> <silent> <kMinus> :silent! foldclose<CR>
+ nnoremap <buffer> <silent> <kMultiply> :silent! %foldopen!<CR>
+ nnoremap <buffer> <silent> <Space> :call <SID>Tlist_Window_Show_Info()<CR>
+ nnoremap <buffer> <silent> u :call <SID>Tlist_Window_Update_File()<CR>
+ nnoremap <buffer> <silent> d :call <SID>Tlist_Remove_File(-1, 1)<CR>
+ nnoremap <buffer> <silent> x :call <SID>Tlist_Window_Zoom()<CR>
+ nnoremap <buffer> <silent> [[ :call <SID>Tlist_Window_Move_To_File(-1)<CR>
+ nnoremap <buffer> <silent> <BS> :call <SID>Tlist_Window_Move_To_File(-1)<CR>
+ nnoremap <buffer> <silent> ]] :call <SID>Tlist_Window_Move_To_File(1)<CR>
+ nnoremap <buffer> <silent> <Tab> :call <SID>Tlist_Window_Move_To_File(1)<CR>
+ nnoremap <buffer> <silent> <F1> :call <SID>Tlist_Window_Toggle_Help_Text()<CR>
+ nnoremap <buffer> <silent> q :close<CR>
+
+ " Insert mode mappings
+ inoremap <buffer> <silent> <CR>
+ \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('useopen')<CR>
+ " Windows needs return
+ inoremap <buffer> <silent> <Return>
+ \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('useopen')<CR>
+ inoremap <buffer> <silent> o
+ \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('newwin')<CR>
+ inoremap <buffer> <silent> p
+ \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('preview')<CR>
+ inoremap <buffer> <silent> P
+ \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('prevwin')<CR>
+ if v:version >= 700
+ inoremap <buffer> <silent> t
+ \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('checktab')<CR>
+ inoremap <buffer> <silent> <C-t>
+ \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('newtab')<CR>
+ endif
+ inoremap <buffer> <silent> <2-LeftMouse>
+ \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('useopen')<CR>
+ inoremap <buffer> <silent> s
+ \ <C-o>:call <SID>Tlist_Change_Sort('cmd', 'toggle', '')<CR>
+ inoremap <buffer> <silent> + <C-o>:silent! foldopen<CR>
+ inoremap <buffer> <silent> - <C-o>:silent! foldclose<CR>
+ inoremap <buffer> <silent> * <C-o>:silent! %foldopen!<CR>
+ inoremap <buffer> <silent> = <C-o>:silent! %foldclose<CR>
+ inoremap <buffer> <silent> <kPlus> <C-o>:silent! foldopen<CR>
+ inoremap <buffer> <silent> <kMinus> <C-o>:silent! foldclose<CR>
+ inoremap <buffer> <silent> <kMultiply> <C-o>:silent! %foldopen!<CR>
+ inoremap <buffer> <silent> <Space> <C-o>:call
+ \ <SID>Tlist_Window_Show_Info()<CR>
+ inoremap <buffer> <silent> u
+ \ <C-o>:call <SID>Tlist_Window_Update_File()<CR>
+ inoremap <buffer> <silent> d <C-o>:call <SID>Tlist_Remove_File(-1, 1)<CR>
+ inoremap <buffer> <silent> x <C-o>:call <SID>Tlist_Window_Zoom()<CR>
+ inoremap <buffer> <silent> [[ <C-o>:call <SID>Tlist_Window_Move_To_File(-1)<CR>
+ inoremap <buffer> <silent> <BS> <C-o>:call <SID>Tlist_Window_Move_To_File(-1)<CR>
+ inoremap <buffer> <silent> ]] <C-o>:call <SID>Tlist_Window_Move_To_File(1)<CR>
+ inoremap <buffer> <silent> <Tab> <C-o>:call <SID>Tlist_Window_Move_To_File(1)<CR>
+ inoremap <buffer> <silent> <F1> <C-o>:call <SID>Tlist_Window_Toggle_Help_Text()<CR>
+ inoremap <buffer> <silent> q <C-o>:close<CR>
+
+ " Map single left mouse click if the user wants this functionality
+ if g:Tlist_Use_SingleClick == 1
+ " Contributed by Bindu Wavell
+ " attempt to perform single click mapping, it would be much
+ " nicer if we could nnoremap <buffer> ... however vim does
+ " not fire the <buffer> <leftmouse> when you use the mouse
+ " to enter a buffer.
+ let clickmap = ':if bufname("%") =~ "__Tag_List__" <bar> ' .
+ \ 'call <SID>Tlist_Window_Jump_To_Tag("useopen") ' .
+ \ '<bar> endif <CR>'
+ if maparg('<leftmouse>', 'n') == ''
+ " no mapping for leftmouse
+ exe ':nnoremap <silent> <leftmouse> <leftmouse>' . clickmap
+ else
+ " we have a mapping
+ let mapcmd = ':nnoremap <silent> <leftmouse> <leftmouse>'
+ let mapcmd = mapcmd . substitute(substitute(
+ \ maparg('<leftmouse>', 'n'), '|', '<bar>', 'g'),
+ \ '\c^<leftmouse>', '', '')
+ let mapcmd = mapcmd . clickmap
+ exe mapcmd
+ endif
+ endif
+
+ " Define the taglist autocommands
+ augroup TagListAutoCmds
+ autocmd!
+ " Display the tag prototype for the tag under the cursor.
+ autocmd CursorHold __Tag_List__ call s:Tlist_Window_Show_Info()
+ " Highlight the current tag periodically
+ autocmd CursorHold * silent call s:Tlist_Window_Highlight_Tag(
+ \ fnamemodify(bufname('%'), ':p'), line('.'), 1, 0)
+
+ " Adjust the Vim window width when taglist window is closed
+ autocmd BufUnload __Tag_List__ call s:Tlist_Post_Close_Cleanup()
+ " Close the fold for this buffer when leaving the buffer
+ if g:Tlist_File_Fold_Auto_Close
+ autocmd BufEnter * silent
+ \ call s:Tlist_Window_Open_File_Fold(expand('<abuf>'))
+ endif
+ " Exit Vim itself if only the taglist window is present (optional)
+ if g:Tlist_Exit_OnlyWindow
+ autocmd BufEnter __Tag_List__ nested
+ \ call s:Tlist_Window_Exit_Only_Window()
+ endif
+ if s:tlist_app_name != "winmanager" &&
+ \ !g:Tlist_Process_File_Always &&
+ \ (!has('gui_running') || !g:Tlist_Show_Menu)
+ " Auto refresh the taglist window
+ autocmd BufEnter * call s:Tlist_Refresh()
+ endif
+
+ if !g:Tlist_Use_Horiz_Window
+ if v:version < 700
+ autocmd WinEnter * call s:Tlist_Window_Check_Width()
+ endif
+ endif
+ if v:version >= 700
+ autocmd TabEnter * silent call s:Tlist_Refresh_Folds()
+ endif
+ augroup end
+
+ " Restore the previous cpoptions settings
+ let &cpoptions = old_cpoptions
+endfunction
+
+" Tlist_Window_Refresh
+" Display the tags for all the files in the taglist window
+function! s:Tlist_Window_Refresh()
+ call s:Tlist_Log_Msg('Tlist_Window_Refresh()')
+ " Set report option to a huge value to prevent informational messages
+ " while deleting the lines
+ let old_report = &report
+ set report=99999
+
+ " Mark the buffer as modifiable
+ setlocal modifiable
+
+ " Delete the contents of the buffer to the black-hole register
+ silent! %delete _
+
+ " As we have cleared the taglist window, mark all the files
+ " as not visible
+ let i = 0
+ while i < s:tlist_file_count
+ let s:tlist_{i}_visible = 0
+ let i = i + 1
+ endwhile
+
+ if g:Tlist_Compact_Format == 0
+ " Display help in non-compact mode
+ call s:Tlist_Window_Display_Help()
+ endif
+
+ " Mark the buffer as not modifiable
+ setlocal nomodifiable
+
+ " Restore the report option
+ let &report = old_report
+
+ " If the tags for only one file should be displayed in the taglist
+ " window, then no need to add the tags here. The bufenter autocommand
+ " will add the tags for that file.
+ if g:Tlist_Show_One_File
+ return
+ endif
+
+ " List all the tags for the previously processed files
+ " Do this only if taglist is configured to display tags for more than
+ " one file. Otherwise, when Tlist_Show_One_File is configured,
+ " tags for the wrong file will be displayed.
+ let i = 0
+ while i < s:tlist_file_count
+ call s:Tlist_Window_Refresh_File(s:tlist_{i}_filename,
+ \ s:tlist_{i}_filetype)
+ let i = i + 1
+ endwhile
+
+ if g:Tlist_Auto_Update
+ " Add and list the tags for all buffers in the Vim buffer list
+ let i = 1
+ let last_bufnum = bufnr('$')
+ while i <= last_bufnum
+ if buflisted(i)
+ let fname = fnamemodify(bufname(i), ':p')
+ let ftype = s:Tlist_Get_Buffer_Filetype(i)
+ " If the file doesn't support tag listing, skip it
+ if !s:Tlist_Skip_File(fname, ftype)
+ call s:Tlist_Window_Refresh_File(fname, ftype)
+ endif
+ endif
+ let i = i + 1
+ endwhile
+ endif
+
+ " If Tlist_File_Fold_Auto_Close option is set, then close all the folds
+ if g:Tlist_File_Fold_Auto_Close
+ " Close all the folds
+ silent! %foldclose
+ endif
+
+ " Move the cursor to the top of the taglist window
+ normal! gg
+endfunction
+
+" Tlist_Post_Close_Cleanup()
+" Close the taglist window and adjust the Vim window width
+function! s:Tlist_Post_Close_Cleanup()
+ call s:Tlist_Log_Msg('Tlist_Post_Close_Cleanup()')
+ " Mark all the files as not visible
+ let i = 0
+ while i < s:tlist_file_count
+ let s:tlist_{i}_visible = 0
+ let i = i + 1
+ endwhile
+
+ " Remove the taglist autocommands
+ silent! autocmd! TagListAutoCmds
+
+ " Clear all the highlights
+ match none
+
+ silent! syntax clear TagListTitle
+ silent! syntax clear TagListComment
+ silent! syntax clear TagListTagScope
+
+ " Remove the left mouse click mapping if it was setup initially
+ if g:Tlist_Use_SingleClick
+ if hasmapto('<LeftMouse>')
+ nunmap <LeftMouse>
+ endif
+ endif
+
+ if s:tlist_app_name != "winmanager"
+ if g:Tlist_Use_Horiz_Window || g:Tlist_Inc_Winwidth == 0 ||
+ \ s:tlist_winsize_chgd != 1 ||
+ \ &columns < (80 + g:Tlist_WinWidth)
+ " No need to adjust window width if using horizontally split taglist
+ " window or if columns is less than 101 or if the user chose not to
+ " adjust the window width
+ else
+ " If the user didn't manually move the window, then restore the window
+ " position to the pre-taglist position
+ if s:tlist_pre_winx != -1 && s:tlist_pre_winy != -1 &&
+ \ getwinposx() == s:tlist_winx &&
+ \ getwinposy() == s:tlist_winy
+ exe 'winpos ' . s:tlist_pre_winx . ' ' . s:tlist_pre_winy
+ endif
+
+ " Adjust the Vim window width
+ let &columns= &columns - (g:Tlist_WinWidth + 1)
+ endif
+ endif
+
+ let s:tlist_winsize_chgd = -1
+
+ " Reset taglist state variables
+ if s:tlist_app_name == "winmanager"
+ let s:tlist_app_name = "none"
+ endif
+ let s:tlist_window_initialized = 0
+endfunction
+
+" Tlist_Window_Refresh_File()
+" List the tags defined in the specified file in a Vim window
+function! s:Tlist_Window_Refresh_File(filename, ftype)
+ call s:Tlist_Log_Msg('Tlist_Window_Refresh_File (' . a:filename . ')')
+ " First check whether the file already exists
+ let fidx = s:Tlist_Get_File_Index(a:filename)
+ if fidx != -1
+ let file_listed = 1
+ else
+ let file_listed = 0
+ endif
+
+ if !file_listed
+ " Check whether this file is removed based on user request
+ " If it is, then don't display the tags for this file
+ if s:Tlist_User_Removed_File(a:filename)
+ return
+ endif
+ endif
+
+ if file_listed && s:tlist_{fidx}_visible
+ " Check whether the file tags are currently valid
+ if s:tlist_{fidx}_valid
+ " Goto the first line in the file
+ exe s:tlist_{fidx}_start
+
+ " If the line is inside a fold, open the fold
+ if foldclosed('.') != -1
+ exe "silent! " . s:tlist_{fidx}_start . "," .
+ \ s:tlist_{fidx}_end . "foldopen!"
+ endif
+ return
+ endif
+
+ " Discard and remove the tags for this file from display
+ call s:Tlist_Discard_TagInfo(fidx)
+ call s:Tlist_Window_Remove_File_From_Display(fidx)
+ endif
+
+ " Process and generate a list of tags defined in the file
+ if !file_listed || !s:tlist_{fidx}_valid
+ let ret_fidx = s:Tlist_Process_File(a:filename, a:ftype)
+ if ret_fidx == -1
+ return
+ endif
+ let fidx = ret_fidx
+ endif
+
+ " Set report option to a huge value to prevent informational messages
+ " while adding lines to the taglist window
+ let old_report = &report
+ set report=99999
+
+ if g:Tlist_Show_One_File
+ " Remove the previous file
+ if s:tlist_cur_file_idx != -1
+ call s:Tlist_Window_Remove_File_From_Display(s:tlist_cur_file_idx)
+ let s:tlist_{s:tlist_cur_file_idx}_visible = 0
+ let s:tlist_{s:tlist_cur_file_idx}_start = 0
+ let s:tlist_{s:tlist_cur_file_idx}_end = 0
+ endif
+ let s:tlist_cur_file_idx = fidx
+ endif
+
+ " Mark the buffer as modifiable
+ setlocal modifiable
+
+ " Add new files to the end of the window. For existing files, add them at
+ " the same line where they were previously present. If the file is not
+ " visible, then add it at the end
+ if s:tlist_{fidx}_start == 0 || !s:tlist_{fidx}_visible
+ if g:Tlist_Compact_Format
+ let s:tlist_{fidx}_start = line('$')
+ else
+ let s:tlist_{fidx}_start = line('$') + 1
+ endif
+ endif
+
+ let s:tlist_{fidx}_visible = 1
+
+ " Goto the line where this file should be placed
+ if g:Tlist_Compact_Format
+ exe s:tlist_{fidx}_start
+ else
+ exe s:tlist_{fidx}_start - 1
+ endif
+
+ let txt = fnamemodify(s:tlist_{fidx}_filename, ':t') . ' (' .
+ \ fnamemodify(s:tlist_{fidx}_filename, ':p:h') . ')'
+ if g:Tlist_Compact_Format == 0
+ silent! put =txt
+ else
+ silent! put! =txt
+ " Move to the next line
+ exe line('.') + 1
+ endif
+ let file_start = s:tlist_{fidx}_start
+
+ " Add the tag names grouped by tag type to the buffer with a title
+ let i = 1
+ let ttype_cnt = s:tlist_{a:ftype}_count
+ while i <= ttype_cnt
+ let ttype = s:tlist_{a:ftype}_{i}_name
+ " Add the tag type only if there are tags for that type
+ let fidx_ttype = 's:tlist_' . fidx . '_' . ttype
+ let ttype_txt = {fidx_ttype}
+ if ttype_txt != ''
+ let txt = ' ' . s:tlist_{a:ftype}_{i}_fullname
+ if g:Tlist_Compact_Format == 0
+ let ttype_start_lnum = line('.') + 1
+ silent! put =txt
+ else
+ let ttype_start_lnum = line('.')
+ silent! put! =txt
+ endif
+ silent! put =ttype_txt
+
+ let {fidx_ttype}_offset = ttype_start_lnum - file_start
+
+ " create a fold for this tag type
+ let fold_start = ttype_start_lnum
+ let fold_end = fold_start + {fidx_ttype}_count
+ exe fold_start . ',' . fold_end . 'fold'
+
+ " Adjust the cursor position
+ if g:Tlist_Compact_Format == 0
+ exe ttype_start_lnum + {fidx_ttype}_count
+ else
+ exe ttype_start_lnum + {fidx_ttype}_count + 1
+ endif
+
+ if g:Tlist_Compact_Format == 0
+ " Separate the tag types by a empty line
+ silent! put =''
+ endif
+ endif
+ let i = i + 1
+ endwhile
+
+ if s:tlist_{fidx}_tag_count == 0
+ if g:Tlist_Compact_Format == 0
+ silent! put =''
+ endif
+ endif
+
+ let s:tlist_{fidx}_end = line('.') - 1
+
+ " Create a fold for the entire file
+ exe s:tlist_{fidx}_start . ',' . s:tlist_{fidx}_end . 'fold'
+ exe 'silent! ' . s:tlist_{fidx}_start . ',' .
+ \ s:tlist_{fidx}_end . 'foldopen!'
+
+ " Goto the starting line for this file,
+ exe s:tlist_{fidx}_start
+
+ if s:tlist_app_name == "winmanager"
+ " To handle a bug in the winmanager plugin, add a space at the
+ " last line
+ call setline('$', ' ')
+ endif
+
+ " Mark the buffer as not modifiable
+ setlocal nomodifiable
+
+ " Restore the report option
+ let &report = old_report
+
+ " Update the start and end line numbers for all the files following this
+ " file
+ let start = s:tlist_{fidx}_start
+ " include the empty line after the last line
+ if g:Tlist_Compact_Format
+ let end = s:tlist_{fidx}_end
+ else
+ let end = s:tlist_{fidx}_end + 1
+ endif
+ call s:Tlist_Window_Update_Line_Offsets(fidx + 1, 1, end - start + 1)
+
+ " Now that we have updated the taglist window, update the tags
+ " menu (if present)
+ if g:Tlist_Show_Menu
+ call s:Tlist_Menu_Update_File(1)
+ endif
+endfunction
+
+" Tlist_Init_File
+" Initialize the variables for a new file
+function! s:Tlist_Init_File(filename, ftype)
+ call s:Tlist_Log_Msg('Tlist_Init_File (' . a:filename . ')')
+ " Add new files at the end of the list
+ let fidx = s:tlist_file_count
+ let s:tlist_file_count = s:tlist_file_count + 1
+ " Add the new file name to the taglist list of file names
+ let s:tlist_file_names = s:tlist_file_names . a:filename . "\n"
+
+ " Initialize the file variables
+ let s:tlist_{fidx}_filename = a:filename
+ let s:tlist_{fidx}_sort_type = g:Tlist_Sort_Type
+ let s:tlist_{fidx}_filetype = a:ftype
+ let s:tlist_{fidx}_mtime = -1
+ let s:tlist_{fidx}_start = 0
+ let s:tlist_{fidx}_end = 0
+ let s:tlist_{fidx}_valid = 0
+ let s:tlist_{fidx}_visible = 0
+ let s:tlist_{fidx}_tag_count = 0
+ let s:tlist_{fidx}_menu_cmd = ''
+
+ " Initialize the tag type variables
+ let i = 1
+ while i <= s:tlist_{a:ftype}_count
+ let ttype = s:tlist_{a:ftype}_{i}_name
+ let s:tlist_{fidx}_{ttype} = ''
+ let s:tlist_{fidx}_{ttype}_offset = 0
+ let s:tlist_{fidx}_{ttype}_count = 0
+ let i = i + 1
+ endwhile
+
+ return fidx
+endfunction
+
+" Tlist_Get_Tag_Type_By_Tag
+" Return the tag type for the specified tag index
+function! s:Tlist_Get_Tag_Type_By_Tag(fidx, tidx)
+ let ttype_var = 's:tlist_' . a:fidx . '_' . a:tidx . '_tag_type'
+
+ " Already parsed and have the tag name
+ if exists(ttype_var)
+ return {ttype_var}
+ endif
+
+ let tag_line = s:tlist_{a:fidx}_{a:tidx}_tag
+ let {ttype_var} = s:Tlist_Extract_Tagtype(tag_line)
+
+ return {ttype_var}
+endfunction
+
+" Tlist_Get_Tag_Prototype
+function! s:Tlist_Get_Tag_Prototype(fidx, tidx)
+ let tproto_var = 's:tlist_' . a:fidx . '_' . a:tidx . '_tag_proto'
+
+ " Already parsed and have the tag prototype
+ if exists(tproto_var)
+ return {tproto_var}
+ endif
+
+ " Parse and extract the tag prototype
+ let tag_line = s:tlist_{a:fidx}_{a:tidx}_tag
+ let start = stridx(tag_line, '/^') + 2
+ let end = stridx(tag_line, '/;"' . "\t")
+ if tag_line[end - 1] == '$'
+ let end = end -1
+ endif
+ let tag_proto = strpart(tag_line, start, end - start)
+ let {tproto_var} = substitute(tag_proto, '\s*', '', '')
+
+ return {tproto_var}
+endfunction
+
+" Tlist_Get_Tag_SearchPat
+function! s:Tlist_Get_Tag_SearchPat(fidx, tidx)
+ let tpat_var = 's:tlist_' . a:fidx . '_' . a:tidx . '_tag_searchpat'
+
+ " Already parsed and have the tag search pattern
+ if exists(tpat_var)
+ return {tpat_var}
+ endif
+
+ " Parse and extract the tag search pattern
+ let tag_line = s:tlist_{a:fidx}_{a:tidx}_tag
+ let start = stridx(tag_line, '/^') + 2
+ let end = stridx(tag_line, '/;"' . "\t")
+ if tag_line[end - 1] == '$'
+ let end = end -1
+ endif
+ let {tpat_var} = '\V\^' . strpart(tag_line, start, end - start) .
+ \ (tag_line[end] == '$' ? '\$' : '')
+
+ return {tpat_var}
+endfunction
+
+" Tlist_Get_Tag_Linenum
+" Return the tag line number, given the tag index
+function! s:Tlist_Get_Tag_Linenum(fidx, tidx)
+ let tline_var = 's:tlist_' . a:fidx . '_' . a:tidx . '_tag_linenum'
+
+ " Already parsed and have the tag line number
+ if exists(tline_var)
+ return {tline_var}
+ endif
+
+ " Parse and extract the tag line number
+ let tag_line = s:tlist_{a:fidx}_{a:tidx}_tag
+ let start = strridx(tag_line, 'line:') + 5
+ let end = strridx(tag_line, "\t")
+ if end < start
+ let {tline_var} = strpart(tag_line, start) + 0
+ else
+ let {tline_var} = strpart(tag_line, start, end - start) + 0
+ endif
+
+ return {tline_var}
+endfunction
+
+" Tlist_Parse_Tagline
+" Parse a tag line from the ctags output. Separate the tag output based on the
+" tag type and store it in the tag type variable.
+" The format of each line in the ctags output is:
+"
+" tag_name<TAB>file_name<TAB>ex_cmd;"<TAB>extension_fields
+"
+function! s:Tlist_Parse_Tagline(tag_line)
+ if a:tag_line == ''
+ " Skip empty lines
+ return
+ endif
+
+ " Extract the tag type
+ let ttype = s:Tlist_Extract_Tagtype(a:tag_line)
+
+ " Make sure the tag type is a valid and supported one
+ if ttype == '' || stridx(s:ctags_flags, ttype) == -1
+ " Line is not in proper tags format or Tag type is not supported
+ return
+ endif
+
+ " Update the total tag count
+ let s:tidx = s:tidx + 1
+
+ " The following variables are used to optimize this code. Vim is slow in
+ " using curly brace names. To reduce the amount of processing needed, the
+ " curly brace variables are pre-processed here
+ let fidx_tidx = 's:tlist_' . s:fidx . '_' . s:tidx
+ let fidx_ttype = 's:tlist_' . s:fidx . '_' . ttype
+
+ " Update the count of this tag type
+ let ttype_idx = {fidx_ttype}_count + 1
+ let {fidx_ttype}_count = ttype_idx
+
+ " Store the ctags output for this tag
+ let {fidx_tidx}_tag = a:tag_line
+
+ " Store the tag index and the tag type index (back pointers)
+ let {fidx_ttype}_{ttype_idx} = s:tidx
+ let {fidx_tidx}_ttype_idx = ttype_idx
+
+ " Extract the tag name
+ let tag_name = strpart(a:tag_line, 0, stridx(a:tag_line, "\t"))
+
+ " Extract the tag scope/prototype
+ if g:Tlist_Display_Prototype
+ let ttxt = ' ' . s:Tlist_Get_Tag_Prototype(s:fidx, s:tidx)
+ else
+ let ttxt = ' ' . tag_name
+
+ " Add the tag scope, if it is available and is configured. Tag
+ " scope is the last field after the 'line:<num>\t' field
+ if g:Tlist_Display_Tag_Scope
+ let tag_scope = s:Tlist_Extract_Tag_Scope(a:tag_line)
+ if tag_scope != ''
+ let ttxt = ttxt . ' [' . tag_scope . ']'
+ endif
+ endif
+ endif
+
+ " Add this tag to the tag type variable
+ let {fidx_ttype} = {fidx_ttype} . ttxt . "\n"
+
+ " Save the tag name
+ let {fidx_tidx}_tag_name = tag_name
+endfunction
+
+" Tlist_Process_File
+" Get the list of tags defined in the specified file and store them
+" in Vim variables. Returns the file index where the tags are stored.
+function! s:Tlist_Process_File(filename, ftype)
+ call s:Tlist_Log_Msg('Tlist_Process_File (' . a:filename . ', ' .
+ \ a:ftype . ')')
+ " Check whether this file is supported
+ if s:Tlist_Skip_File(a:filename, a:ftype)
+ return -1
+ endif
+
+ " If the tag types for this filetype are not yet created, then create
+ " them now
+ let var = 's:tlist_' . a:ftype . '_count'
+ if !exists(var)
+ if s:Tlist_FileType_Init(a:ftype) == 0
+ return -1
+ endif
+ endif
+
+ " If this file is already processed, then use the cached values
+ let fidx = s:Tlist_Get_File_Index(a:filename)
+ if fidx == -1
+ " First time, this file is loaded
+ let fidx = s:Tlist_Init_File(a:filename, a:ftype)
+ else
+ " File was previously processed. Discard the tag information
+ call s:Tlist_Discard_TagInfo(fidx)
+ endif
+
+ let s:tlist_{fidx}_valid = 1
+
+ " Exuberant ctags arguments to generate a tag list
+ let ctags_args = ' -f - --format=2 --excmd=pattern --fields=nks '
+
+ " Form the ctags argument depending on the sort type
+ if s:tlist_{fidx}_sort_type == 'name'
+ let ctags_args = ctags_args . '--sort=yes'
+ else
+ let ctags_args = ctags_args . '--sort=no'
+ endif
+
+ " Add the filetype specific arguments
+ let ctags_args = ctags_args . ' ' . s:tlist_{a:ftype}_ctags_args
+
+ " Ctags command to produce output with regexp for locating the tags
+ let ctags_cmd = g:Tlist_Ctags_Cmd . ctags_args
+ let ctags_cmd = ctags_cmd . ' "' . a:filename . '"'
+
+ if &shellxquote == '"'
+ " Double-quotes within double-quotes will not work in the
+ " command-line.If the 'shellxquote' option is set to double-quotes,
+ " then escape the double-quotes in the ctags command-line.
+ let ctags_cmd = escape(ctags_cmd, '"')
+ endif
+
+ " In Windows 95, if not using cygwin, disable the 'shellslash'
+ " option. Otherwise, this will cause problems when running the
+ " ctags command.
+ if has('win95') && !has('win32unix')
+ let old_shellslash = &shellslash
+ set noshellslash
+ endif
+
+ if has('win32') && !has('win32unix') && !has('win95')
+ \ && (&shell =~ 'cmd.exe')
+ " Windows does not correctly deal with commands that have more than 1
+ " set of double quotes. It will strip them all resulting in:
+ " 'C:\Program' is not recognized as an internal or external command
+ " operable program or batch file. To work around this, place the
+ " command inside a batch file and call the batch file.
+ " Do this only on Win2K, WinXP and above.
+ " Contributed by: David Fishburn.
+ let s:taglist_tempfile = fnamemodify(tempname(), ':h') .
+ \ '\taglist.cmd'
+ exe 'redir! > ' . s:taglist_tempfile
+ silent echo ctags_cmd
+ redir END
+
+ call s:Tlist_Log_Msg('Cmd inside batch file: ' . ctags_cmd)
+ let ctags_cmd = '"' . s:taglist_tempfile . '"'
+ endif
+
+ call s:Tlist_Log_Msg('Cmd: ' . ctags_cmd)
+
+ " Run ctags and get the tag list
+ let cmd_output = system(ctags_cmd)
+
+ " Restore the value of the 'shellslash' option.
+ if has('win95') && !has('win32unix')
+ let &shellslash = old_shellslash
+ endif
+
+ if exists('s:taglist_tempfile')
+ " Delete the temporary cmd file created on MS-Windows
+ call delete(s:taglist_tempfile)
+ endif
+
+ " Handle errors
+ if v:shell_error
+ let msg = "Taglist: Failed to generate tags for " . a:filename
+ call s:Tlist_Warning_Msg(msg)
+ if cmd_output != ''
+ call s:Tlist_Warning_Msg(cmd_output)
+ endif
+ return fidx
+ endif
+
+ " Store the modification time for the file
+ let s:tlist_{fidx}_mtime = getftime(a:filename)
+
+ " No tags for current file
+ if cmd_output == ''
+ call s:Tlist_Log_Msg('No tags defined in ' . a:filename)
+ return fidx
+ endif
+
+ call s:Tlist_Log_Msg('Generated tags information for ' . a:filename)
+
+ if v:version > 601
+ " The following script local variables are used by the
+ " Tlist_Parse_Tagline() function.
+ let s:ctags_flags = s:tlist_{a:ftype}_ctags_flags
+ let s:fidx = fidx
+ let s:tidx = 0
+
+ " Process the ctags output one line at a time. The substitute()
+ " command is used to parse the tag lines instead of using the
+ " matchstr()/stridx()/strpart() functions for performance reason
+ call substitute(cmd_output, "\\([^\n]\\+\\)\n",
+ \ '\=s:Tlist_Parse_Tagline(submatch(1))', 'g')
+
+ " Save the number of tags for this file
+ let s:tlist_{fidx}_tag_count = s:tidx
+
+ " The following script local variables are no longer needed
+ unlet! s:ctags_flags
+ unlet! s:tidx
+ unlet! s:fidx
+ else
+ " Due to a bug in Vim earlier than version 6.1,
+ " we cannot use substitute() to parse the ctags output.
+ " Instead the slow str*() functions are used
+ let ctags_flags = s:tlist_{a:ftype}_ctags_flags
+ let tidx = 0
+
+ while cmd_output != ''
+ " Extract one line at a time
+ let idx = stridx(cmd_output, "\n")
+ let one_line = strpart(cmd_output, 0, idx)
+ " Remove the line from the tags output
+ let cmd_output = strpart(cmd_output, idx + 1)
+
+ if one_line == ''
+ " Line is not in proper tags format
+ continue
+ endif
+
+ " Extract the tag type
+ let ttype = s:Tlist_Extract_Tagtype(one_line)
+
+ " Make sure the tag type is a valid and supported one
+ if ttype == '' || stridx(ctags_flags, ttype) == -1
+ " Line is not in proper tags format or Tag type is not
+ " supported
+ continue
+ endif
+
+ " Update the total tag count
+ let tidx = tidx + 1
+
+ " The following variables are used to optimize this code. Vim is
+ " slow in using curly brace names. To reduce the amount of
+ " processing needed, the curly brace variables are pre-processed
+ " here
+ let fidx_tidx = 's:tlist_' . fidx . '_' . tidx
+ let fidx_ttype = 's:tlist_' . fidx . '_' . ttype
+
+ " Update the count of this tag type
+ let ttype_idx = {fidx_ttype}_count + 1
+ let {fidx_ttype}_count = ttype_idx
+
+ " Store the ctags output for this tag
+ let {fidx_tidx}_tag = one_line
+
+ " Store the tag index and the tag type index (back pointers)
+ let {fidx_ttype}_{ttype_idx} = tidx
+ let {fidx_tidx}_ttype_idx = ttype_idx
+
+ " Extract the tag name
+ let tag_name = strpart(one_line, 0, stridx(one_line, "\t"))
+
+ " Extract the tag scope/prototype
+ if g:Tlist_Display_Prototype
+ let ttxt = ' ' . s:Tlist_Get_Tag_Prototype(fidx, tidx)
+ else
+ let ttxt = ' ' . tag_name
+
+ " Add the tag scope, if it is available and is configured. Tag
+ " scope is the last field after the 'line:<num>\t' field
+ if g:Tlist_Display_Tag_Scope
+ let tag_scope = s:Tlist_Extract_Tag_Scope(one_line)
+ if tag_scope != ''
+ let ttxt = ttxt . ' [' . tag_scope . ']'
+ endif
+ endif
+ endif
+
+ " Add this tag to the tag type variable
+ let {fidx_ttype} = {fidx_ttype} . ttxt . "\n"
+
+ " Save the tag name
+ let {fidx_tidx}_tag_name = tag_name
+ endwhile
+
+ " Save the number of tags for this file
+ let s:tlist_{fidx}_tag_count = tidx
+ endif
+
+ call s:Tlist_Log_Msg('Processed ' . s:tlist_{fidx}_tag_count .
+ \ ' tags in ' . a:filename)
+
+ return fidx
+endfunction
+
+" Tlist_Update_File
+" Update the tags for a file (if needed)
+function! Tlist_Update_File(filename, ftype)
+ call s:Tlist_Log_Msg('Tlist_Update_File (' . a:filename . ')')
+ " If the file doesn't support tag listing, skip it
+ if s:Tlist_Skip_File(a:filename, a:ftype)
+ return
+ endif
+
+ " Convert the file name to a full path
+ let fname = fnamemodify(a:filename, ':p')
+
+ " First check whether the file already exists
+ let fidx = s:Tlist_Get_File_Index(fname)
+
+ if fidx != -1 && s:tlist_{fidx}_valid
+ " File exists and the tags are valid
+ " Check whether the file was modified after the last tags update
+ " If it is modified, then update the tags
+ if s:tlist_{fidx}_mtime == getftime(fname)
+ return
+ endif
+ else
+ " If the tags were removed previously based on a user request,
+ " as we are going to update the tags (based on the user request),
+ " remove the filename from the deleted list
+ call s:Tlist_Update_Remove_List(fname, 0)
+ endif
+
+ " If the taglist window is opened, update it
+ let winnum = bufwinnr(g:TagList_title)
+ if winnum == -1
+ " Taglist window is not present. Just update the taglist
+ " and return
+ call s:Tlist_Process_File(fname, a:ftype)
+ else
+ if g:Tlist_Show_One_File && s:tlist_cur_file_idx != -1
+ " If tags for only one file are displayed and we are not
+ " updating the tags for that file, then no need to
+ " refresh the taglist window. Otherwise, the taglist
+ " window should be updated.
+ if s:tlist_{s:tlist_cur_file_idx}_filename != fname
+ call s:Tlist_Process_File(fname, a:ftype)
+ return
+ endif
+ endif
+
+ " Save the current window number
+ let save_winnr = winnr()
+
+ " Goto the taglist window
+ call s:Tlist_Window_Goto_Window()
+
+ " Save the cursor position
+ let save_line = line('.')
+ let save_col = col('.')
+
+ " Update the taglist window
+ call s:Tlist_Window_Refresh_File(fname, a:ftype)
+
+ " Restore the cursor position
+ if v:version >= 601
+ call cursor(save_line, save_col)
+ else
+ exe save_line
+ exe 'normal! ' . save_col . '|'
+ endif
+
+ if winnr() != save_winnr
+ " Go back to the original window
+ call s:Tlist_Exe_Cmd_No_Acmds(save_winnr . 'wincmd w')
+ endif
+ endif
+
+ " Update the taglist menu
+ if g:Tlist_Show_Menu
+ call s:Tlist_Menu_Update_File(1)
+ endif
+endfunction
+
+" Tlist_Window_Close
+" Close the taglist window
+function! s:Tlist_Window_Close()
+ call s:Tlist_Log_Msg('Tlist_Window_Close()')
+ " Make sure the taglist window exists
+ let winnum = bufwinnr(g:TagList_title)
+ if winnum == -1
+ call s:Tlist_Warning_Msg('Error: Taglist window is not open')
+ return
+ endif
+
+ if winnr() == winnum
+ " Already in the taglist window. Close it and return
+ if winbufnr(2) != -1
+ " If a window other than the taglist window is open,
+ " then only close the taglist window.
+ close
+ endif
+ else
+ " Goto the taglist window, close it and then come back to the
+ " original window
+ let curbufnr = bufnr('%')
+ exe winnum . 'wincmd w'
+ close
+ " Need to jump back to the original window only if we are not
+ " already in that window
+ let winnum = bufwinnr(curbufnr)
+ if winnr() != winnum
+ exe winnum . 'wincmd w'
+ endif
+ endif
+endfunction
+
+" Tlist_Window_Mark_File_Window
+" Mark the current window as the file window to use when jumping to a tag.
+" Only if the current window is a non-plugin, non-preview and non-taglist
+" window
+function! s:Tlist_Window_Mark_File_Window()
+ if getbufvar('%', '&buftype') == '' && !&previewwindow
+ let w:tlist_file_window = "yes"
+ endif
+endfunction
+
+" Tlist_Window_Open
+" Open and refresh the taglist window
+function! s:Tlist_Window_Open()
+ call s:Tlist_Log_Msg('Tlist_Window_Open()')
+ " If the window is open, jump to it
+ let winnum = bufwinnr(g:TagList_title)
+ if winnum != -1
+ " Jump to the existing window
+ if winnr() != winnum
+ exe winnum . 'wincmd w'
+ endif
+ return
+ endif
+
+ if s:tlist_app_name == "winmanager"
+ " Taglist plugin is no longer part of the winmanager app
+ let s:tlist_app_name = "none"
+ endif
+
+ " Get the filename and filetype for the specified buffer
+ let curbuf_name = fnamemodify(bufname('%'), ':p')
+ let curbuf_ftype = s:Tlist_Get_Buffer_Filetype('%')
+ let cur_lnum = line('.')
+
+ " Mark the current window as the desired window to open a file when a tag
+ " is selected.
+ call s:Tlist_Window_Mark_File_Window()
+
+ " Open the taglist window
+ call s:Tlist_Window_Create()
+
+ call s:Tlist_Window_Refresh()
+
+ if g:Tlist_Show_One_File
+ " Add only the current buffer and file
+ "
+ " If the file doesn't support tag listing, skip it
+ if !s:Tlist_Skip_File(curbuf_name, curbuf_ftype)
+ call s:Tlist_Window_Refresh_File(curbuf_name, curbuf_ftype)
+ endif
+ endif
+
+ if g:Tlist_File_Fold_Auto_Close
+ " Open the fold for the current file, as all the folds in
+ " the taglist window are closed
+ let fidx = s:Tlist_Get_File_Index(curbuf_name)
+ if fidx != -1
+ exe "silent! " . s:tlist_{fidx}_start . "," .
+ \ s:tlist_{fidx}_end . "foldopen!"
+ endif
+ endif
+
+ " Highlight the current tag
+ call s:Tlist_Window_Highlight_Tag(curbuf_name, cur_lnum, 1, 1)
+endfunction
+
+" Tlist_Window_Toggle()
+" Open or close a taglist window
+function! s:Tlist_Window_Toggle()
+ call s:Tlist_Log_Msg('Tlist_Window_Toggle()')
+ " If taglist window is open then close it.
+ let winnum = bufwinnr(g:TagList_title)
+ if winnum != -1
+ call s:Tlist_Window_Close()
+ return
+ endif
+
+ call s:Tlist_Window_Open()
+
+ " Go back to the original window, if Tlist_GainFocus_On_ToggleOpen is not
+ " set
+ if !g:Tlist_GainFocus_On_ToggleOpen
+ call s:Tlist_Exe_Cmd_No_Acmds('wincmd p')
+ endif
+
+ " Update the taglist menu
+ if g:Tlist_Show_Menu
+ call s:Tlist_Menu_Update_File(0)
+ endif
+endfunction
+
+" Tlist_Process_Filelist
+" Process multiple files. Each filename is separated by "\n"
+" Returns the number of processed files
+function! s:Tlist_Process_Filelist(file_names)
+ let flist = a:file_names
+
+ " Enable lazy screen updates
+ let old_lazyredraw = &lazyredraw
+ set lazyredraw
+
+ " Keep track of the number of processed files
+ let fcnt = 0
+
+ " Process one file at a time
+ while flist != ''
+ let nl_idx = stridx(flist, "\n")
+ let one_file = strpart(flist, 0, nl_idx)
+
+ " Remove the filename from the list
+ let flist = strpart(flist, nl_idx + 1)
+
+ if one_file == ''
+ continue
+ endif
+
+ " Skip directories
+ if isdirectory(one_file)
+ continue
+ endif
+
+ let ftype = s:Tlist_Detect_Filetype(one_file)
+
+ echon "\r "
+ echon "\rProcessing tags for " . fnamemodify(one_file, ':p:t')
+
+ let fcnt = fcnt + 1
+
+ call Tlist_Update_File(one_file, ftype)
+ endwhile
+
+ " Clear the displayed informational messages
+ echon "\r "
+
+ " Restore the previous state
+ let &lazyredraw = old_lazyredraw
+
+ return fcnt
+endfunction
+
+" Tlist_Process_Dir
+" Process the files in a directory matching the specified pattern
+function! s:Tlist_Process_Dir(dir_name, pat)
+ let flist = glob(a:dir_name . '/' . a:pat) . "\n"
+
+ let fcnt = s:Tlist_Process_Filelist(flist)
+
+ let len = strlen(a:dir_name)
+ if a:dir_name[len - 1] == '\' || a:dir_name[len - 1] == '/'
+ let glob_expr = a:dir_name . '*'
+ else
+ let glob_expr = a:dir_name . '/*'
+ endif
+ let all_files = glob(glob_expr) . "\n"
+
+ while all_files != ''
+ let nl_idx = stridx(all_files, "\n")
+ let one_file = strpart(all_files, 0, nl_idx)
+
+ let all_files = strpart(all_files, nl_idx + 1)
+ if one_file == ''
+ continue
+ endif
+
+ " Skip non-directory names
+ if !isdirectory(one_file)
+ continue
+ endif
+
+ echon "\r "
+ echon "\rProcessing files in directory " . fnamemodify(one_file, ':t')
+ let fcnt = fcnt + s:Tlist_Process_Dir(one_file, a:pat)
+ endwhile
+
+ return fcnt
+endfunction
+
+" Tlist_Add_Files_Recursive
+" Add files recursively from a directory
+function! s:Tlist_Add_Files_Recursive(dir, ...)
+ let dir_name = fnamemodify(a:dir, ':p')
+ if !isdirectory(dir_name)
+ call s:Tlist_Warning_Msg('Error: ' . dir_name . ' is not a directory')
+ return
+ endif
+
+ if a:0 == 1
+ " User specified file pattern
+ let pat = a:1
+ else
+ " Default file pattern
+ let pat = '*'
+ endif
+
+ echon "\r "
+ echon "\rProcessing files in directory " . fnamemodify(dir_name, ':t')
+ let fcnt = s:Tlist_Process_Dir(dir_name, pat)
+
+ echon "\rAdded " . fcnt . " files to the taglist"
+endfunction
+
+" Tlist_Add_Files
+" Add the specified list of files to the taglist
+function! s:Tlist_Add_Files(...)
+ let flist = ''
+ let i = 1
+
+ " Get all the files matching the file patterns supplied as argument
+ while i <= a:0
+ let flist = flist . glob(a:{i}) . "\n"
+ let i = i + 1
+ endwhile
+
+ if flist == ''
+ call s:Tlist_Warning_Msg('Error: No matching files are found')
+ return
+ endif
+
+ let fcnt = s:Tlist_Process_Filelist(flist)
+ echon "\rAdded " . fcnt . " files to the taglist"
+endfunction
+
+" Tlist_Extract_Tagtype
+" Extract the tag type from the tag text
+function! s:Tlist_Extract_Tagtype(tag_line)
+ " The tag type is after the tag prototype field. The prototype field
+ " ends with the /;"\t string. We add 4 at the end to skip the characters
+ " in this special string..
+ let start = strridx(a:tag_line, '/;"' . "\t") + 4
+ let end = strridx(a:tag_line, 'line:') - 1
+ let ttype = strpart(a:tag_line, start, end - start)
+
+ return ttype
+endfunction
+
+" Tlist_Extract_Tag_Scope
+" Extract the tag scope from the tag text
+function! s:Tlist_Extract_Tag_Scope(tag_line)
+ let start = strridx(a:tag_line, 'line:')
+ let end = strridx(a:tag_line, "\t")
+ if end <= start
+ return ''
+ endif
+
+ let tag_scope = strpart(a:tag_line, end + 1)
+ let tag_scope = strpart(tag_scope, stridx(tag_scope, ':') + 1)
+
+ return tag_scope
+endfunction
+
+" Tlist_Refresh()
+" Refresh the taglist
+function! s:Tlist_Refresh()
+ call s:Tlist_Log_Msg('Tlist_Refresh (Skip_Refresh = ' .
+ \ s:Tlist_Skip_Refresh . ', ' . bufname('%') . ')')
+ " If we are entering the buffer from one of the taglist functions, then
+ " no need to refresh the taglist window again.
+ if s:Tlist_Skip_Refresh
+ " We still need to update the taglist menu
+ if g:Tlist_Show_Menu
+ call s:Tlist_Menu_Update_File(0)
+ endif
+ return
+ endif
+
+ " If part of the winmanager plugin and not configured to process
+ " tags always and not configured to display the tags menu, then return
+ if (s:tlist_app_name == 'winmanager') && !g:Tlist_Process_File_Always
+ \ && !g:Tlist_Show_Menu
+ return
+ endif
+
+ " Skip buffers with 'buftype' set to nofile, nowrite, quickfix or help
+ if &buftype != ''
+ return
+ endif
+
+ let filename = fnamemodify(bufname('%'), ':p')
+ let ftype = s:Tlist_Get_Buffer_Filetype('%')
+
+ " If the file doesn't support tag listing, skip it
+ if s:Tlist_Skip_File(filename, ftype)
+ return
+ endif
+
+ let tlist_win = bufwinnr(g:TagList_title)
+
+ " If the taglist window is not opened and not configured to process
+ " tags always and not displaying the tags menu, then return
+ if tlist_win == -1 && !g:Tlist_Process_File_Always && !g:Tlist_Show_Menu
+ return
+ endif
+
+ let fidx = s:Tlist_Get_File_Index(filename)
+ if fidx == -1
+ " Check whether this file is removed based on user request
+ " If it is, then don't display the tags for this file
+ if s:Tlist_User_Removed_File(filename)
+ return
+ endif
+
+ " If the taglist should not be auto updated, then return
+ if !g:Tlist_Auto_Update
+ return
+ endif
+ endif
+
+ let cur_lnum = line('.')
+
+ if fidx == -1
+ " Update the tags for the file
+ let fidx = s:Tlist_Process_File(filename, ftype)
+ else
+ let mtime = getftime(filename)
+ if s:tlist_{fidx}_mtime != mtime
+ " Invalidate the tags listed for this file
+ let s:tlist_{fidx}_valid = 0
+
+ " Update the taglist and the window
+ call Tlist_Update_File(filename, ftype)
+
+ " Store the new file modification time
+ let s:tlist_{fidx}_mtime = mtime
+ endif
+ endif
+
+ " Update the taglist window
+ if tlist_win != -1
+ " Disable screen updates
+ let old_lazyredraw = &lazyredraw
+ set nolazyredraw
+
+ " Save the current window number
+ let save_winnr = winnr()
+
+ " Goto the taglist window
+ call s:Tlist_Window_Goto_Window()
+
+ if !g:Tlist_Auto_Highlight_Tag || !g:Tlist_Highlight_Tag_On_BufEnter
+ " Save the cursor position
+ let save_line = line('.')
+ let save_col = col('.')
+ endif
+
+ " Update the taglist window
+ call s:Tlist_Window_Refresh_File(filename, ftype)
+
+ " Open the fold for the file
+ exe "silent! " . s:tlist_{fidx}_start . "," .
+ \ s:tlist_{fidx}_end . "foldopen!"
+
+ if g:Tlist_Highlight_Tag_On_BufEnter && g:Tlist_Auto_Highlight_Tag
+ if g:Tlist_Show_One_File && s:tlist_cur_file_idx != fidx
+ " If displaying tags for only one file in the taglist
+ " window and about to display the tags for a new file,
+ " then center the current tag line for the new file
+ let center_tag_line = 1
+ else
+ let center_tag_line = 0
+ endif
+
+ " Highlight the current tag
+ call s:Tlist_Window_Highlight_Tag(filename, cur_lnum, 1, center_tag_line)
+ else
+ " Restore the cursor position
+ if v:version >= 601
+ call cursor(save_line, save_col)
+ else
+ exe save_line
+ exe 'normal! ' . save_col . '|'
+ endif
+ endif
+
+ " Jump back to the original window
+ if save_winnr != winnr()
+ call s:Tlist_Exe_Cmd_No_Acmds(save_winnr . 'wincmd w')
+ endif
+
+ " Restore screen updates
+ let &lazyredraw = old_lazyredraw
+ endif
+
+ " Update the taglist menu
+ if g:Tlist_Show_Menu
+ call s:Tlist_Menu_Update_File(0)
+ endif
+endfunction
+
+" Tlist_Change_Sort()
+" Change the sort order of the tag listing
+" caller == 'cmd', command used in the taglist window
+" caller == 'menu', taglist menu
+" action == 'toggle', toggle sort from name to order and vice versa
+" action == 'set', set the sort order to sort_type
+function! s:Tlist_Change_Sort(caller, action, sort_type)
+ call s:Tlist_Log_Msg('Tlist_Change_Sort (caller = ' . a:caller .
+ \ ', action = ' . a:action . ', sort_type = ' . a:sort_type . ')')
+ if a:caller == 'cmd'
+ let fidx = s:Tlist_Window_Get_File_Index_By_Linenum(line('.'))
+ if fidx == -1
+ return
+ endif
+
+ " Remove the previous highlighting
+ match none
+ elseif a:caller == 'menu'
+ let fidx = s:Tlist_Get_File_Index(fnamemodify(bufname('%'), ':p'))
+ if fidx == -1
+ return
+ endif
+ endif
+
+ if a:action == 'toggle'
+ let sort_type = s:tlist_{fidx}_sort_type
+
+ " Toggle the sort order from 'name' to 'order' and vice versa
+ if sort_type == 'name'
+ let s:tlist_{fidx}_sort_type = 'order'
+ else
+ let s:tlist_{fidx}_sort_type = 'name'
+ endif
+ else
+ let s:tlist_{fidx}_sort_type = a:sort_type
+ endif
+
+ " Invalidate the tags listed for this file
+ let s:tlist_{fidx}_valid = 0
+
+ if a:caller == 'cmd'
+ " Save the current line for later restoration
+ let curline = '\V\^' . getline('.') . '\$'
+
+ call s:Tlist_Window_Refresh_File(s:tlist_{fidx}_filename,
+ \ s:tlist_{fidx}_filetype)
+
+ exe s:tlist_{fidx}_start . ',' . s:tlist_{fidx}_end . 'foldopen!'
+
+ " Go back to the cursor line before the tag list is sorted
+ call search(curline, 'w')
+
+ call s:Tlist_Menu_Update_File(1)
+ else
+ call s:Tlist_Menu_Remove_File()
+
+ call s:Tlist_Refresh()
+ endif
+endfunction
+
+" Tlist_Update_Current_File()
+" Update taglist for the current buffer by regenerating the tag list
+" Contributed by WEN Guopeng.
+function! s:Tlist_Update_Current_File()
+ call s:Tlist_Log_Msg('Tlist_Update_Current_File()')
+ if winnr() == bufwinnr(g:TagList_title)
+ " In the taglist window. Update the current file
+ call s:Tlist_Window_Update_File()
+ else
+ " Not in the taglist window. Update the current buffer
+ let filename = fnamemodify(bufname('%'), ':p')
+ let fidx = s:Tlist_Get_File_Index(filename)
+ if fidx != -1
+ let s:tlist_{fidx}_valid = 0
+ endif
+ let ft = s:Tlist_Get_Buffer_Filetype('%')
+ call Tlist_Update_File(filename, ft)
+ endif
+endfunction
+
+" Tlist_Window_Update_File()
+" Update the tags displayed in the taglist window
+function! s:Tlist_Window_Update_File()
+ call s:Tlist_Log_Msg('Tlist_Window_Update_File()')
+ let fidx = s:Tlist_Window_Get_File_Index_By_Linenum(line('.'))
+ if fidx == -1
+ return
+ endif
+
+ " Remove the previous highlighting
+ match none
+
+ " Save the current line for later restoration
+ let curline = '\V\^' . getline('.') . '\$'
+
+ let s:tlist_{fidx}_valid = 0
+
+ " Update the taglist window
+ call s:Tlist_Window_Refresh_File(s:tlist_{fidx}_filename,
+ \ s:tlist_{fidx}_filetype)
+
+ exe s:tlist_{fidx}_start . ',' . s:tlist_{fidx}_end . 'foldopen!'
+
+ " Go back to the tag line before the list is updated
+ call search(curline, 'w')
+endfunction
+
+" Tlist_Window_Get_Tag_Type_By_Linenum()
+" Return the tag type index for the specified line in the taglist window
+function! s:Tlist_Window_Get_Tag_Type_By_Linenum(fidx, lnum)
+ let ftype = s:tlist_{a:fidx}_filetype
+
+ " Determine to which tag type the current line number belongs to using the
+ " tag type start line number and the number of tags in a tag type
+ let i = 1
+ while i <= s:tlist_{ftype}_count
+ let ttype = s:tlist_{ftype}_{i}_name
+ let start_lnum =
+ \ s:tlist_{a:fidx}_start + s:tlist_{a:fidx}_{ttype}_offset
+ let end = start_lnum + s:tlist_{a:fidx}_{ttype}_count
+ if a:lnum >= start_lnum && a:lnum <= end
+ break
+ endif
+ let i = i + 1
+ endwhile
+
+ " Current line doesn't belong to any of the displayed tag types
+ if i > s:tlist_{ftype}_count
+ return ''
+ endif
+
+ return ttype
+endfunction
+
+" Tlist_Window_Get_Tag_Index()
+" Return the tag index for the specified line in the taglist window
+function! s:Tlist_Window_Get_Tag_Index(fidx, lnum)
+ let ttype = s:Tlist_Window_Get_Tag_Type_By_Linenum(a:fidx, a:lnum)
+
+ " Current line doesn't belong to any of the displayed tag types
+ if ttype == ''
+ return 0
+ endif
+
+ " Compute the index into the displayed tags for the tag type
+ let ttype_lnum = s:tlist_{a:fidx}_start + s:tlist_{a:fidx}_{ttype}_offset
+ let tidx = a:lnum - ttype_lnum
+ if tidx == 0
+ return 0
+ endif
+
+ " Get the corresponding tag line and return it
+ return s:tlist_{a:fidx}_{ttype}_{tidx}
+endfunction
+
+" Tlist_Window_Highlight_Line
+" Highlight the current line
+function! s:Tlist_Window_Highlight_Line()
+ " Clear previously selected name
+ match none
+
+ " Highlight the current line
+ if g:Tlist_Display_Prototype == 0
+ let pat = '/\%' . line('.') . 'l\s\+\zs.*/'
+ else
+ let pat = '/\%' . line('.') . 'l.*/'
+ endif
+
+ exe 'match TagListTagName ' . pat
+endfunction
+
+" Tlist_Window_Open_File
+" Open the specified file in either a new window or an existing window
+" and place the cursor at the specified tag pattern
+function! s:Tlist_Window_Open_File(win_ctrl, filename, tagpat)
+ call s:Tlist_Log_Msg('Tlist_Window_Open_File (' . a:filename . ',' .
+ \ a:win_ctrl . ')')
+ let prev_Tlist_Skip_Refresh = s:Tlist_Skip_Refresh
+ let s:Tlist_Skip_Refresh = 1
+
+ if s:tlist_app_name == "winmanager"
+ " Let the winmanager edit the file
+ call WinManagerFileEdit(a:filename, a:win_ctrl == 'newwin')
+ else
+
+ if a:win_ctrl == 'newtab'
+ " Create a new tab
+ exe 'tabnew ' . escape(a:filename, ' ')
+ " Open the taglist window in the new tab
+ call s:Tlist_Window_Open()
+ endif
+
+ if a:win_ctrl == 'checktab'
+ " Check whether the file is present in any of the tabs.
+ " If the file is present in the current tab, then use the
+ " current tab.
+ if bufwinnr(a:filename) != -1
+ let file_present_in_tab = 1
+ let i = tabpagenr()
+ else
+ let i = 1
+ let bnum = bufnr(a:filename)
+ let file_present_in_tab = 0
+ while i <= tabpagenr('$')
+ if index(tabpagebuflist(i), bnum) != -1
+ let file_present_in_tab = 1
+ break
+ endif
+ let i += 1
+ endwhile
+ endif
+
+ if file_present_in_tab
+ " Goto the tab containing the file
+ exe 'tabnext ' . i
+ else
+ " Open a new tab
+ exe 'tabnew ' . escape(a:filename, ' ')
+
+ " Open the taglist window
+ call s:Tlist_Window_Open()
+ endif
+ endif
+
+ let winnum = -1
+ if a:win_ctrl == 'prevwin'
+ " Open the file in the previous window, if it is usable
+ let cur_win = winnr()
+ wincmd p
+ if &buftype == '' && !&previewwindow
+ exe "edit " . escape(a:filename, ' ')
+ let winnum = winnr()
+ else
+ " Previous window is not usable
+ exe cur_win . 'wincmd w'
+ endif
+ endif
+
+ " Goto the window containing the file. If the window is not there, open a
+ " new window
+ if winnum == -1
+ let winnum = bufwinnr(a:filename)
+ endif
+
+ if winnum == -1
+ " Locate the previously used window for opening a file
+ let fwin_num = 0
+ let first_usable_win = 0
+
+ let i = 1
+ let bnum = winbufnr(i)
+ while bnum != -1
+ if getwinvar(i, 'tlist_file_window') == 'yes'
+ let fwin_num = i
+ break
+ endif
+ if first_usable_win == 0 &&
+ \ getbufvar(bnum, '&buftype') == '' &&
+ \ !getwinvar(i, '&previewwindow')
+ " First non-taglist, non-plugin and non-preview window
+ let first_usable_win = i
+ endif
+ let i = i + 1
+ let bnum = winbufnr(i)
+ endwhile
+
+ " If a previously used window is not found, then use the first
+ " non-taglist window
+ if fwin_num == 0
+ let fwin_num = first_usable_win
+ endif
+
+ if fwin_num != 0
+ " Jump to the file window
+ exe fwin_num . "wincmd w"
+
+ " If the user asked to jump to the tag in a new window, then split
+ " the existing window into two.
+ if a:win_ctrl == 'newwin'
+ split
+ endif
+ exe "edit " . escape(a:filename, ' ')
+ else
+ " Open a new window
+ if g:Tlist_Use_Horiz_Window
+ exe 'leftabove split ' . escape(a:filename, ' ')
+ else
+ if winbufnr(2) == -1
+ " Only the taglist window is present
+ if g:Tlist_Use_Right_Window
+ exe 'leftabove vertical split ' .
+ \ escape(a:filename, ' ')
+ else
+ exe 'rightbelow vertical split ' .
+ \ escape(a:filename, ' ')
+ endif
+
+ " Go to the taglist window to change the window size to
+ " the user configured value
+ call s:Tlist_Exe_Cmd_No_Acmds('wincmd p')
+ if g:Tlist_Use_Horiz_Window
+ exe 'resize ' . g:Tlist_WinHeight
+ else
+ exe 'vertical resize ' . g:Tlist_WinWidth
+ endif
+ " Go back to the file window
+ call s:Tlist_Exe_Cmd_No_Acmds('wincmd p')
+ else
+ " A plugin or help window is also present
+ wincmd w
+ exe 'leftabove split ' . escape(a:filename, ' ')
+ endif
+ endif
+ endif
+ " Mark the window, so that it can be reused.
+ call s:Tlist_Window_Mark_File_Window()
+ else
+ if v:version >= 700
+ " If the file is opened in more than one window, then check
+ " whether the last accessed window has the selected file.
+ " If it does, then use that window.
+ let lastwin_bufnum = winbufnr(winnr('#'))
+ if bufnr(a:filename) == lastwin_bufnum
+ let winnum = winnr('#')
+ endif
+ endif
+ exe winnum . 'wincmd w'
+
+ " If the user asked to jump to the tag in a new window, then split the
+ " existing window into two.
+ if a:win_ctrl == 'newwin'
+ split
+ endif
+ endif
+ endif
+
+ " Jump to the tag
+ if a:tagpat != ''
+ " Add the current cursor position to the jump list, so that user can
+ " jump back using the ' and ` marks.
+ mark '
+ silent call search(a:tagpat, 'w')
+
+ " Bring the line to the middle of the window
+ normal! z.
+
+ " If the line is inside a fold, open the fold
+ if foldclosed('.') != -1
+ .foldopen
+ endif
+ endif
+
+ " If the user selects to preview the tag then jump back to the
+ " taglist window
+ if a:win_ctrl == 'preview'
+ " Go back to the taglist window
+ let winnum = bufwinnr(g:TagList_title)
+ exe winnum . 'wincmd w'
+ else
+ " If the user has selected to close the taglist window, when a
+ " tag is selected, close the taglist window
+ if g:Tlist_Close_On_Select
+ call s:Tlist_Window_Goto_Window()
+ close
+
+ " Go back to the window displaying the selected file
+ let wnum = bufwinnr(a:filename)
+ if wnum != -1 && wnum != winnr()
+ call s:Tlist_Exe_Cmd_No_Acmds(wnum . 'wincmd w')
+ endif
+ endif
+ endif
+
+ let s:Tlist_Skip_Refresh = prev_Tlist_Skip_Refresh
+endfunction
+
+" Tlist_Window_Jump_To_Tag()
+" Jump to the location of the current tag
+" win_ctrl == useopen - Reuse the existing file window
+" win_ctrl == newwin - Open a new window
+" win_ctrl == preview - Preview the tag
+" win_ctrl == prevwin - Open in previous window
+" win_ctrl == newtab - Open in new tab
+function! s:Tlist_Window_Jump_To_Tag(win_ctrl)
+ call s:Tlist_Log_Msg('Tlist_Window_Jump_To_Tag(' . a:win_ctrl . ')')
+ " Do not process comment lines and empty lines
+ let curline = getline('.')
+ if curline =~ '^\s*$' || curline[0] == '"'
+ return
+ endif
+
+ " If inside a closed fold, then use the first line of the fold
+ " and jump to the file.
+ let lnum = foldclosed('.')
+ if lnum == -1
+ " Jump to the selected tag or file
+ let lnum = line('.')
+ else
+ " Open the closed fold
+ .foldopen!
+ endif
+
+ let fidx = s:Tlist_Window_Get_File_Index_By_Linenum(lnum)
+ if fidx == -1
+ return
+ endif
+
+ " Get the tag output for the current tag
+ let tidx = s:Tlist_Window_Get_Tag_Index(fidx, lnum)
+ if tidx != 0
+ let tagpat = s:Tlist_Get_Tag_SearchPat(fidx, tidx)
+
+ " Highlight the tagline
+ call s:Tlist_Window_Highlight_Line()
+ else
+ " Selected a line which is not a tag name. Just edit the file
+ let tagpat = ''
+ endif
+
+ call s:Tlist_Window_Open_File(a:win_ctrl, s:tlist_{fidx}_filename, tagpat)
+endfunction
+
+" Tlist_Window_Show_Info()
+" Display information about the entry under the cursor
+function! s:Tlist_Window_Show_Info()
+ call s:Tlist_Log_Msg('Tlist_Window_Show_Info()')
+
+ " Clear the previously displayed line
+ echo
+
+ " Do not process comment lines and empty lines
+ let curline = getline('.')
+ if curline =~ '^\s*$' || curline[0] == '"'
+ return
+ endif
+
+ " If inside a fold, then don't display the prototype
+ if foldclosed('.') != -1
+ return
+ endif
+
+ let lnum = line('.')
+
+ " Get the file index
+ let fidx = s:Tlist_Window_Get_File_Index_By_Linenum(lnum)
+ if fidx == -1
+ return
+ endif
+
+ if lnum == s:tlist_{fidx}_start
+ " Cursor is on a file name
+ let fname = s:tlist_{fidx}_filename
+ if strlen(fname) > 50
+ let fname = fnamemodify(fname, ':t')
+ endif
+ echo fname . ', Filetype=' . s:tlist_{fidx}_filetype .
+ \ ', Tag count=' . s:tlist_{fidx}_tag_count
+ return
+ endif
+
+ " Get the tag output line for the current tag
+ let tidx = s:Tlist_Window_Get_Tag_Index(fidx, lnum)
+ if tidx == 0
+ " Cursor is on a tag type
+ let ttype = s:Tlist_Window_Get_Tag_Type_By_Linenum(fidx, lnum)
+ if ttype == ''
+ return
+ endif
+
+ let ttype_name = ''
+
+ let ftype = s:tlist_{fidx}_filetype
+ let i = 1
+ while i <= s:tlist_{ftype}_count
+ if ttype == s:tlist_{ftype}_{i}_name
+ let ttype_name = s:tlist_{ftype}_{i}_fullname
+ break
+ endif
+ let i = i + 1
+ endwhile
+
+ echo 'Tag type=' . ttype_name .
+ \ ', Tag count=' . s:tlist_{fidx}_{ttype}_count
+ return
+ endif
+
+ " Get the tag search pattern and display it
+ echo s:Tlist_Get_Tag_Prototype(fidx, tidx)
+endfunction
+
+" Tlist_Find_Nearest_Tag_Idx
+" Find the tag idx nearest to the supplied line number
+" Returns -1, if a tag couldn't be found for the specified line number
+function! s:Tlist_Find_Nearest_Tag_Idx(fidx, linenum)
+ let sort_type = s:tlist_{a:fidx}_sort_type
+
+ let left = 1
+ let right = s:tlist_{a:fidx}_tag_count
+
+ if sort_type == 'order'
+ " Tags sorted by order, use a binary search.
+ " The idea behind this function is taken from the ctags.vim script (by
+ " Alexey Marinichev) available at the Vim online website.
+
+ " If the current line is the less than the first tag, then no need to
+ " search
+ let first_lnum = s:Tlist_Get_Tag_Linenum(a:fidx, 1)
+
+ if a:linenum < first_lnum
+ return -1
+ endif
+
+ while left < right
+ let middle = (right + left + 1) / 2
+ let middle_lnum = s:Tlist_Get_Tag_Linenum(a:fidx, middle)
+
+ if middle_lnum == a:linenum
+ let left = middle
+ break
+ endif
+
+ if middle_lnum > a:linenum
+ let right = middle - 1
+ else
+ let left = middle
+ endif
+ endwhile
+ else
+ " Tags sorted by name, use a linear search. (contributed by Dave
+ " Eggum).
+ " Look for a tag with a line number less than or equal to the supplied
+ " line number. If multiple tags are found, then use the tag with the
+ " line number closest to the supplied line number. IOW, use the tag
+ " with the highest line number.
+ let closest_lnum = 0
+ let final_left = 0
+ while left <= right
+ let lnum = s:Tlist_Get_Tag_Linenum(a:fidx, left)
+
+ if lnum < a:linenum && lnum > closest_lnum
+ let closest_lnum = lnum
+ let final_left = left
+ elseif lnum == a:linenum
+ let closest_lnum = lnum
+ let final_left = left
+ break
+ else
+ let left = left + 1
+ endif
+ endwhile
+ if closest_lnum == 0
+ return -1
+ endif
+ if left >= right
+ let left = final_left
+ endif
+ endif
+
+ return left
+endfunction
+
+" Tlist_Window_Highlight_Tag()
+" Highlight the current tag
+" cntx == 1, Called by the taglist plugin itself
+" cntx == 2, Forced by the user through the TlistHighlightTag command
+" center = 1, move the tag line to the center of the taglist window
+function! s:Tlist_Window_Highlight_Tag(filename, cur_lnum, cntx, center)
+ " Highlight the current tag only if the user configured the
+ " taglist plugin to do so or if the user explictly invoked the
+ " command to highlight the current tag.
+ if !g:Tlist_Auto_Highlight_Tag && a:cntx == 1
+ return
+ endif
+
+ if a:filename == ''
+ return
+ endif
+
+ " Make sure the taglist window is present
+ let winnum = bufwinnr(g:TagList_title)
+ if winnum == -1
+ call s:Tlist_Warning_Msg('Error: Taglist window is not open')
+ return
+ endif
+
+ let fidx = s:Tlist_Get_File_Index(a:filename)
+ if fidx == -1
+ return
+ endif
+
+ " If the file is currently not displayed in the taglist window, then retrn
+ if !s:tlist_{fidx}_visible
+ return
+ endif
+
+ " If there are no tags for this file, then no need to proceed further
+ if s:tlist_{fidx}_tag_count == 0
+ return
+ endif
+
+ " Ignore all autocommands
+ let old_ei = &eventignore
+ set eventignore=all
+
+ " Save the original window number
+ let org_winnr = winnr()
+
+ if org_winnr == winnum
+ let in_taglist_window = 1
+ else
+ let in_taglist_window = 0
+ endif
+
+ " Go to the taglist window
+ if !in_taglist_window
+ exe winnum . 'wincmd w'
+ endif
+
+ " Clear previously selected name
+ match none
+
+ let tidx = s:Tlist_Find_Nearest_Tag_Idx(fidx, a:cur_lnum)
+ if tidx == -1
+ " Make sure the current tag line is visible in the taglist window.
+ " Calling the winline() function makes the line visible. Don't know
+ " of a better way to achieve this.
+ let lnum = line('.')
+
+ if lnum < s:tlist_{fidx}_start || lnum > s:tlist_{fidx}_end
+ " Move the cursor to the beginning of the file
+ exe s:tlist_{fidx}_start
+ endif
+
+ if foldclosed('.') != -1
+ .foldopen
+ endif
+
+ call winline()
+
+ if !in_taglist_window
+ exe org_winnr . 'wincmd w'
+ endif
+
+ " Restore the autocommands
+ let &eventignore = old_ei
+ return
+ endif
+
+ " Extract the tag type
+ let ttype = s:Tlist_Get_Tag_Type_By_Tag(fidx, tidx)
+
+ " Compute the line number
+ " Start of file + Start of tag type + offset
+ let lnum = s:tlist_{fidx}_start + s:tlist_{fidx}_{ttype}_offset +
+ \ s:tlist_{fidx}_{tidx}_ttype_idx
+
+ " Goto the line containing the tag
+ exe lnum
+
+ " Open the fold
+ if foldclosed('.') != -1
+ .foldopen
+ endif
+
+ if a:center
+ " Move the tag line to the center of the taglist window
+ normal! z.
+ else
+ " Make sure the current tag line is visible in the taglist window.
+ " Calling the winline() function makes the line visible. Don't know
+ " of a better way to achieve this.
+ call winline()
+ endif
+
+ " Highlight the tag name
+ call s:Tlist_Window_Highlight_Line()
+
+ " Go back to the original window
+ if !in_taglist_window
+ exe org_winnr . 'wincmd w'
+ endif
+
+ " Restore the autocommands
+ let &eventignore = old_ei
+ return
+endfunction
+
+" Tlist_Get_Tag_Prototype_By_Line
+" Get the prototype for the tag on or before the specified line number in the
+" current buffer
+function! Tlist_Get_Tag_Prototype_By_Line(...)
+ if a:0 == 0
+ " Arguments are not supplied. Use the current buffer name
+ " and line number
+ let filename = bufname('%')
+ let linenr = line('.')
+ elseif a:0 == 2
+ " Filename and line number are specified
+ let filename = a:1
+ let linenr = a:2
+ if linenr !~ '\d\+'
+ " Invalid line number
+ return ""
+ endif
+ else
+ " Sufficient arguments are not supplied
+ let msg = 'Usage: Tlist_Get_Tag_Prototype_By_Line <filename> ' .
+ \ '<line_number>'
+ call s:Tlist_Warning_Msg(msg)
+ return ""
+ endif
+
+ " Expand the file to a fully qualified name
+ let filename = fnamemodify(filename, ':p')
+ if filename == ''
+ return ""
+ endif
+
+ let fidx = s:Tlist_Get_File_Index(filename)
+ if fidx == -1
+ return ""
+ endif
+
+ " If there are no tags for this file, then no need to proceed further
+ if s:tlist_{fidx}_tag_count == 0
+ return ""
+ endif
+
+ " Get the tag text using the line number
+ let tidx = s:Tlist_Find_Nearest_Tag_Idx(fidx, linenr)
+ if tidx == -1
+ return ""
+ endif
+
+ return s:Tlist_Get_Tag_Prototype(fidx, tidx)
+endfunction
+
+" Tlist_Get_Tagname_By_Line
+" Get the tag name on or before the specified line number in the
+" current buffer
+function! Tlist_Get_Tagname_By_Line(...)
+ if a:0 == 0
+ " Arguments are not supplied. Use the current buffer name
+ " and line number
+ let filename = bufname('%')
+ let linenr = line('.')
+ elseif a:0 == 2
+ " Filename and line number are specified
+ let filename = a:1
+ let linenr = a:2
+ if linenr !~ '\d\+'
+ " Invalid line number
+ return ""
+ endif
+ else
+ " Sufficient arguments are not supplied
+ let msg = 'Usage: Tlist_Get_Tagname_By_Line <filename> <line_number>'
+ call s:Tlist_Warning_Msg(msg)
+ return ""
+ endif
+
+ " Make sure the current file has a name
+ let filename = fnamemodify(filename, ':p')
+ if filename == ''
+ return ""
+ endif
+
+ let fidx = s:Tlist_Get_File_Index(filename)
+ if fidx == -1
+ return ""
+ endif
+
+ " If there are no tags for this file, then no need to proceed further
+ if s:tlist_{fidx}_tag_count == 0
+ return ""
+ endif
+
+ " Get the tag name using the line number
+ let tidx = s:Tlist_Find_Nearest_Tag_Idx(fidx, linenr)
+ if tidx == -1
+ return ""
+ endif
+
+ return s:tlist_{fidx}_{tidx}_tag_name
+endfunction
+
+" Tlist_Window_Move_To_File
+" Move the cursor to the beginning of the current file or the next file
+" or the previous file in the taglist window
+" dir == -1, move to start of current or previous function
+" dir == 1, move to start of next function
+function! s:Tlist_Window_Move_To_File(dir)
+ if foldlevel('.') == 0
+ " Cursor is on a non-folded line (it is not in any of the files)
+ " Move it to a folded line
+ if a:dir == -1
+ normal! zk
+ else
+ " While moving down to the start of the next fold,
+ " no need to do go to the start of the next file.
+ normal! zj
+ return
+ endif
+ endif
+
+ let fidx = s:Tlist_Window_Get_File_Index_By_Linenum(line('.'))
+ if fidx == -1
+ return
+ endif
+
+ let cur_lnum = line('.')
+
+ if a:dir == -1
+ if cur_lnum > s:tlist_{fidx}_start
+ " Move to the beginning of the current file
+ exe s:tlist_{fidx}_start
+ return
+ endif
+
+ if fidx != 0
+ " Move to the beginning of the previous file
+ let fidx = fidx - 1
+ else
+ " Cursor is at the first file, wrap around to the last file
+ let fidx = s:tlist_file_count - 1
+ endif
+
+ exe s:tlist_{fidx}_start
+ return
+ else
+ " Move to the beginning of the next file
+ let fidx = fidx + 1
+
+ if fidx >= s:tlist_file_count
+ " Cursor is at the last file, wrap around to the first file
+ let fidx = 0
+ endif
+
+ if s:tlist_{fidx}_start != 0
+ exe s:tlist_{fidx}_start
+ endif
+ return
+ endif
+endfunction
+
+" Tlist_Session_Load
+" Load a taglist session (information about all the displayed files
+" and the tags) from the specified file
+function! s:Tlist_Session_Load(...)
+ if a:0 == 0 || a:1 == ''
+ call s:Tlist_Warning_Msg('Usage: TlistSessionLoad <filename>')
+ return
+ endif
+
+ let sessionfile = a:1
+
+ if !filereadable(sessionfile)
+ let msg = 'Taglist: Error - Unable to open file ' . sessionfile
+ call s:Tlist_Warning_Msg(msg)
+ return
+ endif
+
+ " Mark the current window as the file window
+ call s:Tlist_Window_Mark_File_Window()
+
+ " Source the session file
+ exe 'source ' . sessionfile
+
+ let new_file_count = g:tlist_file_count
+ unlet! g:tlist_file_count
+
+ let i = 0
+ while i < new_file_count
+ let ftype = g:tlist_{i}_filetype
+ unlet! g:tlist_{i}_filetype
+
+ if !exists('s:tlist_' . ftype . '_count')
+ if s:Tlist_FileType_Init(ftype) == 0
+ let i = i + 1
+ continue
+ endif
+ endif
+
+ let fname = g:tlist_{i}_filename
+ unlet! g:tlist_{i}_filename
+
+ let fidx = s:Tlist_Get_File_Index(fname)
+ if fidx != -1
+ let s:tlist_{fidx}_visible = 0
+ let i = i + 1
+ continue
+ else
+ " As we are loading the tags from the session file, if this
+ " file was previously deleted by the user, now we need to
+ " add it back. So remove the file from the deleted list.
+ call s:Tlist_Update_Remove_List(fname, 0)
+ endif
+
+ let fidx = s:Tlist_Init_File(fname, ftype)
+
+ let s:tlist_{fidx}_filename = fname
+
+ let s:tlist_{fidx}_sort_type = g:tlist_{i}_sort_type
+ unlet! g:tlist_{i}_sort_type
+
+ let s:tlist_{fidx}_filetype = ftype
+ let s:tlist_{fidx}_mtime = getftime(fname)
+
+ let s:tlist_{fidx}_start = 0
+ let s:tlist_{fidx}_end = 0
+
+ let s:tlist_{fidx}_valid = 1
+
+ let s:tlist_{fidx}_tag_count = g:tlist_{i}_tag_count
+ unlet! g:tlist_{i}_tag_count
+
+ let j = 1
+ while j <= s:tlist_{fidx}_tag_count
+ let s:tlist_{fidx}_{j}_tag = g:tlist_{i}_{j}_tag
+ let s:tlist_{fidx}_{j}_tag_name = g:tlist_{i}_{j}_tag_name
+ let s:tlist_{fidx}_{j}_ttype_idx = g:tlist_{i}_{j}_ttype_idx
+ unlet! g:tlist_{i}_{j}_tag
+ unlet! g:tlist_{i}_{j}_tag_name
+ unlet! g:tlist_{i}_{j}_ttype_idx
+ let j = j + 1
+ endwhile
+
+ let j = 1
+ while j <= s:tlist_{ftype}_count
+ let ttype = s:tlist_{ftype}_{j}_name
+
+ if exists('g:tlist_' . i . '_' . ttype)
+ let s:tlist_{fidx}_{ttype} = g:tlist_{i}_{ttype}
+ unlet! g:tlist_{i}_{ttype}
+ let s:tlist_{fidx}_{ttype}_offset = 0
+ let s:tlist_{fidx}_{ttype}_count = g:tlist_{i}_{ttype}_count
+ unlet! g:tlist_{i}_{ttype}_count
+
+ let k = 1
+ while k <= s:tlist_{fidx}_{ttype}_count
+ let s:tlist_{fidx}_{ttype}_{k} = g:tlist_{i}_{ttype}_{k}
+ unlet! g:tlist_{i}_{ttype}_{k}
+ let k = k + 1
+ endwhile
+ else
+ let s:tlist_{fidx}_{ttype} = ''
+ let s:tlist_{fidx}_{ttype}_offset = 0
+ let s:tlist_{fidx}_{ttype}_count = 0
+ endif
+
+ let j = j + 1
+ endwhile
+
+ let i = i + 1
+ endwhile
+
+ " If the taglist window is open, then update it
+ let winnum = bufwinnr(g:TagList_title)
+ if winnum != -1
+ let save_winnr = winnr()
+
+ " Goto the taglist window
+ call s:Tlist_Window_Goto_Window()
+
+ " Refresh the taglist window
+ call s:Tlist_Window_Refresh()
+
+ " Go back to the original window
+ if save_winnr != winnr()
+ call s:Tlist_Exe_Cmd_No_Acmds('wincmd p')
+ endif
+ endif
+endfunction
+
+" Tlist_Session_Save
+" Save a taglist session (information about all the displayed files
+" and the tags) into the specified file
+function! s:Tlist_Session_Save(...)
+ if a:0 == 0 || a:1 == ''
+ call s:Tlist_Warning_Msg('Usage: TlistSessionSave <filename>')
+ return
+ endif
+
+ let sessionfile = a:1
+
+ if s:tlist_file_count == 0
+ " There is nothing to save
+ call s:Tlist_Warning_Msg('Warning: Taglist is empty. Nothing to save.')
+ return
+ endif
+
+ if filereadable(sessionfile)
+ let ans = input('Do you want to overwrite ' . sessionfile . ' (Y/N)?')
+ if ans !=? 'y'
+ return
+ endif
+
+ echo "\n"
+ endif
+
+ let old_verbose = &verbose
+ set verbose&vim
+
+ exe 'redir! > ' . sessionfile
+
+ silent! echo '" Taglist session file. This file is auto-generated.'
+ silent! echo '" File information'
+ silent! echo 'let tlist_file_count = ' . s:tlist_file_count
+
+ let i = 0
+
+ while i < s:tlist_file_count
+ " Store information about the file
+ silent! echo 'let tlist_' . i . "_filename = '" .
+ \ s:tlist_{i}_filename . "'"
+ silent! echo 'let tlist_' . i . '_sort_type = "' .
+ \ s:tlist_{i}_sort_type . '"'
+ silent! echo 'let tlist_' . i . '_filetype = "' .
+ \ s:tlist_{i}_filetype . '"'
+ silent! echo 'let tlist_' . i . '_tag_count = ' .
+ \ s:tlist_{i}_tag_count
+ " Store information about all the tags
+ let j = 1
+ while j <= s:tlist_{i}_tag_count
+ let txt = escape(s:tlist_{i}_{j}_tag, '"\\')
+ silent! echo 'let tlist_' . i . '_' . j . '_tag = "' . txt . '"'
+ silent! echo 'let tlist_' . i . '_' . j . '_tag_name = "' .
+ \ s:tlist_{i}_{j}_tag_name . '"'
+ silent! echo 'let tlist_' . i . '_' . j . '_ttype_idx' . ' = ' .
+ \ s:tlist_{i}_{j}_ttype_idx
+ let j = j + 1
+ endwhile
+
+ " Store information about all the tags grouped by their type
+ let ftype = s:tlist_{i}_filetype
+ let j = 1
+ while j <= s:tlist_{ftype}_count
+ let ttype = s:tlist_{ftype}_{j}_name
+ if s:tlist_{i}_{ttype}_count != 0
+ let txt = escape(s:tlist_{i}_{ttype}, '"\')
+ let txt = substitute(txt, "\n", "\\\\n", 'g')
+ silent! echo 'let tlist_' . i . '_' . ttype . ' = "' .
+ \ txt . '"'
+ silent! echo 'let tlist_' . i . '_' . ttype . '_count = ' .
+ \ s:tlist_{i}_{ttype}_count
+ let k = 1
+ while k <= s:tlist_{i}_{ttype}_count
+ silent! echo 'let tlist_' . i . '_' . ttype . '_' . k .
+ \ ' = ' . s:tlist_{i}_{ttype}_{k}
+ let k = k + 1
+ endwhile
+ endif
+ let j = j + 1
+ endwhile
+
+ silent! echo
+
+ let i = i + 1
+ endwhile
+
+ redir END
+
+ let &verbose = old_verbose
+endfunction
+
+" Tlist_Buffer_Removed
+" A buffer is removed from the Vim buffer list. Remove the tags defined
+" for that file
+function! s:Tlist_Buffer_Removed(filename)
+ call s:Tlist_Log_Msg('Tlist_Buffer_Removed (' . a:filename . ')')
+
+ " Make sure a valid filename is supplied
+ if a:filename == ''
+ return
+ endif
+
+ " Get tag list index of the specified file
+ let fidx = s:Tlist_Get_File_Index(a:filename)
+ if fidx == -1
+ " File not present in the taglist
+ return
+ endif
+
+ " Remove the file from the list
+ call s:Tlist_Remove_File(fidx, 0)
+endfunction
+
+" When a buffer is deleted, remove the file from the taglist
+autocmd BufDelete * silent call s:Tlist_Buffer_Removed(expand('<afile>:p'))
+
+" Tlist_Window_Open_File_Fold
+" Open the fold for the specified file and close the fold for all the
+" other files
+function! s:Tlist_Window_Open_File_Fold(acmd_bufnr)
+ call s:Tlist_Log_Msg('Tlist_Window_Open_File_Fold (' . a:acmd_bufnr . ')')
+
+ " Make sure the taglist window is present
+ let winnum = bufwinnr(g:TagList_title)
+ if winnum == -1
+ call s:Tlist_Warning_Msg('Taglist: Error - Taglist window is not open')
+ return
+ endif
+
+ " Save the original window number
+ let org_winnr = winnr()
+ if org_winnr == winnum
+ let in_taglist_window = 1
+ else
+ let in_taglist_window = 0
+ endif
+
+ if in_taglist_window
+ " When entering the taglist window, no need to update the folds
+ return
+ endif
+
+ " Go to the taglist window
+ if !in_taglist_window
+ call s:Tlist_Exe_Cmd_No_Acmds(winnum . 'wincmd w')
+ endif
+
+ " Close all the folds
+ silent! %foldclose
+
+ " Get tag list index of the specified file
+ let fname = fnamemodify(bufname(a:acmd_bufnr + 0), ':p')
+ if filereadable(fname)
+ let fidx = s:Tlist_Get_File_Index(fname)
+ if fidx != -1
+ " Open the fold for the file
+ exe "silent! " . s:tlist_{fidx}_start . "," .
+ \ s:tlist_{fidx}_end . "foldopen"
+ endif
+ endif
+
+ " Go back to the original window
+ if !in_taglist_window
+ call s:Tlist_Exe_Cmd_No_Acmds(org_winnr . 'wincmd w')
+ endif
+endfunction
+
+" Tlist_Window_Check_Auto_Open
+" Open the taglist window automatically on Vim startup.
+" Open the window only when files present in any of the Vim windows support
+" tags.
+function! s:Tlist_Window_Check_Auto_Open()
+ let open_window = 0
+
+ let i = 1
+ let buf_num = winbufnr(i)
+ while buf_num != -1
+ let filename = fnamemodify(bufname(buf_num), ':p')
+ let ft = s:Tlist_Get_Buffer_Filetype(buf_num)
+ if !s:Tlist_Skip_File(filename, ft)
+ let open_window = 1
+ break
+ endif
+ let i = i + 1
+ let buf_num = winbufnr(i)
+ endwhile
+
+ if open_window
+ call s:Tlist_Window_Toggle()
+ endif
+endfunction
+
+" Tlist_Refresh_Folds
+" Remove and create the folds for all the files displayed in the taglist
+" window. Used after entering a tab. If this is not done, then the folds
+" are not properly created for taglist windows displayed in multiple tabs.
+function! s:Tlist_Refresh_Folds()
+ let winnum = bufwinnr(g:TagList_title)
+ if winnum == -1
+ return
+ endif
+
+ let save_wnum = winnr()
+ exe winnum . 'wincmd w'
+
+ " First remove all the existing folds
+ normal! zE
+
+ " Create the folds for each in the tag list
+ let fidx = 0
+ while fidx < s:tlist_file_count
+ let ftype = s:tlist_{fidx}_filetype
+
+ " Create the folds for each tag type in a file
+ let j = 1
+ while j <= s:tlist_{ftype}_count
+ let ttype = s:tlist_{ftype}_{j}_name
+ if s:tlist_{fidx}_{ttype}_count
+ let s = s:tlist_{fidx}_start + s:tlist_{fidx}_{ttype}_offset
+ let e = s + s:tlist_{fidx}_{ttype}_count
+ exe s . ',' . e . 'fold'
+ endif
+ let j = j + 1
+ endwhile
+
+ exe s:tlist_{fidx}_start . ',' . s:tlist_{fidx}_end . 'fold'
+ exe 'silent! ' . s:tlist_{fidx}_start . ',' .
+ \ s:tlist_{fidx}_end . 'foldopen!'
+ let fidx = fidx + 1
+ endwhile
+
+ exe save_wnum . 'wincmd w'
+endfunction
+
+function! s:Tlist_Menu_Add_Base_Menu()
+ call s:Tlist_Log_Msg('Adding the base menu')
+
+ " Add the menu
+ anoremenu <silent> T&ags.Refresh\ menu :call <SID>Tlist_Menu_Refresh()<CR>
+ anoremenu <silent> T&ags.Sort\ menu\ by.Name
+ \ :call <SID>Tlist_Change_Sort('menu', 'set', 'name')<CR>
+ anoremenu <silent> T&ags.Sort\ menu\ by.Order
+ \ :call <SID>Tlist_Change_Sort('menu', 'set', 'order')<CR>
+ anoremenu T&ags.-SEP1- :
+
+ if &mousemodel =~ 'popup'
+ anoremenu <silent> PopUp.T&ags.Refresh\ menu
+ \ :call <SID>Tlist_Menu_Refresh()<CR>
+ anoremenu <silent> PopUp.T&ags.Sort\ menu\ by.Name
+ \ :call <SID>Tlist_Change_Sort('menu', 'set', 'name')<CR>
+ anoremenu <silent> PopUp.T&ags.Sort\ menu\ by.Order
+ \ :call <SID>Tlist_Change_Sort('menu', 'set', 'order')<CR>
+ anoremenu PopUp.T&ags.-SEP1- :
+ endif
+endfunction
+
+let s:menu_char_prefix =
+ \ '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
+
+" Tlist_Menu_Get_Tag_Type_Cmd
+" Get the menu command for the specified tag type
+" fidx - File type index
+" ftype - File Type
+" add_ttype_name - To add or not to add the tag type name to the menu entries
+" ttype_idx - Tag type index
+function! s:Tlist_Menu_Get_Tag_Type_Cmd(fidx, ftype, add_ttype_name, ttype_idx)
+ " Curly brace variable name optimization
+ let ftype_ttype_idx = a:ftype . '_' . a:ttype_idx
+
+ let ttype = s:tlist_{ftype_ttype_idx}_name
+ if a:add_ttype_name
+ " If the tag type name contains space characters, escape it. This
+ " will be used to create the menu entries.
+ let ttype_fullname = escape(s:tlist_{ftype_ttype_idx}_fullname, ' ')
+ endif
+
+ " Curly brace variable name optimization
+ let fidx_ttype = a:fidx . '_' . ttype
+
+ " Number of tag entries for this tag type
+ let tcnt = s:tlist_{fidx_ttype}_count
+ if tcnt == 0 " No entries for this tag type
+ return ''
+ endif
+
+ let mcmd = ''
+
+ " Create the menu items for the tags.
+ " Depending on the number of tags of this type, split the menu into
+ " multiple sub-menus, if needed.
+ if tcnt > g:Tlist_Max_Submenu_Items
+ let j = 1
+ while j <= tcnt
+ let final_index = j + g:Tlist_Max_Submenu_Items - 1
+ if final_index > tcnt
+ let final_index = tcnt
+ endif
+
+ " Extract the first and last tag name and form the
+ " sub-menu name
+ let tidx = s:tlist_{fidx_ttype}_{j}
+ let first_tag = s:tlist_{a:fidx}_{tidx}_tag_name
+
+ let tidx = s:tlist_{fidx_ttype}_{final_index}
+ let last_tag = s:tlist_{a:fidx}_{tidx}_tag_name
+
+ " Truncate the names, if they are greater than the
+ " max length
+ let first_tag = strpart(first_tag, 0, g:Tlist_Max_Tag_Length)
+ let last_tag = strpart(last_tag, 0, g:Tlist_Max_Tag_Length)
+
+ " Form the menu command prefix
+ let m_prefix = 'anoremenu <silent> T\&ags.'
+ if a:add_ttype_name
+ let m_prefix = m_prefix . ttype_fullname . '.'
+ endif
+ let m_prefix = m_prefix . first_tag . '\.\.\.' . last_tag . '.'
+
+ " Character prefix used to number the menu items (hotkey)
+ let m_prefix_idx = 0
+
+ while j <= final_index
+ let tidx = s:tlist_{fidx_ttype}_{j}
+
+ let tname = s:tlist_{a:fidx}_{tidx}_tag_name
+
+ let mcmd = mcmd . m_prefix . '\&' .
+ \ s:menu_char_prefix[m_prefix_idx] . '\.' .
+ \ tname . ' :call <SID>Tlist_Menu_Jump_To_Tag(' .
+ \ tidx . ')<CR>|'
+
+ let m_prefix_idx = m_prefix_idx + 1
+ let j = j + 1
+ endwhile
+ endwhile
+ else
+ " Character prefix used to number the menu items (hotkey)
+ let m_prefix_idx = 0
+
+ let m_prefix = 'anoremenu <silent> T\&ags.'
+ if a:add_ttype_name
+ let m_prefix = m_prefix . ttype_fullname . '.'
+ endif
+ let j = 1
+ while j <= tcnt
+ let tidx = s:tlist_{fidx_ttype}_{j}
+
+ let tname = s:tlist_{a:fidx}_{tidx}_tag_name
+
+ let mcmd = mcmd . m_prefix . '\&' .
+ \ s:menu_char_prefix[m_prefix_idx] . '\.' .
+ \ tname . ' :call <SID>Tlist_Menu_Jump_To_Tag(' . tidx
+ \ . ')<CR>|'
+
+ let m_prefix_idx = m_prefix_idx + 1
+ let j = j + 1
+ endwhile
+ endif
+
+ return mcmd
+endfunction
+
+" Update the taglist menu with the tags for the specified file
+function! s:Tlist_Menu_File_Refresh(fidx)
+ call s:Tlist_Log_Msg('Refreshing the tag menu for ' . s:tlist_{a:fidx}_filename)
+ " The 'B' flag is needed in the 'cpoptions' option
+ let old_cpoptions = &cpoptions
+ set cpoptions&vim
+
+ exe s:tlist_{a:fidx}_menu_cmd
+
+ " Update the popup menu (if enabled)
+ if &mousemodel =~ 'popup'
+ let cmd = substitute(s:tlist_{a:fidx}_menu_cmd, ' T\\&ags\.',
+ \ ' PopUp.T\\\&ags.', "g")
+ exe cmd
+ endif
+
+ " The taglist menu is not empty now
+ let s:tlist_menu_empty = 0
+
+ " Restore the 'cpoptions' settings
+ let &cpoptions = old_cpoptions
+endfunction
+
+" Tlist_Menu_Update_File
+" Add the taglist menu
+function! s:Tlist_Menu_Update_File(clear_menu)
+ if !has('gui_running')
+ " Not running in GUI mode
+ return
+ endif
+
+ call s:Tlist_Log_Msg('Updating the tag menu, clear_menu = ' . a:clear_menu)
+
+ " Remove the tags menu
+ if a:clear_menu
+ call s:Tlist_Menu_Remove_File()
+
+ endif
+
+ " Skip buffers with 'buftype' set to nofile, nowrite, quickfix or help
+ if &buftype != ''
+ return
+ endif
+
+ let filename = fnamemodify(bufname('%'), ':p')
+ let ftype = s:Tlist_Get_Buffer_Filetype('%')
+
+ " If the file doesn't support tag listing, skip it
+ if s:Tlist_Skip_File(filename, ftype)
+ return
+ endif
+
+ let fidx = s:Tlist_Get_File_Index(filename)
+ if fidx == -1 || !s:tlist_{fidx}_valid
+ " Check whether this file is removed based on user request
+ " If it is, then don't display the tags for this file
+ if s:Tlist_User_Removed_File(filename)
+ return
+ endif
+
+ " Process the tags for the file
+ let fidx = s:Tlist_Process_File(filename, ftype)
+ if fidx == -1
+ return
+ endif
+ endif
+
+ let fname = escape(fnamemodify(bufname('%'), ':t'), '.')
+ if fname != ''
+ exe 'anoremenu T&ags.' . fname . ' <Nop>'
+ anoremenu T&ags.-SEP2- :
+ endif
+
+ if !s:tlist_{fidx}_tag_count
+ return
+ endif
+
+ if s:tlist_{fidx}_menu_cmd != ''
+ " Update the menu with the cached command
+ call s:Tlist_Menu_File_Refresh(fidx)
+
+ return
+ endif
+
+ " We are going to add entries to the tags menu, so the menu won't be
+ " empty
+ let s:tlist_menu_empty = 0
+
+ let cmd = ''
+
+ " Determine whether the tag type name needs to be added to the menu
+ " If more than one tag type is present in the taglisting for a file,
+ " then the tag type name needs to be present
+ let add_ttype_name = -1
+ let i = 1
+ while i <= s:tlist_{ftype}_count && add_ttype_name < 1
+ let ttype = s:tlist_{ftype}_{i}_name
+ if s:tlist_{fidx}_{ttype}_count
+ let add_ttype_name = add_ttype_name + 1
+ endif
+ let i = i + 1
+ endwhile
+
+ " Process the tags by the tag type and get the menu command
+ let i = 1
+ while i <= s:tlist_{ftype}_count
+ let mcmd = s:Tlist_Menu_Get_Tag_Type_Cmd(fidx, ftype, add_ttype_name, i)
+ if mcmd != ''
+ let cmd = cmd . mcmd
+ endif
+
+ let i = i + 1
+ endwhile
+
+ " Cache the menu command for reuse
+ let s:tlist_{fidx}_menu_cmd = cmd
+
+ " Update the menu
+ call s:Tlist_Menu_File_Refresh(fidx)
+endfunction
+
+" Tlist_Menu_Remove_File
+" Remove the tags displayed in the tags menu
+function! s:Tlist_Menu_Remove_File()
+ if !has('gui_running') || s:tlist_menu_empty
+ return
+ endif
+
+ call s:Tlist_Log_Msg('Removing the tags menu for a file')
+
+ " Cleanup the Tags menu
+ silent! unmenu T&ags
+ if &mousemodel =~ 'popup'
+ silent! unmenu PopUp.T&ags
+ endif
+
+ " Add a dummy menu item to retain teared off menu
+ noremenu T&ags.Dummy l
+
+ silent! unmenu! T&ags
+ if &mousemodel =~ 'popup'
+ silent! unmenu! PopUp.T&ags
+ endif
+
+ call s:Tlist_Menu_Add_Base_Menu()
+
+ " Remove the dummy menu item
+ unmenu T&ags.Dummy
+
+ let s:tlist_menu_empty = 1
+endfunction
+
+" Tlist_Menu_Refresh
+" Refresh the taglist menu
+function! s:Tlist_Menu_Refresh()
+ call s:Tlist_Log_Msg('Refreshing the tags menu')
+ let fidx = s:Tlist_Get_File_Index(fnamemodify(bufname('%'), ':p'))
+ if fidx != -1
+ " Invalidate the cached menu command
+ let s:tlist_{fidx}_menu_cmd = ''
+ endif
+
+ " Update the taglist, menu and window
+ call s:Tlist_Update_Current_File()
+endfunction
+
+" Tlist_Menu_Jump_To_Tag
+" Jump to the selected tag
+function! s:Tlist_Menu_Jump_To_Tag(tidx)
+ let fidx = s:Tlist_Get_File_Index(fnamemodify(bufname('%'), ':p'))
+ if fidx == -1
+ return
+ endif
+
+ let tagpat = s:Tlist_Get_Tag_SearchPat(fidx, a:tidx)
+ if tagpat == ''
+ return
+ endif
+
+ " Add the current cursor position to the jump list, so that user can
+ " jump back using the ' and ` marks.
+ mark '
+
+ silent call search(tagpat, 'w')
+
+ " Bring the line to the middle of the window
+ normal! z.
+
+ " If the line is inside a fold, open the fold
+ if foldclosed('.') != -1
+ .foldopen
+ endif
+endfunction
+
+" Tlist_Menu_Init
+" Initialize the taglist menu
+function! s:Tlist_Menu_Init()
+ call s:Tlist_Menu_Add_Base_Menu()
+
+ " Automatically add the tags defined in the current file to the menu
+ augroup TagListMenuCmds
+ autocmd!
+
+ if !g:Tlist_Process_File_Always
+ autocmd BufEnter * call s:Tlist_Refresh()
+ endif
+ autocmd BufLeave * call s:Tlist_Menu_Remove_File()
+ augroup end
+
+ call s:Tlist_Menu_Update_File(0)
+endfunction
+
+" Tlist_Vim_Session_Load
+" Initialize the taglist window/buffer, which is created when loading
+" a Vim session file.
+function! s:Tlist_Vim_Session_Load()
+ call s:Tlist_Log_Msg('Tlist_Vim_Session_Load')
+
+ " Initialize the taglist window
+ call s:Tlist_Window_Init()
+
+ " Refresh the taglist window
+ call s:Tlist_Window_Refresh()
+endfunction
+
+" Tlist_Set_App
+" Set the name of the external plugin/application to which taglist
+" belongs.
+" Taglist plugin is part of another plugin like cream or winmanager.
+function! Tlist_Set_App(name)
+ if a:name == ""
+ return
+ endif
+
+ let s:tlist_app_name = a:name
+endfunction
+
+" Winmanager integration
+
+" Initialization required for integration with winmanager
+function! TagList_Start()
+ " If current buffer is not taglist buffer, then don't proceed
+ if bufname('%') != '__Tag_List__'
+ return
+ endif
+
+ call Tlist_Set_App('winmanager')
+
+ " Get the current filename from the winmanager plugin
+ let bufnum = WinManagerGetLastEditedFile()
+ if bufnum != -1
+ let filename = fnamemodify(bufname(bufnum), ':p')
+ let ftype = s:Tlist_Get_Buffer_Filetype(bufnum)
+ endif
+
+ " Initialize the taglist window, if it is not already initialized
+ if !exists('s:tlist_window_initialized') || !s:tlist_window_initialized
+ call s:Tlist_Window_Init()
+ call s:Tlist_Window_Refresh()
+ let s:tlist_window_initialized = 1
+ endif
+
+ " Update the taglist window
+ if bufnum != -1
+ if !s:Tlist_Skip_File(filename, ftype) && g:Tlist_Auto_Update
+ call s:Tlist_Window_Refresh_File(filename, ftype)
+ endif
+ endif
+endfunction
+
+function! TagList_IsValid()
+ return 0
+endfunction
+
+function! TagList_WrapUp()
+ return 0
+endfunction
+
+" restore 'cpo'
+let &cpo = s:cpo_save
+unlet s:cpo_save
+
diff --git a/modules/vim/vim/plugin/vcsbzr.vim b/modules/vim/vim/plugin/vcsbzr.vim
new file mode 100644
index 0000000..b8665b8
--- /dev/null
+++ b/modules/vim/vim/plugin/vcsbzr.vim
@@ -0,0 +1,262 @@
+" vim600: set foldmethod=marker:
+"
+" BZR extension for VCSCommand.
+"
+" Maintainer: Bob Hiestand <bob.hiestand@gmail.com>
+" License:
+" Copyright (c) Bob Hiestand
+"
+" Permission is hereby granted, free of charge, to any person obtaining a copy
+" of this software and associated documentation files (the "Software"), to
+" deal in the Software without restriction, including without limitation the
+" rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+" sell copies of the Software, and to permit persons to whom the Software is
+" furnished to do so, subject to the following conditions:
+"
+" The above copyright notice and this permission notice shall be included in
+" all copies or substantial portions of the Software.
+"
+" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+" IN THE SOFTWARE.
+"
+" Section: Documentation {{{1
+"
+" Options documentation: {{{2
+"
+" VCSCommandBZRExec
+" This variable specifies the BZR executable. If not set, it defaults to
+" 'bzr' executed from the user's executable path.
+
+" Section: Plugin header {{{1
+
+if exists('VCSCommandDisableAll')
+ finish
+endif
+
+if v:version < 700
+ echohl WarningMsg|echomsg 'VCSCommand requires at least VIM 7.0'|echohl None
+ finish
+endif
+
+runtime plugin/vcscommand.vim
+
+if !executable(VCSCommandGetOption('VCSCommandBZRExec', 'bzr'))
+ " BZR is not installed
+ finish
+endif
+
+let s:save_cpo=&cpo
+set cpo&vim
+
+" Section: Variable initialization {{{1
+
+let s:bzrFunctions = {}
+
+" Section: Utility functions {{{1
+
+" Function: s:Executable() {{{2
+" Returns the executable used to invoke bzr suitable for use in a shell
+" command.
+function! s:Executable()
+ return shellescape(VCSCommandGetOption('VCSCommandBZRExec', 'bzr'))
+endfunction
+
+" Function: s:DoCommand(cmd, cmdName, statusText) {{{2
+" Wrapper to VCSCommandDoCommand to add the name of the BZR executable to the
+" command argument.
+function! s:DoCommand(cmd, cmdName, statusText, options)
+ if VCSCommandGetVCSType(expand('%')) == 'BZR'
+ let fullCmd = s:Executable() . ' ' . a:cmd
+ return VCSCommandDoCommand(fullCmd, a:cmdName, a:statusText, a:options)
+ else
+ throw 'BZR VCSCommand plugin called on non-BZR item.'
+ endif
+endfunction
+
+" Section: VCS function implementations {{{1
+
+" Function: s:bzrFunctions.Identify(buffer) {{{2
+function! s:bzrFunctions.Identify(buffer)
+ let fileName = resolve(bufname(a:buffer))
+ let l:save_bzr_log=$BZR_LOG
+ try
+ let $BZR_LOG=has("win32") || has("win95") || has("win64") || has("win16") ? "nul" : "/dev/null"
+ let statusText = s:VCSCommandUtility.system(s:Executable() . ' info -- "' . fileName . '"')
+ finally
+ let $BZR_LOG=l:save_bzr_log
+ endtry
+ if(v:shell_error)
+ return 0
+ else
+ return 1
+ endif
+endfunction
+
+" Function: s:bzrFunctions.Add() {{{2
+function! s:bzrFunctions.Add(argList)
+ return s:DoCommand(join(['add'] + a:argList, ' '), 'add', join(a:argList, ' '), {})
+endfunction
+
+" Function: s:bzrFunctions.Annotate(argList) {{{2
+function! s:bzrFunctions.Annotate(argList)
+ if len(a:argList) == 0
+ if &filetype == 'BZRannotate'
+ " Perform annotation of the version indicated by the current line.
+ let caption = matchstr(getline('.'),'\v^\s+\zs\d+')
+ let options = ' -r' . caption
+ else
+ let caption = ''
+ let options = ''
+ endif
+ elseif len(a:argList) == 1 && a:argList[0] !~ '^-'
+ let caption = a:argList[0]
+ let options = ' -r' . caption
+ else
+ let caption = join(a:argList, ' ')
+ let options = ' ' . caption
+ endif
+
+ let resultBuffer = s:DoCommand('blame' . options, 'annotate', caption, {})
+ if resultBuffer > 0
+ normal 1G2dd
+ endif
+ return resultBuffer
+endfunction
+
+" Function: s:bzrFunctions.Commit(argList) {{{2
+function! s:bzrFunctions.Commit(argList)
+ let resultBuffer = s:DoCommand('commit -F "' . a:argList[0] . '"', 'commit', '', {})
+ if resultBuffer == 0
+ echomsg 'No commit needed.'
+ endif
+endfunction
+
+" Function: s:bzrFunctions.Delete() {{{2
+function! s:bzrFunctions.Delete(argList)
+ return s:DoCommand(join(['rm'] + a:argList, ' '), 'rm', join(a:argList, ' '), {})
+endfunction
+
+" Function: s:bzrFunctions.Diff(argList) {{{2
+function! s:bzrFunctions.Diff(argList)
+ if len(a:argList) == 0
+ let revOptions = []
+ let caption = ''
+ elseif len(a:argList) <= 2 && match(a:argList, '^-') == -1
+ let revOptions = ['-r' . join(a:argList, '..')]
+ let caption = '(' . a:argList[0] . ' : ' . get(a:argList, 1, 'current') . ')'
+ else
+ " Pass-through
+ let caption = join(a:argList, ' ')
+ let revOptions = a:argList
+ endif
+
+ return s:DoCommand(join(['diff'] + revOptions), 'diff', caption, {'allowNonZeroExit': 1})
+endfunction
+
+" Function: s:bzrFunctions.GetBufferInfo() {{{2
+" Provides version control details for the current file. Current version
+" number and current repository version number are required to be returned by
+" the vcscommand plugin.
+" Returns: List of results: [revision, repository]
+
+function! s:bzrFunctions.GetBufferInfo()
+ let originalBuffer = VCSCommandGetOriginalBuffer(bufnr('%'))
+ let fileName = resolve(bufname(originalBuffer))
+ let statusText = s:VCSCommandUtility.system(s:Executable() . ' status -S -- "' . fileName . '"')
+ let revision = s:VCSCommandUtility.system(s:Executable() . ' revno -- "' . fileName . '"')
+ if(v:shell_error)
+ return []
+ endif
+
+ " File not under BZR control.
+ if statusText =~ '^?'
+ return ['Unknown']
+ endif
+
+ let [flags, repository] = matchlist(statusText, '^\(.\{3}\)\s\+\(\S\+\)')[1:2]
+ if revision == ''
+ " Error
+ return ['Unknown']
+ elseif flags =~ '^A'
+ return ['New', 'New']
+ else
+ return [revision, repository]
+ endif
+endfunction
+
+" Function: s:bzrFunctions.Info(argList) {{{2
+function! s:bzrFunctions.Info(argList)
+ return s:DoCommand(join(['version-info'] + a:argList, ' '), 'version-info', join(a:argList, ' '), {})
+endfunction
+
+" Function: s:bzrFunctions.Lock(argList) {{{2
+function! s:bzrFunctions.Lock(argList)
+ echomsg 'bzr lock is not necessary'
+endfunction
+
+" Function: s:bzrFunctions.Log() {{{2
+function! s:bzrFunctions.Log(argList)
+ if len(a:argList) == 0
+ let options = []
+ let caption = ''
+ elseif len(a:argList) <= 2 && match(a:argList, '^-') == -1
+ let options = ['-r' . join(a:argList, ':')]
+ let caption = options[0]
+ else
+ " Pass-through
+ let options = a:argList
+ let caption = join(a:argList, ' ')
+ endif
+
+ let resultBuffer = s:DoCommand(join(['log', '-v'] + options), 'log', caption, {})
+ return resultBuffer
+endfunction
+
+" Function: s:bzrFunctions.Revert(argList) {{{2
+function! s:bzrFunctions.Revert(argList)
+ return s:DoCommand('revert', 'revert', '', {})
+endfunction
+
+" Function: s:bzrFunctions.Review(argList) {{{2
+function! s:bzrFunctions.Review(argList)
+ if len(a:argList) == 0
+ let versiontag = '(current)'
+ let versionOption = ''
+ else
+ let versiontag = a:argList[0]
+ let versionOption = ' -r ' . versiontag . ' '
+ endif
+
+ return s:DoCommand('cat' . versionOption, 'review', versiontag, {})
+endfunction
+
+" Function: s:bzrFunctions.Status(argList) {{{2
+function! s:bzrFunctions.Status(argList)
+ let options = ['-S']
+ if len(a:argList) != 0
+ let options = a:argList
+ endif
+ return s:DoCommand(join(['status'] + options, ' '), 'status', join(options, ' '), {})
+endfunction
+
+" Function: s:bzrFunctions.Unlock(argList) {{{2
+function! s:bzrFunctions.Unlock(argList)
+ echomsg 'bzr unlock is not necessary'
+endfunction
+" Function: s:bzrFunctions.Update(argList) {{{2
+function! s:bzrFunctions.Update(argList)
+ return s:DoCommand('update', 'update', '', {})
+endfunction
+
+" Annotate setting {{{2
+let s:bzrFunctions.AnnotateSplitRegex = '^[^|]\+ | '
+
+" Section: Plugin Registration {{{1
+let s:VCSCommandUtility = VCSCommandRegisterModule('BZR', expand('<sfile>'), s:bzrFunctions, [])
+
+let &cpo = s:save_cpo
diff --git a/modules/vim/vim/plugin/vcscommand.vim b/modules/vim/vim/plugin/vcscommand.vim
new file mode 100644
index 0000000..98214f2
--- /dev/null
+++ b/modules/vim/vim/plugin/vcscommand.vim
@@ -0,0 +1,1427 @@
+" vim600: set foldmethod=marker:
+"
+" Vim plugin to assist in working with files under control of various Version
+" Control Systems, such as CVS, SVN, SVK, and git.
+"
+" Maintainer: Bob Hiestand <bob.hiestand@gmail.com>
+" License:
+" Copyright (c) Bob Hiestand
+"
+" Permission is hereby granted, free of charge, to any person obtaining a copy
+" of this software and associated documentation files (the "Software"), to
+" deal in the Software without restriction, including without limitation the
+" rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+" sell copies of the Software, and to permit persons to whom the Software is
+" furnished to do so, subject to the following conditions:
+"
+" The above copyright notice and this permission notice shall be included in
+" all copies or substantial portions of the Software.
+"
+" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+" IN THE SOFTWARE.
+"
+" Section: Documentation {{{1
+"
+" Provides functions to invoke various source control commands on the current
+" file (either the current buffer, or, in the case of an directory buffer, the
+" directory and all subdirectories associated with the current buffer). The
+" output of the commands is captured in a new scratch window.
+"
+" This plugin needs additional extension plugins, each specific to a source
+" control system, to function. Several options include the name of the
+" version control system in the option name. Such options use the placeholder
+" text '{VCSType}', which would be replaced in actual usage with 'CVS' or
+" 'SVN', for instance.
+"
+" Command documentation {{{2
+"
+" VCSAdd Adds the current file to source control.
+"
+" VCSAnnotate[!] Displays the current file with each line annotated with the
+" version in which it was most recently changed. If an
+" argument is given, the argument is used as a revision
+" number to display. If not given an argument, it uses the
+" most recent version of the file on the current branch.
+" Additionally, if the current buffer is a VCSAnnotate buffer
+" already, the version number on the current line is used.
+"
+" If '!' is used, the view of the annotated buffer is split
+" so that the annotation is in a separate window from the
+" content, and each is highlighted separately.
+"
+" VCSBlame Alias for 'VCSAnnotate'.
+"
+" VCSCommit[!] Commits changes to the current file to source control.
+"
+" If called with arguments, the arguments are the log message.
+"
+" If '!' is used, an empty log message is committed.
+"
+" If called with no arguments, this is a two-step command.
+" The first step opens a buffer to accept a log message.
+" When that buffer is written, it is automatically closed and
+" the file is committed using the information from that log
+" message. The commit can be abandoned if the log message
+" buffer is deleted or wiped before being written.
+"
+" VCSDelete Deletes the current file and removes it from source control.
+"
+" VCSDiff With no arguments, this displays the differences between
+" the current file and its parent version under source
+" control in a new scratch buffer.
+"
+" With one argument, the diff is performed on the
+" current file against the specified revision.
+"
+" With two arguments, the diff is performed between the
+" specified revisions of the current file.
+"
+" This command uses the 'VCSCommand{VCSType}DiffOpt' variable
+" to specify diff options. If that variable does not exist,
+" a plugin-specific default is used. If you wish to have no
+" options, then set it to the empty string.
+"
+" VCSGotoOriginal Jumps to the source buffer if the current buffer is a VCS
+" scratch buffer. If VCSGotoOriginal[!] is used, remove all
+" VCS scratch buffers associated with the original file.
+"
+" VCSInfo Displays extended information about the current file in a
+" new scratch buffer.
+"
+" VCSLock Locks the current file in order to prevent other users from
+" concurrently modifying it. The exact semantics of this
+" command depend on the underlying VCS.
+"
+" VCSLog Displays the version history of the current file in a new
+" scratch buffer.
+"
+" VCSRemove Alias for 'VCSDelete'.
+"
+" VCSRevert Replaces the modified version of the current file with the
+" most recent version from the repository.
+"
+" VCSReview Displays a particular version of the current file in a new
+" scratch buffer. If no argument is given, the most recent
+" version of the file on the current branch is retrieved.
+"
+" VCSStatus Displays versioning information about the current file in a
+" new scratch buffer.
+"
+" VCSUnlock Unlocks the current file in order to allow other users from
+" concurrently modifying it. The exact semantics of this
+" command depend on the underlying VCS.
+"
+" VCSUpdate Updates the current file with any relevant changes from the
+" repository.
+"
+" VCSVimDiff Uses vimdiff to display differences between versions of the
+" current file.
+"
+" If no revision is specified, the most recent version of the
+" file on the current branch is used. With one argument,
+" that argument is used as the revision as above. With two
+" arguments, the differences between the two revisions is
+" displayed using vimdiff.
+"
+" With either zero or one argument, the original buffer is
+" used to perform the vimdiff. When the scratch buffer is
+" closed, the original buffer will be returned to normal
+" mode.
+"
+" Once vimdiff mode is started using the above methods,
+" additional vimdiff buffers may be added by passing a single
+" version argument to the command. There may be up to 4
+" vimdiff buffers total.
+"
+" Using the 2-argument form of the command resets the vimdiff
+" to only those 2 versions. Additionally, invoking the
+" command on a different file will close the previous vimdiff
+" buffers.
+"
+" Mapping documentation: {{{2
+"
+" By default, a mapping is defined for each command. User-provided mappings
+" can be used instead by mapping to <Plug>CommandName, for instance:
+"
+" nmap ,ca <Plug>VCSAdd
+"
+" The default mappings are as follow:
+"
+" <Leader>ca VCSAdd
+" <Leader>cn VCSAnnotate
+" <Leader>cN VCSAnnotate!
+" <Leader>cc VCSCommit
+" <Leader>cD VCSDelete
+" <Leader>cd VCSDiff
+" <Leader>cg VCSGotoOriginal
+" <Leader>cG VCSGotoOriginal!
+" <Leader>ci VCSInfo
+" <Leader>cl VCSLog
+" <Leader>cL VCSLock
+" <Leader>cr VCSReview
+" <Leader>cs VCSStatus
+" <Leader>cu VCSUpdate
+" <Leader>cU VCSUnlock
+" <Leader>cv VCSVimDiff
+"
+" Options documentation: {{{2
+"
+" Several variables are checked by the script to determine behavior as follow:
+"
+" VCSCommandCommitOnWrite
+" This variable, if set to a non-zero value, causes the pending commit to
+" take place immediately as soon as the log message buffer is written. If
+" set to zero, only the VCSCommit mapping will cause the pending commit to
+" occur. If not set, it defaults to 1.
+"
+" VCSCommandDeleteOnHide
+" This variable, if set to a non-zero value, causes the temporary VCS result
+" buffers to automatically delete themselves when hidden.
+"
+" VCSCommand{VCSType}DiffOpt
+" This variable, if set, determines the options passed to the diff command
+" of the underlying VCS. Each VCS plugin defines a default value.
+"
+" VCSCommandDiffSplit
+" This variable overrides the VCSCommandSplit variable, but only for buffers
+" created with VCSVimDiff.
+"
+" VCSCommandDisableAll
+" This variable, if set, prevents the plugin or any extensions from loading
+" at all. This is useful when a single runtime distribution is used on
+" multiple systems with varying versions.
+"
+" VCSCommandDisableMappings
+" This variable, if set to a non-zero value, prevents the default command
+" mappings from being set.
+"
+" VCSCommandDisableExtensionMappings
+" This variable, if set to a non-zero value, prevents the default command
+" mappings from being set for commands specific to an individual VCS.
+"
+" VCSCommandDisableMenu
+" This variable, if set to a non-zero value, prevents the default command
+" menu from being set.
+"
+" VCSCommandEdit
+" This variable controls whether to split the current window to display a
+" scratch buffer ('split'), or to display it in the current buffer ('edit').
+" If not set, it defaults to 'split'.
+"
+" VCSCommandEnableBufferSetup
+" This variable, if set to a non-zero value, activates VCS buffer management
+" mode. This mode means that the buffer variable 'VCSRevision' is set if
+" the file is VCS-controlled. This is useful for displaying version
+" information in the status bar. Additional options may be set by
+" individual VCS plugins.
+"
+" VCSCommandMappings
+" This variable, if set, overrides the default mappings used for shortcuts.
+" It should be a List of 2-element Lists, each containing a shortcut and
+" function name pair.
+"
+" VCSCommandMapPrefix
+" This variable, if set, overrides the default mapping prefix ('<Leader>c').
+" This allows customization of the mapping space used by the vcscommand
+" shortcuts.
+"
+" VCSCommandMenuPriority
+" This variable, if set, overrides the default menu priority '' (empty)
+"
+" VCSCommandMenuRoot
+" This variable, if set, overrides the default menu root 'Plugin.VCS'
+"
+" VCSCommandResultBufferNameExtension
+" This variable, if set to a non-blank value, is appended to the name of the
+" VCS command output buffers. For example, '.vcs'. Using this option may
+" help avoid problems caused by autocommands dependent on file extension.
+"
+" VCSCommandResultBufferNameFunction
+" This variable, if set, specifies a custom function for naming VCS command
+" output buffers. This function will be passed the following arguments:
+"
+" command - name of the VCS command being executed (such as 'Log' or
+" 'Diff').
+"
+" originalBuffer - buffer number of the source file.
+"
+" vcsType - type of VCS controlling this file (such as 'CVS' or 'SVN').
+"
+" statusText - extra text associated with the VCS action (such as version
+" numbers).
+"
+" VCSCommandSplit
+" This variable controls the orientation of the various window splits that
+" may occur (such as with VCSVimDiff, when using a VCS command on a VCS
+" command buffer, or when the 'VCSCommandEdit' variable is set to 'split'.
+" If set to 'horizontal', the resulting windows will be on stacked on top of
+" one another. If set to 'vertical', the resulting windows will be
+" side-by-side. If not set, it defaults to 'horizontal' for all but
+" VCSVimDiff windows.
+"
+" VCSCommandVCSTypeOverride
+" This variable allows the VCS type detection to be overridden on a
+" path-by-path basis. The value of this variable is expected to be a List
+" of Lists. Each high-level List item is a List containing two elements.
+" The first element is a regular expression that will be matched against the
+" full file name of a given buffer. If it matches, the second element will
+" be used as the VCS type.
+"
+" Event documentation {{{2
+" For additional customization, VCSCommand.vim uses User event autocommand
+" hooks. Each event is in the VCSCommand group, and different patterns
+" match the various hooks.
+"
+" For instance, the following could be added to the vimrc to provide a 'q'
+" mapping to quit a VCS scratch buffer:
+"
+" augroup VCSCommand
+" au VCSCommand User VCSBufferCreated silent! nmap <unique> <buffer> q :bwipeout<cr>
+" augroup END
+"
+" The following hooks are available:
+"
+" VCSBufferCreated This event is fired just after a VCS command
+" output buffer is created. It is executed
+" within the context of the new buffer.
+"
+" VCSBufferSetup This event is fired just after VCS buffer setup
+" occurs, if enabled.
+"
+" VCSPluginInit This event is fired when the VCSCommand plugin
+" first loads.
+"
+" VCSPluginFinish This event is fired just after the VCSCommand
+" plugin loads.
+"
+" VCSVimDiffFinish This event is fired just after the VCSVimDiff
+" command executes to allow customization of,
+" for instance, window placement and focus.
+"
+" Section: Plugin header {{{1
+
+" loaded_VCSCommand is set to 1 when the initialization begins, and 2 when it
+" completes. This allows various actions to only be taken by functions after
+" system initialization.
+
+if exists('VCSCommandDisableAll')
+ finish
+endif
+
+if exists('loaded_VCSCommand')
+ finish
+endif
+let loaded_VCSCommand = 1
+
+if v:version < 700
+ echohl WarningMsg|echomsg 'VCSCommand requires at least VIM 7.0'|echohl None
+ finish
+endif
+
+let s:save_cpo=&cpo
+set cpo&vim
+
+" Section: Event group setup {{{1
+
+augroup VCSCommand
+augroup END
+
+augroup VCSCommandCommit
+augroup END
+
+" Section: Plugin initialization {{{1
+silent do VCSCommand User VCSPluginInit
+
+" Section: Constants declaration {{{1
+
+let g:VCSCOMMAND_IDENTIFY_EXACT = 1
+let g:VCSCOMMAND_IDENTIFY_INEXACT = -1
+
+" Section: Script variable initialization {{{1
+
+" Hidden functions for use by extensions
+let s:VCSCommandUtility = {}
+
+" plugin-specific information: {vcs -> [script, {command -> function}, {key -> mapping}]}
+let s:plugins = {}
+
+" temporary values of overridden configuration variables
+let s:optionOverrides = {}
+
+" state flag used to vary behavior of certain automated actions
+let s:isEditFileRunning = 0
+
+" Section: Utility functions {{{1
+
+" Function: s:ReportError(mapping) {{{2
+" Displays the given error in a consistent faction. This is intended to be
+" invoked from a catch statement.
+
+function! s:ReportError(error)
+ echohl WarningMsg|echomsg 'VCSCommand: ' . a:error|echohl None
+endfunction
+
+" Function: s:VCSCommandUtility.system(...) {{{2
+" Replacement for system() function. This version protects the quoting in the
+" command line on Windows systems.
+
+function! s:VCSCommandUtility.system(...)
+ if (has("win32") || has("win64")) && &sxq !~ '"'
+ let save_sxq = &sxq
+ set sxq=\"
+ endif
+ try
+ return call('system', a:000)
+ finally
+ if exists("save_sxq")
+ let &sxq = save_sxq
+ endif
+ endtry
+endfunction
+
+" Function: s:VCSCommandUtility.addMenuItem(shortcut, command) {{{2
+" Adds the given menu item.
+
+function! s:VCSCommandUtility.addMenuItem(shortcut, command)
+ if s:menuEnabled
+ exe 'amenu <silent> '.s:menuPriority.' '.s:menuRoot.'.'.a:shortcut.' '.a:command
+ endif
+endfunction
+
+" Function: s:ClearMenu() {{{2
+" Removes all VCSCommand menu items
+function! s:ClearMenu()
+ if s:menuEnabled
+ execute 'aunmenu' s:menuRoot
+ endif
+endfunction
+
+" Function: s:CreateMapping(shortcut, expansion, display) {{{2
+" Creates the given mapping by prepending the contents of
+" 'VCSCommandMapPrefix' (by default '<Leader>c') to the given shortcut and
+" mapping it to the given plugin function. If a mapping exists for the
+" specified shortcut + prefix, emit an error but continue. If a mapping
+" exists for the specified function, do nothing.
+
+function! s:CreateMapping(shortcut, expansion, display)
+ let lhs = VCSCommandGetOption('VCSCommandMapPrefix', '<Leader>c') . a:shortcut
+ if !hasmapto(a:expansion)
+ try
+ execute 'nmap <silent> <unique>' lhs a:expansion
+ catch /^Vim(.*):E227:/
+ if(&verbose != 0)
+ echohl WarningMsg|echomsg 'VCSCommand: mapping ''' . lhs . ''' already exists, refusing to overwrite. The mapping for ' . a:display . ' will not be available.'|echohl None
+ endif
+ endtry
+ endif
+endfunction
+
+" Function: s:ExecuteExtensionMapping(mapping) {{{2
+" Invokes the appropriate extension mapping depending on the type of the
+" current buffer.
+
+function! s:ExecuteExtensionMapping(mapping)
+ let buffer = bufnr('%')
+ let vcsType = VCSCommandGetVCSType(buffer)
+ if !has_key(s:plugins, vcsType)
+ throw 'Unknown VCS type: ' . vcsType
+ endif
+ if !has_key(s:plugins[vcsType][2], a:mapping)
+ throw 'This extended mapping is not defined for ' . vcsType
+ endif
+ silent execute 'normal' ':' . s:plugins[vcsType][2][a:mapping] . "\<CR>"
+endfunction
+
+" Function: s:ExecuteVCSCommand(command, argList) {{{2
+" Calls the indicated plugin-specific VCS command on the current buffer.
+" Returns: buffer number of resulting output scratch buffer, or -1 if an error
+" occurs.
+
+function! s:ExecuteVCSCommand(command, argList)
+ try
+ let buffer = bufnr('%')
+
+ let vcsType = VCSCommandGetVCSType(buffer)
+ if !has_key(s:plugins, vcsType)
+ throw 'Unknown VCS type: ' . vcsType
+ endif
+
+ let originalBuffer = VCSCommandGetOriginalBuffer(buffer)
+ let bufferName = bufname(originalBuffer)
+
+ " It is already known that the directory is under VCS control. No further
+ " checks are needed. Otherwise, perform some basic sanity checks to avoid
+ " VCS-specific error messages from confusing things.
+ if !isdirectory(bufferName)
+ if !filereadable(bufferName)
+ throw 'No such file ' . bufferName
+ endif
+ endif
+
+ let functionMap = s:plugins[vcsType][1]
+ if !has_key(functionMap, a:command)
+ throw 'Command ''' . a:command . ''' not implemented for ' . vcsType
+ endif
+ return functionMap[a:command](a:argList)
+ catch
+ call s:ReportError(v:exception)
+ return -1
+ endtry
+endfunction
+
+" Function: s:GenerateResultBufferName(command, originalBuffer, vcsType, statusText) {{{2
+" Default method of generating the name for VCS result buffers. This can be
+" overridden with the VCSResultBufferNameFunction variable.
+
+function! s:GenerateResultBufferName(command, originalBuffer, vcsType, statusText)
+ let fileName = bufname(a:originalBuffer)
+ let bufferName = a:vcsType . ' ' . a:command
+ if strlen(a:statusText) > 0
+ let bufferName .= ' ' . a:statusText
+ endif
+ let bufferName .= ' ' . fileName
+ let counter = 0
+ let versionedBufferName = bufferName
+ while bufexists(versionedBufferName)
+ let counter += 1
+ let versionedBufferName = bufferName . ' (' . counter . ')'
+ endwhile
+ return versionedBufferName
+endfunction
+
+" Function: s:GenerateResultBufferNameWithExtension(command, originalBuffer, vcsType, statusText) {{{2
+" Method of generating the name for VCS result buffers that uses the original
+" file name with the VCS type and command appended as extensions.
+
+function! s:GenerateResultBufferNameWithExtension(command, originalBuffer, vcsType, statusText)
+ let fileName = bufname(a:originalBuffer)
+ let bufferName = a:vcsType . ' ' . a:command
+ if strlen(a:statusText) > 0
+ let bufferName .= ' ' . a:statusText
+ endif
+ let bufferName .= ' ' . fileName . VCSCommandGetOption('VCSCommandResultBufferNameExtension', '.vcs')
+ let counter = 0
+ let versionedBufferName = bufferName
+ while bufexists(versionedBufferName)
+ let counter += 1
+ let versionedBufferName = '(' . counter . ') ' . bufferName
+ endwhile
+ return versionedBufferName
+endfunction
+
+" Function: s:EditFile(command, originalBuffer, statusText) {{{2
+" Creates a new buffer of the given name and associates it with the given
+" original buffer.
+
+function! s:EditFile(command, originalBuffer, statusText)
+ let vcsType = getbufvar(a:originalBuffer, 'VCSCommandVCSType')
+
+ " Protect against useless buffer set-up
+ let s:isEditFileRunning += 1
+ try
+ let editCommand = VCSCommandGetOption('VCSCommandEdit', 'split')
+ if editCommand == 'split'
+ if VCSCommandGetOption('VCSCommandSplit', 'horizontal') == 'horizontal'
+ rightbelow split
+ else
+ vert rightbelow split
+ endif
+ endif
+
+ enew
+
+ call s:SetupScratchBuffer(a:command, vcsType, a:originalBuffer, a:statusText)
+
+ finally
+ let s:isEditFileRunning -= 1
+ endtry
+endfunction
+
+" Function: s:SetupScratchBuffer(command, vcsType, originalBuffer, statusText) {{{2
+" Creates convenience buffer variables and the name of a vcscommand result
+" buffer.
+
+function! s:SetupScratchBuffer(command, vcsType, originalBuffer, statusText)
+ let nameExtension = VCSCommandGetOption('VCSCommandResultBufferNameExtension', '')
+ if nameExtension == ''
+ let nameFunction = VCSCommandGetOption('VCSCommandResultBufferNameFunction', 's:GenerateResultBufferName')
+ else
+ let nameFunction = VCSCommandGetOption('VCSCommandResultBufferNameFunction', 's:GenerateResultBufferNameWithExtension')
+ endif
+
+ let name = call(nameFunction, [a:command, a:originalBuffer, a:vcsType, a:statusText])
+
+ let b:VCSCommandCommand = a:command
+ let b:VCSCommandOriginalBuffer = a:originalBuffer
+ let b:VCSCommandSourceFile = bufname(a:originalBuffer)
+ let b:VCSCommandVCSType = a:vcsType
+ if a:statusText != ''
+ let b:VCSCommandStatusText = a:statusText
+ endif
+
+ setlocal buftype=nofile
+ setlocal noswapfile
+ let &filetype = tolower(a:vcsType . a:command)
+
+ if VCSCommandGetOption('VCSCommandDeleteOnHide', 0)
+ setlocal bufhidden=delete
+ endif
+ silent noautocmd file `=name`
+endfunction
+
+" Function: s:SetupBuffer() {{{2
+" Attempts to set the b:VCSCommandBufferInfo variable
+
+function! s:SetupBuffer()
+ if (exists('b:VCSCommandBufferSetup') && b:VCSCommandBufferSetup)
+ " This buffer is already set up.
+ return
+ endif
+
+ if !isdirectory(@%) && (strlen(&buftype) > 0 || !filereadable(@%))
+ " No special status for special buffers other than directory buffers.
+ return
+ endif
+
+ if !VCSCommandGetOption('VCSCommandEnableBufferSetup', 0) || s:isEditFileRunning > 0
+ unlet! b:VCSCommandBufferSetup
+ return
+ endif
+
+ try
+ let vcsType = VCSCommandGetVCSType(bufnr('%'))
+ let b:VCSCommandBufferInfo = s:plugins[vcsType][1].GetBufferInfo()
+ silent do VCSCommand User VCSBufferSetup
+ catch /No suitable plugin/
+ " This is not a VCS-controlled file.
+ let b:VCSCommandBufferInfo = []
+ endtry
+
+ let b:VCSCommandBufferSetup = 1
+endfunction
+
+" Function: s:MarkOrigBufferForSetup(buffer) {{{2
+" Resets the buffer setup state of the original buffer for a given VCS scratch
+" buffer.
+" Returns: The VCS buffer number in a passthrough mode.
+
+function! s:MarkOrigBufferForSetup(buffer)
+ checktime
+ if a:buffer > 0
+ let origBuffer = VCSCommandGetOriginalBuffer(a:buffer)
+ " This should never not work, but I'm paranoid
+ if origBuffer != a:buffer
+ call setbufvar(origBuffer, 'VCSCommandBufferSetup', 0)
+ endif
+ endif
+ return a:buffer
+endfunction
+
+" Function: s:OverrideOption(option, [value]) {{{2
+" Provides a temporary override for the given VCS option. If no value is
+" passed, the override is disabled.
+
+function! s:OverrideOption(option, ...)
+ if a:0 == 0
+ call remove(s:optionOverrides[a:option], -1)
+ else
+ if !has_key(s:optionOverrides, a:option)
+ let s:optionOverrides[a:option] = []
+ endif
+ call add(s:optionOverrides[a:option], a:1)
+ endif
+endfunction
+
+" Function: s:WipeoutCommandBuffers() {{{2
+" Clears all current VCS output buffers of the specified type for a given source.
+
+function! s:WipeoutCommandBuffers(originalBuffer, VCSCommand)
+ let buffer = 1
+ while buffer <= bufnr('$')
+ if getbufvar(buffer, 'VCSCommandOriginalBuffer') == a:originalBuffer
+ if getbufvar(buffer, 'VCSCommandCommand') == a:VCSCommand
+ execute 'bw' buffer
+ endif
+ endif
+ let buffer = buffer + 1
+ endwhile
+endfunction
+
+" Function: s:VimDiffRestore(vimDiffBuff) {{{2
+" Checks whether the given buffer is one whose deletion should trigger
+" restoration of an original buffer after it was diffed. If so, it executes
+" the appropriate setting command stored with that original buffer.
+
+function! s:VimDiffRestore(vimDiffBuff)
+ let s:isEditFileRunning += 1
+ try
+ if exists('t:vcsCommandVimDiffSourceBuffer')
+ if a:vimDiffBuff == t:vcsCommandVimDiffSourceBuffer
+ " Original file is being removed.
+ unlet! t:vcsCommandVimDiffSourceBuffer
+ unlet! t:vcsCommandVimDiffRestoreCmd
+ unlet! t:vcsCommandVimDiffScratchList
+ else
+ let index = index(t:vcsCommandVimDiffScratchList, a:vimDiffBuff)
+ if index >= 0
+ call remove(t:vcsCommandVimDiffScratchList, index)
+ if len(t:vcsCommandVimDiffScratchList) == 0
+ if exists('t:vcsCommandVimDiffRestoreCmd')
+ " All scratch buffers are gone, reset the original.
+ " Only restore if the source buffer is still in Diff mode
+
+ let sourceWinNR = bufwinnr(t:vcsCommandVimDiffSourceBuffer)
+ if sourceWinNR != -1
+ " The buffer is visible in at least one window
+ let currentWinNR = winnr()
+ while winbufnr(sourceWinNR) != -1
+ if winbufnr(sourceWinNR) == t:vcsCommandVimDiffSourceBuffer
+ execute sourceWinNR . 'wincmd w'
+ if getwinvar(0, '&diff')
+ execute t:vcsCommandVimDiffRestoreCmd
+ endif
+ endif
+ let sourceWinNR = sourceWinNR + 1
+ endwhile
+ execute currentWinNR . 'wincmd w'
+ else
+ " The buffer is hidden. It must be visible in order to set the
+ " diff option.
+ let currentBufNR = bufnr('')
+ execute 'hide buffer' t:vcsCommandVimDiffSourceBuffer
+ if getwinvar(0, '&diff')
+ execute t:vcsCommandVimDiffRestoreCmd
+ endif
+ execute 'hide buffer' currentBufNR
+ endif
+
+ unlet t:vcsCommandVimDiffRestoreCmd
+ endif
+ " All buffers are gone.
+ unlet t:vcsCommandVimDiffSourceBuffer
+ unlet t:vcsCommandVimDiffScratchList
+ endif
+ endif
+ endif
+ endif
+ finally
+ let s:isEditFileRunning -= 1
+ endtry
+endfunction
+
+" Section: Generic VCS command functions {{{1
+
+" Function: s:VCSAnnotate(...) {{{2
+function! s:VCSAnnotate(bang, ...)
+ try
+ let line = line('.')
+ let currentBuffer = bufnr('%')
+ let originalBuffer = VCSCommandGetOriginalBuffer(currentBuffer)
+
+ let annotateBuffer = s:ExecuteVCSCommand('Annotate', a:000)
+ if annotateBuffer == -1
+ return -1
+ endif
+ if a:bang == '!' && VCSCommandGetOption('VCSCommandDisableSplitAnnotate', 0) == 0
+ let vcsType = VCSCommandGetVCSType(annotateBuffer)
+ let functionMap = s:plugins[vcsType][1]
+ let splitRegex = ''
+ if has_key(s:plugins[vcsType][1], 'AnnotateSplitRegex')
+ let splitRegex = s:plugins[vcsType][1]['AnnotateSplitRegex']
+ endif
+ let splitRegex = VCSCommandGetOption('VCSCommand' . vcsType . 'AnnotateSplitRegex', splitRegex)
+ if splitRegex == ''
+ return annotateBuffer
+ endif
+ let originalFileType = getbufvar(originalBuffer, '&ft')
+ let annotateFileType = getbufvar(annotateBuffer, '&ft')
+ execute "normal 0zR\<c-v>G/" . splitRegex . "/e\<cr>d"
+ call setbufvar('%', '&filetype', getbufvar(originalBuffer, '&filetype'))
+ set scrollbind
+ leftabove vert new
+ normal 0P
+ execute "normal" . col('$') . "\<c-w>|"
+ call s:SetupScratchBuffer('annotate', vcsType, originalBuffer, 'header')
+ wincmd l
+ endif
+
+ if currentBuffer == originalBuffer
+ " Starting from the original source buffer, so the
+ " current line is relevant.
+ if a:0 == 0
+ " No argument list means that we're annotating
+ " the current version, so jumping to the same
+ " line is the expected action.
+ execute "normal" line . 'G'
+ if has('folding')
+ " The execution of the buffer created autocommand
+ " re-folds the buffer. Display the current line
+ " unfolded.
+ normal zv
+ endif
+ endif
+ endif
+
+ return annotateBuffer
+ catch
+ call s:ReportError(v:exception)
+ return -1
+ endtry
+endfunction
+
+" Function: s:VCSCommit() {{{2
+function! s:VCSCommit(bang, message)
+ try
+ let vcsType = VCSCommandGetVCSType(bufnr('%'))
+ if !has_key(s:plugins, vcsType)
+ throw 'Unknown VCS type: ' . vcsType
+ endif
+
+ let originalBuffer = VCSCommandGetOriginalBuffer(bufnr('%'))
+
+ " Handle the commit message being specified. If a message is supplied, it
+ " is used; if bang is supplied, an empty message is used; otherwise, the
+ " user is provided a buffer from which to edit the commit message.
+
+ if strlen(a:message) > 0 || a:bang == '!'
+ return s:VCSFinishCommit([a:message], originalBuffer)
+ endif
+
+ call s:EditFile('commitlog', originalBuffer, '')
+ setlocal ft=vcscommit
+
+ " Create a commit mapping.
+
+ nnoremap <silent> <buffer> <Plug>VCSCommit :call <SID>VCSFinishCommitWithBuffer()<CR>
+
+ silent 0put ='VCS: ----------------------------------------------------------------------'
+ silent put ='VCS: Please enter log message. Lines beginning with ''VCS:'' are removed automatically.'
+ silent put ='VCS: To finish the commit, Type <leader>cc (or your own <Plug>VCSCommit mapping)'
+
+ if VCSCommandGetOption('VCSCommandCommitOnWrite', 1) == 1
+ setlocal buftype=acwrite
+ au VCSCommandCommit BufWriteCmd <buffer> call s:VCSFinishCommitWithBuffer()
+ silent put ='VCS: or write this buffer'
+ endif
+
+ silent put ='VCS: ----------------------------------------------------------------------'
+ $
+ setlocal nomodified
+ silent do VCSCommand User VCSBufferCreated
+ catch
+ call s:ReportError(v:exception)
+ return -1
+ endtry
+endfunction
+
+" Function: s:VCSFinishCommitWithBuffer() {{{2
+" Wrapper for s:VCSFinishCommit which is called only from a commit log buffer
+" which removes all lines starting with 'VCS:'.
+
+function! s:VCSFinishCommitWithBuffer()
+ setlocal nomodified
+ let currentBuffer = bufnr('%')
+ let logMessageList = getbufline('%', 1, '$')
+ call filter(logMessageList, 'v:val !~ ''^\s*VCS:''')
+ let resultBuffer = s:VCSFinishCommit(logMessageList, b:VCSCommandOriginalBuffer)
+ if resultBuffer >= 0
+ execute 'bw' currentBuffer
+ endif
+ return resultBuffer
+endfunction
+
+" Function: s:VCSFinishCommit(logMessageList, originalBuffer) {{{2
+function! s:VCSFinishCommit(logMessageList, originalBuffer)
+ let messageFileName = tempname()
+ call writefile(a:logMessageList, messageFileName)
+ try
+ let resultBuffer = s:ExecuteVCSCommand('Commit', [messageFileName])
+ if resultBuffer < 0
+ return resultBuffer
+ endif
+ return s:MarkOrigBufferForSetup(resultBuffer)
+ finally
+ call delete(messageFileName)
+ endtry
+endfunction
+
+" Function: s:VCSGotoOriginal(bang) {{{2
+function! s:VCSGotoOriginal(bang)
+ let originalBuffer = VCSCommandGetOriginalBuffer(bufnr('%'))
+ if originalBuffer > 0
+ let origWinNR = bufwinnr(originalBuffer)
+ if origWinNR == -1
+ execute 'buffer' originalBuffer
+ else
+ execute origWinNR . 'wincmd w'
+ endif
+ if a:bang == '!'
+ let buffnr = 1
+ let buffmaxnr = bufnr('$')
+ while buffnr <= buffmaxnr
+ if getbufvar(buffnr, 'VCSCommandOriginalBuffer') == originalBuffer
+ execute 'bw' buffnr
+ endif
+ let buffnr = buffnr + 1
+ endwhile
+ endif
+ endif
+endfunction
+
+function! s:VCSDiff(...) "{{{2
+ let resultBuffer = s:ExecuteVCSCommand('Diff', a:000)
+ if resultBuffer > 0
+ let &filetype = 'diff'
+ elseif resultBuffer == 0
+ echomsg 'No differences found'
+ endif
+ return resultBuffer
+endfunction
+
+function! s:VCSReview(...) "{{{2
+ let resultBuffer = s:ExecuteVCSCommand('Review', a:000)
+ if resultBuffer > 0
+ let &filetype = getbufvar(b:VCSCommandOriginalBuffer, '&filetype')
+ endif
+ return resultBuffer
+endfunction
+
+" Function: s:VCSVimDiff(...) {{{2
+function! s:VCSVimDiff(...)
+ try
+ let vcsType = VCSCommandGetVCSType(bufnr('%'))
+ if !has_key(s:plugins, vcsType)
+ throw 'Unknown VCS type: ' . vcsType
+ endif
+ let originalBuffer = VCSCommandGetOriginalBuffer(bufnr('%'))
+ let s:isEditFileRunning = s:isEditFileRunning + 1
+ try
+ " If there's already a VimDiff'ed window, restore it.
+ " There may only be one VCSVimDiff original window at a time.
+
+ if exists('t:vcsCommandVimDiffSourceBuffer') && t:vcsCommandVimDiffSourceBuffer != originalBuffer
+ " Clear the existing vimdiff setup by removing the result buffers.
+ call s:WipeoutCommandBuffers(t:vcsCommandVimDiffSourceBuffer, 'vimdiff')
+ endif
+
+ let orientation = &diffopt =~ 'horizontal' ? 'horizontal' : 'vertical'
+ let orientation = VCSCommandGetOption('VCSCommandSplit', orientation)
+ let orientation = VCSCommandGetOption('VCSCommandDiffSplit', orientation)
+
+ " Split and diff
+ if(a:0 == 2)
+ " Reset the vimdiff system, as 2 explicit versions were provided.
+ if exists('t:vcsCommandVimDiffSourceBuffer')
+ call s:WipeoutCommandBuffers(t:vcsCommandVimDiffSourceBuffer, 'vimdiff')
+ endif
+ let resultBuffer = s:VCSReview(a:1)
+ if resultBuffer < 0
+ echomsg 'Can''t open revision ' . a:1
+ return resultBuffer
+ endif
+ let b:VCSCommandCommand = 'vimdiff'
+ diffthis
+ let t:vcsCommandVimDiffScratchList = [resultBuffer]
+ " If no split method is defined, cheat, and set it to vertical.
+ try
+ call s:OverrideOption('VCSCommandSplit', orientation)
+ let resultBuffer = s:VCSReview(a:2)
+ finally
+ call s:OverrideOption('VCSCommandSplit')
+ endtry
+ if resultBuffer < 0
+ echomsg 'Can''t open revision ' . a:1
+ return resultBuffer
+ endif
+ let b:VCSCommandCommand = 'vimdiff'
+ diffthis
+ let t:vcsCommandVimDiffScratchList += [resultBuffer]
+ else
+ " Add new buffer
+ call s:OverrideOption('VCSCommandEdit', 'split')
+ try
+ " Force splitting behavior, otherwise why use vimdiff?
+ call s:OverrideOption('VCSCommandSplit', orientation)
+ try
+ if(a:0 == 0)
+ let resultBuffer = s:VCSReview()
+ else
+ let resultBuffer = s:VCSReview(a:1)
+ endif
+ finally
+ call s:OverrideOption('VCSCommandSplit')
+ endtry
+ finally
+ call s:OverrideOption('VCSCommandEdit')
+ endtry
+ if resultBuffer < 0
+ echomsg 'Can''t open current revision'
+ return resultBuffer
+ endif
+ let b:VCSCommandCommand = 'vimdiff'
+ diffthis
+
+ if !exists('t:vcsCommandVimDiffSourceBuffer')
+ " New instance of vimdiff.
+ let t:vcsCommandVimDiffScratchList = [resultBuffer]
+
+ " This could have been invoked on a VCS result buffer, not the
+ " original buffer.
+ wincmd W
+ execute 'buffer' originalBuffer
+ " Store info for later original buffer restore
+ let t:vcsCommandVimDiffRestoreCmd =
+ \ 'call setbufvar('.originalBuffer.', ''&diff'', '.getbufvar(originalBuffer, '&diff').')'
+ \ . '|call setbufvar('.originalBuffer.', ''&foldcolumn'', '.getbufvar(originalBuffer, '&foldcolumn').')'
+ \ . '|call setbufvar('.originalBuffer.', ''&foldenable'', '.getbufvar(originalBuffer, '&foldenable').')'
+ \ . '|call setbufvar('.originalBuffer.', ''&foldmethod'', '''.getbufvar(originalBuffer, '&foldmethod').''')'
+ \ . '|call setbufvar('.originalBuffer.', ''&foldlevel'', '''.getbufvar(originalBuffer, '&foldlevel').''')'
+ \ . '|call setbufvar('.originalBuffer.', ''&scrollbind'', '.getbufvar(originalBuffer, '&scrollbind').')'
+ \ . '|call setbufvar('.originalBuffer.', ''&wrap'', '.getbufvar(originalBuffer, '&wrap').')'
+ \ . '|if &foldmethod==''manual''|execute ''normal zE''|endif'
+ diffthis
+ wincmd w
+ else
+ " Adding a window to an existing vimdiff
+ let t:vcsCommandVimDiffScratchList += [resultBuffer]
+ endif
+ endif
+
+ let t:vcsCommandVimDiffSourceBuffer = originalBuffer
+
+ " Avoid executing the modeline in the current buffer after the autocommand.
+
+ let currentBuffer = bufnr('%')
+ let saveModeline = getbufvar(currentBuffer, '&modeline')
+ try
+ call setbufvar(currentBuffer, '&modeline', 0)
+ silent do VCSCommand User VCSVimDiffFinish
+ finally
+ call setbufvar(currentBuffer, '&modeline', saveModeline)
+ endtry
+ return resultBuffer
+ finally
+ let s:isEditFileRunning = s:isEditFileRunning - 1
+ endtry
+ catch
+ call s:ReportError(v:exception)
+ return -1
+ endtry
+endfunction
+
+" Section: Public functions {{{1
+
+" Function: VCSCommandGetVCSType() {{{2
+" Sets the b:VCSCommandVCSType variable in the given buffer to the
+" appropriate source control system name.
+"
+" This uses the Identify extension function to test the buffer. If the
+" Identify function returns VCSCOMMAND_IDENTIFY_EXACT, the match is considered
+" exact. If the Identify function returns VCSCOMMAND_IDENTIFY_INEXACT, the
+" match is considered inexact, and is only applied if no exact match is found.
+" Multiple inexact matches is currently considered an error.
+
+function! VCSCommandGetVCSType(buffer)
+ let vcsType = getbufvar(a:buffer, 'VCSCommandVCSType')
+ if strlen(vcsType) > 0
+ return vcsType
+ endif
+ if exists("g:VCSCommandVCSTypeOverride")
+ let fullpath = fnamemodify(bufname(a:buffer), ':p')
+ for [path, vcsType] in g:VCSCommandVCSTypeOverride
+ if match(fullpath, path) > -1
+ call setbufvar(a:buffer, 'VCSCommandVCSType', vcsType)
+ return vcsType
+ endif
+ endfor
+ endif
+ let matches = []
+ for vcsType in keys(s:plugins)
+ let identified = s:plugins[vcsType][1].Identify(a:buffer)
+ if identified
+ if identified == g:VCSCOMMAND_IDENTIFY_EXACT
+ let matches = [vcsType]
+ break
+ else
+ let matches += [vcsType]
+ endif
+ endif
+ endfor
+ if len(matches) == 1
+ call setbufvar(a:buffer, 'VCSCommandVCSType', matches[0])
+ return matches[0]
+ elseif len(matches) == 0
+ throw 'No suitable plugin'
+ else
+ throw 'Too many matching VCS: ' . join(matches)
+ endif
+endfunction
+
+" Function: VCSCommandChdir(directory) {{{2
+" Changes the current directory, respecting :lcd changes.
+
+function! VCSCommandChdir(directory)
+ let command = 'cd'
+ if exists("*haslocaldir") && haslocaldir()
+ let command = 'lcd'
+ endif
+ execute command escape(a:directory, ' ')
+endfunction
+
+" Function: VCSCommandChangeToCurrentFileDir() {{{2
+" Go to the directory in which the given file is located.
+
+function! VCSCommandChangeToCurrentFileDir(fileName)
+ let oldCwd = getcwd()
+ let newCwd = fnamemodify(resolve(a:fileName), ':p:h')
+ if strlen(newCwd) > 0
+ call VCSCommandChdir(newCwd)
+ endif
+ return oldCwd
+endfunction
+
+" Function: VCSCommandGetOriginalBuffer(vcsBuffer) {{{2
+" Attempts to locate the original file to which VCS operations were applied
+" for a given buffer.
+
+function! VCSCommandGetOriginalBuffer(vcsBuffer)
+ let origBuffer = getbufvar(a:vcsBuffer, 'VCSCommandOriginalBuffer')
+ if origBuffer
+ if bufexists(origBuffer)
+ return origBuffer
+ else
+ " Original buffer no longer exists.
+ throw 'Original buffer for this VCS buffer no longer exists.'
+ endif
+ else
+ " No original buffer
+ return a:vcsBuffer
+ endif
+endfunction
+
+" Function: VCSCommandRegisterModule(name, file, commandMap) {{{2
+" Allows VCS modules to register themselves.
+
+function! VCSCommandRegisterModule(name, path, commandMap, mappingMap)
+ let s:plugins[a:name] = [a:path, a:commandMap, a:mappingMap]
+ if !empty(a:mappingMap)
+ \ && !VCSCommandGetOption('VCSCommandDisableMappings', 0)
+ \ && !VCSCommandGetOption('VCSCommandDisableExtensionMappings', 0)
+ for shortcut in keys(a:mappingMap)
+ let expansion = ":call <SID>ExecuteExtensionMapping('" . shortcut . "')<CR>"
+ call s:CreateMapping(shortcut, expansion, a:name . " extension mapping " . shortcut)
+ endfor
+ endif
+ return s:VCSCommandUtility
+endfunction
+
+" Function: VCSCommandDoCommand(cmd, cmdName, statusText, [options]) {{{2
+" General skeleton for VCS function execution. The given command is executed
+" after appending the current buffer name (or substituting it for
+" <VCSCOMMANDFILE>, if such a token is present). The output is captured in a
+" new buffer.
+"
+" The optional 'options' Dictionary may contain the following options:
+" allowNonZeroExit: if non-zero, if the underlying VCS command has a
+" non-zero exit status, the command is still considered
+" successfuly. This defaults to zero.
+" Returns: name of the new command buffer containing the command results
+
+function! VCSCommandDoCommand(cmd, cmdName, statusText, options)
+ let allowNonZeroExit = 0
+ if has_key(a:options, 'allowNonZeroExit')
+ let allowNonZeroExit = a:options.allowNonZeroExit
+ endif
+
+ let originalBuffer = VCSCommandGetOriginalBuffer(bufnr('%'))
+ if originalBuffer == -1
+ throw 'Original buffer no longer exists, aborting.'
+ endif
+
+ let path = resolve(bufname(originalBuffer))
+
+ " Work with netrw or other systems where a directory listing is displayed in
+ " a buffer.
+
+ if isdirectory(path)
+ let fileName = '.'
+ else
+ let fileName = fnamemodify(path, ':t')
+ endif
+
+ if match(a:cmd, '<VCSCOMMANDFILE>') > 0
+ let fullCmd = substitute(a:cmd, '<VCSCOMMANDFILE>', fileName, 'g')
+ else
+ let fullCmd = a:cmd . ' -- "' . fileName . '"'
+ endif
+
+ " Change to the directory of the current buffer. This is done for CVS, but
+ " is left in for other systems as it does not affect them negatively.
+
+ let oldCwd = VCSCommandChangeToCurrentFileDir(path)
+ try
+ let output = s:VCSCommandUtility.system(fullCmd)
+ finally
+ call VCSCommandChdir(oldCwd)
+ endtry
+
+ " HACK: if line endings in the repository have been corrupted, the output
+ " of the command will be confused.
+ let output = substitute(output, "\r", '', 'g')
+
+ if v:shell_error && !allowNonZeroExit
+ if strlen(output) == 0
+ throw 'Version control command failed'
+ else
+ let output = substitute(output, '\n', ' ', 'g')
+ throw 'Version control command failed: ' . output
+ endif
+ endif
+
+ if strlen(output) == 0
+ " Handle case of no output. In this case, it is important to check the
+ " file status, especially since cvs edit/unedit may change the attributes
+ " of the file with no visible output.
+
+ checktime
+ return 0
+ endif
+
+ call s:EditFile(a:cmdName, originalBuffer, a:statusText)
+
+ silent 0put=output
+
+ " The last command left a blank line at the end of the buffer. If the
+ " last line is folded (a side effect of the 'put') then the attempt to
+ " remove the blank line will kill the last fold.
+ "
+ " This could be fixed by explicitly detecting whether the last line is
+ " within a fold, but I prefer to simply unfold the result buffer altogether.
+
+ if has('folding')
+ normal zR
+ endif
+
+ $d
+ 1
+
+ " Define the environment and execute user-defined hooks.
+
+ silent do VCSCommand User VCSBufferCreated
+ return bufnr('%')
+endfunction
+
+" Function: VCSCommandGetOption(name, default) {{{2
+" Grab a user-specified option to override the default provided. Options are
+" searched in the window, buffer, then global spaces.
+
+function! VCSCommandGetOption(name, default)
+ if has_key(s:optionOverrides, a:name) && len(s:optionOverrides[a:name]) > 0
+ return s:optionOverrides[a:name][-1]
+ elseif exists('w:' . a:name)
+ return w:{a:name}
+ elseif exists('b:' . a:name)
+ return b:{a:name}
+ elseif exists('g:' . a:name)
+ return g:{a:name}
+ else
+ return a:default
+ endif
+endfunction
+
+" Function: VCSCommandDisableBufferSetup() {{{2
+" Global function for deactivating the buffer autovariables.
+
+function! VCSCommandDisableBufferSetup()
+ let g:VCSCommandEnableBufferSetup = 0
+ silent! augroup! VCSCommandPlugin
+endfunction
+
+" Function: VCSCommandEnableBufferSetup() {{{2
+" Global function for activating the buffer autovariables.
+
+function! VCSCommandEnableBufferSetup()
+ let g:VCSCommandEnableBufferSetup = 1
+ augroup VCSCommandPlugin
+ au!
+ au BufEnter * call s:SetupBuffer()
+ augroup END
+
+ " Only auto-load if the plugin is fully loaded. This gives other plugins a
+ " chance to run.
+ if g:loaded_VCSCommand == 2
+ call s:SetupBuffer()
+ endif
+endfunction
+
+" Function: VCSCommandGetStatusLine() {{{2
+" Default (sample) status line entry for VCS-controlled files. This is only
+" useful if VCS-managed buffer mode is on (see the VCSCommandEnableBufferSetup
+" variable for how to do this).
+
+function! VCSCommandGetStatusLine()
+ if exists('b:VCSCommandCommand')
+ " This is a result buffer. Return nothing because the buffer name
+ " contains information already.
+ return ''
+ endif
+
+ if exists('b:VCSCommandVCSType')
+ \ && exists('g:VCSCommandEnableBufferSetup')
+ \ && g:VCSCommandEnableBufferSetup
+ \ && exists('b:VCSCommandBufferInfo')
+ return '[' . join(extend([b:VCSCommandVCSType], b:VCSCommandBufferInfo), ' ') . ']'
+ else
+ return ''
+ endif
+endfunction
+
+" Section: Command definitions {{{1
+" Section: Primary commands {{{2
+com! -nargs=* VCSAdd call s:MarkOrigBufferForSetup(s:ExecuteVCSCommand('Add', [<f-args>]))
+com! -nargs=* -bang VCSAnnotate call s:VCSAnnotate(<q-bang>, <f-args>)
+com! -nargs=* -bang VCSBlame call s:VCSAnnotate(<q-bang>, <f-args>)
+com! -nargs=? -bang VCSCommit call s:VCSCommit(<q-bang>, <q-args>)
+com! -nargs=* VCSDelete call s:ExecuteVCSCommand('Delete', [<f-args>])
+com! -nargs=* VCSDiff call s:VCSDiff(<f-args>)
+com! -nargs=0 -bang VCSGotoOriginal call s:VCSGotoOriginal(<q-bang>)
+com! -nargs=* VCSInfo call s:ExecuteVCSCommand('Info', [<f-args>])
+com! -nargs=* VCSLock call s:MarkOrigBufferForSetup(s:ExecuteVCSCommand('Lock', [<f-args>]))
+com! -nargs=* VCSLog call s:ExecuteVCSCommand('Log', [<f-args>])
+com! -nargs=* VCSRemove call s:ExecuteVCSCommand('Delete', [<f-args>])
+com! -nargs=0 VCSRevert call s:MarkOrigBufferForSetup(s:ExecuteVCSCommand('Revert', []))
+com! -nargs=? VCSReview call s:VCSReview(<f-args>)
+com! -nargs=* VCSStatus call s:ExecuteVCSCommand('Status', [<f-args>])
+com! -nargs=* VCSUnlock call s:MarkOrigBufferForSetup(s:ExecuteVCSCommand('Unlock', [<f-args>]))
+com! -nargs=0 VCSUpdate call s:MarkOrigBufferForSetup(s:ExecuteVCSCommand('Update', []))
+com! -nargs=* VCSVimDiff call s:VCSVimDiff(<f-args>)
+
+" Section: VCS buffer management commands {{{2
+com! VCSCommandDisableBufferSetup call VCSCommandDisableBufferSetup()
+com! VCSCommandEnableBufferSetup call VCSCommandEnableBufferSetup()
+
+" Allow reloading VCSCommand.vim
+com! VCSReload let savedPlugins = s:plugins|let s:plugins = {}|call s:ClearMenu()|unlet! g:loaded_VCSCommand|runtime plugin/vcscommand.vim|for plugin in values(savedPlugins)|execute 'source' plugin[0]|endfor|unlet savedPlugins
+
+" Section: Plugin command mappings {{{1
+nnoremap <silent> <Plug>VCSAdd :VCSAdd<CR>
+nnoremap <silent> <Plug>VCSAnnotate :VCSAnnotate<CR>
+nnoremap <silent> <Plug>VCSCommit :VCSCommit<CR>
+nnoremap <silent> <Plug>VCSDelete :VCSDelete<CR>
+nnoremap <silent> <Plug>VCSDiff :VCSDiff<CR>
+nnoremap <silent> <Plug>VCSGotoOriginal :VCSGotoOriginal<CR>
+nnoremap <silent> <Plug>VCSClearAndGotoOriginal :VCSGotoOriginal!<CR>
+nnoremap <silent> <Plug>VCSInfo :VCSInfo<CR>
+nnoremap <silent> <Plug>VCSLock :VCSLock<CR>
+nnoremap <silent> <Plug>VCSLog :VCSLog<CR>
+nnoremap <silent> <Plug>VCSRevert :VCSRevert<CR>
+nnoremap <silent> <Plug>VCSReview :VCSReview<CR>
+nnoremap <silent> <Plug>VCSSplitAnnotate :VCSAnnotate!<CR>
+nnoremap <silent> <Plug>VCSStatus :VCSStatus<CR>
+nnoremap <silent> <Plug>VCSUnlock :VCSUnlock<CR>
+nnoremap <silent> <Plug>VCSUpdate :VCSUpdate<CR>
+nnoremap <silent> <Plug>VCSVimDiff :VCSVimDiff<CR>
+
+" Section: Default mappings {{{1
+
+let s:defaultMappings = [
+ \['a', 'VCSAdd'],
+ \['c', 'VCSCommit'],
+ \['D', 'VCSDelete'],
+ \['d', 'VCSDiff'],
+ \['G', 'VCSClearAndGotoOriginal'],
+ \['g', 'VCSGotoOriginal'],
+ \['i', 'VCSInfo'],
+ \['L', 'VCSLock'],
+ \['l', 'VCSLog'],
+ \['N', 'VCSSplitAnnotate'],
+ \['n', 'VCSAnnotate'],
+ \['q', 'VCSRevert'],
+ \['r', 'VCSReview'],
+ \['s', 'VCSStatus'],
+ \['U', 'VCSUnlock'],
+ \['u', 'VCSUpdate'],
+ \['v', 'VCSVimDiff'],
+ \]
+
+if !VCSCommandGetOption('VCSCommandDisableMappings', 0)
+ for [s:shortcut, s:vcsFunction] in VCSCommandGetOption('VCSCommandMappings', s:defaultMappings)
+ call s:CreateMapping(s:shortcut, '<Plug>' . s:vcsFunction, '''' . s:vcsFunction . '''')
+ endfor
+ unlet s:shortcut s:vcsFunction
+endif
+unlet s:defaultMappings
+
+" Section: Menu items {{{1
+
+let s:menuEnabled = !VCSCommandGetOption('VCSCommandDisableMenu', 0)
+let s:menuRoot = VCSCommandGetOption('VCSCommandMenuRoot', '&Plugin.VCS')
+let s:menuPriority = VCSCommandGetOption('VCSCommandMenuPriority', '')
+
+for [s:shortcut, s:command] in [
+ \['&Add', '<Plug>VCSAdd'],
+ \['A&nnotate', '<Plug>VCSAnnotate'],
+ \['&Commit', '<Plug>VCSCommit'],
+ \['Delete', '<Plug>VCSDelete'],
+ \['&Diff', '<Plug>VCSDiff'],
+ \['&Info', '<Plug>VCSInfo'],
+ \['&Log', '<Plug>VCSLog'],
+ \['Revert', '<Plug>VCSRevert'],
+ \['&Review', '<Plug>VCSReview'],
+ \['&Status', '<Plug>VCSStatus'],
+ \['&Update', '<Plug>VCSUpdate'],
+ \['&VimDiff', '<Plug>VCSVimDiff']
+ \]
+ call s:VCSCommandUtility.addMenuItem(s:shortcut, s:command)
+endfor
+unlet s:shortcut s:command
+
+" Section: Autocommands to restore vimdiff state {{{1
+augroup VimDiffRestore
+ au!
+ au BufUnload * call s:VimDiffRestore(str2nr(expand('<abuf>')))
+augroup END
+
+" Section: Optional activation of buffer management {{{1
+
+if VCSCommandGetOption('VCSCommandEnableBufferSetup', 0)
+ call VCSCommandEnableBufferSetup()
+endif
+
+" Section: VIM shutdown hook {{{1
+
+" Close all result buffers when VIM exits, to prevent them from being restored
+" via viminfo.
+
+" Function: s:CloseAllResultBuffers() {{{2
+" Closes all vcscommand result buffers.
+function! s:CloseAllResultBuffers()
+ " This avoids using bufdo as that may load buffers already loaded in another
+ " vim process, resulting in an error.
+ let buffnr = 1
+ let buffmaxnr = bufnr('$')
+ while buffnr <= buffmaxnr
+ if getbufvar(buffnr, 'VCSCommandOriginalBuffer') != ""
+ execute 'bw' buffnr
+ endif
+ let buffnr = buffnr + 1
+ endwhile
+endfunction
+
+augroup VCSCommandVIMShutdown
+ au!
+ au VimLeavePre * call s:CloseAllResultBuffers()
+augroup END
+
+" Section: Plugin completion {{{1
+
+let loaded_VCSCommand = 2
+
+silent do VCSCommand User VCSPluginFinish
+
+let &cpo = s:save_cpo
diff --git a/modules/vim/vim/plugin/vcscvs.vim b/modules/vim/vim/plugin/vcscvs.vim
new file mode 100644
index 0000000..73d6a7f
--- /dev/null
+++ b/modules/vim/vim/plugin/vcscvs.vim
@@ -0,0 +1,449 @@
+" vim600: set foldmethod=marker:
+"
+" CVS extension for VCSCommand.
+"
+" Maintainer: Bob Hiestand <bob.hiestand@gmail.com>
+" License:
+" Copyright (c) Bob Hiestand
+"
+" Permission is hereby granted, free of charge, to any person obtaining a copy
+" of this software and associated documentation files (the "Software"), to
+" deal in the Software without restriction, including without limitation the
+" rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+" sell copies of the Software, and to permit persons to whom the Software is
+" furnished to do so, subject to the following conditions:
+"
+" The above copyright notice and this permission notice shall be included in
+" all copies or substantial portions of the Software.
+"
+" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+" IN THE SOFTWARE.
+"
+" Section: Documentation {{{1
+"
+" Command documentation {{{2
+"
+" The following commands only apply to files under CVS source control.
+"
+" CVSEdit Performs "cvs edit" on the current file.
+"
+" CVSEditors Performs "cvs editors" on the current file.
+"
+" CVSUnedit Performs "cvs unedit" on the current file.
+"
+" CVSWatch Takes an argument which must be one of [on|off|add|remove].
+" Performs "cvs watch" with the given argument on the current
+" file.
+"
+" CVSWatchers Performs "cvs watchers" on the current file.
+"
+" CVSWatchAdd Alias for "CVSWatch add"
+"
+" CVSWatchOn Alias for "CVSWatch on"
+"
+" CVSWatchOff Alias for "CVSWatch off"
+"
+" CVSWatchRemove Alias for "CVSWatch remove"
+"
+" Mapping documentation: {{{2
+"
+" By default, a mapping is defined for each command. User-provided mappings
+" can be used instead by mapping to <Plug>CommandName, for instance:
+"
+" nnoremap ,ce <Plug>CVSEdit
+"
+" The default mappings are as follow:
+"
+" <Leader>ce CVSEdit
+" <Leader>cE CVSEditors
+" <Leader>ct CVSUnedit
+" <Leader>cwv CVSWatchers
+" <Leader>cwa CVSWatchAdd
+" <Leader>cwn CVSWatchOn
+" <Leader>cwf CVSWatchOff
+" <Leader>cwr CVSWatchRemove
+"
+" Options documentation: {{{2
+"
+" VCSCommandCVSExec
+" This variable specifies the CVS executable. If not set, it defaults to
+" 'cvs' executed from the user's executable path.
+"
+" VCSCommandCVSDiffOpt
+" This variable, if set, determines the options passed to the cvs diff
+" command. If not set, it defaults to 'u'.
+
+" Section: Plugin header {{{1
+
+if exists('VCSCommandDisableAll')
+ finish
+endif
+
+if v:version < 700
+ echohl WarningMsg|echomsg 'VCSCommand requires at least VIM 7.0'|echohl None
+ finish
+endif
+
+runtime plugin/vcscommand.vim
+
+if !executable(VCSCommandGetOption('VCSCommandCVSExec', 'cvs'))
+ " CVS is not installed
+ finish
+endif
+
+let s:save_cpo=&cpo
+set cpo&vim
+
+" Section: Variable initialization {{{1
+
+let s:cvsFunctions = {}
+
+" Section: Utility functions {{{1
+
+" Function: s:Executable() {{{2
+" Returns the executable used to invoke cvs suitable for use in a shell
+" command.
+function! s:Executable()
+ return shellescape(VCSCommandGetOption('VCSCommandCVSExec', 'cvs'))
+endfunction
+
+" Function: s:DoCommand(cmd, cmdName, statusText, options) {{{2
+" Wrapper to VCSCommandDoCommand to add the name of the CVS executable to the
+" command argument.
+function! s:DoCommand(cmd, cmdName, statusText, options)
+ if VCSCommandGetVCSType(expand('%')) == 'CVS'
+ let fullCmd = s:Executable() . ' ' . a:cmd
+ let ret = VCSCommandDoCommand(fullCmd, a:cmdName, a:statusText, a:options)
+
+ if ret > 0
+ if getline(line('$')) =~ '^cvs \w\+: closing down connection'
+ $d
+ 1
+ endif
+
+ endif
+
+ return ret
+ else
+ throw 'CVS VCSCommand plugin called on non-CVS item.'
+ endif
+endfunction
+
+" Function: s:GetRevision() {{{2
+" Function for retrieving the current buffer's revision number.
+" Returns: Revision number or an empty string if an error occurs.
+
+function! s:GetRevision()
+ if !exists('b:VCSCommandBufferInfo')
+ let b:VCSCommandBufferInfo = s:cvsFunctions.GetBufferInfo()
+ endif
+
+ if len(b:VCSCommandBufferInfo) > 0
+ return b:VCSCommandBufferInfo[0]
+ else
+ return ''
+ endif
+endfunction
+
+" Section: VCS function implementations {{{1
+
+" Function: s:cvsFunctions.Identify(buffer) {{{2
+function! s:cvsFunctions.Identify(buffer)
+ let fileName = resolve(bufname(a:buffer))
+ if isdirectory(fileName)
+ let directoryName = fileName
+ else
+ let directoryName = fnamemodify(fileName, ':h')
+ endif
+ if strlen(directoryName) > 0
+ let CVSRoot = directoryName . '/CVS/Root'
+ else
+ let CVSRoot = 'CVS/Root'
+ endif
+ if filereadable(CVSRoot)
+ return 1
+ else
+ return 0
+ endif
+endfunction
+
+" Function: s:cvsFunctions.Add(argList) {{{2
+function! s:cvsFunctions.Add(argList)
+ return s:DoCommand(join(['add'] + a:argList, ' '), 'add', join(a:argList, ' '), {})
+endfunction
+
+" Function: s:cvsFunctions.Annotate(argList) {{{2
+function! s:cvsFunctions.Annotate(argList)
+ if len(a:argList) == 0
+ if &filetype == 'CVSannotate'
+ " This is a CVSAnnotate buffer. Perform annotation of the version
+ " indicated by the current line.
+ let caption = matchstr(getline('.'),'\v^[0-9.]+')
+
+ if VCSCommandGetOption('VCSCommandCVSAnnotateParent', 0) != 0
+ if caption != '1.1'
+ let revmaj = matchstr(caption,'\v[0-9.]+\ze\.[0-9]+')
+ let revmin = matchstr(caption,'\v[0-9.]+\.\zs[0-9]+') - 1
+ if revmin == 0
+ " Jump to ancestor branch
+ let caption = matchstr(revmaj,'\v[0-9.]+\ze\.[0-9]+')
+ else
+ let caption = revmaj . "." . revmin
+ endif
+ endif
+ endif
+
+ let options = ['-r' . caption]
+ else
+ " CVS defaults to pulling HEAD, regardless of current branch.
+ " Therefore, always pass desired revision.
+ let caption = ''
+ let options = ['-r' . s:GetRevision()]
+ endif
+ elseif len(a:argList) == 1 && a:argList[0] !~ '^-'
+ let caption = a:argList[0]
+ let options = ['-r' . caption]
+ else
+ let caption = join(a:argList)
+ let options = a:argList
+ endif
+
+ let resultBuffer = s:DoCommand(join(['-q', 'annotate'] + options), 'annotate', caption, {})
+ if resultBuffer > 0
+ " Remove header lines from standard error
+ silent v/^\d\+\%(\.\d\+\)\+/d
+ endif
+ return resultBuffer
+endfunction
+
+" Function: s:cvsFunctions.Commit(argList) {{{2
+function! s:cvsFunctions.Commit(argList)
+ let resultBuffer = s:DoCommand('commit -F "' . a:argList[0] . '"', 'commit', '', {})
+ if resultBuffer == 0
+ echomsg 'No commit needed.'
+ endif
+ return resultBuffer
+endfunction
+
+" Function: s:cvsFunctions.Delete() {{{2
+" By default, use the -f option to remove the file first. If options are
+" passed in, use those instead.
+function! s:cvsFunctions.Delete(argList)
+ let options = ['-f']
+ let caption = ''
+ if len(a:argList) > 0
+ let options = a:argList
+ let caption = join(a:argList, ' ')
+ endif
+ return s:DoCommand(join(['remove'] + options, ' '), 'delete', caption, {})
+endfunction
+
+" Function: s:cvsFunctions.Diff(argList) {{{2
+function! s:cvsFunctions.Diff(argList)
+ if len(a:argList) == 0
+ let revOptions = []
+ let caption = ''
+ elseif len(a:argList) <= 2 && match(a:argList, '^-') == -1
+ let revOptions = ['-r' . join(a:argList, ' -r')]
+ let caption = '(' . a:argList[0] . ' : ' . get(a:argList, 1, 'current') . ')'
+ else
+ " Pass-through
+ let caption = join(a:argList, ' ')
+ let revOptions = a:argList
+ endif
+
+ let cvsDiffOpt = VCSCommandGetOption('VCSCommandCVSDiffOpt', 'u')
+ if cvsDiffOpt == ''
+ let diffOptions = []
+ else
+ let diffOptions = ['-' . cvsDiffOpt]
+ endif
+
+ return s:DoCommand(join(['diff'] + diffOptions + revOptions), 'diff', caption, {'allowNonZeroExit': 1})
+endfunction
+
+" Function: s:cvsFunctions.GetBufferInfo() {{{2
+" Provides version control details for the current file. Current version
+" number and current repository version number are required to be returned by
+" the vcscommand plugin. This CVS extension adds branch name to the return
+" list as well.
+" Returns: List of results: [revision, repository, branch]
+
+function! s:cvsFunctions.GetBufferInfo()
+ let originalBuffer = VCSCommandGetOriginalBuffer(bufnr('%'))
+ let fileName = bufname(originalBuffer)
+ if isdirectory(fileName)
+ let tag = ''
+ if filereadable(fileName . '/CVS/Tag')
+ let tagFile = readfile(fileName . '/CVS/Tag')
+ if len(tagFile) == 1
+ let tag = substitute(tagFile[0], '^T', '', '')
+ endif
+ endif
+ return [tag]
+ endif
+ let realFileName = fnamemodify(resolve(fileName), ':t')
+ if !filereadable(fileName)
+ return ['Unknown']
+ endif
+ let oldCwd = VCSCommandChangeToCurrentFileDir(fileName)
+ try
+ let statusText=s:VCSCommandUtility.system(s:Executable() . ' status -- "' . realFileName . '"')
+ if(v:shell_error)
+ return []
+ endif
+ let revision=substitute(statusText, '^\_.*Working revision:\s*\(\d\+\%(\.\d\+\)\+\|New file!\)\_.*$', '\1', '')
+
+ " We can still be in a CVS-controlled directory without this being a CVS
+ " file
+ if match(revision, '^New file!$') >= 0
+ let revision='New'
+ elseif match(revision, '^\d\+\.\d\+\%(\.\d\+\.\d\+\)*$') <0
+ return ['Unknown']
+ endif
+
+ let branch=substitute(statusText, '^\_.*Sticky Tag:\s\+\(\d\+\%(\.\d\+\)\+\|\a[A-Za-z0-9-_]*\|(none)\).*$', '\1', '')
+ let repository=substitute(statusText, '^\_.*Repository revision:\s*\(\d\+\%(\.\d\+\)\+\|New file!\|No revision control file\)\_.*$', '\1', '')
+ let repository=substitute(repository, '^New file!\|No revision control file$', 'New', '')
+ return [revision, repository, branch]
+ finally
+ call VCSCommandChdir(oldCwd)
+ endtry
+endfunction
+
+" Function: s:cvsFunctions.Log() {{{2
+function! s:cvsFunctions.Log(argList)
+ if len(a:argList) == 0
+ let options = []
+ let caption = ''
+ elseif len(a:argList) <= 2 && match(a:argList, '^-') == -1
+ let options = ['-r' . join(a:argList, ':')]
+ let caption = options[0]
+ else
+ " Pass-through
+ let options = a:argList
+ let caption = join(a:argList, ' ')
+ endif
+
+ return s:DoCommand(join(['log'] + options), 'log', caption, {})
+endfunction
+
+" Function: s:cvsFunctions.Revert(argList) {{{2
+function! s:cvsFunctions.Revert(argList)
+ return s:DoCommand('update -C', 'revert', '', {})
+endfunction
+
+" Function: s:cvsFunctions.Review(argList) {{{2
+function! s:cvsFunctions.Review(argList)
+ if len(a:argList) == 0
+ let versiontag = '(current)'
+ let versionOption = ''
+ else
+ let versiontag = a:argList[0]
+ let versionOption = ' -r ' . versiontag . ' '
+ endif
+
+ return s:DoCommand('-q update -p' . versionOption, 'review', versiontag, {})
+endfunction
+
+" Function: s:cvsFunctions.Status(argList) {{{2
+function! s:cvsFunctions.Status(argList)
+ return s:DoCommand(join(['status'] + a:argList, ' '), 'status', join(a:argList, ' '), {})
+endfunction
+
+" Function: s:cvsFunctions.Update(argList) {{{2
+function! s:cvsFunctions.Update(argList)
+ return s:DoCommand('update', 'update', '', {})
+endfunction
+
+" Section: CVS-specific functions {{{1
+
+" Function: s:CVSEdit() {{{2
+function! s:CVSEdit()
+ return s:DoCommand('edit', 'cvsedit', '', {})
+endfunction
+
+" Function: s:CVSEditors() {{{2
+function! s:CVSEditors()
+ return s:DoCommand('editors', 'cvseditors', '', {})
+endfunction
+
+" Function: s:CVSUnedit() {{{2
+function! s:CVSUnedit()
+ return s:DoCommand('unedit', 'cvsunedit', '', {})
+endfunction
+
+" Function: s:CVSWatch(onoff) {{{2
+function! s:CVSWatch(onoff)
+ if a:onoff !~ '^\c\%(on\|off\|add\|remove\)$'
+ echoerr 'Argument to CVSWatch must be one of [on|off|add|remove]'
+ return -1
+ end
+ return s:DoCommand('watch ' . tolower(a:onoff), 'cvswatch', '', {})
+endfunction
+
+" Function: s:CVSWatchers() {{{2
+function! s:CVSWatchers()
+ return s:DoCommand('watchers', 'cvswatchers', '', {})
+endfunction
+
+" Annotate setting {{{2
+let s:cvsFunctions.AnnotateSplitRegex = '): '
+
+" Section: Command definitions {{{1
+" Section: Primary commands {{{2
+com! CVSEdit call s:CVSEdit()
+com! CVSEditors call s:CVSEditors()
+com! CVSUnedit call s:CVSUnedit()
+com! -nargs=1 CVSWatch call s:CVSWatch(<f-args>)
+com! CVSWatchAdd call s:CVSWatch('add')
+com! CVSWatchOn call s:CVSWatch('on')
+com! CVSWatchOff call s:CVSWatch('off')
+com! CVSWatchRemove call s:CVSWatch('remove')
+com! CVSWatchers call s:CVSWatchers()
+
+" Section: Plugin command mappings {{{1
+
+let s:cvsExtensionMappings = {}
+let mappingInfo = [
+ \['CVSEdit', 'CVSEdit', 'e'],
+ \['CVSEditors', 'CVSEditors', 'E'],
+ \['CVSUnedit', 'CVSUnedit', 't'],
+ \['CVSWatchers', 'CVSWatchers', 'wv'],
+ \['CVSWatchAdd', 'CVSWatch add', 'wa'],
+ \['CVSWatchOff', 'CVSWatch off', 'wf'],
+ \['CVSWatchOn', 'CVSWatch on', 'wn'],
+ \['CVSWatchRemove', 'CVSWatch remove', 'wr']
+ \]
+
+for [pluginName, commandText, shortCut] in mappingInfo
+ execute 'nnoremap <silent> <Plug>' . pluginName . ' :' . commandText . '<CR>'
+ if !hasmapto('<Plug>' . pluginName)
+ let s:cvsExtensionMappings[shortCut] = commandText
+ endif
+endfor
+
+" Section: Plugin Registration {{{1
+let s:VCSCommandUtility = VCSCommandRegisterModule('CVS', expand('<sfile>'), s:cvsFunctions, s:cvsExtensionMappings)
+
+" Section: Menu items {{{1
+for [s:shortcut, s:command] in [
+ \['CVS.&Edit', '<Plug>CVSEdit'],
+ \['CVS.Ed&itors', '<Plug>CVSEditors'],
+ \['CVS.Unedi&t', '<Plug>CVSUnedit'],
+ \['CVS.&Watchers', '<Plug>CVSWatchers'],
+ \['CVS.WatchAdd', '<Plug>CVSWatchAdd'],
+ \['CVS.WatchOn', '<Plug>CVSWatchOn'],
+ \['CVS.WatchOff', '<Plug>CVSWatchOff'],
+ \['CVS.WatchRemove', '<Plug>CVSWatchRemove']
+ \]
+ call s:VCSCommandUtility.addMenuItem(s:shortcut, s:command)
+endfor
+unlet s:shortcut s:command
+
+let &cpo = s:save_cpo
diff --git a/modules/vim/vim/plugin/vcsgit.vim b/modules/vim/vim/plugin/vcsgit.vim
new file mode 100644
index 0000000..4e299d9
--- /dev/null
+++ b/modules/vim/vim/plugin/vcsgit.vim
@@ -0,0 +1,247 @@
+" vim600: set foldmethod=marker:
+"
+" git extension for VCSCommand.
+"
+" Maintainer: Bob Hiestand <bob.hiestand@gmail.com>
+" License:
+" Copyright (c) Bob Hiestand
+"
+" Permission is hereby granted, free of charge, to any person obtaining a copy
+" of this software and associated documentation files (the "Software"), to
+" deal in the Software without restriction, including without limitation the
+" rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+" sell copies of the Software, and to permit persons to whom the Software is
+" furnished to do so, subject to the following conditions:
+"
+" The above copyright notice and this permission notice shall be included in
+" all copies or substantial portions of the Software.
+"
+" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+" IN THE SOFTWARE.
+"
+" Section: Documentation {{{1
+"
+" Options documentation: {{{2
+"
+" VCSCommandGitExec
+" This variable specifies the git executable. If not set, it defaults to
+" 'git' executed from the user's executable path.
+"
+" VCSCommandGitDiffOpt
+" This variable, if set, determines the default options passed to the
+" VCSDiff command. If any options (starting with '-') are passed to the
+" command, this variable is not used.
+
+" Section: Plugin header {{{1
+
+if exists('VCSCommandDisableAll')
+ finish
+endif
+
+if v:version < 700
+ echohl WarningMsg|echomsg 'VCSCommand requires at least VIM 7.0'|echohl None
+ finish
+endif
+
+runtime plugin/vcscommand.vim
+
+if !executable(VCSCommandGetOption('VCSCommandGitExec', 'git'))
+ " git is not installed
+ finish
+endif
+
+let s:save_cpo=&cpo
+set cpo&vim
+
+" Section: Variable initialization {{{1
+
+let s:gitFunctions = {}
+
+" Section: Utility functions {{{1
+
+" Function: s:Executable() {{{2
+" Returns the executable used to invoke git suitable for use in a shell
+" command.
+function! s:Executable()
+ return shellescape(VCSCommandGetOption('VCSCommandGitExec', 'git'))
+endfunction
+
+" Function: s:DoCommand(cmd, cmdName, statusText, options) {{{2
+" Wrapper to VCSCommandDoCommand to add the name of the git executable to the
+" command argument.
+function! s:DoCommand(cmd, cmdName, statusText, options)
+ if VCSCommandGetVCSType(expand('%')) == 'git'
+ let fullCmd = s:Executable() . ' ' . a:cmd
+ return VCSCommandDoCommand(fullCmd, a:cmdName, a:statusText, a:options)
+ else
+ throw 'git VCSCommand plugin called on non-git item.'
+ endif
+endfunction
+
+" Section: VCS function implementations {{{1
+
+" Function: s:gitFunctions.Identify(buffer) {{{2
+" This function only returns an inexact match due to the detection method used
+" by git, which simply traverses the directory structure upward.
+function! s:gitFunctions.Identify(buffer)
+ let oldCwd = VCSCommandChangeToCurrentFileDir(resolve(bufname(a:buffer)))
+ try
+ call s:VCSCommandUtility.system(s:Executable() . ' rev-parse --is-inside-work-tree')
+ if(v:shell_error)
+ return 0
+ else
+ return g:VCSCOMMAND_IDENTIFY_INEXACT
+ endif
+ finally
+ call VCSCommandChdir(oldCwd)
+ endtry
+endfunction
+
+" Function: s:gitFunctions.Add(argList) {{{2
+function! s:gitFunctions.Add(argList)
+ return s:DoCommand(join(['add'] + ['-v'] + a:argList, ' '), 'add', join(a:argList, ' '), {})
+endfunction
+
+" Function: s:gitFunctions.Annotate(argList) {{{2
+function! s:gitFunctions.Annotate(argList)
+ if len(a:argList) == 0
+ if &filetype == 'gitannotate'
+ " Perform annotation of the version indicated by the current line.
+ let options = matchstr(getline('.'),'^\x\+')
+ else
+ let options = ''
+ endif
+ elseif len(a:argList) == 1 && a:argList[0] !~ '^-'
+ let options = a:argList[0]
+ else
+ let options = join(a:argList, ' ')
+ endif
+
+ return s:DoCommand('blame ' . options, 'annotate', options, {})
+endfunction
+
+" Function: s:gitFunctions.Commit(argList) {{{2
+function! s:gitFunctions.Commit(argList)
+ try
+ return s:DoCommand('commit -F "' . a:argList[0] . '"', 'commit', '', {})
+ catch /\m^Version control command failed.*nothing\%( added\)\? to commit/
+ echomsg 'No commit needed.'
+ endtry
+endfunction
+
+" Function: s:gitFunctions.Delete() {{{2
+" All options are passed through.
+function! s:gitFunctions.Delete(argList)
+ let options = a:argList
+ let caption = join(a:argList, ' ')
+ return s:DoCommand(join(['rm'] + options, ' '), 'delete', caption, {})
+endfunction
+
+" Function: s:gitFunctions.Diff(argList) {{{2
+" Pass-through call to git-diff. If no options (starting with '-') are found,
+" then the options in the 'VCSCommandGitDiffOpt' variable are added.
+function! s:gitFunctions.Diff(argList)
+ let gitDiffOpt = VCSCommandGetOption('VCSCommandGitDiffOpt', '')
+ if gitDiffOpt == ''
+ let diffOptions = []
+ else
+ let diffOptions = [gitDiffOpt]
+ for arg in a:argList
+ if arg =~ '^-'
+ let diffOptions = []
+ break
+ endif
+ endfor
+ endif
+
+ return s:DoCommand(join(['diff'] + diffOptions + a:argList), 'diff', join(a:argList), {})
+endfunction
+
+" Function: s:gitFunctions.GetBufferInfo() {{{2
+" Provides version control details for the current file. Current version
+" number and current repository version number are required to be returned by
+" the vcscommand plugin. This CVS extension adds branch name to the return
+" list as well.
+" Returns: List of results: [revision, repository, branch]
+
+function! s:gitFunctions.GetBufferInfo()
+ let oldCwd = VCSCommandChangeToCurrentFileDir(resolve(bufname('%')))
+ try
+ let branch = substitute(s:VCSCommandUtility.system(s:Executable() . ' symbolic-ref -q HEAD'), '\n$', '', '')
+ if v:shell_error
+ let branch = 'DETACHED'
+ else
+ let branch = substitute(branch, '^refs/heads/', '', '')
+ endif
+
+ let info = [branch]
+
+ for method in split(VCSCommandGetOption('VCSCommandGitDescribeArgList', (',tags,all,always')), ',', 1)
+ if method != ''
+ let method = ' --' . method
+ endif
+ let tag = substitute(s:VCSCommandUtility.system(s:Executable() . ' describe' . method), '\n$', '', '')
+ if !v:shell_error
+ call add(info, tag)
+ break
+ endif
+ endfor
+
+ return info
+ finally
+ call VCSCommandChdir(oldCwd)
+ endtry
+endfunction
+
+" Function: s:gitFunctions.Log() {{{2
+function! s:gitFunctions.Log(argList)
+ return s:DoCommand(join(['log'] + a:argList), 'log', join(a:argList, ' '), {})
+endfunction
+
+" Function: s:gitFunctions.Revert(argList) {{{2
+function! s:gitFunctions.Revert(argList)
+ return s:DoCommand('checkout', 'revert', '', {})
+endfunction
+
+" Function: s:gitFunctions.Review(argList) {{{2
+function! s:gitFunctions.Review(argList)
+ if len(a:argList) == 0
+ let revision = 'HEAD'
+ else
+ let revision = a:argList[0]
+ endif
+
+ let oldCwd = VCSCommandChangeToCurrentFileDir(resolve(bufname(VCSCommandGetOriginalBuffer('%'))))
+ try
+ let prefix = s:VCSCommandUtility.system(s:Executable() . ' rev-parse --show-prefix')
+ finally
+ call VCSCommandChdir(oldCwd)
+ endtry
+
+ let prefix = substitute(prefix, '\n$', '', '')
+ let blob = '"' . revision . ':' . prefix . '<VCSCOMMANDFILE>"'
+ return s:DoCommand('show ' . blob, 'review', revision, {})
+endfunction
+
+" Function: s:gitFunctions.Status(argList) {{{2
+function! s:gitFunctions.Status(argList)
+ return s:DoCommand(join(['status'] + a:argList), 'status', join(a:argList), {'allowNonZeroExit': 1})
+endfunction
+
+" Function: s:gitFunctions.Update(argList) {{{2
+function! s:gitFunctions.Update(argList)
+ throw "This command is not implemented for git because file-by-file update doesn't make much sense in that context. If you have an idea for what it should do, please let me know."
+endfunction
+
+" Annotate setting {{{2
+let s:gitFunctions.AnnotateSplitRegex = ') '
+
+" Section: Plugin Registration {{{1
+let s:VCSCommandUtility = VCSCommandRegisterModule('git', expand('<sfile>'), s:gitFunctions, [])
+
+let &cpo = s:save_cpo
diff --git a/modules/vim/vim/plugin/vcshg.vim b/modules/vim/vim/plugin/vcshg.vim
new file mode 100644
index 0000000..2c616c0
--- /dev/null
+++ b/modules/vim/vim/plugin/vcshg.vim
@@ -0,0 +1,273 @@
+" vim600: set foldmethod=marker:
+"
+" Mercurial extension for VCSCommand.
+"
+" Maintainer: Bob Hiestand <bob.hiestand@gmail.com>
+" License:
+" Copyright (c) Bob Hiestand
+"
+" Permission is hereby granted, free of charge, to any person obtaining a copy
+" of this software and associated documentation files (the "Software"), to
+" deal in the Software without restriction, including without limitation the
+" rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+" sell copies of the Software, and to permit persons to whom the Software is
+" furnished to do so, subject to the following conditions:
+"
+" The above copyright notice and this permission notice shall be included in
+" all copies or substantial portions of the Software.
+"
+" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+" IN THE SOFTWARE.
+"
+" Section: Documentation {{{1
+"
+" Options documentation: {{{2
+"
+" VCSCommandHGExec
+" This variable specifies the mercurial executable. If not set, it defaults
+" to 'hg' executed from the user's executable path.
+"
+" VCSCommandHGDiffExt
+" This variable, if set, sets the external diff program used by Subversion.
+"
+" VCSCommandHGDiffOpt
+" This variable, if set, determines the options passed to the hg diff
+" command (such as 'u', 'w', or 'b').
+
+" Section: Plugin header {{{1
+
+if exists('VCSCommandDisableAll')
+ finish
+endif
+
+if v:version < 700
+ echohl WarningMsg|echomsg 'VCSCommand requires at least VIM 7.0'|echohl None
+ finish
+endif
+
+runtime plugin/vcscommand.vim
+
+if !executable(VCSCommandGetOption('VCSCommandHGExec', 'hg'))
+ " HG is not installed
+ finish
+endif
+
+let s:save_cpo=&cpo
+set cpo&vim
+
+" Section: Variable initialization {{{1
+
+let s:hgFunctions = {}
+
+" Section: Utility functions {{{1
+
+" Function: s:Executable() {{{2
+" Returns the executable used to invoke hg suitable for use in a shell
+" command.
+function! s:Executable()
+ return shellescape(VCSCommandGetOption('VCSCommandHGExec', 'hg'))
+endfunction
+
+" Function: s:DoCommand(cmd, cmdName, statusText, options) {{{2
+" Wrapper to VCSCommandDoCommand to add the name of the HG executable to the
+" command argument.
+function! s:DoCommand(cmd, cmdName, statusText, options)
+ if VCSCommandGetVCSType(expand('%')) == 'HG'
+ let fullCmd = s:Executable() . ' ' . a:cmd
+ return VCSCommandDoCommand(fullCmd, a:cmdName, a:statusText, a:options)
+ else
+ throw 'HG VCSCommand plugin called on non-HG item.'
+ endif
+endfunction
+
+" Section: VCS function implementations {{{1
+
+" Function: s:hgFunctions.Identify(buffer) {{{2
+function! s:hgFunctions.Identify(buffer)
+ let oldCwd = VCSCommandChangeToCurrentFileDir(resolve(bufname(a:buffer)))
+ try
+ call s:VCSCommandUtility.system(s:Executable() . ' root')
+ if(v:shell_error)
+ return 0
+ else
+ return g:VCSCOMMAND_IDENTIFY_INEXACT
+ endif
+ finally
+ call VCSCommandChdir(oldCwd)
+ endtry
+endfunction
+
+" Function: s:hgFunctions.Add() {{{2
+function! s:hgFunctions.Add(argList)
+ return s:DoCommand(join(['add -v'] + a:argList, ' '), 'add', join(a:argList, ' '), {})
+endfunction
+
+" Function: s:hgFunctions.Annotate(argList) {{{2
+function! s:hgFunctions.Annotate(argList)
+ if len(a:argList) == 0
+ if &filetype == 'HGannotate'
+ " Perform annotation of the version indicated by the current line.
+ let caption = matchstr(getline('.'),'\v^\s+\zs\d+')
+ let options = ' -r' . caption
+ else
+ let caption = ''
+ let options = ' -un'
+ endif
+ elseif len(a:argList) == 1 && a:argList[0] !~ '^-'
+ let caption = a:argList[0]
+ let options = ' -un -r' . caption
+ else
+ let caption = join(a:argList, ' ')
+ let options = ' ' . caption
+ endif
+
+ return s:DoCommand('blame' . options, 'annotate', caption, {})
+endfunction
+
+" Function: s:hgFunctions.Commit(argList) {{{2
+function! s:hgFunctions.Commit(argList)
+ try
+ return s:DoCommand('commit -v -l "' . a:argList[0] . '"', 'commit', '', {})
+ catch /Version control command failed.*nothing changed/
+ echomsg 'No commit needed.'
+ endtry
+endfunction
+
+" Function: s:hgFunctions.Delete() {{{2
+function! s:hgFunctions.Delete(argList)
+ return s:DoCommand(join(['remove'] + a:argList, ' '), 'remove', join(a:argList, ' '), {})
+endfunction
+
+" Function: s:hgFunctions.Diff(argList) {{{2
+function! s:hgFunctions.Diff(argList)
+ if len(a:argList) == 0
+ let revOptions = []
+ let caption = ''
+ elseif len(a:argList) <= 2 && match(a:argList, '^-') == -1
+ let revOptions = ['-r' . join(a:argList, ':')]
+ let caption = '(' . a:argList[0] . ' : ' . get(a:argList, 1, 'current') . ')'
+ else
+ " Pass-through
+ let caption = join(a:argList, ' ')
+ let revOptions = a:argList
+ endif
+
+ let hgDiffExt = VCSCommandGetOption('VCSCommandHGDiffExt', '')
+ if hgDiffExt == ''
+ let diffExt = []
+ else
+ let diffExt = ['--diff-cmd ' . hgDiffExt]
+ endif
+
+ let hgDiffOpt = VCSCommandGetOption('VCSCommandHGDiffOpt', '')
+ if hgDiffOpt == ''
+ let diffOptions = []
+ else
+ let diffOptions = ['-x -' . hgDiffOpt]
+ endif
+
+ return s:DoCommand(join(['diff'] + diffExt + diffOptions + revOptions), 'diff', caption, {})
+endfunction
+
+" Function: s:hgFunctions.Info(argList) {{{2
+function! s:hgFunctions.Info(argList)
+ return s:DoCommand(join(['log --limit 1'] + a:argList, ' '), 'log', join(a:argList, ' '), {})
+endfunction
+
+" Function: s:hgFunctions.GetBufferInfo() {{{2
+" Provides version control details for the current file. Current version
+" number and current repository version number are required to be returned by
+" the vcscommand plugin.
+" Returns: List of results: [revision, repository, branch]
+
+function! s:hgFunctions.GetBufferInfo()
+ let originalBuffer = VCSCommandGetOriginalBuffer(bufnr('%'))
+ let fileName = bufname(originalBuffer)
+ let statusText = s:VCSCommandUtility.system(s:Executable() . ' status -- "' . fileName . '"')
+ if(v:shell_error)
+ return []
+ endif
+
+ " File not under HG control.
+ if statusText =~ '^?'
+ return ['Unknown']
+ endif
+
+ let parentsText = s:VCSCommandUtility.system(s:Executable() . ' parents -- "' . fileName . '"')
+ let revision = matchlist(parentsText, '^changeset:\s\+\(\S\+\)\n')[1]
+
+ let logText = s:VCSCommandUtility.system(s:Executable() . ' log -- "' . fileName . '"')
+ let repository = matchlist(logText, '^changeset:\s\+\(\S\+\)\n')[1]
+
+ if revision == ''
+ " Error
+ return ['Unknown']
+ elseif statusText =~ '^A'
+ return ['New', 'New']
+ else
+ return [revision, repository]
+ endif
+endfunction
+
+" Function: s:hgFunctions.Log(argList) {{{2
+function! s:hgFunctions.Log(argList)
+ if len(a:argList) == 0
+ let options = []
+ let caption = ''
+ elseif len(a:argList) <= 2 && match(a:argList, '^-') == -1
+ let options = ['-r' . join(a:argList, ':')]
+ let caption = options[0]
+ else
+ " Pass-through
+ let options = a:argList
+ let caption = join(a:argList, ' ')
+ endif
+
+ let resultBuffer = s:DoCommand(join(['log', '-v'] + options), 'log', caption, {})
+ return resultBuffer
+endfunction
+
+" Function: s:hgFunctions.Revert(argList) {{{2
+function! s:hgFunctions.Revert(argList)
+ return s:DoCommand('revert', 'revert', '', {})
+endfunction
+
+" Function: s:hgFunctions.Review(argList) {{{2
+function! s:hgFunctions.Review(argList)
+ if len(a:argList) == 0
+ let versiontag = '(current)'
+ let versionOption = ''
+ else
+ let versiontag = a:argList[0]
+ let versionOption = ' -r ' . versiontag . ' '
+ endif
+
+ return s:DoCommand('cat' . versionOption, 'review', versiontag, {})
+endfunction
+
+" Function: s:hgFunctions.Status(argList) {{{2
+function! s:hgFunctions.Status(argList)
+ let options = ['-A', '-v']
+ if len(a:argList) != 0
+ let options = a:argList
+ endif
+ return s:DoCommand(join(['status'] + options, ' '), 'status', join(options, ' '), {})
+endfunction
+
+" Function: s:hgFunctions.Update(argList) {{{2
+function! s:hgFunctions.Update(argList)
+ return s:DoCommand('update', 'update', '', {})
+endfunction
+
+" Annotate setting {{{2
+let s:hgFunctions.AnnotateSplitRegex = '\d\+: '
+
+" Section: Plugin Registration {{{1
+let s:VCSCommandUtility = VCSCommandRegisterModule('HG', expand('<sfile>'), s:hgFunctions, [])
+
+let &cpo = s:save_cpo
diff --git a/modules/vim/vim/plugin/vcssvk.vim b/modules/vim/vim/plugin/vcssvk.vim
new file mode 100644
index 0000000..b7cc6c9
--- /dev/null
+++ b/modules/vim/vim/plugin/vcssvk.vim
@@ -0,0 +1,257 @@
+" vim600: set foldmethod=marker:
+"
+" SVK extension for VCSCommand.
+"
+" Maintainer: Bob Hiestand <bob.hiestand@gmail.com>
+" License:
+" Copyright (c) Bob Hiestand
+"
+" Permission is hereby granted, free of charge, to any person obtaining a copy
+" of this software and associated documentation files (the "Software"), to
+" deal in the Software without restriction, including without limitation the
+" rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+" sell copies of the Software, and to permit persons to whom the Software is
+" furnished to do so, subject to the following conditions:
+"
+" The above copyright notice and this permission notice shall be included in
+" all copies or substantial portions of the Software.
+"
+" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+" IN THE SOFTWARE.
+"
+" Section: Documentation {{{1
+"
+" Options documentation: {{{2
+"
+" VCSCommandSVKExec
+" This variable specifies the SVK executable. If not set, it defaults to
+" 'svk' executed from the user's executable path.
+
+" Section: Plugin header {{{1
+
+if exists('VCSCommandDisableAll')
+ finish
+endif
+
+if v:version < 700
+ echohl WarningMsg|echomsg 'VCSCommand requires at least VIM 7.0'|echohl None
+ finish
+endif
+
+runtime plugin/vcscommand.vim
+
+if !executable(VCSCommandGetOption('VCSCommandSVKExec', 'svk'))
+ " SVK is not installed
+ finish
+endif
+
+let s:save_cpo=&cpo
+set cpo&vim
+
+" Section: Variable initialization {{{1
+
+let s:svkFunctions = {}
+
+" Section: Utility functions {{{1
+
+" Function: s:Executable() {{{2
+" Returns the executable used to invoke SVK suitable for use in a shell
+" command.
+function! s:Executable()
+ return shellescape(VCSCommandGetOption('VCSCommandSVKExec', 'svk'))
+endfunction
+
+" Function: s:DoCommand(cmd, cmdName, statusText, options) {{{2
+" Wrapper to VCSCommandDoCommand to add the name of the SVK executable to the
+" command argument.
+function! s:DoCommand(cmd, cmdName, statusText, options)
+ if VCSCommandGetVCSType(expand('%')) == 'SVK'
+ let fullCmd = s:Executable() . ' ' . a:cmd
+ return VCSCommandDoCommand(fullCmd, a:cmdName, a:statusText, a:options)
+ else
+ throw 'SVK VCSCommand plugin called on non-SVK item.'
+ endif
+endfunction
+
+" Section: VCS function implementations {{{1
+
+" Function: s:svkFunctions.Identify(buffer) {{{2
+function! s:svkFunctions.Identify(buffer)
+ let fileName = resolve(bufname(a:buffer))
+ if isdirectory(fileName)
+ let directoryName = fileName
+ else
+ let directoryName = fnamemodify(fileName, ':p:h')
+ endif
+ let statusText = s:VCSCommandUtility.system(s:Executable() . ' info -- "' . directoryName . '"', "no")
+ if(v:shell_error)
+ return 0
+ else
+ return 1
+ endif
+endfunction
+
+" Function: s:svkFunctions.Add() {{{2
+function! s:svkFunctions.Add(argList)
+ return s:DoCommand(join(['add'] + a:argList, ' '), 'add', join(a:argList, ' '), {})
+endfunction
+
+" Function: s:svkFunctions.Annotate(argList) {{{2
+function! s:svkFunctions.Annotate(argList)
+ if len(a:argList) == 0
+ if &filetype == 'SVKannotate'
+ " Perform annotation of the version indicated by the current line.
+ let caption = matchstr(getline('.'),'\v^\s+\zs\d+')
+ let options = ' -r' . caption
+ else
+ let caption = ''
+ let options = ''
+ endif
+ elseif len(a:argList) == 1 && a:argList[0] !~ '^-'
+ let caption = a:argList[0]
+ let options = ' -r' . caption
+ else
+ let caption = join(a:argList, ' ')
+ let options = ' ' . caption
+ endif
+
+ let resultBuffer = s:DoCommand('blame' . options, 'annotate', caption, {})
+ if resultBuffer > 0
+ normal 1G2dd
+ endif
+ return resultBuffer
+endfunction
+
+" Function: s:svkFunctions.Commit(argList) {{{2
+function! s:svkFunctions.Commit(argList)
+ let resultBuffer = s:DoCommand('commit -F "' . a:argList[0] . '"', 'commit', '', {})
+ if resultBuffer == 0
+ echomsg 'No commit needed.'
+ endif
+endfunction
+
+" Function: s:svkFunctions.Delete() {{{2
+function! s:svkFunctions.Delete(argList)
+ return s:DoCommand(join(['delete'] + a:argList, ' '), 'delete', join(a:argList, ' '), {})
+endfunction
+
+" Function: s:svkFunctions.Diff(argList) {{{2
+function! s:svkFunctions.Diff(argList)
+ if len(a:argList) == 0
+ let revOptions = []
+ let caption = ''
+ elseif len(a:argList) <= 2 && match(a:argList, '^-') == -1
+ let revOptions = ['-r' . join(a:argList, ':')]
+ let caption = '(' . a:argList[0] . ' : ' . get(a:argList, 1, 'current') . ')'
+ else
+ " Pass-through
+ let caption = join(a:argList, ' ')
+ let revOptions = a:argList
+ endif
+
+ return s:DoCommand(join(['diff'] + revOptions), 'diff', caption, {})
+endfunction
+
+" Function: s:svkFunctions.GetBufferInfo() {{{2
+" Provides version control details for the current file. Current version
+" number and current repository version number are required to be returned by
+" the vcscommand plugin.
+" Returns: List of results: [revision, repository]
+
+function! s:svkFunctions.GetBufferInfo()
+ let originalBuffer = VCSCommandGetOriginalBuffer(bufnr('%'))
+ let fileName = resolve(bufname(originalBuffer))
+ let statusText = s:VCSCommandUtility.system(s:Executable() . ' status -v -- "' . fileName . '"')
+ if(v:shell_error)
+ return []
+ endif
+
+ " File not under SVK control.
+ if statusText =~ '^?'
+ return ['Unknown']
+ endif
+
+ let [flags, revision, repository] = matchlist(statusText, '^\(.\{3}\)\s\+\(\S\+\)\s\+\(\S\+\)\s\+\(\S\+\)\s')[1:3]
+ if revision == ''
+ " Error
+ return ['Unknown']
+ elseif flags =~ '^A'
+ return ['New', 'New']
+ else
+ return [revision, repository]
+ endif
+endfunction
+
+" Function: s:svkFunctions.Info(argList) {{{2
+function! s:svkFunctions.Info(argList)
+ return s:DoCommand(join(['info'] + a:argList, ' '), 'info', join(a:argList, ' '), {})
+endfunction
+
+" Function: s:svkFunctions.Lock(argList) {{{2
+function! s:svkFunctions.Lock(argList)
+ return s:DoCommand(join(['lock'] + a:argList, ' '), 'lock', join(a:argList, ' '), {})
+endfunction
+
+" Function: s:svkFunctions.Log() {{{2
+function! s:svkFunctions.Log(argList)
+ if len(a:argList) == 0
+ let options = []
+ let caption = ''
+ elseif len(a:argList) <= 2 && match(a:argList, '^-') == -1
+ let options = ['-r' . join(a:argList, ':')]
+ let caption = options[0]
+ else
+ " Pass-through
+ let options = a:argList
+ let caption = join(a:argList, ' ')
+ endif
+
+ let resultBuffer = s:DoCommand(join(['log', '-v'] + options), 'log', caption, {})
+ return resultBuffer
+endfunction
+
+" Function: s:svkFunctions.Revert(argList) {{{2
+function! s:svkFunctions.Revert(argList)
+ return s:DoCommand('revert', 'revert', '', {})
+endfunction
+
+" Function: s:svkFunctions.Review(argList) {{{2
+function! s:svkFunctions.Review(argList)
+ if len(a:argList) == 0
+ let versiontag = '(current)'
+ let versionOption = ''
+ else
+ let versiontag = a:argList[0]
+ let versionOption = ' -r ' . versiontag . ' '
+ endif
+
+ return s:DoCommand('cat' . versionOption, 'review', versiontag, {})
+endfunction
+
+" Function: s:svkFunctions.Status(argList) {{{2
+function! s:svkFunctions.Status(argList)
+ let options = ['-v']
+ if len(a:argList) != 0
+ let options = a:argList
+ endif
+ return s:DoCommand(join(['status'] + options, ' '), 'status', join(options, ' '), {})
+endfunction
+
+" Function: s:svkFunctions.Unlock(argList) {{{2
+function! s:svkFunctions.Unlock(argList)
+ return s:DoCommand(join(['unlock'] + a:argList, ' '), 'unlock', join(a:argList, ' '), {})
+endfunction
+" Function: s:svkFunctions.Update(argList) {{{2
+function! s:svkFunctions.Update(argList)
+ return s:DoCommand('update', 'update', '', {})
+endfunction
+
+" Section: Plugin Registration {{{1
+let s:VCSCommandUtility = VCSCommandRegisterModule('SVK', expand('<sfile>'), s:svkFunctions, [])
+
+let &cpo = s:save_cpo
diff --git a/modules/vim/vim/plugin/vcssvn.vim b/modules/vim/vim/plugin/vcssvn.vim
new file mode 100644
index 0000000..758f819
--- /dev/null
+++ b/modules/vim/vim/plugin/vcssvn.vim
@@ -0,0 +1,284 @@
+" vim600: set foldmethod=marker:
+"
+" SVN extension for VCSCommand.
+"
+" Maintainer: Bob Hiestand <bob.hiestand@gmail.com>
+" License:
+" Copyright (c) Bob Hiestand
+"
+" Permission is hereby granted, free of charge, to any person obtaining a copy
+" of this software and associated documentation files (the "Software"), to
+" deal in the Software without restriction, including without limitation the
+" rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+" sell copies of the Software, and to permit persons to whom the Software is
+" furnished to do so, subject to the following conditions:
+"
+" The above copyright notice and this permission notice shall be included in
+" all copies or substantial portions of the Software.
+"
+" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+" IN THE SOFTWARE.
+"
+" Section: Documentation {{{1
+"
+" Options documentation: {{{2
+"
+" VCSCommandSVNExec
+" This variable specifies the SVN executable. If not set, it defaults to
+" 'svn' executed from the user's executable path.
+"
+" VCSCommandSVNDiffExt
+" This variable, if set, sets the external diff program used by Subversion.
+"
+" VCSCommandSVNDiffOpt
+" This variable, if set, determines the options passed to the svn diff
+" command (such as 'u', 'w', or 'b').
+
+" Section: Plugin header {{{1
+
+if exists('VCSCommandDisableAll')
+ finish
+endif
+
+if v:version < 700
+ echohl WarningMsg|echomsg 'VCSCommand requires at least VIM 7.0'|echohl None
+ finish
+endif
+
+runtime plugin/vcscommand.vim
+
+if !executable(VCSCommandGetOption('VCSCommandSVNExec', 'svn'))
+ " SVN is not installed
+ finish
+endif
+
+let s:save_cpo=&cpo
+set cpo&vim
+
+" Section: Variable initialization {{{1
+
+let s:svnFunctions = {}
+
+" Section: Utility functions {{{1
+
+" Function: s:Executable() {{{2
+" Returns the executable used to invoke git suitable for use in a shell
+" command.
+function! s:Executable()
+ return shellescape(VCSCommandGetOption('VCSCommandSVNExec', 'svn'))
+endfunction
+
+" Function: s:DoCommand(cmd, cmdName, statusText, options) {{{2
+" Wrapper to VCSCommandDoCommand to add the name of the SVN executable to the
+" command argument.
+function! s:DoCommand(cmd, cmdName, statusText, options)
+ if VCSCommandGetVCSType(expand('%')) == 'SVN'
+ let fullCmd = s:Executable() . ' ' . a:cmd
+ return VCSCommandDoCommand(fullCmd, a:cmdName, a:statusText, a:options)
+ else
+ throw 'SVN VCSCommand plugin called on non-SVN item.'
+ endif
+endfunction
+
+" Section: VCS function implementations {{{1
+
+" Function: s:svnFunctions.Identify(buffer) {{{2
+function! s:svnFunctions.Identify(buffer)
+ let fileName = resolve(bufname(a:buffer))
+ if isdirectory(fileName)
+ let directoryName = fileName
+ else
+ let directoryName = fnamemodify(fileName, ':h')
+ endif
+ if strlen(directoryName) > 0
+ let svnDir = directoryName . '/.svn'
+ else
+ let svnDir = '.svn'
+ endif
+ if isdirectory(svnDir)
+ return 1
+ else
+ return 0
+ endif
+endfunction
+
+" Function: s:svnFunctions.Add() {{{2
+function! s:svnFunctions.Add(argList)
+ return s:DoCommand(join(['add'] + a:argList, ' '), 'add', join(a:argList, ' '), {})
+endfunction
+
+" Function: s:svnFunctions.Annotate(argList) {{{2
+function! s:svnFunctions.Annotate(argList)
+ if len(a:argList) == 0
+ if &filetype == 'SVNannotate'
+ " Perform annotation of the version indicated by the current line.
+ let caption = matchstr(getline('.'),'\v^\s+\zs\d+')
+ let options = ' -r' . caption
+ else
+ let caption = ''
+ let options = ''
+ endif
+ elseif len(a:argList) == 1 && a:argList[0] !~ '^-'
+ let caption = a:argList[0]
+ let options = ' -r' . caption
+ else
+ let caption = join(a:argList, ' ')
+ let options = ' ' . caption
+ endif
+
+ return s:DoCommand('blame --non-interactive' . options, 'annotate', caption, {})
+endfunction
+
+" Function: s:svnFunctions.Commit(argList) {{{2
+function! s:svnFunctions.Commit(argList)
+ let resultBuffer = s:DoCommand('commit --non-interactive -F "' . a:argList[0] . '"', 'commit', '', {})
+ if resultBuffer == 0
+ echomsg 'No commit needed.'
+ endif
+endfunction
+
+" Function: s:svnFunctions.Delete() {{{2
+function! s:svnFunctions.Delete(argList)
+ return s:DoCommand(join(['delete --non-interactive'] + a:argList, ' '), 'delete', join(a:argList, ' '), {})
+endfunction
+
+" Function: s:svnFunctions.Diff(argList) {{{2
+function! s:svnFunctions.Diff(argList)
+ if len(a:argList) == 0
+ let revOptions = []
+ let caption = ''
+ elseif len(a:argList) <= 2 && match(a:argList, '^-') == -1
+ let revOptions = ['-r' . join(a:argList, ':')]
+ let caption = '(' . a:argList[0] . ' : ' . get(a:argList, 1, 'current') . ')'
+ else
+ " Pass-through
+ let caption = join(a:argList, ' ')
+ let revOptions = a:argList
+ endif
+
+ let svnDiffExt = VCSCommandGetOption('VCSCommandSVNDiffExt', '')
+ if svnDiffExt == ''
+ let diffExt = []
+ else
+ let diffExt = ['--diff-cmd ' . svnDiffExt]
+ endif
+
+ let svnDiffOpt = VCSCommandGetOption('VCSCommandSVNDiffOpt', '')
+ if svnDiffOpt == ''
+ let diffOptions = []
+ else
+ let diffOptions = ['-x -' . svnDiffOpt]
+ endif
+
+ return s:DoCommand(join(['diff --non-interactive'] + diffExt + diffOptions + revOptions), 'diff', caption, {})
+endfunction
+
+" Function: s:svnFunctions.GetBufferInfo() {{{2
+" Provides version control details for the current file. Current version
+" number and current repository version number are required to be returned by
+" the vcscommand plugin.
+" Returns: List of results: [revision, repository, branch]
+
+function! s:svnFunctions.GetBufferInfo()
+ let originalBuffer = VCSCommandGetOriginalBuffer(bufnr('%'))
+ let fileName = bufname(originalBuffer)
+ let statusText = s:VCSCommandUtility.system(s:Executable() . ' status --non-interactive -vu -- "' . fileName . '"')
+ if(v:shell_error)
+ return []
+ endif
+
+ " File not under SVN control.
+ if statusText =~ '^?'
+ return ['Unknown']
+ endif
+
+ let [flags, revision, repository] = matchlist(statusText, '^\(.\{9}\)\s*\(\d\+\)\s\+\(\d\+\)')[1:3]
+ if revision == ''
+ " Error
+ return ['Unknown']
+ elseif flags =~ '^A'
+ return ['New', 'New']
+ elseif flags =~ '*'
+ return [revision, repository, '*']
+ else
+ return [revision, repository]
+ endif
+endfunction
+
+" Function: s:svnFunctions.Info(argList) {{{2
+function! s:svnFunctions.Info(argList)
+ return s:DoCommand(join(['info --non-interactive'] + a:argList, ' '), 'info', join(a:argList, ' '), {})
+endfunction
+
+" Function: s:svnFunctions.Lock(argList) {{{2
+function! s:svnFunctions.Lock(argList)
+ return s:DoCommand(join(['lock --non-interactive'] + a:argList, ' '), 'lock', join(a:argList, ' '), {})
+endfunction
+
+" Function: s:svnFunctions.Log(argList) {{{2
+function! s:svnFunctions.Log(argList)
+ if len(a:argList) == 0
+ let options = []
+ let caption = ''
+ elseif len(a:argList) <= 2 && match(a:argList, '^-') == -1
+ let options = ['-r' . join(a:argList, ':')]
+ let caption = options[0]
+ else
+ " Pass-through
+ let options = a:argList
+ let caption = join(a:argList, ' ')
+ endif
+
+ let resultBuffer = s:DoCommand(join(['log --non-interactive', '-v'] + options), 'log', caption, {})
+ return resultBuffer
+endfunction
+
+" Function: s:svnFunctions.Revert(argList) {{{2
+function! s:svnFunctions.Revert(argList)
+ return s:DoCommand('revert', 'revert', '', {})
+endfunction
+
+" Function: s:svnFunctions.Review(argList) {{{2
+function! s:svnFunctions.Review(argList)
+ if len(a:argList) == 0
+ let versiontag = '(current)'
+ let versionOption = ''
+ else
+ let versiontag = a:argList[0]
+ let versionOption = ' -r ' . versiontag . ' '
+ endif
+
+ return s:DoCommand('cat --non-interactive' . versionOption, 'review', versiontag, {})
+endfunction
+
+" Function: s:svnFunctions.Status(argList) {{{2
+function! s:svnFunctions.Status(argList)
+ let options = ['-u', '-v']
+ if len(a:argList) != 0
+ let options = a:argList
+ endif
+ return s:DoCommand(join(['status --non-interactive'] + options, ' '), 'status', join(options, ' '), {})
+endfunction
+
+" Function: s:svnFunctions.Unlock(argList) {{{2
+function! s:svnFunctions.Unlock(argList)
+ return s:DoCommand(join(['unlock --non-interactive'] + a:argList, ' '), 'unlock', join(a:argList, ' '), {})
+endfunction
+
+" Function: s:svnFunctions.Update(argList) {{{2
+function! s:svnFunctions.Update(argList)
+ return s:DoCommand('update --non-interactive', 'update', '', {})
+endfunction
+
+" Annotate setting {{{2
+let s:svnFunctions.AnnotateSplitRegex = '\s\+\S\+\s\+\S\+ '
+
+" Section: Plugin Registration {{{1
+let s:VCSCommandUtility = VCSCommandRegisterModule('SVN', expand('<sfile>'), s:svnFunctions, [])
+
+let &cpo = s:save_cpo
diff --git a/modules/vim/vim/snippets/_.snippets b/modules/vim/vim/snippets/_.snippets
new file mode 100644
index 0000000..c3925a5
--- /dev/null
+++ b/modules/vim/vim/snippets/_.snippets
@@ -0,0 +1,7 @@
+# Global snippets
+
+# (c) holds no legal value ;)
+snippet c)
+ `&enc[:2] == "utf" ? "©" : "(c)"` Copyright `strftime("%Y")` ${1:`g:snips_author`}. All Rights Reserved.${2}
+snippet date
+ `strftime("%Y-%m-%d")`
diff --git a/modules/vim/vim/snippets/autoit.snippets b/modules/vim/vim/snippets/autoit.snippets
new file mode 100644
index 0000000..690018c
--- /dev/null
+++ b/modules/vim/vim/snippets/autoit.snippets
@@ -0,0 +1,66 @@
+snippet if
+ If ${1:condition} Then
+ ${2:; True code}
+ EndIf
+snippet el
+ Else
+ ${1}
+snippet elif
+ ElseIf ${1:condition} Then
+ ${2:; True code}
+# If/Else block
+snippet ifel
+ If ${1:condition} Then
+ ${2:; True code}
+ Else
+ ${3:; Else code}
+ EndIf
+# If/ElseIf/Else block
+snippet ifelif
+ If ${1:condition 1} Then
+ ${2:; True code}
+ ElseIf ${3:condition 2} Then
+ ${4:; True code}
+ Else
+ ${5:; Else code}
+ EndIf
+# Switch block
+snippet switch
+ Switch (${1:condition})
+ Case {$2:case1}:
+ {$3:; Case 1 code}
+ Case Else:
+ {$4:; Else code}
+ EndSwitch
+# Select block
+snippet select
+ Select (${1:condition})
+ Case {$2:case1}:
+ {$3:; Case 1 code}
+ Case Else:
+ {$4:; Else code}
+ EndSelect
+# While loop
+snippet while
+ While (${1:condition})
+ ${2:; code...}
+ WEnd
+# For loop
+snippet for
+ For ${1:n} = ${3:1} to ${2:count}
+ ${4:; code...}
+ Next
+# New Function
+snippet func
+ Func ${1:fname}(${2:`indent('.') ? 'self' : ''`}):
+ ${4:Return}
+ EndFunc
+# Message box
+snippet msg
+ MsgBox(${3:MsgType}, ${1:"Title"}, ${2:"Message Text"})
+# Debug Message
+snippet debug
+ MsgBox(0, "Debug", ${1:"Debug Message"})
+# Show Variable Debug Message
+snippet showvar
+ MsgBox(0, "${1:VarName}", $1)
diff --git a/modules/vim/vim/snippets/c.snippets b/modules/vim/vim/snippets/c.snippets
new file mode 100644
index 0000000..89b81ba
--- /dev/null
+++ b/modules/vim/vim/snippets/c.snippets
@@ -0,0 +1,110 @@
+# main()
+snippet main
+ int main(int argc, const char *argv[])
+ {
+ ${1}
+ return 0;
+ }
+# #include <...>
+snippet inc
+ #include <${1:stdio}.h>${2}
+# #include "..."
+snippet Inc
+ #include "${1:`Filename("$1.h")`}"${2}
+# #ifndef ... #define ... #endif
+snippet Def
+ #ifndef $1
+ #define ${1:SYMBOL} ${2:value}
+ #endif${3}
+snippet def
+ #define
+snippet ifdef
+ #ifdef ${1:FOO}
+ ${2:#define }
+ #endif
+snippet #if
+ #if ${1:FOO}
+ ${2}
+ #endif
+# Header Include-Guard
+# (the randomizer code is taken directly from TextMate; it could probably be
+# cleaner, I don't know how to do it in vim script)
+snippet once
+ #ifndef ${1:`toupper(Filename('', 'UNTITLED').'_'.system("/usr/bin/ruby -e 'print (rand * 2821109907455).round.to_s(36)'"))`}
+
+ #define $1
+
+ ${2}
+
+ #endif /* end of include guard: $1 */
+# If Condition
+snippet if
+ if (${1:/* condition */}) {
+ ${2:/* code */}
+ }
+snippet el
+ else {
+ ${1}
+ }
+# Tertiary conditional
+snippet t
+ ${1:/* condition */} ? ${2:a} : ${3:b}
+# Do While Loop
+snippet do
+ do {
+ ${2:/* code */}
+ } while (${1:/* condition */});
+# While Loop
+snippet wh
+ while (${1:/* condition */}) {
+ ${2:/* code */}
+ }
+# For Loop
+snippet for
+ for (${2:i} = 0; $2 < ${1:count}; $2${3:++}) {
+ ${4:/* code */}
+ }
+# Custom For Loop
+snippet forr
+ for (${1:i} = ${2:0}; ${3:$1 < 10}; $1${4:++}) {
+ ${5:/* code */}
+ }
+# Function
+snippet fun
+ ${1:void} ${2:function_name}(${3})
+ {
+ ${4:/* code */}
+ }
+# Function Declaration
+snippet fund
+ ${1:void} ${2:function_name}(${3});${4}
+# Typedef
+snippet td
+ typedef ${1:int} ${2:MyCustomType};${3}
+# Struct
+snippet st
+ struct ${1:`Filename('$1_t', 'name')`} {
+ ${2:/* data */}
+ }${3: /* optional variable list */};${4}
+# Typedef struct
+snippet tds
+ typedef struct ${2:_$1 }{
+ ${3:/* data */}
+ } ${1:`Filename('$1_t', 'name')`};
+# Typdef enum
+snippet tde
+ typedef enum {
+ ${1:/* data */}
+ } ${2:foo};
+# printf
+# unfortunately version this isn't as nice as TextMates's, given the lack of a
+# dynamic `...`
+snippet pr
+ printf("${1:%s}\n"${2});${3}
+# fprintf (again, this isn't as nice as TextMate's version, but it works)
+snippet fpr
+ fprintf(${1:stderr}, "${2:%s}\n"${3});${4}
+snippet .
+ [${1}]${2}
+snippet un
+ unsigned
diff --git a/modules/vim/vim/snippets/cpp.snippets b/modules/vim/vim/snippets/cpp.snippets
new file mode 100644
index 0000000..e4850cd
--- /dev/null
+++ b/modules/vim/vim/snippets/cpp.snippets
@@ -0,0 +1,30 @@
+# Read File Into Vector
+snippet readfile
+ std::vector<char> v;
+ if (FILE *${2:fp} = fopen(${1:"filename"}, "r")) {
+ char buf[1024];
+ while (size_t len = fread(buf, 1, sizeof(buf), $2))
+ v.insert(v.end(), buf, buf + len);
+ fclose($2);
+ }${3}
+# std::map
+snippet map
+ std::map<${1:key}, ${2:value}> map${3};
+# std::vector
+snippet vector
+ std::vector<${1:char}> v${2};
+# Namespace
+snippet ns
+ namespace ${1:`Filename('', 'my')`} {
+ ${2}
+ } /* $1 */
+# Class
+snippet cl
+ class ${1:`Filename('$1_t', 'name')`} {
+ public:
+ $1 (${2:arguments});
+ virtual ~$1 ();
+
+ private:
+ ${3:/* data */}
+ };
diff --git a/modules/vim/vim/snippets/html.snippets b/modules/vim/vim/snippets/html.snippets
new file mode 100644
index 0000000..aefb9db
--- /dev/null
+++ b/modules/vim/vim/snippets/html.snippets
@@ -0,0 +1,190 @@
+# Some useful Unicode entities
+# Non-Breaking Space
+snippet nbs
+ &nbsp;
+# â†
+snippet left
+ &#x2190;
+# →
+snippet right
+ &#x2192;
+# ↑
+snippet up
+ &#x2191;
+# ↓
+snippet down
+ &#x2193;
+# ↩
+snippet return
+ &#x21A9;
+# ⇤
+snippet backtab
+ &#x21E4;
+# ⇥
+snippet tab
+ &#x21E5;
+# ⇧
+snippet shift
+ &#x21E7;
+# ⌃
+snippet control
+ &#x2303;
+# ⌅
+snippet enter
+ &#x2305;
+# ⌘
+snippet command
+ &#x2318;
+# ⌥
+snippet option
+ &#x2325;
+# ⌦
+snippet delete
+ &#x2326;
+# ⌫
+snippet backspace
+ &#x232B;
+# ⎋
+snippet escape
+ &#x238B;
+# Generic Doctype
+snippet doctype HTML 4.01 Strict
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""
+ "http://www.w3.org/TR/html4/strict.dtd">
+snippet doctype HTML 4.01 Transitional
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""
+ "http://www.w3.org/TR/html4/loose.dtd">
+snippet doctype HTML 5
+ <!DOCTYPE HTML>
+snippet doctype XHTML 1.0 Frameset
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+snippet doctype XHTML 1.0 Strict
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+snippet doctype XHTML 1.0 Transitional
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+snippet doctype XHTML 1.1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+# HTML Doctype 4.01 Strict
+snippet docts
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""
+ "http://www.w3.org/TR/html4/strict.dtd">
+# HTML Doctype 4.01 Transitional
+snippet doct
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""
+ "http://www.w3.org/TR/html4/loose.dtd">
+# HTML Doctype 5
+snippet doct5
+ <!DOCTYPE HTML>
+# XHTML Doctype 1.0 Frameset
+snippet docxf
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
+# XHTML Doctype 1.0 Strict
+snippet docxs
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+# XHTML Doctype 1.0 Transitional
+snippet docxt
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+# XHTML Doctype 1.1
+snippet docx
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+snippet html
+ <html>
+ ${1}
+ </html>
+snippet xhtml
+ <html xmlns="http://www.w3.org/1999/xhtml">
+ ${1}
+ </html>
+snippet body
+ <body>
+ ${1}
+ </body>
+snippet head
+ <head>
+ <meta http-equiv="content-type" content="text/html; charset=utf-8"`Close()`>
+
+ <title>${1:`substitute(Filename('', 'Page Title'), '^.', '\u&', '')`}</title>
+ ${2}
+ </head>
+snippet title
+ <title>${1:`substitute(Filename('', 'Page Title'), '^.', '\u&', '')`}</title>${2}
+snippet script
+ <script type="text/javascript" charset="utf-8">
+ ${1}
+ </script>${2}
+snippet scriptsrc
+ <script src="${1}.js" type="text/javascript" charset="utf-8"></script>${2}
+snippet style
+ <style type="text/css" media="${1:screen}">
+ ${2}
+ </style>${3}
+snippet base
+ <base href="${1}" target="${2}"`Close()`>
+snippet r
+ <br`Close()[1:]`>
+snippet div
+ <div id="${1:name}">
+ ${2}
+ </div>
+# Embed QT Movie
+snippet movie
+ <object width="$2" height="$3" classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B"
+ codebase="http://www.apple.com/qtactivex/qtplugin.cab">
+ <param name="src" value="$1"`Close()`>
+ <param name="controller" value="$4"`Close()`>
+ <param name="autoplay" value="$5"`Close()`>
+ <embed src="${1:movie.mov}"
+ width="${2:320}" height="${3:240}"
+ controller="${4:true}" autoplay="${5:true}"
+ scale="tofit" cache="true"
+ pluginspage="http://www.apple.com/quicktime/download/"
+ `Close()[1:]`>
+ </object>${6}
+snippet fieldset
+ <fieldset id="$1">
+ <legend>${1:name}</legend>
+
+ ${3}
+ </fieldset>
+snippet form
+ <form action="${1:`Filename('$1_submit')`}" method="${2:get}" accept-charset="utf-8">
+ ${3}
+
+
+ <p><input type="submit" value="Continue &rarr;"`Close()`></p>
+ </form>
+snippet h1
+ <h1 id="${1:heading}">${2:$1}</h1>
+snippet input
+ <input type="${1:text/submit/hidden/button}" name="${2:some_name}" value="${3}"`Close()`>${4}
+snippet label
+ <label for="${2:$1}">${1:name}</label><input type="${3:text/submit/hidden/button}" name="${4:$2}" value="${5}" id="${6:$2}"`Close()`>${7}
+snippet link
+ <link rel="${1:stylesheet}" href="${2:/css/master.css}" type="text/css" media="${3:screen}" charset="utf-8"`Close()`>${4}
+snippet mailto
+ <a href="mailto:${1:joe@example.com}?subject=${2:feedback}">${3:email me}</a>
+snippet meta
+ <meta name="${1:name}" content="${2:content}"`Close()`>${3}
+snippet opt
+ <option value="${1:option}">${2:$1}</option>${3}
+snippet optt
+ <option>${1:option}</option>${2}
+snippet select
+ <select name="${1:some_name}" id="${2:$1}">
+ <option value="${3:option}">${4:$3}</option>
+ </select>${5}
+snippet table
+ <table border="${1:0}">
+ <tr><th>${2:Header}</th></tr>
+ <tr><th>${3:Data}</th></tr>
+ </table>${4}
+snippet textarea
+ <textarea name="${1:Name}" rows="${2:8}" cols="${3:40}">${4}</textarea>${5}
diff --git a/modules/vim/vim/snippets/java.snippets b/modules/vim/vim/snippets/java.snippets
new file mode 100644
index 0000000..fd705cb
--- /dev/null
+++ b/modules/vim/vim/snippets/java.snippets
@@ -0,0 +1,78 @@
+snippet main
+ public static void main (String [] args)
+ {
+ ${1:/* code */}
+ }
+snippet pu
+ public
+snippet po
+ protected
+snippet pr
+ private
+snippet st
+ static
+snippet fi
+ final
+snippet ab
+ abstract
+snippet re
+ return
+snippet br
+ break;
+snippet de
+ default:
+ ${1}
+snippet ca
+ catch(${1:Exception} ${2:e}) ${3}
+snippet th
+ throw
+snippet sy
+ synchronized
+snippet im
+ import
+snippet j.u
+ java.util
+snippet j.i
+ java.io.
+snippet j.b
+ java.beans.
+snippet j.n
+ java.net.
+snippet j.m
+ java.math.
+snippet if
+ if (${1}) ${2}
+snippet el
+ else
+snippet elif
+ else if (${1}) ${2}
+snippet wh
+ while (${1}) ${2}
+snippet for
+ for (${1}; ${2}; ${3}) ${4}
+snippet fore
+ for (${1} : ${2}) ${3}
+snippet sw
+ switch (${1}) ${2}
+snippet cs
+ case ${1}:
+ ${2}
+ ${3}
+snippet tc
+ public class ${1:`Filename()`} extends ${2:TestCase}
+snippet t
+ public void test${1:Name}() throws Exception ${2}
+snippet cl
+ class ${1:`Filename("", "untitled")`} ${2}
+snippet in
+ interface ${1:`Filename("", "untitled")`} ${2:extends Parent}${3}
+snippet m
+ ${1:void} ${2:method}(${3}) ${4:throws }${5}
+snippet v
+ ${1:String} ${2:var}${3: = null}${4};${5}
+snippet co
+ static public final ${1:String} ${2:var} = ${3};${4}
+snippet cos
+ static public final String ${1:var} = "${2}";${3}
+snippet as
+ assert ${1:test} : "${2:Failure message}";${3}
diff --git a/modules/vim/vim/snippets/javascript.snippets b/modules/vim/vim/snippets/javascript.snippets
new file mode 100644
index 0000000..51f5e05
--- /dev/null
+++ b/modules/vim/vim/snippets/javascript.snippets
@@ -0,0 +1,74 @@
+# Prototype
+snippet proto
+ ${1:class_name}.prototype.${2:method_name} =
+ function(${3:first_argument}) {
+ ${4:// body...}
+ };
+# Function
+snippet fun
+ function ${1:function_name} (${2:argument}) {
+ ${3:// body...}
+ }
+# Anonymous Function
+snippet f
+ function(${1}) {${2}};
+# if
+snippet if
+ if (${1:true}) {${2}};
+# if ... else
+snippet ife
+ if (${1:true}) {${2}}
+ else{${3}};
+# tertiary conditional
+snippet t
+ ${1:/* condition */} ? ${2:a} : ${3:b}
+# switch
+snippet switch
+ switch(${1:expression}) {
+ case '${3:case}':
+ ${4:// code}
+ break;
+ ${5}
+ default:
+ ${2:// code}
+ }
+# case
+snippet case
+ case '${1:case}':
+ ${2:// code}
+ break;
+ ${3}
+# for (...) {...}
+snippet for
+ for (var ${2:i} = 0; $2 < ${1:Things}.length; $2${3:++}) {
+ ${4:$1[$2]}
+ };
+# for (...) {...} (Improved Native For-Loop)
+snippet forr
+ for (var ${2:i} = ${1:Things}.length - 1; $2 >= 0; $2${3:--}) {
+ ${4:$1[$2]}
+ };
+# while (...) {...}
+snippet wh
+ while (${1:/* condition */}) {
+ ${2:/* code */}
+ }
+# do...while
+snippet do
+ do {
+ ${2:/* code */}
+ } while (${1:/* condition */});
+# Object Method
+snippet :f
+ ${1:method_name}: function(${2:attribute}) {
+ ${4}
+ }${3:,}
+# setTimeout function
+snippet timeout
+ setTimeout(function() {${3}}${2}, ${1:10};
+# Get Elements
+snippet get
+ getElementsBy${1:TagName}('${2}')${3}
+# Get Element
+snippet gett
+ getElementBy${1:Id}('${2}')${3}
diff --git a/modules/vim/vim/snippets/mako.snippets b/modules/vim/vim/snippets/mako.snippets
new file mode 100644
index 0000000..2a0aef9
--- /dev/null
+++ b/modules/vim/vim/snippets/mako.snippets
@@ -0,0 +1,54 @@
+snippet def
+ <%def name="${1:name}">
+ ${2:}
+ </%def>
+snippet call
+ <%call expr="${1:name}">
+ ${2:}
+ </%call>
+snippet doc
+ <%doc>
+ ${1:}
+ </%doc>
+snippet text
+ <%text>
+ ${1:}
+ </%text>
+snippet for
+ % for ${1:i} in ${2:iter}:
+ ${3:}
+ % endfor
+snippet if if
+ % if ${1:condition}:
+ ${2:}
+ % endif
+snippet if if/else
+ % if ${1:condition}:
+ ${2:}
+ % else:
+ ${3:}
+ % endif
+snippet try
+ % try:
+ ${1:}
+ % except${2:}:
+ ${3:pass}
+ % endtry
+snippet wh
+ % while ${1:}:
+ ${2:}
+ % endwhile
+snippet $
+ ${ ${1:} }
+snippet <%
+ <% ${1:} %>
+snippet <!%
+ <!% ${1:} %>
+snippet inherit
+ <%inherit file="${1:filename}" />
+snippet include
+ <%include file="${1:filename}" />
+snippet namespace
+ <%namespace file="${1:name}" />
+snippet page
+ <%page args="${1:}" />
diff --git a/modules/vim/vim/snippets/objc.snippets b/modules/vim/vim/snippets/objc.snippets
new file mode 100644
index 0000000..4749bb7
--- /dev/null
+++ b/modules/vim/vim/snippets/objc.snippets
@@ -0,0 +1,184 @@
+# #import <...>
+snippet Imp
+ #import <${1:Cocoa/Cocoa.h}>${2}
+# #import "..."
+snippet imp
+ #import "${1:`Filename()`.h}"${2}
+# @selector(...)
+snippet sel
+ @selector(${1:method}:)${3}
+# @"..." string
+snippet s
+ @"${1}"${2}
+# Object
+snippet o
+ ${1:NSObject} *${2:foo} = [${3:$1 alloc}]${4};${5}
+# NSLog(...)
+snippet log
+ NSLog(@"${1:%@}"${2});${3}
+# Class
+snippet objc
+ @interface ${1:`Filename('', 'someClass')`} : ${2:NSObject}
+ {
+ }
+ @end
+
+ @implementation $1
+ ${3}
+ @end
+# Class Interface
+snippet int
+ @interface ${1:`Filename('', 'someClass')`} : ${2:NSObject}
+ {${3}
+ }
+ ${4}
+ @end
+# Class Implementation
+snippet impl
+ @implementation ${1:`Filename('', 'someClass')`}
+ ${2}
+ @end
+snippet init
+ - (id)init
+ {
+ [super init];
+ return self;
+ }
+snippet ifself
+ if (self = [super init]) {
+ ${1:/* code */}
+ }
+ return self;
+snippet ibo
+ IBOutlet ${1:NSSomeClass} *${2:$1};${3}
+# Category
+snippet cat
+ @interface ${1:NSObject} (${2:Category})
+ @end
+
+ @implementation $1 ($2)
+ ${3}
+ @end
+# Category Interface
+snippet cath
+ @interface ${1:NSObject} (${2:Category})
+ ${3}
+ @end
+# NSArray
+snippet array
+ NSMutableArray *${1:array} = [NSMutable array];${2}
+# NSDictionary
+snippet dict
+ NSMutableDictionary *${1:dict} = [NSMutableDictionary dictionary];${2}
+# NSBezierPath
+snippet bez
+ NSBezierPath *${1:path} = [NSBezierPath bezierPath];${2}
+# Method
+snippet m
+ - (${1:id})${2:method}
+ {
+ ${3}
+ }
+# Method declaration
+snippet md
+ - (${1:id})${2:method};${3}
+# IBAction declaration
+snippet ibad
+ - (IBAction)${1:method}:(${2:id})sender;${3}
+# IBAction method
+snippet iba
+ - (IBAction)${1:method}:(${2:id})sender
+ {
+ ${3}
+ }
+# awakeFromNib method
+snippet wake
+ - (void)awakeFromNib
+ {
+ ${1}
+ }
+# Class Method
+snippet M
+ + (${1:id})${2:method}
+ {${3}
+ return nil;
+ }
+# Sub-method (Call super)
+snippet sm
+ - (${1:id})${2:method}
+ {
+ [super $2];${3}
+ return self;
+ }
+# Method: Initialize
+snippet I
+ + (void) initialize
+ {
+ [[NSUserDefaults standardUserDefaults] registerDefaults:[NSDictionary dictionaryWIthObjectsAndKeys:
+ ${1}@"value", @"key",
+ nil]];
+ }
+# Accessor Methods For:
+# Object
+snippet objacc
+ - (${1:id})${2:thing}
+ {
+ return $2;
+ }
+
+ - (void)set$2:($1)${3:new$2}
+ {
+ [$3 retain];
+ [$2 release];
+ $2 = $3;
+ }${4}
+# for (object in array)
+snippet forin
+ for (${1:Class} *${2:some$1} in ${3:array}) {
+ ${4}
+ }
+snippet forarray
+ unsigned int ${1:object}Count = [${2:array} count];
+
+ for (unsigned int index = 0; index < $1Count; index++) {
+ ${3:id} $1 = [$2 $1AtIndex:index];
+ ${4}
+ }
+# IBOutlet
+# @property (Objective-C 2.0)
+snippet prop
+ @property (${1:retain}) ${2:NSSomeClass} ${3:*$2};${4}
+# @synthesize (Objective-C 2.0)
+snippet syn
+ @synthesize ${1:property};${2}
+# [[ alloc] init]
+snippet alloc
+ [[${1:foo} alloc] init${2}];${3}
+# retain
+snippet ret
+ [${1:foo} retain];${2}
+# release
+snippet rel
+ [${1:foo} release];
+ ${2:$1 = nil;}
+# autorelease
+snippet arel
+ [${1:foo} autorelease];
+# autorelease pool
+snippet pool
+ NSAutoreleasePool *${1:pool} = [[NSAutoreleasePool alloc] init];
+ ${2:/* code */}
+ [$1 drain];
+# Throw an exception
+snippet except
+ NSException *${1:badness};
+ $1 = [NSException exceptionWithName:@"${2:$1Name}"
+ reason:@"${3}"
+ userInfo:nil];
+ [$1 raise];
+snippet prag
+ #pragma mark ${1:foo}
+snippet cl
+ @class ${1:Foo};${2}
+snippet color
+ [[NSColor ${1:blackColor}] set];
diff --git a/modules/vim/vim/snippets/perl.snippets b/modules/vim/vim/snippets/perl.snippets
new file mode 100644
index 0000000..cf8f9fc
--- /dev/null
+++ b/modules/vim/vim/snippets/perl.snippets
@@ -0,0 +1,91 @@
+# #!/usr/bin/perl
+snippet #!
+ #!/usr/bin/perl
+
+# Hash Pointer
+snippet .
+ =>
+# Function
+snippet sub
+ sub ${1:function_name} {
+ ${2:#body ...}
+ }
+# Conditional
+snippet if
+ if (${1}) {
+ ${2:# body...}
+ }
+# Conditional if..else
+snippet ife
+ if (${1}) {
+ ${2:# body...}
+ } else {
+ ${3:# else...}
+ }
+# Conditional if..elsif..else
+snippet ifee
+ if (${1}) {
+ ${2:# body...}
+ } elsif (${3}) {
+ ${4:# elsif...}
+ } else {
+ ${5:# else...}
+ }
+# Conditional One-line
+snippet xif
+ ${1:expression} if ${2:condition};${3}
+# Unless conditional
+snippet unless
+ unless (${1}) {
+ ${2:# body...}
+ }
+# Unless conditional One-line
+snippet xunless
+ ${1:expression} unless ${2:condition};${3}
+# Try/Except
+snippet eval
+ eval {
+ ${1:# do something risky...}
+ };
+ if ($@) {
+ ${2:# handle failure...}
+ }
+# While Loop
+snippet wh
+ while (${1}) {
+ ${2:# body...}
+ }
+# While Loop One-line
+snippet xwh
+ ${1:expression} while ${2:condition};${3}
+# For Loop
+snippet for
+ for (my $${2:var} = 0; $$2 < ${1:count}; $$2${3:++}) {
+ ${4:# body...}
+ }
+# Foreach Loop
+snippet fore
+ foreach my $${1:x} (@${2:array}) {
+ ${3:# body...}
+ }
+# Foreach Loop One-line
+snippet xfore
+ ${1:expression} foreach @${2:array};${3}
+# Package
+snippet cl
+ package ${1:ClassName};
+
+ use base qw(${2:ParentClass});
+
+ sub new {
+ my $class = shift;
+ $class = ref $class if ref $class;
+ my $self = bless {}, $class;
+ $self;
+ }
+
+ 1;${3}
+# Read File
+snippet slurp
+ my $${1:var};
+ { local $/ = undef; local *FILE; open FILE, "<${2:file}"; $$1 = <FILE>; close FILE }${3}
diff --git a/modules/vim/vim/snippets/php.snippets b/modules/vim/vim/snippets/php.snippets
new file mode 100644
index 0000000..b122b5f
--- /dev/null
+++ b/modules/vim/vim/snippets/php.snippets
@@ -0,0 +1,9397 @@
+snippet php
+ <?php
+ ${1}
+ ?>
+snippet ec
+ echo "${1:string}"${2};
+snippet inc
+ include '${1:file}';${2}
+snippet inc1
+ include_once '${1:file}';${2}
+snippet req
+ require '${1:file}';${2}
+snippet req1
+ require_once '${1:file}';${2}
+# $GLOBALS['...']
+snippet globals
+ $GLOBALS['${1:variable}']${2: = }${3:something}${4:;}${5}
+snippet $_ COOKIE['...']
+ $_COOKIE['${1:variable}']${2}
+snippet $_ ENV['...']
+ $_ENV['${1:variable}']${2}
+snippet $_ FILES['...']
+ $_FILES['${1:variable}']${2}
+snippet $_ Get['...']
+ $_GET['${1:variable}']${2}
+snippet $_ POST['...']
+ $_POST['${1:variable}']${2}
+snippet $_ REQUEST['...']
+ $_REQUEST['${1:variable}']${2}
+snippet $_ SERVER['...']
+ $_SERVER['${1:variable}']${2}
+snippet $_ SESSION['...']
+ $_SESSION['${1:variable}']${2}
+# Start Docblock
+snippet /*
+ /**
+ * ${1}
+ **/
+# Class - post doc
+snippet doc_cp
+ /**
+ * ${1:undocumented class}
+ *
+ * @package ${2:default}
+ * @author ${3:`g:snips_author`}
+ **/${4}
+# Class Variable - post doc
+snippet doc_vp
+ /**
+ * ${1:undocumented class variable}
+ *
+ * @var ${2:string}
+ **/${3}
+# Class Variable
+snippet doc_v
+ /**
+ * ${3:undocumented class variable}
+ *
+ * @var ${4:string}
+ **/
+ ${1:var} $${2};${5}
+# Class
+snippet doc_c
+ /**
+ * ${3:undocumented class}
+ *
+ * @packaged ${4:default}
+ * @author ${5:`g:snips_author`}
+ **/
+ ${1:}class ${2:}
+ {${6}
+ } // END $1class $2
+# Constant Definition - post doc
+snippet doc_dp
+ /**
+ * ${1:undocumented constant}
+ **/${2}
+# Constant Definition
+snippet doc_d
+ /**
+ * ${3:undocumented constant}
+ **/
+ define(${1}, ${2});${4}
+# Function - post doc
+snippet doc_fp
+ /**
+ * ${1:undocumented function}
+ *
+ * @return ${2:void}
+ * @author ${3:`g:snips_author`}
+ **/${4}
+# Function signature
+snippet doc_s
+ /**
+ * ${4:undocumented function}
+ *
+ * @return ${5:void}
+ * @author ${6:`g:snips_author`}
+ **/
+ ${1}function ${2}(${3});${7}
+# Function
+snippet doc_f
+ /**
+ * ${4:undocumented function}
+ *
+ * @return ${5:void}
+ * @author ${6:`g:snips_author`}
+ **/
+ ${1}function ${2}(${3})
+ {${7}
+ }
+# Header
+snippet doc_h
+ /**
+ * ${1}
+ *
+ * @author ${2:`g:snips_author`}
+ * @version ${3:$Id$}
+ * @copyright ${4:$2}, `strftime('%d %B, %Y')`
+ * @package ${5:default}
+ **/
+
+ /**
+ * Define DocBlock
+ *//
+# Interface
+snippet doc_i
+ /**
+ * ${2:undocumented class}
+ *
+ * @package ${3:default}
+ * @author ${4:`g:snips_author`}
+ **/
+ interface ${1:}
+ {${5}
+ } // END interface $1
+# class ...
+snippet class
+ /**
+ * ${1}
+ **/
+ class ${2:ClassName}
+ {
+ ${3}
+ function ${4:__construct}(${5:argument})
+ {
+ ${6:// code...}
+ }
+ }
+# define(...)
+snippet def
+ define('${1}'${2});${3}
+# defined(...)
+snippet def?
+ ${1}defined('${2}')${3}
+snippet wh
+ while (${1:/* condition */}) {
+ ${2:// code...}
+ }
+# do ... while
+snippet do
+ do {
+ ${2:// code... }
+ } while (${1:/* condition */});
+snippet if
+ if (${1:/* condition */}) {
+ ${2:// code...}
+ }
+snippet ife
+ if (${1:/* condition */}) {
+ ${2:// code...}
+ } else {
+ ${3:// code...}
+ }
+ ${4}
+snippet else
+ else {
+ ${1:// code...}
+ }
+snippet elseif
+ elseif (${1:/* condition */}) {
+ ${2:// code...}
+ }
+# Tertiary conditional
+snippet t
+ $${1:retVal} = (${2:condition}) ? ${3:a} : ${4:b};${5}
+snippet switch
+ switch ($${1:variable}) {
+ case '${2:value}':
+ ${3:// code...}
+ break;
+ ${5}
+ default:
+ ${4:// code...}
+ break;
+ }
+snippet case
+ case '${1:value}':
+ ${2:// code...}
+ break;${3}
+snippet for
+ for ($${2:i} = 0; $$2 < ${1:count}; $$2${3:++}) {
+ ${4: // code...}
+ }
+snippet foreach
+ foreach ($${1:variable} as $${2:key}) {
+ ${3:// code...}
+ }
+snippet fun
+ ${1:public }function ${2:FunctionName}(${3})
+ {
+ ${4:// code...}
+ }
+# $... = array (...)
+snippet array
+ $${1:arrayName} = array('${2}' => ${3});${4}
+# DRUPAL 7 Hooks
+snippet h_simpletest_alter
+ /**
+ * Implements hook_simpletest_alter()
+ */
+ function `Filename()`_simpletest_alter(&$groups) {
+ ${1:/* Your code here */}
+ }
+snippet h_test_group_started
+ /**
+ * Implements hook_test_group_started()
+ */
+ function `Filename()`_test_group_started() {
+ ${1:/* Your code here */}
+ }
+snippet h_test_group_finished
+ /**
+ * Implements hook_test_group_finished()
+ */
+ function `Filename()`_test_group_finished() {
+ ${1:/* Your code here */}
+ }
+snippet h_test_finished
+ /**
+ * Implements hook_test_finished()
+ */
+ function `Filename()`_test_finished($results) {
+ ${1:/* Your code here */}
+ }
+snippet h_aggregator_fetch
+ /**
+ * Implements hook_aggregator_fetch()
+ */
+ function `Filename()`_aggregator_fetch($feed) {
+ ${1:/* Your code here */}
+ }
+snippet h_aggregator_fetch_info
+ /**
+ * Implements hook_aggregator_fetch_info()
+ */
+ function `Filename()`_aggregator_fetch_info() {
+ return array(
+ 'title' => t('${1}'),
+ 'description' => t('${2}'),
+ );
+ }
+snippet h_aggregator_parse
+ /**
+ * Implements hook_aggregator_parse()
+ */
+ function `Filename()`_aggregator_parse($feed) {
+ ${1:/* Your code here */}
+ }
+snippet h_aggregator_parse_info
+ /**
+ * Implements hook_aggregator_parse_info()
+ */
+ function `Filename()`_aggregator_parse_info() {
+ return array(
+ 'title' => t('${1}'),
+ 'description' => t('${2}'),
+ );
+ }
+snippet h_aggregator_process
+ /**
+ * Implements hook_aggregator_process()
+ */
+ function `Filename()`_aggregator_process($feed) {
+ ${1:/* Your code here */}
+ }
+snippet h_aggregator_process_info
+ /**
+ * Implements hook_aggregator_process_info()
+ */
+ function `Filename()`_aggregator_process_info($feed) {
+ return array(
+ 'title' => t('${1}'),
+ 'description' => t('${2}'),
+ );
+ }
+snippet h_aggregator_remove
+ /**
+ * Implements hook_aggregator_remove()
+ */
+ function `Filename()`_aggregator_remove($feed) {
+ ${1:/* Your code here */}
+ }
+snippet h_overlay_parent_initialize
+ /**
+ * Implements hook_overlay_parent_initialize()
+ */
+ function `Filename()`_overlay_parent_initialize() {
+ ${1:/* Your code here */}
+ }
+snippet h_overlay_child_initialize
+ /**
+ * Implements hook_overlay_child_initialize()
+ */
+ function `Filename()`_overlay_child_initialize() {
+ ${1:/* Your code here */}
+ }
+snippet h_entity_info
+ /**
+ * Implements hook_entity_info()
+ */
+ function `Filename()`_entity_info() {
+ 'node' => array(
+ 'label' => t('${1}'),
+ 'controller class' => '${2}',
+ 'base table' => '${3}',
+ 'revision table' => '${4}',
+ 'uri callback' => '${5}',
+ 'fieldable' => ${6},
+ 'translation' => array(
+ 'locale' => ${7},
+ ),
+ 'entity keys' => array(
+ 'id' => '${8}',
+ 'revision' => '${9}',
+ 'bundle' => '${10}',
+ ),
+ 'bundle keys' => array(
+ 'bundle' => '${11}',
+ ),
+ 'bundles' => array(),
+ 'view modes' => array(
+ '${12}' => array(
+ 'label' => t('${13}'),
+ 'custom settings' => ${14},
+ ),
+ ),
+ ),
+ );
+ return $return;
+ }
+snippet h_entity_info_alter
+ /**
+ * Implements hook_entity_info_alter()
+ */
+ function `Filename()`_entity_info_alter(&$entity_info) {
+ ${1:/* Your code here */}
+ }
+snippet h_entity_load
+ /**
+ * Implements hook_entity_load()
+ */
+ function `Filename()`_entity_load($entities, $type) {
+ foreach ($entities as $entity) {
+ $entity->${1} = mymodule_add_something($entity, $type);
+ }
+ }
+snippet h_entity_insert
+ /**
+ * Implements hook_entity_insert()
+ */
+ function `Filename()`_entity_insert($entity, $type) {
+ ${1:/* Your code here */}
+ }
+snippet h_entity_update
+ /**
+ * Implements hook_entity_update()
+ */
+ function `Filename()`_entity_update($entity, $type) {
+ ${1:/* Your code here */}
+ }
+snippet h_entity_query_alter
+ /**
+ * Implements hook_entity_query_alter()
+ */
+ function `Filename()`_entity_query_alter($query) {
+ $query->${1} = 'my_module_query_callback';
+ }
+snippet h_admin_paths
+ /**
+ * Implements hook_admin_paths()
+ */
+ function `Filename()`_admin_paths() {
+ $paths = array(
+ ${1:/* Your code here */}
+ );
+ return $paths;
+ }
+snippet h_admin_paths_alter
+ /**
+ * Implements hook_admin_paths_alter()
+ */
+ function `Filename()`_admin_paths_alter(&$paths) {
+ $paths['${1}'] = ${2};
+ }
+snippet h_entity_prepare_view
+ /**
+ * Implements hook_entity_prepare_view()
+ */
+ function `Filename()`_entity_prepare_view($entities, $type) {
+ ${1:/* Your code here */}
+ }
+snippet h_cron
+ /**
+ * Implements hook_cron()
+ */
+ function `Filename()`_cron() {
+ ${1:/* Your code here */}
+ }
+snippet h_cron_queue_info
+ /**
+ * Implements hook_cron_queue_info()
+ */
+ function `Filename()`_cron_queue_info() {
+ $queues['${1}'] = array(
+ 'worker callback' => '${2}',
+ 'time' => ${3},
+ );
+ return $queues;
+ }
+snippet h_cron_queue_info_alter
+ /**
+ * Implements hook_cron_queue_info_alter()
+ */
+ function `Filename()`_cron_queue_info_alter(&$queues) {
+ $queues['${1}']['time'] = ${2};
+ }
+snippet h_element_info
+ /**
+ * Implements hook_element_info()
+ */
+ function `Filename()`_element_info() {
+ $types['${1}'] = array(
+ ${2:/* Your code here */}
+ );
+ return $types;
+ }
+snippet h_element_info_alter
+ /**
+ * Implements hook_element_info_alter()
+ */
+ function `Filename()`_element_info_alter(&$type) {
+ if (isset($type['${1}'])) {
+ $type['${2}'] = ${3};
+ }
+ }
+snippet h_exit
+ /**
+ * Implements hook_exit()
+ */
+ function `Filename()`_exit($destination = NULL) {
+ ${1:/* Your code here */}
+ }
+snippet h_js_alter
+ /**
+ * Implements hook_js_alter()
+ */
+ function `Filename()`_js_alter(&$javascript) {
+ ${1:/* Your code here */}
+ }
+snippet h_library
+ /**
+ * Implements hook_library()
+ */
+ function `Filename()`_library() {
+ $libraries['${1}'] = array(
+ 'title' => '${2}',
+ 'website' => '${3}',
+ 'version' => '${4}',
+ 'js' => array(
+ drupal_get_path('module', 'my_module') . '/${5}' => array(),
+ ),
+ 'css' => array(
+ drupal_get_path('module', 'my_module') . '/${6}' => array(
+ 'type' => 'file',
+ 'media' => '${7}',
+ ),
+ ),
+ 'dependencies' => array(
+ array('system', 'ui'),
+ ),
+ );
+ return $libraries;
+ }
+snippet h_library_alter
+ /**
+ * Implements hook_library_alter()
+ */
+ function `Filename()`_library_alter(&$libraries, $module) {
+ ${1:/* Your code here */}
+ }
+snippet h_css_alter
+ /**
+ * Implements hook_css_alter()
+ */
+ function `Filename()`_css_alter(&$css) {
+ ${1:/* Your code here */}
+ }
+snippet h_ajax_render_alter
+ /**
+ * Implements hook_ajax_render_alter()
+ */
+ function `Filename()`_ajax_render_alter($commands) {
+ $commands[] = ${1}
+ }
+snippet h_page_build
+ /**
+ * Implements hook_page_build()
+ */
+ function `Filename()`_page_build(&$page) {
+ $page['${1}']['${2}'] = array(
+ '#markup' => t('${3}'),
+ '#weight' => ${4},
+ );
+ }
+snippet h_menu
+ /**
+ * Implements hook_menu()
+ */
+ function `Filename()`_menu() {
+ $items['${1}'] = array(
+ 'title' => '${2}',
+ 'page callback' => '${3}',
+ 'page arguments' => array('${4}'),
+ 'access arguments' => array('${5}'),
+ 'type' => ${6},
+ 'file' => ${7},
+ );
+
+ return $items;
+ }
+snippet h_menu_alter
+ /**
+ * Implements hook_menu_alter()
+ */
+ function `Filename()`_menu_alter(&$items) {
+ ${1:/* Your code here */}
+ }
+snippet h_menu_link_alter
+ /**
+ * Implements hook_menu_link_alter()
+ */
+ function `Filename()`_menu_link_alter(&$item) {
+ ${1:/* Your code here */}
+ }
+snippet h_translated_menu_link_alter
+ /**
+ * Implements hook_translated_menu_link_alter()
+ */
+ function `Filename()`_translated_menu_link_alter(&$item, $map) {
+ ${1:/* Your code here */}
+ }
+snippet h_menu_link_insert
+ /**
+ * Implements hook_menu_link_insert()
+ */
+ function `Filename()`_menu_link_insert($link) {
+ ${1:/* Your code here */}
+ }
+snippet h_menu_link_update
+ /**
+ * Implements hook_menu_link_update()
+ */
+ function `Filename()`_menu_link_update($link) {
+ ${1:/* Your code here */}
+ }
+snippet h_menu_link_delete
+ /**
+ * Implements hook_menu_link_delete()
+ */
+ function `Filename()`_menu_link_delete($link) {
+ db_delete('${1}')
+ ->condition('mlid', $link['mlid'])
+ ->execute();
+ }
+snippet h_menu_local_tasks_alter
+ /**
+ * Implements hook_menu_local_tasks_alter()
+ */
+ function `Filename()`_menu_local_tasks_alter(&$data, $router_item, $root_path) {
+ ${1:/* Your code here */}
+ }
+snippet h_menu_breadcrumb_alter
+ /**
+ * Implements hook_menu_breadcrumb_alter()
+ */
+ function `Filename()`_menu_breadcrumb_alter(&$active_trail, $item) {
+ ${1:/* Your code here */}
+ }
+snippet h_menu_contextual_links_alter
+ /**
+ * Implements hook_menu_contextual_links_alter()
+ */
+ function `Filename()`_menu_contextual_links_alter(&$links, $router_item, $root_path) {
+ if ($root_path == '${1}') {
+ $links['${2}'] = array(
+ 'title' => t('${3}'),
+ 'href' => '${4}',
+ 'localized_options' => array(
+ 'query' => array(
+ '${5}' => '${6}',
+ ),
+ ),
+ );
+ }
+ }
+snippet h_page_alter
+ /**
+ * Implements hook_page_alter()
+ */
+ function `Filename()`_page_alter(&$page) {
+ ${1:/* Your code here */}
+ }
+snippet h_form_alter
+ /**
+ * Implements hook_form_alter()
+ */
+ function `Filename()`_form_alter(&$form, &$form_state, $form_id) {
+ $form['${1}'] = array(
+ '#type' => '${2}',
+ '#title' => t('${3}'),
+ '#default_value' => $settings['${4}'],
+ '#required' => ${5},
+ '#element_validate' => array('${6}'),
+ '#description' => t('${7}'),
+ '#${8}' => ${9}
+ );
+ }
+snippet h_forms
+ /**
+ * Implements hook_forms()
+ */
+ function `Filename()`_forms($form_id, $args) {
+ $forms['${1}'] = array(
+ 'callback' => '${2}',
+ 'callback arguments' => array('${3}'),
+ );
+
+ return $forms;
+ }
+snippet h_boot
+ /**
+ * Implements hook_boot()
+ */
+ function `Filename()`_boot() {
+ ${1:/* Your code here */}
+ }
+snippet h_init
+ /**
+ * Implements hook_init()
+ */
+ function `Filename()`_init() {
+ ${1:/* Your code here */}
+ }
+snippet h_image_toolkits
+ /**
+ * Implements hook_image_toolkits()
+ */
+ function `Filename()`_image_toolkits() {
+ return array(
+ '${1}' => array(
+ 'title' => t('${2}'),
+ 'available' => TRUE,
+ ),
+ );
+ }
+snippet h_mail_alter
+ /**
+ * Implements hook_mail_alter()
+ */
+ function `Filename()`_mail_alter(&$message) {
+ if ($message['id'] == '${1}') {
+ $message['body'][] = "${2}";
+ }
+ }
+snippet h_module_implements_alter
+ /**
+ * Implements hook_module_implements_alter()
+ */
+ function `Filename()`_module_implements_alter(&$implementations, $hook) {
+ if ($hook == '${1}') {
+ ${2:/* Your code here */}
+ }
+ }
+snippet h_system_info_alter
+ /**
+ * Implements hook_system_info_alter()
+ */
+ function `Filename()`_system_info_alter(&$info, $file, $type) {
+ ${1:/* Your code here */}
+ }
+snippet h_permission
+ /**
+ * Implements hook_permission()
+ */
+ function `Filename()`_permission() {
+ return array(
+ '${1}' => array(
+ 'title' => t('${2}'),
+ 'description' => t('${3}'),
+ ),
+ );
+ }
+snippet h_theme
+ /**
+ * Implements hook_theme()
+ */
+ function `Filename()`_theme($existing, $type, $theme, $path) {
+ return array(
+ '${1}' => array(
+ 'render element' => '${2}',
+ 'file' => '${3}',
+ 'variables' => array('${4}' => NULL, '${5}' => NULL${6}),
+ ),
+ );
+ }
+snippet h_theme_registry_alter
+ /**
+ * Implements hook_theme_registry_alter()
+ */
+ function `Filename()`_theme_registry_alter(&$theme_registry) {
+ ${1:/* Your code here */}
+ }
+snippet h_custom_theme
+ /**
+ * Implements hook_custom_theme()
+ */
+ function `Filename()`_custom_theme() {
+ ${1:/* Your code here */}
+ }
+snippet h_xmlrpc
+ /**
+ * Implements hook_xmlrpc()
+ */
+ function `Filename()`_xmlrpc() {
+ ${1:/* Your code here */}
+ }
+snippet h_xmlrpc_alter
+ /**
+ * Implements hook_xmlrpc_alter()
+ */
+ function `Filename()`_xmlrpc_alter(&$methods) {
+ ${1:/* Your code here */}
+ }
+snippet h_watchdog
+ /**
+ * Implements hook_watchdog()
+ */
+ function `Filename()`_watchdog(array $log_entry) {
+ ${1:/* Your code here */}
+ }
+snippet h_mail
+ /**
+ * Implements hook_mail()
+ */
+ function `Filename()`_mail($key, &$message, $params) {
+ ${1:/* Your code here */}
+ }
+snippet h_flush_caches
+ /**
+ * Implements hook_flush_caches()
+ */
+ function `Filename()`_flush_caches() {
+ return array('${1}');
+ }
+snippet h_modules_installed
+ /**
+ * Implements hook_modules_installed()
+ */
+ function `Filename()`_modules_installed($modules) {
+ ${1:/* Your code here */}
+ }
+snippet h_modules_enabled
+ /**
+ * Implements hook_modules_enabled()
+ */
+ function `Filename()`_modules_enabled($modules) {
+ ${1:/* Your code here */}
+ }
+snippet h_modules_disabled
+ /**
+ * Implements hook_modules_disabled()
+ */
+ function `Filename()`_modules_disabled($modules) {
+ ${1:/* Your code here */}
+ }
+snippet h_modules_uninstalled
+ /**
+ * Implements hook_modules_uninstalled()
+ */
+ function `Filename()`_modules_uninstalled($modules) {
+ foreach ($modules as $module) {
+ db_delete('${1}')
+ ->condition('module', $module)
+ ->execute();
+ }
+ ${2}_cache_rebuild();
+ }
+snippet h_stream_wrappers
+ /**
+ * Implements hook_stream_wrappers()
+ */
+ function `Filename()`_stream_wrappers() {
+ return array(
+ '${1}' => array(
+ 'name' => t('${2}'),
+ 'class' => '${3}',
+ 'description' => t('${4}'),
+ ),
+ )
+ );
+ }
+snippet h_stream_wrappers_alter
+ /**
+ * Implements hook_stream_wrappers_alter()
+ */
+ function `Filename()`_stream_wrappers_alter(&$wrappers) {
+ ${1:/* Your code here */}
+ }
+snippet h_file_load
+ /**
+ * Implements hook_file_load()
+ */
+ function `Filename()`_file_load($files) {
+ ${1:/* Your code here */}
+ }
+snippet h_file_validate
+ /**
+ * Implements hook_file_validate()
+ */
+ function `Filename()`_file_validate(&$file) {
+ $errors = array();
+ if (${1}) {
+ $errors[] = t("${2}");
+ }
+
+ return $errors;
+ }
+snippet h_file_insert
+ /**
+ * Implements hook_file_insert()
+ */
+ function `Filename()`_file_insert($file) {
+ ${1:/* Your code here */}
+ }
+snippet h_file_update
+ /**
+ * Implements hook_file_update()
+ */
+ function `Filename()`_file_update($file) {
+ ${1:/* Your code here */}
+ }
+snippet h_file_copy
+ /**
+ * Implements hook_file_copy()
+ */
+ function `Filename()`_file_copy($file, $source) {
+ ${1:/* Your code here */}
+ }
+snippet h_file_move
+ /**
+ * Implements hook_file_move()
+ */
+ function `Filename()`_file_move($file, $source) {
+ ${1:/* Your code here */}
+ }
+snippet h_file_delete
+ /**
+ * Implements hook_file_delete()
+ */
+ function `Filename()`_file_delete($file) {
+ ${1:/* Your code here */}
+ }
+snippet h_file_download
+ /**
+ * Implements hook_file_download()
+ */
+ function `Filename()`_file_download($uri) {
+ ${1:/* Your code here */}
+ }
+snippet h_file_url_alter
+ /**
+ * Implements hook_file_url_alter()
+ */
+ function `Filename()`_file_url_alter(&$uri) {
+ ${1:/* Your code here */}
+ }
+snippet h_requirements
+ /**
+ * Implements hook_requirements()
+ */
+ function `Filename()`_requirements($phase) {
+ $requirements = array();
+ ${1:/* Your code here */}
+
+ return $requirements;
+ }
+snippet h_schema
+ /**
+ * Implements hook_schema()
+ */
+ function `Filename()`_schema() {
+ $schema['${1}'] = array(
+ 'description' => '${2}',
+ 'fields' => array(
+ '${3}' => array(
+ 'description' => '${4}',
+ 'type' => '${5}',
+ 'unsigned' => ${6},
+ 'not null' => ${7},
+ 'default' => ${8}),
+ ),
+ 'indexes' => array(
+ '${9}' => array('${10}'),
+ ),
+ 'unique keys' => array(
+ '${11}' => array('${12}')
+ ),
+ 'foreign keys' => array(
+ '${13}' => array(
+ 'table' => '${14}',
+ 'columns' => array('${15}' => '${16}'),
+ ),
+ ),
+ 'primary key' => array('${17}'),
+ );
+ return $schema;
+ }
+snippet h_schema_alter
+ /**
+ * Implements hook_schema_alter()
+ */
+ function `Filename()`_schema_alter(&$schema) {
+ ${1:/* Your code here */}
+ }
+snippet h_query_alter
+ /**
+ * Implements hook_query_alter()
+ */
+ function `Filename()`_query_alter(QueryAlterableInterface $query) {
+ if ($query->hasTag('${1}')) {
+ ${2:/* Your code here */}
+ }
+ }
+snippet h_install
+ /**
+ * Implements hook_install()
+ */
+ function `Filename()`_install() {
+ ${1:/* Your code here */}
+ }
+snippet h_update_dependencies
+ /**
+ * Implements hook_update_dependencies()
+ */
+ function `Filename()`_update_dependencies() {
+ $dependencies['${1}']['${2}'] = array(
+ '${3}' => ${4},
+ );
+
+ return $dependencies;
+ }
+snippet h_update_last_removed
+ /**
+ * Implements hook_update_last_removed()
+ */
+ function `Filename()`_update_last_removed() {
+ ${1:/* Your code here */}
+ }
+snippet h_uninstall
+ /**
+ * Implements hook_uninstall()
+ */
+ function `Filename()`_uninstall() {
+ variable_del('${1}');
+ }
+snippet h_enable
+ /**
+ * Implements hook_enable()
+ */
+ function `Filename()`_enable() {
+ ${1:/* Your code here */}
+ }
+snippet h_disable
+ /**
+ * Implements hook_disable()
+ */
+ function `Filename()`_disable() {
+ ${1:/* Your code here */}
+ }
+snippet h_registry_files_alter
+ /**
+ * Implements hook_registry_files_alter()
+ */
+ function `Filename()`_registry_files_alter(&$files, $modules) {
+ ${1:/* Your code here */}
+ }
+snippet h_install_tasks
+ /**
+ * Implements hook_install_tasks()
+ */
+ function `Filename()`_install_tasks() {
+ $tasks = array(
+ ${1:/* Your code here */}
+ );
+ return $tasks;
+ }
+snippet h_drupal_goto_alter
+ /**
+ * Implements hook_drupal_goto_alter()
+ */
+ function `Filename()`_drupal_goto_alter(&$path, &$options, &$http_response_code) {
+ ${1:/* Your code here */}
+ }
+snippet h_html_head_alter
+ /**
+ * Implements hook_html_head_alter()
+ */
+ function `Filename()`_html_head_alter(&$head_elements) {
+ foreach ($head_elements as $key => $element) {
+ ${1:/* Your code here */}
+ }
+ }
+snippet h_install_tasks_alter
+ /**
+ * Implements hook_install_tasks_alter()
+ */
+ function `Filename()`_install_tasks_alter(&$tasks, $install_state) {
+ $tasks['${1}']['${2}'] = '${3}';
+ }
+snippet h_file_mimetype_mapping_alter
+ /**
+ * Implements hook_file_mimetype_mapping_alter()
+ */
+ function `Filename()`_file_mimetype_mapping_alter(&$mapping) {
+ $mapping['${1}']['${2}'] = '${3}';
+ }
+snippet h_action_info
+ /**
+ * Implements hook_action_info()
+ */
+ function `Filename()`_action_info() {
+ return array(
+ '${1}' => array(
+ 'type' => '${2}',
+ 'label' => t('${3}'),
+ 'configurable' => ${4},
+ 'behavior' => array('${5}'),
+ 'triggers' => array('${6}', ${7}),
+ ),
+ );
+ }
+snippet h_actions_delete
+ /**
+ * Implements hook_actions_delete()
+ */
+ function `Filename()`_actions_delete($aid) {
+ db_delete('${1}')
+ ->condition('aid', $aid)
+ ->execute();
+ }
+snippet h_action_info_alter
+ /**
+ * Implements hook_action_info_alter()
+ */
+ function `Filename()`_action_info_alter(&$actions) {
+ $actions['${1}']['${2}'] = t('${3}');
+ }
+snippet h_archiver_info
+ /**
+ * Implements hook_archiver_info()
+ */
+ function `Filename()`_archiver_info() {
+ return array(
+ '${1}' => array(
+ 'class' => '${2}',
+ 'extensions' => array('${3}'${4}),
+ ),
+ );
+ }
+snippet h_archiver_info_alter
+ /**
+ * Implements hook_archiver_info_alter()
+ */
+ function `Filename()`_archiver_info_alter(&$info) {
+ $info['${1}']['${2}'][] = '${3}';
+ }
+snippet h_date_format_types
+ /**
+ * Implements hook_date_format_types()
+ */
+ function `Filename()`_date_format_types() {
+ return array(
+ '${1}' => t('${2}'),
+ );
+ }
+snippet h_date_format_types_alter
+ /**
+ * Implements hook_date_format_types_alter()
+ */
+ function `Filename()`_date_format_types_alter(&$types) {
+ foreach ($types as $type_name => $type) {
+ $types[$type_name]['${1}'] = ${2};
+ }
+ }
+snippet h_date_formats
+ /**
+ * Implements hook_date_formats()
+ */
+ function `Filename()`_date_formats() {
+ return array(
+ array(
+ 'type' => '${1}',
+ 'format' => '${2}',
+ 'locales' => array('${3}'),
+ ),
+ );
+ }
+snippet h_date_formats_alter
+ /**
+ * Implements hook_date_formats_alter()
+ */
+ function `Filename()`_date_formats_alter(&$formats) {
+ foreach ($formats as $id => $format) {
+ $formats[$id]['${1}'][] = '${2}';
+ }
+ }
+snippet h_page_delivery_callback_alter
+ /**
+ * Implements hook_page_delivery_callback_alter()
+ */
+ function `Filename()`_page_delivery_callback_alter(&$callback) {
+ ${1:/* Your code here */}
+ }
+snippet h_system_themes_page_alter
+ /**
+ * Implements hook_system_themes_page_alter()
+ */
+ function `Filename()`_system_themes_page_alter(&$theme_groups) {
+ foreach ($theme_groups as $state => &$group) {
+ foreach ($theme_groups[$state] as &$theme) {
+ ${1:/* Your code here */}
+ }
+ }
+ }
+snippet h_url_inbound_alter
+ /**
+ * Implements hook_url_inbound_alter()
+ */
+ function `Filename()`_url_inbound_alter(&$path, $original_path, $path_language) {
+ ${1:/* Your code here */}
+ }
+snippet h_url_outbound_alter
+ /**
+ * Implements hook_url_outbound_alter()
+ */
+ function `Filename()`_url_outbound_alter(&$path, &$options, $original_path) {
+ ${1:/* Your code here */}
+ }
+snippet h_username_alter
+ /**
+ * Implements hook_username_alter()
+ */
+ function `Filename()`_username_alter(&$name, $account) {
+ ${1:/* Your code here */}
+ }
+snippet h_tokens($type, $tokens, array $data = array(), array $options = array
+ /**
+ * Implements hook_tokens($type, $tokens, array $data = array(), array $options = array()
+ */
+ function `Filename()`_tokens($type, $tokens, array $data = array(), array $options = array()) {
+ $replacements = array();
+ ${1:/* Your code here */}
+
+ return $replacements;
+ }
+snippet h_token_info
+ /**
+ * Implements hook_token_info()
+ */
+ function `Filename()`_token_info() {
+ $type = array(
+ 'name' => t('${1}'),
+ 'description' => t('${2}'),
+ 'needs-data' => '${3}',
+ );
+ $${4}['${5}'] = array(
+ 'name' => t("${6}"),
+ 'description' => t("${7}"),
+ );
+ return array(
+ 'types' => array('${8}' => $type),
+ 'tokens' => array('${9}' => $${10}),
+ );
+ }
+snippet h_batch_alter
+ /**
+ * Implements hook_batch_alter()
+ */
+ function `Filename()`_batch_alter(&$batch) {
+ ${1:/* Your code here */}
+ }
+snippet h_token_info_alter
+ /**
+ * Implements hook_token_info_alter()
+ */
+ function `Filename()`_token_info_alter(&$data) {
+ $data['tokens']['${1}']['${2}'] = array(
+ 'name' => t("${3}"),
+ 'description' => t("${4}"),
+ );
+ }
+snippet h_updater_info
+ /**
+ * Implements hook_updater_info()
+ */
+ function `Filename()`_updater_info() {
+ return array(
+ '${1}' => array(
+ 'class' => '${2}',
+ 'name' => t('${3}'),
+ 'weight' => ${4},
+ ),
+ );
+ }
+snippet h_updater_info_alter
+ /**
+ * Implements hook_updater_info_alter()
+ */
+ function `Filename()`_updater_info_alter(&$updaters) {
+ ${1:/* Your code here */}
+ }
+snippet h_countries_alter
+ /**
+ * Implements hook_countries_alter()
+ */
+ function `Filename()`_countries_alter(&$countries) {
+ ${1:/* Your code here */}
+ }
+snippet h_filetransfer_backends
+ /**
+ * Implements hook_filetransfer_backends()
+ */
+ function `Filename()`_filetransfer_backends() {
+ $backends = array();
+ ${1:/* Your code here */}
+ return $backends;
+ }
+snippet h_menu_site_status_alter
+ /**
+ * Implements hook_menu_site_status_alter()
+ */
+ function `Filename()`_menu_site_status_alter(&$menu_site_status, $path) {
+ ${1:/* Your code here */}
+ }
+snippet h_form_system_theme_settings_alter
+ /**
+ * Implements hook_form_system_theme_settings_alter()
+ */
+ function `Filename()`_form_system_theme_settings_alter(&$form, &$form_state) {
+ $form['${1}'] = array(
+ '#type' => '${2}',
+ '#title' => t('${3}'),
+ '#default_value' => theme_get_setting('${4}'),
+ '#description' => t('${5}'),
+ );
+ }
+snippet h_preprocess
+ /**
+ * Implements hook_preprocess()
+ */
+ function `Filename()`_preprocess(&$variables, $hook) {
+ static $hooks;
+ ${1:/* Your code here */}
+ }
+snippet h_process
+ /**
+ * Implements hook_process()
+ */
+ function `Filename()`_process(&$variables, $hook) {
+ ${1:/* Your code here */}
+ }
+snippet h_themes_enabled
+ /**
+ * Implements hook_themes_enabled()
+ */
+ function `Filename()`_themes_enabled($theme_list) {
+ foreach ($theme_list as $theme) {
+ ${1:/* Your code here */}
+ }
+ }
+snippet h_themes_disabled
+ /**
+ * Implements hook_themes_disabled()
+ */
+ function `Filename()`_themes_disabled($theme_list) {
+ ${1:/* Your code here */}
+ }
+snippet h_file_download_access
+ /**
+ * Implements hook_file_download_access()
+ */
+ function `Filename()`_file_download_access($field, $entity_type, $entity) {
+ ${1:/* Your code here */}
+ }
+snippet h_file_download_access_alter
+ /**
+ * Implements hook_file_download_access_alter()
+ */
+ function `Filename()`_file_download_access_alter(&$grants, $field, $entity_type, $entity) {
+ ${1:/* Your code here */}
+ }
+snippet h_help
+ /**
+ * Implements hook_help()
+ */
+ function `Filename()`_help($path, $arg) {
+ switch ($path) {
+ case '${1}':
+ return '<p>' . t('${2}', array('${3}' => ${4})) . '</p>';
+ }
+ }
+snippet h_comment_presave
+ /**
+ * Implements hook_comment_presave()
+ */
+ function `Filename()`_comment_presave($comment) {
+ ${1:/* Your code here */}
+ }
+snippet h_comment_insert
+ /**
+ * Implements hook_comment_insert()
+ */
+ function `Filename()`_comment_insert($comment) {
+ ${1:/* Your code here */}
+ }
+snippet h_comment_update
+ /**
+ * Implements hook_comment_update()
+ */
+ function `Filename()`_comment_update($comment) {
+ ${1:/* Your code here */}
+ }
+snippet h_comment_load
+ /**
+ * Implements hook_comment_load()
+ */
+ function `Filename()`_comment_load($comments) {
+ ${1:/* Your code here */}
+ }
+snippet h_comment_view
+ /**
+ * Implements hook_comment_view()
+ */
+ function `Filename()`_comment_view($comment, $view_mode, $langcode) {
+ ${1:/* Your code here */}
+ }
+snippet h_comment_view_alter
+ /**
+ * Implements hook_comment_view_alter()
+ */
+ function `Filename()`_comment_view_alter(&$build) {
+ ${1:/* Your code here */}
+ }
+snippet h_comment_publish
+ /**
+ * Implements hook_comment_publish()
+ */
+ function `Filename()`_comment_publish($comment) {
+ ${1:/* Your code here */}
+ }
+snippet h_comment_unpublish
+ /**
+ * Implements hook_comment_unpublish()
+ */
+ function `Filename()`_comment_unpublish($comment) {
+ ${1:/* Your code here */}
+ }
+snippet h_comment_delete
+ /**
+ * Implements hook_comment_delete()
+ */
+ function `Filename()`_comment_delete($comment) {
+ ${1:/* Your code here */}
+ }
+snippet h_update_projects_alter
+ /**
+ * Implements hook_update_projects_alter()
+ */
+ function `Filename()`_update_projects_alter(&$projects) {
+ ${1:/* Your code here */}
+ }
+snippet h_update_status_alter
+ /**
+ * Implements hook_update_status_alter()
+ */
+ function `Filename()`_update_status_alter(&$projects) {
+ ${1:/* Your code here */}
+ }
+snippet h_verify_update_archive
+ /**
+ * Implements hook_verify_update_archive()
+ */
+ function `Filename()`_verify_update_archive($project, $archive_file, $directory) {
+ if (!file_exists($directory)) {
+ return TRUE;
+ }
+ ${1:/* Add other checks on the archive integrity here */}
+ }
+snippet h_node_grants
+ /**
+ * Implements hook_node_grants()
+ */
+ function `Filename()`_node_grants($account, $op) {
+ ${1:/* Your code here */}
+
+ return $grants;
+ }
+snippet h_node_access_records
+ /**
+ * Implements hook_node_access_records()
+ */
+ function `Filename()`_node_access_records($node) {
+ $grants[] = array(
+ 'realm' => '${1}',
+ 'gid' => ${2},
+ 'grant_view' => ${3},
+ 'grant_update' => ${4},
+ 'grant_delete' => ${5},
+ 'priority' => ${6},
+ );
+
+ return $grants;
+ }
+ }
+snippet h_node_access_records_alter
+ /**
+ * Implements hook_node_access_records_alter()
+ */
+ function `Filename()`_node_access_records_alter(&$grants, $node) {
+ ${1:/* Your code here */}
+ }
+snippet h_node_grants_alter
+ /**
+ * Implements hook_node_grants_alter()
+ */
+ function `Filename()`_node_grants_alter(&$grants, $account, $op) {
+ ${1:/* Your code here */}
+ }
+snippet h_node_operations
+ /**
+ * Implements hook_node_operations()
+ */
+ function `Filename()`_node_operations() {
+ $operations = array(
+ '${1}' => array(
+ 'label' => t('${2}'),
+ 'callback' => '${3}',
+ 'callback arguments' => array('${4}' => array('${5}' => ${6})),
+ ),
+ );
+ return $operations;
+ }
+snippet h_node_delete
+ /**
+ * Implements hook_node_delete()
+ */
+ function `Filename()`_node_delete($node) {
+ db_delete('${1}')
+ ->condition('nid', $node->nid)
+ ->execute();
+ }
+snippet h_node_revision_delete
+ /**
+ * Implements hook_node_revision_delete()
+ */
+ function `Filename()`_node_revision_delete($node) {
+ db_delete('${1}')
+ ->condition('vid', $node->vid)
+ ->execute();
+ }
+snippet h_node_insert
+ /**
+ * Implements hook_node_insert()
+ */
+ function `Filename()`_node_insert($node) {
+ db_insert('${1}')
+ ->fields(array(
+ 'nid' => $node->nid,
+ 'extra' => $node->extra,
+ ))
+ ->execute();
+ }
+snippet h_node_load
+ /**
+ * Implements hook_node_load()
+ */
+ function `Filename()`_node_load($nodes, $types) {
+ ${1:/* Your code here */}
+ }
+snippet h_node_access
+ /**
+ * Implements hook_node_access()
+ */
+ function `Filename()`_node_access($node, $op, $account) {
+ $type = is_string($node) ? $node : $node->type;
+ ${1:/* Your code here */}
+ return NODE_ACCESS_IGNORE;
+ }
+snippet h_node_prepare
+ /**
+ * Implements hook_node_prepare()
+ */
+ function `Filename()`_node_prepare($node) {
+ ${1:/* Your code here */}
+ }
+snippet h_node_search_result
+ /**
+ * Implements hook_node_search_result()
+ */
+ function `Filename()`_node_search_result($node) {
+ ${1:/* Your code here */}
+ }
+snippet h_node_presave
+ /**
+ * Implements hook_node_presave()
+ */
+ function `Filename()`_node_presave($node) {
+ ${1:/* Your code here */}
+ }
+snippet h_node_update
+ /**
+ * Implements hook_node_update()
+ */
+ function `Filename()`_node_update($node) {
+ db_update('${1}')
+ ->fields(array('${2}' => ${3})
+ ->condition('nid', $node->nid)
+ ->execute();
+ }
+snippet h_node_update_index
+ /**
+ * Implements hook_node_update_index()
+ */
+ function `Filename()`_node_update_index($node) {
+ ${1:/* Your code here */}
+ }
+snippet h_node_validate
+ /**
+ * Implements hook_node_validate()
+ */
+ function `Filename()`_node_validate($node, $form, &$form_state) {
+ ${1:/* Your code here */}
+ }
+snippet h_node_submit
+ /**
+ * Implements hook_node_submit()
+ */
+ function `Filename()`_node_submit($node, $form, &$form_state) {
+ ${1:/* Your code here */}
+ }
+snippet h_node_view
+ /**
+ * Implements hook_node_view()
+ */
+ function `Filename()`_node_view($node, $view_mode, $langcode) {
+ ${1:/* Your code here */}
+ }
+snippet h_node_view_alter
+ /**
+ * Implements hook_node_view_alter()
+ */
+ function `Filename()`_node_view_alter(&$build) {
+ }
+snippet h_node_info
+ /**
+ * Implements hook_node_info()
+ */
+ function `Filename()`_node_info() {
+ return array(
+ '${1}' => array(
+ 'name' => t('${2}'),
+ 'base' => '${3}',
+ 'description' => t('${4}'),
+ )
+ );
+ }
+snippet h_ranking
+ /**
+ * Implements hook_ranking()
+ */
+ function `Filename()`_ranking() {
+ ${1:/* Your code here */}
+ }
+snippet h_node_type_insert
+ /**
+ * Implements hook_node_type_insert()
+ */
+ function `Filename()`_node_type_insert($info) {
+ ${1:/* Your code here */}
+ }
+snippet h_node_type_update
+ /**
+ * Implements hook_node_type_update()
+ */
+ function `Filename()`_node_type_update($info) {
+ ${1:/* Your code here */}
+ }
+snippet h_node_type_delete
+ /**
+ * Implements hook_node_type_delete()
+ */
+ function `Filename()`_node_type_delete($info) {
+ ${1:/* Your code here */}
+ }
+snippet h_delete
+ /**
+ * Implements hook_delete()
+ */
+ function `Filename()`_delete($node) {
+ db_delete('${1}')
+ ->condition('nid', $nid->nid)
+ ->execute();
+ }
+snippet h_prepare
+ /**
+ * Implements hook_prepare()
+ */
+ function `Filename()`_prepare($node) {
+ ${1:/* Your code here */}
+ }
+snippet h_form
+ /**
+ * Implements hook_form()
+ */
+ function `Filename()`_form($node, &$form_state) {
+ $type = node_type_get_type($node);
+
+ $form['${1}'] = array(
+ '#type' => '${2}',
+ '#title' => t('${3}'),
+ '#default_value' => $node->${4},
+ '#${5}' => ${6},
+ );
+
+ return $form;
+ }
+snippet h_insert
+ /**
+ * Implements hook_insert()
+ */
+ function `Filename()`_insert($node) {
+ db_insert('${1}')
+ ->fields(array(
+ 'nid' => $node->nid,
+ 'extra' => $node->extra,
+ ))
+ ->execute();
+ }
+snippet h_load
+ /**
+ * Implements hook_load()
+ */
+ function `Filename()`_load($nodes) {
+ ${1:/* Your code here */}
+ }
+snippet h_update
+ /**
+ * Implements hook_update()
+ */
+ function `Filename()`_update($node) {
+ db_update('${1}')
+ ->fields(array('extra' => $node->extra))
+ ->condition('nid', $node->nid)
+ ->execute();
+ }
+snippet h_validate
+ /**
+ * Implements hook_validate()
+ */
+ function `Filename()`_validate($node, $form, &$form_state) {
+ ${1:/* Your code here */}
+ }
+snippet h_view
+ /**
+ * Implements hook_view()
+ */
+ function `Filename()`_view($node, $view_mode) {
+ ${1:/* Your code here */}
+
+ return $node;
+ }
+snippet h_block_info
+ /**
+ * Implements hook_block_info()
+ */
+ function `Filename()`_block_info() {
+ $blocks['${1}'] = array(
+ 'info' => t('${2}'),
+ 'cache' => ${3}DRUPAL_NO_CACHE
+ );
+
+ return $blocks;
+ }
+snippet h_block_info_alter
+ /**
+ * Implements hook_block_info_alter()
+ */
+ function `Filename()`_block_info_alter(&$blocks, $theme, $code_blocks) {
+ ${1:/* Your code here */}
+ }
+snippet h_block_configure
+ /**
+ * Implements hook_block_configure()
+ */
+ function `Filename()`_block_configure($delta = '') {
+ $form = array();
+ if ($delta == '${1}') {
+ $form['${2}'] = array(
+ '#type' => '${3}',
+ '#title' => t('${4}'),
+ '#default_value' => variable_get('${5}', ${6}),
+ '#${7}' => ${8},
+ );
+ }
+ return $form;
+ }
+snippet h_block_save($delta = '', $edit = array
+ /**
+ * Implements hook_block_save($delta = '', $edit = array()
+ */
+ function `Filename()`_block_save($delta = '', $edit = array()) {
+ ${1:/* Your code here */}
+ }
+snippet h_block_view
+ /**
+ * Implements hook_block_view()
+ */
+ function `Filename()`_block_view($delta = '') {
+ $block = array();
+
+ switch ($delta) {
+ case '${1}':
+ $block['subject'] = t('${2}');
+ $block['content'] = theme('${3}', array('${4}' =>${5}));
+ break;
+ ${6}
+ }
+ return $block;
+ }
+snippet h_block_view_alter
+ /**
+ * Implements hook_block_view_alter()
+ */
+ function `Filename()`_block_view_alter(&$data, $block) {
+ ${1:/* Your code here */}
+ }
+snippet h_block_list_alter
+ /**
+ * Implements hook_block_list_alter()
+ */
+ function `Filename()`_block_list_alter(&$blocks) {
+ ${1:/* Your code here */}
+ }
+snippet h_user_load
+ /**
+ * Implements hook_user_load()
+ */
+ function `Filename()`_user_load($users) {
+ ${1:/* Your code here */}
+ }
+snippet h_user_delete
+ /**
+ * Implements hook_user_delete()
+ */
+ function `Filename()`_user_delete($account) {
+ db_delete('${1}')
+ ->condition('uid', $account->uid)
+ ->execute();
+ }
+snippet h_user_cancel
+ /**
+ * Implements hook_user_cancel()
+ */
+ function `Filename()`_user_cancel($edit, $account, $method) {
+ switch ($method) {
+ case '${1}':
+ ${2:/* Your code here */}
+ break;
+ }
+ }
+snippet h_user_cancel_methods_alter
+ /**
+ * Implements hook_user_cancel_methods_alter()
+ */
+ function `Filename()`_user_cancel_methods_alter(&$methods) {
+ $methods['${1}']${2}
+ }
+snippet h_user_operations
+ /**
+ * Implements hook_user_operations()
+ */
+ function `Filename()`_user_operations() {
+ $operations = array(
+ '${1}' => array(
+ 'label' => t('${2}'),
+ 'callback' => '${3}',
+ ),
+ );
+ return $operations;
+ }
+snippet h_user_categories
+ /**
+ * Implements hook_user_categories()
+ */
+ function `Filename()`_user_categories() {
+ return array(array(
+ 'name' => '${1}',
+ 'title' => t('${2}'),
+ 'weight' => ${3},
+ ));
+ }
+snippet h_user_presave
+ /**
+ * Implements hook_user_presave()
+ */
+ function `Filename()`_user_presave(&$edit, $account, $category) {
+ ${1:/* your code here */}
+ }
+snippet h_user_insert
+ /**
+ * Implements hook_user_insert()
+ */
+ function `Filename()`_user_insert(&$edit, $account, $category) {
+ db_insert('${1}')
+ ->fields(array(
+ '${2}' => $edit['${3}'],
+ 'uid' => $account->uid,
+ ))
+ ->execute();
+ }
+snippet h_user_update
+ /**
+ * Implements hook_user_update()
+ */
+ function `Filename()`_user_update(&$edit, $account, $category) {
+ db_insert('${1}')
+ ->fields(array(
+ 'uid' => $account->uid,
+ 'changed' => time(),
+ ))
+ ->execute();
+ }
+snippet h_user_login
+ /**
+ * Implements hook_user_login()
+ */
+ function `Filename()`_user_login(&$edit, $account) {
+ ${1:/* Your code here */}
+ }
+snippet h_user_logout
+ /**
+ * Implements hook_user_logout()
+ */
+ function `Filename()`_user_logout($account) {
+ db_insert('${1}')
+ ->fields(array(
+ 'uid' => $account->uid,
+ 'time' => time(),
+ ))
+ ->execute();
+ }
+snippet h_user_view
+ /**
+ * Implements hook_user_view()
+ */
+ function `Filename()`_user_view($account, $view_mode, $langcode) {
+ ${1:/* Your code here */}
+ }
+snippet h_user_view_alter
+ /**
+ * Implements hook_user_view_alter()
+ */
+ function `Filename()`_user_view_alter(&$build) {
+ ${1:/* Your code here */}
+ }
+snippet h_user_role_insert
+ /**
+ * Implements hook_user_role_insert()
+ */
+ function `Filename()`_user_role_insert($role) {
+ db_insert('${1}')
+ ->fields(array(
+ 'rid' => $role->rid,
+ 'role_description' => $role->description,
+ ))
+ ->execute();
+ }
+snippet h_user_role_update
+ /**
+ * Implements hook_user_role_update()
+ */
+ function `Filename()`_user_role_update($role) {
+ db_merge('${1}')
+ ->key(array('rid' => $role->rid))
+ ->fields(array(
+ 'role_description' => $role->description
+ ))
+ ->execute();
+ }
+snippet h_user_role_delete
+ /**
+ * Implements hook_user_role_delete()
+ */
+ function `Filename()`_user_role_delete($role) {
+ db_delete('${1}')
+ ->condition('rid', $role->rid)
+ ->execute();
+ }
+snippet h_taxonomy_vocabulary_load
+ /**
+ * Implements hook_taxonomy_vocabulary_load()
+ */
+ function `Filename()`_taxonomy_vocabulary_load($vocabularies) {
+ foreach ($vocabularies as $vocabulary) {
+ ${1:/* Your code here */}
+ }
+ }
+snippet h_taxonomy_vocabulary_presave
+ /**
+ * Implements hook_taxonomy_vocabulary_presave()
+ */
+ function `Filename()`_taxonomy_vocabulary_presave($vocabulary) {
+ ${1:/* Your code here */}
+ }
+snippet h_taxonomy_vocabulary_insert
+ /**
+ * Implements hook_taxonomy_vocabulary_insert()
+ */
+ function `Filename()`_taxonomy_vocabulary_insert($vocabulary) {
+ ${1:/* Your code here */}
+ }
+snippet h_taxonomy_vocabulary_update
+ /**
+ * Implements hook_taxonomy_vocabulary_update()
+ */
+ function `Filename()`_taxonomy_vocabulary_update($vocabulary) {
+ ${1:/* Your code here */}
+ }
+snippet h_taxonomy_vocabulary_delete
+ /**
+ * Implements hook_taxonomy_vocabulary_delete()
+ */
+ function `Filename()`_taxonomy_vocabulary_delete($vocabulary) {
+ ${1:/* Your code here */}
+ }
+snippet h_taxonomy_term_load
+ /**
+ * Implements hook_taxonomy_term_load()
+ */
+ function `Filename()`_taxonomy_term_load($terms) {
+ ${1:/* Your code here */}
+ }
+snippet h_taxonomy_term_presave
+ /**
+ * Implements hook_taxonomy_term_presave()
+ */
+ function `Filename()`_taxonomy_term_presave($term) {
+ ${1:/* Your code here */}
+ }
+snippet h_taxonomy_term_insert
+ /**
+ * Implements hook_taxonomy_term_insert()
+ */
+ function `Filename()`_taxonomy_term_insert($term) {
+ ${1:/* Your code here */}
+ }
+snippet h_taxonomy_term_update
+ /**
+ * Implements hook_taxonomy_term_update()
+ */
+ function `Filename()`_taxonomy_term_update($term) {
+ ${1:/* Your code here */}
+ }
+snippet h_taxonomy_term_delete
+ /**
+ * Implements hook_taxonomy_term_delete()
+ */
+ function `Filename()`_taxonomy_term_delete($term) {
+ ${1:/* Your code here */}
+ }
+snippet h_openid
+ /**
+ * Implements hook_openid()
+ */
+ function `Filename()`_openid($op, $request) {
+ ${1:/* Your code here */}
+
+ return $request;
+ }
+snippet h_openid_response
+ /**
+ * Implements hook_openid_response()
+ */
+ function `Filename()`_openid_response($response, $account) {
+ ${1:/* Your code here */}
+ }
+snippet h_openid_discovery_method_info
+ /**
+ * Implements hook_openid_discovery_method_info()
+ */
+ function `Filename()`_openid_discovery_method_info() {
+ return array(
+ '${1}' => '${2}',
+ );
+ }
+snippet h_openid_discovery_method_info_alter
+ /**
+ * Implements hook_openid_discovery_method_info_alter()
+ */
+ function `Filename()`_openid_discovery_method_info_alter(&$methods) {
+ ${1:/* Your code here */}
+ }
+snippet h_openid_normalization_method_info
+ /**
+ * Implements hook_openid_normalization_method_info()
+ */
+ function `Filename()`_openid_normalization_method_info() {
+ return array(
+ '${1}' => '${2}',
+ );
+ }
+snippet h_openid_normalization_method_info_alter
+ /**
+ * Implements hook_openid_normalization_method_info_alter()
+ */
+ function `Filename()`_openid_normalization_method_info_alter(&$methods) {
+ ${1:/* Your code here */}
+ }
+snippet h_filter_info
+ /**
+ * Implements hook_filter_info()
+ */
+ function `Filename()`_filter_info() {
+ $filters['${1}'] = array(
+ 'title' => t('${2}'),
+ 'description' => t('${3}'),
+ 'process callback' => '${4}',
+ 'settings callback' => '${5}',
+ 'default settings' => array(
+ 'allowed_html' => '${6}',
+ 'filter_html_help' => ${7},
+ 'filter_html_nofollow' => ${8},
+ ),
+ 'tips callback' => '${9}',
+ );
+ return $filters;
+ }
+snippet h_filter_info_alter
+ /**
+ * Implements hook_filter_info_alter()
+ */
+ function `Filename()`_filter_info_alter(&$info) {
+ ${1:/* Your code here */}
+ }
+snippet h_filter_format_insert
+ /**
+ * Implements hook_filter_format_insert()
+ */
+ function `Filename()`_filter_format_insert($format) {
+ ${1:/* Your code here */}
+ }
+snippet h_filter_format_update
+ /**
+ * Implements hook_filter_format_update()
+ */
+ function `Filename()`_filter_format_update($format) {
+ ${1:/* Your code here */}
+ }
+snippet h_filter_format_disable
+ /**
+ * Implements hook_filter_format_disable()
+ */
+ function `Filename()`_filter_format_disable($format) {
+ ${1:/* Your code here */}
+ }
+snippet h_rdf_mapping
+ /**
+ * Implements hook_rdf_mapping()
+ */
+ function `Filename()`_rdf_mapping() {
+ return array(
+ array(
+ 'type' => '${1}',
+ 'bundle' => '${2}',
+ 'mapping' => array(
+ 'rdftype' => array('${3}'),
+ 'title' => array(
+ 'predicates' => array('${4}'),
+ ),
+ 'created' => array(
+ 'predicates' => array('${5}'),
+ 'datatype' => '${6}',
+ 'callback' => '${7}',
+ ),
+ 'body' => array(
+ 'predicates' => array('${8}'),
+ ),
+ 'uid' => array(
+ 'predicates' => array('${9}'),
+ 'type' => '${10}',
+ ),
+ 'name' => array(
+ 'predicates' => array('${11}'),
+ ),
+ ),
+ ),
+ );
+ }
+snippet h_rdf_namespaces
+ /**
+ * Implements hook_rdf_namespaces()
+ */
+ function `Filename()`_rdf_namespaces() {
+ return array(
+ '${1}' => '${2}',
+ );
+ }
+snippet h_field_settings_form
+ /**
+ * Implements hook_field_settings_form()
+ */
+ function `Filename()`_field_settings_form($field, $instance, $has_data) {
+ $settings = $field['settings'];
+ $form['${1}'] = array(
+ '#type' => '${2}',
+ '#title' => t('${3}'),
+ '#default_value' => $settings['${4}'],
+ '#required' => ${5},
+ '#element_validate' => array('${6}'),
+ '#description' => t('${7}'),
+ '#${8}' => ${9}
+ );
+ return $form;
+ }
+snippet h_field_instance_settings_form
+ /**
+ * Implements hook_field_instance_settings_form()
+ */
+ function `Filename()`_field_instance_settings_form($field, $instance) {
+ $settings = $instance['settings'];
+ $form['${1}'] = array(
+ '#type' => '${2}',
+ '#title' => t('${3}'),
+ '#default_value' => $settings['${4}'],
+ '#required' => ${5},
+ '#element_validate' => array('${6}'),
+ '#description' => t('${7}'),
+ '#${8}' => ${9}
+ );
+ return $form;
+ }
+snippet h_field_widget_settings_form
+ /**
+ * Implements hook_field_widget_settings_form()
+ */
+ function `Filename()`_field_widget_settings_form($field, $instance) {
+ $widget = $instance['widget'];
+ $settings = $widget['settings'];
+ $form['${1}'] = array(
+ '#type' => '${2}',
+ '#title' => t('${3}'),
+ '#default_value' => $settings['${4}'],
+ '#required' => ${5},
+ '#element_validate' => array('${6}'),
+ '#description' => t('${7}'),
+ '#${8}' => ${9}
+ );
+ return $form;
+ }
+snippet h_field_formatter_settings_form
+ /**
+ * Implements hook_field_formatter_settings_form()
+ */
+ function `Filename()`_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
+ $display = $instance['display'][$view_mode];
+ $settings = $display['settings'];
+ $element['${1}'] = array(
+ '#type' => '${2}',
+ '#title' => t('${3}'),
+ '#default_value' => $settings['${4}'],
+ '#required' => ${5},
+ '#element_validate' => array('${6}'),
+ '#description' => t('${7}'),
+ '#${8}' => ${9}
+ );
+
+ return $element;
+
+ }
+snippet h_field_formatter_settings_summary
+ /**
+ * Implements hook_field_formatter_settings_summary()
+ */
+ function `Filename()`_field_formatter_settings_summary($field, $instance, $view_mode) {
+ ${1:/* Your code here */}
+
+ return $summary;
+ }
+snippet h_field_extra_fields
+ /**
+ * Implements hook_field_extra_fields()
+ */
+ function `Filename()`_field_extra_fields() {
+ $extra['${1}']['${2}'] = array(
+ 'form' => array(
+ '${3}' => array(
+ 'label' => t('${4}'),
+ 'description' => t('${5}'),
+ 'weight' => ${6},
+ ),
+ ),
+ 'display' => array(
+ '${7}' => array(
+ 'label' => t('${8}'),
+ 'description' => t('${9}'),
+ 'weight' => ${10},
+ ),
+ )
+ );
+
+ return $extra;
+ }
+snippet h_field_extra_fields_alter
+ /**
+ * Implements hook_field_extra_fields_alter()
+ */
+ function `Filename()`_field_extra_fields_alter(&$info) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_info
+ /**
+ * Implements hook_field_info()
+ */
+ function `Filename()`_field_info() {
+ return array(
+ '${1}' => array(
+ 'label' => t('${2}'),
+ 'description' => t('${3}'),
+ 'settings' => array('${4}' => ${5}),
+ 'instance_settings' => array('${6}' => ${7}),
+ 'default_widget' => '${8}',
+ 'default_formatter' => '${9}',
+ ),
+ );
+ }
+snippet h_field_info_alter
+ /**
+ * Implements hook_field_info_alter()
+ */
+ function `Filename()`_field_info_alter(&$info) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_schema
+ /**
+ * Implements hook_field_schema()
+ */
+ function `Filename()`_field_schema($field) {
+ $columns = array(
+ '${1}' => array(
+ 'type' => '${2}',
+ 'length' => ${3},
+ 'unsigned' => ${4},
+ 'not null' => ${5},
+ ),
+ );
+ $columns = array(
+ '${6}' => array(
+ 'type' => '${7}',
+ 'length' => ${8},
+ 'unsigned' => ${9},
+ 'not null' => ${10},
+ ),
+ );
+ return array(
+ 'columns' => $columns,
+ 'indexes' => array(
+ '${11}' => array('${12}'),
+ ),
+ );
+ }
+snippet h_field_load
+ /**
+ * Implements hook_field_load()
+ */
+ function `Filename()`_field_load($entity_type, $entities, $field, $instances, $langcode, &$items, $age) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_prepare_view
+ /**
+ * Implements hook_field_prepare_view()
+ */
+ function `Filename()`_field_prepare_view($entity_type, $entities, $field, $instances, $langcode, &$items) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_validate
+ /**
+ * Implements hook_field_validate()
+ */
+ function `Filename()`_field_validate($entity_type, $entity, $field, $instance, $langcode, $items, &$errors) {
+ foreach ($items as $delta => $item) {
+ if (!empty($item['value'])) {
+ ${1:/* Your code here */}
+ }
+ }
+ }
+snippet h_field_presave
+ /**
+ * Implements hook_field_presave()
+ */
+ function `Filename()`_field_presave($entity_type, $entity, $field, $instance, $langcode, &$items) {
+ if ($field['type'] == '${1}') {
+ foreach ($items as $delta => $item) {
+ ${1:/* Your code here */}
+ }
+ }
+ }
+snippet h_field_insert
+ /**
+ * Implements hook_field_insert()
+ */
+ function `Filename()`_field_insert($entity_type, $entity, $field, $instance, $langcode, &$items) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_update
+ /**
+ * Implements hook_field_update()
+ */
+ function `Filename()`_field_update($entity_type, $entity, $field, $instance, $langcode, &$items) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_storage_update_field
+ /**
+ * Implements hook_field_storage_update_field()
+ */
+ function `Filename()`_field_storage_update_field($field, $prior_field, $has_data) {
+ if (!$has_data) {
+ ${1:/* Your code here */}
+ }
+ else {
+ ${2:/* Your code here */}
+ }
+ drupal_get_schema(NULL, TRUE);
+ }
+snippet h_field_delete
+ /**
+ * Implements hook_field_delete()
+ */
+ function `Filename()`_field_delete($entity_type, $entity, $field, $instance, $langcode, &$items) {
+ list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
+ foreach ($items as $delta => $item) {
+ ${1:/* Your code here */}
+ }
+ }
+snippet h_field_delete_revision
+ /**
+ * Implements hook_field_delete_revision()
+ */
+ function `Filename()`_field_delete_revision($entity_type, $entity, $field, $instance, $langcode, &$items) {
+ foreach ($items as $delta => $item) {
+ ${1:/* Your code here */}
+ }
+ }
+snippet h_field_prepare_translation
+ /**
+ * Implements hook_field_prepare_translation()
+ */
+ function `Filename()`_field_prepare_translation($entity_type, $entity, $field, $instance, $langcode, &$items, $source_entity, $source_langcode) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_is_empty
+ /**
+ * Implements hook_field_is_empty()
+ */
+ function `Filename()`_field_is_empty($item, $field) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_widget_info
+ /**
+ * Implements hook_field_widget_info()
+ */
+ function `Filename()`_field_widget_info() {
+ return array(
+ '${1}' => array(
+ 'label' => t('${2}'),
+ 'field types' => array('${3}'),
+ 'settings' => array('${4}' => ${5}),
+ 'behaviors' => array(
+ 'multiple values' => ${6}FIELD_BEHAVIOR_DEFAULT,
+ 'default value' => ${7}FIELD_BEHAVIOR_DEFAULT,
+ ),
+ ),
+ );
+ }
+snippet h_field_widget_info_alter
+ /**
+ * Implements hook_field_widget_info_alter()
+ */
+ function `Filename()`_field_widget_info_alter(&$info) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_widget_form
+ /**
+ * Implements hook_field_widget_form()
+ */
+ function `Filename()`_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
+ $element += array(
+ '#type' => ${1},
+ '#default_value' => ${2},
+ );
+ return $element;
+ }
+snippet h_field_widget_error
+ /**
+ * Implements hook_field_widget_error()
+ */
+ function `Filename()`_field_widget_error($element, $error, $form, &$form_state) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_formatter_info
+ /**
+ * Implements hook_field_formatter_info()
+ */
+ function `Filename()`_field_formatter_info() {
+ return array(
+ '${1}' => array(
+ 'label' => t('${2}'),
+ 'field types' => array('${3}'),
+ ),
+ );
+ }
+snippet h_field_formatter_info_alter
+ /**
+ * Implements hook_field_formatter_info_alter()
+ */
+ function `Filename()`_field_formatter_info_alter(&$info) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_formatter_prepare_view
+ /**
+ * Implements hook_field_formatter_prepare_view()
+ */
+ function `Filename()`_field_formatter_prepare_view($entity_type, $entities, $field, $instances, $langcode, &$items, $displays) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_formatter_view
+ /**
+ * Implements hook_field_formatter_view()
+ */
+ function `Filename()`_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
+ $element = array();
+ $settings = $display['settings'];
+
+ switch ($display['type']) {
+ case '${1}':
+ foreach ($items as $delta => $item) {
+ $element[$delta] = array(
+ '#theme' => '${2}',
+ '#data' => $item['value'],
+ '#markup' => ${3},
+ '#${4}' => $settings['${5}'],
+ );
+ }
+ break;
+ }
+
+ return $element;
+ }
+snippet h_field_attach_form
+ /**
+ * Implements hook_field_attach_form()
+ */
+ function `Filename()`_field_attach_form($entity_type, $entity, &$form, &$form_state, $langcode) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_attach_load
+ /**
+ * Implements hook_field_attach_load()
+ */
+ function `Filename()`_field_attach_load($entity_type, &$entities, $age, $options) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_attach_validate
+ /**
+ * Implements hook_field_attach_validate()
+ */
+ function `Filename()`_field_attach_validate($entity_type, $entity, &$errors) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_attach_submit
+ /**
+ * Implements hook_field_attach_submit()
+ */
+ function `Filename()`_field_attach_submit($entity_type, $entity, $form, &$form_state) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_attach_presave
+ /**
+ * Implements hook_field_attach_presave()
+ */
+ function `Filename()`_field_attach_presave($entity_type, $entity) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_attach_insert
+ /**
+ * Implements hook_field_attach_insert()
+ */
+ function `Filename()`_field_attach_insert($entity_type, $entity) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_attach_update
+ /**
+ * Implements hook_field_attach_update()
+ */
+ function `Filename()`_field_attach_update($entity_type, $entity) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_attach_preprocess_alter
+ /**
+ * Implements hook_field_attach_preprocess_alter()
+ */
+ function `Filename()`_field_attach_preprocess_alter(&$variables, $context) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_attach_delete
+ /**
+ * Implements hook_field_attach_delete()
+ */
+ function `Filename()`_field_attach_delete($entity_type, $entity) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_attach_delete_revision
+ /**
+ * Implements hook_field_attach_delete_revision()
+ */
+ function `Filename()`_field_attach_delete_revision($entity_type, $entity) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_attach_purge
+ /**
+ * Implements hook_field_attach_purge()
+ */
+ function `Filename()`_field_attach_purge($entity_type, $entity, $field, $instance) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_attach_view_alter
+ /**
+ * Implements hook_field_attach_view_alter()
+ */
+ function `Filename()`_field_attach_view_alter(&$output, $context) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_attach_prepare_translation_alter
+ /**
+ * Implements hook_field_attach_prepare_translation_alter()
+ */
+ function `Filename()`_field_attach_prepare_translation_alter(&$entity, $context) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_language_alter
+ /**
+ * Implements hook_field_language_alter()
+ */
+ function `Filename()`_field_language_alter(&$display_language, $context) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_available_languages_alter
+ /**
+ * Implements hook_field_available_languages_alter()
+ */
+ function `Filename()`_field_available_languages_alter(&$languages, $context) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_attach_create_bundle
+ /**
+ * Implements hook_field_attach_create_bundle()
+ */
+ function `Filename()`_field_attach_create_bundle($entity_type, $bundle) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_attach_rename_bundle
+ /**
+ * Implements hook_field_attach_rename_bundle()
+ */
+ function `Filename()`_field_attach_rename_bundle($entity_type, $bundle_old, $bundle_new) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_attach_delete_bundle
+ /**
+ * Implements hook_field_attach_delete_bundle()
+ */
+ function `Filename()`_field_attach_delete_bundle($entity_type, $bundle, $instances) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_storage_info
+ /**
+ * Implements hook_field_storage_info()
+ */
+ function `Filename()`_field_storage_info() {
+ return array(
+ '${1}' => array(
+ 'label' => t('${2}'),
+ 'description' => t('${3}'),
+ 'settings' => array('${4}'${5}),
+ ),
+ );
+ }
+snippet h_field_storage_info_alter
+ /**
+ * Implements hook_field_storage_info_alter()
+ */
+ function `Filename()`_field_storage_info_alter(&$info) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_storage_details
+ /**
+ * Implements hook_field_storage_details()
+ */
+ function `Filename()`_field_storage_details($field) {
+ $details = array();
+ ${1:/* Your code here */}
+ }
+snippet h_field_storage_details_alter
+ /**
+ * Implements hook_field_storage_details_alter()
+ */
+ function `Filename()`_field_storage_details_alter(&$details, $field) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_storage_load
+ /**
+ * Implements hook_field_storage_load()
+ */
+ function `Filename()`_field_storage_load($entity_type, &$entities, $age, $fields, $options) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_storage_write
+ /**
+ * Implements hook_field_storage_write()
+ */
+ function `Filename()`_field_storage_write($entity_type, $entity, $op, $fields) {
+ list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
+ $etid = _field_sql_storage_etid($entity_type);
+
+ foreach ($fields as $field_id) {
+ ${1:/* Your code here */}
+ }
+ }
+snippet h_field_storage_delete
+ /**
+ * Implements hook_field_storage_delete()
+ */
+ function `Filename()`_field_storage_delete($entity_type, $entity, $fields) {
+ list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
+ $etid = _field_sql_storage_etid($entity_type);
+
+ foreach (field_info_instances($entity_type, $bundle) as $instance) {
+ ${1:/* Your code here */}
+ }
+ }
+snippet h_field_storage_delete_revision
+ /**
+ * Implements hook_field_storage_delete_revision()
+ */
+ function `Filename()`_field_storage_delete_revision($entity_type, $entity, $fields) {
+ list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
+ $etid = _field_sql_storage_etid($entity_type);
+
+ if (isset($vid)) {
+ foreach ($fields as $field_id) {
+ ${1:/* Your code here */}
+ }
+ }
+ }
+snippet h_field_storage_query
+ /**
+ * Implements hook_field_storage_query()
+ */
+ function `Filename()`_field_storage_query($query) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_storage_create_field
+ /**
+ * Implements hook_field_storage_create_field()
+ */
+ function `Filename()`_field_storage_create_field($field) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_storage_delete_field
+ /**
+ * Implements hook_field_storage_delete_field()
+ */
+ function `Filename()`_field_storage_delete_field($field) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_storage_delete_instance
+ /**
+ * Implements hook_field_storage_delete_instance()
+ */
+ function `Filename()`_field_storage_delete_instance($instance) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_storage_pre_load
+ /**
+ * Implements hook_field_storage_pre_load()
+ */
+ function `Filename()`_field_storage_pre_load($entity_type, $entities, $age, &$skip_fields, $options) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_storage_pre_insert
+ /**
+ * Implements hook_field_storage_pre_insert()
+ */
+ function `Filename()`_field_storage_pre_insert($entity_type, $entity, &$skip_fields) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_storage_pre_update
+ /**
+ * Implements hook_field_storage_pre_update()
+ */
+ function `Filename()`_field_storage_pre_update($entity_type, $entity, &$skip_fields) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_info_max_weight
+ /**
+ * Implements hook_field_info_max_weight()
+ */
+ function `Filename()`_field_info_max_weight($entity_type, $bundle, $context) {
+ $weights = array();
+ ${1:/* Your code here */}
+
+ return $weights ? max($weights) : NULL;
+ }
+snippet h_field_display_alter
+ /**
+ * Implements hook_field_display_alter()
+ */
+ function `Filename()`_field_display_alter(&$display, $context) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_display_ENTITY_TYPE_alter
+ /**
+ * Implements hook_field_display_ENTITY_TYPE_alter()
+ */
+ function `Filename()`_field_display_ENTITY_TYPE_alter(&$display, $context) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_extra_fields_display_alter
+ /**
+ * Implements hook_field_extra_fields_display_alter()
+ */
+ function `Filename()`_field_extra_fields_display_alter(&$displays, $context) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_create_field
+ /**
+ * Implements hook_field_create_field()
+ */
+ function `Filename()`_field_create_field($field) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_create_instance
+ /**
+ * Implements hook_field_create_instance()
+ */
+ function `Filename()`_field_create_instance($instance) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_update_forbid
+ /**
+ * Implements hook_field_update_forbid()
+ */
+ function `Filename()`_field_update_forbid($field, $prior_field, $has_data) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_update_field
+ /**
+ * Implements hook_field_update_field()
+ */
+ function `Filename()`_field_update_field($field, $prior_field, $has_data) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_delete_field
+ /**
+ * Implements hook_field_delete_field()
+ */
+ function `Filename()`_field_delete_field($field) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_update_instance
+ /**
+ * Implements hook_field_update_instance()
+ */
+ function `Filename()`_field_update_instance($instance, $prior_instance) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_delete_instance
+ /**
+ * Implements hook_field_delete_instance()
+ */
+ function `Filename()`_field_delete_instance($instance) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_read_field
+ /**
+ * Implements hook_field_read_field()
+ */
+ function `Filename()`_field_read_field(&$field) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_read_instance
+ /**
+ * Implements hook_field_read_instance()
+ */
+ function `Filename()`_field_read_instance($instance) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_purge_field
+ /**
+ * Implements hook_field_purge_field()
+ */
+ function `Filename()`_field_purge_field($field) {
+ db_delete('${1}')
+ ->condition('id', $field['id'])
+ ->execute();
+ }
+snippet h_field_purge_field_instance
+ /**
+ * Implements hook_field_purge_field_instance()
+ */
+ function `Filename()`_field_purge_field_instance($instance) {
+ db_delete('${1}')
+ ->condition('id', $instance['id'])
+ ->execute();
+ }
+snippet h_field_storage_purge_field
+ /**
+ * Implements hook_field_storage_purge_field()
+ */
+ function `Filename()`_field_storage_purge_field($field) {
+ ${1:/* Your code here */}
+ }
+snippet h_field_storage_purge_field_instance
+ /**
+ * Implements hook_field_storage_purge_field_instance()
+ */
+ function `Filename()`_field_storage_purge_field_instance($instance) {
+ db_delete('${1}')
+ ->condition('id', $instance['id'])
+ ->execute();
+ }
+snippet h_field_storage_purge
+ /**
+ * Implements hook_field_storage_purge()
+ */
+ function `Filename()`_field_storage_purge($entity_type, $entity, $field, $instance) {
+ list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
+ ${1:/* Your code here */}
+ }
+snippet h_field_access
+ /**
+ * Implements hook_field_access()
+ */
+ function `Filename()`_field_access($op, $field, $entity_type, $entity, $account) {
+ ${1:/* Your code here */}
+ return TRUE;
+ }
+snippet h_options_list
+ /**
+ * Implements hook_options_list()
+ */
+ function `Filename()`_options_list($field) {
+ $options = array(
+ ${1} => ${2},
+ );
+
+ return $options;
+ }
+snippet h_contextual_links_view_alter
+ /**
+ * Implements hook_contextual_links_view_alter()
+ */
+ function `Filename()`_contextual_links_view_alter(&$element, $items) {
+ ${1:/* Your code here */}
+ }
+snippet h_dashboard_regions
+ /**
+ * Implements hook_dashboard_regions()
+ */
+ function `Filename()`_dashboard_regions() {
+ ${1:/* Your code here */}
+ }
+snippet h_dashboard_regions_alter
+ /**
+ * Implements hook_dashboard_regions_alter()
+ */
+ function `Filename()`_dashboard_regions_alter($regions) {
+ ${1:/* Your code here */}
+ }
+snippet h_menu_insert
+ /**
+ * Implements hook_menu_insert()
+ */
+ function `Filename()`_menu_insert($menu) {
+ ${1:/* Your code here */}
+ }
+snippet h_menu_update
+ /**
+ * Implements hook_menu_update()
+ */
+ function `Filename()`_menu_update($menu) {
+ ${1:/* Your code here */}
+ }
+snippet h_menu_delete
+ /**
+ * Implements hook_menu_delete()
+ */
+ function `Filename()`_menu_delete($menu) {
+ ${1:/* Your code here */}
+ }
+snippet h_path_insert
+ /**
+ * Implements hook_path_insert()
+ */
+ function `Filename()`_path_insert($path) {
+ ${1:/* Your code here */}
+ }
+snippet h_path_update
+ /**
+ * Implements hook_path_update()
+ */
+ function `Filename()`_path_update($path) {
+ ${1:/* Your code here */}
+ }
+snippet h_path_delete
+ /**
+ * Implements hook_path_delete()
+ */
+ function `Filename()`_path_delete($path) {
+ ${1:/* Your code here */}
+ }
+snippet h_shortcut_default_set
+ /**
+ * Implements hook_shortcut_default_set()
+ */
+ function `Filename()`_shortcut_default_set($account) {
+ ${1:/* Your code here */}
+ }
+snippet h_image_effect_info
+ /**
+ * Implements hook_image_effect_info()
+ */
+ function `Filename()`_image_effect_info() {
+ $effects = array();
+
+ $effects['${1}'] = array(
+ 'label' => t('${2}'),
+ 'help' => t('${3}'),
+ 'effect callback' => '${4}',
+ 'form callback' => '${5}',
+ 'summary theme' => '${6}',
+ );
+
+ return $effects;
+ }
+snippet h_image_effect_info_alter
+ /**
+ * Implements hook_image_effect_info_alter()
+ */
+ function `Filename()`_image_effect_info_alter(&$effects) {
+ ${1:/* Your code here */}
+ }
+snippet h_image_style_save
+ /**
+ * Implements hook_image_style_save()
+ */
+ function `Filename()`_image_style_save($style) {
+ ${1:/* Your code here */}
+ }
+snippet h_image_style_delete
+ /**
+ * Implements hook_image_style_delete()
+ */
+ function `Filename()`_image_style_delete($style) {
+ ${1:/* Your code here */}
+ }
+snippet h_image_style_flush
+ /**
+ * Implements hook_image_style_flush()
+ */
+ function `Filename()`_image_style_flush($style) {
+ ${1:/* Your code here */}
+ }
+snippet h_image_styles_alter
+ /**
+ * Implements hook_image_styles_alter()
+ */
+ function `Filename()`_image_styles_alter(&$styles) {
+ ${1:/* Your code here */}
+ }
+snippet h_image_default_styles
+ /**
+ * Implements hook_image_default_styles()
+ */
+ function `Filename()`_image_default_styles() {
+ $styles = array();
+
+ $styles['${1}'] = array(
+ 'effects' => array(
+ array(
+ 'name' => '${2}',
+ 'data' => array('width' => ${3}, 'height' => ${4}, 'upscale' => ${5}),
+ 'weight' => ${6},
+ ),
+ ),
+ );
+
+ return $styles;
+ }
+snippet h_trigger_info
+ /**
+ * Implements hook_trigger_info()
+ */
+ function `Filename()`_trigger_info() {
+ return array(
+ '${1}' => array(
+ '${2}' => array(
+ 'label' => t('${3}'),
+ ),
+ ),
+ );
+ }
+snippet h_trigger_info_alter
+ /**
+ * Implements hook_trigger_info_alter()
+ */
+ function `Filename()`_trigger_info_alter(&$triggers) {
+ ${1:/* Your code here */}
+ }
+snippet h_search_info
+ /**
+ * Implements hook_search_info()
+ */
+ function `Filename()`_search_info() {
+ return array(
+ 'title' => '${1}',
+ 'path' => '${2}',
+ 'conditions_callback' => '${3}',
+ );
+ }
+snippet h_search_access
+ /**
+ * Implements hook_search_access()
+ */
+ function `Filename()`_search_access() {
+ ${1:/* Your code here */}
+ }
+snippet h_search_reset
+ /**
+ * Implements hook_search_reset()
+ */
+ function `Filename()`_search_reset() {
+ ${1:/* Your code here */}
+ }
+snippet h_search_status
+ /**
+ * Implements hook_search_status()
+ */
+ function `Filename()`_search_status() {
+ ${1:/* Your code here */}
+ }
+snippet h_search_admin
+ /**
+ * Implements hook_search_admin()
+ */
+ function `Filename()`_search_admin() {
+ $form['${1}'] = array(
+ '#title' => t('${2}'),
+ '#type' => '${3}',
+ '#theme' => '${4}',
+ '#default_value' => ${5},
+
+ return $form;
+ }
+snippet h_search_execute
+ /**
+ * Implements hook_search_execute()
+ */
+ function `Filename()`_search_execute($keys = NULL, $conditions = NULL) {
+ ${1:/* Your code here */}
+ }
+snippet h_search_page
+ /**
+ * Implements hook_search_page()
+ */
+ function `Filename()`_search_page($results) {
+ $output['prefix']['#markup'] = '<ol class="search-results">';
+
+ foreach ($results as $entry) {
+ $output[] = array(
+ '#theme' => '${1}',
+ '#result' => $entry,
+ '#module' => '${2}',
+ );
+ }
+ $output['suffix']['#markup'] = '</ol>' . theme('pager');
+
+ return $output;
+ }
+snippet h_search_preprocess
+ /**
+ * Implements hook_search_preprocess()
+ */
+ function `Filename()`_search_preprocess($text) {
+ ${1:/* Your code here */}
+ }
+snippet h_update_index
+ /**
+ * Implements hook_update_index()
+ */
+ function `Filename()`_update_index() {
+ ${1:/* Your code here */}
+ }
+snippet h_locale
+ /**
+ * Implements hook_locale()
+ */
+ function `Filename()`_locale($op = 'groups') {
+ switch ($op) {
+ case '${1}':
+ return array('${2}' => t('${3}'));
+ }
+ }
+snippet h_language_init
+ /**
+ * Implements hook_language_init()
+ */
+ function `Filename()`_language_init() {
+ global $language, $conf;
+
+ switch ($language->language) {
+ case '${1}':
+ $conf['${2}'] = '${3}';
+ break;
+ }
+ }
+snippet h_language_switch_links_alter
+ /**
+ * Implements hook_language_switch_links_alter()
+ */
+ function `Filename()`_language_switch_links_alter(array &$links, $type, $path) {
+ global $language;
+ ${1:/* Your code here */}
+ }
+snippet h_language_types_info
+ /**
+ * Implements hook_language_types_info()
+ */
+ function `Filename()`_language_types_info() {
+ return array(
+ '${1}' => array(
+ 'name' => t('${2}'),
+ 'description' => t('${3}'),
+ ),
+ );
+ }
+snippet h_language_types_info_alter
+ /**
+ * Implements hook_language_types_info_alter()
+ */
+ function `Filename()`_language_types_info_alter(array &$language_types) {
+ ${1:/* Your code here */}
+ }
+snippet h_language_negotiation_info
+ /**
+ * Implements hook_language_negotiation_info()
+ */
+ function `Filename()`_language_negotiation_info() {
+ return array(
+ '${1}' => array(
+ 'callbacks' => array(
+ 'language' => '${2}',
+ 'switcher' => '${3}',
+ 'url_rewrite' => '${4}',
+ ),
+ 'file' => drupal_get_path('module', '${5}') . '/${6}',
+ 'weight' => ${7},
+ 'types' => array('${8}'),
+ 'name' => t('${9}'),
+ 'description' => t('${10}'),
+ 'cache' => ${11},
+ ),
+ );
+ }
+snippet h_language_negotiation_info_alter
+ /**
+ * Implements hook_language_negotiation_info_alter()
+ */
+ function `Filename()`_language_negotiation_info_alter(array &$language_providers) {
+ ${1:/* Your code here */}
+ }
+snippet h_multilingual_settings_changed
+ /**
+ * Implements hook_multilingual_settings_changed()
+ */
+ function `Filename()`_multilingual_settings_changed() {
+ ${1:/* Your code here */}
+ }
+snippet h_language_fallback_candidates_alter
+ /**
+ * Implements hook_language_fallback_candidates_alter()
+ */
+ function `Filename()`_language_fallback_candidates_alter(array &$fallback_candidates) {
+ ${1:/* Your code here */}
+ }
+snippet hook_simpletest_alter
+ /**
+ * Implements hook_simpletest_alter()
+ */
+ function `Filename()`_simpletest_alter(&$groups) {
+ // An alternative session handler module would not want to run the original
+ // Session https handling test because it checks the sessions table in the
+ // database.
+ /*
+ *unset($groups['Session']['testHttpsSession']);
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_test_group_started
+ /**
+ * Implements hook_test_group_started()
+ */
+ function `Filename()`_test_group_started() {
+ ${1:/* Your code here */}
+ }
+snippet hook_test_group_finished
+ /**
+ * Implements hook_test_group_finished()
+ */
+ function `Filename()`_test_group_finished() {
+ ${1:/* Your code here */}
+ }
+snippet hook_test_finished
+ /**
+ * Implements hook_test_finished()
+ */
+ function `Filename()`_test_finished($results) {
+ ${1:/* Your code here */}
+ }
+snippet hook_aggregator_fetch
+ /**
+ * Implements hook_aggregator_fetch()
+ */
+ function `Filename()`_aggregator_fetch($feed) {
+ /*
+ *$feed->source_string = mymodule_fetch($feed->url);
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_aggregator_fetch_info
+ /**
+ * Implements hook_aggregator_fetch_info()
+ */
+ function `Filename()`_aggregator_fetch_info() {
+ return array(
+ 'title' => t('${1}'),
+ 'description' => t('${2}'),
+ );
+ }
+snippet hook_aggregator_parse
+ /**
+ * Implements hook_aggregator_parse()
+ */
+ function `Filename()`_aggregator_parse($feed) {
+ /*
+ *if ($items = mymodule_parse($feed->source_string)) {
+ * $feed->items = $items;
+ * return TRUE;
+ *}
+ *return FALSE;
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_aggregator_parse_info
+ /**
+ * Implements hook_aggregator_parse_info()
+ */
+ function `Filename()`_aggregator_parse_info() {
+ return array(
+ 'title' => t('${1}'),
+ 'description' => t('${2}'),
+ );
+ }
+snippet hook_aggregator_process
+ /**
+ * Implements hook_aggregator_process()
+ */
+ function `Filename()`_aggregator_process($feed) {
+ /*
+ *foreach ($feed->items as $item) {
+ * mymodule_save($item);
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_aggregator_process_info
+ /**
+ * Implements hook_aggregator_process_info()
+ */
+ function `Filename()`_aggregator_process_info($feed) {
+ return array(
+ 'title' => t('${1}'),
+ 'description' => t('${2}'),
+ );
+ }
+snippet hook_aggregator_remove
+ /**
+ * Implements hook_aggregator_remove()
+ */
+ function `Filename()`_aggregator_remove($feed) {
+ /*
+ *mymodule_remove_items($feed->fid);
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_overlay_parent_initialize
+ /**
+ * Implements hook_overlay_parent_initialize()
+ */
+ function `Filename()`_overlay_parent_initialize() {
+ // Add our custom JavaScript.
+ /*
+ *drupal_add_js(drupal_get_path('module', 'hook') . '/hook-overlay.js');
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_overlay_child_initialize
+ /**
+ * Implements hook_overlay_child_initialize()
+ */
+ function `Filename()`_overlay_child_initialize() {
+ // Add our custom JavaScript.
+ /*
+ *drupal_add_js(drupal_get_path('module', 'hook') . '/hook-overlay-child.js');
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_entity_info
+ /**
+ * Implements hook_entity_info()
+ */
+ function `Filename()`_entity_info() {
+ /*
+ * $return = array(
+ * 'node' => array(
+ * 'label' => t('Node'),
+ * 'controller class' => 'NodeController',
+ * 'base table' => 'node',
+ * 'revision table' => 'node_revision',
+ * 'uri callback' => 'node_uri',
+ * 'fieldable' => TRUE,
+ * 'translation' => array(
+ * 'locale' => TRUE,
+ * ),
+ * 'entity keys' => array(
+ * 'id' => 'nid',
+ * 'revision' => 'vid',
+ * 'bundle' => 'type',
+ * ),
+ * 'bundle keys' => array(
+ * 'bundle' => 'type',
+ * ),
+ * 'bundles' => array(),
+ * 'view modes' => array(
+ * 'full' => array(
+ * 'label' => t('Full content'),
+ * 'custom settings' => FALSE,
+ * ),
+ * 'teaser' => array(
+ * 'label' => t('Teaser'),
+ * 'custom settings' => TRUE,
+ * ),
+ * 'rss' => array(
+ * 'label' => t('RSS'),
+ * 'custom settings' => FALSE,
+ * ),
+ * ),
+ * ),
+ * );
+ *
+ * // Search integration is provided by node.module, so search-related
+ * // view modes for nodes are defined here and not in search.module.
+ * if (module_exists('search')) {
+ * $return['node']['view modes'] += array(
+ * 'search_index' => array(
+ * 'label' => t('Search index'),
+ * 'custom settings' => FALSE,
+ * ),
+ * 'search_result' => array(
+ * 'label' => t('Search result'),
+ * 'custom settings' => FALSE,
+ * ),
+ * );
+ * }
+ *
+ * // Bundles must provide a human readable name so we can create help and error
+ * // messages, and the path to attach Field admin pages to.
+ * foreach (node_type_get_names() as $type => $name) {
+ * $return['node']['bundles'][$type] = array(
+ * 'label' => $name,
+ * 'admin' => array(
+ * 'path' => 'admin/structure/types/manage/%node_type',
+ * 'real path' => 'admin/structure/types/manage/' . str_replace('_', '-', $type),
+ * 'bundle argument' => 4,
+ * 'access arguments' => array('administer content types'),
+ * ),
+ * );
+ * }
+ */
+ 'node' => array(
+ 'label' => t('${1}'),
+ 'controller class' => '${2}',
+ 'base table' => '${3}',
+ 'revision table' => '${4}',
+ 'uri callback' => '${5}',
+ 'fieldable' => ${6},
+ 'translation' => array(
+ 'locale' => ${7},
+ ),
+ 'entity keys' => array(
+ 'id' => '${8}',
+ 'revision' => '${9}',
+ 'bundle' => '${10}',
+ ),
+ 'bundle keys' => array(
+ 'bundle' => '${11}',
+ ),
+ 'bundles' => array(),
+ 'view modes' => array(
+ '${12}' => array(
+ 'label' => t('${13}'),
+ 'custom settings' => ${14},
+ ),
+ ),
+ ),
+ );
+ return $return;
+ }
+snippet hook_entity_info_alter
+ /**
+ * Implements hook_entity_info_alter()
+ */
+ function `Filename()`_entity_info_alter(&$entity_info) {
+ // Set the controller class for nodes to an alternate implementation of the
+ // DrupalEntityController interface.
+ /*
+ *$entity_info['node']['controller class'] = 'MyCustomNodeController';
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_entity_load
+ /**
+ * Implements hook_entity_load()
+ */
+ function `Filename()`_entity_load($entities, $type) {
+ foreach ($entities as $entity) {
+ $entity->${1} = mymodule_add_something($entity, $type);
+ }
+ }
+snippet hook_entity_insert
+ /**
+ * Implements hook_entity_insert()
+ */
+ function `Filename()`_entity_insert($entity, $type) {
+ ${1:/* Your code here */}
+ }
+snippet hook_entity_update
+ /**
+ * Implements hook_entity_update()
+ */
+ function `Filename()`_entity_update($entity, $type) {
+ ${1:/* Your code here */}
+ }
+snippet hook_entity_query_alter
+ /**
+ * Implements hook_entity_query_alter()
+ */
+ function `Filename()`_entity_query_alter($query) {
+ $query->${1} = 'my_module_query_callback';
+ }
+snippet hook_admin_paths
+ /**
+ * Implements hook_admin_paths()
+ */
+ function `Filename()`_admin_paths() {
+ $paths = array(
+ /*
+ *'mymodule/* /add' => TRUE,
+ *'mymodule/* /edit' => TRUE,
+ */
+ ${1:/* Your code here */}
+ );
+ return $paths;
+ }
+snippet hook_admin_paths_alter
+ /**
+ * Implements hook_admin_paths_alter()
+ */
+ function `Filename()`_admin_paths_alter(&$paths) {
+ // Treat all user pages as administrative.
+ /*
+ *$paths['user'] = TRUE;
+ *$paths['user/*'] = TRUE;
+ */
+ // Treat the forum topic node form as a non-administrative page.
+ /*
+ *$paths['node/add/forum'] = FALSE;
+ */
+ $paths['${1}'] = ${2};
+ }
+snippet hook_entity_prepare_view
+ /**
+ * Implements hook_entity_prepare_view()
+ */
+ function `Filename()`_entity_prepare_view($entities, $type) {
+ // Load a specific node into the user object for later theming.
+ /*
+ *if ($type == 'user') {
+ * $nodes = mymodule_get_user_nodes(array_keys($entities));
+ * foreach ($entities as $uid => $entity) {
+ * $entity->user_node = $nodes[$uid];
+ * }
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_cron
+ /**
+ * Implements hook_cron()
+ */
+ function `Filename()`_cron() {
+ /*
+ * // Short-running operation example, not using a queue:
+ * // Delete all expired records since the last cron run.
+ * $expires = variable_get('mymodule_cron_last_run', REQUEST_TIME);
+ * db_delete('mymodule_table')
+ * ->condition('expires', $expires, '>=')
+ * ->execute();
+ * variable_set('mymodule_cron_last_run', REQUEST_TIME);
+ *
+ * // Long-running operation example, leveraging a queue:
+ * // Fetch feeds from other sites.
+ * $result = db_query('SELECT * FROM {aggregator_feed} WHERE checked + refresh < :time AND refresh != :never', array(
+ * ':time' => REQUEST_TIME,
+ * ':never' => AGGREGATOR_CLEAR_NEVER,
+ * ));
+ * $queue = DrupalQueue::get('aggregator_feeds');
+ * foreach ($result as $feed) {
+ * $queue->createItem($feed);
+ * }
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_cron_queue_info
+ /**
+ * Implements hook_cron_queue_info()
+ */
+ function `Filename()`_cron_queue_info() {
+ /*
+ *$queues['aggregator_feeds'] = array(
+ * 'worker callback' => 'aggregator_refresh',
+ * 'time' => 60,
+ *);
+ */
+ $queues['${1}'] = array(
+ 'worker callback' => '${2}',
+ 'time' => ${3},
+ );
+ return $queues;
+ }
+snippet hook_cron_queue_info_alter
+ /**
+ * Implements hook_cron_queue_info_alter()
+ */
+ function `Filename()`_cron_queue_info_alter(&$queues) {
+ // This site has many feeds so let's spend 90 seconds on each cron run
+ // updating feeds instead of the default 60.
+ /*
+ *$queues['aggregator_feeds']['time'] = 90;
+ */
+ $queues['${1}']['time'] = ${2};
+ }
+snippet hook_element_info
+ /**
+ * Implements hook_element_info()
+ */
+ function `Filename()`_element_info() {
+ $types['${1}'] = array(
+ ${2:/* Your code here */}
+ );
+ return $types;
+ }
+snippet hook_element_info_alter
+ /**
+ * Implements hook_element_info_alter()
+ */
+ function `Filename()`_element_info_alter(&$type) {
+ // Decrease the default size of textfields.
+ /*
+ *if (isset($type['textfield']['#size'])) {
+ * $type['textfield']['#size'] = 40;
+ *}
+ */
+ if (isset($type['${1}'])) {
+ $type['${2}'] = ${3};
+ }
+ }
+snippet hook_exit
+ /**
+ * Implements hook_exit()
+ */
+ function `Filename()`_exit($destination = NULL) {
+ /*
+ *db_update('counter')
+ * ->expression('hits', 'hits + 1')
+ * ->condition('type', 1)
+ * ->execute();
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_js_alter
+ /**
+ * Implements hook_js_alter()
+ */
+ function `Filename()`_js_alter(&$javascript) {
+ // Swap out jQuery to use an updated version of the library.
+ /*
+ *$javascript['misc/jquery.js']['data'] = drupal_get_path('module', 'jquery_update') . '/jquery.js';
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_library
+ /**
+ * Implements hook_library()
+ */
+ function `Filename()`_library() {
+ // Library One.
+ /*
+ *$libraries['library-1'] = array(
+ * 'title' => 'Library One',
+ * 'website' => 'http://example.com/library-1',
+ * 'version' => '1.2',
+ * 'js' => array(
+ * drupal_get_path('module', 'my_module') . '/library-1.js' => array(),
+ * ),
+ * 'css' => array(
+ * drupal_get_path('module', 'my_module') . '/library-2.css' => array(
+ * 'type' => 'file',
+ * 'media' => 'screen',
+ * ),
+ * ),
+ *);
+ */
+ // Library Two.
+ /*
+ *$libraries['library-2'] = array(
+ * 'title' => 'Library Two',
+ * 'website' => 'http://example.com/library-2',
+ * 'version' => '3.1-beta1',
+ * 'js' => array(
+ * // JavaScript settings may use the 'data' key.
+ * array(
+ * 'type' => 'setting',
+ * 'data' => array('library2' => TRUE),
+ * ),
+ * ),
+ * 'dependencies' => array(
+ * // Require jQuery UI core by System module.
+ * array('system', 'ui'),
+ * // Require our other library.
+ * array('my_module', 'library-1'),
+ * // Require another library.
+ * array('other_module', 'library-3'),
+ * ),
+ *);
+ */
+ $libraries['${1}'] = array(
+ 'title' => '${2}',
+ 'website' => '${3}',
+ 'version' => '${4}',
+ 'js' => array(
+ drupal_get_path('module', 'my_module') . '/${5}' => array(),
+ ),
+ 'css' => array(
+ drupal_get_path('module', 'my_module') . '/${6}' => array(
+ 'type' => 'file',
+ 'media' => '${7}',
+ ),
+ ),
+ 'dependencies' => array(
+ // Require jQuery UI core by System module.
+ array('system', 'ui'),
+ ),
+ );
+ return $libraries;
+ }
+snippet hook_library_alter
+ /**
+ * Implements hook_library_alter()
+ */
+ function `Filename()`_library_alter(&$libraries, $module) {
+ // Update Farbtastic to version 2.0.
+ /*
+ *if ($module == 'system' && isset($libraries['farbtastic'])) {
+ * // Verify existing version is older than the one we are updating to.
+ * if (version_compare($libraries['farbtastic']['version'], '2.0', '<')) {
+ * // Update the existing Farbtastic to version 2.0.
+ * $libraries['farbtastic']['version'] = '2.0';
+ * $libraries['farbtastic']['js'] = array(
+ * drupal_get_path('module', 'farbtastic_update') . '/farbtastic-2.0.js' => array(),
+ * );
+ * }
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_css_alter
+ /**
+ * Implements hook_css_alter()
+ */
+ function `Filename()`_css_alter(&$css) {
+ // Remove defaults.css file.
+ /*
+ *unset($css[drupal_get_path('module', 'system') . '/defaults.css']);
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_ajax_render_alter
+ /**
+ * Implements hook_ajax_render_alter()
+ */
+ function `Filename()`_ajax_render_alter($commands) {
+ // Inject any new status messages into the content area.
+ /*
+ *$commands[] = ajax_command_prepend('#block-system-main .content', theme('status_messages'));
+ */
+ $commands[] = ${1}
+ }
+snippet hook_page_build
+ /**
+ * Implements hook_page_build()
+ */
+ function `Filename()`_page_build(&$page) {
+ /*
+ *if (menu_get_object('node', 1)) {
+ * // We are on a node detail page. Append a standard disclaimer to the
+ * // content region.
+ * $page['content']['disclaimer'] = array(
+ * '#markup' => t('Acme, Inc. is not responsible for the contents of this sample code.'),
+ * '#weight' => 25,
+ * );
+ *}
+ */
+ $page['${1}']['${2}'] = array(
+ '#markup' => t('${3}'),
+ '#weight' => ${4},
+ );
+ }
+snippet hook_menu
+ /**
+ * Implements hook_menu()
+ */
+ function `Filename()`_menu() {
+ /*
+ *$items['blog'] = array(
+ * 'title' => 'blogs',
+ * 'page callback' => 'blog_page',
+ * 'access arguments' => array('access content'),
+ * 'type' => MENU_SUGGESTED_ITEM,
+ *);
+ */
+ $items['${1}'] = array(
+ 'title' => '${2}',
+ 'page callback' => '${3}',
+ 'page arguments' => array('${4}'),
+ 'access arguments' => array('${5}'),
+ 'type' => ${6},
+ 'file' => ${7},
+ );
+
+ return $items;
+ }
+snippet hook_menu_alter
+ /**
+ * Implements hook_menu_alter()
+ */
+ function `Filename()`_menu_alter(&$items) {
+ // Example - disable the page at node/add
+ /*
+ *$items['node/add']['access callback'] = FALSE;
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_menu_link_alter
+ /**
+ * Implements hook_menu_link_alter()
+ */
+ function `Filename()`_menu_link_alter(&$item) {
+ // Example 1 - make all new admin links hidden (a.k.a disabled).
+ /*
+ *if (strpos($item['link_path'], 'admin') === 0 && empty($item['mlid'])) {
+ * $item['hidden'] = 1;
+ *}
+ */
+ // Example 2 - flag a link to be altered by hook_translated_menu_link_alter()
+ /*
+ *if ($item['link_path'] == 'devel/cache/clear') {
+ * $item['options']['alter'] = TRUE;
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_translated_menu_link_alter
+ /**
+ * Implements hook_translated_menu_link_alter()
+ */
+ function `Filename()`_translated_menu_link_alter(&$item, $map) {
+ /*
+ *if ($item['href'] == 'devel/cache/clear') {
+ * $item['localized_options']['query'] = drupal_get_destination();
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_menu_link_insert
+ /**
+ * Implements hook_menu_link_insert()
+ */
+ function `Filename()`_menu_link_insert($link) {
+ // In our sample case, we track menu items as editing sections
+ // of the site. These are stored in our table as 'disabled' items.
+ /*
+ *$record['mlid'] = $link['mlid'];
+ *$record['menu_name'] = $link['menu_name'];
+ *$record['status'] = 0;
+ *drupal_write_record('menu_example', $record);
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_menu_link_update
+ /**
+ * Implements hook_menu_link_update()
+ */
+ function `Filename()`_menu_link_update($link) {
+ // If the parent menu has changed, update our record.
+ /*
+ *$menu_name = db_result(db_query("SELECT mlid, menu_name, status FROM {menu_example} WHERE mlid = :mlid", array(':mlid' => $link['mlid'])));
+ *if ($menu_name != $link['menu_name']) {
+ * db_update('menu_example')
+ * ->fields(array('menu_name' => $link['menu_name']))
+ * ->condition('mlid', $link['mlid'])
+ * ->execute();
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_menu_link_delete
+ /**
+ * Implements hook_menu_link_delete()
+ */
+ function `Filename()`_menu_link_delete($link) {
+ // Delete the record from our table.
+ db_delete('${1}')
+ ->condition('mlid', $link['mlid'])
+ ->execute();
+ }
+snippet hook_menu_local_tasks_alter
+ /**
+ * Implements hook_menu_local_tasks_alter()
+ */
+ function `Filename()`_menu_local_tasks_alter(&$data, $router_item, $root_path) {
+ // Add an action to all pages.
+ // $data['actions']['output'][] = array(
+ //
+ // Add a tab to all pages.
+ /*
+ *$data['tabs'][0]['output'][] = array(
+ * '#theme' => 'menu_local_task',
+ * '#link' => array(
+ * 'title' => t('${1}'),
+ * 'href' => '${2}',
+ * 'localized_options' => array(
+ * 'attributes' => array(
+ * 'title' => t('${3}'),
+ * ),
+ * ),
+ * ),
+ * // Define whether this link is active. This can be omitted for
+ * // implementations that add links to pages outside of the current page
+ * // context.
+ * '#active' => ($router_item['path'] == $root_path),
+ *);
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_menu_breadcrumb_alter
+ /**
+ * Implements hook_menu_breadcrumb_alter()
+ */
+ function `Filename()`_menu_breadcrumb_alter(&$active_trail, $item) {
+ // Always display a link to the current page by duplicating the last link in
+ // the active trail. This means that menu_get_active_breadcrumb() will remove
+ // the last link (for the current page), but since it is added once more here,
+ // it will appear.
+ /*
+ *if (!drupal_is_front_page()) {
+ * $end = end($active_trail);
+ * if ($item['href'] == $end['href']) {
+ * $active_trail[] = $end;
+ * }
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_menu_contextual_links_alter
+ /**
+ * Implements hook_menu_contextual_links_alter()
+ */
+ function `Filename()`_menu_contextual_links_alter(&$links, $router_item, $root_path) {
+ // Add a link to all contextual links for nodes.
+ /*
+ *if ($root_path == 'node/%') {
+ * $links['foo'] = array(
+ * 'title' => t('Do fu'),
+ * 'href' => 'foo/do',
+ * 'localized_options' => array(
+ * 'query' => array(
+ * 'foo' => 'bar',
+ * ),
+ * ),
+ * );
+ *}
+ */
+ if ($root_path == '${1}') {
+ $links['${2}'] = array(
+ 'title' => t('${3}'),
+ 'href' => '${4}',
+ 'localized_options' => array(
+ 'query' => array(
+ '${5}' => '${6}',
+ ),
+ ),
+ );
+ }
+ }
+snippet hook_page_alter
+ /**
+ * Implements hook_page_alter()
+ */
+ function `Filename()`_page_alter(&$page) {
+ // Add help text to the user login block.
+ /*
+ *$page['sidebar_first']['user_login']['help'] = array(
+ * '#weight' => -10,
+ * '#markup' => t('To post comments or add new content, you first have to log in.'),
+ *);
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_form_alter
+ /**
+ * Implements hook_form_alter()
+ */
+ function `Filename()`_form_alter(&$form, &$form_state, $form_id) {
+ /*
+ *if (isset($form['type']) && $form['type']['#value'] . '_node_settings' == $form_id) {
+ * $form['workflow']['upload_' . $form['type']['#value']] = array(
+ * '#type' => 'radios',
+ * '#title' => t('Attachments'),
+ * '#default_value' => variable_get('upload_' . $form['type']['#value'], 1),
+ * '#options' => array(t('Disabled'), t('Enabled')),
+ * );
+ *}
+ */
+ $form['${1}'] = array(
+ '#type' => '${2}',
+ '#title' => t('${3}'),
+ '#default_value' => $settings['${4}'],
+ '#required' => ${5},
+ '#element_validate' => array('${6}'),
+ '#description' => t('${7}'),
+ '#${8}' => ${9}
+ );
+ }
+snippet hook_forms
+ /**
+ * Implements hook_forms()
+ */
+ function `Filename()`_forms($form_id, $args) {
+ // Simply reroute the (non-existing) $form_id 'mymodule_first_form' to
+ // 'mymodule_main_form'.
+ /*
+ *$forms['mymodule_first_form'] = array(
+ * 'callback' => 'mymodule_main_form',
+ *);
+ */
+ // Reroute the $form_id and prepend an additional argument that gets passed to
+ // the 'mymodule_main_form' form builder function.
+ /*
+ *$forms['mymodule_second_form'] = array(
+ * 'callback' => 'mymodule_main_form',
+ * 'callback arguments' => array('some parameter'),
+ *);
+ */
+ // Reroute the $form_id, but invoke the form builder function
+ // 'mymodule_main_form_wrapper' first, so we can prepopulate the $form array
+ // that is passed to the actual form builder 'mymodule_main_form'.
+ /*
+ *$forms['mymodule_wrapped_form'] = array(
+ * 'callback' => 'mymodule_main_form',
+ * 'wrapper_callback' => 'mymodule_main_form_wrapper',
+ *);
+ */
+ $forms['${1}'] = array(
+ 'callback' => '${2}',
+ 'callback arguments' => array('${3}'),
+ );
+
+ return $forms;
+ }
+snippet hook_boot
+ /**
+ * Implements hook_boot()
+ */
+ function `Filename()`_boot() {
+ // we need user_access() in the shutdown function. make sure it gets loaded
+ /*
+ *drupal_load('module', 'user');
+ *drupal_register_shutdown_function('devel_shutdown');
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_init
+ /**
+ * Implements hook_init()
+ */
+ function `Filename()`_init() {
+ /*
+ *drupal_add_css(drupal_get_path('module', 'book') . '/book.css');
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_image_toolkits
+ /**
+ * Implements hook_image_toolkits()
+ */
+ function `Filename()`_image_toolkits() {
+ return array(
+ '${1}' => array(
+ 'title' => t('${2}'),
+ 'available' => TRUE,
+ ),
+ );
+ }
+snippet hook_mail_alter
+ /**
+ * Implements hook_mail_alter()
+ */
+ function `Filename()`_mail_alter(&$message) {
+ /*
+ *if ($message['id'] == 'modulename_messagekey') {
+ * $message['body'][] = "--\nMail sent out from " . variable_get('sitename', t('Drupal'));
+ *}
+ */
+ if ($message['id'] == '${1}') {
+ $message['body'][] = "${2}";
+ }
+ }
+snippet hook_module_implements_alter
+ /**
+ * Implements hook_module_implements_alter()
+ */
+ function `Filename()`_module_implements_alter(&$implementations, $hook) {
+ /*
+ *if ($hook == 'rdf_mapping') {
+ * // Move my_module_rdf_mapping() to the end of the list. module_implements()
+ * // iterates through $implementations with a foreach loop which PHP iterates
+ * // in the order that the items were added, so to move an item to the end of
+ * // the array, we remove it and then add it.
+ * $group = $implementations['my_module'];
+ * unset($implementations['my_module']);
+ * $implementations['my_module'] = $group;
+ *}
+ */
+ if ($hook == '${1}') {
+ ${2:/* Your code here */}
+ }
+ }
+snippet hook_system_info_alter
+ /**
+ * Implements hook_system_info_alter()
+ */
+ function `Filename()`_system_info_alter(&$info, $file, $type) {
+ // Only fill this in if the .info file does not define a 'datestamp'.
+ /*
+ *if (empty($info['datestamp'])) {
+ * $info['datestamp'] = filemtime($file->filename);
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_permission
+ /**
+ * Implements hook_permission()
+ */
+ function `Filename()`_permission() {
+ return array(
+ /*
+ *'administer my module' => array(
+ * 'title' => t('Administer my module'),
+ * 'description' => t('Perform administration tasks for my module.'),
+ *),
+ */
+ '${1}' => array(
+ 'title' => t('${2}'),
+ 'description' => t('${3}'),
+ ),
+ );
+ }
+snippet hook_theme
+ /**
+ * Implements hook_theme()
+ */
+ function `Filename()`_theme($existing, $type, $theme, $path) {
+ return array(
+ /*
+ *'forum_icon' => array(
+ * 'variables' => array('new_posts' => NULL, 'num_posts' => 0, 'comment_mode' => 0, 'sticky' => 0),
+ *),
+ *'status_report' => array(
+ * 'render element' => 'requirements',
+ * 'file' => 'system.admin.inc',
+ *),
+ */
+ '${1}' => array(
+ 'render element' => '${2}',
+ 'file' => '${3}',
+ 'variables' => array('${4}' => NULL, '${5}' => NULL${6}),
+ ),
+ );
+ }
+snippet hook_theme_registry_alter
+ /**
+ * Implements hook_theme_registry_alter()
+ */
+ function `Filename()`_theme_registry_alter(&$theme_registry) {
+ // Kill the next/previous forum topic navigation links.
+ /*
+ *foreach ($theme_registry['forum_topic_navigation']['preprocess functions'] as $key => $value) {
+ * if ($value = 'template_preprocess_forum_topic_navigation') {
+ * unset($theme_registry['forum_topic_navigation']['preprocess functions'][$key]);
+ * }
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_custom_theme
+ /**
+ * Implements hook_custom_theme()
+ */
+ function `Filename()`_custom_theme() {
+ // Allow the user to request a particular theme via a query parameter.
+ /*
+ *if (isset($_GET['theme'])) {
+ * return $_GET['theme'];
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_xmlrpc
+ /**
+ * Implements hook_xmlrpc()
+ */
+ function `Filename()`_xmlrpc() {
+ /*
+ *return array(
+ * 'drupal.login' => 'drupal_login',
+ * array(
+ * 'drupal.site.ping',
+ * 'drupal_directory_ping',
+ * array('boolean', 'string', 'string', 'string', 'string', 'string'),
+ * t('Handling ping request'))
+ *);
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_xmlrpc_alter
+ /**
+ * Implements hook_xmlrpc_alter()
+ */
+ function `Filename()`_xmlrpc_alter(&$methods) {
+ // Directly change a simple method.
+ /*
+ *$methods['drupal.login'] = 'mymodule_login';
+ */
+ // Alter complex definitions.
+ /*
+ *foreach ($methods as $key => &$method) {
+ * // Skip simple method definitions.
+ * if (!is_int($key)) {
+ * continue;
+ * }
+ * // Perform the wanted manipulation.
+ * if ($method[0] == 'drupal.site.ping') {
+ * $method[1] = 'mymodule_directory_ping';
+ * }
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_watchdog
+ /**
+ * Implements hook_watchdog()
+ */
+ function `Filename()`_watchdog(array $log_entry) {
+ /*
+ * global $base_url, $language;
+ *
+ * $severity_list = array(
+ * WATCHDOG_EMERGENCY => t('Emergency'),
+ * WATCHDOG_ALERT => t('Alert'),
+ * WATCHDOG_CRITICAL => t('Critical'),
+ * WATCHDOG_ERROR => t('Error'),
+ * WATCHDOG_WARNING => t('Warning'),
+ * WATCHDOG_NOTICE => t('Notice'),
+ * WATCHDOG_INFO => t('Info'),
+ * WATCHDOG_DEBUG => t('Debug'),
+ * );
+ *
+ * $to = 'someone@example.com';
+ * $params = array();
+ * $params['subject'] = t('[@site_name] @severity_desc: Alert from your web site', array(
+ * '@site_name' => variable_get('site_name', 'Drupal'),
+ * '@severity_desc' => $severity_list[$log_entry['severity']],
+ * ));
+ *
+ * $params['message'] = "\nSite: @base_url";
+ * $params['message'] .= "\nSeverity: (@severity) @severity_desc";
+ * $params['message'] .= "\nTimestamp: @timestamp";
+ * $params['message'] .= "\nType: @type";
+ * $params['message'] .= "\nIP Address: @ip";
+ * $params['message'] .= "\nRequest URI: @request_uri";
+ * $params['message'] .= "\nReferrer URI: @referer_uri";
+ * $params['message'] .= "\nUser: (@uid) @name";
+ * $params['message'] .= "\nLink: @link";
+ * $params['message'] .= "\nMessage: \n\n@message";
+ *
+ * $params['message'] = t($params['message'], array(
+ * '@base_url' => $base_url,
+ * '@severity' => $log_entry['severity'],
+ * '@severity_desc' => $severity_list[$log_entry['severity']],
+ * '@timestamp' => format_date($log_entry['timestamp']),
+ * '@type' => $log_entry['type'],
+ * '@ip' => $log_entry['ip'],
+ * '@request_uri' => $log_entry['request_uri'],
+ * '@referer_uri' => $log_entry['referer'],
+ * '@uid' => $log_entry['user']->uid,
+ * '@name' => $log_entry['user']->name,
+ * '@link' => strip_tags($log_entry['link']),
+ * '@message' => strip_tags($log_entry['message']),
+ * ));
+ *
+ * drupal_mail('emaillog', 'entry', $to, $language, $params);
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_mail
+ /**
+ * Implements hook_mail()
+ */
+ function `Filename()`_mail($key, &$message, $params) {
+ /*
+ * $account = $params['account'];
+ * $context = $params['context'];
+ * $variables = array(
+ * '%site_name' => variable_get('site_name', 'Drupal'),
+ * '%username' => format_username($account),
+ * );
+ * if ($context['hook'] == 'taxonomy') {
+ * $entity = $params['entity'];
+ * $vocabulary = taxonomy_vocabulary_load($entity->vid);
+ * $variables += array(
+ * '%term_name' => $entity->name,
+ * '%term_description' => $entity->description,
+ * '%term_id' => $entity->tid,
+ * '%vocabulary_name' => $vocabulary->name,
+ * '%vocabulary_description' => $vocabulary->description,
+ * '%vocabulary_id' => $vocabulary->vid,
+ * );
+ * }
+ *
+ * // Node-based variable translation is only available if we have a node.
+ * if (isset($params['node'])) {
+ * $node = $params['node'];
+ * $variables += array(
+ * '%uid' => $node->uid,
+ * '%node_url' => url('node/' . $node->nid, array('absolute' => TRUE)),
+ * '%node_type' => node_type_get_name($node),
+ * '%title' => $node->title,
+ * '%teaser' => $node->teaser,
+ * '%body' => $node->body,
+ * );
+ * }
+ * $subject = strtr($context['subject'], $variables);
+ * $body = strtr($context['message'], $variables);
+ * $message['subject'] .= str_replace(array("\r", "\n"), '', $subject);
+ * $message['body'][] = drupal_html_to_text($body);
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_flush_caches
+ /**
+ * Implements hook_flush_caches()
+ */
+ function `Filename()`_flush_caches() {
+ /*
+ *return array('cache_example');
+ */
+ return array('${1}');
+ }
+snippet hook_modules_installed
+ /**
+ * Implements hook_modules_installed()
+ */
+ function `Filename()`_modules_installed($modules) {
+ /*
+ *if (in_array('lousy_module', $modules)) {
+ * variable_set('lousy_module_conflicting_variable', FALSE);
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_modules_enabled
+ /**
+ * Implements hook_modules_enabled()
+ */
+ function `Filename()`_modules_enabled($modules) {
+ /*
+ *if (in_array('lousy_module', $modules)) {
+ * drupal_set_message(t('mymodule is not compatible with lousy_module'), 'error');
+ * mymodule_disable_functionality();
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_modules_disabled
+ /**
+ * Implements hook_modules_disabled()
+ */
+ function `Filename()`_modules_disabled($modules) {
+ /*
+ *if (in_array('lousy_module', $modules)) {
+ * mymodule_enable_functionality();
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_modules_uninstalled
+ /**
+ * Implements hook_modules_uninstalled()
+ */
+ function `Filename()`_modules_uninstalled($modules) {
+ foreach ($modules as $module) {
+ db_delete('${1}')
+ ->condition('module', $module)
+ ->execute();
+ }
+ ${2}_cache_rebuild();
+ }
+snippet hook_stream_wrappers
+ /**
+ * Implements hook_stream_wrappers()
+ */
+ function `Filename()`_stream_wrappers() {
+ return array(
+ /*
+ *'public' => array(
+ * 'name' => t('Public files'),
+ * 'class' => 'DrupalPublicStreamWrapper',
+ * 'description' => t('Public local files served by the webserver.'),
+ *),
+ */
+ '${1}' => array(
+ 'name' => t('${2}'),
+ 'class' => '${3}',
+ 'description' => t('${4}'),
+ ),
+ )
+ );
+ }
+snippet hook_stream_wrappers_alter
+ /**
+ * Implements hook_stream_wrappers_alter()
+ */
+ function `Filename()`_stream_wrappers_alter(&$wrappers) {
+ // Change the name of private files to reflect the performance.
+ /*
+ *$wrappers['private']['name'] = t('Slow files');
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_file_load
+ /**
+ * Implements hook_file_load()
+ */
+ function `Filename()`_file_load($files) {
+ // Add the upload specific data into the file object.
+ /*
+ *$result = db_query('SELECT * FROM {upload} u WHERE u.fid IN (:fids)', array(':fids' => array_keys($files)))->fetchAll(PDO::FETCH_ASSOC);
+ *foreach ($result as $record) {
+ * foreach ($record as $key => $value) {
+ * $files[$record['fid']]->$key = $value;
+ * }
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_file_validate
+ /**
+ * Implements hook_file_validate()
+ */
+ function `Filename()`_file_validate(&$file) {
+ $errors = array();
+
+ /*
+ *if (empty($file->filename)) {
+ * $errors[] = t("The file's name is empty. Please give a name to the file.");
+ *}
+ *if (strlen($file->filename) > 255) {
+ * $errors[] = t("The file's name exceeds the 255 characters limit. Please rename the file and try again.");
+ *}
+ */
+ if (${1}) {
+ $errors[] = t("${2}");
+ }
+
+ return $errors;
+ }
+snippet hook_file_insert
+ /**
+ * Implements hook_file_insert()
+ */
+ function `Filename()`_file_insert($file) {
+ ${1:/* Your code here */}
+ }
+snippet hook_file_update
+ /**
+ * Implements hook_file_update()
+ */
+ function `Filename()`_file_update($file) {
+ ${1:/* Your code here */}
+ }
+snippet hook_file_copy
+ /**
+ * Implements hook_file_copy()
+ */
+ function `Filename()`_file_copy($file, $source) {
+ ${1:/* Your code here */}
+ }
+snippet hook_file_move
+ /**
+ * Implements hook_file_move()
+ */
+ function `Filename()`_file_move($file, $source) {
+ ${1:/* Your code here */}
+ }
+snippet hook_file_delete
+ /**
+ * Implements hook_file_delete()
+ */
+ function `Filename()`_file_delete($file) {
+ // Delete all information associated with the file.
+ /*
+ *db_delete('upload')->condition('fid', $file->fid)->execute();
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_file_download
+ /**
+ * Implements hook_file_download()
+ */
+ function `Filename()`_file_download($uri) {
+ // Check if the file is controlled by the current module.
+ /*
+ *if (!file_prepare_directory($uri)) {
+ * $uri = FALSE;
+ *}
+ *$result = db_query("SELECT f.* FROM {file_managed} f INNER JOIN {upload} u ON f.fid = u.fid WHERE uri = :uri", array('uri' => $uri));
+ *foreach ($result as $file) {
+ * if (!user_access('view uploaded files')) {
+ * return -1;
+ * }
+ * return array(
+ * 'Content-Type' => $file->filemime,
+ * 'Content-Length' => $file->filesize,
+ * );
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_file_url_alter
+ /**
+ * Implements hook_file_url_alter()
+ */
+ function `Filename()`_file_url_alter(&$uri) {
+ /*
+ * global $user;
+ *
+ * // User 1 will always see the local file in this example.
+ * if ($user->uid == 1) {
+ * return;
+ * }
+ *
+ * $cdn1 = 'http://cdn1.example.com';
+ * $cdn2 = 'http://cdn2.example.com';
+ * $cdn_extensions = array('css', 'js', 'gif', 'jpg', 'jpeg', 'png');
+ *
+ * // Most CDNs don't support private file transfers without a lot of hassle,
+ * // so don't support this in the common case.
+ * $schemes = array('public');
+ *
+ * $scheme = file_uri_scheme($uri);
+ *
+ * // Only serve shipped files and public created files from the CDN.
+ * if (!$scheme || in_array($scheme, $schemes)) {
+ * // Shipped files.
+ * if (!$scheme) {
+ * $path = $uri;
+ * }
+ * // Public created files.
+ * else {
+ * $wrapper = file_stream_wrapper_get_instance_by_scheme($scheme);
+ * $path = $wrapper->getDirectoryPath() . '/' . file_uri_target($uri);
+ * }
+ *
+ * // Clean up Windows paths.
+ * $path = str_replace('\\', '/', $path);
+ *
+ * // Serve files with one of the CDN extensions from CDN 1, all others from
+ * // CDN 2.
+ * $pathinfo = pathinfo($path);
+ * if (array_key_exists('extension', $pathinfo) && in_array($pathinfo['extension'], $cdn_extensions)) {
+ * $uri = $cdn1 . '/' . $path;
+ * }
+ * else {
+ * $uri = $cdn2 . '/' . $path;
+ * }
+ * }
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_requirements
+ /**
+ * Implements hook_requirements()
+ */
+ function `Filename()`_requirements($phase) {
+ $requirements = array();
+
+ /*
+ * // Ensure translations don't break at install time
+ * $t = get_t();
+ *
+ * // Report Drupal version
+ * if ($phase == 'runtime') {
+ * $requirements['drupal'] = array(
+ * 'title' => $t('Drupal'),
+ * 'value' => VERSION,
+ * 'severity' => REQUIREMENT_INFO
+ * );
+ * }
+ *
+ * // Test PHP version
+ * $requirements['php'] = array(
+ * 'title' => $t('PHP'),
+ * 'value' => ($phase == 'runtime') ? l(phpversion(), 'admin/logs/status/php') : phpversion(),
+ * );
+ * if (version_compare(phpversion(), DRUPAL_MINIMUM_PHP) < 0) {
+ * $requirements['php']['description'] = $t('Your PHP installation is too old. Drupal requires at least PHP %version.', array('%version' => DRUPAL_MINIMUM_PHP));
+ * $requirements['php']['severity'] = REQUIREMENT_ERROR;
+ * }
+ *
+ * // Report cron status
+ * if ($phase == 'runtime') {
+ * $cron_last = variable_get('cron_last');
+ *
+ * if (is_numeric($cron_last)) {
+ * $requirements['cron']['value'] = $t('Last run !time ago', array('!time' => format_interval(REQUEST_TIME - $cron_last)));
+ * }
+ * else {
+ * $requirements['cron'] = array(
+ * 'description' => $t('Cron has not run. It appears cron jobs have not been setup on your system. Check the help pages for <a href="@url">configuring cron jobs</a>.', array('@url' => 'http://drupal.org/cron')),
+ * 'severity' => REQUIREMENT_ERROR,
+ * 'value' => $t('Never run'),
+ * );
+ * }
+ *
+ * $requirements['cron']['description'] .= ' ' . t('You can <a href="@cron">run cron manually</a>.', array('@cron' => url('admin/logs/status/run-cron')));
+ *
+ * $requirements['cron']['title'] = $t('Cron maintenance tasks');
+ * }
+ */
+ ${1:/* Your code here */}
+
+ return $requirements;
+ }
+snippet hook_schema
+ /**
+ * Implements hook_schema()
+ */
+ function `Filename()`_schema() {
+ /*
+ *$schema['node'] = array(
+ * // example (partial) specification for table "node"
+ * 'description' => 'The base table for nodes.',
+ * 'fields' => array(
+ * 'nid' => array(
+ * 'description' => 'The primary identifier for a node.',
+ * 'type' => 'serial',
+ * 'unsigned' => TRUE,
+ * 'not null' => TRUE),
+ * 'vid' => array(
+ * 'description' => 'The current {node_revision}.vid version identifier.',
+ * 'type' => 'int',
+ * 'unsigned' => TRUE,
+ * 'not null' => TRUE,
+ * 'default' => 0),
+ * 'type' => array(
+ * 'description' => 'The {node_type} of this node.',
+ * 'type' => 'varchar',
+ * 'length' => 32,
+ * 'not null' => TRUE,
+ * 'default' => ''),
+ * 'title' => array(
+ * 'description' => 'The title of this node, always treated as non-markup plain text.',
+ * 'type' => 'varchar',
+ * 'length' => 255,
+ * 'not null' => TRUE,
+ * 'default' => ''),
+ * ),
+ * 'indexes' => array(
+ * 'node_changed' => array('changed'),
+ * 'node_created' => array('created'),
+ * ),
+ * 'unique keys' => array(
+ * 'nid_vid' => array('nid', 'vid'),
+ * 'vid' => array('vid')
+ * ),
+ * 'foreign keys' => array(
+ * 'node_revision' => array(
+ * 'table' => 'node_revision',
+ * 'columns' => array('vid' => 'vid'),
+ * ),
+ * 'node_author' => array(
+ * 'table' => 'users',
+ * 'columns' => array('uid' => 'uid')
+ * ),
+ * ),
+ * 'primary key' => array('nid'),
+ *);
+ */
+ $schema['${1}'] = array(
+ 'description' => '${2}',
+ 'fields' => array(
+ '${3}' => array(
+ 'description' => '${4}',
+ 'type' => '${5}',
+ 'unsigned' => ${6},
+ 'not null' => ${7},
+ 'default' => ${8}),
+ ),
+ 'indexes' => array(
+ '${9}' => array('${10}'),
+ ),
+ 'unique keys' => array(
+ '${11}' => array('${12}')
+ ),
+ 'foreign keys' => array(
+ '${13}' => array(
+ 'table' => '${14}',
+ 'columns' => array('${15}' => '${16}'),
+ ),
+ ),
+ 'primary key' => array('${17}'),
+ );
+ return $schema;
+ }
+snippet hook_schema_alter
+ /**
+ * Implements hook_schema_alter()
+ */
+ function `Filename()`_schema_alter(&$schema) {
+ // Add field to existing schema.
+ /*
+ *$schema['users']['fields']['timezone_id'] = array(
+ * 'type' => 'int',
+ * 'not null' => TRUE,
+ * 'default' => 0,
+ * 'description' => 'Per-user timezone configuration.',
+ *);
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_query_alter
+ /**
+ * Implements hook_query_alter()
+ */
+ function `Filename()`_query_alter(QueryAlterableInterface $query) {
+ if ($query->hasTag('${1}')) {
+ /*
+ *$query->range(0, 2);
+ */
+ ${2:/* Your code here */}
+ }
+ }
+snippet hook_install
+ /**
+ * Implements hook_install()
+ */
+ function `Filename()`_install() {
+ // Populate the default {node_access} record.
+ /*
+ *db_insert('node_access')
+ * ->fields(array(
+ * 'nid' => 0,
+ * 'gid' => 0,
+ * 'realm' => 'all',
+ * 'grant_view' => 1,
+ * 'grant_update' => 0,
+ * 'grant_delete' => 0,
+ * ))
+ * ->execute();
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_update_dependencies
+ /**
+ * Implements hook_update_dependencies()
+ */
+ function `Filename()`_update_dependencies() {
+ // Indicate that the mymodule_update_7000() function provided by this module
+ // must run after the another_module_update_7002() function provided by the
+ // 'another_module' module.
+ /*
+ *$dependencies['mymodule'][7000] = array(
+ * 'another_module' => 7002,
+ *);
+ */
+ // Indicate that the mymodule_update_7001() function provided by this module
+ // must run before the yet_another_module_update_7004() function provided by
+ // the 'yet_another_module' module. (Note that declaring dependencies in this
+ // direction should be done only in rare situations, since it can lead to the
+ // following problem: If a site has already run the yet_another_module
+ // module's database updates before it updates its codebase to pick up the
+ // newest mymodule code, then the dependency declared here will be ignored.)
+ /*
+ *$dependencies['yet_another_module'][7004] = array(
+ * 'mymodule' => 7001,
+ *);
+ *return $dependencies;
+ */
+ $dependencies['${1}']['${2}'] = array(
+ '${3}' => ${4},
+ );
+
+ return $dependencies;
+ }
+snippet hook_update_last_removed
+ /**
+ * Implements hook_update_last_removed()
+ */
+ function `Filename()`_update_last_removed() {
+ ${1:/* Your code here */}
+ }
+snippet hook_uninstall
+ /**
+ * Implements hook_uninstall()
+ */
+ function `Filename()`_uninstall() {
+ /*
+ *variable_del('upload_file_types');
+ */
+ variable_del('${1}');
+ }
+snippet hook_enable
+ /**
+ * Implements hook_enable()
+ */
+ function `Filename()`_enable() {
+ /*
+ *mymodule_cache_rebuild();
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_disable
+ /**
+ * Implements hook_disable()
+ */
+ function `Filename()`_disable() {
+ /*
+ *mymodule_cache_rebuild();
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_registry_files_alter
+ /**
+ * Implements hook_registry_files_alter()
+ */
+ function `Filename()`_registry_files_alter(&$files, $modules) {
+ /*
+ *foreach ($modules as $module) {
+ * // Only add test files for disabled modules, as enabled modules should
+ * // already include any test files they provide.
+ * if (!$module->status) {
+ * $dir = $module->dir;
+ * foreach ($module->info['files'] as $file) {
+ * if (substr($file, -5) == '.test') {
+ * $files["$dir/$file"] = array('module' => $module->name, 'weight' => $module->weight);
+ * }
+ * }
+ * }
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_install_tasks
+ /**
+ * Implements hook_install_tasks()
+ */
+ function `Filename()`_install_tasks() {
+ // Here, we define a variable to allow tasks to indicate that a particular,
+ // processor-intensive batch process needs to be triggered later on in the
+ // installation.
+ /*
+ *$myprofile_needs_batch_processing = variable_get('myprofile_needs_batch_processing', FALSE);
+ *$tasks = array(
+ * // This is an example of a task that defines a form which the user who is
+ * // installing the site will be asked to fill out. To implement this task,
+ * // your profile would define a function named myprofile_data_import_form()
+ * // as a normal form API callback function, with associated validation and
+ * // submit handlers. In the submit handler, in addition to saving whatever
+ * // other data you have collected from the user, you might also call
+ * // variable_set('myprofile_needs_batch_processing', TRUE) if the user has
+ * // entered data which requires that batch processing will need to occur
+ * // later on.
+ * 'myprofile_data_import_form' => array(
+ * 'display_name' => st('Data import options'),
+ * 'type' => 'form',
+ * ),
+ * // Similarly, to implement this task, your profile would define a function
+ * // named myprofile_settings_form() with associated validation and submit
+ * // handlers. This form might be used to collect and save additional
+ * // information from the user that your profile needs. There are no extra
+ * // steps required for your profile to act as an "installation wizard"; you
+ * // can simply define as many tasks of type 'form' as you wish to execute,
+ * // and the forms will be presented to the user, one after another.
+ * 'myprofile_settings_form' => array(
+ * 'display_name' => st('Additional options'),
+ * 'type' => 'form',
+ * ),
+ * // This is an example of a task that performs batch operations. To
+ * // implement this task, your profile would define a function named
+ * // myprofile_batch_processing() which returns a batch API array definition
+ * // that the installer will use to execute your batch operations. Due to the
+ * // 'myprofile_needs_batch_processing' variable used here, this task will be
+ * // hidden and skipped unless your profile set it to TRUE in one of the
+ * // previous tasks.
+ * 'myprofile_batch_processing' => array(
+ * 'display_name' => st('Import additional data'),
+ * 'display' => $myprofile_needs_batch_processing,
+ * 'type' => 'batch',
+ * 'run' => $myprofile_needs_batch_processing ? INSTALL_TASK_RUN_IF_NOT_COMPLETED : INSTALL_TASK_SKIP,
+ * ),
+ * // This is an example of a task that will not be displayed in the list that
+ * // the user sees. To implement this task, your profile would define a
+ * // function named myprofile_final_site_setup(), in which additional,
+ * // automated site setup operations would be performed. Since this is the
+ * // last task defined by your profile, you should also use this function to
+ * // call variable_del('myprofile_needs_batch_processing') and clean up the
+ * // variable that was used above. If you want the user to pass to the final
+ * // Drupal installation tasks uninterrupted, return no output from this
+ * // function. Otherwise, return themed output that the user will see (for
+ * // example, a confirmation page explaining that your profile's tasks are
+ * // complete, with a link to reload the current page and therefore pass on
+ * // to the final Drupal installation tasks when the user is ready to do so).
+ * 'myprofile_final_site_setup' => array(
+ * ),
+ *);
+ */
+ $tasks = array(
+ ${1:/* Your code here */}
+ );
+ return $tasks;
+ }
+snippet hook_drupal_goto_alter
+ /**
+ * Implements hook_drupal_goto_alter()
+ */
+ function `Filename()`_drupal_goto_alter(&$path, &$options, &$http_response_code) {
+ ${1:/* Your code here */}
+ }
+snippet hook_html_head_alter
+ /**
+ * Implements hook_html_head_alter()
+ */
+ function `Filename()`_html_head_alter(&$head_elements) {
+ foreach ($head_elements as $key => $element) {
+ /*
+ *if (isset($element['#attributes']['rel']) && $element['#attributes']['rel'] == 'canonical') {
+ * // I want a custom canonical url.
+ * $head_elements[$key]['#attributes']['href'] = mymodule_canonical_url();
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+ }
+snippet hook_install_tasks_alter
+ /**
+ * Implements hook_install_tasks_alter()
+ */
+ function `Filename()`_install_tasks_alter(&$tasks, $install_state) {
+ // Replace the "Choose language" installation task provided by Drupal core
+ // with a custom callback function defined by this installation profile.
+ /*
+ *$tasks['install_select_locale']['function'] = 'myprofile_locale_selection';
+ */
+ $tasks['${1}']['${2}'] = '${3}';
+ }
+snippet hook_file_mimetype_mapping_alter
+ /**
+ * Implements hook_file_mimetype_mapping_alter()
+ */
+ function `Filename()`_file_mimetype_mapping_alter(&$mapping) {
+ // Add new MIME type 'drupal/info'.
+ /*
+ *$mapping['mimetypes']['example_info'] = 'drupal/info';
+ */
+ // Add new extension '.info' and map it to the 'drupal/info' MIME type.
+ /*
+ *$mapping['extensions']['info'] = 'example_info';
+ */
+ // Override existing extension mapping for '.ogg' files.
+ /*
+ *$mapping['extensions']['ogg'] = 189;
+ */
+ $mapping['${1}']['${2}'] = '${3}';
+ }
+snippet hook_action_info
+ /**
+ * Implements hook_action_info()
+ */
+ function `Filename()`_action_info() {
+ return array(
+ /*
+ *'comment_unpublish_action' => array(
+ * 'type' => 'comment',
+ * 'label' => t('Unpublish comment'),
+ * 'configurable' => FALSE,
+ * 'behavior' => array('changes_property'),
+ * 'triggers' => array('comment_presave', 'comment_insert', 'comment_update'),
+ *),
+ */
+ '${1}' => array(
+ 'type' => '${2}',
+ 'label' => t('${3}'),
+ 'configurable' => ${4},
+ 'behavior' => array('${5}'),
+ 'triggers' => array('${6}', ${7}),
+ ),
+ );
+ }
+snippet hook_actions_delete
+ /**
+ * Implements hook_actions_delete()
+ */
+ function `Filename()`_actions_delete($aid) {
+ db_delete('${1}')
+ ->condition('aid', $aid)
+ ->execute();
+ }
+snippet hook_action_info_alter
+ /**
+ * Implements hook_action_info_alter()
+ */
+ function `Filename()`_action_info_alter(&$actions) {
+ $actions['${1}']['${2}'] = t('${3}');
+ }
+snippet hook_archiver_info
+ /**
+ * Implements hook_archiver_info()
+ */
+ function `Filename()`_archiver_info() {
+ return array(
+ /*
+ *'tar' => array(
+ * 'class' => 'ArchiverTar',
+ * 'extensions' => array('tar', 'tar.gz', 'tar.bz2'),
+ */
+ '${1}' => array(
+ 'class' => '${2}',
+ 'extensions' => array('${3}'${4}),
+ ),
+ );
+ }
+snippet hook_archiver_info_alter
+ /**
+ * Implements hook_archiver_info_alter()
+ */
+ function `Filename()`_archiver_info_alter(&$info) {
+ /*
+ *$info['tar']['extensions'][] = 'tgz';
+ */
+ $info['${1}']['${2}'][] = '${3}';
+ }
+snippet hook_date_format_types
+ /**
+ * Implements hook_date_format_types()
+ */
+ function `Filename()`_date_format_types() {
+ return array(
+ /*
+ *'long' => t('Long'),
+ *'medium' => t('Medium'),
+ *'short' => t('Short'),
+ */
+ '${1}' => t('${2}'),
+ );
+ }
+snippet hook_date_format_types_alter
+ /**
+ * Implements hook_date_format_types_alter()
+ */
+ function `Filename()`_date_format_types_alter(&$types) {
+ foreach ($types as $type_name => $type) {
+ /*
+ *$types[$type_name]['locked'] = 1;
+ */
+ $types[$type_name]['${1}'] = ${2};
+ }
+ }
+snippet hook_date_formats
+ /**
+ * Implements hook_date_formats()
+ */
+ function `Filename()`_date_formats() {
+ return array(
+ /*
+ *array(
+ * 'type' => 'mymodule_extra_long',
+ * 'format' => 'l jS F Y H:i:s e',
+ * 'locales' => array('en-ie'),
+ *),
+ */
+ array(
+ 'type' => '${1}',
+ 'format' => '${2}',
+ 'locales' => array('${3}'),
+ ),
+ );
+ }
+snippet hook_date_formats_alter
+ /**
+ * Implements hook_date_formats_alter()
+ */
+ function `Filename()`_date_formats_alter(&$formats) {
+ foreach ($formats as $id => $format) {
+ /*
+ *$formats[$id]['locales'][] = 'en-ca';
+ */
+ $formats[$id]['${1}'][] = '${2}';
+ }
+ }
+snippet hook_page_delivery_callback_alter
+ /**
+ * Implements hook_page_delivery_callback_alter()
+ */
+ function `Filename()`_page_delivery_callback_alter(&$callback) {
+ // jQuery sets a HTTP_X_REQUESTED_WITH header of 'XMLHttpRequest'.
+ // If a page would normally be delivered as an html page, and it is called
+ // from jQuery, deliver it instead as an AJAX response.
+ /*
+ *if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest' && $callback == 'drupal_deliver_html_page') {
+ * $callback = 'ajax_deliver';
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_system_themes_page_alter
+ /**
+ * Implements hook_system_themes_page_alter()
+ */
+ function `Filename()`_system_themes_page_alter(&$theme_groups) {
+ foreach ($theme_groups as $state => &$group) {
+ foreach ($theme_groups[$state] as &$theme) {
+ // Add a foo link to each list of theme operations.
+ /*
+ *$theme->operations[] = l(t('Foo'), 'admin/appearance/foo', array('query' => array('theme' => $theme->name)));
+ */
+ ${1:/* Your code here */}
+ }
+ }
+ }
+snippet hook_url_inbound_alter
+ /**
+ * Implements hook_url_inbound_alter()
+ */
+ function `Filename()`_url_inbound_alter(&$path, $original_path, $path_language) {
+ // Create the path user/me/edit, which allows a user to edit their account.
+ /*
+ *if (preg_match('|^user/me/edit(/.*)?|', $path, $matches)) {
+ * global $user;
+ * $path = 'user/' . $user->uid . '/edit' . $matches[1];
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_url_outbound_alter
+ /**
+ * Implements hook_url_outbound_alter()
+ */
+ function `Filename()`_url_outbound_alter(&$path, &$options, $original_path) {
+ // Instead of pointing to user/[uid]/edit, point to user/me/edit.
+ /*
+ *if (preg_match('|^user/([0-9]*)/edit(/.*)?|', $path, $matches)) {
+ * global $user;
+ * if ($user->uid == $matches[1]) {
+ * $path = 'user/me/edit' . $matches[2];
+ * }
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_username_alter
+ /**
+ * Implements hook_username_alter()
+ */
+ function `Filename()`_username_alter(&$name, $account) {
+ // Display the user's uid instead of name.
+ /*
+ *if (isset($account->uid)) {
+ * $name = t('User !uid', array('!uid' => $account->uid));
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_tokens($type, $tokens, array $data = array(), array $options = array
+ /**
+ * Implements hook_tokens($type, $tokens, array $data = array(), array $options = array()
+ */
+ function `Filename()`_tokens($type, $tokens, array $data = array(), array $options = array()) {
+ $replacements = array();
+
+ /*
+ * $url_options = array('absolute' => TRUE);
+ * if (isset($options['language'])) {
+ * $url_options['language'] = $options['language'];
+ * $language_code = $options['language']->language;
+ * }
+ * else {
+ * $language_code = NULL;
+ * }
+ * $sanitize = !empty($options['sanitize']);
+ *
+ * $replacements = array();
+ *
+ * if ($type == 'node' && !empty($data['node'])) {
+ * $node = $data['node'];
+ *
+ * foreach ($tokens as $name => $original) {
+ * switch ($name) {
+ * // Simple key values on the node.
+ * case 'nid':
+ * $replacements[$original] = $node->nid;
+ * break;
+ *
+ * case 'title':
+ * $replacements[$original] = $sanitize ? check_plain($node->title) : $node->title;
+ * break;
+ *
+ * case 'edit-url':
+ * $replacements[$original] = url('node/' . $node->nid . '/edit', $url_options);
+ * break;
+ *
+ * // Default values for the chained tokens handled below.
+ * case 'author':
+ * $name = ($node->uid == 0) ? variable_get('anonymous', t('Anonymous')) : $node->name;
+ * $replacements[$original] = $sanitize ? filter_xss($name) : $name;
+ * break;
+ *
+ * case 'created':
+ * $replacements[$original] = format_date($node->created, 'medium', '', NULL, $language_code);
+ * break;
+ * }
+ * }
+ *
+ * if ($author_tokens = token_find_with_prefix($tokens, 'author')) {
+ * $author = user_load($node->uid);
+ * $replacements += token_generate('user', $author_tokens, array('user' => $author), $options);
+ * }
+ *
+ * if ($created_tokens = token_find_with_prefix($tokens, 'created')) {
+ * $replacements += token_generate('date', $created_tokens, array('date' => $node->created), $options);
+ * }
+ * }
+ */
+ ${1:/* Your code here */}
+
+ return $replacements;
+ }
+snippet hook_token_info
+ /**
+ * Implements hook_token_info()
+ */
+ function `Filename()`_token_info() {
+ /*
+ *$type = array(
+ * 'name' => t('Nodes'),
+ * 'description' => t('Tokens related to individual nodes.'),
+ * 'needs-data' => 'node',
+ *);
+ */
+ $type = array(
+ 'name' => t('${1}'),
+ 'description' => t('${2}'),
+ 'needs-data' => '${3}',
+ );
+
+ // Core tokens for nodes.
+ /*
+ *$node['nid'] = array(
+ * 'name' => t("Node ID"),
+ * 'description' => t("The unique ID of the node."),
+ *);
+ */
+ $${4}['${5}'] = array(
+ 'name' => t("${6}"),
+ 'description' => t("${7}"),
+ );
+
+ /*
+ *return array(
+ * 'types' => array('node' => $type),
+ * 'tokens' => array('node' => $node),
+ *);
+ */
+ return array(
+ 'types' => array('${8}' => $type),
+ 'tokens' => array('${9}' => $${10}),
+ );
+ }
+snippet hook_batch_alter
+ /**
+ * Implements hook_batch_alter()
+ */
+ function `Filename()`_batch_alter(&$batch) {
+ // If the current page request is inside the overlay, add ?render=overlay to
+ // the success callback URL, so that it appears correctly within the overlay.
+ /*
+ *if (overlay_get_mode() == 'child') {
+ * if (isset($batch['url_options']['query'])) {
+ * $batch['url_options']['query']['render'] = 'overlay';
+ * }
+ * else {
+ * $batch['url_options']['query'] = array('render' => 'overlay');
+ * }
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_token_info_alter
+ /**
+ * Implements hook_token_info_alter()
+ */
+ function `Filename()`_token_info_alter(&$data) {
+ // Modify description of node tokens for our site.
+ /*
+ *$data['tokens']['node']['nid'] = array(
+ * 'name' => t("Node ID"),
+ * 'description' => t("The unique ID of the article."),
+ *);
+ *$data['tokens']['node']['title'] = array(
+ * 'name' => t("Title"),
+ * 'description' => t("The title of the article."),
+ *);
+ */
+ // Chained tokens for nodes.
+ /*
+ *$data['tokens']['node']['created'] = array(
+ * 'name' => t("Date created"),
+ * 'description' => t("The date the article was posted."),
+ * 'type' => 'date',
+ *);
+ */
+ $data['tokens']['${1}']['${2}'] = array(
+ 'name' => t("${3}"),
+ 'description' => t("${4}"),
+ );
+ }
+snippet hook_updater_info
+ /**
+ * Implements hook_updater_info()
+ */
+ function `Filename()`_updater_info() {
+ /*
+ *return array(
+ * 'module' => array(
+ * 'class' => 'ModuleUpdater',
+ * 'name' => t('Update modules'),
+ * 'weight' => 0,
+ * ),
+ * 'theme' => array(
+ * 'class' => 'ThemeUpdater',
+ * 'name' => t('Update themes'),
+ * 'weight' => 0,
+ * ),
+ *);
+ */
+ return array(
+ '${1}' => array(
+ 'class' => '${2}',
+ 'name' => t('${3}'),
+ 'weight' => ${4},
+ ),
+ );
+ }
+snippet hook_updater_info_alter
+ /**
+ * Implements hook_updater_info_alter()
+ */
+ function `Filename()`_updater_info_alter(&$updaters) {
+ // Adjust weight so that the theme Updater gets a chance to handle a given
+ // update task before module updaters.
+ /*
+ *$updaters['theme']['weight'] = -1;
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_countries_alter
+ /**
+ * Implements hook_countries_alter()
+ */
+ function `Filename()`_countries_alter(&$countries) {
+ // Elbonia is now independent, so add it to the country list.
+ /*
+ *$countries['EB'] = 'Elbonia';
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_filetransfer_backends
+ /**
+ * Implements hook_filetransfer_backends()
+ */
+ function `Filename()`_filetransfer_backends() {
+ $backends = array();
+
+ // This is the default, will be available on most systems.
+ /*
+ *if (function_exists('ftp_connect')) {
+ * $backends['ftp'] = array(
+ * 'title' => t('FTP'),
+ * 'class' => 'FileTransferFTP',
+ * 'settings_form' => 'system_filetransfer_backend_form_ftp',
+ * 'weight' => 0,
+ * );
+ *}
+ */
+ ${1:/* Your code here */}
+ return $backends;
+ }
+snippet hook_menu_site_status_alter
+ /**
+ * Implements hook_menu_site_status_alter()
+ */
+ function `Filename()`_menu_site_status_alter(&$menu_site_status, $path) {
+ // Allow access to my_module/authentication even if site is in offline mode.
+ /*
+ *if ($menu_site_status == MENU_SITE_OFFLINE && user_is_anonymous() && $path == 'my_module/authentication') {
+ * $menu_site_status = MENU_SITE_ONLINE;
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_form_system_theme_settings_alter
+ /**
+ * Implements hook_form_system_theme_settings_alter()
+ */
+ function `Filename()`_form_system_theme_settings_alter(&$form, &$form_state) {
+ // Add a checkbox to toggle the breadcrumb trail.
+ /*
+ *$form['toggle_breadcrumb'] = array(
+ * '#type' => 'checkbox',
+ * '#title' => t('Display the breadcrumb'),
+ * '#default_value' => theme_get_setting('toggle_breadcrumb'),
+ * '#description' => t('Show a trail of links from the homepage to the current page.'),
+ *);
+ */
+ $form['${1}'] = array(
+ '#type' => '${2}',
+ '#title' => t('${3}'),
+ '#default_value' => theme_get_setting('${4}'),
+ '#description' => t('${5}'),
+ );
+ }
+snippet hook_preprocess
+ /**
+ * Implements hook_preprocess()
+ */
+ function `Filename()`_preprocess(&$variables, $hook) {
+ static $hooks;
+
+ /*
+ * // Add contextual links to the variables, if the user has permission.
+ *
+ * if (!user_access('access contextual links')) {
+ * return;
+ * }
+ *
+ * if (!isset($hooks)) {
+ * $hooks = theme_get_registry();
+ * }
+ *
+ * // Determine the primary theme function argument.
+ * if (isset($hooks[$hook]['variables'])) {
+ * $keys = array_keys($hooks[$hook]['variables']);
+ * $key = $keys[0];
+ * }
+ * else {
+ * $key = $hooks[$hook]['render element'];
+ * }
+ *
+ * if (isset($variables[$key])) {
+ * $element = $variables[$key];
+ * }
+ *
+ * if (isset($element) && is_array($element) && !empty($element['#contextual_links'])) {
+ * $variables['title_suffix']['contextual_links'] = contextual_links_view($element);
+ * if (!empty($variables['title_suffix']['contextual_links'])) {
+ * $variables['classes_array'][] = 'contextual-links-region';
+ * }
+ * }
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_process
+ /**
+ * Implements hook_process()
+ */
+ function `Filename()`_process(&$variables, $hook) {
+ // Wraps variables in RDF wrappers.
+ /*
+ *if (!empty($variables['rdf_template_variable_attributes_array'])) {
+ * foreach ($variables['rdf_template_variable_attributes_array'] as $variable_name => $attributes) {
+ * $context = array(
+ * 'hook' => $hook,
+ * 'variable_name' => $variable_name,
+ * 'variables' => $variables,
+ * );
+ * $variables[$variable_name] = theme('rdf_template_variable_wrapper', array('content' => $variables[$variable_name], 'attributes' => $attributes, 'context' => $context));
+ * }
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_themes_enabled
+ /**
+ * Implements hook_themes_enabled()
+ */
+ function `Filename()`_themes_enabled($theme_list) {
+ foreach ($theme_list as $theme) {
+ /*
+ *block_theme_initialize($theme);
+ */
+ ${1:/* Your code here */}
+ }
+ }
+snippet hook_themes_disabled
+ /**
+ * Implements hook_themes_disabled()
+ */
+ function `Filename()`_themes_disabled($theme_list) {
+ // Clear all update module caches.
+ /*
+ *_update_cache_clear();
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_file_download_access
+ /**
+ * Implements hook_file_download_access()
+ */
+ function `Filename()`_file_download_access($field, $entity_type, $entity) {
+ /*
+ *if ($entity_type == 'node') {
+ * return node_access('view', $entity);
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_file_download_access_alter
+ /**
+ * Implements hook_file_download_access_alter()
+ */
+ function `Filename()`_file_download_access_alter(&$grants, $field, $entity_type, $entity) {
+ // For our example module, we always enforce the rules set by node module.
+ /*
+ *if (isset($grants['node'])) {
+ * $grants = array('node' => $grants['node']);
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_help
+ /**
+ * Implements hook_help()
+ */
+ function `Filename()`_help($path, $arg) {
+ switch ($path) {
+ // Main module help for the block module
+ /*
+ *case 'admin/help#block':
+ * return '<p>' . t('Blocks are boxes of content rendered into an area, or region, of a web page. The default theme Bartik, for example, implements the regions "Sidebar first", "Sidebar second", "Featured", "Content", "Header", "Footer", etc., and a block may appear in any one of these areas. The <a href="@blocks">blocks administration page</a> provides a drag-and-drop interface for assigning a block to a region, and for controlling the order of blocks within regions.', array('@blocks' => url('admin/structure/block'))) . '</p>';
+ */
+ case '${1}':
+ return '<p>' . t('${2}', array('${3}' => ${4})) . '</p>';
+ }
+ }
+snippet hook_comment_presave
+ /**
+ * Implements hook_comment_presave()
+ */
+ function `Filename()`_comment_presave($comment) {
+ // Remove leading & trailing spaces from the comment subject.
+ /*
+ *$comment->subject = trim($comment->subject);
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_comment_insert
+ /**
+ * Implements hook_comment_insert()
+ */
+ function `Filename()`_comment_insert($comment) {
+ // Reindex the node when comments are added.
+ /*
+ *search_touch_node($comment->nid);
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_comment_update
+ /**
+ * Implements hook_comment_update()
+ */
+ function `Filename()`_comment_update($comment) {
+ // Reindex the node when comments are updated.
+ /*
+ *search_touch_node($comment->nid);
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_comment_load
+ /**
+ * Implements hook_comment_load()
+ */
+ function `Filename()`_comment_load($comments) {
+ /*
+ *$result = db_query('SELECT cid, foo FROM {mytable} WHERE cid IN (:cids)', array(':cids' => array_keys($comments)));
+ *foreach ($result as $record) {
+ * $comments[$record->cid]->foo = $record->foo;
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_comment_view
+ /**
+ * Implements hook_comment_view()
+ */
+ function `Filename()`_comment_view($comment, $view_mode, $langcode) {
+ // how old is the comment
+ /*
+ *$comment->time_ago = time() - $comment->changed;
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_comment_view_alter
+ /**
+ * Implements hook_comment_view_alter()
+ */
+ function `Filename()`_comment_view_alter(&$build) {
+ // Check for the existence of a field added by another module.
+ /*
+ *if ($build['#view_mode'] == 'full' && isset($build['an_additional_field'])) {
+ * // Change its weight.
+ * $build['an_additional_field']['#weight'] = -10;
+ *}
+ */
+ // Add a #post_render callback to act on the rendered HTML of the comment.
+ /*
+ *$build['#post_render'][] = 'my_module_comment_post_render';
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_comment_publish
+ /**
+ * Implements hook_comment_publish()
+ */
+ function `Filename()`_comment_publish($comment) {
+ /*
+ *drupal_set_message(t('Comment: @subject has been published', array('@subject' => $comment->subject)));
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_comment_unpublish
+ /**
+ * Implements hook_comment_unpublish()
+ */
+ function `Filename()`_comment_unpublish($comment) {
+ /*
+ *drupal_set_message(t('Comment: @subject has been unpublished', array('@subject' => $comment->subject)));
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_comment_delete
+ /**
+ * Implements hook_comment_delete()
+ */
+ function `Filename()`_comment_delete($comment) {
+ /*
+ *drupal_set_message(t('Comment: @subject has been deleted', array('@subject' => $comment->subject)));
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_update_projects_alter
+ /**
+ * Implements hook_update_projects_alter()
+ */
+ function `Filename()`_update_projects_alter(&$projects) {
+ // Hide a site-specific module from the list.
+ /*
+ *unset($projects['site_specific_module']);
+ */
+ // Add a disabled module to the list.
+ // The key for the array should be the machine-readable project "short name".
+ /*
+ *$projects['disabled_project_name'] = array(
+ * // Machine-readable project short name (same as the array key above).
+ * 'name' => 'disabled_project_name',
+ * // Array of values from the main .info file for this project.
+ * 'info' => array(
+ * 'name' => 'Some disabled module',
+ * 'description' => 'A module not enabled on the site that you want to see in the available updates report.',
+ * 'version' => '7.x-1.0',
+ * 'core' => '7.x',
+ * // The maximum file change time (the "ctime" returned by the filectime()
+ * // PHP method) for all of the .info files included in this project.
+ * '_info_file_ctime' => 1243888165,
+ * ),
+ * // The date stamp when the project was released, if known. If the disabled
+ * // project was an officially packaged release from drupal.org, this will
+ * // be included in the .info file as the 'datestamp' field. This only
+ * // really matters for development snapshot releases that are regenerated,
+ * // so it can be left undefined or set to 0 in most cases.
+ * 'datestamp' => 1243888185,
+ * // Any modules (or themes) included in this project. Keyed by machine-
+ * // readable "short name", value is the human-readable project name printed
+ * // in the UI.
+ * 'includes' => array(
+ * 'disabled_project' => 'Disabled module',
+ * 'disabled_project_helper' => 'Disabled module helper module',
+ * 'disabled_project_foo' => 'Disabled module foo add-on module',
+ * ),
+ * // Does this project contain a 'module', 'theme', 'disabled-module', or
+ * // 'disabled-theme'?
+ * 'project_type' => 'disabled-module',
+ *);
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_update_status_alter
+ /**
+ * Implements hook_update_status_alter()
+ */
+ function `Filename()`_update_status_alter(&$projects) {
+ /*
+ *$settings = variable_get('update_advanced_project_settings', array());
+ *foreach ($projects as $project => $project_info) {
+ * if (isset($settings[$project]) && isset($settings[$project]['check']) &&
+ * ($settings[$project]['check'] == 'never' ||
+ * (isset($project_info['recommended']) &&
+ * $settings[$project]['check'] === $project_info['recommended']))) {
+ * $projects[$project]['status'] = UPDATE_NOT_CHECKED;
+ * $projects[$project]['reason'] = t('Ignored from settings');
+ * if (!empty($settings[$project]['notes'])) {
+ * $projects[$project]['extra'][] = array(
+ * 'class' => array('admin-note'),
+ * 'label' => t('Administrator note'),
+ * 'data' => $settings[$project]['notes'],
+ * );
+ * }
+ * }
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_verify_update_archive
+ /**
+ * Implements hook_verify_update_archive()
+ */
+ function `Filename()`_verify_update_archive($project, $archive_file, $directory) {
+ if (!file_exists($directory)) {
+ return TRUE;
+ }
+ ${1:/* Add other checks on the archive integrity here */}
+ }
+snippet hook_node_grants
+ /**
+ * Implements hook_node_grants()
+ */
+ function `Filename()`_node_grants($account, $op) {
+ /*
+ *if (user_access('access private content', $account)) {
+ * $grants['example'] = array(1);
+ *}
+ *$grants['example_owner'] = array($account->uid);
+ */
+ ${1:/* Your code here */}
+
+ return $grants;
+ }
+snippet hook_node_access_records
+ /**
+ * Implements hook_node_access_records()
+ */
+ function `Filename()`_node_access_records($node) {
+ // We only care about the node if it has been marked private. If not, it is
+ // treated just like any other node and we completely ignore it.
+ /*
+ * if ($node->private) {
+ * $grants = array();
+ * // Only published nodes should be viewable to all users. If we allow access
+ * // blindly here, then all users could view an unpublished node.
+ * if ($node->status) {
+ * $grants[] = array(
+ * 'realm' => 'example',
+ * 'gid' => 1,
+ * 'grant_view' => 1,
+ * 'grant_update' => 0,
+ * 'grant_delete' => 0,
+ * 'priority' => 0,
+ * );
+ * }
+ * // For the example_author array, the GID is equivalent to a UID, which
+ * // means there are many groups of just 1 user.
+ * // Note that an author can always view his or her nodes, even if they
+ * // have status unpublished.
+ * $grants[] = array(
+ * 'realm' => 'example_author',
+ * 'gid' => $node->uid,
+ * 'grant_view' => 1,
+ * 'grant_update' => 1,
+ * 'grant_delete' => 1,
+ * 'priority' => 0,
+ * );
+ *
+ * return $grants;
+ * }
+ */
+ $grants[] = array(
+ 'realm' => '${1}',
+ 'gid' => ${2},
+ 'grant_view' => ${3},
+ 'grant_update' => ${4},
+ 'grant_delete' => ${5},
+ 'priority' => ${6},
+ );
+
+ return $grants;
+ }
+ }
+snippet hook_node_access_records_alter
+ /**
+ * Implements hook_node_access_records_alter()
+ */
+ function `Filename()`_node_access_records_alter(&$grants, $node) {
+ // Our module allows editors to mark specific articles with the 'is_preview'
+ // field. If the node being saved has a TRUE value for that field, then only
+ // our grants are retained, and other grants are removed. Doing so ensures
+ // that our rules are enforced no matter what priority other grants are given.
+ /*
+ *if ($node->is_preview) {
+ * // Our module grants are set in $grants['example'].
+ * $temp = $grants['example'];
+ * // Now remove all module grants but our own.
+ * $grants = array('example' => $temp);
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_node_grants_alter
+ /**
+ * Implements hook_node_grants_alter()
+ */
+ function `Filename()`_node_grants_alter(&$grants, $account, $op) {
+ // Our sample module never allows certain roles to edit or delete
+ // content. Since some other node access modules might allow this
+ // permission, we expressly remove it by returning an empty $grants
+ // array for roles specified in our variable setting.
+ //
+ // Get our list of banned roles.
+ /*
+ *$restricted = variable_get('example_restricted_roles', array());
+ *
+ *if ($op != 'view' && !empty($restricted)) {
+ * // Now check the roles for this account against the restrictions.
+ * foreach ($restricted as $role_id) {
+ * if (isset($user->roles[$role_id])) {
+ * $grants = array();
+ * }
+ * }
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_node_operations
+ /**
+ * Implements hook_node_operations()
+ */
+ function `Filename()`_node_operations() {
+ $operations = array(
+ /*
+ *'publish' => array(
+ * 'label' => t('Publish selected content'),
+ * 'callback' => 'node_mass_update',
+ * 'callback arguments' => array('updates' => array('status' => NODE_PUBLISHED)),
+ *),
+ */
+ '${1}' => array(
+ 'label' => t('${2}'),
+ 'callback' => '${3}',
+ 'callback arguments' => array('${4}' => array('${5}' => ${6})),
+ ),
+ );
+ return $operations;
+ }
+snippet hook_node_delete
+ /**
+ * Implements hook_node_delete()
+ */
+ function `Filename()`_node_delete($node) {
+ db_delete('${1}')
+ ->condition('nid', $node->nid)
+ ->execute();
+ }
+snippet hook_node_revision_delete
+ /**
+ * Implements hook_node_revision_delete()
+ */
+ function `Filename()`_node_revision_delete($node) {
+ db_delete('${1}')
+ ->condition('vid', $node->vid)
+ ->execute();
+ }
+snippet hook_node_insert
+ /**
+ * Implements hook_node_insert()
+ */
+ function `Filename()`_node_insert($node) {
+ db_insert('${1}')
+ ->fields(array(
+ 'nid' => $node->nid,
+ 'extra' => $node->extra,
+ ))
+ ->execute();
+ }
+snippet hook_node_load
+ /**
+ * Implements hook_node_load()
+ */
+ function `Filename()`_node_load($nodes, $types) {
+ /*
+ *$result = db_query('SELECT nid, foo FROM {mytable} WHERE nid IN(:nids)', array(':nids' => array_keys($nodes)));
+ *foreach ($result as $record) {
+ * $nodes[$record->nid]->foo = $record->foo;
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_node_access
+ /**
+ * Implements hook_node_access()
+ */
+ function `Filename()`_node_access($node, $op, $account) {
+ $type = is_string($node) ? $node : $node->type;
+
+ /*
+ *if (in_array($type, node_permissions_get_configured_types())) {
+ * if ($op == 'create' && user_access('create ' . $type . ' content', $account)) {
+ * return NODE_ACCESS_ALLOW;
+ * }
+ *
+ * if ($op == 'update') {
+ * if (user_access('edit any ' . $type . ' content', $account) || (user_access('edit own ' . $type . ' content', $account) && ($account->uid == $node->uid))) {
+ * return NODE_ACCESS_ALLOW;
+ * }
+ * }
+ *
+ * if ($op == 'delete') {
+ * if (user_access('delete any ' . $type . ' content', $account) || (user_access('delete own ' . $type . ' content', $account) && ($account->uid == $node->uid))) {
+ * return NODE_ACCESS_ALLOW;
+ * }
+ * }
+ *}
+ */
+ ${1:/* Your code here */}
+
+ // Returning nothing from this function would have the same effect.
+ return NODE_ACCESS_IGNORE;
+ }
+snippet hook_node_prepare
+ /**
+ * Implements hook_node_prepare()
+ */
+ function `Filename()`_node_prepare($node) {
+ /*
+ *if (!isset($node->comment)) {
+ * $node->comment = variable_get("comment_$node->type", COMMENT_NODE_OPEN);
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_node_search_result
+ /**
+ * Implements hook_node_search_result()
+ */
+ function `Filename()`_node_search_result($node) {
+ /*
+ *$comments = db_query('SELECT comment_count FROM {node_comment_statistics} WHERE nid = :nid', array('nid' => $node->nid))->fetchField();
+ *return format_plural($comments, '1 comment', '@count comments');
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_node_presave
+ /**
+ * Implements hook_node_presave()
+ */
+ function `Filename()`_node_presave($node) {
+ /*
+ *if ($node->nid && $node->moderate) {
+ * // Reset votes when node is updated:
+ * $node->score = 0;
+ * $node->users = '';
+ * $node->votes = 0;
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_node_update
+ /**
+ * Implements hook_node_update()
+ */
+ function `Filename()`_node_update($node) {
+ db_update('${1}')
+ ->fields(array('${2}' => ${3})
+ ->condition('nid', $node->nid)
+ ->execute();
+ }
+snippet hook_node_update_index
+ /**
+ * Implements hook_node_update_index()
+ */
+ function `Filename()`_node_update_index($node) {
+ /*
+ *$text = '';
+ *$comments = db_query('SELECT subject, comment, format FROM {comment} WHERE nid = :nid AND status = :status', array(':nid' => $node->nid, ':status' => COMMENT_PUBLISHED));
+ *foreach ($comments as $comment) {
+ * $text .= '<h2>' . check_plain($comment->subject) . '</h2>' . check_markup($comment->comment, $comment->format, '', TRUE);
+ *}
+ *return $text;
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_node_validate
+ /**
+ * Implements hook_node_validate()
+ */
+ function `Filename()`_node_validate($node, $form, &$form_state) {
+ /*
+ *if (isset($node->end) && isset($node->start)) {
+ * if ($node->start > $node->end) {
+ * form_set_error('time', t('An event may not end before it starts.'));
+ * }
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_node_submit
+ /**
+ * Implements hook_node_submit()
+ */
+ function `Filename()`_node_submit($node, $form, &$form_state) {
+ // Decompose the selected menu parent option into 'menu_name' and 'plid', if
+ // the form used the default parent selection widget.
+ /*
+ *if (!empty($form_state['values']['menu']['parent'])) {
+ * list($node->menu['menu_name'], $node->menu['plid']) = explode(':', $form_state['values']['menu']['parent']);
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_node_view
+ /**
+ * Implements hook_node_view()
+ */
+ function `Filename()`_node_view($node, $view_mode, $langcode) {
+ /*
+ *$node->content['my_additional_field'] = array(
+ * '#markup' => $additional_field,
+ * '#weight' => 10,
+ * '#theme' => 'mymodule_my_additional_field',
+ *);
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_node_view_alter
+ /**
+ * Implements hook_node_view_alter()
+ */
+ function `Filename()`_node_view_alter(&$build) {
+ /*
+ *if ($build['#view_mode'] == 'full' && isset($build['an_additional_field'])) {
+ * // Change its weight.
+ * $build['an_additional_field']['#weight'] = -10;
+ *}
+ *
+ * // Add a #post_render callback to act on the rendered HTML of the node.
+ * $build['#post_render'][] = 'my_module_node_post_render';
+ */
+ }
+snippet hook_node_info
+ /**
+ * Implements hook_node_info()
+ */
+ function `Filename()`_node_info() {
+ return array(
+ /*
+ *'blog' => array(
+ * 'name' => t('Blog entry'),
+ * 'base' => 'blog',
+ * 'description' => t('Use for multi-user blogs. Every user gets a personal blog.'),
+ *)
+ */
+ '${1}' => array(
+ 'name' => t('${2}'),
+ 'base' => '${3}',
+ 'description' => t('${4}'),
+ )
+ );
+ }
+snippet hook_ranking
+ /**
+ * Implements hook_ranking()
+ */
+ function `Filename()`_ranking() {
+ // If voting is disabled, we can avoid returning the array, no hard feelings.
+ /*
+ *if (variable_get('vote_node_enabled', TRUE)) {
+ * return array(
+ * 'vote_average' => array(
+ * 'title' => t('Average vote'),
+ * // Note that we use i.sid, the search index's search item id, rather than
+ * // n.nid.
+ * 'join' => 'LEFT JOIN {vote_node_data} vote_node_data ON vote_node_data.nid = i.sid',
+ * // The highest possible score should be 1, and the lowest possible score,
+ * // always 0, should be 0.
+ * 'score' => 'vote_node_data.average / CAST(%f AS DECIMAL)',
+ * // Pass in the highest possible voting score as a decimal argument.
+ * 'arguments' => array(variable_get('vote_score_max', 5)),
+ * ),
+ * );
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_node_type_insert
+ /**
+ * Implements hook_node_type_insert()
+ */
+ function `Filename()`_node_type_insert($info) {
+ ${1:/* Your code here */}
+ }
+snippet hook_node_type_update
+ /**
+ * Implements hook_node_type_update()
+ */
+ function `Filename()`_node_type_update($info) {
+ /*
+ *if (!empty($info->old_type) && $info->old_type != $info->type) {
+ * $setting = variable_get('comment_' . $info->old_type, COMMENT_NODE_OPEN);
+ * variable_del('comment_' . $info->old_type);
+ * variable_set('comment_' . $info->type, $setting);
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_node_type_delete
+ /**
+ * Implements hook_node_type_delete()
+ */
+ function `Filename()`_node_type_delete($info) {
+ /*
+ *variable_del('comment_' . $info->type);
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_delete
+ /**
+ * Implements hook_delete()
+ */
+ function `Filename()`_delete($node) {
+ db_delete('${1}')
+ ->condition('nid', $nid->nid)
+ ->execute();
+ }
+snippet hook_prepare
+ /**
+ * Implements hook_prepare()
+ */
+ function `Filename()`_prepare($node) {
+ /*
+ *if ($file = file_check_upload($field_name)) {
+ * $file = file_save_upload($field_name, _image_filename($file->filename, NULL, TRUE));
+ * if ($file) {
+ * if (!image_get_info($file->uri)) {
+ * form_set_error($field_name, t('Uploaded file is not a valid image'));
+ * return;
+ * }
+ * }
+ * else {
+ * return;
+ * }
+ * $node->images['_original'] = $file->uri;
+ * _image_build_derivatives($node, TRUE);
+ * $node->new_file = TRUE;
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_form
+ /**
+ * Implements hook_form()
+ */
+ function `Filename()`_form($node, &$form_state) {
+ $type = node_type_get_type($node);
+
+ $form['${1}'] = array(
+ '#type' => '${2}',
+ '#title' => t('${3}'),
+ '#default_value' => $node->${4},
+ '#${5}' => ${6},
+ );
+
+ return $form;
+ }
+snippet hook_insert
+ /**
+ * Implements hook_insert()
+ */
+ function `Filename()`_insert($node) {
+ db_insert('${1}')
+ ->fields(array(
+ 'nid' => $node->nid,
+ 'extra' => $node->extra,
+ ))
+ ->execute();
+ }
+snippet hook_load
+ /**
+ * Implements hook_load()
+ */
+ function `Filename()`_load($nodes) {
+ /*
+ *$result = db_query('SELECT nid, foo FROM {mytable} WHERE nid IN (:nids)', array(':nids' => array_keys($nodes)));
+ *foreach ($result as $record) {
+ * $nodes[$record->nid]->foo = $record->foo;
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_update
+ /**
+ * Implements hook_update()
+ */
+ function `Filename()`_update($node) {
+ db_update('${1}')
+ ->fields(array('extra' => $node->extra))
+ ->condition('nid', $node->nid)
+ ->execute();
+ }
+snippet hook_validate
+ /**
+ * Implements hook_validate()
+ */
+ function `Filename()`_validate($node, $form, &$form_state) {
+ /*
+ *if (isset($node->end) && isset($node->start)) {
+ * if ($node->start > $node->end) {
+ * form_set_error('time', t('An event may not end before it starts.'));
+ * }
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_view
+ /**
+ * Implements hook_view()
+ */
+ function `Filename()`_view($node, $view_mode) {
+ /*
+ *if ($view_mode == 'full' && node_is_page($node)) {
+ * $breadcrumb = array();
+ * $breadcrumb[] = l(t('Home'), NULL);
+ * $breadcrumb[] = l(t('Example'), 'example');
+ * $breadcrumb[] = l($node->field1, 'example/' . $node->field1);
+ * drupal_set_breadcrumb($breadcrumb);
+ *}
+ *
+ *$node->content['myfield'] = array(
+ * '#value' => theme('mymodule_myfield', $node->myfield),
+ * '#weight' => 1,
+ *);
+ */
+ ${1:/* Your code here */}
+
+ return $node;
+ }
+snippet hook_block_info
+ /**
+ * Implements hook_block_info()
+ */
+ function `Filename()`_block_info() {
+ // This example comes from node.module.
+ /*
+ *$blocks['syndicate'] = array(
+ * 'info' => t('Syndicate'),
+ * 'cache' => DRUPAL_NO_CACHE
+ *);
+ */
+ $blocks['${1}'] = array(
+ 'info' => t('${2}'),
+ 'cache' => ${3}DRUPAL_NO_CACHE
+ );
+
+ return $blocks;
+ }
+snippet hook_block_info_alter
+ /**
+ * Implements hook_block_info_alter()
+ */
+ function `Filename()`_block_info_alter(&$blocks, $theme, $code_blocks) {
+ // Disable the login block.
+ /*
+ *$blocks['user']['login']['status'] = 0;
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_block_configure
+ /**
+ * Implements hook_block_configure()
+ */
+ function `Filename()`_block_configure($delta = '') {
+ // This example comes from node.module.
+ /*
+ *$form = array();
+ *if ($delta == 'recent') {
+ * $form['node_recent_block_count'] = array(
+ * '#type' => 'select',
+ * '#title' => t('Number of recent content items to display'),
+ * '#default_value' => variable_get('node_recent_block_count', 10),
+ * '#options' => drupal_map_assoc(array(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 25, 30)),
+ * );
+ *}
+ */
+ $form = array();
+ if ($delta == '${1}') {
+ $form['${2}'] = array(
+ '#type' => '${3}',
+ '#title' => t('${4}'),
+ '#default_value' => variable_get('${5}', ${6}),
+ '#${7}' => ${8},
+ );
+ }
+ return $form;
+ }
+snippet hook_block_save($delta = '', $edit = array
+ /**
+ * Implements hook_block_save($delta = '', $edit = array()
+ */
+ function `Filename()`_block_save($delta = '', $edit = array()) {
+ // This example comes from node.module.
+ /*
+ *if ($delta == 'recent') {
+ * variable_set('node_recent_block_count', $edit['node_recent_block_count']);
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_block_view
+ /**
+ * Implements hook_block_view()
+ */
+ function `Filename()`_block_view($delta = '') {
+ $block = array();
+
+ switch ($delta) {
+ /*
+ *case 'syndicate':
+ * $block['subject'] = t('Syndicate');
+ * $block['content'] = theme('feed_icon', array('url' => url('rss.xml'), 'title' => t('Syndicate')));
+ * break;
+ *
+ *case 'recent':
+ * if (user_access('access content')) {
+ * $block['subject'] = t('Recent content');
+ * if ($nodes = node_get_recent(variable_get('node_recent_block_count', 10))) {
+ * $block['content'] = theme('node_recent_block', array(
+ * 'nodes' => $nodes,
+ * ));
+ * } else {
+ * $block['content'] = t('No content available.');
+ * }
+ * }
+ * break;
+ */
+ case '${1}':
+ $block['subject'] = t('${2}');
+ $block['content'] = theme('${3}', array('${4}' =>${5}));
+ break;
+ ${6}
+ }
+ return $block;
+ }
+snippet hook_block_view_alter
+ /**
+ * Implements hook_block_view_alter()
+ */
+ function `Filename()`_block_view_alter(&$data, $block) {
+ // Remove the contextual links on all blocks that provide them.
+ /*
+ *if (is_array($data['content']) && isset($data['content']['#contextual_links'])) {
+ * unset($data['content']['#contextual_links']);
+ *}
+ */
+ // Add a theme wrapper function defined by the current module to all blocks
+ // provided by the "somemodule" module.
+ /*
+ *if (is_array($data['content']) && $block->module == 'somemodule') {
+ * $data['content']['#theme_wrappers'][] = 'mymodule_special_block';
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_block_list_alter
+ /**
+ * Implements hook_block_list_alter()
+ */
+ function `Filename()`_block_list_alter(&$blocks) {
+ // This example shows how to achieve language specific visibility setting for
+ // blocks.
+ /*
+ *global $language, $theme_key;
+ *$result = db_query('SELECT module, delta, language FROM {my_table}');
+ *$block_languages = array();
+ *foreach ($result as $record) {
+ * $block_languages[$record->module][$record->delta][$record->language] = TRUE;
+ *}
+ *
+ *foreach ($blocks as $key => $block) {
+ * // Any module using this alter should inspect the data before changing it,
+ * // to ensure it is what they expect.
+ * if (!isset($block->theme) || !isset($block->status) || $block->theme != $theme_key || $block->status != 1) {
+ * // This block was added by a contrib module, leave it in the list.
+ * continue;
+ * }
+ *
+ * if (!isset($block_languages[$block->module][$block->delta])) {
+ * // No language setting for this block, leave it in the list.
+ * continue;
+ * }
+ *
+ * if (!isset($block_languages[$block->module][$block->delta][$language->language])) {
+ * // This block should not be displayed with the active language, remove
+ * // from the list.
+ * unset($blocks[$key]);
+ * }
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_user_load
+ /**
+ * Implements hook_user_load()
+ */
+ function `Filename()`_user_load($users) {
+ /*
+ *$result = db_query('SELECT * FROM {my_table} WHERE uid IN (:uids)', array(':uids' => array_keys($users)));
+ *foreach ($result as $record) {
+ * $users[$record->uid]->foo = $result->foo;
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_user_delete
+ /**
+ * Implements hook_user_delete()
+ */
+ function `Filename()`_user_delete($account) {
+ db_delete('${1}')
+ ->condition('uid', $account->uid)
+ ->execute();
+ }
+snippet hook_user_cancel
+ /**
+ * Implements hook_user_cancel()
+ */
+ function `Filename()`_user_cancel($edit, $account, $method) {
+ switch ($method) {
+ /*
+ *case 'user_cancel_block_unpublish':
+ * // Unpublish nodes (current revisions).
+ * module_load_include('inc', 'node', 'node.admin');
+ * $nodes = db_select('node', 'n')
+ * ->fields('n', array('nid'))
+ * ->condition('uid', $account->uid)
+ * ->execute()
+ * ->fetchCol();
+ * node_mass_update($nodes, array('status' => 0));
+ * break;
+ */
+ case '${1}':
+ ${2:/* Your code here */}
+ break;
+ }
+ }
+snippet hook_user_cancel_methods_alter
+ /**
+ * Implements hook_user_cancel_methods_alter()
+ */
+ function `Filename()`_user_cancel_methods_alter(&$methods) {
+ // Limit access to disable account and unpublish content method.
+ /*
+ *$methods['user_cancel_block_unpublish']['access'] = user_access('administer site configuration');
+ */
+ // Remove the content re-assigning method.
+ /*
+ *unset($methods['user_cancel_reassign']);
+ */
+ // Add a custom zero-out method.
+ /*
+ *$methods['mymodule_zero_out'] = array(
+ * 'title' => t('Delete the account and remove all content.'),
+ * 'description' => t('All your content will be replaced by empty strings.'),
+ * // access should be used for administrative methods only.
+ * 'access' => user_access('access zero-out account cancellation method'),
+ *);
+ */
+ $methods['${1}']${2}
+ }
+snippet hook_user_operations
+ /**
+ * Implements hook_user_operations()
+ */
+ function `Filename()`_user_operations() {
+ $operations = array(
+ /*
+ *'unblock' => array(
+ * 'label' => t('Unblock the selected users'),
+ * 'callback' => 'user_user_operations_unblock',
+ *),
+ */
+ '${1}' => array(
+ 'label' => t('${2}'),
+ 'callback' => '${3}',
+ ),
+ );
+ return $operations;
+ }
+snippet hook_user_categories
+ /**
+ * Implements hook_user_categories()
+ */
+ function `Filename()`_user_categories() {
+ return array(array(
+ /*
+ *'name' => 'account',
+ *'title' => t('Account settings'),
+ *'weight' => 1,
+ */
+ 'name' => '${1}',
+ 'title' => t('${2}'),
+ 'weight' => ${3},
+ ));
+ }
+snippet hook_user_presave
+ /**
+ * Implements hook_user_presave()
+ */
+ function `Filename()`_user_presave(&$edit, $account, $category) {
+ // make sure that our form value 'mymodule_foo' is stored as 'mymodule_bar'.
+ /*
+ *if (isset($edit['mymodule_foo'])) {
+ * $edit['data']['my_module_foo'] = $edit['my_module_foo'];
+ *}
+ */
+ ${1:/* your code here */}
+ }
+snippet hook_user_insert
+ /**
+ * Implements hook_user_insert()
+ */
+ function `Filename()`_user_insert(&$edit, $account, $category) {
+ db_insert('${1}')
+ ->fields(array(
+ '${2}' => $edit['${3}'],
+ 'uid' => $account->uid,
+ ))
+ ->execute();
+ }
+snippet hook_user_update
+ /**
+ * Implements hook_user_update()
+ */
+ function `Filename()`_user_update(&$edit, $account, $category) {
+ db_insert('${1}')
+ ->fields(array(
+ 'uid' => $account->uid,
+ 'changed' => time(),
+ ))
+ ->execute();
+ }
+snippet hook_user_login
+ /**
+ * Implements hook_user_login()
+ */
+ function `Filename()`_user_login(&$edit, $account) {
+ // If the user has a NULL time zone, notify them to set a time zone.
+ /*
+ *if (!$user->timezone && variable_get('configurable_timezones', 1) && variable_get('empty_timezone_message', 0)) {
+ * drupal_set_message(t('Configure your <a href="@user-edit">account time zone setting</a>.', array('@user-edit' => url("user/$user->uid/edit", array('query' => drupal_get_destination(), 'fragment' => 'edit-timezone')))));
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_user_logout
+ /**
+ * Implements hook_user_logout()
+ */
+ function `Filename()`_user_logout($account) {
+ db_insert('${1}')
+ ->fields(array(
+ 'uid' => $account->uid,
+ 'time' => time(),
+ ))
+ ->execute();
+ }
+snippet hook_user_view
+ /**
+ * Implements hook_user_view()
+ */
+ function `Filename()`_user_view($account, $view_mode, $langcode) {
+ /*
+ *if (user_access('create blog content', $account)) {
+ * $account->content['summary']['blog'] = array(
+ * '#type' => 'user_profile_item',
+ * '#title' => t('Blog'),
+ * '#markup' => l(t('View recent blog entries'), "blog/$account->uid", array('attributes' => array('title' => t("Read !username's latest blog entries.", array('!username' => format_username($account)))))),
+ * '#attributes' => array('class' => array('blog')),
+ * );
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_user_view_alter
+ /**
+ * Implements hook_user_view_alter()
+ */
+ function `Filename()`_user_view_alter(&$build) {
+ // Check for the existence of a field added by another module.
+ /*
+ *if (isset($build['an_additional_field'])) {
+ * // Change its weight.
+ * $build['an_additional_field']['#weight'] = -10;
+ *}
+ */
+ // Add a #post_render callback to act on the rendered HTML of the user.
+ /*
+ *$build['#post_render'][] = 'my_module_user_post_render';
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_user_role_insert
+ /**
+ * Implements hook_user_role_insert()
+ */
+ function `Filename()`_user_role_insert($role) {
+ // Save extra fields provided by the module to user roles.
+ db_insert('${1}')
+ ->fields(array(
+ 'rid' => $role->rid,
+ 'role_description' => $role->description,
+ ))
+ ->execute();
+ }
+snippet hook_user_role_update
+ /**
+ * Implements hook_user_role_update()
+ */
+ function `Filename()`_user_role_update($role) {
+ // Save extra fields provided by the module to user roles.
+ db_merge('${1}')
+ ->key(array('rid' => $role->rid))
+ ->fields(array(
+ 'role_description' => $role->description
+ ))
+ ->execute();
+ }
+snippet hook_user_role_delete
+ /**
+ * Implements hook_user_role_delete()
+ */
+ function `Filename()`_user_role_delete($role) {
+ // Delete existing instances of the deleted role.
+ db_delete('${1}')
+ ->condition('rid', $role->rid)
+ ->execute();
+ }
+snippet hook_taxonomy_vocabulary_load
+ /**
+ * Implements hook_taxonomy_vocabulary_load()
+ */
+ function `Filename()`_taxonomy_vocabulary_load($vocabularies) {
+ foreach ($vocabularies as $vocabulary) {
+ /*
+ *$vocabulary->synonyms = variable_get('taxonomy_' . $vocabulary->vid . '_synonyms', FALSE);
+ */
+ ${1:/* Your code here */}
+ }
+ }
+snippet hook_taxonomy_vocabulary_presave
+ /**
+ * Implements hook_taxonomy_vocabulary_presave()
+ */
+ function `Filename()`_taxonomy_vocabulary_presave($vocabulary) {
+ /*
+ *$vocabulary->foo = 'bar';
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_taxonomy_vocabulary_insert
+ /**
+ * Implements hook_taxonomy_vocabulary_insert()
+ */
+ function `Filename()`_taxonomy_vocabulary_insert($vocabulary) {
+ /*
+ *if ($vocabulary->synonyms) {
+ * variable_set('taxonomy_' . $vocabulary->vid . '_synonyms', TRUE);
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_taxonomy_vocabulary_update
+ /**
+ * Implements hook_taxonomy_vocabulary_update()
+ */
+ function `Filename()`_taxonomy_vocabulary_update($vocabulary) {
+ /*
+ *$status = $vocabulary->synonyms ? TRUE : FALSE;
+ *if ($vocabulary->synonyms) {
+ * variable_set('taxonomy_' . $vocabulary->vid . '_synonyms', $status);
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_taxonomy_vocabulary_delete
+ /**
+ * Implements hook_taxonomy_vocabulary_delete()
+ */
+ function `Filename()`_taxonomy_vocabulary_delete($vocabulary) {
+ /*
+ *if (variable_get('taxonomy_' . $vocabulary->vid . '_synonyms', FALSE)) {
+ * variable_del('taxonomy_' . $vocabulary->vid . '_synonyms');
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_taxonomy_term_load
+ /**
+ * Implements hook_taxonomy_term_load()
+ */
+ function `Filename()`_taxonomy_term_load($terms) {
+ /*
+ *$result = db_query('SELECT tid, foo FROM {mytable} WHERE tid IN (:tids)', array(':tids' => array_keys($terms)));
+ *foreach ($result as $record) {
+ * $terms[$record->tid]->foo = $record->foo;
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_taxonomy_term_presave
+ /**
+ * Implements hook_taxonomy_term_presave()
+ */
+ function `Filename()`_taxonomy_term_presave($term) {
+ /*
+ *$term->foo = 'bar';
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_taxonomy_term_insert
+ /**
+ * Implements hook_taxonomy_term_insert()
+ */
+ function `Filename()`_taxonomy_term_insert($term) {
+ /*
+ *if (!empty($term->synonyms)) {
+ * foreach (explode ("\n", str_replace("\r", '', $term->synonyms)) as $synonym) {
+ * if ($synonym) {
+ * db_insert('taxonomy_term_synonym')
+ * ->fields(array(
+ * 'tid' => $term->tid,
+ * 'name' => rtrim($synonym),
+ * ))
+ * ->execute();
+ * }
+ * }
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_taxonomy_term_update
+ /**
+ * Implements hook_taxonomy_term_update()
+ */
+ function `Filename()`_taxonomy_term_update($term) {
+ /*
+ *hook_taxonomy_term_delete($term);
+ *if (!empty($term->synonyms)) {
+ * foreach (explode ("\n", str_replace("\r", '', $term->synonyms)) as $synonym) {
+ * if ($synonym) {
+ * db_insert('taxonomy_term_synonym')
+ * ->fields(array(
+ * 'tid' => $term->tid,
+ * 'name' => rtrim($synonym),
+ * ))
+ * ->execute();
+ * }
+ * }
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_taxonomy_term_delete
+ /**
+ * Implements hook_taxonomy_term_delete()
+ */
+ function `Filename()`_taxonomy_term_delete($term) {
+ /*
+ *db_delete('term_synoynm')->condition('tid', $term->tid)->execute();
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_openid
+ /**
+ * Implements hook_openid()
+ */
+ function `Filename()`_openid($op, $request) {
+ /*
+ *if ($op == 'request') {
+ * $request['openid.identity'] = 'http://myname.myopenid.com/';
+ *}
+ */
+ ${1:/* Your code here */}
+
+ return $request;
+ }
+snippet hook_openid_response
+ /**
+ * Implements hook_openid_response()
+ */
+ function `Filename()`_openid_response($response, $account) {
+ /*
+ *if (isset($response['openid.ns.ax'])) {
+ * _mymodule_store_ax_fields($response, $account);
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_openid_discovery_method_info
+ /**
+ * Implements hook_openid_discovery_method_info()
+ */
+ function `Filename()`_openid_discovery_method_info() {
+ return array(
+ '${1}' => '${2}',
+ );
+ }
+snippet hook_openid_discovery_method_info_alter
+ /**
+ * Implements hook_openid_discovery_method_info_alter()
+ */
+ function `Filename()`_openid_discovery_method_info_alter(&$methods) {
+ // Remove XRI discovery scheme.
+ /*
+ *unset($methods['xri']);
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_openid_normalization_method_info
+ /**
+ * Implements hook_openid_normalization_method_info()
+ */
+ function `Filename()`_openid_normalization_method_info() {
+ return array(
+ /*
+ *'new_discovery_idea' => '_my_discovery_method',
+ */
+ '${1}' => '${2}',
+ );
+ }
+snippet hook_openid_normalization_method_info_alter
+ /**
+ * Implements hook_openid_normalization_method_info_alter()
+ */
+ function `Filename()`_openid_normalization_method_info_alter(&$methods) {
+ // Remove Google IDP normalization.
+ /*
+ *unset($methods['google_idp']);
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_filter_info
+ /**
+ * Implements hook_filter_info()
+ */
+ function `Filename()`_filter_info() {
+ /*
+ *$filters['filter_html'] = array(
+ * 'title' => t('Limit allowed HTML tags'),
+ * 'description' => t('Allows you to restrict the HTML tags the user can use. It will also remove harmful content such as JavaScript events, JavaScript URLs and CSS styles from those tags that are not removed.'),
+ * 'process callback' => '_filter_html',
+ * 'settings callback' => '_filter_html_settings',
+ * 'default settings' => array(
+ * 'allowed_html' => '<a> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd>',
+ * 'filter_html_help' => 1,
+ * 'filter_html_nofollow' => 0,
+ * ),
+ * 'tips callback' => '_filter_html_tips',
+ *);
+ *$filters['filter_autop'] = array(
+ * 'title' => t('Convert line breaks'),
+ * 'description' => t('Converts line breaks into HTML (i.e. &lt;br&gt; and &lt;p&gt;) tags.'),
+ * 'process callback' => '_filter_autop',
+ * 'tips callback' => '_filter_autop_tips',
+ *);
+ *return $filters;
+ */
+ $filters['${1}'] = array(
+ 'title' => t('${2}'),
+ 'description' => t('${3}'),
+ 'process callback' => '${4}',
+ 'settings callback' => '${5}',
+ 'default settings' => array(
+ 'allowed_html' => '${6}',
+ 'filter_html_help' => ${7},
+ 'filter_html_nofollow' => ${8},
+ ),
+ 'tips callback' => '${9}',
+ );
+ return $filters;
+ }
+snippet hook_filter_info_alter
+ /**
+ * Implements hook_filter_info_alter()
+ */
+ function `Filename()`_filter_info_alter(&$info) {
+ // Replace the PHP evaluator process callback with an improved
+ // PHP evaluator provided by a module.
+ /*
+ *$info['php_code']['process callback'] = 'my_module_php_evaluator';
+ */
+ // Alter the default settings of the URL filter provided by core.
+ /*
+ *$info['filter_url']['default settings'] = array(
+ * 'filter_url_length' => 100,
+ *);
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_filter_format_insert
+ /**
+ * Implements hook_filter_format_insert()
+ */
+ function `Filename()`_filter_format_insert($format) {
+ /*
+ *mymodule_cache_rebuild();
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_filter_format_update
+ /**
+ * Implements hook_filter_format_update()
+ */
+ function `Filename()`_filter_format_update($format) {
+ /*
+ *mymodule_cache_rebuild();
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_filter_format_disable
+ /**
+ * Implements hook_filter_format_disable()
+ */
+ function `Filename()`_filter_format_disable($format) {
+ /*
+ *mymodule_cache_rebuild();
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_rdf_mapping
+ /**
+ * Implements hook_rdf_mapping()
+ */
+ function `Filename()`_rdf_mapping() {
+ return array(
+ array(
+ /*
+ *'type' => 'node',
+ *'bundle' => 'blog',
+ *'mapping' => array(
+ * 'rdftype' => array('sioct:Weblog'),
+ * 'title' => array(
+ * 'predicates' => array('dc:title'),
+ * ),
+ * 'created' => array(
+ * 'predicates' => array('dc:date', 'dc:created'),
+ * 'datatype' => 'xsd:dateTime',
+ * 'callback' => 'date_iso8601',
+ * ),
+ * 'body' => array(
+ * 'predicates' => array('content:encoded'),
+ * ),
+ * 'uid' => array(
+ * 'predicates' => array('sioc:has_creator'),
+ * 'type' => 'rel',
+ * ),
+ * 'name' => array(
+ * 'predicates' => array('foaf:name'),
+ * ),
+ */
+ 'type' => '${1}',
+ 'bundle' => '${2}',
+ 'mapping' => array(
+ 'rdftype' => array('${3}'),
+ 'title' => array(
+ 'predicates' => array('${4}'),
+ ),
+ 'created' => array(
+ 'predicates' => array('${5}'),
+ 'datatype' => '${6}',
+ 'callback' => '${7}',
+ ),
+ 'body' => array(
+ 'predicates' => array('${8}'),
+ ),
+ 'uid' => array(
+ 'predicates' => array('${9}'),
+ 'type' => '${10}',
+ ),
+ 'name' => array(
+ 'predicates' => array('${11}'),
+ ),
+ ),
+ ),
+ );
+ }
+snippet hook_rdf_namespaces
+ /**
+ * Implements hook_rdf_namespaces()
+ */
+ function `Filename()`_rdf_namespaces() {
+ return array(
+ /*
+ *'content' => 'http://purl.org/rss/1.0/modules/content/',
+ *'dc' => 'http://purl.org/dc/terms/',
+ *'foaf' => 'http://xmlns.com/foaf/0.1/',
+ *'og' => 'http://ogp.me/ns#',
+ *'rdfs' => 'http://www.w3.org/2000/01/rdf-schema#',
+ *'sioc' => 'http://rdfs.org/sioc/ns#',
+ *'sioct' => 'http://rdfs.org/sioc/types#',
+ *'skos' => 'http://www.w3.org/2004/02/skos/core#',
+ *'xsd' => 'http://www.w3.org/2001/XMLSchema#',
+ */
+ '${1}' => '${2}',
+ );
+ }
+snippet hook_field_settings_form
+ /**
+ * Implements hook_field_settings_form()
+ */
+ function `Filename()`_field_settings_form($field, $instance, $has_data) {
+ /*
+ *$settings = $field['settings'];
+ *$form['max_length'] = array(
+ * '#type' => 'textfield',
+ * '#title' => t('Maximum length'),
+ * '#default_value' => $settings['max_length'],
+ * '#required' => FALSE,
+ * '#element_validate' => array('_element_validate_integer_positive'),
+ * '#description' => t('The maximum length of the field in characters. Leave blank for an unlimited size.'),
+ *);
+ */
+ $settings = $field['settings'];
+ $form['${1}'] = array(
+ '#type' => '${2}',
+ '#title' => t('${3}'),
+ '#default_value' => $settings['${4}'],
+ '#required' => ${5},
+ '#element_validate' => array('${6}'),
+ '#description' => t('${7}'),
+ '#${8}' => ${9}
+ );
+ return $form;
+ }
+snippet hook_field_instance_settings_form
+ /**
+ * Implements hook_field_instance_settings_form()
+ */
+ function `Filename()`_field_instance_settings_form($field, $instance) {
+ /*
+ * $settings = $instance['settings'];
+ *
+ * $form['text_processing'] = array(
+ * '#type' => 'radios',
+ * '#title' => t('Text processing'),
+ * '#default_value' => $settings['text_processing'],
+ * '#options' => array(
+ * t('Plain text'),
+ * t('Filtered text (user selects text format)'),
+ * ),
+ * );
+ * if ($field['type'] == 'text_with_summary') {
+ * $form['display_summary'] = array(
+ * '#type' => 'select',
+ * '#title' => t('Display summary'),
+ * '#options' => array(
+ * t('No'),
+ * t('Yes'),
+ * ),
+ * '#description' => t('Display the summary to allow the user to input a summary value. Hide the summary to automatically fill it with a trimmed portion from the main post. '),
+ * '#default_value' => !empty($settings['display_summary']) ? $settings['display_summary'] : 0,
+ * );
+ * }
+ */
+ $settings = $instance['settings'];
+ $form['${1}'] = array(
+ '#type' => '${2}',
+ '#title' => t('${3}'),
+ '#default_value' => $settings['${4}'],
+ '#required' => ${5},
+ '#element_validate' => array('${6}'),
+ '#description' => t('${7}'),
+ '#${8}' => ${9}
+ );
+ return $form;
+ }
+snippet hook_field_widget_settings_form
+ /**
+ * Implements hook_field_widget_settings_form()
+ */
+ function `Filename()`_field_widget_settings_form($field, $instance) {
+ $widget = $instance['widget'];
+ $settings = $widget['settings'];
+
+ /*
+ *if ($widget['type'] == 'text_textfield') {
+ * $form['size'] = array(
+ * '#type' => 'textfield',
+ * '#title' => t('Size of textfield'),
+ * '#default_value' => $settings['size'],
+ * '#element_validate' => array('_element_validate_integer_positive'),
+ * '#required' => TRUE,
+ * );
+ *}
+ *else {
+ * $form['rows'] = array(
+ * '#type' => 'textfield',
+ * '#title' => t('Rows'),
+ * '#default_value' => $settings['rows'],
+ * '#element_validate' => array('_element_validate_integer_positive'),
+ * '#required' => TRUE,
+ * );
+ *}
+ */
+ $form['${1}'] = array(
+ '#type' => '${2}',
+ '#title' => t('${3}'),
+ '#default_value' => $settings['${4}'],
+ '#required' => ${5},
+ '#element_validate' => array('${6}'),
+ '#description' => t('${7}'),
+ '#${8}' => ${9}
+ );
+ return $form;
+ }
+snippet hook_field_formatter_settings_form
+ /**
+ * Implements hook_field_formatter_settings_form()
+ */
+ function `Filename()`_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
+ $display = $instance['display'][$view_mode];
+ $settings = $display['settings'];
+
+ /*
+ *if ($display['type'] == 'text_trimmed' || $display['type'] == 'text_summary_or_trimmed') {
+ * $element['trim_length'] = array(
+ * '#title' => t('Length'),
+ * '#type' => 'textfield',
+ * '#size' => 20,
+ * '#default_value' => $settings['trim_length'],
+ * '#element_validate' => array('_element_validate_integer_positive'),
+ * '#required' => TRUE,
+ * );
+ *}
+ */
+ $element['${1}'] = array(
+ '#type' => '${2}',
+ '#title' => t('${3}'),
+ '#default_value' => $settings['${4}'],
+ '#required' => ${5},
+ '#element_validate' => array('${6}'),
+ '#description' => t('${7}'),
+ '#${8}' => ${9}
+ );
+
+ return $element;
+
+ }
+snippet hook_field_formatter_settings_summary
+ /**
+ * Implements hook_field_formatter_settings_summary()
+ */
+ function `Filename()`_field_formatter_settings_summary($field, $instance, $view_mode) {
+ /*
+ *$display = $instance['display'][$view_mode];
+ *$settings = $display['settings'];
+ *
+ *$summary = '';
+ *
+ *if ($display['type'] == 'text_trimmed' || $display['type'] == 'text_summary_or_trimmed') {
+ * $summary = t('Length: @chars chars', array('@chars' => $settings['trim_length']));
+ *}
+ */
+ ${1:/* Your code here */}
+
+ return $summary;
+ }
+snippet hook_field_extra_fields
+ /**
+ * Implements hook_field_extra_fields()
+ */
+ function `Filename()`_field_extra_fields() {
+ /*
+ *$extra['node']['poll'] = array(
+ * 'form' => array(
+ * 'choice_wrapper' => array(
+ * 'label' => t('Poll choices'),
+ * 'description' => t('Poll choices'),
+ * 'weight' => -4,
+ * ),
+ * 'settings' => array(
+ * 'label' => t('Poll settings'),
+ * 'description' => t('Poll module settings'),
+ * 'weight' => -3,
+ * ),
+ * ),
+ * 'display' => array(
+ * 'poll_view_voting' => array(
+ * 'label' => t('Poll vote'),
+ * 'description' => t('Poll vote'),
+ * 'weight' => 0,
+ * ),
+ * 'poll_view_results' => array(
+ * 'label' => t('Poll results'),
+ * 'description' => t('Poll results'),
+ * 'weight' => 0,
+ * ),
+ * )
+ *);
+ */
+ $extra['${1}']['${2}'] = array(
+ 'form' => array(
+ '${3}' => array(
+ 'label' => t('${4}'),
+ 'description' => t('${5}'),
+ 'weight' => ${6},
+ ),
+ ),
+ 'display' => array(
+ '${7}' => array(
+ 'label' => t('${8}'),
+ 'description' => t('${9}'),
+ 'weight' => ${10},
+ ),
+ )
+ );
+
+ return $extra;
+ }
+snippet hook_field_extra_fields_alter
+ /**
+ * Implements hook_field_extra_fields_alter()
+ */
+ function `Filename()`_field_extra_fields_alter(&$info) {
+ // Force node title to always be at the top of the list by default.
+ /*
+ *foreach (node_type_get_types() as $bundle) {
+ * if (isset($info['node'][$bundle]['title'])) {
+ * $info['node'][$bundle]['title']['weight'] = -20;
+ * }
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_field_info
+ /**
+ * Implements hook_field_info()
+ */
+ function `Filename()`_field_info() {
+ return array(
+ /*
+ *'text' => array(
+ * 'label' => t('Text'),
+ * 'description' => t('This field stores varchar text in the database.'),
+ * 'settings' => array('max_length' => 255),
+ * 'instance_settings' => array('text_processing' => 0),
+ * 'default_widget' => 'text_textfield',
+ * 'default_formatter' => 'text_default',
+ *),
+ */
+ '${1}' => array(
+ 'label' => t('${2}'),
+ 'description' => t('${3}'),
+ 'settings' => array('${4}' => ${5}),
+ 'instance_settings' => array('${6}' => ${7}),
+ 'default_widget' => '${8}',
+ 'default_formatter' => '${9}',
+ ),
+ );
+ }
+snippet hook_field_info_alter
+ /**
+ * Implements hook_field_info_alter()
+ */
+ function `Filename()`_field_info_alter(&$info) {
+ // Add a setting to all field types.
+ /*
+ *foreach ($info as $field_type => $field_type_info) {
+ * $info[$field_type]['settings'] += array(
+ * 'mymodule_additional_setting' => 'default value',
+ * );
+ *}
+ */
+ // Change the default widget for fields of type 'foo'.
+ /*
+ *if (isset($info['foo'])) {
+ * $info['foo']['default widget'] = 'mymodule_widget';
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_field_schema
+ /**
+ * Implements hook_field_schema()
+ */
+ function `Filename()`_field_schema($field) {
+ /*
+ *if ($field['type'] == 'text_long') {
+ * $columns = array(
+ * 'value' => array(
+ * 'type' => 'text',
+ * 'size' => 'big',
+ * 'not null' => FALSE,
+ * ),
+ * );
+ *}
+ *else {
+ * $columns = array(
+ * 'value' => array(
+ * 'type' => 'varchar',
+ * 'length' => $field['settings']['max_length'],
+ * 'not null' => FALSE,
+ * ),
+ * );
+ *}
+ *$columns += array(
+ * 'format' => array(
+ * 'type' => 'int',
+ * 'unsigned' => TRUE,
+ * 'not null' => FALSE,
+ * ),
+ *);
+ *return array(
+ * 'columns' => $columns,
+ * 'indexes' => array(
+ * 'format' => array('format'),
+ * ),
+ *);
+ */
+ $columns = array(
+ '${1}' => array(
+ 'type' => '${2}',
+ 'length' => ${3},
+ 'unsigned' => ${4},
+ 'not null' => ${5},
+ ),
+ );
+ $columns = array(
+ '${6}' => array(
+ 'type' => '${7}',
+ 'length' => ${8},
+ 'unsigned' => ${9},
+ 'not null' => ${10},
+ ),
+ );
+ return array(
+ 'columns' => $columns,
+ 'indexes' => array(
+ '${11}' => array('${12}'),
+ ),
+ );
+ }
+snippet hook_field_load
+ /**
+ * Implements hook_field_load()
+ */
+ function `Filename()`_field_load($entity_type, $entities, $field, $instances, $langcode, &$items, $age) {
+ // Sample code from text.module: precompute sanitized strings so they are
+ // stored in the field cache.
+ /*
+ *foreach ($entities as $id => $entity) {
+ * foreach ($items[$id] as $delta => $item) {
+ * // Only process items with a cacheable format, the rest will be handled
+ * // by formatters if needed.
+ * if (empty($instances[$id]['settings']['text_processing']) || filter_format_allowcache($item['format'])) {
+ * $items[$id][$delta]['safe_value'] = isset($item['value']) ? _text_sanitize($instances[$id], $langcode, $item, 'value') : '';
+ * if ($field['type'] == 'text_with_summary') {
+ * $items[$id][$delta]['safe_summary'] = isset($item['summary']) ? _text_sanitize($instances[$id], $langcode, $item, 'summary') : '';
+ * }
+ * }
+ * }
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_field_prepare_view
+ /**
+ * Implements hook_field_prepare_view()
+ */
+ function `Filename()`_field_prepare_view($entity_type, $entities, $field, $instances, $langcode, &$items) {
+ // Sample code from image.module: if there are no images specified at all,
+ // use the default image.
+ /*
+ *foreach ($entities as $id => $entity) {
+ * if (empty($items[$id]) && $field['settings']['default_image']) {
+ * if ($file = file_load($field['settings']['default_image'])) {
+ * $items[$id][0] = (array) $file + array(
+ * 'is_default' => TRUE,
+ * 'alt' => '',
+ * 'title' => '',
+ * );
+ * }
+ * }
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_field_validate
+ /**
+ * Implements hook_field_validate()
+ */
+ function `Filename()`_field_validate($entity_type, $entity, $field, $instance, $langcode, $items, &$errors) {
+ foreach ($items as $delta => $item) {
+ if (!empty($item['value'])) {
+ /*
+ *if (!empty($field['settings']['max_length']) && drupal_strlen($item['value']) > $field['settings']['max_length']) {
+ * $errors[$field['field_name']][$delta][] = array(
+ * 'error' => 'text_max_length',
+ * 'message' => t('%name: the value may not be longer than %max characters.', array('%name' => $instance['label'], '%max' => $field['settings']['max_length'])),
+ * );
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+ }
+ }
+snippet hook_field_presave
+ /**
+ * Implements hook_field_presave()
+ */
+ function `Filename()`_field_presave($entity_type, $entity, $field, $instance, $langcode, &$items) {
+ if ($field['type'] == '${1}') {
+ // Let PHP round the value to ensure consistent behavior across storage
+ // backends.
+ foreach ($items as $delta => $item) {
+ /*
+ *if (isset($item['value'])) {
+ * $items[$delta]['value'] = round($item['value'], $field['settings']['scale']);
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+ }
+ }
+snippet hook_field_insert
+ /**
+ * Implements hook_field_insert()
+ */
+ function `Filename()`_field_insert($entity_type, $entity, $field, $instance, $langcode, &$items) {
+ /*
+ *if (variable_get('taxonomy_maintain_index_table', TRUE) && $field['storage']['type'] == 'field_sql_storage' && $entity_type == 'node' && $entity->status) {
+ * $query = db_insert('taxonomy_index')->fields(array('nid', 'tid', 'sticky', 'created', ));
+ * foreach ($items as $item) {
+ * $query->values(array(
+ * 'nid' => $entity->nid,
+ * 'tid' => $item['tid'],
+ * 'sticky' => $entity->sticky,
+ * 'created' => $entity->created,
+ * ));
+ * }
+ * $query->execute();
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_field_update
+ /**
+ * Implements hook_field_update()
+ */
+ function `Filename()`_field_update($entity_type, $entity, $field, $instance, $langcode, &$items) {
+ /*
+ *if (variable_get('taxonomy_maintain_index_table', TRUE) && $field['storage']['type'] == 'field_sql_storage' && $entity_type == 'node') {
+ * $first_call = &drupal_static(__FUNCTION__, array());
+ *
+ * // We don't maintain data for old revisions, so clear all previous values
+ * // from the table. Since this hook runs once per field, per object, make
+ * // sure we only wipe values once.
+ * if (!isset($first_call[$entity->nid])) {
+ * $first_call[$entity->nid] = FALSE;
+ * db_delete('taxonomy_index')->condition('nid', $entity->nid)->execute();
+ * }
+ * // Only save data to the table if the node is published.
+ * if ($entity->status) {
+ * $query = db_insert('taxonomy_index')->fields(array('nid', 'tid', 'sticky', 'created'));
+ * foreach ($items as $item) {
+ * $query->values(array(
+ * 'nid' => $entity->nid,
+ * 'tid' => $item['tid'],
+ * 'sticky' => $entity->sticky,
+ * 'created' => $entity->created,
+ * ));
+ * }
+ * $query->execute();
+ * }
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_field_storage_update_field
+ /**
+ * Implements hook_field_storage_update_field()
+ */
+ function `Filename()`_field_storage_update_field($field, $prior_field, $has_data) {
+ if (!$has_data) {
+ // There is no data. Re-create the tables completely.
+ /*
+ *$prior_schema = _field_sql_storage_schema($prior_field);
+ *foreach ($prior_schema as $name => $table) {
+ * db_drop_table($name, $table);
+ *}
+ *$schema = _field_sql_storage_schema($field);
+ *foreach ($schema as $name => $table) {
+ * db_create_table($name, $table);
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+ else {
+ // There is data. See field_sql_storage_field_storage_update_field() for
+ // an example of what to do to modify the schema in place, preserving the
+ // old data as much as possible.
+ ${2:/* Your code here */}
+ }
+ drupal_get_schema(NULL, TRUE);
+ }
+snippet hook_field_delete
+ /**
+ * Implements hook_field_delete()
+ */
+ function `Filename()`_field_delete($entity_type, $entity, $field, $instance, $langcode, &$items) {
+ list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
+ foreach ($items as $delta => $item) {
+ // For hook_file_references(), remember that this is being deleted.
+ /*
+ *$item['file_field_name'] = $field['field_name'];
+ */
+ // Pass in the ID of the object that is being removed so all references can
+ // be counted in hook_file_references().
+ /*
+ *$item['file_field_type'] = $entity_type;
+ *$item['file_field_id'] = $id;
+ *file_field_delete_file($item, $field);
+ */
+ ${1:/* Your code here */}
+ }
+ }
+snippet hook_field_delete_revision
+ /**
+ * Implements hook_field_delete_revision()
+ */
+ function `Filename()`_field_delete_revision($entity_type, $entity, $field, $instance, $langcode, &$items) {
+ foreach ($items as $delta => $item) {
+ // For hook_file_references, remember that this file is being deleted.
+ /*
+ *$item['file_field_name'] = $field['field_name'];
+ *if (file_field_delete_file($item, $field)) {
+ * $items[$delta] = NULL;
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+ }
+snippet hook_field_prepare_translation
+ /**
+ * Implements hook_field_prepare_translation()
+ */
+ function `Filename()`_field_prepare_translation($entity_type, $entity, $field, $instance, $langcode, &$items, $source_entity, $source_langcode) {
+ // If the translating user is not permitted to use the assigned text format,
+ // we must not expose the source values.
+ /*
+ *$field_name = $field['field_name'];
+ *$formats = filter_formats();
+ *$format_id = $source_entity->{$field_name}[$source_langcode][0]['format'];
+ *if (!filter_access($formats[$format_id])) {
+ * $items = array();
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_field_is_empty
+ /**
+ * Implements hook_field_is_empty()
+ */
+ function `Filename()`_field_is_empty($item, $field) {
+ /*
+ *if (empty($item['value']) && (string) $item['value'] !== '0') {
+ * return TRUE;
+ *}
+ *return FALSE;
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_field_widget_info
+ /**
+ * Implements hook_field_widget_info()
+ */
+ function `Filename()`_field_widget_info() {
+ return array(
+ /*
+ *'text_textfield' => array(
+ * 'label' => t('Text field'),
+ * 'field types' => array('text'),
+ * 'settings' => array('size' => 60),
+ * 'behaviors' => array(
+ * 'multiple values' => FIELD_BEHAVIOR_DEFAULT,
+ * 'default value' => FIELD_BEHAVIOR_DEFAULT,
+ * ),
+ *),
+ */
+ '${1}' => array(
+ 'label' => t('${2}'),
+ 'field types' => array('${3}'),
+ 'settings' => array('${4}' => ${5}),
+ 'behaviors' => array(
+ 'multiple values' => ${6}FIELD_BEHAVIOR_DEFAULT,
+ 'default value' => ${7}FIELD_BEHAVIOR_DEFAULT,
+ ),
+ ),
+ );
+ }
+snippet hook_field_widget_info_alter
+ /**
+ * Implements hook_field_widget_info_alter()
+ */
+ function `Filename()`_field_widget_info_alter(&$info) {
+ // Add a setting to a widget type.
+ /*
+ *$info['text_textfield']['settings'] += array(
+ * 'mymodule_additional_setting' => 'default value',
+ *);
+ */
+ // Let a new field type re-use an existing widget.
+ /*
+ *$info['options_select']['field types'][] = 'my_field_type';
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_field_widget_form
+ /**
+ * Implements hook_field_widget_form()
+ */
+ function `Filename()`_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
+ /*
+ *$element += array(
+ * '#type' => $instance['widget']['type'],
+ * '#default_value' => isset($items[$delta]) ? $items[$delta] : '',
+ *);
+ */
+ $element += array(
+ '#type' => ${1},
+ '#default_value' => ${2},
+ );
+ return $element;
+ }
+snippet hook_field_widget_error
+ /**
+ * Implements hook_field_widget_error()
+ */
+ function `Filename()`_field_widget_error($element, $error, $form, &$form_state) {
+ /*
+ *form_error($element['value'], $error['message']);
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_field_formatter_info
+ /**
+ * Implements hook_field_formatter_info()
+ */
+ function `Filename()`_field_formatter_info() {
+ return array(
+ /*
+ *'text_default' => array(
+ * 'label' => t('Default'),
+ * 'field types' => array('text', 'text_long', 'text_with_summary'),
+ *),
+ */
+ '${1}' => array(
+ 'label' => t('${2}'),
+ 'field types' => array('${3}'),
+ ),
+ );
+ }
+snippet hook_field_formatter_info_alter
+ /**
+ * Implements hook_field_formatter_info_alter()
+ */
+ function `Filename()`_field_formatter_info_alter(&$info) {
+ // Add a setting to a formatter type.
+ /*
+ *$info['text_default']['settings'] += array(
+ * 'mymodule_additional_setting' => 'default value',
+ *);
+ */
+ // Let a new field type re-use an existing formatter.
+ /*
+ *$info['text_default']['field types'][] = 'my_field_type';
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_field_formatter_prepare_view
+ /**
+ * Implements hook_field_formatter_prepare_view()
+ */
+ function `Filename()`_field_formatter_prepare_view($entity_type, $entities, $field, $instances, $langcode, &$items, $displays) {
+ /*
+ * $tids = array();
+ *
+ * // Collect every possible term attached to any of the fieldable entities.
+ * foreach ($entities as $id => $entity) {
+ * foreach ($items[$id] as $delta => $item) {
+ * // Force the array key to prevent duplicates.
+ * $tids[$item['tid']] = $item['tid'];
+ * }
+ * }
+ *
+ * if ($tids) {
+ * $terms = taxonomy_term_load_multiple($tids);
+ *
+ * // Iterate through the fieldable entities again to attach the loaded term
+ * // data.
+ * foreach ($entities as $id => $entity) {
+ * $rekey = FALSE;
+ *
+ * foreach ($items[$id] as $delta => $item) {
+ * // Check whether the taxonomy term field instance value could be loaded.
+ * if (isset($terms[$item['tid']])) {
+ * // Replace the instance value with the term data.
+ * $items[$id][$delta]['taxonomy_term'] = $terms[$item['tid']];
+ * }
+ * // Otherwise, unset the instance value, since the term does not exist.
+ * else {
+ * unset($items[$id][$delta]);
+ * $rekey = TRUE;
+ * }
+ * }
+ *
+ * if ($rekey) {
+ * // Rekey the items array.
+ * $items[$id] = array_values($items[$id]);
+ * }
+ * }
+ * }
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_field_formatter_view
+ /**
+ * Implements hook_field_formatter_view()
+ */
+ function `Filename()`_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
+ $element = array();
+ $settings = $display['settings'];
+
+ switch ($display['type']) {
+ /*
+ *case 'sample_field_formatter_simple':
+ * // Common case: each value is displayed individually in a sub-element
+ * // keyed by delta. The field.tpl.php template specifies the markup
+ * // wrapping each value.
+ * foreach ($items as $delta => $item) {
+ * $element[$delta] = array('#markup' => $settings['some_setting'] . $item['value']);
+ * }
+ * break;
+ *
+ *case 'sample_field_formatter_themeable':
+ * // More elaborate formatters can defer to a theme function for easier
+ * // customization.
+ * foreach ($items as $delta => $item) {
+ * $element[$delta] = array(
+ * '#theme' => 'mymodule_theme_sample_field_formatter_themeable',
+ * '#data' => $item['value'],
+ * '#some_setting' => $settings['some_setting'],
+ * );
+ * }
+ * break;
+ *
+ *case 'sample_field_formatter_combined':
+ * // Some formatters might need to display all values within a single piece
+ * // of markup.
+ * $rows = array();
+ * foreach ($items as $delta => $item) {
+ * $rows[] = array($delta, $item['value']);
+ * }
+ * $element[0] = array(
+ * '#theme' => 'table',
+ * '#header' => array(t('Delta'), t('Value')),
+ * '#rows' => $rows,
+ * );
+ * break;
+ */
+ case '${1}':
+ foreach ($items as $delta => $item) {
+ $element[$delta] = array(
+ '#theme' => '${2}',
+ '#data' => $item['value'],
+ '#markup' => ${3},
+ '#${4}' => $settings['${5}'],
+ );
+ }
+ break;
+ }
+
+ return $element;
+ }
+snippet hook_field_attach_form
+ /**
+ * Implements hook_field_attach_form()
+ */
+ function `Filename()`_field_attach_form($entity_type, $entity, &$form, &$form_state, $langcode) {
+ ${1:/* Your code here */}
+ }
+snippet hook_field_attach_load
+ /**
+ * Implements hook_field_attach_load()
+ */
+ function `Filename()`_field_attach_load($entity_type, &$entities, $age, $options) {
+ ${1:/* Your code here */}
+ }
+snippet hook_field_attach_validate
+ /**
+ * Implements hook_field_attach_validate()
+ */
+ function `Filename()`_field_attach_validate($entity_type, $entity, &$errors) {
+ ${1:/* Your code here */}
+ }
+snippet hook_field_attach_submit
+ /**
+ * Implements hook_field_attach_submit()
+ */
+ function `Filename()`_field_attach_submit($entity_type, $entity, $form, &$form_state) {
+ ${1:/* Your code here */}
+ }
+snippet hook_field_attach_presave
+ /**
+ * Implements hook_field_attach_presave()
+ */
+ function `Filename()`_field_attach_presave($entity_type, $entity) {
+ ${1:/* Your code here */}
+ }
+snippet hook_field_attach_insert
+ /**
+ * Implements hook_field_attach_insert()
+ */
+ function `Filename()`_field_attach_insert($entity_type, $entity) {
+ ${1:/* Your code here */}
+ }
+snippet hook_field_attach_update
+ /**
+ * Implements hook_field_attach_update()
+ */
+ function `Filename()`_field_attach_update($entity_type, $entity) {
+ ${1:/* Your code here */}
+ }
+snippet hook_field_attach_preprocess_alter
+ /**
+ * Implements hook_field_attach_preprocess_alter()
+ */
+ function `Filename()`_field_attach_preprocess_alter(&$variables, $context) {
+ ${1:/* Your code here */}
+ }
+snippet hook_field_attach_delete
+ /**
+ * Implements hook_field_attach_delete()
+ */
+ function `Filename()`_field_attach_delete($entity_type, $entity) {
+ ${1:/* Your code here */}
+ }
+snippet hook_field_attach_delete_revision
+ /**
+ * Implements hook_field_attach_delete_revision()
+ */
+ function `Filename()`_field_attach_delete_revision($entity_type, $entity) {
+ ${1:/* Your code here */}
+ }
+snippet hook_field_attach_purge
+ /**
+ * Implements hook_field_attach_purge()
+ */
+ function `Filename()`_field_attach_purge($entity_type, $entity, $field, $instance) {
+ // find the corresponding data in mymodule and purge it
+ /*
+ *if($entity_type == 'node' && $field->field_name == 'my_field_name') {
+ * mymodule_remove_mydata($entity->nid);
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_field_attach_view_alter
+ /**
+ * Implements hook_field_attach_view_alter()
+ */
+ function `Filename()`_field_attach_view_alter(&$output, $context) {
+ // Append RDF term mappings on displayed taxonomy links.
+ /*
+ *foreach (element_children($output) as $field_name) {
+ * $element = &$output[$field_name];
+ * if ($element['#field_type'] == 'taxonomy_term_reference' && $element['#formatter'] == 'taxonomy_term_reference_link') {
+ * foreach ($element['#items'] as $delta => $item) {
+ * $term = $item['taxonomy_term'];
+ * if (!empty($term->rdf_mapping['rdftype'])) {
+ * $element[$delta]['#options']['attributes']['typeof'] = $term->rdf_mapping['rdftype'];
+ * }
+ * if (!empty($term->rdf_mapping['name']['predicates'])) {
+ * $element[$delta]['#options']['attributes']['property'] = $term->rdf_mapping['name']['predicates'];
+ * }
+ * }
+ * }
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_field_attach_prepare_translation_alter
+ /**
+ * Implements hook_field_attach_prepare_translation_alter()
+ */
+ function `Filename()`_field_attach_prepare_translation_alter(&$entity, $context) {
+ /*
+ *if ($context['entity_type'] == 'custom_entity_type') {
+ * $entity->custom_field = $context['source_entity']->custom_field;
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_field_language_alter
+ /**
+ * Implements hook_field_language_alter()
+ */
+ function `Filename()`_field_language_alter(&$display_language, $context) {
+ // Do not apply core language fallback rules if they are disabled or if Locale
+ // is not registered as a translation handler.
+ /*
+ *if (variable_get('locale_field_language_fallback', TRUE) && field_has_translation_handler($context['entity_type'], 'locale')) {
+ * locale_field_language_fallback($display_language, $context['entity'], $context['language']);
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_field_available_languages_alter
+ /**
+ * Implements hook_field_available_languages_alter()
+ */
+ function `Filename()`_field_available_languages_alter(&$languages, $context) {
+ // Add an unavailable language.
+ /*
+ *$languages[] = 'xx';
+ */
+ // Remove an available language.
+ /*
+ *$index = array_search('yy', $languages);
+ *unset($languages[$index]);
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_field_attach_create_bundle
+ /**
+ * Implements hook_field_attach_create_bundle()
+ */
+ function `Filename()`_field_attach_create_bundle($entity_type, $bundle) {
+ // When a new bundle is created, the menu needs to be rebuilt to add the
+ // Field UI menu item tabs.
+ /*
+ *variable_set('menu_rebuild_needed', TRUE);
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_field_attach_rename_bundle
+ /**
+ * Implements hook_field_attach_rename_bundle()
+ */
+ function `Filename()`_field_attach_rename_bundle($entity_type, $bundle_old, $bundle_new) {
+ // Update the extra weights variable with new information.
+ /*
+ *if ($bundle_old !== $bundle_new) {
+ * $extra_weights = variable_get('field_extra_weights', array());
+ * if (isset($info[$entity_type][$bundle_old])) {
+ * $extra_weights[$entity_type][$bundle_new] = $extra_weights[$entity_type][$bundle_old];
+ * unset($extra_weights[$entity_type][$bundle_old]);
+ * variable_set('field_extra_weights', $extra_weights);
+ * }
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_field_attach_delete_bundle
+ /**
+ * Implements hook_field_attach_delete_bundle()
+ */
+ function `Filename()`_field_attach_delete_bundle($entity_type, $bundle, $instances) {
+ // Remove the extra weights variable information for this bundle.
+ /*
+ *$extra_weights = variable_get('field_extra_weights', array());
+ *if (isset($extra_weights[$entity_type][$bundle])) {
+ * unset($extra_weights[$entity_type][$bundle]);
+ * variable_set('field_extra_weights', $extra_weights);
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_field_storage_info
+ /**
+ * Implements hook_field_storage_info()
+ */
+ function `Filename()`_field_storage_info() {
+ return array(
+ /*
+ *'field_sql_storage' => array(
+ * 'label' => t('Default SQL storage'),
+ * 'description' => t('Stores fields in the local SQL database, using per-field tables.'),
+ * 'settings' => array(),
+ *),
+ */
+ '${1}' => array(
+ 'label' => t('${2}'),
+ 'description' => t('${3}'),
+ 'settings' => array('${4}'${5}),
+ ),
+ );
+ }
+snippet hook_field_storage_info_alter
+ /**
+ * Implements hook_field_storage_info_alter()
+ */
+ function `Filename()`_field_storage_info_alter(&$info) {
+ // Add a setting to a storage type.
+ /*
+ *$info['field_sql_storage']['settings'] += array(
+ * 'mymodule_additional_setting' => 'default value',
+ *);
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_field_storage_details
+ /**
+ * Implements hook_field_storage_details()
+ */
+ function `Filename()`_field_storage_details($field) {
+ $details = array();
+
+ // Add field columns.
+ /*
+ *foreach ((array) $field['columns'] as $column_name => $attributes) {
+ * $real_name = _field_sql_storage_columnname($field['field_name'], $column_name);
+ * $columns[$column_name] = $real_name;
+ *}
+ *return array(
+ * 'sql' => array(
+ * FIELD_LOAD_CURRENT => array(
+ * _field_sql_storage_tablename($field) => $columns,
+ * ),
+ * FIELD_LOAD_REVISION => array(
+ * _field_sql_storage_revision_tablename($field) => $columns,
+ * ),
+ * ),
+ *);
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_field_storage_details_alter
+ /**
+ * Implements hook_field_storage_details_alter()
+ */
+ function `Filename()`_field_storage_details_alter(&$details, $field) {
+ /*
+ *if ($field['field_name'] == 'field_of_interest') {
+ * $columns = array();
+ * foreach ((array) $field['columns'] as $column_name => $attributes) {
+ * $columns[$column_name] = $column_name;
+ * }
+ * $details['drupal_variables'] = array(
+ * FIELD_LOAD_CURRENT => array(
+ * 'moon' => $columns,
+ * ),
+ * FIELD_LOAD_REVISION => array(
+ * 'mars' => $columns,
+ * ),
+ * );
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_field_storage_load
+ /**
+ * Implements hook_field_storage_load()
+ */
+ function `Filename()`_field_storage_load($entity_type, &$entities, $age, $fields, $options) {
+ /*
+ * $field_info = field_info_field_by_ids();
+ * $etid = _field_sql_storage_etid($entity_type);
+ * $load_current = $age == FIELD_LOAD_CURRENT;
+ *
+ * foreach ($fields as $field_id => $ids) {
+ * $field = $field_info[$field_id];
+ * $field_name = $field['field_name'];
+ * $table = $load_current ? _field_sql_storage_tablename($field) : _field_sql_storage_revision_tablename($field);
+ *
+ * $query = db_select($table, 't')
+ * ->fields('t')
+ * ->condition('etid', $etid)
+ * ->condition($load_current ? 'entity_id' : 'revision_id', $ids, 'IN')
+ * ->condition('language', field_available_languages($entity_type, $field), 'IN')
+ * ->orderBy('delta');
+ *
+ * if (empty($options['deleted'])) {
+ * $query->condition('deleted', 0);
+ * }
+ *
+ * $results = $query->execute();
+ *
+ * $delta_count = array();
+ * foreach ($results as $row) {
+ * if (!isset($delta_count[$row->entity_id][$row->language])) {
+ * $delta_count[$row->entity_id][$row->language] = 0;
+ * }
+ *
+ * if ($field['cardinality'] == FIELD_CARDINALITY_UNLIMITED || $delta_count[$row->entity_id][$row->language] < $field['cardinality']) {
+ * $item = array();
+ * // For each column declared by the field, populate the item
+ * // from the prefixed database column.
+ * foreach ($field['columns'] as $column => $attributes) {
+ * $column_name = _field_sql_storage_columnname($field_name, $column);
+ * $item[$column] = $row->$column_name;
+ * }
+ *
+ * // Add the item to the field values for the entity.
+ * $entities[$row->entity_id]->{$field_name}[$row->language][] = $item;
+ * $delta_count[$row->entity_id][$row->language]++;
+ * }
+ * }
+ * }
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_field_storage_write
+ /**
+ * Implements hook_field_storage_write()
+ */
+ function `Filename()`_field_storage_write($entity_type, $entity, $op, $fields) {
+ list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
+ $etid = _field_sql_storage_etid($entity_type);
+
+ foreach ($fields as $field_id) {
+ /*
+ * $field = field_info_field_by_id($field_id);
+ * $field_name = $field['field_name'];
+ * $table_name = _field_sql_storage_tablename($field);
+ * $revision_name = _field_sql_storage_revision_tablename($field);
+ *
+ * $all_languages = field_available_languages($entity_type, $field);
+ * $field_languages = array_intersect($all_languages, array_keys((array) $entity->$field_name));
+ *
+ * // Delete and insert, rather than update, in case a value was added.
+ * if ($op == FIELD_STORAGE_UPDATE) {
+ * // Delete languages present in the incoming $entity->$field_name.
+ * // Delete all languages if $entity->$field_name is empty.
+ * $languages = !empty($entity->$field_name) ? $field_languages : $all_languages;
+ * if ($languages) {
+ * db_delete($table_name)
+ * ->condition('etid', $etid)
+ * ->condition('entity_id', $id)
+ * ->condition('language', $languages, 'IN')
+ * ->execute();
+ * if (isset($vid)) {
+ * db_delete($revision_name)
+ * ->condition('etid', $etid)
+ * ->condition('entity_id', $id)
+ * ->condition('revision_id', $vid)
+ * ->condition('language', $languages, 'IN')
+ * ->execute();
+ * }
+ * }
+ * }
+ *
+ * // Prepare the multi-insert query.
+ * $do_insert = FALSE;
+ * $columns = array('etid', 'entity_id', 'revision_id', 'bundle', 'delta', 'language');
+ * foreach ($field['columns'] as $column => $attributes) {
+ * $columns[] = _field_sql_storage_columnname($field_name, $column);
+ * }
+ * $query = db_insert($table_name)->fields($columns);
+ * if (isset($vid)) {
+ * $revision_query = db_insert($revision_name)->fields($columns);
+ * }
+ *
+ * foreach ($field_languages as $langcode) {
+ * $items = (array) $entity->{$field_name}[$langcode];
+ * $delta_count = 0;
+ * foreach ($items as $delta => $item) {
+ * // We now know we have someting to insert.
+ * $do_insert = TRUE;
+ * $record = array(
+ * 'etid' => $etid,
+ * 'entity_id' => $id,
+ * 'revision_id' => $vid,
+ * 'bundle' => $bundle,
+ * 'delta' => $delta,
+ * 'language' => $langcode,
+ * );
+ * foreach ($field['columns'] as $column => $attributes) {
+ * $record[_field_sql_storage_columnname($field_name, $column)] = isset($item[$column]) ? $item[$column] : NULL;
+ * }
+ * $query->values($record);
+ * if (isset($vid)) {
+ * $revision_query->values($record);
+ * }
+ *
+ * if ($field['cardinality'] != FIELD_CARDINALITY_UNLIMITED && ++$delta_count == $field['cardinality']) {
+ * break;
+ * }
+ * }
+ * }
+ *
+ * // Execute the query if we have values to insert.
+ * if ($do_insert) {
+ * $query->execute();
+ * if (isset($vid)) {
+ * $revision_query->execute();
+ * }
+ * }
+ */
+ ${1:/* Your code here */}
+ }
+ }
+snippet hook_field_storage_delete
+ /**
+ * Implements hook_field_storage_delete()
+ */
+ function `Filename()`_field_storage_delete($entity_type, $entity, $fields) {
+ list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
+ $etid = _field_sql_storage_etid($entity_type);
+
+ foreach (field_info_instances($entity_type, $bundle) as $instance) {
+ /*
+ *if (isset($fields[$instance['field_id']])) {
+ * $field = field_info_field_by_id($instance['field_id']);
+ * field_sql_storage_field_storage_purge($entity_type, $entity, $field, $instance);
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+ }
+snippet hook_field_storage_delete_revision
+ /**
+ * Implements hook_field_storage_delete_revision()
+ */
+ function `Filename()`_field_storage_delete_revision($entity_type, $entity, $fields) {
+ list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
+ $etid = _field_sql_storage_etid($entity_type);
+
+ if (isset($vid)) {
+ foreach ($fields as $field_id) {
+ /*
+ *$field = field_info_field_by_id($field_id);
+ *$revision_name = _field_sql_storage_revision_tablename($field);
+ *db_delete($revision_name)
+ * ->condition('etid', $etid)
+ * ->condition('entity_id', $id)
+ * ->condition('revision_id', $vid)
+ * ->execute();
+ */
+ ${1:/* Your code here */}
+ }
+ }
+ }
+snippet hook_field_storage_query
+ /**
+ * Implements hook_field_storage_query()
+ */
+ function `Filename()`_field_storage_query($query) {
+ /*
+ * $load_current = $options['age'] == FIELD_LOAD_CURRENT;
+ *
+ * $field = field_info_field_by_id($field_id);
+ * $field_name = $field['field_name'];
+ * $table = $load_current ? _field_sql_storage_tablename($field) : _field_sql_storage_revision_tablename($field);
+ * $field_columns = array_keys($field['columns']);
+ *
+ * // Build the query.
+ * $query = db_select($table, 't');
+ * $query->join('field_config_entity_type', 'e', 't.etid = e.etid');
+ *
+ * // Add conditions.
+ * foreach ($conditions as $condition) {
+ * // A condition is either a (column, value, operator) triple, or a
+ * // (column, value) pair with implied operator.
+ * @list($column, $value, $operator) = $condition;
+ * // Translate operator and value if needed.
+ * switch ($operator) {
+ * case 'STARTS_WITH':
+ * $operator = 'LIKE';
+ * $value = db_like($value) . '%';
+ * break;
+ *
+ * case 'ENDS_WITH':
+ * $operator = 'LIKE';
+ * $value = '%' . db_like($value);
+ * break;
+ *
+ * case 'CONTAINS':
+ * $operator = 'LIKE';
+ * $value = '%' . db_like($value) . '%';
+ * break;
+ * }
+ * // Translate field columns into prefixed db columns.
+ * if (in_array($column, $field_columns)) {
+ * $column = _field_sql_storage_columnname($field_name, $column);
+ * }
+ * // Translate entity types into numeric ids. Expressing the condition on the
+ * // local 'etid' column rather than the JOINed 'type' column avoids a
+ * // filesort.
+ * if ($column == 'type') {
+ * $column = 't.etid';
+ * if (is_array($value)) {
+ * foreach (array_keys($value) as $key) {
+ * $value[$key] = _field_sql_storage_etid($value[$key]);
+ * }
+ * }
+ * else {
+ * $value = _field_sql_storage_etid($value);
+ * }
+ * }
+ * // Track condition on 'deleted'.
+ * if ($column == 'deleted') {
+ * $condition_deleted = TRUE;
+ * }
+ *
+ * $query->condition($column, $value, $operator);
+ * }
+ *
+ * // Exclude deleted data unless we have a condition on it.
+ * if (!isset($condition_deleted)) {
+ * $query->condition('deleted', 0);
+ * }
+ *
+ * // For a count query, return the count now.
+ * if ($options['count']) {
+ * return $query
+ * ->fields('t', array('etid', 'entity_id', 'revision_id'))
+ * ->distinct()
+ * ->countQuery()
+ * ->execute()
+ * ->fetchField();
+ * }
+ *
+ * // For a data query, add fields.
+ * $query
+ * ->fields('t', array('bundle', 'entity_id', 'revision_id'))
+ * ->fields('e', array('type'))
+ * // We need to ensure entities arrive in a consistent order for the
+ * // range() operation to work.
+ * ->orderBy('t.etid')
+ * ->orderBy('t.entity_id');
+ *
+ * // Initialize results array
+ * $return = array();
+ *
+ * // Getting $count entities possibly requires reading more than $count rows
+ * // since fields with multiple values span over several rows. We query for
+ * // batches of $count rows until we've either read $count entities or received
+ * // less rows than asked for.
+ * $entity_count = 0;
+ * do {
+ * if ($options['limit'] != FIELD_QUERY_NO_LIMIT) {
+ * $query->range($options['cursor'], $options['limit']);
+ * }
+ * $results = $query->execute();
+ *
+ * $row_count = 0;
+ * foreach ($results as $row) {
+ * $row_count++;
+ * $options['cursor']++;
+ * // If querying all revisions and the entity type has revisions, we need
+ * // to key the results by revision_ids.
+ * $entity_type = entity_get_info($row->type);
+ * $id = ($load_current || empty($entity_type['entity keys']['revision'])) ? $row->entity_id : $row->revision_id;
+ *
+ * if (!isset($return[$row->type][$id])) {
+ * $return[$row->type][$id] = entity_create_stub_entity($row->type, array($row->entity_id, $row->revision_id, $row->bundle));
+ * $entity_count++;
+ * }
+ * }
+ * } while ($options['limit'] != FIELD_QUERY_NO_LIMIT && $row_count == $options['limit'] && $entity_count < $options['limit']);
+ *
+ * // The query is complete when the last batch returns less rows than asked
+ * // for.
+ * if ($row_count < $options['limit']) {
+ * $options['cursor'] = FIELD_QUERY_COMPLETE;
+ * }
+ *
+ * return $return;
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_field_storage_create_field
+ /**
+ * Implements hook_field_storage_create_field()
+ */
+ function `Filename()`_field_storage_create_field($field) {
+ /*
+ *$schema = _field_sql_storage_schema($field);
+ *foreach ($schema as $name => $table) {
+ * db_create_table($name, $table);
+ *}
+ *drupal_get_schema(NULL, TRUE);
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_field_storage_delete_field
+ /**
+ * Implements hook_field_storage_delete_field()
+ */
+ function `Filename()`_field_storage_delete_field($field) {
+ // Mark all data associated with the field for deletion.
+ /*
+ *$field['deleted'] = 0;
+ *$table = _field_sql_storage_tablename($field);
+ *$revision_table = _field_sql_storage_revision_tablename($field);
+ *db_update($table)
+ * ->fields(array('deleted' => 1))
+ * ->execute();
+ */
+ // Move the table to a unique name while the table contents are being deleted.
+ /*
+ *$field['deleted'] = 1;
+ *$new_table = _field_sql_storage_tablename($field);
+ *$revision_new_table = _field_sql_storage_revision_tablename($field);
+ *db_rename_table($table, $new_table);
+ *db_rename_table($revision_table, $revision_new_table);
+ *drupal_get_schema(NULL, TRUE);
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_field_storage_delete_instance
+ /**
+ * Implements hook_field_storage_delete_instance()
+ */
+ function `Filename()`_field_storage_delete_instance($instance) {
+ /*
+ *$etid = _field_sql_storage_etid($instance['entity_type']);
+ *$field = field_info_field($instance['field_name']);
+ *$table_name = _field_sql_storage_tablename($field);
+ *$revision_name = _field_sql_storage_revision_tablename($field);
+ *db_update($table_name)
+ * ->fields(array('deleted' => 1))
+ * ->condition('etid', $etid)
+ * ->condition('bundle', $instance['bundle'])
+ * ->execute();
+ *db_update($revision_name)
+ * ->fields(array('deleted' => 1))
+ * ->condition('etid', $etid)
+ * ->condition('bundle', $instance['bundle'])
+ * ->execute();
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_field_storage_pre_load
+ /**
+ * Implements hook_field_storage_pre_load()
+ */
+ function `Filename()`_field_storage_pre_load($entity_type, $entities, $age, &$skip_fields, $options) {
+ ${1:/* Your code here */}
+ }
+snippet hook_field_storage_pre_insert
+ /**
+ * Implements hook_field_storage_pre_insert()
+ */
+ function `Filename()`_field_storage_pre_insert($entity_type, $entity, &$skip_fields) {
+ /*
+ *if ($entity_type == 'node' && $entity->status && _forum_node_check_node_type($entity)) {
+ * $query = db_insert('forum_index')->fields(array('nid', 'title', 'tid', 'sticky', 'created', 'comment_count', 'last_comment_timestamp'));
+ * foreach ($entity->taxonomy_forums as $language) {
+ * foreach ($language as $delta) {
+ * $query->values(array(
+ * 'nid' => $entity->nid,
+ * 'title' => $entity->title,
+ * 'tid' => $delta['value'],
+ * 'sticky' => $entity->sticky,
+ * 'created' => $entity->created,
+ * 'comment_count' => 0,
+ * 'last_comment_timestamp' => $entity->created,
+ * ));
+ * }
+ * }
+ * $query->execute();
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_field_storage_pre_update
+ /**
+ * Implements hook_field_storage_pre_update()
+ */
+ function `Filename()`_field_storage_pre_update($entity_type, $entity, &$skip_fields) {
+ /*
+ * $first_call = &drupal_static(__FUNCTION__, array());
+ *
+ * if ($entity_type == 'node' && $entity->status && _forum_node_check_node_type($entity)) {
+ * // We don't maintain data for old revisions, so clear all previous values
+ * // from the table. Since this hook runs once per field, per entity, make
+ * // sure we only wipe values once.
+ * if (!isset($first_call[$entity->nid])) {
+ * $first_call[$entity->nid] = FALSE;
+ * db_delete('forum_index')->condition('nid', $entity->nid)->execute();
+ * }
+ * // Only save data to the table if the node is published.
+ * if ($entity->status) {
+ * $query = db_insert('forum_index')->fields(array('nid', 'title', 'tid', 'sticky', 'created', 'comment_count', 'last_comment_timestamp'));
+ * foreach ($entity->taxonomy_forums as $language) {
+ * foreach ($language as $delta) {
+ * $query->values(array(
+ * 'nid' => $entity->nid,
+ * 'title' => $entity->title,
+ * 'tid' => $delta['value'],
+ * 'sticky' => $entity->sticky,
+ * 'created' => $entity->created,
+ * 'comment_count' => 0,
+ * 'last_comment_timestamp' => $entity->created,
+ * ));
+ * }
+ * }
+ * $query->execute();
+ * // The logic for determining last_comment_count is fairly complex, so
+ * // call _forum_update_forum_index() too.
+ * _forum_update_forum_index($entity->nid);
+ * }
+ * }
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_field_info_max_weight
+ /**
+ * Implements hook_field_info_max_weight()
+ */
+ function `Filename()`_field_info_max_weight($entity_type, $bundle, $context) {
+ $weights = array();
+
+ /*
+ *foreach (my_module_entity_additions($entity_type, $bundle, $context) as $addition) {
+ * $weights[] = $addition['weight'];
+ *}
+ */
+ ${1:/* Your code here */}
+
+ return $weights ? max($weights) : NULL;
+ }
+snippet hook_field_display_alter
+ /**
+ * Implements hook_field_display_alter()
+ */
+ function `Filename()`_field_display_alter(&$display, $context) {
+ // Leave field labels out of the search index.
+ // Note: The check against $context['entity_type'] == 'node' could be avoided
+ // by using hook_field_display_node_alter() instead of
+ // hook_field_display_alter(), resulting in less function calls when
+ // rendering non-node entities.
+ /*
+ *if ($context['entity_type'] == 'node' && $context['view_mode'] == 'search_index') {
+ * $display['label'] = 'hidden';
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_field_display_ENTITY_TYPE_alter
+ /**
+ * Implements hook_field_display_ENTITY_TYPE_alter()
+ */
+ function `Filename()`_field_display_ENTITY_TYPE_alter(&$display, $context) {
+ // Leave field labels out of the search index.
+ /*
+ *if ($context['view_mode'] == 'search_index') {
+ * $display['label'] = 'hidden';
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_field_extra_fields_display_alter
+ /**
+ * Implements hook_field_extra_fields_display_alter()
+ */
+ function `Filename()`_field_extra_fields_display_alter(&$displays, $context) {
+ /*
+ *if ($context['entity_type'] == 'taxonomy_term' && $context['view_mode'] == 'full') {
+ * $displays['description']['visibility'] = FALSE;
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_field_create_field
+ /**
+ * Implements hook_field_create_field()
+ */
+ function `Filename()`_field_create_field($field) {
+ ${1:/* Your code here */}
+ }
+snippet hook_field_create_instance
+ /**
+ * Implements hook_field_create_instance()
+ */
+ function `Filename()`_field_create_instance($instance) {
+ ${1:/* Your code here */}
+ }
+snippet hook_field_update_forbid
+ /**
+ * Implements hook_field_update_forbid()
+ */
+ function `Filename()`_field_update_forbid($field, $prior_field, $has_data) {
+ // A 'list' field stores integer keys mapped to display values. If
+ // the new field will have fewer values, and any data exists for the
+ // abandoned keys, the field will have no way to display them. So,
+ // forbid such an update.
+ /*
+ *if ($has_data && count($field['settings']['allowed_values']) < count($prior_field['settings']['allowed_values'])) {
+ * // Identify the keys that will be lost.
+ * $lost_keys = array_diff(array_keys($field['settings']['allowed_values']), array_keys($prior_field['settings']['allowed_values']));
+ * // If any data exist for those keys, forbid the update.
+ * $query = new EntityFieldQuery();
+ * $found = $query
+ * ->fieldCondition($prior_field['field_name'], 'value', $lost_keys)
+ * ->range(0, 1)
+ * ->execute();
+ * if ($found) {
+ * throw new FieldUpdateForbiddenException("Cannot update a list field not to include keys with existing data");
+ * }
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_field_update_field
+ /**
+ * Implements hook_field_update_field()
+ */
+ function `Filename()`_field_update_field($field, $prior_field, $has_data) {
+ // Reset the static value that keeps track of allowed values for list fields.
+ /*
+ *drupal_static_reset('list_allowed_values');
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_field_delete_field
+ /**
+ * Implements hook_field_delete_field()
+ */
+ function `Filename()`_field_delete_field($field) {
+ ${1:/* Your code here */}
+ }
+snippet hook_field_update_instance
+ /**
+ * Implements hook_field_update_instance()
+ */
+ function `Filename()`_field_update_instance($instance, $prior_instance) {
+ ${1:/* Your code here */}
+ }
+snippet hook_field_delete_instance
+ /**
+ * Implements hook_field_delete_instance()
+ */
+ function `Filename()`_field_delete_instance($instance) {
+ ${1:/* Your code here */}
+ }
+snippet hook_field_read_field
+ /**
+ * Implements hook_field_read_field()
+ */
+ function `Filename()`_field_read_field(&$field) {
+ ${1:/* Your code here */}
+ }
+snippet hook_field_read_instance
+ /**
+ * Implements hook_field_read_instance()
+ */
+ function `Filename()`_field_read_instance($instance) {
+ ${1:/* Your code here */}
+ }
+snippet hook_field_purge_field
+ /**
+ * Implements hook_field_purge_field()
+ */
+ function `Filename()`_field_purge_field($field) {
+ db_delete('${1}')
+ ->condition('id', $field['id'])
+ ->execute();
+ }
+snippet hook_field_purge_field_instance
+ /**
+ * Implements hook_field_purge_field_instance()
+ */
+ function `Filename()`_field_purge_field_instance($instance) {
+ db_delete('${1}')
+ ->condition('id', $instance['id'])
+ ->execute();
+ }
+snippet hook_field_storage_purge_field
+ /**
+ * Implements hook_field_storage_purge_field()
+ */
+ function `Filename()`_field_storage_purge_field($field) {
+ /*
+ *$table_name = _field_sql_storage_tablename($field);
+ *$revision_name = _field_sql_storage_revision_tablename($field);
+ *db_drop_table($table_name);
+ *db_drop_table($revision_name);
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_field_storage_purge_field_instance
+ /**
+ * Implements hook_field_storage_purge_field_instance()
+ */
+ function `Filename()`_field_storage_purge_field_instance($instance) {
+ db_delete('${1}')
+ ->condition('id', $instance['id'])
+ ->execute();
+ }
+snippet hook_field_storage_purge
+ /**
+ * Implements hook_field_storage_purge()
+ */
+ function `Filename()`_field_storage_purge($entity_type, $entity, $field, $instance) {
+ list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
+ /*
+ *$etid = _field_sql_storage_etid($entity_type);
+ *
+ *$table_name = _field_sql_storage_tablename($field);
+ *$revision_name = _field_sql_storage_revision_tablename($field);
+ *db_delete($table_name)
+ * ->condition('etid', $etid)
+ * ->condition('entity_id', $id)
+ * ->execute();
+ *db_delete($revision_name)
+ * ->condition('etid', $etid)
+ * ->condition('entity_id', $id)
+ * ->execute();
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_field_access
+ /**
+ * Implements hook_field_access()
+ */
+ function `Filename()`_field_access($op, $field, $entity_type, $entity, $account) {
+ /*
+ *if ($field['field_name'] == 'field_of_interest' && $op == 'edit') {
+ * return user_access('edit field of interest', $account);
+ *}
+ */
+ ${1:/* Your code here */}
+ return TRUE;
+ }
+snippet hook_options_list
+ /**
+ * Implements hook_options_list()
+ */
+ function `Filename()`_options_list($field) {
+ // Sample structure.
+ /*
+ *$options = array(
+ * 0 => t('Zero'),
+ * 1 => t('One'),
+ * 2 => t('Two'),
+ * 3 => t('Three'),
+ *);
+ */
+ // Sample structure with groups. Only one level of nesting is allowed. This
+ // is only supported by the 'options_select' widget. Other widgets will
+ // flatten the array.
+ /*
+ *$options = array(
+ * t('First group') => array(
+ * 0 => t('Zero'),
+ * ),
+ * t('Second group') => array(
+ * 1 => t('One'),
+ * 2 => t('Two'),
+ * ),
+ * 3 => t('Three'),
+ *);
+ */
+ // In actual implementations, the array of options will most probably depend
+ // on properties of the field. Example from taxonomy.module:
+ /*
+ *$options = array();
+ *foreach ($field['settings']['allowed_values'] as $tree) {
+ * $terms = taxonomy_get_tree($tree['vid'], $tree['parent']);
+ * if ($terms) {
+ * foreach ($terms as $term) {
+ * $options[$term->tid] = str_repeat('-', $term->depth) . $term->name;
+ * }
+ * }
+ *}
+ */
+ $options = array(
+ ${1} => ${2},
+ );
+
+ return $options;
+ }
+snippet hook_contextual_links_view_alter
+ /**
+ * Implements hook_contextual_links_view_alter()
+ */
+ function `Filename()`_contextual_links_view_alter(&$element, $items) {
+ // Add another class to all contextual link lists to facilitate custom
+ // styling.
+ /*
+ *$element['#attributes']['class'][] = 'custom-class';
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_dashboard_regions
+ /**
+ * Implements hook_dashboard_regions()
+ */
+ function `Filename()`_dashboard_regions() {
+ // Define a new dashboard region. Your module can also then define
+ // theme_mymodule_dashboard_region() as a theme wrapper function to control
+ // the region's appearance.
+ /*
+ *return array('mymodule_dashboard_region' => "My module's dashboard region");
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_dashboard_regions_alter
+ /**
+ * Implements hook_dashboard_regions_alter()
+ */
+ function `Filename()`_dashboard_regions_alter($regions) {
+ // Remove the sidebar region defined by the core dashboard module.
+ /*
+ *unset($regions['dashboard_sidebar']);
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_menu_insert
+ /**
+ * Implements hook_menu_insert()
+ */
+ function `Filename()`_menu_insert($menu) {
+ // For example, we track available menus in a variable.
+ /*
+ *$my_menus = variable_get('my_module_menus', array());
+ *$my_menus[$menu['menu_name']] = $menu['menu_name'];
+ *variable_set('my_module_menus', $my_menus);
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_menu_update
+ /**
+ * Implements hook_menu_update()
+ */
+ function `Filename()`_menu_update($menu) {
+ // For example, we track available menus in a variable.
+ /*
+ *$my_menus = variable_get('my_module_menus', array());
+ *$my_menus[$menu['menu_name']] = $menu['menu_name'];
+ *variable_set('my_module_menus', $my_menus);
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_menu_delete
+ /**
+ * Implements hook_menu_delete()
+ */
+ function `Filename()`_menu_delete($menu) {
+ // Delete the record from our variable.
+ /*
+ *$my_menus = variable_get('my_module_menus', array());
+ *unset($my_menus[$menu['menu_name']]);
+ *variable_set('my_module_menus', $my_menus);
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_path_insert
+ /**
+ * Implements hook_path_insert()
+ */
+ function `Filename()`_path_insert($path) {
+ ${1:/* Your code here */}
+ }
+snippet hook_path_update
+ /**
+ * Implements hook_path_update()
+ */
+ function `Filename()`_path_update($path) {
+ ${1:/* Your code here */}
+ }
+snippet hook_path_delete
+ /**
+ * Implements hook_path_delete()
+ */
+ function `Filename()`_path_delete($path) {
+ ${1:/* Your code here */}
+ }
+snippet hook_shortcut_default_set
+ /**
+ * Implements hook_shortcut_default_set()
+ */
+ function `Filename()`_shortcut_default_set($account) {
+ // Use a special set of default shortcuts for administrators only.
+ /*
+ *if (in_array(variable_get('user_admin_role', 0), $account->roles)) {
+ * return variable_get('mymodule_shortcut_admin_default_set');
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_image_effect_info
+ /**
+ * Implements hook_image_effect_info()
+ */
+ function `Filename()`_image_effect_info() {
+ $effects = array();
+
+ $effects['${1}'] = array(
+ 'label' => t('${2}'),
+ 'help' => t('${3}'),
+ 'effect callback' => '${4}',
+ 'form callback' => '${5}',
+ 'summary theme' => '${6}',
+ );
+
+ return $effects;
+ }
+snippet hook_image_effect_info_alter
+ /**
+ * Implements hook_image_effect_info_alter()
+ */
+ function `Filename()`_image_effect_info_alter(&$effects) {
+ // override the image module's crop effect with more options.
+ /*
+ *$effect['image_crop']['effect callback'] = 'mymodule_crop_effect';
+ *$effect['image_crop']['form callback'] = 'mymodule_crop_form';
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_image_style_save
+ /**
+ * Implements hook_image_style_save()
+ */
+ function `Filename()`_image_style_save($style) {
+ // if a module defines an image style and that style is renamed by the user
+ // the module should update any references to that style.
+ /*
+ *if (isset($style['old_name']) && $style['old_name'] == variable_get('mymodule_image_style', '')) {
+ * variable_set('mymodule_image_style', $style['name']);
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_image_style_delete
+ /**
+ * Implements hook_image_style_delete()
+ */
+ function `Filename()`_image_style_delete($style) {
+ // Administrators can choose an optional replacement style when deleting.
+ // Update the modules style variable accordingly.
+ /*
+ *if (isset($style['old_name']) && $style['old_name'] == variable_get('mymodule_image_style', '')) {
+ * variable_set('mymodule_image_style', $style['name']);
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_image_style_flush
+ /**
+ * Implements hook_image_style_flush()
+ */
+ function `Filename()`_image_style_flush($style) {
+ // Empty cached data that contains information about the style.
+ /*
+ *cache_clear_all('*', 'cache_mymodule', TRUE);
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_image_styles_alter
+ /**
+ * Implements hook_image_styles_alter()
+ */
+ function `Filename()`_image_styles_alter(&$styles) {
+ // Check that we only affect a default style.
+ /*
+ *if ($styles['thumbnail']['storage'] == IMAGE_STORAGE_DEFAULT) {
+ * // Add an additional effect to the thumbnail style.
+ * $styles['thumbnail']['effects'][] = array(
+ * 'name' => 'image_desaturate',
+ * 'data' => array(),
+ * 'weight' => 1,
+ * 'effect callback' => 'image_desaturate_effect',
+ * );
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_image_default_styles
+ /**
+ * Implements hook_image_default_styles()
+ */
+ function `Filename()`_image_default_styles() {
+ $styles = array();
+
+ $styles['${1}'] = array(
+ 'effects' => array(
+ array(
+ 'name' => '${2}',
+ 'data' => array('width' => ${3}, 'height' => ${4}, 'upscale' => ${5}),
+ 'weight' => ${6},
+ ),
+ ),
+ );
+
+ return $styles;
+ }
+snippet hook_trigger_info
+ /**
+ * Implements hook_trigger_info()
+ */
+ function `Filename()`_trigger_info() {
+ return array(
+ '${1}' => array(
+ /*
+ *'node_presave' => array(
+ * 'label' => t('When either saving new content or updating existing content'),
+ *),
+ */
+ '${2}' => array(
+ 'label' => t('${3}'),
+ ),
+ ),
+ );
+ }
+snippet hook_trigger_info_alter
+ /**
+ * Implements hook_trigger_info_alter()
+ */
+ function `Filename()`_trigger_info_alter(&$triggers) {
+ /*
+ *$triggers['node']['node_insert']['label'] = t('When content is saved');
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_search_info
+ /**
+ * Implements hook_search_info()
+ */
+ function `Filename()`_search_info() {
+ return array(
+ 'title' => '${1}',
+ 'path' => '${2}',
+ 'conditions_callback' => '${3}',
+ );
+ }
+snippet hook_search_access
+ /**
+ * Implements hook_search_access()
+ */
+ function `Filename()`_search_access() {
+ /*
+ *return user_access('access content');
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_search_reset
+ /**
+ * Implements hook_search_reset()
+ */
+ function `Filename()`_search_reset() {
+ /*
+ *db_update('search_dataset')
+ * ->fields(array('reindex' => REQUEST_TIME))
+ * ->condition('type', 'node')
+ * ->execute();
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_search_status
+ /**
+ * Implements hook_search_status()
+ */
+ function `Filename()`_search_status() {
+ /*
+ *$total = db_query('SELECT COUNT(*) FROM {node} WHERE status = 1')->fetchField();
+ *$remaining = db_query("SELECT COUNT(*) FROM {node} n LEFT JOIN {search_dataset} d ON d.type = 'node' AND d.sid = n.nid WHERE n.status = 1 AND d.sid IS NULL OR d.reindex <> 0")->fetchField();
+ *return array('remaining' => $remaining, 'total' => $total);
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_search_admin
+ /**
+ * Implements hook_search_admin()
+ */
+ function `Filename()`_search_admin() {
+ // Output form for defining rank factor weights.
+ /*
+ *$form['content_ranking'] = array(
+ * '#type' => 'fieldset',
+ * '#title' => t('Content ranking'),
+ *);
+ *$form['content_ranking']['#theme'] = 'node_search_admin';
+ *$form['content_ranking']['info'] = array(
+ * '#value' => '<em>' . t('The following numbers control which properties the content search should favor when ordering the results. Higher numbers mean more influence, zero means the property is ignored. Changing these numbers does not require the search index to be rebuilt. Changes take effect immediately.') . '</em>'
+ *);
+ */
+ // Note: reversed to reflect that higher number = higher ranking.
+ /*
+ *$options = drupal_map_assoc(range(0, 10));
+ *foreach (module_invoke_all('ranking') as $var => $values) {
+ * $form['content_ranking']['factors']['node_rank_' . $var] = array(
+ * '#title' => $values['title'],
+ * '#type' => 'select',
+ * '#options' => $options,
+ * '#default_value' => variable_get('node_rank_' . $var, 0),
+ * );
+ *}
+ */
+ $form['${1}'] = array(
+ '#title' => t('${2}'),
+ '#type' => '${3}',
+ '#theme' => '${4}',
+ '#default_value' => ${5},
+
+ return $form;
+ }
+snippet hook_search_execute
+ /**
+ * Implements hook_search_execute()
+ */
+ function `Filename()`_search_execute($keys = NULL, $conditions = NULL) {
+ /*
+ * // Build matching conditions
+ * $query = db_select('search_index', 'i', array('target' => 'slave'))->extend('SearchQuery')->extend('PagerDefault');
+ * $query->join('node', 'n', 'n.nid = i.sid');
+ * $query
+ * ->condition('n.status', 1)
+ * ->addTag('node_access')
+ * ->searchExpression($keys, 'node');
+ *
+ * // Insert special keywords.
+ * $query->setOption('type', 'n.type');
+ * $query->setOption('language', 'n.language');
+ * if ($query->setOption('term', 'ti.tid')) {
+ * $query->join('taxonomy_index', 'ti', 'n.nid = ti.nid');
+ * }
+ * // Only continue if the first pass query matches.
+ * if (!$query->executeFirstPass()) {
+ * return array();
+ * }
+ *
+ * // Add the ranking expressions.
+ * _node_rankings($query);
+ *
+ * // Load results.
+ * $find = $query
+ * ->limit(10)
+ * ->execute();
+ * $results = array();
+ * foreach ($find as $item) {
+ * // Build the node body.
+ * $node = node_load($item->sid);
+ * node_build_content($node, 'search_result');
+ * $node->body = drupal_render($node->content);
+ *
+ * // Fetch comments for snippet.
+ * $node->rendered .= ' ' . module_invoke('comment', 'node_update_index', $node);
+ * // Fetch terms for snippet.
+ * $node->rendered .= ' ' . module_invoke('taxonomy', 'node_update_index', $node);
+ *
+ * $extra = module_invoke_all('node_search_result', $node);
+ *
+ * $results[] = array(
+ * 'link' => url('node/' . $item->sid, array('absolute' => TRUE)),
+ * 'type' => check_plain(node_type_get_name($node)),
+ * 'title' => $node->title,
+ * 'user' => theme('username', array('account' => $node)),
+ * 'date' => $node->changed,
+ * 'node' => $node,
+ * 'extra' => $extra,
+ * 'score' => $item->calculated_score,
+ * 'snippet' => search_excerpt($keys, $node->body),
+ * );
+ * }
+ * return $results;
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_search_page
+ /**
+ * Implements hook_search_page()
+ */
+ function `Filename()`_search_page($results) {
+ $output['prefix']['#markup'] = '<ol class="search-results">';
+
+ foreach ($results as $entry) {
+ $output[] = array(
+ '#theme' => '${1}',
+ '#result' => $entry,
+ '#module' => '${2}',
+ );
+ }
+ $output['suffix']['#markup'] = '</ol>' . theme('pager');
+
+ return $output;
+ }
+snippet hook_search_preprocess
+ /**
+ * Implements hook_search_preprocess()
+ */
+ function `Filename()`_search_preprocess($text) {
+ // Do processing on $text
+ /*
+ *return $text;
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_update_index
+ /**
+ * Implements hook_update_index()
+ */
+ function `Filename()`_update_index() {
+ /*
+ * $limit = (int)variable_get('search_cron_limit', 100);
+ *
+ * $result = db_query_range("SELECT n.nid FROM {node} n LEFT JOIN {search_dataset} d ON d.type = 'node' AND d.sid = n.nid WHERE d.sid IS NULL OR d.reindex <> 0 ORDER BY d.reindex ASC, n.nid ASC", 0, $limit);
+ *
+ * foreach ($result as $node) {
+ * $node = node_load($node->nid);
+ *
+ * // Save the changed time of the most recent indexed node, for the search
+ * // results half-life calculation.
+ * variable_set('node_cron_last', $node->changed);
+ *
+ * // Render the node.
+ * node_build_content($node, 'search_index');
+ * $node->rendered = drupal_render($node->content);
+ *
+ * $text = '<h1>' . check_plain($node->title) . '</h1>' . $node->rendered;
+ *
+ * // Fetch extra data normally not visible
+ * $extra = module_invoke_all('node_update_index', $node);
+ * foreach ($extra as $t) {
+ * $text .= $t;
+ * }
+ *
+ * // Update index
+ * search_index($node->nid, 'node', $text);
+ * }
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_locale
+ /**
+ * Implements hook_locale()
+ */
+ function `Filename()`_locale($op = 'groups') {
+ switch ($op) {
+ case '${1}':
+ return array('${2}' => t('${3}'));
+ }
+ }
+snippet hook_language_init
+ /**
+ * Implements hook_language_init()
+ */
+ function `Filename()`_language_init() {
+ global $language, $conf;
+
+ switch ($language->language) {
+ /*
+ *case 'it':
+ * $conf['site_name'] = 'Il mio sito Drupal';
+ * break;
+ */
+ case '${1}':
+ $conf['${2}'] = '${3}';
+ break;
+ }
+ }
+snippet hook_language_switch_links_alter
+ /**
+ * Implements hook_language_switch_links_alter()
+ */
+ function `Filename()`_language_switch_links_alter(array &$links, $type, $path) {
+ global $language;
+
+ /*
+ *if ($type == LANGUAGE_TYPE_CONTENT && isset($links[$language->language])) {
+ * foreach ($links[$language->language] as $link) {
+ * $link['attributes']['class'][] = 'active-language';
+ * }
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_language_types_info
+ /**
+ * Implements hook_language_types_info()
+ */
+ function `Filename()`_language_types_info() {
+ return array(
+ /*
+ *'custom_language_type' => array(
+ * 'name' => t('Custom language'),
+ * 'description' => t('A custom language type.'),
+ *),
+ *'fixed_custom_language_type' => array(
+ * 'fixed' => array('custom_language_provider'),
+ *),
+ */
+ '${1}' => array(
+ 'name' => t('${2}'),
+ 'description' => t('${3}'),
+ ),
+ );
+ }
+snippet hook_language_types_info_alter
+ /**
+ * Implements hook_language_types_info_alter()
+ */
+ function `Filename()`_language_types_info_alter(array &$language_types) {
+ /*
+ *if (isset($language_types['custom_language_type'])) {
+ * $language_types['custom_language_type_custom']['description'] = t('A far better description.');
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_language_negotiation_info
+ /**
+ * Implements hook_language_negotiation_info()
+ */
+ function `Filename()`_language_negotiation_info() {
+ return array(
+ /*
+ *'custom_language_provider' => array(
+ * 'callbacks' => array(
+ * 'language' => 'custom_language_provider_callback',
+ * 'switcher' => 'custom_language_switcher_callback',
+ * 'url_rewrite' => 'custom_language_url_rewrite_callback',
+ * ),
+ * 'file' => drupal_get_path('module', 'custom') . '/custom.module',
+ * 'weight' => -4,
+ * 'types' => array('custom_language_type'),
+ * 'name' => t('Custom language provider'),
+ * 'description' => t('This is a custom language provider.'),
+ * 'cache' => 0,
+ *),
+ */
+ '${1}' => array(
+ 'callbacks' => array(
+ 'language' => '${2}',
+ 'switcher' => '${3}',
+ 'url_rewrite' => '${4}',
+ ),
+ 'file' => drupal_get_path('module', '${5}') . '/${6}',
+ 'weight' => ${7},
+ 'types' => array('${8}'),
+ 'name' => t('${9}'),
+ 'description' => t('${10}'),
+ 'cache' => ${11},
+ ),
+ );
+ }
+snippet hook_language_negotiation_info_alter
+ /**
+ * Implements hook_language_negotiation_info_alter()
+ */
+ function `Filename()`_language_negotiation_info_alter(array &$language_providers) {
+ /*
+ *if (isset($language_providers['custom_language_provider'])) {
+ * $language_providers['custom_language_provider']['config'] = 'admin/config/regional/language/configure/custom-language-provider';
+ *}
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_multilingual_settings_changed
+ /**
+ * Implements hook_multilingual_settings_changed()
+ */
+ function `Filename()`_multilingual_settings_changed() {
+ /*
+ *field_info_cache_clear();
+ */
+ ${1:/* Your code here */}
+ }
+snippet hook_language_fallback_candidates_alter
+ /**
+ * Implements hook_language_fallback_candidates_alter()
+ */
+ function `Filename()`_language_fallback_candidates_alter(array &$fallback_candidates) {
+ /*
+ *$fallback_candidates = array_reverse($fallback_candidates);
+ */
+ ${1:/* Your code here */}
+ }
diff --git a/modules/vim/vim/snippets/python.snippets b/modules/vim/vim/snippets/python.snippets
new file mode 100644
index 0000000..d511184
--- /dev/null
+++ b/modules/vim/vim/snippets/python.snippets
@@ -0,0 +1,86 @@
+snippet #!
+ #!/usr/bin/python
+
+snippet imp
+ import ${1:module}
+# Module Docstring
+snippet docs
+ '''
+ File: ${1:`Filename('$1.py', 'foo.py')`}
+ Author: ${2:`g:snips_author`}
+ Description: ${3}
+ '''
+snippet wh
+ while ${1:condition}:
+ ${2:# code...}
+snippet for
+ for ${1:needle} in ${2:haystack}:
+ ${3:# code...}
+# New Class
+snippet cl
+ class ${1:ClassName}(${2:object}):
+ """${3:docstring for $1}"""
+ def __init__(self, ${4:arg}):
+ ${5:super($1, self).__init__()}
+ self.$4 = $4
+ ${6}
+# New Function
+snippet def
+ def ${1:fname}(${2:`indent('.') ? 'self' : ''`}):
+ """${3:docstring for $1}"""
+ ${4:pass}
+snippet deff
+ def ${1:fname}(${2:`indent('.') ? 'self' : ''`}):
+ ${3}
+# New Method
+snippet defs
+ def ${1:mname}(self, ${2:arg}):
+ ${3:pass}
+# New Property
+snippet property
+ def ${1:foo}():
+ doc = "${2:The $1 property.}"
+ def fget(self):
+ ${3:return self._$1}
+ def fset(self, value):
+ ${4:self._$1 = value}
+# Lambda
+snippet ld
+ ${1:var} = lambda ${2:vars} : ${3:action}
+snippet .
+ self.
+snippet try Try/Except
+ try:
+ ${1:pass}
+ except ${2:Exception}, ${3:e}:
+ ${4:raise $3}
+snippet try Try/Except/Else
+ try:
+ ${1:pass}
+ except ${2:Exception}, ${3:e}:
+ ${4:raise $3}
+ else:
+ ${5:pass}
+snippet try Try/Except/Finally
+ try:
+ ${1:pass}
+ except ${2:Exception}, ${3:e}:
+ ${4:raise $3}
+ finally:
+ ${5:pass}
+snippet try Try/Except/Else/Finally
+ try:
+ ${1:pass}
+ except ${2:Exception}, ${3:e}:
+ ${4:raise $3}
+ else:
+ ${5:pass}
+ finally:
+ ${6:pass}
+# if __name__ == '__main__':
+snippet ifmain
+ if __name__ == '__main__':
+ ${1:main()}
+# __magic__
+snippet _
+ __${1:init}__${2}
diff --git a/modules/vim/vim/snippets/ruby.snippets b/modules/vim/vim/snippets/ruby.snippets
new file mode 100644
index 0000000..bf1d7f1
--- /dev/null
+++ b/modules/vim/vim/snippets/ruby.snippets
@@ -0,0 +1,420 @@
+# #!/usr/bin/ruby
+snippet #!
+ #!/usr/bin/ruby
+
+# New Block
+snippet =b
+ =begin rdoc
+ ${1}
+ =end
+snippet y
+ :yields: ${1:arguments}
+snippet rb
+ #!/usr/bin/env ruby -wKU
+
+snippet req
+ require "${1}"${2}
+snippet #
+ # =>
+snippet end
+ __END__
+snippet case
+ case ${1:object}
+ when ${2:condition}
+ ${3}
+ end
+snippet when
+ when ${1:condition}
+ ${2}
+snippet def
+ def ${1:method_name}
+ ${2}
+ end
+snippet deft
+ def test_${1:case_name}
+ ${2}
+ end
+snippet if
+ if ${1:condition}
+ ${2}
+ end
+snippet ife
+ if ${1:condition}
+ ${2}
+ else
+ ${3}
+ end
+snippet elsif
+ elsif ${1:condition}
+ ${2}
+snippet unless
+ unless ${1:condition}
+ ${2}
+ end
+snippet while
+ while ${1:condition}
+ ${2}
+ end
+snippet until
+ until ${1:condition}
+ ${2}
+ end
+snippet cla class .. end
+ class ${1:`substitute(Filename(), '^.', '\u&', '')`}
+ ${2}
+ end
+snippet cla class .. initialize .. end
+ class ${1:`substitute(Filename(), '^.', '\u&', '')`}
+ def initialize(${2:args})
+ ${3}
+ end
+
+
+ end
+snippet cla class .. < ParentClass .. initialize .. end
+ class ${1:`substitute(Filename(), '^.', '\u&', '')`} < ${2:ParentClass}
+ def initialize(${3:args})
+ ${4}
+ end
+
+
+ end
+snippet cla ClassName = Struct .. do .. end
+ ${1:`substitute(Filename(), '^.', '\u&', '')`} = Struct.new(:${2:attr_names}) do
+ def ${3:method_name}
+ ${4}
+ end
+
+
+ end
+snippet cla class BlankSlate .. initialize .. end
+ class ${1:BlankSlate}
+ instance_methods.each { |meth| undef_method(meth) unless meth =~ /\A__/ }
+snippet cla class << self .. end
+ class << ${1:self}
+ ${2}
+ end
+# class .. < DelegateClass .. initialize .. end
+snippet cla-
+ class ${1:`substitute(Filename(), '^.', '\u&', '')`} < DelegateClass(${2:ParentClass})
+ def initialize(${3:args})
+ super(${4:del_obj})
+
+ ${5}
+ end
+
+
+ end
+snippet mod module .. end
+ module ${1:`substitute(Filename(), '^.', '\u&', '')`}
+ ${2}
+ end
+snippet mod module .. module_function .. end
+ module ${1:`substitute(Filename(), '^.', '\u&', '')`}
+ module_function
+
+ ${2}
+ end
+snippet mod module .. ClassMethods .. end
+ module ${1:`substitute(Filename(), '^.', '\u&', '')`}
+ module ClassMethods
+ ${2}
+ end
+
+ module InstanceMethods
+
+ end
+
+ def self.included(receiver)
+ receiver.extend ClassMethods
+ receiver.send :include, InstanceMethods
+ end
+ end
+# attr_reader
+snippet r
+ attr_reader :${1:attr_names}
+# attr_writer
+snippet w
+ attr_writer :${1:attr_names}
+# attr_accessor
+snippet rw
+ attr_accessor :${1:attr_names}
+# include Enumerable
+snippet Enum
+ include Enumerable
+
+ def each(&block)
+ ${1}
+ end
+# include Comparable
+snippet Comp
+ include Comparable
+
+ def <=>(other)
+ ${1}
+ end
+# extend Forwardable
+snippet Forw-
+ extend Forwardable
+# def self
+snippet defs
+ def self.${1:class_method_name}
+ ${2}
+ end
+# def method_missing
+snippet defmm
+ def method_missing(meth, *args, &blk)
+ ${1}
+ end
+snippet defd
+ def_delegator :${1:@del_obj}, :${2:del_meth}, :${3:new_name}
+snippet defds
+ def_delegators :${1:@del_obj}, :${2:del_methods}
+snippet am
+ alias_method :${1:new_name}, :${2:old_name}
+snippet app
+ if __FILE__ == $PROGRAM_NAME
+ ${1}
+ end
+# usage_if()
+snippet usai
+ if ARGV.${1}
+ abort "Usage: #{$PROGRAM_NAME} ${2:ARGS_GO_HERE}"${3}
+ end
+# usage_unless()
+snippet usau
+ unless ARGV.${1}
+ abort "Usage: #{$PROGRAM_NAME} ${2:ARGS_GO_HERE}"${3}
+ end
+snippet array
+ Array.new(${1:10}) { |${2:i}| ${3} }
+snippet hash
+ Hash.new { |${1:hash}, ${2:key}| $1[$2] = ${3} }
+snippet file File.foreach() { |line| .. }
+ File.foreach(${1:"path/to/file"}) { |${2:line}| ${3} }
+snippet file File.read()
+ File.read(${1:"path/to/file"})${2}
+snippet Dir Dir.global() { |file| .. }
+ Dir.glob(${1:"dir/glob/*"}) { |${2:file}| ${3} }
+snippet Dir Dir[".."]
+ Dir[${1:"glob/**/*.rb"}]${2}
+snippet dir
+ Filename.dirname(__FILE__)
+snippet deli
+ delete_if { |${1:e}| ${2} }
+snippet fil
+ fill(${1:range}) { |${2:i}| ${3} }
+# flatten_once()
+snippet flao
+ inject(Array.new) { |${1:arr}, ${2:a}| $1.push(*$2)}${3}
+snippet zip
+ zip(${1:enums}) { |${2:row}| ${3} }
+# downto(0) { |n| .. }
+snippet dow
+ downto(${1:0}) { |${2:n}| ${3} }
+snippet ste
+ step(${1:2}) { |${2:n}| ${3} }
+snippet tim
+ times { |${1:n}| ${2} }
+snippet upt
+ upto(${1:1.0/0.0}) { |${2:n}| ${3} }
+snippet loo
+ loop { ${1} }
+snippet ea
+ each { |${1:e}| ${2} }
+snippet eab
+ each_byte { |${1:byte}| ${2} }
+snippet eac- each_char { |chr| .. }
+ each_char { |${1:chr}| ${2} }
+snippet eac- each_cons(..) { |group| .. }
+ each_cons(${1:2}) { |${2:group}| ${3} }
+snippet eai
+ each_index { |${1:i}| ${2} }
+snippet eak
+ each_key { |${1:key}| ${2} }
+snippet eal
+ each_line { |${1:line}| ${2} }
+snippet eap
+ each_pair { |${1:name}, ${2:val}| ${3} }
+snippet eas-
+ each_slice(${1:2}) { |${2:group}| ${3} }
+snippet eav
+ each_value { |${1:val}| ${2} }
+snippet eawi
+ each_with_index { |${1:e}, ${2:i}| ${3} }
+snippet reve
+ reverse_each { |${1:e}| ${2} }
+snippet inj
+ inject(${1:init}) { |${2:mem}, ${3:var}| ${4} }
+snippet map
+ map { |${1:e}| ${2} }
+snippet mapwi-
+ enum_with_index.map { |${1:e}, ${2:i}| ${3} }
+snippet sor
+ sort { |a, b| ${1} }
+snippet sorb
+ sort_by { |${1:e}| ${2} }
+snippet ran
+ sort_by { rand }
+snippet all
+ all? { |${1:e}| ${2} }
+snippet any
+ any? { |${1:e}| ${2} }
+snippet cl
+ classify { |${1:e}| ${2} }
+snippet col
+ collect { |${1:e}| ${2} }
+snippet det
+ detect { |${1:e}| ${2} }
+snippet fet
+ fetch(${1:name}) { |${2:key}| ${3} }
+snippet fin
+ find { |${1:e}| ${2} }
+snippet fina
+ find_all { |${1:e}| ${2} }
+snippet gre
+ grep(${1:/pattern/}) { |${2:match}| ${3} }
+snippet sub
+ ${1:g}sub(${2:/pattern/}) { |${3:match}| ${4} }
+snippet sca
+ scan(${1:/pattern/}) { |${2:match}| ${3} }
+snippet max
+ max { |a, b|, ${1} }
+snippet min
+ min { |a, b|, ${1} }
+snippet par
+ partition { |${1:e}|, ${2} }
+snippet rej
+ reject { |${1:e}|, ${2} }
+snippet sel
+ select { |${1:e}|, ${2} }
+snippet lam
+ lambda { |${1:args}| ${2} }
+snippet do
+ do |${1:variable}|
+ ${2}
+ end
+snippet :
+ :${1:key} => ${2:"value"}${3}
+snippet ope
+ open(${1:"path/or/url/or/pipe"}, "${2:w}") { |${3:io}| ${4} }
+# path_from_here()
+snippet patfh
+ File.join(File.dirname(__FILE__), *%2[${1:rel path here}])${2}
+# unix_filter {}
+snippet unif
+ ARGF.each_line${1} do |${2:line}|
+ ${3}
+ end
+# option_parse {}
+snippet optp
+ require "optparse"
+
+ options = {${1:default => "args"}}
+
+ ARGV.options do |opts|
+ opts.banner = "Usage: #{File.basename($PROGRAM_NAME)}
+snippet opt
+ opts.on( "-${1:o}", "--${2:long-option-name}", ${3:String},
+ "${4:Option description.}") do |${5:opt}|
+ ${6}
+ end
+snippet tc
+ require "test/unit"
+
+ require "${1:library_file_name}"
+
+ class Test${2:$1} < Test::Unit::TestCase
+ def test_${3:case_name}
+ ${4}
+ end
+ end
+snippet ts
+ require "test/unit"
+
+ require "tc_${1:test_case_file}"
+ require "tc_${2:test_case_file}"${3}
+snippet as
+ assert(${1:test}, "${2:Failure message.}")${3}
+snippet ase
+ assert_equal(${1:expected}, ${2:actual})${3}
+snippet asne
+ assert_not_equal(${1:unexpected}, ${2:actual})${3}
+snippet asid
+ assert_in_delta(${1:expected_float}, ${2:actual_float}, ${3:2 ** -20})${4}
+snippet asio
+ assert_instance_of(${1:ExpectedClass}, ${2:actual_instance})${3}
+snippet asko
+ assert_kind_of(${1:ExpectedKind}, ${2:actual_instance})${3}
+snippet asn
+ assert_nil(${1:instance})${2}
+snippet asnn
+ assert_not_nil(${1:instance})${2}
+snippet asm
+ assert_match(/${1:expected_pattern}/, ${2:actual_string})${3}
+snippet asnm
+ assert_no_match(/${1:unexpected_pattern}/, ${2:actual_string})${3}
+snippet aso
+ assert_operator(${1:left}, :${2:operator}, ${3:right})${4}
+snippet asr
+ assert_raise(${1:Exception}) { ${2} }
+snippet asnr
+ assert_nothing_raised(${1:Exception}) { ${2} }
+snippet asrt
+ assert_respond_to(${1:object}, :${2:method})${3}
+snippet ass assert_same(..)
+ assert_same(${1:expected}, ${2:actual})${3}
+snippet ass assert_send(..)
+ assert_send([${1:object}, :${2:message}, ${3:args}])${4}
+snippet asns
+ assert_not_same(${1:unexpected}, ${2:actual})${3}
+snippet ast
+ assert_throws(:${1:expected}) { ${2} }
+snippet asnt
+ assert_nothing_thrown { ${1} }
+snippet fl
+ flunk("${1:Failure message.}")${2}
+# Benchmark.bmbm do .. end
+snippet bm-
+ TESTS = ${1:10_000}
+ Benchmark.bmbm do |results|
+ ${2}
+ end
+snippet rep
+ results.report("${1:name}:") { TESTS.times { ${2} }}
+# Marshal.dump(.., file)
+snippet Md
+ File.open(${1:"path/to/file.dump"}, "wb") { |${2:file}| Marshal.dump(${3:obj}, $2) }${4}
+# Mashal.load(obj)
+snippet Ml
+ File.open(${1:"path/to/file.dump"}, "rb") { |${2:file}| Marshal.load($2) }${3}
+# deep_copy(..)
+snippet deec
+ Marshal.load(Marshal.dump(${1:obj_to_copy}))${2}
+snippet Pn-
+ PStore.new(${1:"file_name.pstore"})${2}
+snippet tra
+ transaction(${1:true}) { ${2} }
+# xmlread(..)
+snippet xml-
+ REXML::Document.new(File.read(${1:"path/to/file"}))${2}
+# xpath(..) { .. }
+snippet xpa
+ elements.each(${1:"//Xpath"}) do |${2:node}|
+ ${3}
+ end
+# class_from_name()
+snippet clafn
+ split("::").inject(Object) { |par, const| par.const_get(const) }
+# singleton_class()
+snippet sinc
+ class << self; self end
+snippet nam
+ namespace :${1:`Filename()`} do
+ ${2}
+ end
+snippet tas
+ desc "${1:Task description\}"
+ task :${2:task_name => [:dependent, :tasks]} do
+ ${3}
+ end
diff --git a/modules/vim/vim/snippets/sh.snippets b/modules/vim/vim/snippets/sh.snippets
new file mode 100644
index 0000000..f035126
--- /dev/null
+++ b/modules/vim/vim/snippets/sh.snippets
@@ -0,0 +1,28 @@
+# #!/bin/bash
+snippet #!
+ #!/bin/bash
+
+snippet if
+ if [[ ${1:condition} ]]; then
+ ${2:#statements}
+ fi
+snippet elif
+ elif [[ ${1:condition} ]]; then
+ ${2:#statements}
+snippet for
+ for (( ${2:i} = 0; $2 < ${1:count}; $2++ )); do
+ ${3:#statements}
+ done
+snippet wh
+ while [[ ${1:condition} ]]; do
+ ${2:#statements}
+ done
+snippet until
+ until [[ ${1:condition} ]]; do
+ ${2:#statements}
+ done
+snippet case
+ case ${1:word} in
+ ${2:pattern})
+ ${3};;
+ esac
diff --git a/modules/vim/vim/snippets/snippet.snippets b/modules/vim/vim/snippets/snippet.snippets
new file mode 100644
index 0000000..854c058
--- /dev/null
+++ b/modules/vim/vim/snippets/snippet.snippets
@@ -0,0 +1,7 @@
+# snippets for making snippets :)
+snippet snip
+ snippet ${1:trigger}
+ ${2}
+snippet msnip
+ snippet ${1:trigger} ${2:description}
+ ${3}
diff --git a/modules/vim/vim/snippets/tcl.snippets b/modules/vim/vim/snippets/tcl.snippets
new file mode 100644
index 0000000..bee2ef8
--- /dev/null
+++ b/modules/vim/vim/snippets/tcl.snippets
@@ -0,0 +1,92 @@
+# #!/usr/bin/tclsh
+snippet #!
+ #!/usr/bin/tclsh
+
+# Process
+snippet pro
+ proc ${1:function_name} {${2:args}} {
+ ${3:#body ...}
+ }
+#xif
+snippet xif
+ ${1:expr}? ${2:true} : ${3:false}
+# Conditional
+snippet if
+ if {${1}} {
+ ${2:# body...}
+ }
+# Conditional if..else
+snippet ife
+ if {${1}} {
+ ${2:# body...}
+ } else {
+ ${3:# else...}
+ }
+# Conditional if..elsif..else
+snippet ifee
+ if {${1}} {
+ ${2:# body...}
+ } elseif {${3}} {
+ ${4:# elsif...}
+ } else {
+ ${5:# else...}
+ }
+# If catch then
+snippet ifc
+ if { [catch {${1:#do something...}} ${2:err}] } {
+ ${3:# handle failure...}
+ }
+# Catch
+snippet catch
+ catch {${1}} ${2:err} ${3:options}
+# While Loop
+snippet wh
+ while {${1}} {
+ ${2:# body...}
+ }
+# For Loop
+snippet for
+ for {set ${2:var} 0} {$$2 < ${1:count}} {${3:incr} $2} {
+ ${4:# body...}
+ }
+# Foreach Loop
+snippet fore
+ foreach ${1:x} {${2:#list}} {
+ ${3:# body...}
+ }
+# after ms script...
+snippet af
+ after ${1:ms} ${2:#do something}
+# after cancel id
+snippet afc
+ after cancel ${1:id or script}
+# after idle
+snippet afi
+ after idle ${1:script}
+# after info id
+snippet afin
+ after info ${1:id}
+# Expr
+snippet exp
+ expr {${1:#expression here}}
+# Switch
+snippet sw
+ switch ${1:var} {
+ ${3:pattern 1} {
+ ${4:#do something}
+ }
+ default {
+ ${2:#do something}
+ }
+ }
+# Case
+snippet ca
+ ${1:pattern} {
+ ${2:#do something}
+ }${3}
+# Namespace eval
+snippet ns
+ namespace eval ${1:path} {${2:#script...}}
+# Namespace current
+snippet nsc
+ namespace current
diff --git a/modules/vim/vim/snippets/tex.snippets b/modules/vim/vim/snippets/tex.snippets
new file mode 100644
index 0000000..22f7316
--- /dev/null
+++ b/modules/vim/vim/snippets/tex.snippets
@@ -0,0 +1,115 @@
+# \begin{}...\end{}
+snippet begin
+ \begin{${1:env}}
+ ${2}
+ \end{$1}
+# Tabular
+snippet tab
+ \begin{${1:tabular}}{${2:c}}
+ ${3}
+ \end{$1}
+# Align(ed)
+snippet ali
+ \begin{align${1:ed}}
+ ${2}
+ \end{align$1}
+# Gather(ed)
+snippet gat
+ \begin{gather${1:ed}}
+ ${2}
+ \end{gather$1}
+# Equation
+snippet eq
+ \begin{equation}
+ ${1}
+ \end{equation}
+# Unnumbered Equation
+snippet \
+ \\[
+ ${1}
+ \\]
+# Enumerate
+snippet enum
+ \begin{enumerate}
+ \item ${1}
+ \end{enumerate}
+# Itemize
+snippet item
+ \begin{itemize}
+ \item ${1}
+ \end{itemize}
+# Description
+snippet desc
+ \begin{description}
+ \item[${1}] ${2}
+ \end{description}
+# Matrix
+snippet mat
+ \begin{${1:p/b/v/V/B/small}matrix}
+ ${2}
+ \end{$1matrix}
+# Cases
+snippet cas
+ \begin{cases}
+ ${1:equation}, &\text{ if }${2:case}\\
+ ${3}
+ \end{cases}
+# Split
+snippet spl
+ \begin{split}
+ ${1}
+ \end{split}
+# Part
+snippet part
+ \part{${1:part name}} % (fold)
+ \label{prt:${2:$1}}
+ ${3}
+ % part $2 (end)
+# Chapter
+snippet cha
+ \chapter{${1:chapter name}} % (fold)
+ \label{cha:${2:$1}}
+ ${3}
+ % chapter $2 (end)
+# Section
+snippet sec
+ \section{${1:section name}} % (fold)
+ \label{sec:${2:$1}}
+ ${3}
+ % section $2 (end)
+# Sub Section
+snippet sub
+ \subsection{${1:subsection name}} % (fold)
+ \label{sub:${2:$1}}
+ ${3}
+ % subsection $2 (end)
+# Sub Sub Section
+snippet subs
+ \subsubsection{${1:subsubsection name}} % (fold)
+ \label{ssub:${2:$1}}
+ ${3}
+ % subsubsection $2 (end)
+# Paragraph
+snippet par
+ \paragraph{${1:paragraph name}} % (fold)
+ \label{par:${2:$1}}
+ ${3}
+ % paragraph $2 (end)
+# Sub Paragraph
+snippet subp
+ \subparagraph{${1:subparagraph name}} % (fold)
+ \label{subp:${2:$1}}
+ ${3}
+ % subparagraph $2 (end)
+snippet itd
+ \item[${1:description}] ${2:item}
+snippet figure
+ ${1:Figure}~\ref{${2:fig:}}${3}
+snippet table
+ ${1:Table}~\ref{${2:tab:}}${3}
+snippet listing
+ ${1:Listing}~\ref{${2:list}}${3}
+snippet section
+ ${1:Section}~\ref{${2:sec:}}${3}
+snippet page
+ ${1:page}~\pageref{${2}}${3}
diff --git a/modules/vim/vim/snippets/vim.snippets b/modules/vim/vim/snippets/vim.snippets
new file mode 100644
index 0000000..64e7807
--- /dev/null
+++ b/modules/vim/vim/snippets/vim.snippets
@@ -0,0 +1,32 @@
+snippet header
+ " File: ${1:`expand('%:t')`}
+ " Author: ${2:`g:snips_author`}
+ " Description: ${3}
+ ${4:" Last Modified: `strftime("%B %d, %Y")`}
+snippet guard
+ if exists('${1:did_`Filename()`}') || &cp${2: || version < 700}
+ finish
+ endif
+ let $1 = 1${3}
+snippet f
+ fun ${1:function_name}(${2})
+ ${3:" code}
+ endf
+snippet for
+ for ${1:needle} in ${2:haystack}
+ ${3:" code}
+ endfor
+snippet wh
+ while ${1:condition}
+ ${2:" code}
+ endw
+snippet if
+ if ${1:condition}
+ ${2:" code}
+ endif
+snippet ife
+ if ${1:condition}
+ ${2}
+ else
+ ${3}
+ endif
diff --git a/modules/vim/vim/snippets/zsh.snippets b/modules/vim/vim/snippets/zsh.snippets
new file mode 100644
index 0000000..7aee05b
--- /dev/null
+++ b/modules/vim/vim/snippets/zsh.snippets
@@ -0,0 +1,58 @@
+# #!/bin/zsh
+snippet #!
+ #!/bin/zsh
+
+snippet if
+ if ${1:condition}; then
+ ${2:# statements}
+ fi
+snippet ife
+ if ${1:condition}; then
+ ${2:# statements}
+ else
+ ${3:# statements}
+ fi
+snippet elif
+ elif ${1:condition} ; then
+ ${2:# statements}
+snippet for
+ for (( ${2:i} = 0; $2 < ${1:count}; $2++ )); do
+ ${3:# statements}
+ done
+snippet fore
+ for ${1:item} in ${2:list}; do
+ ${3:# statements}
+ done
+snippet wh
+ while ${1:condition}; do
+ ${2:# statements}
+ done
+snippet until
+ until ${1:condition}; do
+ ${2:# statements}
+ done
+snippet repeat
+ repeat ${1:integer}; do
+ ${2:# statements}
+ done
+snippet case
+ case ${1:word} in
+ ${2:pattern})
+ ${3};;
+ esac
+snippet select
+ select ${1:answer} in ${2:choices}; do
+ ${3:# statements}
+ done
+snippet (
+ ( ${1:#statements} )
+snippet {
+ { ${1:#statements} }
+snippet [
+ [[ ${1:test} ]]
+snippet always
+ { ${1:try} } always { ${2:always} }
+snippet fun
+ function ${1:name} (${2:args}) {
+ ${3:# body}
+ }
diff --git a/modules/vim/vim/syntax/CVSAnnotate.vim b/modules/vim/vim/syntax/CVSAnnotate.vim
new file mode 100644
index 0000000..4af5809
--- /dev/null
+++ b/modules/vim/vim/syntax/CVSAnnotate.vim
@@ -0,0 +1,45 @@
+" Vim syntax file
+" Language: CVS annotate output
+" Maintainer: Bob Hiestand <bob.hiestand@gmail.com>
+" Remark: Used by the cvscommand plugin. Originally written by Mathieu
+" Clabaut
+" License:
+" Copyright (c) 2007 Bob Hiestand
+"
+" Permission is hereby granted, free of charge, to any person obtaining a copy
+" of this software and associated documentation files (the "Software"), to
+" deal in the Software without restriction, including without limitation the
+" rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+" sell copies of the Software, and to permit persons to whom the Software is
+" furnished to do so, subject to the following conditions:
+"
+" The above copyright notice and this permission notice shall be included in
+" all copies or substantial portions of the Software.
+"
+" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+" IN THE SOFTWARE.
+
+if version < 600
+ syntax clear
+elseif exists("b:current_syntax")
+ finish
+endif
+
+syn match cvsDate /\d\d-...-\d\d/ contained
+syn match cvsName /(\S* /hs=s+1,he=e-1 contained nextgroup=cvsDate
+syn match cvsVer /^\d\+\(\.\d\+\)\+/ contained nextgroup=cvsName
+syn region cvsHead start="^\d\+\.\d\+" end="):" contains=cvsVer,cvsName,cvsDate
+
+if !exists("did_cvsannotate_syntax_inits")
+ let did_cvsannotate_syntax_inits = 1
+ hi link cvsDate Comment
+ hi link cvsName Type
+ hi link cvsVer Statement
+endif
+
+let b:current_syntax="CVSAnnotate"
diff --git a/modules/vim/vim/syntax/SVKAnnotate.vim b/modules/vim/vim/syntax/SVKAnnotate.vim
new file mode 100644
index 0000000..3c53c3c
--- /dev/null
+++ b/modules/vim/vim/syntax/SVKAnnotate.vim
@@ -0,0 +1,42 @@
+" Vim syntax file
+" Language: SVK annotate output
+" Maintainer: Bob Hiestand <bob.hiestand@gmail.com>
+" Remark: Used by the vcscommand plugin.
+" License:
+" Copyright (c) 2007 Bob Hiestand
+"
+" Permission is hereby granted, free of charge, to any person obtaining a copy
+" of this software and associated documentation files (the "Software"), to
+" deal in the Software without restriction, including without limitation the
+" rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+" sell copies of the Software, and to permit persons to whom the Software is
+" furnished to do so, subject to the following conditions:
+"
+" The above copyright notice and this permission notice shall be included in
+" all copies or substantial portions of the Software.
+"
+" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+" IN THE SOFTWARE.
+
+if exists("b:current_syntax")
+ finish
+endif
+
+syn match svkDate /\d\{4}-\d\{1,2}-\d\{1,2}/ skipwhite contained
+syn match svkName /(\s*\zs\S\+/ contained nextgroup=svkDate skipwhite
+syn match svkVer /^\s*\d\+/ contained nextgroup=svkName skipwhite
+syn region svkHead start=/^/ end="):" contains=svkVer,svkName,svkDate oneline
+
+if !exists("did_svkannotate_syntax_inits")
+ let did_svkannotate_syntax_inits = 1
+ hi link svkName Type
+ hi link svkDate Comment
+ hi link svkVer Statement
+endif
+
+let b:current_syntax="svkAnnotate"
diff --git a/modules/vim/vim/syntax/SVNAnnotate.vim b/modules/vim/vim/syntax/SVNAnnotate.vim
new file mode 100644
index 0000000..d46f771
--- /dev/null
+++ b/modules/vim/vim/syntax/SVNAnnotate.vim
@@ -0,0 +1,40 @@
+" Vim syntax file
+" Language: SVN annotate output
+" Maintainer: Bob Hiestand <bob.hiestand@gmail.com>
+" Remark: Used by the vcscommand plugin.
+" License:
+" Copyright (c) 2007 Bob Hiestand
+"
+" Permission is hereby granted, free of charge, to any person obtaining a copy
+" of this software and associated documentation files (the "Software"), to
+" deal in the Software without restriction, including without limitation the
+" rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+" sell copies of the Software, and to permit persons to whom the Software is
+" furnished to do so, subject to the following conditions:
+"
+" The above copyright notice and this permission notice shall be included in
+" all copies or substantial portions of the Software.
+"
+" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+" IN THE SOFTWARE.
+
+if exists("b:current_syntax")
+ finish
+endif
+
+syn match svnName /\S\+/ contained
+syn match svnVer /^\s\+\zs\d\+/ contained nextgroup=svnName skipwhite
+syn match svnHead /^\s\+\d\+\s\+\S\+/ contains=svnVer,svnName
+
+if !exists("did_svnannotate_syntax_inits")
+ let did_svnannotate_syntax_inits = 1
+ hi link svnName Type
+ hi link svnVer Statement
+endif
+
+let b:current_syntax="svnAnnotate"
diff --git a/modules/vim/vim/syntax/cvsannotate.vim b/modules/vim/vim/syntax/cvsannotate.vim
new file mode 100644
index 0000000..f35ed96
--- /dev/null
+++ b/modules/vim/vim/syntax/cvsannotate.vim
@@ -0,0 +1,45 @@
+" Vim syntax file
+" Language: CVS annotate output
+" Maintainer: Bob Hiestand <bob.hiestand@gmail.com>
+" Remark: Used by the cvscommand plugin. Originally written by Mathieu
+" Clabaut
+" License:
+" Copyright (c) Bob Hiestand
+"
+" Permission is hereby granted, free of charge, to any person obtaining a copy
+" of this software and associated documentation files (the "Software"), to
+" deal in the Software without restriction, including without limitation the
+" rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+" sell copies of the Software, and to permit persons to whom the Software is
+" furnished to do so, subject to the following conditions:
+"
+" The above copyright notice and this permission notice shall be included in
+" all copies or substantial portions of the Software.
+"
+" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+" IN THE SOFTWARE.
+
+if version < 600
+ syntax clear
+elseif exists("b:current_syntax")
+ finish
+endif
+
+syn match cvsDate /\d\d-...-\d\d/ contained
+syn match cvsName /(\S* /hs=s+1,he=e-1 contained nextgroup=cvsDate
+syn match cvsVer /^\d\+\(\.\d\+\)\+/ contained nextgroup=cvsName
+syn region cvsHead start="^\d\+\.\d\+" end="):" contains=cvsVer,cvsName,cvsDate
+
+if !exists("did_cvsannotate_syntax_inits")
+ let did_cvsannotate_syntax_inits = 1
+ hi link cvsDate Comment
+ hi link cvsName Type
+ hi link cvsVer Statement
+endif
+
+let b:current_syntax="CVSAnnotate"
diff --git a/modules/vim/vim/syntax/git-diff.vim b/modules/vim/vim/syntax/git-diff.vim
new file mode 100644
index 0000000..54a97ec
--- /dev/null
+++ b/modules/vim/vim/syntax/git-diff.vim
@@ -0,0 +1,8 @@
+runtime syntax/diff.vim
+
+syntax match gitDiffStatLine /^ .\{-}\zs[+-]\+$/ contains=gitDiffStatAdd,gitDiffStatDelete
+syntax match gitDiffStatAdd /+/ contained
+syntax match gitDiffStatDelete /-/ contained
+
+highlight gitDiffStatAdd ctermfg=2
+highlight gitDiffStatDelete ctermfg=5
diff --git a/modules/vim/vim/syntax/git-log.vim b/modules/vim/vim/syntax/git-log.vim
new file mode 100644
index 0000000..571b28a
--- /dev/null
+++ b/modules/vim/vim/syntax/git-log.vim
@@ -0,0 +1,3 @@
+syntax match gitLogCommit +^commit \x\{40}+
+
+highlight link gitLogCommit Statement
diff --git a/modules/vim/vim/syntax/git-status.vim b/modules/vim/vim/syntax/git-status.vim
new file mode 100644
index 0000000..4cf05e5
--- /dev/null
+++ b/modules/vim/vim/syntax/git-status.vim
@@ -0,0 +1,18 @@
+runtime syntax/diff.vim
+setlocal filetype=
+
+syntax match gitStatusComment +^#.*+ contains=ALL
+
+syntax match gitStatusBranch +On branch .\++
+
+syntax match gitStatusUndracked +\t\zs.\++
+syntax match gitStatusNewFile +\t\zsnew file: .\++
+syntax match gitStatusModified +\t\zsmodified: .\++
+
+highlight link gitStatusComment Comment
+
+highlight link gitStatusBranch Title
+
+highlight link gitStatusUndracked diffOnly
+highlight link gitStatusNewFile diffAdded
+highlight link gitStatusModified diffChanged
diff --git a/modules/vim/vim/syntax/gitannotate.vim b/modules/vim/vim/syntax/gitannotate.vim
new file mode 100644
index 0000000..77ad14e
--- /dev/null
+++ b/modules/vim/vim/syntax/gitannotate.vim
@@ -0,0 +1,44 @@
+" Vim syntax file
+" Language: git annotate output
+" Maintainer: Bob Hiestand <bob.hiestand@gmail.com>
+" Remark: Used by the vcscommand plugin.
+" License:
+" Copyright (c) Bob Hiestand
+"
+" Permission is hereby granted, free of charge, to any person obtaining a copy
+" of this software and associated documentation files (the "Software"), to
+" deal in the Software without restriction, including without limitation the
+" rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+" sell copies of the Software, and to permit persons to whom the Software is
+" furnished to do so, subject to the following conditions:
+"
+" The above copyright notice and this permission notice shall be included in
+" all copies or substantial portions of the Software.
+"
+" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+" IN THE SOFTWARE.
+
+if exists("b:current_syntax")
+ finish
+endif
+
+syn region gitName start="(\@<=" end="\( \d\d\d\d-\)\@=" contained
+syn match gitCommit /^\^\?\x\+/ contained
+syn match gitDate /\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d [+-]\d\d\d\d/ contained
+syn match gitLineNumber /\d\+)\@=/ contained
+syn region gitAnnotation start="^" end=") " oneline keepend contains=gitCommit,gitLineNumber,gitDate,gitName
+
+if !exists("did_gitannotate_syntax_inits")
+ let did_gitannotate_syntax_inits = 1
+ hi link gitName Type
+ hi link gitCommit Statement
+ hi link gitDate Comment
+ hi link gitLineNumber Label
+endif
+
+let b:current_syntax="gitAnnotate"
diff --git a/modules/vim/vim/syntax/hgannotate.vim b/modules/vim/vim/syntax/hgannotate.vim
new file mode 100644
index 0000000..4e1d627
--- /dev/null
+++ b/modules/vim/vim/syntax/hgannotate.vim
@@ -0,0 +1,40 @@
+" Vim syntax file
+" Language: HG annotate output
+" Maintainer: Bob Hiestand <bob.hiestand@gmail.com>
+" Remark: Used by the vcscommand plugin.
+" License:
+" Copyright (c) Bob Hiestand
+"
+" Permission is hereby granted, free of charge, to any person obtaining a copy
+" of this software and associated documentation files (the "Software"), to
+" deal in the Software without restriction, including without limitation the
+" rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+" sell copies of the Software, and to permit persons to whom the Software is
+" furnished to do so, subject to the following conditions:
+"
+" The above copyright notice and this permission notice shall be included in
+" all copies or substantial portions of the Software.
+"
+" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+" IN THE SOFTWARE.
+
+if exists("b:current_syntax")
+ finish
+endif
+
+syn match hgVer /\d\+/ contained
+syn match hgName /^\s*\S\+/ contained
+syn match hgHead /^\s*\S\+\s\+\d\+:/ contains=hgVer,hgName
+
+if !exists("did_hgannotate_syntax_inits")
+ let did_hgannotate_syntax_inits = 1
+ hi link hgName Type
+ hi link hgVer Statement
+endif
+
+let b:current_syntax="hgAnnotate"
diff --git a/modules/vim/vim/syntax/ikiwiki.vim b/modules/vim/vim/syntax/ikiwiki.vim
new file mode 100644
index 0000000..bbcad42
--- /dev/null
+++ b/modules/vim/vim/syntax/ikiwiki.vim
@@ -0,0 +1,71 @@
+" Vim syntax file
+" Language: Ikiwiki (links)
+" Maintainer: Recai OktaÅŸ (roktasATdebian.org)
+" Last Change: 2007 May 29
+
+" Instructions:
+" - make sure to use the relevant syntax file which can be found
+" at vim.org; below are the syntax files for markdown and reST,
+" respectively:
+" http://www.vim.org/scripts/script.php?script_id=1242
+" http://www.vim.org/scripts/script.php?script_id=973
+" - put the file into your syntax directory (e.g. ~/.vim/syntax)
+" - if you use markdown (with .mdwn extension) add sth like below
+" in your VIM startup file:
+" au BufNewFile,BufRead *.mdwn set ft=ikiwiki
+" - if you use a different markup other than markdown (e.g. reST)
+" make sure to setup 'g:ikiwiki_render_filetype' properly in
+" your startup file (skip this step for mkd.vim, it should work
+" out of the box)
+" Todo:
+" - revamp the whole file so as to detect valid ikiwiki directives
+" and parameters (needs a serious work)
+
+let s:cpo_save = &cpo
+set cpo&vim
+
+" Load the base syntax (default to markdown) if nothing was loaded.
+if !exists("b:current_syntax")
+ let s:ikiwiki_render_filetype = "mkd"
+ if exists("g:ikiwiki_render_filetype")
+ let s:ikiwiki_render_filetype = g:ikiwiki_render_filetype
+ endif
+ exe 'runtime! syntax/' . s:ikiwiki_render_filetype . '.vim'
+endif
+
+unlet b:current_syntax
+
+syn case match
+
+syn region ikiwikiLinkContent matchgroup=ikiwikiLink start=+\[\[\(\w\+\s\+\)\{,1}+ end=+\]\]+ contains=ikiwikiLinkNested,ikiwikiParam,ikiwikiNoParam
+syn region ikiwikiLinkNested matchgroup=ikiwikiLinkNested start=+"""+ end=+"""+ contains=ikiwikiLinkContent contained
+
+" FIXME: Below is an ugly hack to prevent highlighting of simple links
+" as directives. Links with spaces are still problematic though.
+syn region ikiwikiNoParam start=+\[\[[^|=]\+|+ end=+[^|=]\+\]\]+ keepend contains=ikiwikiMagic,ikiwikiDelim
+
+syn match ikiwikiDelim "\(\[\[\|\]\]\)" contained
+syn match ikiwikiMagic "|" contained
+syn match ikiwikiParam "\<\i\+\ze=" nextgroup=ikiwikiParamAssign contained
+syn match ikiwikiParamAssign "=" nextgroup=ikiwikiValue contained
+syn region ikiwikiValue start=+"[^"]+hs=e-1 end=+[^"]"+ skip=+\\"+ keepend contains=ikiwikiValueMagic,ikiwikiDelim contained
+syn match ikiwikiValueMagic +\(!\<\|\*\|\<\(and\|or\)\>\|\<\i*(\|\>)\)+ contained
+
+syn sync minlines=50
+
+hi def link ikiwikiLink Statement
+hi def link ikiwikiLinkNested String
+hi def link ikiwikiLinkContent Underlined
+
+hi def link ikiwikiMagic Operator
+hi def link ikiwikiDelim Operator
+hi def link ikiwikiNoParam Underlined
+hi def link ikiwikiParam Identifier
+hi def link ikiwikiParamAssign Operator
+hi def link ikiwikiValue String
+hi def link ikiwikiValueMagic Type
+
+let b:current_syntax = "ikiwiki"
+unlet s:cpo_save
+
+" vim:ts=8:sts=8:noet
diff --git a/modules/vim/vim/syntax/mkd.vim b/modules/vim/vim/syntax/mkd.vim
new file mode 100644
index 0000000..6c23415
--- /dev/null
+++ b/modules/vim/vim/syntax/mkd.vim
@@ -0,0 +1,86 @@
+" Vim syntax file
+" Language: Markdown
+" Maintainer: Ben Williams <benw@plasticboy.com>
+" URL: http://plasticboy.com/markdown-vim-mode/
+" Version: 8
+" Last Change: 2008 April 29
+" Remark: Uses HTML syntax file
+" Remark: I don't do anything with angle brackets (<>) because that would too easily
+" easily conflict with HTML syntax
+" TODO: Do something appropriate with image syntax
+" TODO: Handle stuff contained within stuff (e.g. headings within blockquotes)
+
+
+" Read the HTML syntax to start with
+if version < 600
+ so <sfile>:p:h/html.vim
+else
+ runtime! syntax/html.vim
+ unlet b:current_syntax
+endif
+
+if version < 600
+ syntax clear
+elseif exists("b:current_syntax")
+ finish
+endif
+
+" don't use standard HiLink, it will not work with included syntax files
+if version < 508
+ command! -nargs=+ HtmlHiLink hi link <args>
+else
+ command! -nargs=+ HtmlHiLink hi def link <args>
+endif
+
+syn spell toplevel
+syn case ignore
+syn sync linebreaks=1
+
+"additions to HTML groups
+syn region htmlBold start=/\(^\|\s\)\*\@<!\*\*\*\@!/ end=/\*\@<!\*\*\*\@!\($\|\s\)/ contains=@Spell,htmlItalic
+syn region htmlItalic start=/\(^\|\s\)\*\@<!\*\*\@!/ end=/\*\@<!\*\*\@!\($\|\s\)/ contains=htmlBold,@Spell
+syn region htmlBold start=/\(^\|\s\)_\@<!___\@!/ end=/_\@<!___\@!\($\|\s\)/ contains=htmlItalic,@Spell
+syn region htmlItalic start=/\(^\|\s\)_\@<!__\@!/ end=/_\@<!__\@!\($\|\s\)/ contains=htmlBold,@Spell
+syn region htmlString start="]("ms=s+2 end=")"me=e-1
+syn region htmlLink start="\["ms=s+1 end="\]"me=e-1 contains=@Spell
+syn region htmlString start="\(\[.*]: *\)\@<=.*" end="$"
+
+"define Markdown groups
+syn match mkdLineContinue ".$" contained
+syn match mkdRule /^\s*\*\s\{0,1}\*\s\{0,1}\*$/
+syn match mkdRule /^\s*-\s\{0,1}-\s\{0,1}-$/
+syn match mkdRule /^\s*_\s\{0,1}_\s\{0,1}_$/
+syn match mkdRule /^\s*-\{3,}$/
+syn match mkdRule /^\s*\*\{3,5}$/
+syn match mkdListItem "^\s*[-*+]\s\+"
+syn match mkdListItem "^\s*\d\+\.\s\+"
+syn match mkdCode /^\s*\n\(\(\s\{4,}\|[\t]\+\)[^*-+ ].*\n\)\+/
+syn region mkdCode start=/`/ end=/`/
+syn region mkdCode start=/\s*``[^`]*/ end=/[^`]*``\s*/
+syn region mkdBlockquote start=/^\s*>/ end=/$/ contains=mkdLineContinue,@Spell
+syn region mkdCode start="<pre[^>]*>" end="</pre>"
+syn region mkdCode start="<code[^>]*>" end="</code>"
+
+"HTML headings
+syn region htmlH1 start="^\s*#" end="\($\|#\+\)" contains=@Spell
+syn region htmlH2 start="^\s*##" end="\($\|#\+\)" contains=@Spell
+syn region htmlH3 start="^\s*###" end="\($\|#\+\)" contains=@Spell
+syn region htmlH4 start="^\s*####" end="\($\|#\+\)" contains=@Spell
+syn region htmlH5 start="^\s*#####" end="\($\|#\+\)" contains=@Spell
+syn region htmlH6 start="^\s*######" end="\($\|#\+\)" contains=@Spell
+syn match htmlH1 /^.\+\n=\+$/ contains=@Spell
+syn match htmlH2 /^.\+\n-\+$/ contains=@Spell
+
+"highlighting for Markdown groups
+HtmlHiLink mkdString String
+HtmlHiLink mkdCode String
+HtmlHiLink mkdBlockquote Comment
+HtmlHiLink mkdLineContinue Comment
+HtmlHiLink mkdListItem Identifier
+HtmlHiLink mkdRule Identifier
+
+
+let b:current_syntax = "mkd"
+
+delcommand HtmlHiLink
+" vim: ts=8
diff --git a/modules/vim/vim/syntax/nginx.vim b/modules/vim/vim/syntax/nginx.vim
new file mode 100644
index 0000000..ccd4768
--- /dev/null
+++ b/modules/vim/vim/syntax/nginx.vim
@@ -0,0 +1,664 @@
+" Vim syntax file
+" Language: nginx.conf
+
+if exists("b:current_syntax")
+ finish
+end
+
+setlocal iskeyword+=.
+setlocal iskeyword+=/
+setlocal iskeyword+=:
+
+syn match ngxVariable '\$\w\w*'
+syn match ngxVariableBlock '\$\w\w*' contained
+syn match ngxVariableString '\$\w\w*' contained
+syn region ngxBlock start=+^+ end=+{+ contains=ngxComment,ngxDirectiveBlock,ngxVariableBlock,ngxString oneline
+syn region ngxString start=+"+ end=+"+ skip=+\\\\\|\\"+ contains=ngxVariableString oneline
+syn region ngxString start=+'+ end=+'+ skip=+\\\\\|\\'+ contains=ngxVariableString oneline
+syn match ngxComment ' *#.*$'
+
+syn keyword ngxBoolean on
+syn keyword ngxBoolean off
+
+syn keyword ngxDirectiveBlock http contained
+syn keyword ngxDirectiveBlock mail contained
+syn keyword ngxDirectiveBlock events contained
+syn keyword ngxDirectiveBlock server contained
+syn keyword ngxDirectiveBlock types contained
+syn keyword ngxDirectiveBlock location contained
+syn keyword ngxDirectiveBlock upstream contained
+syn keyword ngxDirectiveBlock charset_map contained
+syn keyword ngxDirectiveBlock limit_except contained
+syn keyword ngxDirectiveBlock if contained
+syn keyword ngxDirectiveBlock geo contained
+syn keyword ngxDirectiveBlock map contained
+
+syn keyword ngxDirectiveImportant include
+syn keyword ngxDirectiveImportant root
+syn keyword ngxDirectiveImportant server
+syn keyword ngxDirectiveImportant server_name
+syn keyword ngxDirectiveImportant listen
+syn keyword ngxDirectiveImportant internal
+syn keyword ngxDirectiveImportant proxy_pass
+syn keyword ngxDirectiveImportant memcached_pass
+syn keyword ngxDirectiveImportant fastcgi_pass
+syn keyword ngxDirectiveImportant try_files
+
+syn keyword ngxDirectiveControl break
+syn keyword ngxDirectiveControl return
+syn keyword ngxDirectiveControl rewrite
+syn keyword ngxDirectiveControl set
+
+syn keyword ngxDirectiveError error_page
+syn keyword ngxDirectiveError post_action
+
+syn keyword ngxDirectiveDeprecated connections
+syn keyword ngxDirectiveDeprecated imap
+syn keyword ngxDirectiveDeprecated open_file_cache_retest
+syn keyword ngxDirectiveDeprecated optimize_server_names
+syn keyword ngxDirectiveDeprecated satisfy_any
+
+syn keyword ngxDirective accept_mutex
+syn keyword ngxDirective accept_mutex_delay
+syn keyword ngxDirective access_log
+syn keyword ngxDirective add_after_body
+syn keyword ngxDirective add_before_body
+syn keyword ngxDirective add_header
+syn keyword ngxDirective addition_types
+syn keyword ngxDirective aio
+syn keyword ngxDirective alias
+syn keyword ngxDirective allow
+syn keyword ngxDirective ancient_browser
+syn keyword ngxDirective ancient_browser_value
+syn keyword ngxDirective auth_basic
+syn keyword ngxDirective auth_basic_user_file
+syn keyword ngxDirective auth_http
+syn keyword ngxDirective auth_http_header
+syn keyword ngxDirective auth_http_timeout
+syn keyword ngxDirective autoindex
+syn keyword ngxDirective autoindex_exact_size
+syn keyword ngxDirective autoindex_localtime
+syn keyword ngxDirective charset
+syn keyword ngxDirective charset_types
+syn keyword ngxDirective client_body_buffer_size
+syn keyword ngxDirective client_body_in_file_only
+syn keyword ngxDirective client_body_in_single_buffer
+syn keyword ngxDirective client_body_temp_path
+syn keyword ngxDirective client_body_timeout
+syn keyword ngxDirective client_header_buffer_size
+syn keyword ngxDirective client_header_timeout
+syn keyword ngxDirective client_max_body_size
+syn keyword ngxDirective connection_pool_size
+syn keyword ngxDirective create_full_put_path
+syn keyword ngxDirective daemon
+syn keyword ngxDirective dav_access
+syn keyword ngxDirective dav_methods
+syn keyword ngxDirective debug_connection
+syn keyword ngxDirective debug_points
+syn keyword ngxDirective default_type
+syn keyword ngxDirective degradation
+syn keyword ngxDirective degrade
+syn keyword ngxDirective deny
+syn keyword ngxDirective devpoll_changes
+syn keyword ngxDirective devpoll_events
+syn keyword ngxDirective directio
+syn keyword ngxDirective directio_alignment
+syn keyword ngxDirective empty_gif
+syn keyword ngxDirective env
+syn keyword ngxDirective epoll_events
+syn keyword ngxDirective error_log
+syn keyword ngxDirective eventport_events
+syn keyword ngxDirective expires
+syn keyword ngxDirective fastcgi_bind
+syn keyword ngxDirective fastcgi_buffer_size
+syn keyword ngxDirective fastcgi_buffers
+syn keyword ngxDirective fastcgi_busy_buffers_size
+syn keyword ngxDirective fastcgi_cache
+syn keyword ngxDirective fastcgi_cache_key
+syn keyword ngxDirective fastcgi_cache_methods
+syn keyword ngxDirective fastcgi_cache_min_uses
+syn keyword ngxDirective fastcgi_cache_path
+syn keyword ngxDirective fastcgi_cache_use_stale
+syn keyword ngxDirective fastcgi_cache_valid
+syn keyword ngxDirective fastcgi_catch_stderr
+syn keyword ngxDirective fastcgi_connect_timeout
+syn keyword ngxDirective fastcgi_hide_header
+syn keyword ngxDirective fastcgi_ignore_client_abort
+syn keyword ngxDirective fastcgi_ignore_headers
+syn keyword ngxDirective fastcgi_index
+syn keyword ngxDirective fastcgi_intercept_errors
+syn keyword ngxDirective fastcgi_max_temp_file_size
+syn keyword ngxDirective fastcgi_next_upstream
+syn keyword ngxDirective fastcgi_param
+syn keyword ngxDirective fastcgi_pass_header
+syn keyword ngxDirective fastcgi_pass_request_body
+syn keyword ngxDirective fastcgi_pass_request_headers
+syn keyword ngxDirective fastcgi_read_timeout
+syn keyword ngxDirective fastcgi_send_lowat
+syn keyword ngxDirective fastcgi_send_timeout
+syn keyword ngxDirective fastcgi_split_path_info
+syn keyword ngxDirective fastcgi_store
+syn keyword ngxDirective fastcgi_store_access
+syn keyword ngxDirective fastcgi_temp_file_write_size
+syn keyword ngxDirective fastcgi_temp_path
+syn keyword ngxDirective fastcgi_upstream_fail_timeout
+syn keyword ngxDirective fastcgi_upstream_max_fails
+syn keyword ngxDirective flv
+syn keyword ngxDirective geoip_city
+syn keyword ngxDirective geoip_country
+syn keyword ngxDirective google_perftools_profiles
+syn keyword ngxDirective gzip
+syn keyword ngxDirective gzip_buffers
+syn keyword ngxDirective gzip_comp_level
+syn keyword ngxDirective gzip_disable
+syn keyword ngxDirective gzip_hash
+syn keyword ngxDirective gzip_http_version
+syn keyword ngxDirective gzip_min_length
+syn keyword ngxDirective gzip_no_buffer
+syn keyword ngxDirective gzip_proxied
+syn keyword ngxDirective gzip_static
+syn keyword ngxDirective gzip_types
+syn keyword ngxDirective gzip_vary
+syn keyword ngxDirective gzip_window
+syn keyword ngxDirective if_modified_since
+syn keyword ngxDirective ignore_invalid_headers
+syn keyword ngxDirective image_filter
+syn keyword ngxDirective image_filter_buffer
+syn keyword ngxDirective image_filter_jpeg_quality
+syn keyword ngxDirective image_filter_transparency
+syn keyword ngxDirective imap_auth
+syn keyword ngxDirective imap_capabilities
+syn keyword ngxDirective imap_client_buffer
+syn keyword ngxDirective index
+syn keyword ngxDirective ip_hash
+syn keyword ngxDirective keepalive_requests
+syn keyword ngxDirective keepalive_timeout
+syn keyword ngxDirective kqueue_changes
+syn keyword ngxDirective kqueue_events
+syn keyword ngxDirective large_client_header_buffers
+syn keyword ngxDirective limit_conn
+syn keyword ngxDirective limit_conn_log_level
+syn keyword ngxDirective limit_rate
+syn keyword ngxDirective limit_rate_after
+syn keyword ngxDirective limit_req
+syn keyword ngxDirective limit_req_log_level
+syn keyword ngxDirective limit_req_zone
+syn keyword ngxDirective limit_zone
+syn keyword ngxDirective lingering_time
+syn keyword ngxDirective lingering_timeout
+syn keyword ngxDirective lock_file
+syn keyword ngxDirective log_format
+syn keyword ngxDirective log_not_found
+syn keyword ngxDirective log_subrequest
+syn keyword ngxDirective map_hash_bucket_size
+syn keyword ngxDirective map_hash_max_size
+syn keyword ngxDirective master_process
+syn keyword ngxDirective memcached_bind
+syn keyword ngxDirective memcached_buffer_size
+syn keyword ngxDirective memcached_connect_timeout
+syn keyword ngxDirective memcached_next_upstream
+syn keyword ngxDirective memcached_read_timeout
+syn keyword ngxDirective memcached_send_timeout
+syn keyword ngxDirective memcached_upstream_fail_timeout
+syn keyword ngxDirective memcached_upstream_max_fails
+syn keyword ngxDirective merge_slashes
+syn keyword ngxDirective min_delete_depth
+syn keyword ngxDirective modern_browser
+syn keyword ngxDirective modern_browser_value
+syn keyword ngxDirective msie_padding
+syn keyword ngxDirective msie_refresh
+syn keyword ngxDirective multi_accept
+syn keyword ngxDirective open_file_cache
+syn keyword ngxDirective open_file_cache_errors
+syn keyword ngxDirective open_file_cache_events
+syn keyword ngxDirective open_file_cache_min_uses
+syn keyword ngxDirective open_file_cache_valid
+syn keyword ngxDirective open_log_file_cache
+syn keyword ngxDirective output_buffers
+syn keyword ngxDirective override_charset
+syn keyword ngxDirective perl
+syn keyword ngxDirective perl_modules
+syn keyword ngxDirective perl_require
+syn keyword ngxDirective perl_set
+syn keyword ngxDirective pid
+syn keyword ngxDirective pop3_auth
+syn keyword ngxDirective pop3_capabilities
+syn keyword ngxDirective port_in_redirect
+syn keyword ngxDirective postpone_gzipping
+syn keyword ngxDirective postpone_output
+syn keyword ngxDirective protocol
+syn keyword ngxDirective proxy
+syn keyword ngxDirective proxy_bind
+syn keyword ngxDirective proxy_buffer
+syn keyword ngxDirective proxy_buffer_size
+syn keyword ngxDirective proxy_buffering
+syn keyword ngxDirective proxy_buffers
+syn keyword ngxDirective proxy_busy_buffers_size
+syn keyword ngxDirective proxy_cache
+syn keyword ngxDirective proxy_cache_key
+syn keyword ngxDirective proxy_cache_methods
+syn keyword ngxDirective proxy_cache_min_uses
+syn keyword ngxDirective proxy_cache_path
+syn keyword ngxDirective proxy_cache_use_stale
+syn keyword ngxDirective proxy_cache_valid
+syn keyword ngxDirective proxy_connect_timeout
+syn keyword ngxDirective proxy_headers_hash_bucket_size
+syn keyword ngxDirective proxy_headers_hash_max_size
+syn keyword ngxDirective proxy_hide_header
+syn keyword ngxDirective proxy_ignore_client_abort
+syn keyword ngxDirective proxy_ignore_headers
+syn keyword ngxDirective proxy_intercept_errors
+syn keyword ngxDirective proxy_max_temp_file_size
+syn keyword ngxDirective proxy_method
+syn keyword ngxDirective proxy_next_upstream
+syn keyword ngxDirective proxy_pass_error_message
+syn keyword ngxDirective proxy_pass_header
+syn keyword ngxDirective proxy_pass_request_body
+syn keyword ngxDirective proxy_pass_request_headers
+syn keyword ngxDirective proxy_read_timeout
+syn keyword ngxDirective proxy_redirect
+syn keyword ngxDirective proxy_send_lowat
+syn keyword ngxDirective proxy_send_timeout
+syn keyword ngxDirective proxy_set_body
+syn keyword ngxDirective proxy_set_header
+syn keyword ngxDirective proxy_ssl_session_reuse
+syn keyword ngxDirective proxy_store
+syn keyword ngxDirective proxy_store_access
+syn keyword ngxDirective proxy_temp_file_write_size
+syn keyword ngxDirective proxy_temp_path
+syn keyword ngxDirective proxy_timeout
+syn keyword ngxDirective proxy_upstream_fail_timeout
+syn keyword ngxDirective proxy_upstream_max_fails
+syn keyword ngxDirective random_index
+syn keyword ngxDirective read_ahead
+syn keyword ngxDirective real_ip_header
+syn keyword ngxDirective recursive_error_pages
+syn keyword ngxDirective request_pool_size
+syn keyword ngxDirective reset_timedout_connection
+syn keyword ngxDirective resolver
+syn keyword ngxDirective resolver_timeout
+syn keyword ngxDirective rewrite_log
+syn keyword ngxDirective rtsig_overflow_events
+syn keyword ngxDirective rtsig_overflow_test
+syn keyword ngxDirective rtsig_overflow_threshold
+syn keyword ngxDirective rtsig_signo
+syn keyword ngxDirective satisfy
+syn keyword ngxDirective secure_link_secret
+syn keyword ngxDirective send_lowat
+syn keyword ngxDirective send_timeout
+syn keyword ngxDirective sendfile
+syn keyword ngxDirective sendfile_max_chunk
+syn keyword ngxDirective server_name_in_redirect
+syn keyword ngxDirective server_names_hash_bucket_size
+syn keyword ngxDirective server_names_hash_max_size
+syn keyword ngxDirective server_tokens
+syn keyword ngxDirective set_real_ip_from
+syn keyword ngxDirective smtp_auth
+syn keyword ngxDirective smtp_capabilities
+syn keyword ngxDirective smtp_client_buffer
+syn keyword ngxDirective smtp_greeting_delay
+syn keyword ngxDirective so_keepalive
+syn keyword ngxDirective source_charset
+syn keyword ngxDirective ssi
+syn keyword ngxDirective ssi_ignore_recycled_buffers
+syn keyword ngxDirective ssi_min_file_chunk
+syn keyword ngxDirective ssi_silent_errors
+syn keyword ngxDirective ssi_types
+syn keyword ngxDirective ssi_value_length
+syn keyword ngxDirective ssl
+syn keyword ngxDirective ssl_certificate
+syn keyword ngxDirective ssl_certificate_key
+syn keyword ngxDirective ssl_ciphers
+syn keyword ngxDirective ssl_client_certificate
+syn keyword ngxDirective ssl_crl
+syn keyword ngxDirective ssl_dhparam
+syn keyword ngxDirective ssl_engine
+syn keyword ngxDirective ssl_prefer_server_ciphers
+syn keyword ngxDirective ssl_protocols
+syn keyword ngxDirective ssl_session_cache
+syn keyword ngxDirective ssl_session_timeout
+syn keyword ngxDirective ssl_verify_client
+syn keyword ngxDirective ssl_verify_depth
+syn keyword ngxDirective starttls
+syn keyword ngxDirective stub_status
+syn keyword ngxDirective sub_filter
+syn keyword ngxDirective sub_filter_once
+syn keyword ngxDirective sub_filter_types
+syn keyword ngxDirective tcp_nodelay
+syn keyword ngxDirective tcp_nopush
+syn keyword ngxDirective thread_stack_size
+syn keyword ngxDirective timeout
+syn keyword ngxDirective timer_resolution
+syn keyword ngxDirective types_hash_bucket_size
+syn keyword ngxDirective types_hash_max_size
+syn keyword ngxDirective underscores_in_headers
+syn keyword ngxDirective uninitialized_variable_warn
+syn keyword ngxDirective use
+syn keyword ngxDirective user
+syn keyword ngxDirective userid
+syn keyword ngxDirective userid_domain
+syn keyword ngxDirective userid_expires
+syn keyword ngxDirective userid_mark
+syn keyword ngxDirective userid_name
+syn keyword ngxDirective userid_p3p
+syn keyword ngxDirective userid_path
+syn keyword ngxDirective userid_service
+syn keyword ngxDirective valid_referers
+syn keyword ngxDirective variables_hash_bucket_size
+syn keyword ngxDirective variables_hash_max_size
+syn keyword ngxDirective worker_connections
+syn keyword ngxDirective worker_cpu_affinity
+syn keyword ngxDirective worker_priority
+syn keyword ngxDirective worker_processes
+syn keyword ngxDirective worker_rlimit_core
+syn keyword ngxDirective worker_rlimit_nofile
+syn keyword ngxDirective worker_rlimit_sigpending
+syn keyword ngxDirective worker_threads
+syn keyword ngxDirective working_directory
+syn keyword ngxDirective xclient
+syn keyword ngxDirective xml_entities
+syn keyword ngxDirective xslt_stylesheet
+syn keyword ngxDirective xslt_types
+
+" 3rd party module list:
+" http://wiki.nginx.org/Nginx3rdPartyModules
+
+" Accept Language Module <http://wiki.nginx.org/NginxAcceptLanguageModule>
+" Parses the Accept-Language header and gives the most suitable locale from a list of supported locales.
+syn keyword ngxDirectiveThirdParty set_from_accept_language
+
+" Access Key Module <http://wiki.nginx.org/NginxHttpAccessKeyModule>
+" Denies access unless the request URL contains an access key.
+syn keyword ngxDirectiveThirdParty accesskey
+syn keyword ngxDirectiveThirdParty accesskey_arg
+syn keyword ngxDirectiveThirdParty accesskey_hashmethod
+syn keyword ngxDirectiveThirdParty accesskey_signature
+
+" Auth PAM Module <http://web.iti.upv.es/~sto/nginx/>
+" HTTP Basic Authentication using PAM.
+syn keyword ngxDirectiveThirdParty auth_pam
+syn keyword ngxDirectiveThirdParty auth_pam_service_name
+
+" Cache Purge Module <http://labs.frickle.com/nginx_ngx_cache_purge/>
+" Module adding ability to purge content from FastCGI and proxy caches.
+syn keyword ngxDirectiveThirdParty fastcgi_cache_purge
+syn keyword ngxDirectiveThirdParty proxy_cache_purge
+
+" Chunkin Module <http://wiki.nginx.org/NginxHttpChunkinModule>
+" HTTP 1.1 chunked-encoding request body support for Nginx.
+syn keyword ngxDirectiveThirdParty chunkin
+syn keyword ngxDirectiveThirdParty chunkin_keepalive
+syn keyword ngxDirectiveThirdParty chunkin_max_chunks_per_buf
+syn keyword ngxDirectiveThirdParty chunkin_resume
+
+" Circle GIF Module <http://wiki.nginx.org/NginxHttpCircleGifModule>
+" Generates simple circle images with the colors and size specified in the URL.
+syn keyword ngxDirectiveThirdParty circle_gif
+syn keyword ngxDirectiveThirdParty circle_gif_max_radius
+syn keyword ngxDirectiveThirdParty circle_gif_min_radius
+syn keyword ngxDirectiveThirdParty circle_gif_step_radius
+
+" Drizzle Module <http://github.com/chaoslawful/drizzle-nginx-module>
+" Make nginx talk directly to mysql, drizzle, and sqlite3 by libdrizzle.
+syn keyword ngxDirectiveThirdParty drizzle_connect_timeout
+syn keyword ngxDirectiveThirdParty drizzle_dbname
+syn keyword ngxDirectiveThirdParty drizzle_keepalive
+syn keyword ngxDirectiveThirdParty drizzle_module_header
+syn keyword ngxDirectiveThirdParty drizzle_pass
+syn keyword ngxDirectiveThirdParty drizzle_query
+syn keyword ngxDirectiveThirdParty drizzle_recv_cols_timeout
+syn keyword ngxDirectiveThirdParty drizzle_recv_rows_timeout
+syn keyword ngxDirectiveThirdParty drizzle_send_query_timeout
+syn keyword ngxDirectiveThirdParty drizzle_server
+
+" Echo Module <http://wiki.nginx.org/NginxHttpEchoModule>
+" Brings 'echo', 'sleep', 'time', 'exec' and more shell-style goodies to Nginx config file.
+syn keyword ngxDirectiveThirdParty echo
+syn keyword ngxDirectiveThirdParty echo_after_body
+syn keyword ngxDirectiveThirdParty echo_before_body
+syn keyword ngxDirectiveThirdParty echo_blocking_sleep
+syn keyword ngxDirectiveThirdParty echo_duplicate
+syn keyword ngxDirectiveThirdParty echo_end
+syn keyword ngxDirectiveThirdParty echo_exec
+syn keyword ngxDirectiveThirdParty echo_flush
+syn keyword ngxDirectiveThirdParty echo_foreach_split
+syn keyword ngxDirectiveThirdParty echo_location
+syn keyword ngxDirectiveThirdParty echo_location_async
+syn keyword ngxDirectiveThirdParty echo_read_request_body
+syn keyword ngxDirectiveThirdParty echo_request_body
+syn keyword ngxDirectiveThirdParty echo_reset_timer
+syn keyword ngxDirectiveThirdParty echo_sleep
+syn keyword ngxDirectiveThirdParty echo_subrequest
+syn keyword ngxDirectiveThirdParty echo_subrequest_async
+
+" Events Module <http://docs.dutov.org/nginx_modules_events_en.html>
+" Privides options for start/stop events.
+syn keyword ngxDirectiveThirdParty on_start
+syn keyword ngxDirectiveThirdParty on_stop
+
+" EY Balancer Module <http://github.com/ry/nginx-ey-balancer>
+" Adds a request queue to Nginx that allows the limiting of concurrent requests passed to the upstream.
+syn keyword ngxDirectiveThirdParty max_connections
+syn keyword ngxDirectiveThirdParty max_connections_max_queue_length
+syn keyword ngxDirectiveThirdParty max_connections_queue_timeout
+
+" Fancy Indexes Module <https://connectical.com/projects/ngx-fancyindex/wiki>
+" Like the built-in autoindex module, but fancier.
+syn keyword ngxDirectiveThirdParty fancyindex
+syn keyword ngxDirectiveThirdParty fancyindex_exact_size
+syn keyword ngxDirectiveThirdParty fancyindex_footer
+syn keyword ngxDirectiveThirdParty fancyindex_header
+syn keyword ngxDirectiveThirdParty fancyindex_localtime
+syn keyword ngxDirectiveThirdParty fancyindex_readme
+syn keyword ngxDirectiveThirdParty fancyindex_readme_mode
+
+" GeoIP Module (DEPRECATED) <http://wiki.nginx.org/NginxHttp3rdPartyGeoIPModule>
+" Country code lookups via the MaxMind GeoIP API.
+syn keyword ngxDirectiveThirdParty geoip_country_file
+
+" Headers More Module <http://wiki.nginx.org/NginxHttpHeadersMoreModule>
+" Set and clear input and output headers...more than "add"!
+syn keyword ngxDirectiveThirdParty more_clear_headers
+syn keyword ngxDirectiveThirdParty more_clear_input_headers
+syn keyword ngxDirectiveThirdParty more_set_headers
+syn keyword ngxDirectiveThirdParty more_set_input_headers
+
+" HTTP Push Module <http://pushmodule.slact.net/>
+" Turn Nginx into an adept long-polling HTTP Push (Comet) server.
+syn keyword ngxDirectiveThirdParty push_buffer_size
+syn keyword ngxDirectiveThirdParty push_listener
+syn keyword ngxDirectiveThirdParty push_message_timeout
+syn keyword ngxDirectiveThirdParty push_queue_messages
+syn keyword ngxDirectiveThirdParty push_sender
+
+" HTTP Redis Module <http://people.FreeBSD.ORG/~osa/ngx_http_redis-0.3.1.tar.gz>>
+" Redis <http://code.google.com/p/redis/> support.>
+syn keyword ngxDirectiveThirdParty redis_bind
+syn keyword ngxDirectiveThirdParty redis_buffer_size
+syn keyword ngxDirectiveThirdParty redis_connect_timeout
+syn keyword ngxDirectiveThirdParty redis_next_upstream
+syn keyword ngxDirectiveThirdParty redis_pass
+syn keyword ngxDirectiveThirdParty redis_read_timeout
+syn keyword ngxDirectiveThirdParty redis_send_timeout
+
+" HTTP JavaScript Module <http://wiki.github.com/kung-fu-tzu/ngx_http_js_module>
+" Embedding SpiderMonkey. Nearly full port on Perl module.
+syn keyword ngxDirectiveThirdParty js
+syn keyword ngxDirectiveThirdParty js_filter
+syn keyword ngxDirectiveThirdParty js_filter_types
+syn keyword ngxDirectiveThirdParty js_load
+syn keyword ngxDirectiveThirdParty js_maxmem
+syn keyword ngxDirectiveThirdParty js_require
+syn keyword ngxDirectiveThirdParty js_set
+syn keyword ngxDirectiveThirdParty js_utf8
+
+" Log Request Speed <http://wiki.nginx.org/NginxHttpLogRequestSpeed>
+" Log the time it took to process each request.
+syn keyword ngxDirectiveThirdParty log_request_speed_filter
+syn keyword ngxDirectiveThirdParty log_request_speed_filter_timeout
+
+" Memc Module <http://wiki.nginx.org/NginxHttpMemcModule>
+" An extended version of the standard memcached module that supports set, add, delete, and many more memcached commands.
+syn keyword ngxDirectiveThirdParty memc_buffer_size
+syn keyword ngxDirectiveThirdParty memc_cmds_allowed
+syn keyword ngxDirectiveThirdParty memc_connect_timeout
+syn keyword ngxDirectiveThirdParty memc_flags_to_last_modified
+syn keyword ngxDirectiveThirdParty memc_next_upstream
+syn keyword ngxDirectiveThirdParty memc_pass
+syn keyword ngxDirectiveThirdParty memc_read_timeout
+syn keyword ngxDirectiveThirdParty memc_send_timeout
+syn keyword ngxDirectiveThirdParty memc_upstream_fail_timeout
+syn keyword ngxDirectiveThirdParty memc_upstream_max_fails
+
+" Mogilefs Module <http://www.grid.net.ru/nginx/mogilefs.en.html>
+" Implements a MogileFS client, provides a replace to the Perlbal reverse proxy of the original MogileFS.
+syn keyword ngxDirectiveThirdParty mogilefs_connect_timeout
+syn keyword ngxDirectiveThirdParty mogilefs_domain
+syn keyword ngxDirectiveThirdParty mogilefs_methods
+syn keyword ngxDirectiveThirdParty mogilefs_noverify
+syn keyword ngxDirectiveThirdParty mogilefs_pass
+syn keyword ngxDirectiveThirdParty mogilefs_read_timeout
+syn keyword ngxDirectiveThirdParty mogilefs_send_timeout
+syn keyword ngxDirectiveThirdParty mogilefs_tracker
+
+" MP4 Streaming Lite Module <http://wiki.nginx.org/NginxMP4StreamingLite>
+" Will seek to a certain time within H.264/MP4 files when provided with a 'start' parameter in the URL.
+syn keyword ngxDirectiveThirdParty mp4
+
+" Nginx Notice Module <http://xph.us/software/nginx-notice/>
+" Serve static file to POST requests.
+syn keyword ngxDirectiveThirdParty notice
+syn keyword ngxDirectiveThirdParty notice_type
+
+" Phusion Passenger <http://www.modrails.com/documentation.html>
+" Easy and robust deployment of Ruby on Rails application on Apache and Nginx webservers.
+syn keyword ngxDirectiveThirdParty passenger_base_uri
+syn keyword ngxDirectiveThirdParty passenger_default_user
+syn keyword ngxDirectiveThirdParty passenger_enabled
+syn keyword ngxDirectiveThirdParty passenger_log_level
+syn keyword ngxDirectiveThirdParty passenger_max_instances_per_app
+syn keyword ngxDirectiveThirdParty passenger_max_pool_size
+syn keyword ngxDirectiveThirdParty passenger_pool_idle_time
+syn keyword ngxDirectiveThirdParty passenger_root
+syn keyword ngxDirectiveThirdParty passenger_ruby
+syn keyword ngxDirectiveThirdParty passenger_use_global_queue
+syn keyword ngxDirectiveThirdParty passenger_user_switching
+syn keyword ngxDirectiveThirdParty rack_env
+syn keyword ngxDirectiveThirdParty rails_app_spawner_idle_time
+syn keyword ngxDirectiveThirdParty rails_env
+syn keyword ngxDirectiveThirdParty rails_framework_spawner_idle_time
+syn keyword ngxDirectiveThirdParty rails_spawn_method
+
+" RDS JSON Module <http://github.com/agentzh/rds-json-nginx-module>
+" Help ngx_drizzle and other DBD modules emit JSON data.
+syn keyword ngxDirectiveThirdParty rds_json
+syn keyword ngxDirectiveThirdParty rds_json_content_type
+syn keyword ngxDirectiveThirdParty rds_json_format
+syn keyword ngxDirectiveThirdParty rds_json_ret
+
+" RRD Graph Module <http://wiki.nginx.org/NginxNgx_rrd_graph>
+" This module provides an HTTP interface to RRDtool's graphing facilities.
+syn keyword ngxDirectiveThirdParty rrd_graph
+syn keyword ngxDirectiveThirdParty rrd_graph_root
+
+" Secure Download <http://wiki.nginx.org/NginxHttpSecureDownload>
+" Create expiring links.
+syn keyword ngxDirectiveThirdParty secure_download
+syn keyword ngxDirectiveThirdParty secure_download_fail_location
+syn keyword ngxDirectiveThirdParty secure_download_path_mode
+syn keyword ngxDirectiveThirdParty secure_download_secret
+
+" SlowFS Cache Module <http://labs.frickle.com/nginx_ngx_slowfs_cache/>
+" Module adding ability to cache static files.
+syn keyword ngxDirectiveThirdParty slowfs_big_file_size
+syn keyword ngxDirectiveThirdParty slowfs_cache
+syn keyword ngxDirectiveThirdParty slowfs_cache_key
+syn keyword ngxDirectiveThirdParty slowfs_cache_min_uses
+syn keyword ngxDirectiveThirdParty slowfs_cache_path
+syn keyword ngxDirectiveThirdParty slowfs_cache_purge
+syn keyword ngxDirectiveThirdParty slowfs_cache_valid
+syn keyword ngxDirectiveThirdParty slowfs_temp_path
+
+" Strip Module <http://wiki.nginx.org/NginxHttpStripModule>
+" Whitespace remover.
+syn keyword ngxDirectiveThirdParty strip
+
+" Substitutions Module <http://wiki.nginx.org/NginxHttpSubsModule>
+" A filter module which can do both regular expression and fixed string substitutions on response bodies.
+syn keyword ngxDirectiveThirdParty subs_filter
+syn keyword ngxDirectiveThirdParty subs_filter_types
+
+" Supervisord Module <http://labs.frickle.com/nginx_ngx_supervisord/>
+" Module providing nginx with API to communicate with supervisord and manage (start/stop) backends on-demand.
+syn keyword ngxDirectiveThirdParty supervisord
+syn keyword ngxDirectiveThirdParty supervisord_inherit_backend_status
+syn keyword ngxDirectiveThirdParty supervisord_name
+syn keyword ngxDirectiveThirdParty supervisord_start
+syn keyword ngxDirectiveThirdParty supervisord_stop
+
+" Upload Module <http://www.grid.net.ru/nginx/upload.en.html>
+" Parses multipart/form-data allowing arbitrary handling of uploaded files.
+syn keyword ngxDirectiveThirdParty upload_aggregate_form_field
+syn keyword ngxDirectiveThirdParty upload_buffer_size
+syn keyword ngxDirectiveThirdParty upload_cleanup
+syn keyword ngxDirectiveThirdParty upload_limit_rate
+syn keyword ngxDirectiveThirdParty upload_max_file_size
+syn keyword ngxDirectiveThirdParty upload_max_output_body_len
+syn keyword ngxDirectiveThirdParty upload_max_part_header_len
+syn keyword ngxDirectiveThirdParty upload_pass
+syn keyword ngxDirectiveThirdParty upload_pass_args
+syn keyword ngxDirectiveThirdParty upload_pass_form_field
+syn keyword ngxDirectiveThirdParty upload_set_form_field
+syn keyword ngxDirectiveThirdParty upload_store
+syn keyword ngxDirectiveThirdParty upload_store_access
+
+" Upload Progress Module <http://wiki.nginx.org/NginxHttpUploadProgressModule>
+" Tracks and reports upload progress.
+syn keyword ngxDirectiveThirdParty report_uploads
+syn keyword ngxDirectiveThirdParty track_uploads
+syn keyword ngxDirectiveThirdParty upload_progress
+syn keyword ngxDirectiveThirdParty upload_progress_content_type
+syn keyword ngxDirectiveThirdParty upload_progress_header
+syn keyword ngxDirectiveThirdParty upload_progress_json_output
+syn keyword ngxDirectiveThirdParty upload_progress_template
+
+" Upstream Fair Balancer <http://wiki.nginx.org/NginxHttpUpstreamFairModule>
+" Sends an incoming request to the least-busy backend server, rather than distributing requests round-robin.
+syn keyword ngxDirectiveThirdParty fair
+syn keyword ngxDirectiveThirdParty upstream_fair_shm_size
+
+" Upstream Consistent Hash <http://wiki.nginx.org/NginxHttpUpstreamConsistentHash>
+" Select backend based on Consistent hash ring.
+syn keyword ngxDirectiveThirdParty consistent_hash
+
+" Upstream Hash Module <http://wiki.nginx.org/NginxHttpUpstreamRequestHashModule>
+" Provides simple upstream load distribution by hashing a configurable variable.
+syn keyword ngxDirectiveThirdParty hash
+syn keyword ngxDirectiveThirdParty hash_again
+
+" XSS Module <http://github.com/agentzh/xss-nginx-module>
+" Native support for cross-site scripting (XSS) in an nginx.
+syn keyword ngxDirectiveThirdParty xss_callback_arg
+syn keyword ngxDirectiveThirdParty xss_get
+syn keyword ngxDirectiveThirdParty xss_input_types
+syn keyword ngxDirectiveThirdParty xss_output_type
+
+" highlight
+
+hi link ngxComment Comment
+hi link ngxVariable Identifier
+hi link ngxVariableBlock Identifier
+hi link ngxVariableString PreProc
+hi link ngxBlock Normal
+hi link ngxString String
+
+hi link ngxBoolean Boolean
+hi link ngxDirectiveBlock Statement
+hi link ngxDirectiveImportant Type
+hi link ngxDirectiveControl Keyword
+hi link ngxDirectiveError Constant
+hi link ngxDirectiveDeprecated Error
+hi link ngxDirective Identifier
+hi link ngxDirectiveThirdParty Special
+
+let b:current_syntax = "nginx"
diff --git a/modules/vim/vim/syntax/puppet.vim b/modules/vim/vim/syntax/puppet.vim
new file mode 100644
index 0000000..bb85415
--- /dev/null
+++ b/modules/vim/vim/syntax/puppet.vim
@@ -0,0 +1,87 @@
+" puppet syntax file
+" Filename: puppet.vim
+" Language: puppet configuration file
+" Maintainer: Luke Kanies <luke@madstop.com>
+" URL:
+" Last Change:
+" Version:
+"
+
+" Copied from the cfengine, ruby, and perl syntax files
+" For version 5.x: Clear all syntax items
+" For version 6.x: Quit when a syntax file was already loaded
+if version < 600
+ syntax clear
+elseif exists("b:current_syntax")
+ finish
+endif
+
+syn region puppetDefine start="^\s*\(class\|define\|site\|node\)" end="{" contains=puppetDefType,puppetDefName,puppetDefArguments
+syn keyword puppetDefType class define site node inherits contained
+syn keyword puppetInherits inherits contained
+syn region puppetDefArguments start="(" end=")" contains=puppetArgument
+syn match puppetArgument "\w\+" contained
+syn match puppetDefName "\w\+" contained
+
+syn match puppetInstance "\w\+\s*{" contains=puppetTypeBrace,puppetTypeName,puppetTypeDefault
+syn match puppetTypeBrace "{" contained
+syn match puppetTypeName "[a-z]\w*" contained
+syn match puppetTypeDefault "[A-Z]\w*" contained
+
+syn match puppetParam "\w\+\s*=>" contains=puppetTypeRArrow,puppetParamName
+syn match puppetParamRArrow "=>" contained
+syn match puppetParamName "\w\+" contained
+syn match puppetVariable "$\w\+"
+syn match puppetVariable "${\w\+}"
+syn match puppetParen "("
+syn match puppetParen ")"
+syn match puppetBrace "{"
+syn match puppetBrace "}"
+
+syn region puppetString start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=puppetVariable
+
+syn keyword puppetBoolean true false
+syn keyword puppetKeyword import inherits include
+syn keyword puppetControl case default
+
+" comments last overriding everything else
+syn match puppetComment "\s*#.*$" contains=puppetTodo
+syn keyword puppetTodo TODO NOTE FIXME XXX contained
+
+" Define the default highlighting.
+" For version 5.7 and earlier: only when not done already
+" For version 5.8 and later: only when an item doesn't have highlighting yet
+if version >= 508 || !exists("did_puppet_syn_inits")
+ if version < 508
+ let did_puppet_syn_inits = 1
+ command -nargs=+ HiLink hi link <args>
+ else
+ command -nargs=+ HiLink hi def link <args>
+ endif
+
+ HiLink puppetVariable Identifier
+ HiLink puppetBoolean Boolean
+ HiLink puppetType Identifier
+ HiLink puppetDefault Identifier
+ HiLink puppetKeyword Define
+ HiLink puppetTypeDefs Define
+ HiLink puppetComment Comment
+ HiLink puppetString String
+ HiLink puppetTodo Todo
+" HiLink puppetBrace Delimiter
+" HiLink puppetTypeBrace Delimiter
+" HiLink puppetParen Delimiter
+ HiLink puppetDelimiter Delimiter
+ HiLink puppetControl Statement
+ HiLink puppetDefType Define
+ HiLink puppetDefName Type
+ HiLink puppetTypeName Statement
+ HiLink puppetTypeDefault Type
+ HiLink puppetParamName Identifier
+ HiLink puppetArgument Identifier
+
+ delcommand HiLink
+endif
+
+let b:current_syntax = "puppet"
+
diff --git a/modules/vim/vim/syntax/remind.vim b/modules/vim/vim/syntax/remind.vim
new file mode 100644
index 0000000..d220f75
--- /dev/null
+++ b/modules/vim/vim/syntax/remind.vim
@@ -0,0 +1,79 @@
+" Vim syntax file
+" Language: Remind
+" Maintainer: Davide Alberani <alberanid@libero.it>
+" Last Change: 25 Jun 2007
+" Version: 0.4
+" URL: http://erlug.linux.it/~da/vim/syntax/remind.vim
+"
+" remind is a sophisticated reminder service
+" you can download remind from:
+" http://www.roaringpenguin.com/penguin/open_source_remind.php
+
+if version < 600
+ syntax clear
+elseif exists("b:current_syntax")
+ finish
+endif
+
+" shut case off
+syn case ignore
+
+syn keyword remindCommands REM OMIT SET FSET UNSET
+syn keyword remindExpiry UNTIL FROM SCANFROM SCAN WARN SCHED
+syn keyword remindTag PRIORITY TAG
+syn keyword remindTimed AT DURATION
+syn keyword remindMove ONCE SKIP BEFORE AFTER
+syn keyword remindSpecial INCLUDE INC BANNER PUSH-OMIT-CONTEXT PUSH CLEAR-OMIT-CONTEXT CLEAR POP-OMIT-CONTEXT POP COLOR
+syn keyword remindRun MSG MSF RUN CAL SATISFY SPECIAL PS PSFILE SHADE MOON
+syn keyword remindConditional IF ELSE ENDIF IFTRIG
+syn keyword remindDebug DEBUG DUMPVARS DUMP ERRMSG FLUSH PRESERVE
+syn match remindComment "#.*$"
+syn region remindString start=+'+ end=+'+ skip=+\\\\\|\\'+ oneline
+syn region remindString start=+"+ end=+"+ skip=+\\\\\|\\"+ oneline
+syn match remindVar "\$[_a-zA-Z][_a-zA-Z0-9]*"
+syn match remindSubst "%[^ ]"
+syn match remindAdvanceNumber "\(\*\|+\|-\|++\|--\)[0-9]\+"
+" XXX: divide separators used for dates from the ones used by times?
+syn match remindDateSeparators "[/:@\.-]" contained
+syn match remindTimes "[0-9]\{1,2}[:\.][0-9]\{1,2}" contains=remindDateSeparators
+" TODO: why not match only valid dates? (ok, checking for 02/29 would be
+" impossible, but at least check for valid months and times).
+syn match remindDates "'[0-9]\{4}[/-][0-9]\{1,2}[/-][0-9]\{1,2}\(@[0-9]\{1,2}[:\.][0-9]\{1,2}\)\?'" contains=remindDateSeparators
+" This will match trailing whitespaces that seem to broke rem2ps.
+" Courtesy of Michael Dunn.
+syn match remindWarning display excludenl "\S\s\+$"ms=s+1
+
+
+if version >= 508 || !exists("did_remind_syn_inits")
+ if version < 508
+ let did_remind_syn_inits = 1
+ command -nargs=+ HiLink hi link <args>
+ else
+ command -nargs=+ HiLink hi def link <args>
+ endif
+
+ HiLink remindCommands Function
+ HiLink remindExpiry Repeat
+ HiLink remindTag Label
+ HiLink remindTimed Statement
+ HiLink remindMove Statement
+ HiLink remindSpecial Include
+ HiLink remindRun Function
+ HiLink remindConditional Conditional
+ HiLink remindComment Comment
+ HiLink remindDateSeparators Comment
+ HiLink remindDates String
+ HiLink remindTimes String
+ HiLink remindString String
+ HiLink remindDebug Debug
+ HiLink remindVar Identifier
+ HiLink remindSubst Constant
+ HiLink remindAdvanceNumber Number
+ HiLink remindWarning Error
+
+ delcommand HiLink
+endif
+
+let b:current_syntax = "remind"
+
+" vim: ts=8 sw=2
diff --git a/modules/vim/vim/syntax/rest.vim b/modules/vim/vim/syntax/rest.vim
new file mode 100644
index 0000000..17a1a86
--- /dev/null
+++ b/modules/vim/vim/syntax/rest.vim
@@ -0,0 +1,169 @@
+" Vim syntax file
+" Language: reStructuredText Documentation Format
+" Maintainer: Estienne Swart
+" URL: http://www.sanbi.ac.za/~estienne/vim/syntax/rest.vim
+" Latest Revision: 2004-04-26
+"
+" A reStructuredText syntax highlighting mode for vim.
+" (derived somewhat from Nikolai Weibull's <source@p...>
+" source)
+
+"TODO:
+" 0. Make sure that no syntax highlighting bleeding occurs!
+" 1. Need to fix up clusters and contains.
+" 2. Need to validate against restructured.txt.gz and tools/test.txt.
+" 3. Fixup superfluous matching.
+" 4. I need to figure out how to keep a running tally of the indentation in order
+" to enable block definitions, i.e. a block ends when its indentation drops
+" below that of the existing one.
+" 5. Define folding patterns for sections, etc.
+" 6. Setup a completion mode for target references to hyperlinks
+
+" Remove any old syntax stuff that was loaded (5.x) or quit when a syntax file
+" was already loaded (6.x).
+if version < 600
+ syntax clear
+elseif exists("b:current_syntax")
+ finish
+endif
+
+"syn match rstJunk "\\_"
+
+"ReStructuredText Text Inline Markup:
+syn region rstEmphasis start=+\*[^*]+ end=+\*+
+syn region rstStrongEmphasis start=+\*\*[^*]+ end=+\*\*+
+syn region rstInterpretedText start=+`[^`]+ end=+`+ contains=rstURL
+syn region rstInlineLiteral start="``" end="``" contains=rstURL
+"Using a syn region here causes too much to be highlighted.
+
+syn region rstSubstitutionReference start=+|\w+ end=+\w|+ skip=+\\|+
+"I'm forcing matching of word characters before and after '|' in order to
+"prevent table matching (this causes messy highlighting)
+
+syn region rstGridTable start=/\n\n\s*+\([-=]\|+\)\+/ms=s+2 end=/+\([-=]\|+\)\+\n\s*\n/me=e-2
+
+syn match rstRuler "\(=\|-\|+\)\{3,120}"
+
+" syn match rstInlineInternalTarget "_`\_.\{-}`"
+syn region rstInlineInternalHyperlink start=+_`+ end=+`+ contains=rsturl
+" this messes up with InterpretedText
+
+syn match rstFootnoteReference "\[\%([#*]\|[0-9]\+\|#[a-zA-Z0-9_.-]\+\)\]_"
+"syn region rstCitationReference start=+\[+ end=+\]_+
+"syn match rstCitationReferenceNothing +\[.*\]+
+"TODO: fix Citation reference - patterns defined still cause "bleeding"
+"if end doesn't get matched, catch it first with another pattern - this is ugly???
+syn match rstURL "\(acap\|cid\|data\|dav\|fax\|file\|ftp\|gopher\|http\|https\|imap\|ldap\|mailto\|mid\|modem\|news\|nfs\|nntp\|pop\|prospero\|rtsp\|service\|sip\|tel\|telnet\|tip\|urn\|vemmi\|wais\):[-./[:alnum:]_~@]\+"
+"I need a better regexp for URLs here. This doesn't cater for URLs that are
+"broken across lines
+
+" hyperlinks
+syn match rstHyperlinks /`[^`]\+`_/
+"syn region rstHyperlinks start="`\w" end="`_"
+syn match rstExternalHyperlinks "\w\+_\w\@!"
+"This seems to overlap with the ReStructuredText comment?!?
+
+"ReStructuredText Sections:
+syn match rstTitle ".\{2,120}\n\(\.\|=\|-\|=\|`\|:\|'\|\"\|\~\|\^\|_\|\*\|+\|#\|<\|>\)\{3,120}"
+" [-=`:'"~^_*+#<>]
+"for some strange reason this only gets highlighted upon refresh
+
+"syn match rstTitle "\w.*\n\(=\|-\|+\)\{2,120}"
+
+"ReStructuredText Lists:
+syn match rstEnumeratedList "^\s*\d\{1,3}\.\s"
+
+syn match rstBulletedList "^\s*\([+-]\|\*\)\s"
+" syn match rstBulletedList "^\s*[+-]\|\*\s"
+"I'm not sure how to include "*" within a range []?!?
+" this seems to match more than it should :-(
+
+
+syn match rstFieldList ":[^:]\+:\s"me=e-1 contains=rstBibliographicField
+"still need to add rstDefinitionList rstOptionList
+
+"ReStructuredText Preformatting:
+syn match rstLiteralBlock "::\s*\n" contains=rstGridTable
+"syn region rstLiteralBlock start=+\(contents\)\@<!::\n+ end=+[^:]\{2}\s*\n\s*\n\s*+me=e-1 contains=rstEmphasis,rstStrongEmphasis,rstInlineLiteral,rstRuler,rstFieldList,rstInlineInternalTargets,rstGridTable transparent
+"Add more to allbut?
+"This command currently ignores the 'contents::' line that is found in some
+"restructured documents.
+"syn region rstBlockQuote start=+\s\n+ end=+[^:]\{2}\s*\n\s*\n\s*+me=e-1 contains=ALLBUT,rstEmphasis,rstStrongEmphasis,rstInlineLiteral,rstRuler
+"FIX rstBlockQuote
+
+"syn match rstDocTestBlock
+"
+"
+"RestructureText Targets:
+syn match rstFootnoteTarget "\[\%([#*]\|[0-9]\+\|#[a-zA-Z0-9_.-]\+\)\]" contained
+syn region rstCitationTarget start=+\[+ end=+\]+ contained
+"syn region rstInlineInternalTarget start=+_\_s\@!+ end=+\:+ contained
+"seems to match things in reagions it should not
+syn match rstDirective +\.\.\s\{-}[^_]\{-}\:\:+ms=s+3 contained
+
+"ReStructuredText Comments:
+syn region rstComment matchgroup=rstComment start="\.\{2} " end="^\s\@!" contains=rstFootnoteTarget,rstCitationTarget,rstInlineInternalTarget,rstDirective,rstURL
+"THIS NEEDS TO BE FIXED TO HANDLE COMMENTS WITH PARAGRAPHS
+"It can be modelled on rstBlock (which also needs to be worked)
+"It also matches too much :-( e.g. normal ellipsis
+"Define fold group for comments?
+
+"ReStructuredText Miscellaneous:
+
+syn keyword rstBibliographicField contained Author Organization Contact Address Version Status Date Copyright Dedication Abstract Authors
+"keyword revison too??? Lower case variants too?
+
+" todo
+syn keyword rstTodo contained FIXME TODO XXX
+
+syn region rstQuotes start=+\"+ end=+\"+ skip=+\\"+ contains=ALLBUT,rstEmphasis,rstStrongEmphasis,rstBibliographicField
+
+" footnotes
+"syn region rstFootnote matchgroup=rstDirective start="^\.\.\[\%([#*]\|[0-9]\+\|#[a-z0-9_.-]\+\)\]\s" end="^\s\@!" contains=@rstCruft
+
+" citations
+"syn region rstCitation matchgroup=rstDirective start="^\.\.\[[a-z0-9_.-]\+\]\s" end="^\s\@!" contains=@rstCruft
+
+syn region rstBlock start="::\(\n\s*\)\{-}\z(\s\+\)" skip="^$" end="^\z1\@!" fold contains=ALLBUT,rstInterpretedText,rstFootnoteTarget,rstCitationTarget,rstInlineInternalTarget
+"almost perfect
+"Still need to get stop on unident correct. Also need to work on recursive
+"blocking for proper folding.
+"TODO: Define syntax regions for Sections (defined by titles)
+
+syn sync minlines=50
+
+if !exists("did_rst_syn_inits")
+ let did_rst_syn_inits = 1
+
+ hi link rstBibliographicField Operator
+ hi link rstBlock Type
+ hi link rstExternalHyperlinks Underlined
+ hi link rstHyperlinks Underlined
+ hi link rstTitle Constant
+ hi link rstRuler Special
+ hi link rstURL Underlined
+ hi link rstSubstitutionReference Macro
+ hi link rstEmphasis Exception
+ hi link rstStrongEmphasis Exception
+ hi link rstLiteralBlock Type
+ hi link rstBlockQuote Type
+ hi link rstEnumeratedList Operator
+ hi link rstBulletedList Operator
+ hi link rstFieldList Label
+ hi link rstTodo Todo
+ hi link rstComment Comment
+ hi link rstGridTable Delimiter
+ hi link rstInlineLiteral Function
+ hi link rstInterpretedText Keyword
+ hi link rstInlineInternalHyperlink Identifier
+ hi link rstInlineInternalTarget Identifier
+ hi link rstFootnoteReference Identifier
+ hi link rstCitationReference Identifier
+ hi link rstFootnoteTarget Identifier
+ hi link rstCitationTarget Identifier
+ hi link rstDirective Underlined
+endif
+
+let b:current_syntax = "rst"
+
+" vim: set sts=4 sw=4:
diff --git a/modules/vim/vim/syntax/snippet.vim b/modules/vim/vim/syntax/snippet.vim
new file mode 100644
index 0000000..5e919e7
--- /dev/null
+++ b/modules/vim/vim/syntax/snippet.vim
@@ -0,0 +1,19 @@
+" Syntax highlighting for snippet files (used for snipMate.vim)
+" Hopefully this should make snippets a bit nicer to write!
+syn match snipComment '^#.*'
+syn match placeHolder '\${\d\+\(:.\{-}\)\=}' contains=snipCommand
+syn match tabStop '\$\d\+'
+syn match snipCommand '`.\{-}`'
+syn match snippet '^snippet.*' transparent contains=multiSnipText,snipKeyword
+syn match multiSnipText '\S\+ \zs.*' contained
+syn match snipKeyword '^snippet'me=s+8 contained
+syn match snipError "^[^#s\t].*$"
+
+hi link snipComment Comment
+hi link multiSnipText String
+hi link snipKeyword Keyword
+hi link snipComment Comment
+hi link placeHolder Special
+hi link tabStop Special
+hi link snipCommand String
+hi link snipError Error
diff --git a/modules/vim/vim/syntax/svkannotate.vim b/modules/vim/vim/syntax/svkannotate.vim
new file mode 100644
index 0000000..d93e9dd
--- /dev/null
+++ b/modules/vim/vim/syntax/svkannotate.vim
@@ -0,0 +1,42 @@
+" Vim syntax file
+" Language: SVK annotate output
+" Maintainer: Bob Hiestand <bob.hiestand@gmail.com>
+" Remark: Used by the vcscommand plugin.
+" License:
+" Copyright (c) Bob Hiestand
+"
+" Permission is hereby granted, free of charge, to any person obtaining a copy
+" of this software and associated documentation files (the "Software"), to
+" deal in the Software without restriction, including without limitation the
+" rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+" sell copies of the Software, and to permit persons to whom the Software is
+" furnished to do so, subject to the following conditions:
+"
+" The above copyright notice and this permission notice shall be included in
+" all copies or substantial portions of the Software.
+"
+" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+" IN THE SOFTWARE.
+
+if exists("b:current_syntax")
+ finish
+endif
+
+syn match svkDate /\d\{4}-\d\{1,2}-\d\{1,2}/ skipwhite contained
+syn match svkName /(\s*\zs\S\+/ contained nextgroup=svkDate skipwhite
+syn match svkVer /^\s*\d\+/ contained nextgroup=svkName skipwhite
+syn region svkHead start=/^/ end="):" contains=svkVer,svkName,svkDate oneline
+
+if !exists("did_svkannotate_syntax_inits")
+ let did_svkannotate_syntax_inits = 1
+ hi link svkName Type
+ hi link svkDate Comment
+ hi link svkVer Statement
+endif
+
+let b:current_syntax="svkAnnotate"
diff --git a/modules/vim/vim/syntax/svnannotate.vim b/modules/vim/vim/syntax/svnannotate.vim
new file mode 100644
index 0000000..87a63ab
--- /dev/null
+++ b/modules/vim/vim/syntax/svnannotate.vim
@@ -0,0 +1,40 @@
+" Vim syntax file
+" Language: SVN annotate output
+" Maintainer: Bob Hiestand <bob.hiestand@gmail.com>
+" Remark: Used by the vcscommand plugin.
+" License:
+" Copyright (c) Bob Hiestand
+"
+" Permission is hereby granted, free of charge, to any person obtaining a copy
+" of this software and associated documentation files (the "Software"), to
+" deal in the Software without restriction, including without limitation the
+" rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+" sell copies of the Software, and to permit persons to whom the Software is
+" furnished to do so, subject to the following conditions:
+"
+" The above copyright notice and this permission notice shall be included in
+" all copies or substantial portions of the Software.
+"
+" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+" IN THE SOFTWARE.
+
+if exists("b:current_syntax")
+ finish
+endif
+
+syn match svnName /\S\+/ contained
+syn match svnVer /^\s*\zs\d\+/ contained nextgroup=svnName skipwhite
+syn match svnHead /^\s*\d\+\s\+\S\+/ contains=svnVer,svnName
+
+if !exists("did_svnannotate_syntax_inits")
+ let did_svnannotate_syntax_inits = 1
+ hi link svnName Type
+ hi link svnVer Statement
+endif
+
+let b:current_syntax="svnAnnotate"
diff --git a/modules/vim/vim/syntax/vcscommit.vim b/modules/vim/vim/syntax/vcscommit.vim
new file mode 100644
index 0000000..80b4c6e
--- /dev/null
+++ b/modules/vim/vim/syntax/vcscommit.vim
@@ -0,0 +1,31 @@
+" Vim syntax file
+" Language: VCS commit file
+" Maintainer: Bob Hiestand (bob.hiestand@gmail.com)
+" License:
+" Copyright (c) Bob Hiestand
+"
+" Permission is hereby granted, free of charge, to any person obtaining a copy
+" of this software and associated documentation files (the "Software"), to
+" deal in the Software without restriction, including without limitation the
+" rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+" sell copies of the Software, and to permit persons to whom the Software is
+" furnished to do so, subject to the following conditions:
+"
+" The above copyright notice and this permission notice shall be included in
+" all copies or substantial portions of the Software.
+"
+" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+" IN THE SOFTWARE.
+
+if exists("b:current_syntax")
+ finish
+endif
+
+syntax region vcsComment start="^VCS: " end="$"
+highlight link vcsComment Comment
+let b:current_syntax = "vcscommit"