aboutsummaryrefslogtreecommitdiff
path: root/vim.dot.link/plugin
diff options
context:
space:
mode:
authorSilvio Rhatto <rhatto@riseup.net>2013-12-27 15:32:50 -0200
committerSilvio Rhatto <rhatto@riseup.net>2013-12-27 15:32:50 -0200
commit5032aca04f4d0bce092ade66fe914c34af357a5e (patch)
tree3ba885989ff09b1ab3eb0a16ac865e797c8ca0e7 /vim.dot.link/plugin
downloadvim-5032aca04f4d0bce092ade66fe914c34af357a5e.tar.gz
vim-5032aca04f4d0bce092ade66fe914c34af357a5e.tar.bz2
Initial import
Diffstat (limited to 'vim.dot.link/plugin')
-rw-r--r--vim.dot.link/plugin/Rename.vim27
-rw-r--r--vim.dot.link/plugin/bufexplorer.vim1157
-rw-r--r--vim.dot.link/plugin/git.vim372
-rw-r--r--vim.dot.link/plugin/indexer.vim.disabled672
-rw-r--r--vim.dot.link/plugin/project.vim1293
-rw-r--r--vim.dot.link/plugin/snipMate.vim247
-rw-r--r--vim.dot.link/plugin/startshell_mapping.vim.disabled36
-rw-r--r--vim.dot.link/plugin/taglist.vim.disable4546
-rw-r--r--vim.dot.link/plugin/vcsbzr.vim262
-rw-r--r--vim.dot.link/plugin/vcscommand.vim1427
-rw-r--r--vim.dot.link/plugin/vcscvs.vim449
-rw-r--r--vim.dot.link/plugin/vcsgit.vim247
-rw-r--r--vim.dot.link/plugin/vcshg.vim273
-rw-r--r--vim.dot.link/plugin/vcssvk.vim257
-rw-r--r--vim.dot.link/plugin/vcssvn.vim284
15 files changed, 11549 insertions, 0 deletions
diff --git a/vim.dot.link/plugin/Rename.vim b/vim.dot.link/plugin/Rename.vim
new file mode 100644
index 0000000..b56c516
--- /dev/null
+++ b/vim.dot.link/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/vim.dot.link/plugin/bufexplorer.vim b/vim.dot.link/plugin/bufexplorer.vim
new file mode 100644
index 0000000..de957d8
--- /dev/null
+++ b/vim.dot.link/plugin/bufexplorer.vim
@@ -0,0 +1,1157 @@
+"=============================================================================
+" Copyright: Copyright (C) 2001-2012 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: Sunday, 23 Dec 2012
+" 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 override the defaults and define your own mapping
+" in your vimrc file, for example:
+"
+" noremap <silent> <F11> :BufExplorer<CR>
+" noremap <silent> <m-F11> :BufExplorerHorizontalSplit<CR>
+" noremap <silent> <c-F11> :BufExplorerVerticalSplit<CR>
+"
+" Or you can use
+"
+" ":BufExplorer" - Opens BufExplorer
+" ":BufExplorerHorizontalSplit" - Opens horizontally window BufExplorer
+" ":BufExplorerVerticalSplit" - Opens vertically split window BufExplorer
+"
+" For more help see supplied documentation.
+" History: See supplied documentation.
+" Issues: 'D' and 'd' remove the buffer from the list but the list is not
+" displayed correctly.
+" - Add ability to open a buffer in a new split when \be is used.
+"=============================================================================
+
+" Plugin Code {{{1
+" Exit quickly if already running or when 'compatible' is set. {{{2
+if exists("g:bufexplorer_version") || &cp
+ finish
+endif
+"2}}}
+
+" Version number
+let g:bufexplorer_version = "7.3.2"
+
+" Check for Vim version {{{2
+if v:version < 700
+ echohl WarningMsg
+ echo "Sorry, bufexplorer ".g:bufexplorer_version." required Vim 7.0 and greater."
+ echohl None
+ finish
+endif
+
+" Create commands {{{2
+command! BufExplorer :call BufExplorer(has ("gui") ? "drop" : "hide edit")
+command! BufExplorerHorizontalSplit :call BufExplorerHorizontalSplit()
+command! BufExplorerVerticalSplit :call BufExplorerVerticalSplit()
+
+" Set {{{2
+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
+
+" Script variables {{{2
+let s:MRU_Exclude_List = ["[BufExplorer]","__MRU_Files__"]
+let s:MRUList = []
+let s:name = '[BufExplorer]'
+let s:originBuffer = 0
+let s:running = 0
+let s:sort_by = ["number", "name", "fullpath", "mru", "extension"]
+let s:splitMode = ""
+let s:tabSpace = []
+let s:types = {"fullname": ':p', "path": ':p:h', "relativename": ':~:.', "relativepath": ':~:.:h', "shortname": ':t'}
+
+" Setup the autocommands that handle the MRUList and other stuff. {{{2
+autocmd VimEnter * call s:Setup()
+
+" Setup {{{2
+function! s:Setup()
+ call s:Reset()
+
+ " Now that the MRUList is created, add the other autocmds.
+ augroup BufExplorer
+ autocmd!
+ 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()
+
+ autocmd TabEnter * call s:TabEnter()
+
+ autocmd SessionLoadPost * call s:Reset()
+ augroup END
+endfunction
+
+" Reset {{{2
+function! s:Reset()
+ " Build initial MRUList. This makes sure all the files specified on the
+ " command line are picked up correctly.
+ let s:MRUList = range(1, bufnr('$'))
+
+ " Initialize one tab space array, ignore zero-based tabpagenr
+ " since all tabpagenr's start at 1.
+ " -1 signifies this is the first time we are referencing this
+ " tabpagenr.
+ " If Vim has been loaded with mksession, then it is possible for
+ " more tabs to exist. So use tabpagenr() to determine how large
+ " to make the array. If there are 4 tabs, there should be 5
+ " elements in this array.
+ " Each element will hold a CSV list of buffers viewed in
+ " that tab. So on the 3rd tab, if there user has viewed
+ " 4 different buffers in that tab, the value would be:
+ " echo s:tabSpace[3]
+ " [4, 9, 1, 10]
+ " echo s:tabSpace
+ " [[-1], [-1], [-1], [4, 9, 1, 10], [-1]]
+ let s:tabSpace = []
+ let i = 0
+
+ while( tabpagenr('$') > 0 && i <= tabpagenr('$') )
+ call add(s:tabSpace, [-1])
+ let i = i + 1
+ endwhile
+endfunction
+
+" ActivateBuffer {{{2
+function! s:ActivateBuffer()
+ " Verify the current tabpage exists in the
+ " current s:tabSpace array. This can be missing
+ " entries when restoring sessions.
+ let i = 0
+ while( tabpagenr('$') > 0 && i <= tabpagenr() )
+ " Number: 0
+ " String: 1
+ " Funcref: 2
+ " List: 3
+ " Dictionary: 4
+ " Float: 5
+ if type(get(s:tabSpace, i)) == 0
+ call add(s:tabSpace, [-1])
+ endif
+
+ let i = i + 1
+ endwhile
+
+ let _bufnr = bufnr("%")
+ let list = get(s:tabSpace, tabpagenr(), [-1])
+
+ if !empty(list) && list[0] == '-1'
+ " The first time we add a tab, Vim uses the current buffer
+ " as it's starting page. Even though we are about to
+ " edit a new page (BufEnter is triggered after), so
+ " remove the -1 entry indicating we have covered this case.
+ let list = []
+ call add(list, _bufnr)
+ let s:tabSpace[tabpagenr()] = list
+ elseif empty(list) || index(list, _bufnr) == -1
+ " Add new buffer to this tab's buffer list.
+ call add(list, _bufnr)
+ let s:tabSpace[tabpagenr()] = list
+
+ if g:bufExplorerOnlyOneTab == 1
+ " If a buffer can only be available in 1 tab page ensure this
+ " buffer is not present in any other tabs
+ let tabidx = 1
+ while tabidx < len(s:tabSpace)
+ if tabidx != tabpagenr()
+ let bufidx = index(s:tabSpace[tabidx], _bufnr)
+ if bufidx != -1
+ call remove(s:tabSpace[tabidx], bufidx)
+ endif
+ endif
+ let tabidx = tabidx + 1
+ endwhile
+ endif
+ endif
+
+ call s:MRUPush(_bufnr)
+endfunction
+
+" DeactivateBuffer {{{2
+function! s:DeactivateBuffer(remove)
+ let _bufnr = str2nr(expand("<abuf>"))
+ call s:MRUPop(_bufnr)
+endfunction
+
+" TabEnter {{{2
+function! s:TabEnter()
+ " Make s:tabSpace 1-based
+ if empty(s:tabSpace) || len(s:tabSpace) < (tabpagenr() + 1)
+ call add(s:tabSpace, [-1])
+ endif
+endfunction
+
+" MRUPop {{{2
+function! s:MRUPop(bufnr)
+ call filter(s:MRUList, 'v:val != '.a:bufnr)
+endfunction
+
+" MRUPush {{{2
+function! s:MRUPush(buf)
+ " Skip temporary buffer with buftype set. Don't add the BufExplorer window to the
+ " list.
+ if s:ShouldIgnore(a:buf) == 1
+ return
+ endif
+
+ " 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
+
+" ShouldIgnore {{{2
+function! s:ShouldIgnore(buf)
+ " Ignore temporary buffers with buftype set.
+ if empty(getbufvar(a:buf, "&buftype") == 0)
+ return 1
+ endif
+
+ " Ignore unlisted buffers.
+ if buflisted(a:buf) == 0
+ return 1
+ endif
+
+ " Ignore buffers with no name.
+ if empty(bufname(a:buf)) == 1
+ return 1
+ endif
+
+ " Ignore the BufExplorer buffer.
+ if fnamemodify(bufname(a:buf), ":t") == s:name
+ return 1
+ endif
+
+ " Ignore any buffers in the exclude list.
+ if index(s:MRU_Exclude_List, bufname(a:buf)) >= 0
+ return 1
+ endif
+
+ " Else return 0 to indicate that the buffer was not ignored.
+ return 0
+endfunction
+
+" Initialize {{{2
+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
+
+ setlocal nobuflisted
+
+ let s:running = 1
+endfunction
+
+" Cleanup {{{2
+function! s:Cleanup()
+ if exists("s:_insertmode")
+ let &insertmode = s:_insertmode
+ endif
+
+ if exists("s:_showcmd")
+ let &showcmd = s:_showcmd
+ endif
+
+ if exists("s:_cpo")
+ let &cpo = s:_cpo
+ endif
+
+ if exists("s:_report")
+ let &report = s:_report
+ endif
+
+ if exists("s:_list")
+ let &list = s:_list
+ endif
+
+ let s:running = 0
+ let s:splitMode = ""
+
+ delmarks!
+endfunction
+
+" BufExplorerHorizontalSplit {{{2
+function! BufExplorerHorizontalSplit()
+ let s:splitMode = "sp"
+ exec "BufExplorer"
+endfunction
+
+" BufExplorerVerticalSplit {{{2
+function! BufExplorerVerticalSplit()
+ let s:splitMode = "vsp"
+ exec "BufExplorer"
+endfunction
+
+" BufExplorer {{{2
+function! BufExplorer(open)
+ let name = s:name
+
+ 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
+
+ " Add zero to ensure the variable is treated as a number.
+ let s:originBuffer = bufnr("%") + 0
+
+ silent let s:raw_buffer_listing = s:GetBufferInfo(0)
+
+ let buffer_listing_copy = copy(s:raw_buffer_listing)
+
+ if (g:bufExplorerShowUnlisted == 0)
+ call filter(buffer_listing_copy, 'v:val.attributes !~ "u"')
+ endif
+
+ if (!empty(buffer_listing_copy))
+ call filter(buffer_listing_copy, 'v:val.shortname !~ "\\\[No Name\\\]"')
+ endif
+
+" if len(buffer_listing_copy) <= 1
+" 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 'keepalt '.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()
+
+ " Position the cursor in the newly displayed list on the line representing
+ " the active buffer. The active buffer is the line with the '%' character
+ " in it.
+ execute search("%")
+endfunction
+
+" DisplayBufferList {{{2
+function! s:DisplayBufferList()
+ " Do not set bufhidden since it wipes out the data if we switch away from
+ " the buffer using CTRL-^.
+ 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 {{{2
+function! s:MapKeys()
+ if exists("b:displayMode") && b:displayMode == "winmanager"
+ nnoremap <buffer> <silent> <tab> :call <SID>SelectBuffer()<CR>
+ endif
+
+ nnoremap <script> <silent> <buffer> <2-leftmouse> :call <SID>SelectBuffer()<CR>
+ nnoremap <script> <silent> <buffer> <CR> :call <SID>SelectBuffer()<CR>
+ nnoremap <script> <silent> <buffer> <F1> :call <SID>ToggleHelp()<CR>
+ nnoremap <script> <silent> <buffer> <s-cr> :call <SID>SelectBuffer("tab")<CR>
+ nnoremap <script> <silent> <buffer> B :call <SID>ToggleOnlyOneTab()<CR>
+ nnoremap <script> <silent> <buffer> d :call <SID>RemoveBuffer("delete")<CR>
+ nnoremap <script> <silent> <buffer> D :call <SID>RemoveBuffer("wipe")<CR>
+ nnoremap <script> <silent> <buffer> f :call <SID>ToggleFindActive()<CR>
+ nnoremap <script> <silent> <buffer> m :call <SID>MRUListShow()<CR>
+ nnoremap <script> <silent> <buffer> o :call <SID>SelectBuffer()<CR>
+ nnoremap <script> <silent> <buffer> p :call <SID>ToggleSplitOutPathName()<CR>
+ nnoremap <script> <silent> <buffer> q :call <SID>Close()<CR>
+ nnoremap <script> <silent> <buffer> r :call <SID>SortReverse()<CR>
+ nnoremap <script> <silent> <buffer> R :call <SID>ToggleShowRelativePath()<CR>
+ nnoremap <script> <silent> <buffer> s :call <SID>SortSelect()<CR>
+ nnoremap <script> <silent> <buffer> S :call <SID>ReverseSortSelect()<CR>
+ nnoremap <script> <silent> <buffer> t :call <SID>SelectBuffer("tab")<CR>
+ nnoremap <script> <silent> <buffer> T :call <SID>ToggleShowTabBuffer()<CR>
+ nnoremap <script> <silent> <buffer> u :call <SID>ToggleShowUnlisted()<CR>
+
+ for k in ["G", "n", "N", "L", "M", "H"]
+ exec "nnoremap <buffer> <silent>" k ":keepjumps normal!" k."<CR>"
+ endfor
+endfunction
+
+" SetupSyntax {{{2
+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 {{{2
+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")
+ endif
+endfunction
+
+" GetHelpStatus {{{2
+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:bufExplorerShowTabBuffer == 0) ? "" : " | Show buffers/tab")
+ let ret .= ((g:bufExplorerOnlyOneTab == 1) ? "" : " | One tab/buffer")
+ let ret .= ' | '.((g:bufExplorerShowRelativePath == 0) ? "Absolute" : "Relative")
+ let ret .= ' '.((g:bufExplorerSplitOutPathName == 0) ? "Full" : "Split")." path"
+
+ return ret
+endfunction
+
+" CreateHelp {{{2
+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 o or Mouse-Double-Click : open buffer under cursor')
+ call add(header, '" <shift-enter> or t : open buffer in another tab')
+ call add(header, '" B : toggle if to save/use recent tab or not')
+ call add(header, '" d : delete buffer')
+ call add(header, '" D : wipe buffer')
+ call add(header, '" f : toggle find active 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, '" s : cycle thru "sort by" fields '.string(s:sort_by).'')
+ call add(header, '" S : reverse cycle thru "sort by" fields')
+ call add(header, '" T : toggle if to show only buffers for this tab or not')
+ call add(header, '" u : toggle showing unlisted buffers')
+ else
+ call add(header, '" Press <F1> for Help')
+ endif
+
+ if (!exists("b:displayMode") || b:displayMode != "winmanager") || (b:displayMode == "winmanager" && g:bufExplorerDetailedHelp == 1)
+ call add(header, s:GetHelpStatus())
+ call add(header, '"=')
+ endif
+
+ let s:firstBufferLine = len(header) + 1
+
+ return header
+endfunction
+
+" GetBufferInfo {{{2
+function! s:GetBufferInfo(bufnr)
+ redir => bufoutput
+ buffers!
+ redir END
+
+ if (a:bufnr > 0)
+ " Since we are only interested in this specified buffer
+ " remove the other buffers listed
+ let bufoutput = substitute(bufoutput."\n", '^.*\n\(\s*'.a:bufnr.'\>.\{-}\)\n.*', '\1', '')
+ endif
+
+ let [all, allwidths, listedwidths] = [[], {}, {}]
+
+ for n in keys(s:types)
+ let allwidths[n] = []
+ let listedwidths[n] = []
+ endfor
+
+ " Loop over each line in the buffer.
+ 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>"
+ endif
+
+ 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 {{{2
+function! s:BuildBufferList()
+ let lines = []
+
+ " Loop through every buffer.
+ for buf in s:raw_buffer_listing
+ " Skip unlisted buffers if we are not to show them.
+ if (!g:bufExplorerShowUnlisted && buf.attributes =~ "u")
+ " Skip unlisted buffers if we are not to show them.
+ continue
+ endif
+
+ " Ignore buffers with no name.
+ if empty(bufname(str2nr(buf.attributes))) == 1
+ continue
+ endif
+
+ if (g:bufExplorerShowTabBuffer)
+ let show_buffer = 0
+
+ for bufnr in s:tabSpace[tabpagenr()]
+ if (buf.attributes =~ '^\s*'.bufnr.'\>')
+ " Only buffers shown on the current tabpagenr
+ let show_buffer = 1
+ break
+ endif
+ endfor
+
+ if show_buffer == 0
+ continue
+ endif
+ 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 {{{2
+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.
+" 3/25/2012 echo ""
+
+ " Are we on a line with a file name?
+ if line('.') < s:firstBufferLine
+ exec "normal! \<CR>"
+ return
+ endif
+
+ let _bufNbr = str2nr(getline('.'))
+
+ " Check and see if we are running BufferExplorer via WinManager.
+ 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
+ endif
+
+ if bufexists(_bufNbr)
+ if bufnr("#") == _bufNbr && !exists("g:bufExplorerChgWin")
+ return s:Close()
+ endif
+
+ " Are we suppose to open the selected buffer in a tab?
+ if (a:0 == 1) && (a:1 == "tab")
+ " Yes, we are to open the selected buffer in a tab.
+
+ " Restore [BufExplorer] buffer.
+ exec "keepjumps silent buffer!".s:originBuffer
+
+ " Get the tab nmber where this bufer is located in.
+ let tabNbr = s:GetTabNbr(_bufNbr)
+
+ " Was the tab found?
+ 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 a tab, go to that tab.
+ exec tabNbr . "tabnext"
+
+ " Focus window.
+ exec s:GetWinNbr(tabNbr, _bufNbr) . "wincmd w"
+ endif
+ else
+ " No, the user did not ask to open the selected buffer in a tab.
+
+ " Are we suppose to move to the tab where the active buffer is?
+ if exists("g:bufExplorerChgWin")
+ exe g:bufExplorerChgWin."wincmd w"
+ elseif bufloaded(_bufNbr) && g:bufExplorerFindActive
+ call s:Close()
+
+ " Get the tab number where this buffer is located in.
+ let tabNbr = s:GetTabNbr(_bufNbr)
+
+ " Was the tab found?
+ if tabNbr != 0
+ " Yes, the buffer is located in a tab. Go to that tab number.
+ exec tabNbr . "tabnext"
+ else
+ "Nope, the buffer is not in a tab. Simply switch to that
+ "buffer.
+ 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")
+
+ " Call any associated function references. g:bufExplorerFuncRef may be
+ " an individual function reference or it may be a list containing
+ " function references. It will ignore anything that's not a function
+ " reference.
+ "
+ " See :help FuncRef for more on function references.
+ if exists("g:BufExplorerFuncRef")
+ if type(g:BufExplorerFuncRef) == 2
+ keepj call g:BufExplorerFuncRef()
+ elseif type(g:BufExplorerFuncRef) == 3
+ for FncRef in g:BufExplorerFuncRef
+ if type(FncRef) == 2
+ keepj call FncRef()
+ endif
+ endfor
+ endif
+ endif
+ else
+ call s:Error("Sorry, that buffer no longer exists, please select another")
+ call s:DeleteBuffer(_bufNbr, "wipe")
+ endif
+endfunction
+
+" RemoveBuffer {{{2
+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 {{{2
+function! s:DeleteBuffer(buf, mode)
+ " This routine assumes that the buffer to be removed is on the current line.
+ try
+ " Wipe/Delete buffer from Vim.
+ if a:mode == "wipe"
+ exe "silent bwipe" a:buf
+ else
+ exe "silent bdelete" a:buf
+ endif
+
+ " Delete the buffer from the list on screen.
+ 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 {{{2
+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"
+ endif
+
+ " Check to see if there are anymore buffers listed.
+ if len(listed) == 0
+ " Since there are no buffers left to switch to, open a new empty
+ " buffers.
+ exe "enew"
+ else
+ " Since there are buffers left to switch to, swith to them...
+ for b in reverse(listed[0:1])
+ exec "keepjumps silent b ".b
+ endfor
+ endif
+
+ " Clear any messages.
+ echo
+endfunction
+
+" ToggleSplitOutPathName {{{2
+function! s:ToggleSplitOutPathName()
+ let g:bufExplorerSplitOutPathName = !g:bufExplorerSplitOutPathName
+ call s:RebuildBufferList()
+ call s:UpdateHelpStatus()
+endfunction
+
+" ToggleShowRelativePath {{{2
+function! s:ToggleShowRelativePath()
+ let g:bufExplorerShowRelativePath = !g:bufExplorerShowRelativePath
+ call s:RebuildBufferList()
+ call s:UpdateHelpStatus()
+endfunction
+
+" ToggleShowTabBuffer {{{2
+function! s:ToggleShowTabBuffer()
+ let g:bufExplorerShowTabBuffer = !g:bufExplorerShowTabBuffer
+ call s:RebuildBufferList(g:bufExplorerShowTabBuffer)
+ call s:UpdateHelpStatus()
+endfunction
+
+" ToggleOnlyOneTab {{{2
+function! s:ToggleOnlyOneTab()
+ let g:bufExplorerOnlyOneTab = !g:bufExplorerOnlyOneTab
+ call s:RebuildBufferList()
+ call s:UpdateHelpStatus()
+endfunction
+
+" ToggleShowUnlisted {{{2
+function! s:ToggleShowUnlisted()
+ let g:bufExplorerShowUnlisted = !g:bufExplorerShowUnlisted
+ let num_bufs = s:RebuildBufferList(g:bufExplorerShowUnlisted == 0)
+ call s:UpdateHelpStatus()
+endfunction
+
+" ToggleFindActive {{{2
+function! s:ToggleFindActive()
+ let g:bufExplorerFindActive = !g:bufExplorerFindActive
+ call s:UpdateHelpStatus()
+endfunction
+
+" RebuildBufferList {{{2
+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 {{{2
+function! s:UpdateHelpStatus()
+ setlocal modifiable
+
+ let text = s:GetHelpStatus()
+ call setline(s:firstBufferLine - 2, text)
+
+ setlocal nomodifiable
+endfunction
+
+" MRUCmp {{{2
+function! s:MRUCmp(line1, line2)
+ return index(s:MRUList, str2nr(a:line1)) - index(s:MRUList, str2nr(a:line2))
+endfunction
+
+" SortReverse {{{2
+function! s:SortReverse()
+ let g:bufExplorerReverseSort = !g:bufExplorerReverseSort
+ call s:ReSortListing()
+endfunction
+
+" SortSelect {{{2
+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
+
+" ReverseSortSelect {{{2
+function! s:ReverseSortSelect()
+ let g:bufExplorerSortBy = get(s:sort_by, index(s:sort_by, g:bufExplorerSortBy) - 1, s:sort_by[-1])
+ call s:ReSortListing()
+endfunction
+
+" ReSortListing {{{2
+function! s:ReSortListing()
+ setlocal modifiable
+
+ let curPos = getpos('.')
+
+ call s:SortListing()
+ call s:UpdateHelpStatus()
+
+ call setpos('.', curPos)
+
+ setlocal nomodifiable
+endfunction
+
+" SortListing {{{2
+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 {{{2
+function! s:MRUListShow()
+ echomsg "MRUList=".string(s:MRUList)
+endfunction
+
+" Error {{{2
+" Display a message using ErrorMsg highlight group.
+function! s:Error(msg)
+ echohl ErrorMsg
+ echomsg a:msg
+ echohl None
+endfunction
+
+" Warning {{{2
+" Display a message using WarningMsg highlight group.
+function! s:Warning(msg)
+ echohl WarningMsg
+ echomsg a:msg
+ echohl None
+endfunction
+
+" GetTabNbr {{{2
+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" {{{2
+function! s:GetWinNbr(tabNbr, bufNbr)
+ " window number in tabpage.
+ let tablist = tabpagebuflist(a:tabNbr)
+ " Number: 0
+ " String: 1
+ " Funcref: 2
+ " List: 3
+ " Dictionary: 4
+ " Float: 5
+ if type(tablist) == 3
+ return index(tabpagebuflist(a:tabNbr), a:bufNbr) + 1
+ else
+ return 1
+ endif
+endfunction
+
+" Winmanager Integration {{{2
+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 BufExplorer("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 BufExplorer("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
+
+" Default key mapping {{{1
+if !hasmapto('BufExplorer')
+ noremap <script> <silent> <unique> <Leader>be :BufExplorer<CR>
+endif
+
+if !hasmapto('BufExplorerHorizontalSplit')
+ noremap <script> <silent> <unique> <Leader>bs :BufExplorerHorizontalSplit<CR>
+endif
+
+if !hasmapto('BufExplorerVerticalSplit')
+ noremap <script> <silent> <unique> <Leader>bv :BufExplorerVerticalSplit<CR>
+endif
+
+" 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:bufExplorerOnlyOneTab", 1) " If ShowTabBuffer = 1, only store the most recent tab for this buffer.
+call s:Set("g:bufExplorerReverseSort", 0) " Sort in reverse order by default?
+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:bufExplorerShowTabBuffer", 0) " Show only buffer(s) for this tab?
+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:bufExplorerSplitBelow", &splitbelow) " Should horizontal splits be below or above current window?
+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?
+"1}}}
+
+" vim:ft=vim foldmethod=marker sw=4
diff --git a/vim.dot.link/plugin/git.vim b/vim.dot.link/plugin/git.vim
new file mode 100644
index 0000000..bd0b053
--- /dev/null
+++ b/vim.dot.link/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/vim.dot.link/plugin/indexer.vim.disabled b/vim.dot.link/plugin/indexer.vim.disabled
new file mode 100644
index 0000000..28c9472
--- /dev/null
+++ b/vim.dot.link/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/vim.dot.link/plugin/project.vim b/vim.dot.link/plugin/project.vim
new file mode 100644
index 0000000..47bd379
--- /dev/null
+++ b/vim.dot.link/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/vim.dot.link/plugin/snipMate.vim b/vim.dot.link/plugin/snipMate.vim
new file mode 100644
index 0000000..3efee2a
--- /dev/null
+++ b/vim.dot.link/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/vim.dot.link/plugin/startshell_mapping.vim.disabled b/vim.dot.link/plugin/startshell_mapping.vim.disabled
new file mode 100644
index 0000000..e9704f4
--- /dev/null
+++ b/vim.dot.link/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/vim.dot.link/plugin/taglist.vim.disable b/vim.dot.link/plugin/taglist.vim.disable
new file mode 100644
index 0000000..59901f6
--- /dev/null
+++ b/vim.dot.link/plugin/taglist.vim.disable
@@ -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/vim.dot.link/plugin/vcsbzr.vim b/vim.dot.link/plugin/vcsbzr.vim
new file mode 100644
index 0000000..b8665b8
--- /dev/null
+++ b/vim.dot.link/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/vim.dot.link/plugin/vcscommand.vim b/vim.dot.link/plugin/vcscommand.vim
new file mode 100644
index 0000000..98214f2
--- /dev/null
+++ b/vim.dot.link/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/vim.dot.link/plugin/vcscvs.vim b/vim.dot.link/plugin/vcscvs.vim
new file mode 100644
index 0000000..73d6a7f
--- /dev/null
+++ b/vim.dot.link/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/vim.dot.link/plugin/vcsgit.vim b/vim.dot.link/plugin/vcsgit.vim
new file mode 100644
index 0000000..4e299d9
--- /dev/null
+++ b/vim.dot.link/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/vim.dot.link/plugin/vcshg.vim b/vim.dot.link/plugin/vcshg.vim
new file mode 100644
index 0000000..2c616c0
--- /dev/null
+++ b/vim.dot.link/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/vim.dot.link/plugin/vcssvk.vim b/vim.dot.link/plugin/vcssvk.vim
new file mode 100644
index 0000000..b7cc6c9
--- /dev/null
+++ b/vim.dot.link/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/vim.dot.link/plugin/vcssvn.vim b/vim.dot.link/plugin/vcssvn.vim
new file mode 100644
index 0000000..758f819
--- /dev/null
+++ b/vim.dot.link/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