first commit

This commit is contained in:
colben 2021-08-29 00:05:19 +08:00
commit 6574151a51
45 changed files with 13483 additions and 0 deletions

87
autoload/gocomplete.vim Normal file
View File

@ -0,0 +1,87 @@
if exists('g:loaded_gocode')
finish
endif
let g:loaded_gocode = 1
fu! s:gocodeCurrentBuffer()
let buf = getline(1, '$')
if &encoding != 'utf-8'
let buf = map(buf, 'iconv(v:val, &encoding, "utf-8")')
endif
if &l:fileformat == 'dos'
" XXX: line2byte() depend on 'fileformat' option.
" so if fileformat is 'dos', 'buf' must include '\r'.
let buf = map(buf, 'v:val."\r"')
endif
let file = tempname()
call writefile(buf, file)
return file
endf
let s:vim_system = get(g:, 'gocomplete#system_function', 'system')
fu! s:system(str, ...)
return call(s:vim_system, [a:str] + a:000)
endf
fu! s:gocodeShellescape(arg)
try
let ssl_save = &shellslash
set noshellslash
return shellescape(a:arg)
finally
let &shellslash = ssl_save
endtry
endf
fu! s:gocodeCommand(cmd, preargs, args)
for i in range(0, len(a:args) - 1)
let a:args[i] = s:gocodeShellescape(a:args[i])
endfor
for i in range(0, len(a:preargs) - 1)
let a:preargs[i] = s:gocodeShellescape(a:preargs[i])
endfor
let result = s:system(printf('gocode %s %s %s', join(a:preargs), a:cmd, join(a:args)))
if v:shell_error != 0
return "[\"0\", []]"
else
if &encoding != 'utf-8'
let result = iconv(result, 'utf-8', &encoding)
endif
return result
endif
endf
fu! s:gocodeCurrentBufferOpt(filename)
return '-in=' . a:filename
endf
fu! s:gocodeCursor()
if &encoding != 'utf-8'
let c = col('.')
let buf = line('.') == 1 ? "" : (join(getline(1, line('.')-1), "\n") . "\n")
let buf .= c == 1 ? "" : getline('.')[:c-2]
return printf('%d', len(iconv(buf, &encoding, "utf-8")))
endif
return printf('%d', line2byte(line('.')) + (col('.')-2))
endf
fu! s:gocodeAutocomplete()
let filename = s:gocodeCurrentBuffer()
let result = s:gocodeCommand('autocomplete',
\ [s:gocodeCurrentBufferOpt(filename), '-f=vim'],
\ [expand('%:p'), s:gocodeCursor()])
call delete(filename)
return result
endf
fu! gocomplete#Complete(findstart, base)
"findstart = 1 when we need to get the text length
if a:findstart == 1
execute "silent let g:gocomplete_completions = " . s:gocodeAutocomplete()
return col('.') - g:gocomplete_completions[0] - 1
"findstart = 0 when we need to return the list of completions
else
return g:gocomplete_completions[1]
endif
endf

200
autoload/nerdtree.vim Normal file
View File

@ -0,0 +1,200 @@
if exists("g:loaded_nerdtree_autoload")
finish
endif
let g:loaded_nerdtree_autoload = 1
function! nerdtree#version()
return '5.0.0'
endfunction
" SECTION: General Functions {{{1
"============================================================
"FUNCTION: nerdtree#checkForBrowse(dir) {{{2
"inits a window tree in the current buffer if appropriate
function! nerdtree#checkForBrowse(dir)
if !isdirectory(a:dir)
return
endif
if s:reuseWin(a:dir)
return
endif
call g:NERDTreeCreator.CreateWindowTree(a:dir)
endfunction
"FUNCTION: s:reuseWin(dir) {{{2
"finds a NERDTree buffer with root of dir, and opens it.
function! s:reuseWin(dir) abort
let path = g:NERDTreePath.New(fnamemodify(a:dir, ":p"))
for i in range(1, bufnr("$"))
unlet! nt
let nt = getbufvar(i, "NERDTree")
if empty(nt)
continue
endif
if nt.isWinTree() && nt.root.path.equals(path)
call nt.setPreviousBuf(bufnr("#"))
exec "buffer " . i
return 1
endif
endfor
return 0
endfunction
" FUNCTION: nerdtree#completeBookmarks(A,L,P) {{{2
" completion function for the bookmark commands
function! nerdtree#completeBookmarks(A,L,P)
return filter(g:NERDTreeBookmark.BookmarkNames(), 'v:val =~# "^' . a:A . '"')
endfunction
"FUNCTION: nerdtree#compareNodes(dir) {{{2
function! nerdtree#compareNodes(n1, n2)
return a:n1.path.compareTo(a:n2.path)
endfunction
"FUNCTION: nerdtree#compareNodesBySortKey(n1, n2) {{{2
function! nerdtree#compareNodesBySortKey(n1, n2)
let sortKey1 = a:n1.path.getSortKey()
let sortKey2 = a:n2.path.getSortKey()
let i = 0
while i < min([len(sortKey1), len(sortKey2)])
" Compare chunks upto common length.
" If chunks have different type, the one which has
" integer type is the lesser.
if type(sortKey1[i]) == type(sortKey2[i])
if sortKey1[i] <# sortKey2[i]
return - 1
elseif sortKey1[i] ># sortKey2[i]
return 1
endif
elseif type(sortKey1[i]) == v:t_number
return -1
elseif type(sortKey2[i]) == v:t_number
return 1
endif
let i = i + 1
endwhile
" Keys are identical upto common length.
" The key which has smaller chunks is the lesser one.
if len(sortKey1) < len(sortKey2)
return -1
elseif len(sortKey1) > len(sortKey2)
return 1
else
return 0
endif
endfunction
" FUNCTION: nerdtree#deprecated(func, [msg]) {{{2
" Issue a deprecation warning for a:func. If a second arg is given, use this
" as the deprecation message
function! nerdtree#deprecated(func, ...)
let msg = a:0 ? a:func . ' ' . a:1 : a:func . ' is deprecated'
if !exists('s:deprecationWarnings')
let s:deprecationWarnings = {}
endif
if !has_key(s:deprecationWarnings, a:func)
let s:deprecationWarnings[a:func] = 1
echomsg msg
endif
endfunction
" FUNCTION: nerdtree#exec(cmd) {{{2
" Same as :exec cmd but with eventignore set for the duration
" to disable the autocommands used by NERDTree (BufEnter,
" BufLeave and VimEnter)
function! nerdtree#exec(cmd)
let old_ei = &ei
set ei=BufEnter,BufLeave,VimEnter
exec a:cmd
let &ei = old_ei
endfunction
" FUNCTION: nerdtree#has_opt(options, name) {{{2
function! nerdtree#has_opt(options, name)
return has_key(a:options, a:name) && a:options[a:name] == 1
endfunction
" FUNCTION: nerdtree#loadClassFiles() {{{2
function! nerdtree#loadClassFiles()
runtime lib/nerdtree/path.vim
runtime lib/nerdtree/menu_controller.vim
runtime lib/nerdtree/menu_item.vim
runtime lib/nerdtree/key_map.vim
runtime lib/nerdtree/bookmark.vim
runtime lib/nerdtree/tree_file_node.vim
runtime lib/nerdtree/tree_dir_node.vim
runtime lib/nerdtree/opener.vim
runtime lib/nerdtree/creator.vim
runtime lib/nerdtree/flag_set.vim
runtime lib/nerdtree/nerdtree.vim
runtime lib/nerdtree/ui.vim
runtime lib/nerdtree/event.vim
runtime lib/nerdtree/notifier.vim
endfunction
" FUNCTION: nerdtree#postSourceActions() {{{2
function! nerdtree#postSourceActions()
call g:NERDTreeBookmark.CacheBookmarks(1)
call nerdtree#ui_glue#createDefaultBindings()
"load all nerdtree plugins
runtime! nerdtree_plugin/**/*.vim
endfunction
"FUNCTION: nerdtree#runningWindows(dir) {{{2
function! nerdtree#runningWindows()
return has("win16") || has("win32") || has("win64")
endfunction
"FUNCTION: nerdtree#runningCygwin(dir) {{{2
function! nerdtree#runningCygwin()
return has("win32unix")
endfunction
" SECTION: View Functions {{{1
"============================================================
"FUNCTION: nerdtree#echo {{{2
"A wrapper for :echo. Appends 'NERDTree:' on the front of all messages
"
"Args:
"msg: the message to echo
function! nerdtree#echo(msg)
redraw
echomsg "NERDTree: " . a:msg
endfunction
"FUNCTION: nerdtree#echoError {{{2
"Wrapper for nerdtree#echo, sets the message type to errormsg for this message
"Args:
"msg: the message to echo
function! nerdtree#echoError(msg)
echohl errormsg
call nerdtree#echo(a:msg)
echohl normal
endfunction
"FUNCTION: nerdtree#echoWarning {{{2
"Wrapper for nerdtree#echo, sets the message type to warningmsg for this message
"Args:
"msg: the message to echo
function! nerdtree#echoWarning(msg)
echohl warningmsg
call nerdtree#echo(a:msg)
echohl normal
endfunction
"FUNCTION: nerdtree#renderView {{{2
function! nerdtree#renderView()
call b:NERDTree.render()
endfunction
" vim: set sw=4 sts=4 et fdm=marker:

View File

@ -0,0 +1,649 @@
if exists("g:loaded_nerdtree_ui_glue_autoload")
finish
endif
let g:loaded_nerdtree_ui_glue_autoload = 1
" FUNCTION: nerdtree#ui_glue#createDefaultBindings() {{{1
function! nerdtree#ui_glue#createDefaultBindings()
let s = '<SNR>' . s:SID() . '_'
call NERDTreeAddKeyMap({ 'key': '<MiddleMouse>', 'scope': 'all', 'callback': s . 'handleMiddleMouse' })
call NERDTreeAddKeyMap({ 'key': '<LeftRelease>', 'scope': "all", 'callback': s."handleLeftClick" })
call NERDTreeAddKeyMap({ 'key': '<2-LeftMouse>', 'scope': "DirNode", 'callback': s."activateDirNode" })
call NERDTreeAddKeyMap({ 'key': '<2-LeftMouse>', 'scope': "FileNode", 'callback': s."activateFileNode" })
call NERDTreeAddKeyMap({ 'key': '<2-LeftMouse>', 'scope': "Bookmark", 'callback': s."activateBookmark" })
call NERDTreeAddKeyMap({ 'key': '<2-LeftMouse>', 'scope': "all", 'callback': s."activateAll" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapActivateNode, 'scope': "DirNode", 'callback': s."activateDirNode" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapActivateNode, 'scope': "FileNode", 'callback': s."activateFileNode" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapActivateNode, 'scope': "Bookmark", 'callback': s."activateBookmark" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapActivateNode, 'scope': "all", 'callback': s."activateAll" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenSplit, 'scope': "Node", 'callback': s."openHSplit" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenVSplit, 'scope': "Node", 'callback': s."openVSplit" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapPreview, 'scope': "Node", 'callback': s."previewNodeCurrent" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapPreviewVSplit, 'scope': "Node", 'callback': s."previewNodeVSplit" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapPreviewSplit, 'scope': "Node", 'callback': s."previewNodeHSplit" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenRecursively, 'scope': "DirNode", 'callback': s."openNodeRecursively" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapUpdir, 'scope': 'all', 'callback': s . 'upDirCurrentRootClosed' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapUpdirKeepOpen, 'scope': 'all', 'callback': s . 'upDirCurrentRootOpen' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapChangeRoot, 'scope': 'Node', 'callback': s . 'chRoot' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapChdir, 'scope': "Node", 'callback': s."chCwd" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapQuit, 'scope': "all", 'callback': s."closeTreeWindow" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapCWD, 'scope': "all", 'callback': "nerdtree#ui_glue#chRootCwd" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapRefreshRoot, 'scope': "all", 'callback': s."refreshRoot" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapRefresh, 'scope': "Node", 'callback': s."refreshCurrent" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapHelp, 'scope': "all", 'callback': s."displayHelp" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapToggleZoom, 'scope': "all", 'callback': s."toggleZoom" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapToggleHidden, 'scope': "all", 'callback': s."toggleShowHidden" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapToggleFilters, 'scope': "all", 'callback': s."toggleIgnoreFilter" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapToggleFiles, 'scope': "all", 'callback': s."toggleShowFiles" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapToggleBookmarks, 'scope': "all", 'callback': s."toggleShowBookmarks" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapCloseDir, 'scope': "Node", 'callback': s."closeCurrentDir" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapCloseChildren, 'scope': "DirNode", 'callback': s."closeChildren" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapMenu, 'scope': "Node", 'callback': s."showMenu" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpParent, 'scope': "Node", 'callback': s."jumpToParent" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpFirstChild, 'scope': "Node", 'callback': s."jumpToFirstChild" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpLastChild, 'scope': "Node", 'callback': s."jumpToLastChild" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpRoot, 'scope': "all", 'callback': s."jumpToRoot" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpNextSibling, 'scope': "Node", 'callback': s."jumpToNextSibling" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpPrevSibling, 'scope': "Node", 'callback': s."jumpToPrevSibling" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenInTab, 'scope': 'Node', 'callback': s . 'openInNewTab' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenInTabSilent, 'scope': 'Node', 'callback': s . 'openInNewTabSilent' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenInTab, 'scope': 'Bookmark', 'callback': s . 'openInNewTab' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenInTabSilent, 'scope': 'Bookmark', 'callback': s . 'openInNewTabSilent' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenExpl, 'scope': "DirNode", 'callback': s."openExplorer" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapDeleteBookmark, 'scope': "Bookmark", 'callback': s."deleteBookmark" })
endfunction
"SECTION: Interface bindings {{{1
"============================================================
"FUNCTION: s:activateAll() {{{1
"handle the user activating the updir line
function! s:activateAll()
if getline(".") ==# g:NERDTreeUI.UpDirLine()
return nerdtree#ui_glue#upDir(0)
endif
endfunction
" FUNCTION: s:activateDirNode(directoryNode) {{{1
function! s:activateDirNode(directoryNode)
if a:directoryNode.isRoot() && a:directoryNode.isOpen
call nerdtree#echo('cannot close tree root')
return
endif
call a:directoryNode.activate()
endfunction
"FUNCTION: s:activateFileNode() {{{1
"handle the user activating a tree node
function! s:activateFileNode(node)
call a:node.activate({'reuse': 'all', 'where': 'p'})
endfunction
"FUNCTION: s:activateBookmark() {{{1
"handle the user activating a bookmark
function! s:activateBookmark(bm)
call a:bm.activate(b:NERDTree, !a:bm.path.isDirectory ? {'where': 'p'} : {})
endfunction
" FUNCTION: nerdtree#ui_glue#bookmarkNode(name) {{{1
" Associate the current node with the given name
function! nerdtree#ui_glue#bookmarkNode(...)
let currentNode = g:NERDTreeFileNode.GetSelected()
if currentNode != {}
let name = a:1
if empty(name)
let name = currentNode.path.getLastPathComponent(0)
endif
try
call currentNode.bookmark(name)
call b:NERDTree.render()
catch /^NERDTree.IllegalBookmarkNameError/
call nerdtree#echo("bookmark names must not contain spaces")
endtry
else
call nerdtree#echo("select a node first")
endif
endfunction
" FUNCTION: s:chCwd(node) {{{1
function! s:chCwd(node)
try
call a:node.path.changeToDir()
catch /^NERDTree.PathChangeError/
call nerdtree#echoWarning("could not change cwd")
endtry
endfunction
" FUNCTION: s:chRoot(node) {{{1
" changes the current root to the selected one
function! s:chRoot(node)
call b:NERDTree.changeRoot(a:node)
endfunction
" FUNCTION: s:nerdtree#ui_glue#chRootCwd() {{{1
" Change the NERDTree root to match the current working directory.
function! nerdtree#ui_glue#chRootCwd()
NERDTreeCWD
endfunction
" FUNCTION: nnerdtree#ui_glue#clearBookmarks(bookmarks) {{{1
function! nerdtree#ui_glue#clearBookmarks(bookmarks)
if a:bookmarks ==# ''
let currentNode = g:NERDTreeFileNode.GetSelected()
if currentNode != {}
call currentNode.clearBookmarks()
endif
else
for name in split(a:bookmarks, ' ')
let bookmark = g:NERDTreeBookmark.BookmarkFor(name)
call bookmark.delete()
endfor
endif
call b:NERDTree.root.refresh()
call b:NERDTree.render()
endfunction
" FUNCTION: s:closeChildren(node) {{{1
" closes all childnodes of the current node
function! s:closeChildren(node)
call a:node.closeChildren()
call b:NERDTree.render()
call a:node.putCursorHere(0, 0)
endfunction
" FUNCTION: s:closeCurrentDir(node) {{{1
" Close the parent directory of the current node.
function! s:closeCurrentDir(node)
if a:node.isRoot()
call nerdtree#echo('cannot close parent of tree root')
return
endif
let l:parent = a:node.parent
while l:parent.isCascadable()
let l:parent = l:parent.parent
endwhile
if l:parent.isRoot()
call nerdtree#echo('cannot close tree root')
return
endif
call l:parent.close()
call b:NERDTree.render()
call l:parent.putCursorHere(0, 0)
endfunction
" FUNCTION: s:closeTreeWindow() {{{1
" close the tree window
function! s:closeTreeWindow()
if b:NERDTree.isWinTree() && b:NERDTree.previousBuf() != -1
exec "buffer " . b:NERDTree.previousBuf()
else
if winnr("$") > 1
call g:NERDTree.Close()
else
call nerdtree#echo("Cannot close last window")
endif
endif
endfunction
" FUNCTION: s:deleteBookmark(bookmark) {{{1
" Prompt the user to confirm the deletion of the selected bookmark.
function! s:deleteBookmark(bookmark)
let l:message = "Delete the bookmark \"" . a:bookmark.name
\ . "\" from the bookmark list?"
let l:choices = "&Yes\n&No"
echo | redraw
let l:selection = confirm(l:message, l:choices, 1, 'Warning')
if l:selection != 1
call nerdtree#echo('bookmark not deleted')
return
endif
try
call a:bookmark.delete()
silent call b:NERDTree.root.refresh()
call b:NERDTree.render()
echo | redraw
catch /^NERDTree/
call nerdtree#echoWarning('could not remove bookmark')
endtry
endfunction
" FUNCTION: s:displayHelp() {{{1
" toggles the help display
function! s:displayHelp()
call b:NERDTree.ui.toggleHelp()
call b:NERDTree.render()
call b:NERDTree.ui.centerView()
endfunction
" FUNCTION: s:findAndRevealPath(pathStr) {{{1
function! s:findAndRevealPath(pathStr)
let l:pathStr = !empty(a:pathStr) ? a:pathStr : expand('%:p')
if empty(l:pathStr)
call nerdtree#echoWarning('no file for the current buffer')
return
endif
try
let l:pathStr = g:NERDTreePath.Resolve(l:pathStr)
let l:pathObj = g:NERDTreePath.New(l:pathStr)
catch /^NERDTree.InvalidArgumentsError/
call nerdtree#echoWarning('invalid path')
return
endtry
if !g:NERDTree.ExistsForTab()
try
let l:cwd = g:NERDTreePath.New(getcwd())
catch /^NERDTree.InvalidArgumentsError/
call nerdtree#echo('current directory does not exist.')
let l:cwd = l:pathObj.getParent()
endtry
if l:pathObj.isUnder(l:cwd)
call g:NERDTreeCreator.CreateTabTree(l:cwd.str())
else
call g:NERDTreeCreator.CreateTabTree(l:pathObj.getParent().str())
endif
else
NERDTreeFocus
if !l:pathObj.isUnder(b:NERDTree.root.path)
call s:chRoot(g:NERDTreeDirNode.New(l:pathObj.getParent(), b:NERDTree))
endif
endif
if l:pathObj.isHiddenUnder(b:NERDTree.root.path)
call b:NERDTree.ui.setShowHidden(1)
endif
let l:node = b:NERDTree.root.reveal(l:pathObj)
call b:NERDTree.render()
call l:node.putCursorHere(1, 0)
endfunction
"FUNCTION: s:handleLeftClick() {{{1
"Checks if the click should open the current node
function! s:handleLeftClick()
let currentNode = g:NERDTreeFileNode.GetSelected()
if currentNode != {}
"the dir arrows are multibyte chars, and vim's string functions only
"deal with single bytes - so split the line up with the hack below and
"take the line substring manually
let line = split(getline(line(".")), '\zs')
let startToCur = ""
for i in range(0,len(line)-1)
let startToCur .= line[i]
endfor
if currentNode.path.isDirectory
if startToCur =~# g:NERDTreeUI.MarkupReg() && startToCur =~# '[+~'.g:NERDTreeDirArrowExpandable.g:NERDTreeDirArrowCollapsible.'] \?$'
call currentNode.activate()
return
endif
endif
if (g:NERDTreeMouseMode ==# 2 && currentNode.path.isDirectory) || g:NERDTreeMouseMode ==# 3
let char = strpart(startToCur, strlen(startToCur)-1, 1)
if char !~# g:NERDTreeUI.MarkupReg()
if currentNode.path.isDirectory
call currentNode.activate()
else
call currentNode.activate({'reuse': 'all', 'where': 'p'})
endif
return
endif
endif
endif
endfunction
" FUNCTION: s:handleMiddleMouse() {{{1
function! s:handleMiddleMouse()
" A middle mouse click does not automatically position the cursor as one
" would expect. Forcing the execution of a regular left mouse click here
" fixes this problem.
execute "normal! \<LeftMouse>"
let l:currentNode = g:NERDTreeFileNode.GetSelected()
if empty(l:currentNode)
call nerdtree#echoError('use the pointer to select a node')
return
endif
if l:currentNode.path.isDirectory
call l:currentNode.openExplorer()
else
call l:currentNode.open({'where': 'h'})
endif
endfunction
" FUNCTION: nerdtree#ui_glue#invokeKeyMap(key) {{{1
"this is needed since I cant figure out how to invoke dict functions from a
"key map
function! nerdtree#ui_glue#invokeKeyMap(key)
call g:NERDTreeKeyMap.Invoke(a:key)
endfunction
" FUNCTION: s:jumpToFirstChild(node) {{{1
function! s:jumpToFirstChild(node)
call s:jumpToChild(a:node, 0)
endfunction
" FUNCTION: s:jumpToLastChild(node) {{{1
function! s:jumpToLastChild(node)
call s:jumpToChild(a:node, 1)
endfunction
" FUNCTION: s:jumpToChild(node, last) {{{2
" Jump to the first or last child node at the same file system level.
"
" Args:
" node: the node on which the cursor currently sits
" last: 1 (true) if jumping to last child, 0 (false) if jumping to first
function! s:jumpToChild(node, last)
let l:node = a:node.path.isDirectory ? a:node.getCascadeRoot() : a:node
if l:node.isRoot()
return
endif
let l:parent = l:node.parent
let l:children = l:parent.getVisibleChildren()
let l:target = a:last ? l:children[len(l:children) - 1] : l:children[0]
call l:target.putCursorHere(1, 0)
call b:NERDTree.ui.centerView()
endfunction
" FUNCTION: s:jumpToParent(node) {{{1
" Move the cursor to the parent of the specified node. For a cascade, move to
" the parent of the cascade's first node. At the root node, do nothing.
function! s:jumpToParent(node)
let l:node = a:node.path.isDirectory ? a:node.getCascadeRoot() : a:node
if l:node.isRoot()
return
endif
if empty(l:node.parent)
call nerdtree#echo('could not jump to parent node')
return
endif
call l:node.parent.putCursorHere(1, 0)
call b:NERDTree.ui.centerView()
endfunction
" FUNCTION: s:jumpToRoot() {{{1
" moves the cursor to the root node
function! s:jumpToRoot()
call b:NERDTree.root.putCursorHere(1, 0)
call b:NERDTree.ui.centerView()
endfunction
" FUNCTION: s:jumpToNextSibling(node) {{{1
function! s:jumpToNextSibling(node)
call s:jumpToSibling(a:node, 1)
endfunction
" FUNCTION: s:jumpToPrevSibling(node) {{{1
function! s:jumpToPrevSibling(node)
call s:jumpToSibling(a:node, 0)
endfunction
" FUNCTION: s:jumpToSibling(node, forward) {{{2
" Move the cursor to the next or previous node at the same file system level.
"
" Args:
" node: the node on which the cursor currently sits
" forward: 0 to jump to previous sibling, 1 to jump to next sibling
function! s:jumpToSibling(node, forward)
let l:node = a:node.path.isDirectory ? a:node.getCascadeRoot() : a:node
let l:sibling = l:node.findSibling(a:forward)
if empty(l:sibling)
return
endif
call l:sibling.putCursorHere(1, 0)
call b:NERDTree.ui.centerView()
endfunction
" FUNCTION: nerdtree#ui_glue#openBookmark(name) {{{1
" Open the Bookmark that has the specified name. This function provides the
" implementation for the ":OpenBookmark" command.
function! nerdtree#ui_glue#openBookmark(name)
try
let l:bookmark = g:NERDTreeBookmark.BookmarkFor(a:name)
catch /^NERDTree.BookmarkNotFoundError/
call nerdtree#echoError('bookmark "' . a:name . '" not found')
return
endtry
if l:bookmark.path.isDirectory
call l:bookmark.open(b:NERDTree)
else
call l:bookmark.open(b:NERDTree, {'where': 'p'})
endif
endfunction
" FUNCTION: s:openHSplit(target) {{{1
function! s:openHSplit(target)
call a:target.activate({'where': 'h'})
endfunction
" FUNCTION: s:openVSplit(target) {{{1
function! s:openVSplit(target)
call a:target.activate({'where': 'v'})
endfunction
" FUNCTION: s:openExplorer(node) {{{1
function! s:openExplorer(node)
call a:node.openExplorer()
endfunction
" FUNCTION: s:openInNewTab(target) {{{1
function! s:openInNewTab(target)
let l:opener = g:NERDTreeOpener.New(a:target.path, {'where': 't'})
call l:opener.open(a:target)
endfunction
" FUNCTION: s:openInNewTabSilent(target) {{{1
function! s:openInNewTabSilent(target)
let l:opener = g:NERDTreeOpener.New(a:target.path, {'where': 't', 'stay': 1})
call l:opener.open(a:target)
endfunction
" FUNCTION: s:openNodeRecursively(node) {{{1
function! s:openNodeRecursively(node)
call nerdtree#echo("Recursively opening node. Please wait...")
call a:node.openRecursively()
call b:NERDTree.render()
redraw
call nerdtree#echo("Recursively opening node. Please wait... DONE")
endfunction
"FUNCTION: s:previewNodeCurrent(node) {{{1
function! s:previewNodeCurrent(node)
call a:node.open({'stay': 1, 'where': 'p', 'keepopen': 1})
endfunction
"FUNCTION: s:previewNodeHSplit(node) {{{1
function! s:previewNodeHSplit(node)
call a:node.open({'stay': 1, 'where': 'h', 'keepopen': 1})
endfunction
"FUNCTION: s:previewNodeVSplit(node) {{{1
function! s:previewNodeVSplit(node)
call a:node.open({'stay': 1, 'where': 'v', 'keepopen': 1})
endfunction
" FUNCTION: nerdtree#ui_glue#revealBookmark(name) {{{1
" put the cursor on the node associate with the given name
function! nerdtree#ui_glue#revealBookmark(name)
try
let targetNode = g:NERDTreeBookmark.GetNodeForName(a:name, 0, b:NERDTree)
call targetNode.putCursorHere(0, 1)
catch /^NERDTree.BookmarkNotFoundError/
call nerdtree#echo("Bookmark isnt cached under the current root")
endtry
endfunction
" FUNCTION: s:refreshRoot() {{{1
" Reloads the current root. All nodes below this will be lost and the root dir
" will be reloaded.
function! s:refreshRoot()
if !g:NERDTree.IsOpen()
return
endif
call nerdtree#echo("Refreshing the root node. This could take a while...")
let l:curWin = winnr()
call nerdtree#exec(g:NERDTree.GetWinNum() . "wincmd w")
call b:NERDTree.root.refresh()
call b:NERDTree.render()
redraw
call nerdtree#exec(l:curWin . "wincmd w")
call nerdtree#echo("Refreshing the root node. This could take a while... DONE")
endfunction
" FUNCTION: s:refreshCurrent(node) {{{1
" refreshes the root for the current node
function! s:refreshCurrent(node)
let node = a:node
if !node.path.isDirectory
let node = node.parent
endif
call nerdtree#echo("Refreshing node. This could take a while...")
call node.refresh()
call b:NERDTree.render()
redraw
call nerdtree#echo("Refreshing node. This could take a while... DONE")
endfunction
" FUNCTION: nerdtree#ui_glue#setupCommands() {{{1
function! nerdtree#ui_glue#setupCommands()
command! -n=? -complete=dir -bar NERDTree :call g:NERDTreeCreator.CreateTabTree('<args>')
command! -n=? -complete=dir -bar NERDTreeToggle :call g:NERDTreeCreator.ToggleTabTree('<args>')
command! -n=0 -bar NERDTreeClose :call g:NERDTree.Close()
command! -n=1 -complete=customlist,nerdtree#completeBookmarks -bar NERDTreeFromBookmark call g:NERDTreeCreator.CreateTabTree('<args>')
command! -n=0 -bar NERDTreeMirror call g:NERDTreeCreator.CreateMirror()
command! -n=? -complete=file -bar NERDTreeFind call s:findAndRevealPath('<args>')
command! -n=0 -bar NERDTreeRefreshRoot call s:refreshRoot()
command! -n=0 -bar NERDTreeFocus call NERDTreeFocus()
command! -n=0 -bar NERDTreeCWD call NERDTreeCWD()
endfunction
" Function: s:SID() {{{1
function s:SID()
if !exists("s:sid")
let s:sid = matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze_SID$')
endif
return s:sid
endfun
" FUNCTION: s:showMenu(node) {{{1
function! s:showMenu(node)
let mc = g:NERDTreeMenuController.New(g:NERDTreeMenuItem.AllEnabled())
call mc.showMenu()
endfunction
" FUNCTION: s:toggleIgnoreFilter() {{{1
function! s:toggleIgnoreFilter()
call b:NERDTree.ui.toggleIgnoreFilter()
endfunction
" FUNCTION: s:toggleShowBookmarks() {{{1
function! s:toggleShowBookmarks()
call b:NERDTree.ui.toggleShowBookmarks()
endfunction
" FUNCTION: s:toggleShowFiles() {{{1
function! s:toggleShowFiles()
call b:NERDTree.ui.toggleShowFiles()
endfunction
" FUNCTION: s:toggleShowHidden() {{{1
" toggles the display of hidden files
function! s:toggleShowHidden()
call b:NERDTree.ui.toggleShowHidden()
endfunction
" FUNCTION: s:toggleZoom() {{{1
function! s:toggleZoom()
call b:NERDTree.ui.toggleZoom()
endfunction
" FUNCTION: nerdtree#ui_glue#upDir(preserveState) {{{1
" Move the NERDTree up one level.
"
" Args:
" preserveState: if 1, the current root is left open when the new tree is
" rendered; if 0, the current root node is closed
function! nerdtree#ui_glue#upDir(preserveState)
try
call b:NERDTree.root.cacheParent()
catch /^NERDTree.CannotCacheParentError/
call nerdtree#echo('already at root directory')
return
endtry
let l:oldRoot = b:NERDTree.root
let l:newRoot = b:NERDTree.root.parent
call l:newRoot.open()
call l:newRoot.transplantChild(l:oldRoot)
if !a:preserveState
call l:oldRoot.close()
endif
call b:NERDTree.changeRoot(l:newRoot)
call l:oldRoot.putCursorHere(0, 0)
endfunction
" FUNCTION: s:upDirCurrentRootOpen() {{{1
function! s:upDirCurrentRootOpen()
call nerdtree#ui_glue#upDir(1)
endfunction
" FUNCTION: s:upDirCurrentRootClosed() {{{1
function! s:upDirCurrentRootClosed()
call nerdtree#ui_glue#upDir(0)
endfunction
" vim: set sw=4 sts=4 et fdm=marker:

1314
colors/atom-dark-256.vim Normal file

File diff suppressed because it is too large Load Diff

115
colors/atom-dark.vim Normal file
View File

@ -0,0 +1,115 @@
" Vim color file
"
" Author: Federico Ramirez
" https://github.com/gosukiwi/vim-atom-dark
"
" Note: Based on the Monokai theme variation by Tomas Restrepo
" https://github.com/tomasr/molokai
hi clear
if version > 580
" no guarantees for version 5.8 and below, but this makes it stop
" complaining
hi clear
if exists("syntax_on")
syntax reset
endif
endif
let g:colors_name="atom-dark"
hi Boolean guifg=#99CC99
hi Character guifg=#A8FF60
hi Number guifg=#99CC99
hi String guifg=#A8FF60
hi Conditional guifg=#92C5F7 gui=none
hi Constant guifg=#99CC99 gui=none
hi Cursor guifg=#F1F1F1 guibg=#777777
hi iCursor guifg=#F1F1F1 guibg=#777777
hi Debug guifg=#BCA3A3 gui=none
hi Define guifg=#66D9EF
hi Delimiter guifg=#8F8F8F
hi DiffAdd guibg=#13354A
hi DiffChange guifg=#89807D guibg=#4C4745
hi DiffDelete guifg=#960050 guibg=#1E0010
hi DiffText guibg=#4C4745 gui=none
hi Directory guifg=#AAAAAA gui=none
hi Error guifg=#A8FF60 guibg=#1E0010
hi ErrorMsg guifg=#92C5F7 guibg=#232526 gui=none
hi Exception guifg=#DAD085 gui=none
hi Float guifg=#99CC99
hi FoldColumn guifg=#465457 guibg=#000000
hi Folded guifg=#465457 guibg=#000000
hi Function guifg=#DAD085
hi Identifier guifg=#B6B7EB
hi Ignore guifg=#808080 guibg=bg
hi IncSearch guifg=#C4BE89 guibg=#000000
hi Keyword guifg=#92C5F7 gui=none
hi Label guifg=#A8FF60 gui=none
hi Macro guifg=#C4BE89 gui=none
hi SpecialKey guifg=#66D9EF gui=none
hi MatchParen guifg=#B7B9B8 guibg=#444444 gui=none
hi ModeMsg guifg=#A8FF60
hi MoreMsg guifg=#A8FF60
hi Operator guifg=#92C5F7
" complete menu
hi Pmenu guifg=#66D9EF guibg=#000000
hi PmenuSel guibg=#808080
hi PmenuSbar guibg=#080808
hi PmenuThumb guifg=#66D9EF
hi PreCondit guifg=#DAD085 gui=none
hi PreProc guifg=#DAD085
hi Question guifg=#66D9EF
hi Repeat guifg=#92C5F7 gui=none
hi Search guifg=#000000 guibg=#B4EC85
" marks
hi SignColumn guifg=#DAD085 guibg=#232526
hi SpecialChar guifg=#92C5F7 gui=none
hi SpecialComment guifg=#7C7C7C gui=none
hi Special guifg=#66D9EF guibg=bg gui=none
if has("spell")
hi SpellBad guisp=#FF0000 gui=undercurl
hi SpellCap guisp=#7070F0 gui=undercurl
hi SpellLocal guisp=#70F0F0 gui=undercurl
hi SpellRare guisp=#FFFFFF gui=undercurl
endif
hi Statement guifg=#92C5F7 gui=none
hi StatusLine guifg=#455354 guibg=fg gui=none
hi StatusLineNC guifg=#808080 guibg=#080808
hi StorageClass guifg=#B6B7EB gui=none
hi Structure guifg=#66D9EF
hi Tag guifg=#92C5F7 gui=none
hi Title guifg=#B6B7EB gui=none
hi Todo guifg=#FFFFFF guibg=bg gui=none
hi Typedef guifg=#66D9EF
hi Type guifg=#66D9EF gui=none
hi Underlined guifg=#808080 gui=underline
hi VertSplit guifg=#808080 guibg=#080808
hi VisualNOS guibg=#403D3D
hi Visual guibg=#403D3D
hi WarningMsg guifg=#FFFFFF guibg=#333333
hi WildMenu guifg=#66D9EF guibg=#000000
hi TabLineFill guifg=#1D1F21 guibg=#1D1F21
hi TabLine guibg=#1D1F21 guifg=#808080 gui=none
hi Normal guifg=#F8F8F2 guibg=#1D1F21
hi Comment guifg=#7C7C7C
hi CursorLine guibg=#293739
hi CursorLineNr guifg=#B6B7EB gui=none
hi CursorColumn guibg=#293739
hi ColorColumn guifg=#B62323 guibg=#232526
hi LineNr guifg=#465457 guibg=#232526
hi NonText guifg=#465457
hi SpecialKey guifg=#465457
" Must be at the end, because of ctermbg=234 bug.
" https://groups.google.com/forum/#!msg/vim_dev/afPqwAFNdrU/nqh6tOM87QUJ
set background=dark

5
ctags.conf Normal file
View File

@ -0,0 +1,5 @@
--langdef=Go
--langmap=Go:.go
--regex-Go=/func([ \t]+[)]+)?[ \t]+([a-zA-Z0-9_]+)/\2/f,func/
--regex-Go=/var[ \t]+([a-zA-Z_][a-zA-Z0-9_]+)/\1/v,var/
--regex-Go=/type[ \t]+([a-zA-Z_][a-zA-Z0-9_]+)/\1/t,type/

1328
doc/NERDTree.txt Normal file

File diff suppressed because it is too large Load Diff

1238
doc/NERD_tree.txt Normal file

File diff suppressed because it is too large Load Diff

431
doc/asyncrun.txt Normal file
View File

@ -0,0 +1,431 @@
*asyncrun.txt* asyncrun.vim: Run Async Shell Commands in Vim 8.0 and Output to Quickfix Window
===============================================================================
Contents ~
1. Introduction |asyncrun-introduction|
2. Preface |asyncrun-43-preface|
3. News |asyncrun-44-news|
4. Install |asyncrun-45-install|
5. Example |asyncrun-46-example|
6. Tutorials |asyncrun-48-tutorials|
1. Async run gcc to compile current file |asyncrun-49-async-run-gcc-to-compile-current-file|
2. Async run make |asyncrun-50-async-run-make|
3. Grep key word |asyncrun-51-grep-key-word|
4. Compile go project |asyncrun-52-compile-go-project|
5. Lookup man page |asyncrun-53-lookup-man-page|
6. Git push |asyncrun-54-git-push|
7. Setup '<F7>' to compile file |F7|
7. Manual |asyncrun-56-manual|
1. AsyncRun - Run shell command |57-asyncrun-run-shell-command|
2. AsyncStop - Stop the running job |asyncrun-58-asyncstop-stop-running-job|
3. Settings: |asyncrun-59-settings|
4. Variables: |asyncrun-61-variables|
5. Requirements: |asyncrun-62-requirements|
6. Cooperate with vim-fugitive: |asyncrun-63-cooperate-with-vim-fugitive|
8. More |asyncrun-66-more|
9. Further |asyncrun-75-further|
10. History |asyncrun-77-history|
11. Credits |asyncrun-78-credits|
12. References |asyncrun-references|
===============================================================================
*asyncrun-introduction*
Introduction ~
Run Async Shell Commands in Vim 8.0 and Output to Quickfix Window
===============================================================================
*asyncrun-43-preface*
Preface ~
This plugin takes the advantage of new apis in Vim 8 (and NeoVim) to enable you
to run shell commands in background and read output in the quickfix window in
realtime:
- Easy to use, just start your background command by ':AsyncRun' (just like
old "!" cmd).
- Command is done in the background, no need to wait for the entire process
to finish.
- Output are displayed in the quickfix window, errors are matched with
'errorformat'.
- You can explore the error output immediately or keep working in vim while
executing.
- Ring the bell or play a sound to notify you job finished while you're
focusing on editing.
- Fast and lightweight, just a single self-contained 'asyncrun.vim' source
file.
- Provide corresponding user experience vim, neovim, gvim and macvim.
If that doesn't excite you, then perhaps this GIF screen capture below will
change your mind.
===============================================================================
*asyncrun-44-news*
News ~
- 2016/10/17 Glad to announce that 'asyncrun.vim' supports NeoVim now.
- 2016/10/15 'asyncrun.vim' can cooperate with 'vim-fugitive', see the bottom
of the README.
===============================================================================
*asyncrun-45-install*
Install ~
Copy 'asyncrun.vim' to your '~/.vim/plugin' or use Vundle to install it from
'skywind3000/asyncrun.vim' .
===============================================================================
*asyncrun-46-example*
Example ~
Image: [47]
===============================================================================
*asyncrun-48-tutorials*
Tutorials ~
-------------------------------------------------------------------------------
*asyncrun-49-async-run-gcc-to-compile-current-file*
Async run gcc to compile current file ~
>
:AsyncRun gcc % -o %<
:AsyncRun g++ -O3 "%" -o "%<" -lpthread
<
This command will run gcc in the background and output to the quickfix window
in realtime. Macro ''%'' stands for filename and ''%>'' represents filename
without extension.
-------------------------------------------------------------------------------
*asyncrun-50-async-run-make*
Async run make ~
>
:AsyncRun make
:AsyncRun make -f makefile
<
-------------------------------------------------------------------------------
*asyncrun-51-grep-key-word*
Grep key word ~
>
:AsyncRun! grep -R word .
:AsyncRun! grep -R <cword> .
<
when '!' is included, auto-scroll in quickfix will be disabled. '<cword>'
represents current word under cursor.
-------------------------------------------------------------------------------
*asyncrun-52-compile-go-project*
Compile go project ~
>
:AsyncRun go build "%:p:h"
<
Macro ''%:p:h'' stands for current file dir.
-------------------------------------------------------------------------------
*asyncrun-53-lookup-man-page*
Lookup man page ~
>
:AsyncRun! man -S 3:2:1 <cword>
<
-------------------------------------------------------------------------------
*asyncrun-54-git-push*
Git push ~
>
:AsyncRun git push origin master
<
-------------------------------------------------------------------------------
Setup '<*F7*>' to compile file
>
:noremap <F7> :AsyncRun gcc "%" -o "%<" <cr>
<
File name may contain spaces, therefore, it's safe to quote them.
===============================================================================
*asyncrun-56-manual*
Manual ~
There are two vim commands: ':AsyncRun' and ':AsyncStop' to control async jobs.
-------------------------------------------------------------------------------
*57-asyncrun-run-shell-command*
AsyncRun - Run shell command ~
>
:AsyncRun[!] [options] {cmd} ...
<
run shell command in background and output to quickfix. when '!' is included,
auto-scroll in quickfix will be disabled. Parameters are splited by space, if a
parameter contains space, it should be **quoted** or escaped as backslash +
space (unix only).
Parameters accept macros start with ''%'', ''#'' or ''<'' :
>
%:p - File name of current buffer with full path
%:t - File name of current buffer without path
%:p:h - File path of current buffer without file name
%:e - File extension of current buffer
%:t:r - File name of current buffer without path and extension
% - File name relativize to current directory
%:h:. - File path relativize to current directory
<cwd> - Current directory
<cword> - Current word under cursor
<cfile> - Current file name under cursor
<
Environment variables are set before executing:
>
$VIM_FILEPATH - File name of current buffer with full path
$VIM_FILENAME - File name of current buffer without path
$VIM_FILEDIR - Full path of current buffer without the file name
$VIM_FILEEXT - File extension of current buffer
$VIM_FILENOEXT - File name of current buffer without path and extension
$VIM_CWD - Current directory
$VIM_RELDIR - File path relativize to current directory
$VIM_RELNAME - File name relativize to current directory
$VIM_CWORD - Current word under cursor
$VIM_CFILE - Current filename under cursor
$VIM_GUI - Is running under gui ?
$VIM_VERSION - Value of v:version
$VIM_COLUMNS - How many columns in vim's screen
$VIM_LINES - How many lines in vim's screen
$VIM_SVRNAME - Value of v:servername for +clientserver usage
<
These environment variables wrapped by '$(...)' (eg. '$(VIM_FILENAME)') will
also be expanded in the parameters.
There can be some options before your '[cmd]':
>
-mode=0/1/2 - start mode: 0(async, default), 1(:make), 2(:!)
-cwd=? - initial directory, (use current directory if unset)
-save=0/1 - non-zero to save unsaved files before executing
-program=? - set to `make` to use `&makeprg`, `grep` to use `&grepprg`
-post=? - vimscript to exec after this job finished, spaces **must** be escaped to '\ '
<
All options must start with a minus and position **before** '[cmd]'. Since no
shell command string starts with a minus. So they can be distinguished from
shell command easily without any ambiguity.
Don't worry if you do have a shell command starting with '-', Just put a
placeholder '@' before your command to tell asyncrun explicitly: "stop parsing
options now, the following string is all my command".
-------------------------------------------------------------------------------
*asyncrun-58-asyncstop-stop-running-job*
AsyncStop - Stop the running job ~
>
:AsyncStop[!]
<
stop the running job, when "!" is included, job will be stopped by signal KILL
-------------------------------------------------------------------------------
*asyncrun-59-settings*
Settings: ~
- g:asyncrun_exit - script will be executed after finished
- g:asyncrun_bell - non-zero to ring a bell after finished
- g:asyncrun_mode - 0:async(require vim 7.4.1829) 1:sync 2:shell
- g:asyncrun_encs - set shell encoding if it's different from '&encoding',
see here [60]
- g:asyncrun_trim - non-zero to trim the empty lines in the quickfix window.
-------------------------------------------------------------------------------
*asyncrun-61-variables*
Variables: ~
- g:asyncrun_code - exit code
- g:asyncrun_status - 'running', 'success' or 'failure'
-------------------------------------------------------------------------------
*asyncrun-62-requirements*
Requirements: ~
Vim 7.4.1829 is minimal version to support async mode. If you are use older
versions, 'g:asyncrun_mode' will fall back from '0/async' to '1/sync'. NeoVim
0.1.4 or later is also supported.
Recommend to use Vim 8.0 or later.
-------------------------------------------------------------------------------
*asyncrun-63-cooperate-with-vim-fugitive*
Cooperate with vim-fugitive: ~
asyncrun.vim can cooperate with 'vim-fugitive', see here [64].
Image: [65]
===============================================================================
*asyncrun-66-more*
More ~
- Additional examples (background ctags updating, pdf conversion, ...) [67]
- Notify user job finished by playing a sound [68]
- View progress in status line or vim airline [69]
- Best practice with quickfix windows [70]
- Scroll the quickfix window only if the cursor is on the last line [71]
- Cooperate with vim-fugitive [64]
- Replace old ':make' command with asyncrun [72]
- Quickfix encoding problem when using Chinese or Japanese [60]
- Example for updating and adding cscope files [73]
Don't forget to read the Frequently Asked Questions [74].
===============================================================================
*asyncrun-75-further*
Further ~
- Experiment: get netrw using asyncrun to save remote files [76]
===============================================================================
*asyncrun-77-history*
History ~
- 1.3.3 (2016-10-28): prevent job who reads stdin getting hanging, fixed an
issue in fast exiting jobs.
- 1.3.2 (2016-10-19): new "-post" option to run a vimscript after the job
finished
- 1.3.1 (2016-10-18): fixed few issues of arguments passing in different
modes
- 1.3.0 (2016-10-17): add support to neovim, better CJK characters handling.
- 1.2.0 (2016-10-16): refactor, correct arguments parsing, cmd options and
&makeprg supports
- 1.1.1 (2016-10-13): use the vim native &shell and &shellcmdflag config to
execute commands.
- 1.1.0 (2016-10-12): quickfix window scroll only if cursor is on the last
line
- 1.0.3 (2016-10-10): reduce quickfix output latency.
- 1.0.2 (2016-10-09): fixed an issue in replacing macros in parameters.
- 1.0.1 (2016-10-07): Add a convenient way to toggle quickfix window
(asyncrun#quickfix_toggle)
- 1.0.0 (2016-09-21): can fall back to sync mode to compatible older vim
versions.
- 0.0.3 (2016-09-15): new arguments now accept environment variables wrapped
by $(...)
- 0.0.2 (2016-09-12): some improvements and more documents for a tiny
tutorial.
- 0.0.1 (2016-09-08): improve arguments parsing
- 0.0.0 (2016-08-24): initial version
===============================================================================
*asyncrun-78-credits*
Credits ~
Trying best to provide the most simply and convenience experience in the
asynchronous-jobs.
Author: skywind3000 Please vote it if you like it:
http://www.vim.org/scripts/script.php?script_id=5431
===============================================================================
*asyncrun-references*
References ~
[1] https://github.com/skywind3000/asyncrun.vim#start-of-content
[2] https://github.com/
[3] https://github.com/personal
[4] https://github.com/open-source
[5] https://github.com/business
[6] https://github.com/explore
[7] https://github.com/join?source=header-repo
[8] https://github.com/login?return_to=%2Fskywind3000%2Fasyncrun.vim
[9] https://github.com/pricing
[10] https://github.com/blog
[11] https://help.github.com
[12] https://github.com/search
[13] https://github.com/skywind3000/asyncrun.vim/watchers
[14] https://github.com/skywind3000/asyncrun.vim/stargazers
[15] https://github.com/skywind3000/asyncrun.vim/network
[16] https://github.com/skywind3000/asyncrun.vim
[17] https://github.com/skywind3000/asyncrun.vim/issues
[18] https://github.com/skywind3000/asyncrun.vim/pulls
[19] https://github.com/skywind3000/asyncrun.vim/projects
[20] https://github.com/skywind3000/asyncrun.vim/wiki
[21] https://github.com/skywind3000/asyncrun.vim/pulse
[22] https://github.com/skywind3000/asyncrun.vim/graphs
[23] https://github.com/skywind3000/asyncrun.vim/commits/master
[24] https://github.com/skywind3000/asyncrun.vim/branches
[25] https://github.com/skywind3000/asyncrun.vim/releases
[26] https://github.com/skywind3000/asyncrun.vim/graphs/contributors
[27] https://github.com/skywind3000/asyncrun.vim/blob/master/LICENSE
[28] https://github.com/skywind3000/asyncrun.vim/search?l=vim
[29] https://help.github.com/articles/which-remote-url-should-i-use
[30] https://github.com/skywind3000/asyncrun.vim/archive/master.zip
[31] https://github.com/skywind3000/asyncrun.vim/find/master
[32] https://github.com/skywind3000/asyncrun.vim/tree/master
[33] https://github.com/skywind3000/asyncrun.vim/commit/1edc42699bcb8a1b17398c2590a27636e327531d
[34] https://camo.githubusercontent.com/a08cc422099cb8fd2a030bc7e6da7732e483e336/68747470733a2f2f322e67726176617461722e636f6d2f6176617461722f33313761636661306235663764643563623831363331303365326266623366363f643d68747470732533412532462532466173736574732d63646e2e6769746875622e636f6d253246696d6167657325324667726176617461727325324667726176617461722d757365722d3432302e706e6726723d7826733d313430
[35] https://github.com/skywind3000/asyncrun.vim/tree/1edc42699bcb8a1b17398c2590a27636e327531d
[36] https://assets-cdn.github.com/images/spinners/octocat-spinner-32.gif
[37] https://github.com/skywind3000/asyncrun.vim/tree/master/doc
[38] https://github.com/skywind3000/asyncrun.vim/commit/7b906e89f42b811176007a52a8affdfd11c76a93
[39] https://github.com/skywind3000/asyncrun.vim/tree/master/plugin
[40] https://github.com/skywind3000/asyncrun.vim/commit/c9bb3b9a1909a7e3bcc53817cefa94460cd4a85e
[41] https://github.com/skywind3000/asyncrun.vim/commit/e4f207983822abb58df9f3577cf0b3fbacdf0231
[42] https://github.com/skywind3000/asyncrun.vim/blob/master/README.md
[43] https://github.com/skywind3000/asyncrun.vim#preface
[44] https://github.com/skywind3000/asyncrun.vim#news
[45] https://github.com/skywind3000/asyncrun.vim#install
[46] https://github.com/skywind3000/asyncrun.vim#example
[47] https://raw.githubusercontent.com/skywind3000/asyncrun.vim/master/doc/screenshot.gif
[48] https://github.com/skywind3000/asyncrun.vim#tutorials
[49] https://github.com/skywind3000/asyncrun.vim#async-run-gcc-to-compile-current-file
[50] https://github.com/skywind3000/asyncrun.vim#async-run-make
[51] https://github.com/skywind3000/asyncrun.vim#grep-key-word
[52] https://github.com/skywind3000/asyncrun.vim#compile-go-project
[53] https://github.com/skywind3000/asyncrun.vim#lookup-man-page
[54] https://github.com/skywind3000/asyncrun.vim#git-push
[55] https://github.com/skywind3000/asyncrun.vim#setup-f7-to-compile-file
[56] https://github.com/skywind3000/asyncrun.vim#manual
[57] https://github.com/skywind3000/asyncrun.vim#asyncrun---run-shell-command
[58] https://github.com/skywind3000/asyncrun.vim#asyncstop---stop-the-running-job
[59] https://github.com/skywind3000/asyncrun.vim#settings
[60] https://github.com/skywind3000/asyncrun.vim/wiki/Quickfix-encoding-problem-when-using-Chinese-or-Japanese
[61] https://github.com/skywind3000/asyncrun.vim#variables
[62] https://github.com/skywind3000/asyncrun.vim#requirements
[63] https://github.com/skywind3000/asyncrun.vim#cooperate-with-vim-fugitive
[64] https://github.com/skywind3000/asyncrun.vim/wiki/Cooperate-with-vim-fugitive
[65] https://raw.githubusercontent.com/skywind3000/asyncrun.vim/master/doc/cooperate_with_fugitive.gif
[66] https://github.com/skywind3000/asyncrun.vim#more
[67] https://github.com/skywind3000/asyncrun.vim/wiki/Additional-Examples
[68] https://github.com/skywind3000/asyncrun.vim/wiki/Playing-Sound
[69] https://github.com/skywind3000/asyncrun.vim/wiki/Display-Progress-in-Status-Line-or-Airline
[70] https://github.com/skywind3000/asyncrun.vim/wiki/Quickfix-Best-Practice
[71] https://github.com/skywind3000/asyncrun.vim/wiki/Scroll-the-quickfix-window-only-if-cursor-is-on-the-last-line
[72] https://github.com/skywind3000/asyncrun.vim/wiki/Replace-old-make-command-with-AsyncRun
[73] https://github.com/skywind3000/asyncrun.vim/wiki/Example-for-updating-and-adding-cscope
[74] https://github.com/skywind3000/asyncrun.vim/wiki/FAQ
[75] https://github.com/skywind3000/asyncrun.vim#further
[76] https://github.com/skywind3000/asyncrun.vim/wiki/Get-netrw-using-asyncrun-to-save-remote-files
[77] https://github.com/skywind3000/asyncrun.vim#history
[78] https://github.com/skywind3000/asyncrun.vim#credits
[79] https://github.com/contact
[80] https://developer.github.com
[81] https://training.github.com
[82] https://shop.github.com
[83] https://github.com/about
[84] https://github.com
[85] https://github.com/site/terms
[86] https://github.com/site/privacy
[87] https://github.com/security
[88] https://status.github.com/
vim: ft=help

335
doc/buffergator.txt Normal file
View File

@ -0,0 +1,335 @@
*buffergator.txt* Buffer indexing and navigation plugin.
===============================================================================
*buffergator* *buffergator-contents*
CONTENTS~
1. Introduction ........................... |buffergator-introduction|
2. Commands ............................... |buffergator-commands|
3. Key Mappings (Global) .................. |buffergator-global-keys|
4. Key Mappings (Buffer Catalog) .......... |buffergator-buffer-keys|
5. Key Mappings (Tab Page Catalog) ........ |buffergator-tabpage-keys|
6. Options and Settings ................... |buffergator-options|
===============================================================================
*buffergator-introduction*
INTRODUCTION~
Buffergator is a plugin for listing, navigating between, and selecting buffers
to edit. Upon invocation (using the command, ":BuffergatorOpen" or
"BuffergatorToggle", or the provided key mapping, "<Leader>b"), a "catalog" of
listed buffers are displayed in a separate new window split (vertical or
horizontal, based on user options; default = vertical). From this "buffer
catalog", a buffer can be selected and opened in an existing window, a new
window split (vertical or horizontal), or a new tab page.
Selected buffers can be "previewed", i.e. opened in a window or tab page, but
with focus remaining in the buffer catalog. Even better, you can "walk" up and
down the list of buffers shown in the catalog by using <C-N> (or <SPACE>) /
<C-P> (or <C-SPACE>). These keys select the next/previous buffer in succession,
respectively, opening it for preview without leaving the buffer catalog
viewer.
Buffergator also provides a way to list tab pages and buffers associated with
windows in tab pages (the "tab page catalog", which can be invoked using the
command ":BuffergatorTabsOpen" or the provided key mapping, "<Leader>to").
By default, Buffergator provides global key maps that invoke its main
commands: "<Leader>b" to open and "<Leader>B" to close the buffer catalog, and
"<Leader>to" to open and "<Leader>tc" to close the tab page catalog. If you
prefer to map other keys, or do not want any keys mapped at all, set
"g:buffergator_suppress_keymaps" to 1 in your $VIMRUNTIME.
===============================================================================
*buffergator-commands*
COMMANDS~
These following commands are provided globally by Buffergator:
:BuffergatorOpen
Open the buffer catalog, or go to it if it is already open.
:BuffergatorClose
Close the buffer catalog if it is already open.
:BuffergatorToggle
Open the buffer catalog if it is closed, or close it if
it is already open.
:BuffergatorTabsOpen
Open the tab page catalog, or go to it if it is already open.
:BuffergatorTabsClose
Close the tab page catalog if it is already open.
:BuffergatorTabsToggle
Open the tab page catalog if it is closed, or close it if
it is already open.
===============================================================================
*buffergator-global-keys*
KEY MAPPINGS (GLOBAL)~
Unless "g:buffergator_suppress_keymaps" is set to 1, then the following
key mappings are defined:
<Leader>b Invokes ":BuffergatorOpen": open the buffer catalog, or go
to it if it is already open.
<Leader>B Invokes ":BuffergatorClose": close the buffer catalog.
<Leader>to Invokes ":BuffergatorTabsOpen": open the tab page catalog,
or go to it if it is already open.
<Leader>tc Invokes ":BuffergatorTabsClose": close the tab page
catalog.
[b, <M-B> Invokes ":BuffergatorMruCyclePrev": cycle to an older
buffer in the most-recently used (MRU) buffer list.
most-recently used buffer. If
"g:buffergator_mru_cycle_loop" is set to 1 (default), then
this will loop, i.e. returning to the initial buffer after
reaching the oldest buffer.
]b, <M-S-B> Invokes ":BuffergatorMruCycleNext": cycle to a newer
buffer in the most-recently used (MRU) buffer list.
most-recently used buffer. If
"g:buffergator_mru_cycle_loop" is set to 1 (default), then
this will loop, i.e. returning to the oldest buffer after
reaching the newest buffer.
===============================================================================
*buffergator-buffer-keys*
KEY MAPPINGS (BUFFER CATALOG)~
Invoking Buffergator results in the listed buffers being displayed in a
special Buffergator window, which is referred to as a "buffer catalog viewer".
The following key mappings are available when in the viewer.
-------------------------------------------------------------------------------
Catalog Management~
cs Cycle through sort regimes.
cd Cycle through display regimes.
cp Toggle showing full paths (only "basename" display regime)
cw Cycle through window (viewport) split modes.
cq Cycle through quit (autodismiss-on-select) policies.
r Update (rebuild/refresh) index.
d Delete the selected buffer.
D Unconditionally delete the selected buffer.
x Wipe the selected buffer.
X Unconditionally wipe the selected buffer.
q Quit the index/catalog window.
-------------------------------------------------------------------------------
Open Selected Buffer~
The following keys all open the currently-selected buffer and switch focus to
it. If the key presses are preceded by a number, then the buffer with that
number will be selected and opened instead of the current buffer. The catalog
buffer will be closed if 'g:buffergator_autodismiss_on_select' evaluates to
true; otherwise it will be kept open.
<CR>, o Open the currently-selected buffer (or, if [count] is
given, buffer with number [count]), in previous window.
s Open the currently-selected buffer (or, if [count] is
given, buffer with number [count]), in a new vertical
split.
<C-V> As above (compatibility with Ctrl-P/Command-T)
i Open the currently-selected buffer (or, if [count] is
given, buffer with number [count]), in a new split.
<C-S> As above (compatibility with Ctrl-P/Command-T)
t Open the currently-selected buffer (or, if [count] is
given, buffer with number [count]), in a new tab page.
<C-T> As above (compatibility with Ctrl-P/Command-T)
-------------------------------------------------------------------------------
Preview Selected Buffer~
The following keys all open the currently-selected buffer, but retain focus on
the catalog viewer. If the key presses are preceded by a number, than the
buffer with that number will be opened.
O, go Preview the currently-selected buffer (or, if [count] is
given, buffer with number [count]), in the previous
window.
S, gs Preview the currently-selected buffer (or, if [count] is
given, buffer with number [count]), is a new vertical
split.
I, gi Preview the currently-selected buffer (or, if [count] is
given, buffer with number [count]), in a new split
T Preview the currently-selected buffer (or, if [count] is
given, buffer with number [count]), in a new tab
page.
<SPACE>, <C-N> Go to the next buffer entry (or, if [count] is
given, buffer with number [count]), and preview it in the
previous window.
<C-SPACE>, <C-P> Go to the previous buffer entry (or, if [count] is
given, buffer with number [count]), and preview it in the
previous window.
-------------------------------------------------------------------------------
Open and Switch Focus to Selected Buffer~
The following keys all open the currently-selected buffer and switch focus to
it, keeping the catalog viewe open, regardless of the
'g:buffergator_autodismiss_on_select' setting. If the key presses are preceded
by a number, than the buffer with that number will be opened.
po Open the currently-selected buffer (or, if [count] is
given, buffer with number [count]), in the previous
window, and switch focus to it, keeping the catalog
viewer open.
ps Open the currently-selected buffer (or, if [count] is
given, buffer with number [count]), is a new vertical
split, and switch focus to it, keeping the catalog
viewer open.
pi Open the currently-selected buffer (or, if [count] is
given, buffer with number [count]), in a new split,
and switch focus to it, keeping the catalog
viewer open.
-------------------------------------------------------------------------------
Go to Existing Viewport Showing Buffer~
The following keys will try to find the selected buffer in an existing
viewport (whether on the current tab page or another). If the key presses are
preceded by a number, then the buffer with that number will be the target
buffer.
eo If currently-selected buffer (or, if [count] is
given, buffer with number [count]), is showing in an existing
viewport on this or any other tab page, go to it;
otherwise show it in the previous window.
es If currently-selected buffer (or, if [count] is
given, buffer with number [count]), is showing in an existing
viewport on this or any other tab page, go to it;
otherwise show it in a new vertical split.
ei If currently-selected buffer (or, if [count] is
given, buffer with number [count]), is showing in an existing
viewport on this or any other tab page, go to it;
otherwise show it in a new horizontal split.
et If currently-selected buffer (or, if [count] is
given, buffer with number [count]), is showing in an existing
viewport on this or any other tab page, go to it;
otherwise show it in a new tab page.
E If currently-selected buffer (or, if [count] is
given, buffer with number [count]), is showing in an existing
viewport on this or any other tab page, go to it;
otherwise do nothing.
-------------------------------------------------------------------------------
Window Control~
A Zoom/unzoom window, expanding to full height (if
horizontally split) or full width (if vertically split)
===============================================================================
*buffergator-tabpage-keys*
KEY MAPPINGS (TAB PAGE CATALOG)~
-------------------------------------------------------------------------------
Catalog Management~
cd Cycle through display regimes.
r Update (rebuild/refresh) index.
q Quit the index/catalog window.
-------------------------------------------------------------------------------
Open Selected Tab Page or Tab Page Window~
The following keys all open the currently-selected tab page or window.
<CR>, o Open the currently-selected tab page or window.
<SPACE> Select the next tab page entry.
<C-SPACE> Select the previous tab page entry.
<C-N> Select the next tab page window entry.
<C-P> Select the previous tab page window entry.
-------------------------------------------------------------------------------
Window Control~
A Zoom/unzoom window, expanding to full height (if
horizontally split) or full width (if vertically split)
===============================================================================
*buffergator-options*
OPTIONS AND SETTINGS~
The following options can be used to customize the behavior of this plugin:
g:buffergator_viewport_split_policy~
Default: "L"
Determines how a new Buffergator window will be opened. Can be one of the
following values:
"L" : vertical left (full screen height)
"R" : vertical right (full screen height)
"T" : horizontal top (full screen width)
"B" : horizontal bottom (full screen width)
g:buffergator_autodismiss_on_select~
Default: 1
If true, then selection an entry with <CR> will close the catalog. Otherwise,
catalog stays open. Default is 1.
g:buffergator_autoexpand_on_split~
Default: 1
If true and running in GUI mode, then the application screen will be expanded
to accommodate the Buffergator window.
g:buffergator_autoupdate~
Default: 0
If true, then the Buffergator window will be updated when the buffer list
changes.
g:buffergator_split_size~
Default: 40
If greater than 0, this will be the width of the Buffergator window in any
vertical splitting mode, or its height in any horizontal splitting mode.
g:buffergator_vsplit_size~
Default: 40
If greater than 0, this will be the width of the Buffergator window in
any vertical splitting mode.
g:buffergator_hsplit_size~
Default: 20
If greater than 0, this will be the height of the Buffergator window in
any horizontal splitting mode.
g:buffergator_sort_regime~
Default: "bufnum"
Sets the default sort regime for buffer listing:
"bufnum" : sort by buffer number [default]
"basename": sort by buffer file basename (followed by directory)
"filepath": sort by full buffer filepath
"extension": sort by buffer filename extension (followed by full
filepath)
"mru": sort by most recently used
g:buffergator_display_regime~
Default: "basename"
Sets the default display regime for buffer listing:
"basename": display buffer basename first,
followed by directory [default]
"filepath": display full buffer filepath
"bufname": display buffer name
g:buffergator_show_full_directory_path~
Default: 1
If true, then show the full path of each buffer. Otherwise, show the
relative path.
Only relevant when the display regime is "basename".
g:buffergator_suppress_keymaps~
Default: 0
If true, then Buffergator will not automatically map "<Leader>b" to
open the Buffergator catalog and "<Leader>B" to close it.
g:buffergator_mru_cycle_local_to_window~
Default: 1
If true, then the most recently used list will include only buffers
within the window. Otherwise, it will incude all buffers.
vim:tw=78:ts=8:ft=help:norl:

View File

@ -0,0 +1 @@
setlocal omnifunc=gocomplete#Complete

430
gvimrc Normal file
View File

@ -0,0 +1,430 @@
"----------------------------------------------------------------
" New Filetypes
""""""""""""""""""""""""
au BufNewFile,BufRead *.h setf c
"----------------------------------------------------------------
" Common
""""""""""""""""""""""""
set fileencodings=utf-8,gb18030 " 兼容txt
set nocompatible " 关闭 vi 兼容模式
syntax on " 自动语法高亮
colorscheme atom-dark-256 " 设定配色方案
set number " 显示行号
"set number relativenumber " 显示相对行号
set cursorline " 突出显示当前行
set ruler " 打开状态栏标尺
set tabstop=4 " 设定 tab 长度为 4
set softtabstop=4 " 使得按退格键时可以一次删掉 4 个空格
set shiftwidth=4 " 设定 > 命令移动时的宽度为 4
set expandtab
set nobackup " 覆盖文件时不备份
set autochdir " 自动切换当前目录为当前文件所在的目录
filetype plugin indent on " 开启插件
set smartindent " 开启新行时使用智能自动缩进
set backupcopy=yes " 设置备份时的行为为覆盖
set ignorecase smartcase " 搜索时忽略大小写,但在有一个或以上大写字母时仍保持对大小写敏感
set nowrapscan " 禁止在搜索到文件两端时重新搜索
set incsearch " 输入搜索内容时就显示搜索结果
set hlsearch " 搜索时高亮显示被找到的文本
set noerrorbells " 关闭错误信息响铃
set novisualbell " 关闭使用可视响铃代替呼叫
set t_vb= " 置空错误铃声的终端代码
"set showmatch " 插入括号时,短暂地跳转到匹配的对应括号
"set matchtime=1 " 短暂跳转到匹配括号的时间
set magic " 设置魔术
set hidden " 允许在有未保存的修改时切换缓冲区,此时的修改由 vim 负责保存
set backspace=indent,eol,start " 不设定在插入状态无法用退格键和 Delete 键删除回车符
set laststatus=2 " 显示状态栏 (默认值为 1, 无法显示状态栏)
set cmdheight=1 " 设定状态栏命令行的行数为 1
"set showtabline=2 " 显示标签栏
"set mouse=a " 开启鼠标模式
set guifont=YaHei\ Consolas\ Hybrid\ 12
set guioptions-=T " 隐藏工具栏
set guioptions-=m " 隐藏菜单栏
set guioptions-=L " 隐藏左侧滚动条
set guioptions-=r " 隐藏右侧滚动条
"----------------------------------------------------------------
"Status Line
""""""""""""""""""""""""
set statusline=%F " 文件的路径
set statusline+=%= " 切换到右边
set statusline+=%{&fileencoding} " 文件的编码
set statusline+=\ " 分隔符
set statusline+=%c " 当前列
set statusline+=\, " 分隔符
set statusline+=%l " 当前行
set statusline+=/ " 分隔符
set statusline+=%L " 总行数
set statusline+=\ " 分隔符
set statusline+=%P " 当前位置
"----------------------------------------------------------------
" Vim Shotcuts
""""""""""""""""""""""""
inoremap <F3> <Esc>:NERDTreeToggle<CR>
nnoremap <F3> :NERDTreeToggle<CR>
nnoremap <C-w><C-n> :tabp<CR>
nnoremap <C-w>n :tabn<CR>
nnoremap <C-w><C-l> :vertical resize +2<CR>
nnoremap <C-w><C-h> :vertical resize -2<CR>
nnoremap <C-w><C-j> :resize +2<CR>
nnoremap <C-w><C-k> :resize -2<CR>
au Syntax python set makeprg=python3\ -u\ %\
au Syntax go set makeprg=go\ install\
au Syntax rust set makeprg=rustc\ %\
au Syntax lua set makeprg=lua5.1\ %\
au Syntax sh set makeprg=bash\ %\
au Syntax c,python,go,rust,lua,sh nnoremap <F7> :execute "normal! ".QuickFix()<CR>
au Syntax c,go,rust nnoremap e :cn<CR>
au Syntax c,go,rust nnoremap E :cp<CR>
au Syntax go nnoremap H :!go doc <cword><CR>
au Syntax python nnoremap H :!pydoc3 <cword><CR>
"----------------------------------------------------------------
" Fold
""""""""""""""""""""""""
set fdm=marker
set foldmarker=<<FOLD<<,>>FOLD>>
nnoremap <space> @=((foldclosed(line('.')) < 0) ? 'zc' : 'zo')<CR>
"----------------------------------------------------------------
" Complement
""""""""""""""""""""""""
" HTML
au Syntax html,css,javascript,xml inoremap ><space> ><Esc>%lyiwh%a</<Esc>pa><Esc>%i
au Syntax html,css,javascript,xml inoremap ><CR> ><Esc>%lyiwo</<Esc>pa><Esc>^d0k^y0j0Pk$
au Syntax html,css,javascript,xml inoremap {<CR> <Esc>:s/ *$//g<CR>:nohls<CR>A {<CR><BS>}<ESC>O
au Syntax html,css,javascript,xml inoremap ;<CR> <Esc>A;<CR>
" PHP
au Syntax php inoremap ><space> ><Esc>%lyiwh%a</<Esc>pa><Esc>%i
au Syntax php inoremap ><CR> ><Esc>%lyiwo</<Esc>pa><Esc>^d0k^y0j0Pk$
au Syntax php inoremap >p <?php ?><Esc>2hi
au Syntax php inoremap >P <?php<CR>?><Esc>O
au Syntax php inoremap #I include '';<Esc>hi
au Syntax php inoremap #R require '';<Esc>hi
au Syntax php inoremap ;<CR> <Esc>A;<CR>
" SQL
au Syntax sql,plsql inoremap #I IF THEN<CR>END IF;<ESC>khhhi
au Syntax sql,plsql inoremap #C CASE <CR>WHEN THEN<CR>ELSE<CR>END CASE;<ESC>kkkA
au Syntax sql,plsql inoremap #L LOOP<CR>END LOOP;<ESC>O
au Syntax sql,plsql inoremap #P DBMS_OUTPUT.PUT_LINE();<ESC>hi
au Syntax sql,plsql inoremap ;<CR> <Esc>A;<CR>
" C
au Syntax c inoremap #< #include<><Esc>i
au Syntax c inoremap #" #include ""<Esc>i
au Syntax c inoremap #M int main(int argc,char *argv[]){<CR>return 0;<CR>}<Esc>kO
au Syntax c inoremap {<CR> <Esc>:s/ *$//g<CR>:nohls<CR>A{<CR>}<ESC>O
au Syntax c inoremap ;<CR> <Esc>A;<CR>
" GO
au Syntax go inoremap {<CR> <Esc>:s/ *$//g<CR>:nohls<CR>A {<CR><BS>}<ESC>O
au Syntax go inoremap {<space> {<CR><BS>}<ESC>O
au Syntax go inoremap (<CR> <Esc>:s/ *$//g<CR>:nohls<CR>A (<CR>)<ESC>O
au Syntax go inoremap ;<CR> <Esc>A;<CR>
" RUST
au Syntax rust inoremap {<CR> <Esc>:s/ *$//g<CR>:nohls<CR>A {<CR><BS>}<ESC>O
au Syntax rust inoremap ;<CR> <Esc>A;<CR>
" SH
au Syntax sh inoremap {<CR> <Esc>:s/ *$//g<CR>:nohls<CR>A {<CR><BS>}<ESC>O
" PYTHON
au Syntax python inoremap :<CR> <C-r>=PythonColon()<CR>
" LUA
au Syntax lua inoremap #fu function ()<CR>end<Esc>Oreturn <Esc>k$F(i
au Syntax lua inoremap #if if then<CR>end<Esc>k$F i
au Syntax lua inoremap #fo for do<CR>end<Esc>k$F i
au Syntax lua inoremap #wh while do<CR>end<Esc>k$F i
"----------------------------------------------------------------
" Operators
""""""""""""""""""""""""
" PHP
au Syntax php inoremap .= <space>.=<space>
au Syntax php inoremap === <space>===<space>
au Syntax php inoremap !== <space>!==<space>
au Syntax php inoremap <= <space><=<space>
au Syntax php inoremap >= <space>>=<space>
au Syntax php inoremap != <space>!=<space>
au Syntax php inoremap \|\| <space>\|\|<space>
au Syntax php inoremap == <space>==<space>
au Syntax php inoremap += <space>+=<space>
au Syntax php inoremap -= <space>-=<space>
au Syntax php inoremap *= <space>*=<space>
au Syntax php inoremap /= <space>/=<space>
au Syntax php inoremap && <space>&&<space>
" C
au Syntax c inoremap <= <space><=<space>
au Syntax c inoremap >= <space>>=<space>
au Syntax c inoremap != <space>!=<space>
au Syntax c inoremap \|\| <space>\|\|<space>
au Syntax c inoremap == <space>==<space>
au Syntax c inoremap += <space>+=<space>
au Syntax c inoremap -= <space>-=<space>
au Syntax c inoremap *= <space>*=<space>
au Syntax c inoremap /= <space>/=<space>
au Syntax c inoremap &= <space>&=<space>
au Syntax c inoremap \|= <space>\|=<space>
au Syntax c inoremap ~= <space>~=<space>
au Syntax c inoremap ^= <space>^=<space>
au Syntax c inoremap && <space>&&<space>
au Syntax c inoremap -> <space>-><space>
au Syntax c inoremap >> <space>>><space>
au Syntax c inoremap << <space><<<space>
" GO
au Syntax go inoremap := <space>:=<space>
au Syntax go inoremap <= <space><=<space>
au Syntax go inoremap >= <space>>=<space>
au Syntax go inoremap != <space>!=<space>
au Syntax go inoremap \|\| <space>\|\|<space>
au Syntax go inoremap == <space>==<space>
au Syntax go inoremap += <space>+=<space>
au Syntax go inoremap -= <space>-=<space>
au Syntax go inoremap *= <space>*=<space>
au Syntax go inoremap /= <space>/=<space>
au Syntax go inoremap &= <space>&=<space>
au Syntax go inoremap \|= <space>\|=<space>
au Syntax go inoremap ~= <space>~=<space>
au Syntax go inoremap ^= <space>^=<space>
au Syntax go inoremap && <space>&&<space>
au Syntax go inoremap -> <space>-><space>
au Syntax go inoremap >> <space>>><space>
au Syntax go inoremap << <space><<<space>
" RUST
au Syntax rust inoremap <= <space><=<space>
au Syntax rust inoremap >= <space>>=<space>
au Syntax rust inoremap != <space>!=<space>
au Syntax rust inoremap \|\| <space>\|\|<space>
au Syntax rust inoremap == <space>==<space>
au Syntax rust inoremap += <space>+=<space>
au Syntax rust inoremap -= <space>-=<space>
au Syntax rust inoremap *= <space>*=<space>
au Syntax rust inoremap /= <space>/=<space>
au Syntax rust inoremap &= <space>&=<space>
au Syntax rust inoremap \|= <space>\|=<space>
au Syntax rust inoremap ~= <space>~=<space>
au Syntax rust inoremap ^= <space>^=<space>
au Syntax rust inoremap && <space>&&<space>
au Syntax rust inoremap -> <space>-><space>
au Syntax rust inoremap >> <space>>><space>
au Syntax rust inoremap << <space><<<space>
" PYTHON
au Syntax python inoremap <= <space><=<space>
au Syntax python inoremap >= <space>>=<space>
au Syntax python inoremap != <space>!=<space>
au Syntax python inoremap \|\| <space>\|\|<space>
au Syntax python inoremap == <space>==<space>
au Syntax python inoremap += <space>+=<space>
au Syntax python inoremap -= <space>-=<space>
au Syntax python inoremap *= <space>*=<space>
au Syntax python inoremap /= <space>/=<space>
au Syntax python inoremap &= <space>&=<space>
au Syntax python inoremap \|= <space>\|=<space>
au Syntax python inoremap ~= <space>~=<space>
au Syntax python inoremap ^= <space>^=<space>
au Syntax python inoremap && <space>&&<space>
" LUA
au Syntax lua inoremap <= <space><=<space>
au Syntax lua inoremap >= <space>>=<space>
au Syntax lua inoremap != <space>!=<space>
au Syntax lua inoremap \|\| <space>\|\|<space>
au Syntax lua inoremap == <space>==<space>
au Syntax lua inoremap += <space>+=<space>
au Syntax lua inoremap -= <space>-=<space>
au Syntax lua inoremap *= <space>*=<space>
au Syntax lua inoremap /= <space>/=<space>
au Syntax lua inoremap &= <space>&=<space>
au Syntax lua inoremap \|= <space>\|=<space>
au Syntax lua inoremap ~= <space>~=<space>
au Syntax lua inoremap ^= <space>^=<space>
au Syntax lua inoremap && <space>&&<space>
" SQL
au Syntax sql,plsql inoremap := <space>:=<space>
au Syntax sql,plsql inoremap <= <space><=<space>
au Syntax sql,plsql inoremap >= <space>>=<space>
au Syntax sql,plsql inoremap != <space>!=<space>
au Syntax sql,plsql inoremap \|\| <space>\|\|<space>
"----------------------------------------------------------------
" Comments
""""""""""""""""""""""""
" Html
au Syntax html nnoremap - V
au Syntax html vnoremap - <Esc>:call setpos(".",[0,line("'<"),0,0])<CR>I<!--<Esc>:call setpos(".",[0,line("'>"),0,0])<CR>A--><Esc>
au Syntax html nnoremap == $?<!--<CR>4x/--><CR>3x:nohls<CR>
" Sql
au Syntax sql,plsql nnoremap - 0<C-v>
au Syntax sql,plsql nnoremap = 0<C-v>
au Syntax sql,plsql vnoremap - I--<Esc>
au Syntax sql,plsql vnoremap = :s:--::<CR>:nohls<CR>0
" C
au Syntax c nnoremap - 0<C-v>
au Syntax c nnoremap = 0<C-v>
au Syntax c vnoremap - I//<Esc>
au Syntax c vnoremap = :s://::<CR><CR>:nohls<CR>0
au Syntax c nnoremap - 0<C-v>
au Syntax c nnoremap = 0<C-v>
" GO
au Syntax go nnoremap - 0<C-v>
au Syntax go nnoremap = 0<C-v>
au Syntax go vnoremap - I//<Esc>
au Syntax go vnoremap = :s://::<CR><CR>:nohls<CR>0
" RUST
au Syntax rust nnoremap - 0<C-v>
au Syntax rust nnoremap = 0<C-v>
au Syntax rust vnoremap - I//<Esc>
au Syntax rust vnoremap = :s://::<CR><CR>:nohls<CR>0
" LUA
au Syntax lua nnoremap - 0<C-v>
au Syntax lua nnoremap = 0<C-v>
au Syntax lua vnoremap - I--<Esc>
au Syntax lua vnoremap = :s:--::<CR>:nohls<CR>0
"-----------------------------------------------------------------
" Matching Pairs
"""""""""""""""""""""""""
inoremap " <c-r>=QuoteDelim('"')<CR>
inoremap ' <c-r>=QuoteDelim("'")<CR>
inoremap ( ()<Esc>i
inoremap ) <c-r>=ClosePair(')')<CR>
inoremap [ []<Esc>i
inoremap ] <c-r>=ClosePair(']')<CR>
inoremap { {}<Esc>i
inoremap } <c-r>=ClosePair('}')<CR>
au Syntax html,css,js,php,xml set mps+=<:>
au Syntax html,css,js,php,xml inoremap > <c-r>=ClosePair('>')<CR>
au Syntax vim inoremap " "
"------------------------------------------------------------------------------
" Ctags
"""""""""""""""""""""""
" C
au syntax c nnoremap <C-w>t <Esc>:let $SRC=input("Enter source dir:")<CR>
au syntax c nnoremap <C-w>T <Esc>:!ctags -R -f /tmp/c_sys_tags -I __THROW --extra=+f --languages=c --langmap=c:+.h --c-kinds=+px --fields=+aiKSz --exclude=/usr/include/c++ --exclude=/usr/include/libio.h /usr/include<CR><CR>
au syntax c set tags=/tmp/c_cur_tags,/tmp/c_sys_tags
au BufWrite *.c,*.h !ctags -R -f /tmp/c_cur_tags --extra=+f --languages=c --langmap=c:+.h --c-kinds=+px --fields=+aiKSz $SRC
" GO
"au syntax go nnoremap <C-w>t <Esc>:let $GOPATH=input("Enter GOPATH dir:")<CR>
au syntax go nnoremap <C-w>t <Esc>:!ctags -R -f /tmp/go_sys_tags --languages=Go /usr/lib/go/src<CR><CR>
au syntax go set tags=/tmp/go_cur_tags,/tmp/go_sys_tags
au BufWrite *.go !ctags -R -f /tmp/go_cur_tags --languages=Go $GOPATH
" PYTHON
au syntax python nnoremap <C-w>t <Esc>:let $SRC=input("Enter source dir:")<CR>
au syntax python nnoremap <C-w>T <Esc>:!ctags -R -f /tmp/python_sys_tags --languages=Python /usr/lib/python3.7<CR><CR>
au syntax python set tags=/tmp/python_cur_tags,/tmp/python_sys_tags
au BufWrite *.py !ctags -R -f /tmp/python_cur_tags --languages=python $SRC
"------------------------------------------------------------------------------
" Cscope
""""""""""""""""""""""""
set cst
set csto=1
set cscopequickfix=s-,g-,c-,d-,i-,t-,e-
"au BufNewFile,BufRead *.c,*.h nnoremap #SS <ESC>:cs add $SRC/cscope.out<CR>
"au BufWrite *.c,*.h !find $SRC -type f|cscope -bk -i -;mv cscope.out $SRC/cscope.out
"au BufNewFile,BufRead *.c,*.h nnoremap #CC <ESC>:!echo 'Generating cs tags ...';find $SRC -type f\|cscope -bk -i -;mv cscope.out $SRC<CR>
"nnoremap <C-_>s :cs find s <C-R>=expand("<cword>")<CR><CR> "查找本C符号跳过注释
"nnoremap <C-_>g :cs find g <C-R>=expand("<cword>")<CR><CR> "查找本定义
"nnoremap <C-_>d :cs find d <C-R>=expand("<cword>")<CR><CR> "查找本函数调用的函数
"nnoremap <C-_>c :cs find c <C-R>=expand("<cword>")<CR><CR> "查找调用本函数的函数
"nnoremap <C-_>t :cs find t <C-R>=expand("<cword>")<CR><CR> "查找本字符串
"nnoremap <C-_>e :cs find e <C-R>=expand("<cword>")<CR><CR> "查找本 egrep 模式
"nnoremap <C-_>f :cs find f <C-R>=expand("<cfile>")<CR><CR> "查找本文件
"nnoremap <C-_>i :cs find i <C-R>=expand("<cfile>")<CR><CR> "查找包含本文件的文件
"------------------------------------------------------------------------------
" NERDTree
"""""""""""""""""""""""
let NERDChristmasTree = 1
let NERDTreeAutoCenter = 1
let NERDTreeQuitOnOpen = 1
let NERDTreeShowBookmarks = 1
let NERDTreeHighlightCursorline = 1
let NERDTreeShowFiles = 1
let NERDTreeStatusline = 1
"let NERDTreeShowHidden=1
"let NERDTreeShowLineNumbers=1
"let NERDTreeWinSize=30
" t.......在新Tab中打开选中文件/书签并跳到新Tab
" T.......在新Tab中打开选中文件/书签但不跳到新Tab
" i.......split一个新窗口打开选中文件并跳到该窗口
" gi......split一个新窗口打开选中文件但不跳到该窗口
" s.......vsp一个新窗口打开选中文件并跳到该窗口
" gs......vsp一个新窗口打开选中文件但不跳到该窗口
" !.......执行当前文件
" O.......递归打开选中结点下的所有目录
" x.......合拢选中结点的父目录
" X.......递归合拢选中结点下的所有目录
"------------------------------------------------------------------------------
" Templates
"""""""""""""""""""""""
let g:enable_template=1
let g:template_dir="~/.vim/templates"
"------------------------------------------------------------------------------
" Functions
"""""""""""""""""""""""
"function QuickFix()
" if exists('g:QuickFixState') && g:QuickFixState
" if exists('g:asyncrun_status') && 'running' == g:asyncrun_status
" return ":AsyncStop!\<CR>"
" endif
" let g:QuickFixState = 0
" if 'c' == &filetype
" return ":cclose\<CR>:make clean\<CR>\<CR>"
" elseif 'go' == &filetype
" return ":cclose\<CR>:!go clean\<CR>\<CR>"
" else
" return ":cclose\<CR>"
" endif
" else
" let g:QuickFixState = 1
" if 0 <= index(['c', 'python', 'go', 'rust', 'lua', 'sh'], &filetype)
" let b:argvs = input("Enter arguments:")
" if matchstr(v:version, '^8')
" return ":w!\<CR>\<CR>\<CR>:copen 15\<CR>\<C-w>k:AsyncRun ".&makeprg.b:argvs."\<CR>"
" else
" return ":w!\<CR>\<CR>\<CR>:make! ".b:argvs."\<CR>\<CR>:copen 15\<CR>\<C-w>k"
" endif
" else
" let g:QuickFixState = 0
" return "\<Esc>"
" endif
" endif
"endf
"function PythonColon()
" let KeyWords = ['if', 'elif', 'else', 'for', 'while', 'class', 'def', 'with', 'try', 'except', 'finally']
" let FirstWord = split(getline('.'))[0]
" if FirstWord == 'try'
" return "\<Esc>A:\<CR>except Exception, e:\<Esc><<O"
" elseif 0 <= index(KeyWords, FirstWord)
" return "\<Esc>A:\<CR>"
" endif
"endf
"function ClosePair(char)
" if getline('.')[col('.') - 1] == a:char
" return "\<Right>"
" else
" return a:char
" endif
"endf
"function QuoteDelim(char)
" let line = getline('.')
" let col = col('.')
" if line[col - 2] == "\\"
" return a:char
" elseif line[col - 1] == a:char
" return "\<Right>"
" else
" return a:char.a:char."\<Left>"
" endif
"endf
"------------------------------------------------------------------------------
"------------------------------------------------------------------------------

354
lib/nerdtree/bookmark.vim Normal file
View File

@ -0,0 +1,354 @@
" ============================================================================
" CLASS: Bookmark
"
" The Bookmark class serves two purposes:
" (1) It is the top-level prototype for new, concrete Bookmark objects.
" (2) It provides an interface for client code to query and manipulate the
" global list of Bookmark objects within the current Vim session.
" ============================================================================
let s:Bookmark = {}
let g:NERDTreeBookmark = s:Bookmark
" FUNCTION: Bookmark.activate(nerdtree) {{{1
function! s:Bookmark.activate(nerdtree, ...)
call self.open(a:nerdtree, a:0 ? a:1 : {})
endfunction
" FUNCTION: Bookmark.AddBookmark(name, path) {{{1
" Class method to add a new bookmark to the list, if a previous bookmark exists
" with the same name, just update the path for that bookmark
function! s:Bookmark.AddBookmark(name, path)
for i in s:Bookmark.Bookmarks()
if i.name ==# a:name
let i.path = a:path
return
endif
endfor
call add(s:Bookmark.Bookmarks(), s:Bookmark.New(a:name, a:path))
endfunction
" FUNCTION: Bookmark.Bookmarks() {{{1
" Class method to get all bookmarks. Lazily initializes the bookmarks global
" variable
function! s:Bookmark.Bookmarks()
if !exists("g:NERDTreeBookmarks")
let g:NERDTreeBookmarks = []
endif
return g:NERDTreeBookmarks
endfunction
" FUNCTION: Bookmark.BookmarkExistsFor(name) {{{1
" class method that returns 1 if a bookmark with the given name is found, 0
" otherwise
function! s:Bookmark.BookmarkExistsFor(name)
try
call s:Bookmark.BookmarkFor(a:name)
return 1
catch /^NERDTree.BookmarkNotFoundError/
return 0
endtry
endfunction
" FUNCTION: Bookmark.BookmarkFor(name) {{{1
" Class method that returns the Bookmark object having the specified name.
" Throws "NERDTree.BookmarkNotFoundError" if no Bookmark is found.
function! s:Bookmark.BookmarkFor(name)
let l:result = {}
for l:bookmark in s:Bookmark.Bookmarks()
if l:bookmark.name ==# a:name
let l:result = l:bookmark
break
endif
endfor
if empty(l:result)
throw 'NERDTree.BookmarkNotFoundError: "' . a:name . '" not found'
endif
return l:result
endfunction
" FUNCTION: Bookmark.BookmarkNames() {{{1
" Class method to return an array of all bookmark names
function! s:Bookmark.BookmarkNames()
let names = []
for i in s:Bookmark.Bookmarks()
call add(names, i.name)
endfor
return names
endfunction
" FUNCTION: Bookmark.CacheBookmarks(silent) {{{1
" Class method to read all bookmarks from the bookmarks file initialize
" bookmark objects for each one.
"
" Args:
" silent - dont echo an error msg if invalid bookmarks are found
function! s:Bookmark.CacheBookmarks(silent)
if filereadable(g:NERDTreeBookmarksFile)
let g:NERDTreeBookmarks = []
let g:NERDTreeInvalidBookmarks = []
let bookmarkStrings = readfile(g:NERDTreeBookmarksFile)
let invalidBookmarksFound = 0
for i in bookmarkStrings
"ignore blank lines
if i != ''
let name = substitute(i, '^\(.\{-}\) .*$', '\1', '')
let path = substitute(i, '^.\{-} \(.*\)$', '\1', '')
let path = fnamemodify(path, ':p')
try
let bookmark = s:Bookmark.New(name, g:NERDTreePath.New(path))
call add(g:NERDTreeBookmarks, bookmark)
catch /^NERDTree.InvalidArgumentsError/
call add(g:NERDTreeInvalidBookmarks, i)
let invalidBookmarksFound += 1
endtry
endif
endfor
if invalidBookmarksFound
call s:Bookmark.Write()
if !a:silent
call nerdtree#echo(invalidBookmarksFound . " invalid bookmarks were read. See :help NERDTreeInvalidBookmarks for info.")
endif
endif
endif
endfunction
" FUNCTION: Bookmark.CompareBookmarksByName(firstBookmark, secondBookmark) {{{1
" Class method that indicates the relative position of two bookmarks when
" placed in alphabetical order by name. Case-sensitivity is determined by an
" option. Supports the "s:Bookmark.SortBookmarksList()" method.
function! s:Bookmark.CompareBookmarksByName(firstBookmark, secondBookmark)
let l:result = 0
if g:NERDTreeBookmarksSort == 1
if a:firstBookmark.name <? a:secondBookmark.name
let l:result = -1
elseif a:firstBookmark.name >? a:secondBookmark.name
let l:result = 1
endif
elseif g:NERDTreeBookmarksSort == 2
if a:firstBookmark.name <# a:secondBookmark.name
let l:result = -1
elseif a:firstBookmark.name ># a:secondBookmark.name
let l:result = 1
endif
endif
return l:result
endfunction
" FUNCTION: Bookmark.ClearAll() {{{1
" Class method to delete all bookmarks.
function! s:Bookmark.ClearAll()
for i in s:Bookmark.Bookmarks()
call i.delete()
endfor
call s:Bookmark.Write()
endfunction
" FUNCTION: Bookmark.delete() {{{1
" Delete this bookmark. If the node for this bookmark is under the current
" root, then recache bookmarks for its Path object
function! s:Bookmark.delete()
call remove(s:Bookmark.Bookmarks(), index(s:Bookmark.Bookmarks(), self))
call s:Bookmark.Write()
endfunction
" FUNCTION: Bookmark.getNode(nerdtree, searchFromAbsoluteRoot) {{{1
" Returns the tree node object associated with this Bookmark.
" Throws "NERDTree.BookmarkedNodeNotFoundError" if the node is not found.
"
" Args:
" searchFromAbsoluteRoot: boolean flag, search from the highest cached node
" if true and from the current tree root if false
function! s:Bookmark.getNode(nerdtree, searchFromAbsoluteRoot)
if a:searchFromAbsoluteRoot
let l:searchRoot = a:nerdtree.root.AbsoluteTreeRoot()
else
let l:searchRoot = a:nerdtree.root
endif
let l:targetNode = l:searchRoot.findNode(self.path)
if empty(l:targetNode)
throw 'NERDTree.BookmarkedNodeNotFoundError: node for bookmark "' . self.name . '" not found'
endif
return l:targetNode
endfunction
" FUNCTION: Bookmark.GetNodeForName(name, searchFromAbsoluteRoot, nerdtree) {{{1
" Class method that returns the tree node object for the Bookmark with the
" given name. Throws "NERDTree.BookmarkNotFoundError" if a Bookmark with the
" name does not exist. Throws "NERDTree.BookmarkedNodeNotFoundError" if a
" tree node for the named Bookmark could not be found.
function! s:Bookmark.GetNodeForName(name, searchFromAbsoluteRoot, nerdtree)
let l:bookmark = s:Bookmark.BookmarkFor(a:name)
return l:bookmark.getNode(a:nerdtree, a:searchFromAbsoluteRoot)
endfunction
" FUNCTION: Bookmark.GetSelected() {{{1
" returns the Bookmark the cursor is over, or {}
function! s:Bookmark.GetSelected()
let line = getline(".")
let name = substitute(line, '^>\(.\{-}\) .\+$', '\1', '')
if name != line
try
return s:Bookmark.BookmarkFor(name)
catch /^NERDTree.BookmarkNotFoundError/
return {}
endtry
endif
return {}
endfunction
" FUNCTION: Bookmark.InvalidBookmarks() {{{1
" Class method to get all invalid bookmark strings read from the bookmarks
" file
function! s:Bookmark.InvalidBookmarks()
if !exists("g:NERDTreeInvalidBookmarks")
let g:NERDTreeInvalidBookmarks = []
endif
return g:NERDTreeInvalidBookmarks
endfunction
" FUNCTION: Bookmark.mustExist() {{{1
function! s:Bookmark.mustExist()
if !self.path.exists()
call s:Bookmark.CacheBookmarks(1)
throw "NERDTree.BookmarkPointsToInvalidLocationError: the bookmark \"".
\ self.name ."\" points to a non existing location: \"". self.path.str()
endif
endfunction
" FUNCTION: Bookmark.New(name, path) {{{1
" Create a new bookmark object with the given name and path object
function! s:Bookmark.New(name, path)
if a:name =~# ' '
throw "NERDTree.IllegalBookmarkNameError: illegal name:" . a:name
endif
let newBookmark = copy(self)
let newBookmark.name = a:name
let newBookmark.path = a:path
return newBookmark
endfunction
" FUNCTION: Bookmark.open(nerdtree, [options]) {{{1
"Args:
"
"nerdtree: the tree to load open the bookmark in
"
"A dictionary containing the following keys (all optional):
" 'where': Specifies whether the node should be opened in new split/tab or in
" the previous window. Can be either 'v' (vertical split), 'h'
" (horizontal split), 't' (new tab) or 'p' (previous window).
" 'reuse': if a window is displaying the file then jump the cursor there
" 'keepopen': dont close the tree window
" 'stay': open the file, but keep the cursor in the tree win
"
function! s:Bookmark.open(nerdtree, ...)
let opts = a:0 ? a:1 : {}
if self.path.isDirectory && !has_key(opts, 'where')
call self.toRoot(a:nerdtree)
else
let opener = g:NERDTreeOpener.New(self.path, opts)
call opener.open(self)
endif
endfunction
" FUNCTION: Bookmark.openInNewTab(options) {{{1
" Create a new bookmark object with the given name and path object
function! s:Bookmark.openInNewTab(options)
call nerdtree#deprecated('Bookmark.openInNewTab', 'is deprecated, use open() instead')
call self.open(a:options)
endfunction
" FUNCTION: Bookmark.setPath(path) {{{1
" makes this bookmark point to the given path
function! s:Bookmark.setPath(path)
let self.path = a:path
endfunction
" FUNCTION: Bookmark.SortBookmarksList() {{{1
" Class method that sorts the global list of bookmarks alphabetically by name.
" Note that case-sensitivity is determined by a user option.
function! s:Bookmark.SortBookmarksList()
call sort(s:Bookmark.Bookmarks(), s:Bookmark.CompareBookmarksByName, s:Bookmark)
endfunction
" FUNCTION: Bookmark.str() {{{1
" Get the string that should be rendered in the view for this bookmark
function! s:Bookmark.str()
let pathStrMaxLen = winwidth(g:NERDTree.GetWinNum()) - 4 - strdisplaywidth(self.name)
if &nu
let pathStrMaxLen = pathStrMaxLen - &numberwidth
endif
let pathStr = self.path.str({'format': 'UI'})
if strdisplaywidth(pathStr) > pathStrMaxLen
while strdisplaywidth(pathStr) > pathStrMaxLen && strchars(pathStr) > 0
let pathStr = substitute(pathStr, '^.', '', '')
endwhile
let pathStr = '<' . pathStr
endif
return '>' . self.name . ' ' . pathStr
endfunction
" FUNCTION: Bookmark.toRoot(nerdtree) {{{1
" Set the root of the given NERDTree to the node for this Bookmark. If a node
" for this Bookmark does not exist, a new one is initialized.
function! s:Bookmark.toRoot(nerdtree)
if self.validate()
try
let l:targetNode = self.getNode(a:nerdtree, 1)
call l:targetNode.closeChildren()
catch /^NERDTree.BookmarkedNodeNotFoundError/
let l:targetNode = g:NERDTreeFileNode.New(s:Bookmark.BookmarkFor(self.name).path, a:nerdtree)
endtry
call a:nerdtree.changeRoot(l:targetNode)
endif
endfunction
" FUNCTION: Bookmark.ToRoot(name, nerdtree) {{{1
" Class method that makes the Bookmark with the given name the root of
" specified NERDTree.
function! s:Bookmark.ToRoot(name, nerdtree)
let l:bookmark = s:Bookmark.BookmarkFor(a:name)
call l:bookmark.toRoot(a:nerdtree)
endfunction
" FUNCTION: Bookmark.validate() {{{1
function! s:Bookmark.validate()
if self.path.exists()
return 1
else
call s:Bookmark.CacheBookmarks(1)
call nerdtree#echo(self.name . "now points to an invalid location. See :help NERDTreeInvalidBookmarks for info.")
return 0
endif
endfunction
" FUNCTION: Bookmark.Write() {{{1
" Class method to write all bookmarks to the bookmarks file
function! s:Bookmark.Write()
let bookmarkStrings = []
for i in s:Bookmark.Bookmarks()
call add(bookmarkStrings, i.name . ' ' . fnamemodify(i.path.str(), ':~'))
endfor
"add a blank line before the invalid ones
call add(bookmarkStrings, "")
for j in s:Bookmark.InvalidBookmarks()
call add(bookmarkStrings, j)
endfor
try
call writefile(bookmarkStrings, g:NERDTreeBookmarksFile)
catch
call nerdtree#echoError("Failed to write bookmarks file. Make sure g:NERDTreeBookmarksFile points to a valid location.")
endtry
endfunction
" vim: set sw=4 sts=4 et fdm=marker:

389
lib/nerdtree/creator.vim Normal file
View File

@ -0,0 +1,389 @@
" ============================================================================
" CLASS: Creator
"
" This class is responsible for creating NERDTree instances. The new NERDTree
" may be a tab tree, a window tree, or a mirrored tree. In the process of
" creating a NERDTree, it sets up all of the window and buffer options and key
" mappings etc.
" ============================================================================
let s:Creator = {}
let g:NERDTreeCreator = s:Creator
" FUNCTION: s:Creator._bindMappings() {{{1
function! s:Creator._bindMappings()
"make <cr> do the same as the activate node mapping
nnoremap <silent> <buffer> <cr> :call nerdtree#ui_glue#invokeKeyMap(g:NERDTreeMapActivateNode)<cr>
call g:NERDTreeKeyMap.BindAll()
command! -buffer -nargs=? Bookmark :call nerdtree#ui_glue#bookmarkNode('<args>')
command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=1 RevealBookmark :call nerdtree#ui_glue#revealBookmark('<args>')
command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=1 OpenBookmark call nerdtree#ui_glue#openBookmark('<args>')
command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=* ClearBookmarks call nerdtree#ui_glue#clearBookmarks('<args>')
command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=+ BookmarkToRoot call g:NERDTreeBookmark.ToRoot('<args>', b:NERDTree)
command! -buffer -nargs=0 ClearAllBookmarks call g:NERDTreeBookmark.ClearAll() <bar> call b:NERDTree.render()
command! -buffer -nargs=0 ReadBookmarks call g:NERDTreeBookmark.CacheBookmarks(0) <bar> call b:NERDTree.render()
command! -buffer -nargs=0 WriteBookmarks call g:NERDTreeBookmark.Write()
endfunction
" FUNCTION: s:Creator._broadcastInitEvent() {{{1
function! s:Creator._broadcastInitEvent()
silent doautocmd User NERDTreeInit
endfunction
" FUNCTION: s:Creator.BufNamePrefix() {{{2
function! s:Creator.BufNamePrefix()
return 'NERD_tree_'
endfunction
" FUNCTION: s:Creator.CreateTabTree(a:name) {{{1
function! s:Creator.CreateTabTree(name)
let creator = s:Creator.New()
call creator.createTabTree(a:name)
endfunction
" FUNCTION: s:Creator.createTabTree(a:name) {{{1
" name: the name of a bookmark or a directory
function! s:Creator.createTabTree(name)
let l:path = self._pathForString(a:name)
" Abort if an exception was thrown (i.e., if the bookmark or directory
" does not exist).
if empty(l:path)
return
endif
" Obey the user's preferences for changing the working directory.
if g:NERDTreeChDirMode != 0
call l:path.changeToDir()
endif
if g:NERDTree.ExistsForTab()
call g:NERDTree.Close()
call self._removeTreeBufForTab()
endif
call self._createTreeWin()
call self._createNERDTree(l:path, 'tab')
call b:NERDTree.render()
call b:NERDTree.root.putCursorHere(0, 0)
call self._broadcastInitEvent()
endfunction
" FUNCTION: s:Creator.CreateWindowTree(dir) {{{1
function! s:Creator.CreateWindowTree(dir)
let creator = s:Creator.New()
call creator.createWindowTree(a:dir)
endfunction
" FUNCTION: s:Creator.createWindowTree(dir) {{{1
function! s:Creator.createWindowTree(dir)
try
let path = g:NERDTreePath.New(a:dir)
catch /^NERDTree.InvalidArgumentsError/
call nerdtree#echo("Invalid directory name:" . a:name)
return
endtry
"we want the directory buffer to disappear when we do the :edit below
setlocal bufhidden=wipe
let previousBuf = expand("#")
"we need a unique name for each window tree buffer to ensure they are
"all independent
exec g:NERDTreeCreatePrefix . " edit " . self._nextBufferName()
call self._createNERDTree(path, "window")
let b:NERDTree._previousBuf = bufnr(previousBuf)
call self._setCommonBufOptions()
call b:NERDTree.render()
call self._broadcastInitEvent()
endfunction
" FUNCTION: s:Creator._createNERDTree(path) {{{1
function! s:Creator._createNERDTree(path, type)
let b:NERDTree = g:NERDTree.New(a:path, a:type)
" TODO: This assignment is kept for compatibility reasons. Many other
" plugins use "b:NERDTreeRoot" instead of "b:NERDTree.root". Remove this
" assignment in the future.
let b:NERDTreeRoot = b:NERDTree.root
call b:NERDTree.root.open()
endfunction
" FUNCTION: s:Creator.CreateMirror() {{{1
function! s:Creator.CreateMirror()
let creator = s:Creator.New()
call creator.createMirror()
endfunction
" FUNCTION: s:Creator.createMirror() {{{1
function! s:Creator.createMirror()
"get the names off all the nerd tree buffers
let treeBufNames = []
for i in range(1, tabpagenr("$"))
let nextName = self._tabpagevar(i, 'NERDTreeBufName')
if nextName != -1 && (!exists("t:NERDTreeBufName") || nextName != t:NERDTreeBufName)
call add(treeBufNames, nextName)
endif
endfor
let treeBufNames = self._uniq(treeBufNames)
"map the option names (that the user will be prompted with) to the nerd
"tree buffer names
let options = {}
let i = 0
while i < len(treeBufNames)
let bufName = treeBufNames[i]
let treeRoot = getbufvar(bufName, "NERDTree").root
let options[i+1 . '. ' . treeRoot.path.str() . ' (buf name: ' . bufName . ')'] = bufName
let i = i + 1
endwhile
"work out which tree to mirror, if there is more than 1 then ask the user
let bufferName = ''
if len(keys(options)) > 1
let choices = ["Choose a tree to mirror"]
let choices = extend(choices, sort(keys(options)))
let choice = inputlist(choices)
if choice < 1 || choice > len(options) || choice ==# ''
return
endif
let bufferName = options[sort(keys(options))[choice-1]]
elseif len(keys(options)) ==# 1
let bufferName = values(options)[0]
else
call nerdtree#echo("No trees to mirror")
return
endif
if g:NERDTree.ExistsForTab() && g:NERDTree.IsOpen()
call g:NERDTree.Close()
endif
let t:NERDTreeBufName = bufferName
call self._createTreeWin()
exec 'buffer ' . bufferName
if !&hidden
call b:NERDTree.render()
endif
endfunction
" FUNCTION: s:Creator._createTreeWin() {{{1
" Initialize the NERDTree window. Open the window, size it properly, set all
" local options, etc.
function! s:Creator._createTreeWin()
let l:splitLocation = g:NERDTreeWinPos ==# 'left' ? 'topleft ' : 'botright '
let l:splitSize = g:NERDTreeWinSize
if !g:NERDTree.ExistsForTab()
let t:NERDTreeBufName = self._nextBufferName()
silent! execute l:splitLocation . 'vertical ' . l:splitSize . ' new'
silent! execute 'edit ' . t:NERDTreeBufName
else
silent! execute l:splitLocation . 'vertical ' . l:splitSize . ' split'
silent! execute 'buffer ' . t:NERDTreeBufName
endif
call self._setCommonBufOptions()
if has('patch-7.4.1925')
clearjumps
endif
setlocal winfixwidth
endfunction
" FUNCTION: s:Creator._isBufHidden(nr) {{{1
function! s:Creator._isBufHidden(nr)
redir => bufs
silent ls!
redir END
return bufs =~ a:nr . '..h'
endfunction
" FUNCTION: s:Creator.New() {{{1
function! s:Creator.New()
let newCreator = copy(self)
return newCreator
endfunction
" FUNCTION: s:Creator._nextBufferName() {{{2
" returns the buffer name for the next nerd tree
function! s:Creator._nextBufferName()
let name = s:Creator.BufNamePrefix() . self._nextBufferNumber()
return name
endfunction
" FUNCTION: s:Creator._nextBufferNumber() {{{2
" the number to add to the nerd tree buffer name to make the buf name unique
function! s:Creator._nextBufferNumber()
if !exists("s:Creator._NextBufNum")
let s:Creator._NextBufNum = 1
else
let s:Creator._NextBufNum += 1
endif
return s:Creator._NextBufNum
endfunction
" FUNCTION: s:Creator._pathForString(str) {{{1
" find a bookmark or adirectory for the given string
function! s:Creator._pathForString(str)
let path = {}
if g:NERDTreeBookmark.BookmarkExistsFor(a:str)
let path = g:NERDTreeBookmark.BookmarkFor(a:str).path
else
let dir = a:str ==# '' ? getcwd() : a:str
"hack to get an absolute path if a relative path is given
if dir =~# '^\.'
let dir = getcwd() . g:NERDTreePath.Slash() . dir
endif
let dir = g:NERDTreePath.Resolve(dir)
try
let path = g:NERDTreePath.New(dir)
catch /^NERDTree.InvalidArgumentsError/
call nerdtree#echo("No bookmark or directory found for: " . a:str)
return {}
endtry
endif
if !path.isDirectory
let path = path.getParent()
endif
return path
endfunction
" Function: s:Creator._removeTreeBufForTab() {{{1
function! s:Creator._removeTreeBufForTab()
let buf = bufnr(t:NERDTreeBufName)
"if &hidden is not set then it will already be gone
if buf != -1
"nerdtree buf may be mirrored/displayed elsewhere
if self._isBufHidden(buf)
exec "bwipeout " . buf
endif
endif
unlet t:NERDTreeBufName
endfunction
" FUNCTION: s:Creator._setCommonBufOptions() {{{1
function! s:Creator._setCommonBufOptions()
" Options for a non-file/control buffer.
setlocal bufhidden=hide
setlocal buftype=nofile
setlocal noswapfile
" Options for controlling buffer/window appearance.
setlocal foldcolumn=0
setlocal foldmethod=manual
setlocal nobuflisted
setlocal nofoldenable
setlocal nolist
setlocal nospell
setlocal nowrap
if g:NERDTreeShowLineNumbers
setlocal nu
else
setlocal nonu
if v:version >= 703
setlocal nornu
endif
endif
iabc <buffer>
if g:NERDTreeHighlightCursorline
setlocal cursorline
endif
call self._setupStatusline()
call self._bindMappings()
setlocal filetype=nerdtree
endfunction
" FUNCTION: s:Creator._setupStatusline() {{{1
function! s:Creator._setupStatusline()
if g:NERDTreeStatusline != -1
let &l:statusline = g:NERDTreeStatusline
endif
endfunction
" FUNCTION: s:Creator._tabpagevar(tabnr, var) {{{1
function! s:Creator._tabpagevar(tabnr, var)
let currentTab = tabpagenr()
let old_ei = &ei
set ei=all
exec "tabnext " . a:tabnr
let v = -1
if exists('t:' . a:var)
exec 'let v = t:' . a:var
endif
exec "tabnext " . currentTab
let &ei = old_ei
return v
endfunction
" FUNCTION: s:Creator.ToggleTabTree(dir) {{{1
function! s:Creator.ToggleTabTree(dir)
let creator = s:Creator.New()
call creator.toggleTabTree(a:dir)
endfunction
" FUNCTION: s:Creator.toggleTabTree(dir) {{{1
" Toggles the NERD tree. I.e the NERD tree is open, it is closed, if it is
" closed it is restored or initialized (if it doesnt exist)
"
" Args:
" dir: the full path for the root node (is only used if the NERD tree is being
" initialized.
function! s:Creator.toggleTabTree(dir)
if g:NERDTree.ExistsForTab()
if !g:NERDTree.IsOpen()
call self._createTreeWin()
if !&hidden
call b:NERDTree.render()
endif
call b:NERDTree.ui.restoreScreenState()
else
call g:NERDTree.Close()
endif
else
call self.createTabTree(a:dir)
endif
endfunction
" Function: s:Creator._uniq(list) {{{1
" returns a:list without duplicates
function! s:Creator._uniq(list)
let uniqlist = []
for elem in a:list
if index(uniqlist, elem) ==# -1
let uniqlist += [elem]
endif
endfor
return uniqlist
endfunction
" vim: set sw=4 sts=4 et fdm=marker:

13
lib/nerdtree/event.vim Normal file
View File

@ -0,0 +1,13 @@
"CLASS: Event
"============================================================
let s:Event = {}
let g:NERDTreeEvent = s:Event
function! s:Event.New(nerdtree, subject, action, params) abort
let newObj = copy(self)
let newObj.nerdtree = a:nerdtree
let newObj.subject = a:subject
let newObj.action = a:action
let newObj.params = a:params
return newObj
endfunction

58
lib/nerdtree/flag_set.vim Normal file
View File

@ -0,0 +1,58 @@
"CLASS: FlagSet
"============================================================
let s:FlagSet = {}
let g:NERDTreeFlagSet = s:FlagSet
"FUNCTION: FlagSet.addFlag(scope, flag) {{{1
function! s:FlagSet.addFlag(scope, flag)
let flags = self._flagsForScope(a:scope)
if index(flags, a:flag) == -1
call add(flags, a:flag)
end
endfunction
"FUNCTION: FlagSet.clearFlags(scope) {{{1
function! s:FlagSet.clearFlags(scope)
let self._flags[a:scope] = []
endfunction
"FUNCTION: FlagSet._flagsForScope(scope) {{{1
function! s:FlagSet._flagsForScope(scope)
if !has_key(self._flags, a:scope)
let self._flags[a:scope] = []
endif
return self._flags[a:scope]
endfunction
"FUNCTION: FlagSet.New() {{{1
function! s:FlagSet.New()
let newObj = copy(self)
let newObj._flags = {}
return newObj
endfunction
"FUNCTION: FlagSet.removeFlag(scope, flag) {{{1
function! s:FlagSet.removeFlag(scope, flag)
let flags = self._flagsForScope(a:scope)
let i = index(flags, a:flag)
if i >= 0
call remove(flags, i)
endif
endfunction
"FUNCTION: FlagSet.renderToString() {{{1
function! s:FlagSet.renderToString()
let flagstring = ""
for i in values(self._flags)
let flagstring .= join(i)
endfor
if len(flagstring) == 0
return ""
endif
return '[' . flagstring . ']'
endfunction
" vim: set sw=4 sts=4 et fdm=marker:

163
lib/nerdtree/key_map.vim Normal file
View File

@ -0,0 +1,163 @@
"CLASS: KeyMap
"============================================================
let s:KeyMap = {}
let g:NERDTreeKeyMap = s:KeyMap
let s:keyMaps = {}
"FUNCTION: KeyMap.All() {{{1
function! s:KeyMap.All()
let sortedKeyMaps = values(s:keyMaps)
call sort(sortedKeyMaps, s:KeyMap.Compare, s:KeyMap)
return sortedKeyMaps
endfunction
"FUNCTION: KeyMap.Compare(keyMap1, keyMap2) {{{1
function! s:KeyMap.Compare(keyMap1, keyMap2)
if a:keyMap1.key >? a:keyMap2.key
return 1
endif
if a:keyMap1.key <? a:keyMap2.key
return -1
endif
return 0
endfunction
"FUNCTION: KeyMap.FindFor(key, scope) {{{1
function! s:KeyMap.FindFor(key, scope)
return get(s:keyMaps, a:key . a:scope, {})
endfunction
"FUNCTION: KeyMap.BindAll() {{{1
function! s:KeyMap.BindAll()
for i in values(s:keyMaps)
call i.bind()
endfor
endfunction
"FUNCTION: KeyMap.bind() {{{1
function! s:KeyMap.bind()
" If the key sequence we're trying to map contains any '<>' notation, we
" must replace each of the '<' characters with '<lt>' to ensure the string
" is not translated into its corresponding keycode during the later part
" of the map command below
" :he <>
let specialNotationRegex = '\m<\([[:alnum:]_-]\+>\)'
if self.key =~# specialNotationRegex
let keymapInvokeString = substitute(self.key, specialNotationRegex, '<lt>\1', 'g')
else
let keymapInvokeString = self.key
endif
let premap = self.key == "<LeftRelease>" ? " <LeftRelease>" : " "
exec 'nnoremap <buffer> <silent> '. self.key . premap . ':call nerdtree#ui_glue#invokeKeyMap("'. keymapInvokeString .'")<cr>'
endfunction
"FUNCTION: KeyMap.Remove(key, scope) {{{1
function! s:KeyMap.Remove(key, scope)
return remove(s:keyMaps, a:key . a:scope)
endfunction
"FUNCTION: KeyMap.invoke() {{{1
"Call the KeyMaps callback function
function! s:KeyMap.invoke(...)
let Callback = function(self.callback)
if a:0
call Callback(a:1)
else
call Callback()
endif
endfunction
"FUNCTION: KeyMap.Invoke() {{{1
"Find a keymapping for a:key and the current scope invoke it.
"
"Scope is determined as follows:
" * if the cursor is on a dir node then "DirNode"
" * if the cursor is on a file node then "FileNode"
" * if the cursor is on a bookmark then "Bookmark"
"
"If a keymap has the scope of "all" then it will be called if no other keymap
"is found for a:key and the scope.
function! s:KeyMap.Invoke(key)
"required because clicking the command window below another window still
"invokes the <LeftRelease> mapping - but changes the window cursor
"is in first
"
"TODO: remove this check when the vim bug is fixed
if !g:NERDTree.ExistsForBuf()
return {}
endif
let node = g:NERDTreeFileNode.GetSelected()
if !empty(node)
"try file node
if !node.path.isDirectory
let km = s:KeyMap.FindFor(a:key, "FileNode")
if !empty(km)
return km.invoke(node)
endif
endif
"try dir node
if node.path.isDirectory
let km = s:KeyMap.FindFor(a:key, "DirNode")
if !empty(km)
return km.invoke(node)
endif
endif
"try generic node
let km = s:KeyMap.FindFor(a:key, "Node")
if !empty(km)
return km.invoke(node)
endif
endif
"try bookmark
let bm = g:NERDTreeBookmark.GetSelected()
if !empty(bm)
let km = s:KeyMap.FindFor(a:key, "Bookmark")
if !empty(km)
return km.invoke(bm)
endif
endif
"try all
let km = s:KeyMap.FindFor(a:key, "all")
if !empty(km)
return km.invoke()
endif
endfunction
"FUNCTION: KeyMap.Create(options) {{{1
function! s:KeyMap.Create(options)
let opts = extend({'scope': 'all', 'quickhelpText': ''}, copy(a:options))
"dont override other mappings unless the 'override' option is given
if get(opts, 'override', 0) == 0 && !empty(s:KeyMap.FindFor(opts['key'], opts['scope']))
return
end
let newKeyMap = copy(self)
let newKeyMap.key = opts['key']
let newKeyMap.quickhelpText = opts['quickhelpText']
let newKeyMap.callback = opts['callback']
let newKeyMap.scope = opts['scope']
call s:KeyMap.Add(newKeyMap)
endfunction
"FUNCTION: KeyMap.Add(keymap) {{{1
function! s:KeyMap.Add(keymap)
let s:keyMaps[a:keymap.key . a:keymap.scope] = a:keymap
endfunction
" vim: set sw=4 sts=4 et fdm=marker:

View File

@ -0,0 +1,186 @@
"CLASS: MenuController
"============================================================
let s:MenuController = {}
let g:NERDTreeMenuController = s:MenuController
"FUNCTION: MenuController.New(menuItems) {{{1
"create a new menu controller that operates on the given menu items
function! s:MenuController.New(menuItems)
let newMenuController = copy(self)
if a:menuItems[0].isSeparator()
let newMenuController.menuItems = a:menuItems[1:-1]
else
let newMenuController.menuItems = a:menuItems
endif
return newMenuController
endfunction
" FUNCTION: MenuController.showMenu() {{{1
" Enter the main loop of the NERDTree menu, prompting the user to select
" a menu item.
function! s:MenuController.showMenu()
call self._saveOptions()
try
let self.selection = 0
let l:done = 0
while !l:done
redraw!
call self._echoPrompt()
let l:key = nr2char(getchar())
let l:done = self._handleKeypress(l:key)
endwhile
finally
call self._restoreOptions()
" Redraw when "Ctrl-C" or "Esc" is received.
if !l:done || self.selection == -1
redraw!
endif
endtry
if self.selection != -1
let l:m = self._current()
call l:m.execute()
endif
endfunction
"FUNCTION: MenuController._echoPrompt() {{{1
function! s:MenuController._echoPrompt()
echo "NERDTree Menu. Use j/k/enter and the shortcuts indicated"
echo "=========================================================="
for i in range(0, len(self.menuItems)-1)
if self.selection == i
echo "> " . self.menuItems[i].text
else
echo " " . self.menuItems[i].text
endif
endfor
endfunction
"FUNCTION: MenuController._current(key) {{{1
"get the MenuItem that is currently selected
function! s:MenuController._current()
return self.menuItems[self.selection]
endfunction
"FUNCTION: MenuController._handleKeypress(key) {{{1
"change the selection (if appropriate) and return 1 if the user has made
"their choice, 0 otherwise
function! s:MenuController._handleKeypress(key)
if a:key == 'j'
call self._cursorDown()
elseif a:key == 'k'
call self._cursorUp()
elseif a:key == nr2char(27) "escape
let self.selection = -1
return 1
elseif a:key == "\r" || a:key == "\n" "enter and ctrl-j
return 1
else
let index = self._nextIndexFor(a:key)
if index != -1
let self.selection = index
if len(self._allIndexesFor(a:key)) == 1
return 1
endif
endif
endif
return 0
endfunction
"FUNCTION: MenuController._allIndexesFor(shortcut) {{{1
"get indexes to all menu items with the given shortcut
function! s:MenuController._allIndexesFor(shortcut)
let toReturn = []
for i in range(0, len(self.menuItems)-1)
if self.menuItems[i].shortcut == a:shortcut
call add(toReturn, i)
endif
endfor
return toReturn
endfunction
"FUNCTION: MenuController._nextIndexFor(shortcut) {{{1
"get the index to the next menu item with the given shortcut, starts from the
"current cursor location and wraps around to the top again if need be
function! s:MenuController._nextIndexFor(shortcut)
for i in range(self.selection+1, len(self.menuItems)-1)
if self.menuItems[i].shortcut == a:shortcut
return i
endif
endfor
for i in range(0, self.selection)
if self.menuItems[i].shortcut == a:shortcut
return i
endif
endfor
return -1
endfunction
"FUNCTION: MenuController._setCmdheight() {{{1
"sets &cmdheight to whatever is needed to display the menu
function! s:MenuController._setCmdheight()
let &cmdheight = len(self.menuItems) + 3
endfunction
"FUNCTION: MenuController._saveOptions() {{{1
"set any vim options that are required to make the menu work (saving their old
"values)
function! s:MenuController._saveOptions()
let self._oldLazyredraw = &lazyredraw
let self._oldCmdheight = &cmdheight
set nolazyredraw
call self._setCmdheight()
endfunction
"FUNCTION: MenuController._restoreOptions() {{{1
"restore the options we saved in _saveOptions()
function! s:MenuController._restoreOptions()
let &cmdheight = self._oldCmdheight
let &lazyredraw = self._oldLazyredraw
endfunction
"FUNCTION: MenuController._cursorDown() {{{1
"move the cursor to the next menu item, skipping separators
function! s:MenuController._cursorDown()
let done = 0
while !done
if self.selection < len(self.menuItems)-1
let self.selection += 1
else
let self.selection = 0
endif
if !self._current().isSeparator()
let done = 1
endif
endwhile
endfunction
"FUNCTION: MenuController._cursorUp() {{{1
"move the cursor to the previous menu item, skipping separators
function! s:MenuController._cursorUp()
let done = 0
while !done
if self.selection > 0
let self.selection -= 1
else
let self.selection = len(self.menuItems)-1
endif
if !self._current().isSeparator()
let done = 1
endif
endwhile
endfunction
" vim: set sw=4 sts=4 et fdm=marker:

114
lib/nerdtree/menu_item.vim Normal file
View File

@ -0,0 +1,114 @@
"CLASS: MenuItem
"============================================================
let s:MenuItem = {}
let g:NERDTreeMenuItem = s:MenuItem
"FUNCTION: MenuItem.All() {{{1
"get all top level menu items
function! s:MenuItem.All()
if !exists("s:menuItems")
let s:menuItems = []
endif
return s:menuItems
endfunction
"FUNCTION: MenuItem.AllEnabled() {{{1
"get all top level menu items that are currently enabled
function! s:MenuItem.AllEnabled()
let toReturn = []
for i in s:MenuItem.All()
if i.enabled()
call add(toReturn, i)
endif
endfor
return toReturn
endfunction
"FUNCTION: MenuItem.Create(options) {{{1
"make a new menu item and add it to the global list
function! s:MenuItem.Create(options)
let newMenuItem = copy(self)
let newMenuItem.text = a:options['text']
let newMenuItem.shortcut = a:options['shortcut']
let newMenuItem.children = []
let newMenuItem.isActiveCallback = -1
if has_key(a:options, 'isActiveCallback')
let newMenuItem.isActiveCallback = a:options['isActiveCallback']
endif
let newMenuItem.callback = -1
if has_key(a:options, 'callback')
let newMenuItem.callback = a:options['callback']
endif
if has_key(a:options, 'parent')
call add(a:options['parent'].children, newMenuItem)
else
call add(s:MenuItem.All(), newMenuItem)
endif
return newMenuItem
endfunction
"FUNCTION: MenuItem.CreateSeparator(options) {{{1
"make a new separator menu item and add it to the global list
function! s:MenuItem.CreateSeparator(options)
let standard_options = { 'text': '--------------------',
\ 'shortcut': -1,
\ 'callback': -1 }
let options = extend(a:options, standard_options, "force")
return s:MenuItem.Create(options)
endfunction
"FUNCTION: MenuItem.CreateSubmenu(options) {{{1
"make a new submenu and add it to global list
function! s:MenuItem.CreateSubmenu(options)
let standard_options = { 'callback': -1 }
let options = extend(a:options, standard_options, "force")
return s:MenuItem.Create(options)
endfunction
"FUNCTION: MenuItem.enabled() {{{1
"return 1 if this menu item should be displayed
"
"delegates off to the isActiveCallback, and defaults to 1 if no callback was
"specified
function! s:MenuItem.enabled()
if self.isActiveCallback != -1
return {self.isActiveCallback}()
endif
return 1
endfunction
"FUNCTION: MenuItem.execute() {{{1
"perform the action behind this menu item, if this menuitem has children then
"display a new menu for them, otherwise deletegate off to the menuitem's
"callback
function! s:MenuItem.execute()
if len(self.children)
let mc = g:NERDTreeMenuController.New(self.children)
call mc.showMenu()
else
if self.callback != -1
call {self.callback}()
endif
endif
endfunction
"FUNCTION: MenuItem.isSeparator() {{{1
"return 1 if this menuitem is a separator
function! s:MenuItem.isSeparator()
return self.callback == -1 && self.children == []
endfunction
"FUNCTION: MenuItem.isSubmenu() {{{1
"return 1 if this menuitem is a submenu
function! s:MenuItem.isSubmenu()
return self.callback == -1 && !empty(self.children)
endfunction
" vim: set sw=4 sts=4 et fdm=marker:

208
lib/nerdtree/nerdtree.vim Normal file
View File

@ -0,0 +1,208 @@
"CLASS: NERDTree
"============================================================
let s:NERDTree = {}
let g:NERDTree = s:NERDTree
"FUNCTION: s:NERDTree.AddPathFilter() {{{1
function! s:NERDTree.AddPathFilter(callback)
call add(s:NERDTree.PathFilters(), a:callback)
endfunction
"FUNCTION: s:NERDTree.changeRoot(node) {{{1
function! s:NERDTree.changeRoot(node)
if a:node.path.isDirectory
let self.root = a:node
else
call a:node.cacheParent()
let self.root = a:node.parent
endif
call self.root.open()
"change dir to the dir of the new root if instructed to
if g:NERDTreeChDirMode ==# 2
call self.root.path.changeToDir()
endif
call self.render()
call self.root.putCursorHere(0, 0)
silent doautocmd User NERDTreeNewRoot
endfunction
"FUNCTION: s:NERDTree.Close() {{{1
"Closes the tab tree window for this tab
function! s:NERDTree.Close()
if !s:NERDTree.IsOpen()
return
endif
if winnr("$") != 1
" Use the window ID to identify the currently active window or fall
" back on the buffer ID if win_getid/win_gotoid are not available, in
" which case we'll focus an arbitrary window showing the buffer.
let l:useWinId = exists('*win_getid') && exists('*win_gotoid')
if winnr() == s:NERDTree.GetWinNum()
call nerdtree#exec("wincmd p")
let l:activeBufOrWin = l:useWinId ? win_getid() : bufnr("")
call nerdtree#exec("wincmd p")
else
let l:activeBufOrWin = l:useWinId ? win_getid() : bufnr("")
endif
call nerdtree#exec(s:NERDTree.GetWinNum() . " wincmd w")
close
if l:useWinId
call nerdtree#exec("call win_gotoid(" . l:activeBufOrWin . ")")
else
call nerdtree#exec(bufwinnr(l:activeBufOrWin) . " wincmd w")
endif
else
close
endif
endfunction
"FUNCTION: s:NERDTree.CloseIfQuitOnOpen() {{{1
"Closes the NERD tree window if the close on open option is set
function! s:NERDTree.CloseIfQuitOnOpen()
if g:NERDTreeQuitOnOpen && s:NERDTree.IsOpen()
call s:NERDTree.Close()
endif
endfunction
"FUNCTION: s:NERDTree.CursorToBookmarkTable(){{{1
"Places the cursor at the top of the bookmarks table
function! s:NERDTree.CursorToBookmarkTable()
if !b:NERDTree.ui.getShowBookmarks()
throw "NERDTree.IllegalOperationError: cant find bookmark table, bookmarks arent active"
endif
if g:NERDTreeMinimalUI
return cursor(1, 2)
endif
let rootNodeLine = b:NERDTree.ui.getRootLineNum()
let line = 1
while getline(line) !~# '^>-\+Bookmarks-\+$'
let line = line + 1
if line >= rootNodeLine
throw "NERDTree.BookmarkTableNotFoundError: didnt find the bookmarks table"
endif
endwhile
call cursor(line, 2)
endfunction
"FUNCTION: s:NERDTree.CursorToTreeWin(){{{1
"Places the cursor in the nerd tree window
function! s:NERDTree.CursorToTreeWin()
call g:NERDTree.MustBeOpen()
call nerdtree#exec(g:NERDTree.GetWinNum() . "wincmd w")
endfunction
" Function: s:NERDTree.ExistsForBuffer() {{{1
" Returns 1 if a nerd tree root exists in the current buffer
function! s:NERDTree.ExistsForBuf()
return exists("b:NERDTree")
endfunction
" Function: s:NERDTree.ExistsForTab() {{{1
" Returns 1 if a nerd tree root exists in the current tab
function! s:NERDTree.ExistsForTab()
if !exists("t:NERDTreeBufName")
return
end
"check b:NERDTree is still there and hasn't been e.g. :bdeleted
return !empty(getbufvar(bufnr(t:NERDTreeBufName), 'NERDTree'))
endfunction
function! s:NERDTree.ForCurrentBuf()
if s:NERDTree.ExistsForBuf()
return b:NERDTree
else
return {}
endif
endfunction
"FUNCTION: s:NERDTree.ForCurrentTab() {{{1
function! s:NERDTree.ForCurrentTab()
if !s:NERDTree.ExistsForTab()
return
endif
let bufnr = bufnr(t:NERDTreeBufName)
return getbufvar(bufnr, "NERDTree")
endfunction
"FUNCTION: s:NERDTree.getRoot() {{{1
function! s:NERDTree.getRoot()
return self.root
endfunction
"FUNCTION: s:NERDTree.GetWinNum() {{{1
"gets the nerd tree window number for this tab
function! s:NERDTree.GetWinNum()
if exists("t:NERDTreeBufName")
return bufwinnr(t:NERDTreeBufName)
endif
return -1
endfunction
"FUNCTION: s:NERDTree.IsOpen() {{{1
function! s:NERDTree.IsOpen()
return s:NERDTree.GetWinNum() != -1
endfunction
"FUNCTION: s:NERDTree.isTabTree() {{{1
function! s:NERDTree.isTabTree()
return self._type == "tab"
endfunction
"FUNCTION: s:NERDTree.isWinTree() {{{1
function! s:NERDTree.isWinTree()
return self._type == "window"
endfunction
"FUNCTION: s:NERDTree.MustBeOpen() {{{1
function! s:NERDTree.MustBeOpen()
if !s:NERDTree.IsOpen()
throw "NERDTree.TreeNotOpen"
endif
endfunction
"FUNCTION: s:NERDTree.New() {{{1
function! s:NERDTree.New(path, type)
let newObj = copy(self)
let newObj.ui = g:NERDTreeUI.New(newObj)
let newObj.root = g:NERDTreeDirNode.New(a:path, newObj)
let newObj._type = a:type
return newObj
endfunction
"FUNCTION: s:NERDTree.PathFilters() {{{1
function! s:NERDTree.PathFilters()
if !exists('s:NERDTree._PathFilters')
let s:NERDTree._PathFilters = []
endif
return s:NERDTree._PathFilters
endfunction
"FUNCTION: s:NERDTree.previousBuf() {{{1
function! s:NERDTree.previousBuf()
return self._previousBuf
endfunction
function! s:NERDTree.setPreviousBuf(bnum)
let self._previousBuf = a:bnum
endfunction
"FUNCTION: s:NERDTree.render() {{{1
"A convenience function - since this is called often
function! s:NERDTree.render()
call self.ui.render()
endfunction
" vim: set sw=4 sts=4 et fdm=marker:

34
lib/nerdtree/notifier.vim Normal file
View File

@ -0,0 +1,34 @@
"CLASS: Notifier
"============================================================
let s:Notifier = {}
function! s:Notifier.AddListener(event, funcname)
let listeners = s:Notifier.GetListenersForEvent(a:event)
if listeners == []
let listenersMap = s:Notifier.GetListenersMap()
let listenersMap[a:event] = listeners
endif
call add(listeners, a:funcname)
endfunction
function! s:Notifier.NotifyListeners(event, path, nerdtree, params)
let event = g:NERDTreeEvent.New(a:nerdtree, a:path, a:event, a:params)
for listener in s:Notifier.GetListenersForEvent(a:event)
call {listener}(event)
endfor
endfunction
function! s:Notifier.GetListenersMap()
if !exists("s:refreshListenersMap")
let s:refreshListenersMap = {}
endif
return s:refreshListenersMap
endfunction
function! s:Notifier.GetListenersForEvent(name)
let listenersMap = s:Notifier.GetListenersMap()
return get(listenersMap, a:name, [])
endfunction
let g:NERDTreePathNotifier = deepcopy(s:Notifier)

352
lib/nerdtree/opener.vim Normal file
View File

@ -0,0 +1,352 @@
" ============================================================================
" CLASS: Opener
"
" The Opener class defines an API for "opening" operations.
" ============================================================================
let s:Opener = {}
let g:NERDTreeOpener = s:Opener
" FUNCTION: s:Opener._bufInWindows(bnum) {{{1
" [[STOLEN FROM VTREEEXPLORER.VIM]]
" Determine the number of windows open to this buffer number.
" Care of Yegappan Lakshman. Thanks!
"
" Args:
" bnum: the subject buffers buffer number
function! s:Opener._bufInWindows(bnum)
let cnt = 0
let winnum = 1
while 1
let bufnum = winbufnr(winnum)
if bufnum < 0
break
endif
if bufnum ==# a:bnum
let cnt = cnt + 1
endif
let winnum = winnum + 1
endwhile
return cnt
endfunction
" FUNCTION: Opener._checkToCloseTree(newtab) {{{1
" Check the class options and global options (i.e. NERDTreeQuitOnOpen) to see
" if the tree should be closed now.
"
" Args:
" a:newtab - boolean. If set, only close the tree now if we are opening the
" target in a new tab. This is needed because we have to close tree before we
" leave the tab
function! s:Opener._checkToCloseTree(newtab)
if self._keepopen
return
endif
if (a:newtab && self._where == 't') || !a:newtab
call g:NERDTree.CloseIfQuitOnOpen()
endif
endfunction
" FUNCTION: s:Opener._firstUsableWindow() {{{1
" find the window number of the first normal window
function! s:Opener._firstUsableWindow()
let i = 1
while i <= winnr("$")
let bnum = winbufnr(i)
if bnum != -1 && getbufvar(bnum, '&buftype') ==# ''
\ && !getwinvar(i, '&previewwindow')
\ && (!getbufvar(bnum, '&modified') || &hidden)
return i
endif
let i += 1
endwhile
return -1
endfunction
" FUNCTION: Opener._gotoTargetWin() {{{1
function! s:Opener._gotoTargetWin()
if b:NERDTree.isWinTree()
if self._where == 'v'
vsplit
elseif self._where == 'h'
split
elseif self._where == 't'
tabnew
endif
else
call self._checkToCloseTree(1)
if self._where == 'v'
call self._newVSplit()
elseif self._where == 'h'
call self._newSplit()
elseif self._where == 't'
tabnew
elseif self._where == 'p'
call self._previousWindow()
endif
call self._checkToCloseTree(0)
endif
endfunction
" FUNCTION: s:Opener._isWindowUsable(winnumber) {{{1
" Returns 0 if opening a file from the tree in the given window requires it to
" be split, 1 otherwise
"
" Args:
" winnumber: the number of the window in question
function! s:Opener._isWindowUsable(winnumber)
"gotta split if theres only one window (i.e. the NERD tree)
if winnr("$") ==# 1
return 0
endif
let oldwinnr = winnr()
call nerdtree#exec(a:winnumber . "wincmd p")
let specialWindow = getbufvar("%", '&buftype') != '' || getwinvar('%', '&previewwindow')
let modified = &modified
call nerdtree#exec(oldwinnr . "wincmd p")
"if its a special window e.g. quickfix or another explorer plugin then we
"have to split
if specialWindow
return 0
endif
if &hidden
return 1
endif
return !modified || self._bufInWindows(winbufnr(a:winnumber)) >= 2
endfunction
" FUNCTION: Opener.New(path, opts) {{{1
" Instantiate a new NERDTreeOpener object.
" Args:
" a:path: the path object that is to be opened
" a:opts: a dictionary containing the following optional keys...
" 'where': specifies whether the node should be opened in new split, in
" a new tab or, in the last window; takes values "v", "h", or "t"
" 'reuse': if file is already shown in a window, jump there; takes values
" "all", "currenttab", or empty
" 'keepopen': boolean (0 or 1); if true, the tree window will not be closed
" 'stay': boolean (0 or 1); if true, remain in tree window after opening
function! s:Opener.New(path, opts)
let l:newOpener = copy(self)
let l:newOpener._keepopen = nerdtree#has_opt(a:opts, 'keepopen')
let l:newOpener._nerdtree = b:NERDTree
let l:newOpener._path = a:path
let l:newOpener._reuse = has_key(a:opts, 'reuse') ? a:opts['reuse'] : ''
let l:newOpener._stay = nerdtree#has_opt(a:opts, 'stay')
let l:newOpener._where = has_key(a:opts, 'where') ? a:opts['where'] : ''
call l:newOpener._saveCursorPos()
return l:newOpener
endfunction
" FUNCTION: Opener._newSplit() {{{1
function! s:Opener._newSplit()
" Save the user's settings for splitbelow and splitright
let savesplitbelow=&splitbelow
let savesplitright=&splitright
" 'there' will be set to a command to move from the split window
" back to the explorer window
"
" 'back' will be set to a command to move from the explorer window
" back to the newly split window
"
" 'right' and 'below' will be set to the settings needed for
" splitbelow and splitright IF the explorer is the only window.
"
let there= g:NERDTreeWinPos ==# "left" ? "wincmd h" : "wincmd l"
let back = g:NERDTreeWinPos ==# "left" ? "wincmd l" : "wincmd h"
let right= g:NERDTreeWinPos ==# "left"
let below=0
" Attempt to go to adjacent window
call nerdtree#exec(back)
let onlyOneWin = (winnr("$") ==# 1)
" If no adjacent window, set splitright and splitbelow appropriately
if onlyOneWin
let &splitright=right
let &splitbelow=below
else
" found adjacent window - invert split direction
let &splitright=!right
let &splitbelow=!below
endif
let splitMode = onlyOneWin ? "vertical" : ""
" Open the new window
try
exec(splitMode." sp ")
catch /^Vim\%((\a\+)\)\=:E37/
call g:NERDTree.CursorToTreeWin()
throw "NERDTree.FileAlreadyOpenAndModifiedError: ". self._path.str() ." is already open and modified."
catch /^Vim\%((\a\+)\)\=:/
"do nothing
endtry
"resize the tree window if no other window was open before
if onlyOneWin
let size = exists("b:NERDTreeOldWindowSize") ? b:NERDTreeOldWindowSize : g:NERDTreeWinSize
call nerdtree#exec(there)
exec("silent ". splitMode ." resize ". size)
call nerdtree#exec('wincmd p')
endif
" Restore splitmode settings
let &splitbelow=savesplitbelow
let &splitright=savesplitright
endfunction
" FUNCTION: Opener._newVSplit() {{{1
function! s:Opener._newVSplit()
let l:winwidth = winwidth('.')
if winnr('$') == 1
let l:winwidth = g:NERDTreeWinSize
endif
call nerdtree#exec('wincmd p')
vnew
let l:currentWindowNumber = winnr()
" Restore the NERDTree to its original width.
call g:NERDTree.CursorToTreeWin()
execute 'silent vertical resize ' . l:winwidth
call nerdtree#exec(l:currentWindowNumber . 'wincmd w')
endfunction
" FUNCTION: Opener.open(target) {{{1
function! s:Opener.open(target)
if self._path.isDirectory
call self._openDirectory(a:target)
return
endif
call self._openFile()
endfunction
" FUNCTION: Opener._openFile() {{{1
function! s:Opener._openFile()
if !self._stay && !g:NERDTreeQuitOnOpen && exists("b:NERDTreeZoomed") && b:NERDTreeZoomed
call b:NERDTree.ui.toggleZoom()
endif
if self._reuseWindow()
return
endif
call self._gotoTargetWin()
if self._stay
silent call self._path.edit()
call self._restoreCursorPos()
return
endif
call self._path.edit()
endfunction
" FUNCTION: Opener._openDirectory(node) {{{1
function! s:Opener._openDirectory(node)
call self._gotoTargetWin()
if self._nerdtree.isWinTree()
call g:NERDTreeCreator.CreateWindowTree(a:node.path.str())
else
if empty(self._where)
call b:NERDTree.changeRoot(a:node)
elseif self._where == 't'
call g:NERDTreeCreator.CreateTabTree(a:node.path.str())
else
call g:NERDTreeCreator.CreateWindowTree(a:node.path.str())
endif
endif
if self._stay
call self._restoreCursorPos()
endif
endfunction
" FUNCTION: Opener._previousWindow() {{{1
function! s:Opener._previousWindow()
if !self._isWindowUsable(winnr("#")) && self._firstUsableWindow() ==# -1
call self._newSplit()
else
try
if !self._isWindowUsable(winnr("#"))
call nerdtree#exec(self._firstUsableWindow() . "wincmd w")
else
call nerdtree#exec('wincmd p')
endif
catch /^Vim\%((\a\+)\)\=:E37/
call g:NERDTree.CursorToTreeWin()
throw "NERDTree.FileAlreadyOpenAndModifiedError: ". self._path.str() ." is already open and modified."
catch /^Vim\%((\a\+)\)\=:/
echo v:exception
endtry
endif
endfunction
" FUNCTION: Opener._restoreCursorPos() {{{1
function! s:Opener._restoreCursorPos()
call nerdtree#exec(self._tabnr . 'tabnext')
call nerdtree#exec(bufwinnr(self._bufnr) . 'wincmd w')
endfunction
" FUNCTION: Opener._reuseWindow() {{{1
" put the cursor in the first window we find for this file
"
" return 1 if we were successful
function! s:Opener._reuseWindow()
if empty(self._reuse)
return 0
endif
"check the current tab for the window
let winnr = bufwinnr('^' . self._path.str() . '$')
if winnr != -1
call nerdtree#exec(winnr . "wincmd w")
call self._checkToCloseTree(0)
return 1
endif
if self._reuse == 'currenttab'
return 0
endif
"check other tabs
let tabnr = self._path.tabnr()
if tabnr
call self._checkToCloseTree(1)
call nerdtree#exec(tabnr . 'tabnext')
let winnr = bufwinnr('^' . self._path.str() . '$')
call nerdtree#exec(winnr . "wincmd w")
return 1
endif
return 0
endfunction
" FUNCTION: Opener._saveCursorPos() {{{1
function! s:Opener._saveCursorPos()
let self._bufnr = bufnr("")
let self._tabnr = tabpagenr()
endfunction
" vim: set sw=4 sts=4 et fdm=marker:

869
lib/nerdtree/path.vim Normal file
View File

@ -0,0 +1,869 @@
" ============================================================================
" CLASS: Path
"
" The Path class provides an abstracted representation of a file system
" pathname. Various operations on pathnames are provided and a number of
" representations of a given path name can be accessed here.
" ============================================================================
let s:Path = {}
let g:NERDTreePath = s:Path
" FUNCTION: Path.AbsolutePathFor(pathStr) {{{1
function! s:Path.AbsolutePathFor(pathStr)
let l:prependWorkingDir = 0
if nerdtree#runningWindows()
let l:prependWorkingDir = a:pathStr !~# '^.:\(\\\|\/\)' && a:pathStr !~# '^\(\\\\\|\/\/\)'
else
let l:prependWorkingDir = a:pathStr !~# '^/'
endif
let l:result = a:pathStr
if l:prependWorkingDir
let l:result = getcwd() . s:Path.Slash() . a:pathStr
endif
return l:result
endfunction
" FUNCTION: Path.bookmarkNames() {{{1
function! s:Path.bookmarkNames()
if !exists("self._bookmarkNames")
call self.cacheDisplayString()
endif
return self._bookmarkNames
endfunction
" FUNCTION: Path.cacheDisplayString() {{{1
function! s:Path.cacheDisplayString() abort
let self.cachedDisplayString = g:NERDTreeNodeDelimiter . self.getLastPathComponent(1)
if self.isExecutable
let self.cachedDisplayString = self.addDelimiter(self.cachedDisplayString) . '*'
endif
let self._bookmarkNames = []
for i in g:NERDTreeBookmark.Bookmarks()
if i.path.equals(self)
call add(self._bookmarkNames, i.name)
endif
endfor
if !empty(self._bookmarkNames) && g:NERDTreeMarkBookmarks == 1
let self.cachedDisplayString = self.addDelimiter(self.cachedDisplayString) . ' {' . join(self._bookmarkNames) . '}'
endif
if self.isSymLink
let self.cachedDisplayString = self.addDelimiter(self.cachedDisplayString) . ' -> ' . self.symLinkDest
endif
if self.isReadOnly
let self.cachedDisplayString = self.addDelimiter(self.cachedDisplayString) . ' ['.g:NERDTreeGlyphReadOnly.']'
endif
endfunction
" FUNCTION: Path.addDelimiter() {{{1
function! s:Path.addDelimiter(line)
if a:line =~# '\(.*' . g:NERDTreeNodeDelimiter . '\)\{2}'
return a:line
else
return a:line . g:NERDTreeNodeDelimiter
endif
endfunction
" FUNCTION: Path.changeToDir() {{{1
function! s:Path.changeToDir()
let dir = self.str({'format': 'Cd'})
if self.isDirectory ==# 0
let dir = self.getParent().str({'format': 'Cd'})
endif
try
execute "cd " . dir
call nerdtree#echo("CWD is now: " . getcwd())
catch
throw "NERDTree.PathChangeError: cannot change CWD to " . dir
endtry
endfunction
" FUNCTION: Path.compareTo() {{{1
"
" Compares this Path to the given path and returns 0 if they are equal, -1 if
" this Path is "less than" the given path, or 1 if it is "greater".
"
" Args:
" path: the path object to compare this to
"
" Return:
" 1, -1 or 0
function! s:Path.compareTo(path)
let thisPath = self.getLastPathComponent(1)
let thatPath = a:path.getLastPathComponent(1)
"if the paths are the same then clearly we return 0
if thisPath ==# thatPath
return 0
endif
let thisSS = self.getSortOrderIndex()
let thatSS = a:path.getSortOrderIndex()
"compare the sort sequences, if they are different then the return
"value is easy
if thisSS < thatSS
return -1
elseif thisSS > thatSS
return 1
else
if !g:NERDTreeSortHiddenFirst
let thisPath = substitute(thisPath, '^[._]', '', '')
let thatPath = substitute(thatPath, '^[._]', '', '')
endif
"if the sort sequences are the same then compare the paths
"alphabetically
let pathCompare = g:NERDTreeCaseSensitiveSort ? thisPath <# thatPath : thisPath <? thatPath
if pathCompare
return -1
else
return 1
endif
endif
endfunction
" FUNCTION: Path.Create(fullpath) {{{1
"
" Factory method.
"
" Creates a path object with the given path. The path is also created on the
" filesystem. If the path already exists, a NERDTree.Path.Exists exception is
" thrown. If any other errors occur, a NERDTree.Path exception is thrown.
"
" Args:
" fullpath: the full filesystem path to the file/dir to create
function! s:Path.Create(fullpath)
"bail if the a:fullpath already exists
if isdirectory(a:fullpath) || filereadable(a:fullpath)
throw "NERDTree.CreatePathError: Directory Exists: '" . a:fullpath . "'"
endif
try
"if it ends with a slash, assume its a dir create it
if a:fullpath =~# '\(\\\|\/\)$'
"whack the trailing slash off the end if it exists
let fullpath = substitute(a:fullpath, '\(\\\|\/\)$', '', '')
call mkdir(fullpath, 'p')
"assume its a file and create
else
call s:Path.createParentDirectories(a:fullpath)
call writefile([], a:fullpath)
endif
catch
throw "NERDTree.CreatePathError: Could not create path: '" . a:fullpath . "'"
endtry
return s:Path.New(a:fullpath)
endfunction
" FUNCTION: Path.copy(dest) {{{1
"
" Copies the file/dir represented by this Path to the given location
"
" Args:
" dest: the location to copy this dir/file to
function! s:Path.copy(dest)
if !s:Path.CopyingSupported()
throw "NERDTree.CopyingNotSupportedError: Copying is not supported on this OS"
endif
call s:Path.createParentDirectories(a:dest)
if exists('g:NERDTreeCopyCmd')
let cmd_prefix = g:NERDTreeCopyCmd
else
let cmd_prefix = (self.isDirectory ? g:NERDTreeCopyDirCmd : g:NERDTreeCopyFileCmd)
endif
let cmd = cmd_prefix . " " . escape(self.str(), self._escChars()) . " " . escape(a:dest, self._escChars())
let success = system(cmd)
if v:shell_error != 0
throw "NERDTree.CopyError: Could not copy ''". self.str() ."'' to: '" . a:dest . "'"
endif
endfunction
" FUNCTION: Path.CopyingSupported() {{{1
"
" returns 1 if copying is supported for this OS
function! s:Path.CopyingSupported()
return exists('g:NERDTreeCopyCmd') || (exists('g:NERDTreeCopyDirCmd') && exists('g:NERDTreeCopyFileCmd'))
endfunction
" FUNCTION: Path.copyingWillOverwrite(dest) {{{1
"
" returns 1 if copy this path to the given location will cause files to
" overwritten
"
" Args:
" dest: the location this path will be copied to
function! s:Path.copyingWillOverwrite(dest)
if filereadable(a:dest)
return 1
endif
if isdirectory(a:dest)
let path = s:Path.JoinPathStrings(a:dest, self.getLastPathComponent(0))
if filereadable(path)
return 1
endif
endif
endfunction
" FUNCTION: Path.createParentDirectories(path) {{{1
"
" create parent directories for this path if needed
" without throwing any errors if those directories already exist
"
" Args:
" path: full path of the node whose parent directories may need to be created
function! s:Path.createParentDirectories(path)
let dir_path = fnamemodify(a:path, ':h')
if !isdirectory(dir_path)
call mkdir(dir_path, 'p')
endif
endfunction
" FUNCTION: Path.delete() {{{1
"
" Deletes the file or directory represented by this path.
"
" Throws NERDTree.Path.Deletion exceptions
function! s:Path.delete()
if self.isDirectory
let cmd = g:NERDTreeRemoveDirCmd . self.str({'escape': 1})
let success = system(cmd)
if v:shell_error != 0
throw "NERDTree.PathDeletionError: Could not delete directory: '" . self.str() . "'"
endif
else
if exists('g:NERDTreeRemoveFileCmd')
let cmd = g:NERDTreeRemoveFileCmd . self.str({'escape': 1})
let success = system(cmd)
else
let success = delete(self.str())
endif
if success != 0
throw "NERDTree.PathDeletionError: Could not delete file: '" . self.str() . "'"
endif
endif
"delete all bookmarks for this path
for i in self.bookmarkNames()
let bookmark = g:NERDTreeBookmark.BookmarkFor(i)
call bookmark.delete()
endfor
endfunction
" FUNCTION: Path.displayString() {{{1
"
" Returns a string that specifies how the path should be represented as a
" string
function! s:Path.displayString()
if self.cachedDisplayString ==# ""
call self.cacheDisplayString()
endif
return self.cachedDisplayString
endfunction
" FUNCTION: Path.edit() {{{1
function! s:Path.edit()
exec "edit " . self.str({'format': 'Edit'})
endfunction
" FUNCTION: Path.extractDriveLetter(fullpath) {{{1
"
" If running windows, cache the drive letter for this path
function! s:Path.extractDriveLetter(fullpath)
if nerdtree#runningWindows()
if a:fullpath =~ '^\(\\\\\|\/\/\)'
"For network shares, the 'drive' consists of the first two parts of the path, i.e. \\boxname\share
let self.drive = substitute(a:fullpath, '^\(\(\\\\\|\/\/\)[^\\\/]*\(\\\|\/\)[^\\\/]*\).*', '\1', '')
let self.drive = substitute(self.drive, '/', '\', "g")
else
let self.drive = substitute(a:fullpath, '\(^[a-zA-Z]:\).*', '\1', '')
endif
else
let self.drive = ''
endif
endfunction
" FUNCTION: Path.exists() {{{1
" return 1 if this path points to a location that is readable or is a directory
function! s:Path.exists()
let p = self.str()
return filereadable(p) || isdirectory(p)
endfunction
" FUNCTION: Path._escChars() {{{1
function! s:Path._escChars()
if nerdtree#runningWindows()
return " `\|\"#%&,?()\*^<>$"
endif
return " \\`\|\"#%&,?()\*^<>[]$"
endfunction
" FUNCTION: Path.getDir() {{{1
"
" Returns this path if it is a directory, else this paths parent.
"
" Return:
" a Path object
function! s:Path.getDir()
if self.isDirectory
return self
else
return self.getParent()
endif
endfunction
" FUNCTION: Path.getParent() {{{1
"
" Returns a new path object for this paths parent
"
" Return:
" a new Path object
function! s:Path.getParent()
if nerdtree#runningWindows()
let path = self.drive . '\' . join(self.pathSegments[0:-2], '\')
else
let path = '/'. join(self.pathSegments[0:-2], '/')
endif
return s:Path.New(path)
endfunction
" FUNCTION: Path.getLastPathComponent(dirSlash) {{{1
"
" Gets the last part of this path.
"
" Args:
" dirSlash: if 1 then a trailing slash will be added to the returned value for
" directory nodes.
function! s:Path.getLastPathComponent(dirSlash)
if empty(self.pathSegments)
return ''
endif
let toReturn = self.pathSegments[-1]
if a:dirSlash && self.isDirectory
let toReturn = toReturn . '/'
endif
return toReturn
endfunction
" FUNCTION: Path.getSortOrderIndex() {{{1
" returns the index of the pattern in g:NERDTreeSortOrder that this path matches
function! s:Path.getSortOrderIndex()
let i = 0
while i < len(g:NERDTreeSortOrder)
if self.getLastPathComponent(1) =~# g:NERDTreeSortOrder[i]
return i
endif
let i = i + 1
endwhile
return index(g:NERDTreeSortOrder, '*')
endfunction
" FUNCTION: Path._splitChunks(path) {{{1
" returns a list of path chunks
function! s:Path._splitChunks(path)
let chunks = split(a:path, '\(\D\+\|\d\+\)\zs')
let i = 0
while i < len(chunks)
"convert number literals to numbers
if match(chunks[i], '^\d\+$') == 0
let chunks[i] = str2nr(chunks[i])
endif
let i = i + 1
endwhile
return chunks
endfunction
" FUNCTION: Path.getSortKey() {{{1
" returns a key used in compare function for sorting
function! s:Path.getSortKey()
let l:ascending = index(g:NERDTreeSortOrder,'[[timestamp]]')
let l:descending = index(g:NERDTreeSortOrder,'[[-timestamp]]')
if !exists("self._sortKey") || g:NERDTreeSortOrder !=# g:NERDTreeOldSortOrder || l:ascending >= 0 || l:descending >= 0
let self._sortKey = [self.getSortOrderIndex()]
if l:descending >= 0
call insert(self._sortKey, -getftime(self.str()), l:descending == 0 ? 0 : len(self._sortKey))
elseif l:ascending >= 0
call insert(self._sortKey, getftime(self.str()), l:ascending == 0 ? 0 : len(self._sortKey))
endif
let path = self.getLastPathComponent(1)
if !g:NERDTreeSortHiddenFirst
let path = substitute(path, '^[._]', '', '')
endif
if !g:NERDTreeCaseSensitiveSort
let path = tolower(path)
endif
call extend(self._sortKey, (g:NERDTreeNaturalSort ? self._splitChunks(path) : [path]))
endif
return self._sortKey
endfunction
" FUNCTION: Path.isHiddenUnder(path) {{{1
function! s:Path.isHiddenUnder(path)
if !self.isUnder(a:path)
return 0
endif
let l:startIndex = len(a:path.pathSegments)
let l:segments = self.pathSegments[l:startIndex : ]
for l:segment in l:segments
if l:segment =~# '^\.'
return 1
endif
endfor
return 0
endfunction
" FUNCTION: Path.isUnixHiddenFile() {{{1
" check for unix hidden files
function! s:Path.isUnixHiddenFile()
return self.getLastPathComponent(0) =~# '^\.'
endfunction
" FUNCTION: Path.isUnixHiddenPath() {{{1
" check for unix path with hidden components
function! s:Path.isUnixHiddenPath()
if self.getLastPathComponent(0) =~# '^\.'
return 1
else
for segment in self.pathSegments
if segment =~# '^\.'
return 1
endif
endfor
return 0
endif
endfunction
" FUNCTION: Path.ignore(nerdtree) {{{1
" returns true if this path should be ignored
function! s:Path.ignore(nerdtree)
"filter out the user specified paths to ignore
if a:nerdtree.ui.isIgnoreFilterEnabled()
for i in g:NERDTreeIgnore
if self._ignorePatternMatches(i)
return 1
endif
endfor
for callback in g:NERDTree.PathFilters()
if {callback}({'path': self, 'nerdtree': a:nerdtree})
return 1
endif
endfor
endif
"dont show hidden files unless instructed to
if !a:nerdtree.ui.getShowHidden() && self.isUnixHiddenFile()
return 1
endif
if a:nerdtree.ui.getShowFiles() ==# 0 && self.isDirectory ==# 0
return 1
endif
return 0
endfunction
" FUNCTION: Path._ignorePatternMatches(pattern) {{{1
" returns true if this path matches the given ignore pattern
function! s:Path._ignorePatternMatches(pattern)
let pat = a:pattern
if strpart(pat,len(pat)-7) == '[[dir]]'
if !self.isDirectory
return 0
endif
let pat = strpart(pat,0, len(pat)-7)
elseif strpart(pat,len(pat)-8) == '[[file]]'
if self.isDirectory
return 0
endif
let pat = strpart(pat,0, len(pat)-8)
endif
return self.getLastPathComponent(0) =~# pat
endfunction
" FUNCTION: Path.isAncestor(path) {{{1
" return 1 if this path is somewhere above the given path in the filesystem.
"
" a:path should be a dir
function! s:Path.isAncestor(path)
if !self.isDirectory
return 0
endif
let this = self.str()
let that = a:path.str()
return stridx(that, this) == 0
endfunction
" FUNCTION: Path.isUnder(path) {{{1
" return 1 if this path is somewhere under the given path in the filesystem.
function! s:Path.isUnder(path)
if a:path.isDirectory == 0
return 0
endif
let this = self.str()
let that = a:path.str()
return stridx(this, that . s:Path.Slash()) == 0
endfunction
" FUNCTION: Path.JoinPathStrings(...) {{{1
function! s:Path.JoinPathStrings(...)
let components = []
for i in a:000
let components = extend(components, split(i, '/'))
endfor
return '/' . join(components, '/')
endfunction
" FUNCTION: Path.equals() {{{1
"
" Determines whether 2 path objects are "equal".
" They are equal if the paths they represent are the same
"
" Args:
" path: the other path obj to compare this with
function! s:Path.equals(path)
return self.str() ==# a:path.str()
endfunction
" FUNCTION: Path.New(pathStr) {{{1
function! s:Path.New(pathStr)
let l:newPath = copy(self)
call l:newPath.readInfoFromDisk(s:Path.AbsolutePathFor(a:pathStr))
let l:newPath.cachedDisplayString = ''
let l:newPath.flagSet = g:NERDTreeFlagSet.New()
return l:newPath
endfunction
" FUNCTION: Path.Slash() {{{1
" Return the path separator used by the underlying file system. Special
" consideration is taken for the use of the 'shellslash' option on Windows
" systems.
function! s:Path.Slash()
if nerdtree#runningWindows()
if exists('+shellslash') && &shellslash
return '/'
endif
return '\'
endif
return '/'
endfunction
" FUNCTION: Path.Resolve() {{{1
" Invoke the vim resolve() function and return the result
" This is necessary because in some versions of vim resolve() removes trailing
" slashes while in other versions it doesn't. This always removes the trailing
" slash
function! s:Path.Resolve(path)
let tmp = resolve(a:path)
return tmp =~# '.\+/$' ? substitute(tmp, '/$', '', '') : tmp
endfunction
" FUNCTION: Path.readInfoFromDisk(fullpath) {{{1
"
"
" Throws NERDTree.Path.InvalidArguments exception.
function! s:Path.readInfoFromDisk(fullpath)
call self.extractDriveLetter(a:fullpath)
let fullpath = s:Path.WinToUnixPath(a:fullpath)
if getftype(fullpath) ==# "fifo"
throw "NERDTree.InvalidFiletypeError: Cant handle FIFO files: " . a:fullpath
endif
let self.pathSegments = filter(split(fullpath, '/'), '!empty(v:val)')
let self.isReadOnly = 0
if isdirectory(a:fullpath)
let self.isDirectory = 1
elseif filereadable(a:fullpath)
let self.isDirectory = 0
let self.isReadOnly = filewritable(a:fullpath) ==# 0
else
throw "NERDTree.InvalidArgumentsError: Invalid path = " . a:fullpath
endif
let self.isExecutable = 0
if !self.isDirectory
let self.isExecutable = getfperm(a:fullpath) =~# 'x'
endif
"grab the last part of the path (minus the trailing slash)
let lastPathComponent = self.getLastPathComponent(0)
"get the path to the new node with the parent dir fully resolved
let hardPath = s:Path.Resolve(self.strTrunk()) . '/' . lastPathComponent
"if the last part of the path is a symlink then flag it as such
let self.isSymLink = (s:Path.Resolve(hardPath) != hardPath)
if self.isSymLink
let self.symLinkDest = s:Path.Resolve(fullpath)
"if the link is a dir then slap a / on the end of its dest
if isdirectory(self.symLinkDest)
"we always wanna treat MS windows shortcuts as files for
"simplicity
if hardPath !~# '\.lnk$'
let self.symLinkDest = self.symLinkDest . '/'
endif
endif
endif
endfunction
" FUNCTION: Path.refresh(nerdtree) {{{1
function! s:Path.refresh(nerdtree)
call self.readInfoFromDisk(self.str())
call g:NERDTreePathNotifier.NotifyListeners('refresh', self, a:nerdtree, {})
call self.cacheDisplayString()
endfunction
" FUNCTION: Path.refreshFlags(nerdtree) {{{1
function! s:Path.refreshFlags(nerdtree)
call g:NERDTreePathNotifier.NotifyListeners('refreshFlags', self, a:nerdtree, {})
call self.cacheDisplayString()
endfunction
" FUNCTION: Path.rename() {{{1
"
" Renames this node on the filesystem
function! s:Path.rename(newPath)
if a:newPath ==# ''
throw "NERDTree.InvalidArgumentsError: Invalid newPath for renaming = ". a:newPath
endif
call s:Path.createParentDirectories(a:newPath)
let success = rename(self.str(), a:newPath)
if success != 0
throw "NERDTree.PathRenameError: Could not rename: '" . self.str() . "'" . 'to:' . a:newPath
endif
call self.readInfoFromDisk(a:newPath)
for i in self.bookmarkNames()
let b = g:NERDTreeBookmark.BookmarkFor(i)
call b.setPath(copy(self))
endfor
call g:NERDTreeBookmark.Write()
endfunction
" FUNCTION: Path.str() {{{1
" Return a string representation of this Path object.
"
" Args:
" This function takes a single dictionary (optional) with keys and values that
" specify how the returned pathname should be formatted.
"
" The dictionary may have the following keys:
" 'format'
" 'escape'
" 'truncateTo'
"
" The 'format' key may have a value of:
" 'Cd' - a string to be used with ":cd" and similar commands
" 'Edit' - a string to be used with ":edit" and similar commands
" 'UI' - a string to be displayed in the NERDTree user interface
"
" The 'escape' key, if specified, will cause the output to be escaped with
" Vim's internal "shellescape()" function.
"
" The 'truncateTo' key shortens the length of the path to that given by the
" value associated with 'truncateTo'. A '<' is prepended.
function! s:Path.str(...)
let options = a:0 ? a:1 : {}
let toReturn = ""
if has_key(options, 'format')
let format = options['format']
if has_key(self, '_strFor' . format)
exec 'let toReturn = self._strFor' . format . '()'
else
throw 'NERDTree.UnknownFormatError: unknown format "'. format .'"'
endif
else
let toReturn = self._str()
endif
if nerdtree#has_opt(options, 'escape')
let toReturn = shellescape(toReturn)
endif
if has_key(options, 'truncateTo')
let limit = options['truncateTo']
if strdisplaywidth(toReturn) > limit-1
while strdisplaywidth(toReturn) > limit-1 && strchars(toReturn) > 0
let toReturn = substitute(toReturn, '^.', '', '')
endwhile
if len(split(toReturn, '/')) > 1
let toReturn = '</' . join(split(toReturn, '/')[1:], '/') . '/'
else
let toReturn = '<' . toReturn
endif
endif
endif
return toReturn
endfunction
" FUNCTION: Path._strForUI() {{{1
function! s:Path._strForUI()
let toReturn = '/' . join(self.pathSegments, '/')
if self.isDirectory && toReturn != '/'
let toReturn = toReturn . '/'
endif
return toReturn
endfunction
" FUNCTION: Path._strForCd() {{{1
" Return a string representation of this Path that is suitable for use as an
" argument to Vim's internal ":cd" command.
function! s:Path._strForCd()
return fnameescape(self.str())
endfunction
" FUNCTION: Path._strForEdit() {{{1
" Return a string representation of this Path that is suitable for use as an
" argument to Vim's internal ":edit" command.
function! s:Path._strForEdit()
" Make the path relative to the current working directory, if possible.
let l:result = fnamemodify(self.str(), ':.')
" On Windows, the drive letter may be removed by "fnamemodify()". Add it
" back, if necessary.
if nerdtree#runningWindows() && l:result[0] == s:Path.Slash()
let l:result = self.drive . l:result
endif
let l:result = fnameescape(l:result)
if empty(l:result)
let l:result = '.'
endif
return l:result
endfunction
" FUNCTION: Path._strForGlob() {{{1
function! s:Path._strForGlob()
let lead = s:Path.Slash()
"if we are running windows then slap a drive letter on the front
if nerdtree#runningWindows()
let lead = self.drive . '\'
endif
let toReturn = lead . join(self.pathSegments, s:Path.Slash())
if !nerdtree#runningWindows()
let toReturn = escape(toReturn, self._escChars())
endif
return toReturn
endfunction
" FUNCTION: Path._str() {{{1
" Return the absolute pathname associated with this Path object. The pathname
" returned is appropriate for the underlying file system.
function! s:Path._str()
let l:separator = s:Path.Slash()
let l:leader = l:separator
if nerdtree#runningWindows()
let l:leader = self.drive . l:separator
endif
return l:leader . join(self.pathSegments, l:separator)
endfunction
" FUNCTION: Path.strTrunk() {{{1
" Gets the path without the last segment on the end.
function! s:Path.strTrunk()
return self.drive . '/' . join(self.pathSegments[0:-2], '/')
endfunction
" FUNCTION: Path.tabnr() {{{1
" return the number of the first tab that is displaying this file
"
" return 0 if no tab was found
function! s:Path.tabnr()
let str = self.str()
for t in range(tabpagenr('$'))
for b in tabpagebuflist(t+1)
if str ==# expand('#' . b . ':p')
return t+1
endif
endfor
endfor
return 0
endfunction
" FUNCTION: Path.WinToUnixPath(pathstr){{{1
" Takes in a windows path and returns the unix equiv
"
" A class level method
"
" Args:
" pathstr: the windows path to convert
function! s:Path.WinToUnixPath(pathstr)
if !nerdtree#runningWindows()
return a:pathstr
endif
let toReturn = a:pathstr
"remove the x:\ of the front
let toReturn = substitute(toReturn, '^.*:\(\\\|/\)\?', '/', "")
"remove the \\ network share from the front
let toReturn = substitute(toReturn, '^\(\\\\\|\/\/\)[^\\\/]*\(\\\|\/\)[^\\\/]*\(\\\|\/\)\?', '/', "")
"convert all \ chars to /
let toReturn = substitute(toReturn, '\', '/', "g")
return toReturn
endfunction
" vim: set sw=4 sts=4 et fdm=marker:

View File

@ -0,0 +1,679 @@
" ============================================================================
" CLASS: TreeDirNode
"
" A subclass of NERDTreeFileNode.
"
" The 'composite' part of the file/dir composite.
" ============================================================================
let s:TreeDirNode = copy(g:NERDTreeFileNode)
let g:NERDTreeDirNode = s:TreeDirNode
" FUNCTION: TreeDirNode.AbsoluteTreeRoot(){{{1
" Class method that returns the highest cached ancestor of the current root.
function! s:TreeDirNode.AbsoluteTreeRoot()
let currentNode = b:NERDTree.root
while currentNode.parent != {}
let currentNode = currentNode.parent
endwhile
return currentNode
endfunction
" FUNCTION: TreeDirNode.activate([options]) {{{1
function! s:TreeDirNode.activate(...)
let l:options = (a:0 > 0) ? a:1 : {}
call self.toggleOpen(l:options)
" Note that we only re-render the NERDTree for this node if we did NOT
" create a new node and render it in a new window or tab. In the latter
" case, rendering the NERDTree for this node could overwrite the text of
" the new NERDTree!
if !has_key(l:options, 'where') || empty(l:options['where'])
call self.getNerdtree().render()
call self.putCursorHere(0, 0)
endif
endfunction
" FUNCTION: TreeDirNode.addChild(treenode, inOrder) {{{1
" Adds the given treenode to the list of children for this node
"
" Args:
" -treenode: the node to add
" -inOrder: 1 if the new node should be inserted in sorted order
function! s:TreeDirNode.addChild(treenode, inOrder)
call add(self.children, a:treenode)
let a:treenode.parent = self
if a:inOrder
call self.sortChildren()
endif
endfunction
" FUNCTION: TreeDirNode.close() {{{1
" Mark this TreeDirNode as closed.
function! s:TreeDirNode.close()
" Close all directories in this directory node's cascade. This is
" necessary to ensure consistency when cascades are rendered.
for l:dirNode in self.getCascade()
let l:dirNode.isOpen = 0
endfor
endfunction
" FUNCTION: TreeDirNode.closeChildren() {{{1
" Recursively close any directory nodes that are descendants of this node.
function! s:TreeDirNode.closeChildren()
for l:child in self.children
if l:child.path.isDirectory
call l:child.close()
call l:child.closeChildren()
endif
endfor
endfunction
" FUNCTION: TreeDirNode.createChild(path, inOrder) {{{1
" Instantiates a new child node for this node with the given path. The new
" nodes parent is set to this node.
"
" Args:
" path: a Path object that this node will represent/contain
" inOrder: 1 if the new node should be inserted in sorted order
"
" Returns:
" the newly created node
function! s:TreeDirNode.createChild(path, inOrder)
let newTreeNode = g:NERDTreeFileNode.New(a:path, self.getNerdtree())
call self.addChild(newTreeNode, a:inOrder)
return newTreeNode
endfunction
" FUNCTION: TreeDirNode.displayString() {{{1
" Assemble and return a string that can represent this TreeDirNode object in
" the NERDTree window.
function! s:TreeDirNode.displayString()
let l:result = ''
" Build a label that identifies this TreeDirNode.
let l:label = ''
let l:cascade = self.getCascade()
for l:dirNode in l:cascade
let l:next = l:dirNode.path.displayString()
let l:label .= l:label == '' ? l:next : strcharpart(l:next,1)
endfor
" Select the appropriate open/closed status indicator symbol.
if l:cascade[-1].isOpen
let l:symbol = g:NERDTreeDirArrowCollapsible
else
let l:symbol = g:NERDTreeDirArrowExpandable
endif
let l:flags = l:cascade[-1].path.flagSet.renderToString()
let l:result = l:symbol . ' ' . l:flags . l:label
return l:result
endfunction
" FUNCTION: TreeDirNode.findNode(path) {{{1
" Will find one of the children (recursively) that has the given path
"
" Args:
" path: a path object
unlet s:TreeDirNode.findNode
function! s:TreeDirNode.findNode(path)
if a:path.equals(self.path)
return self
endif
if stridx(a:path.str(), self.path.str(), 0) ==# -1
return {}
endif
if self.path.isDirectory
for i in self.children
let retVal = i.findNode(a:path)
if retVal != {}
return retVal
endif
endfor
endif
return {}
endfunction
" FUNCTION: TreeDirNode.getCascade() {{{1
" Return an array of dir nodes (starting from self) that can be cascade opened.
function! s:TreeDirNode.getCascade()
if !self.isCascadable()
return [self]
endif
let vc = self.getVisibleChildren()
let visChild = vc[0]
return [self] + visChild.getCascade()
endfunction
" FUNCTION: TreeDirNode.getCascadeRoot() {{{1
" Return the first directory node in the cascade in which this directory node
" is rendered.
function! s:TreeDirNode.getCascadeRoot()
" Don't search above the current NERDTree root node.
if self.isRoot()
return self
endif
let l:cascadeRoot = self
let l:parent = self.parent
while !empty(l:parent) && !l:parent.isRoot()
if index(l:parent.getCascade(), self) == -1
break
endif
let l:cascadeRoot = l:parent
let l:parent = l:parent.parent
endwhile
return l:cascadeRoot
endfunction
" FUNCTION: TreeDirNode.getChildCount() {{{1
" Returns the number of children this node has
function! s:TreeDirNode.getChildCount()
return len(self.children)
endfunction
" FUNCTION: TreeDirNode.getChild(path) {{{1
" Returns child node of this node that has the given path or {} if no such node
" exists.
"
" This function doesnt not recurse into child dir nodes
"
" Args:
" path: a path object
function! s:TreeDirNode.getChild(path)
if stridx(a:path.str(), self.path.str(), 0) ==# -1
return {}
endif
let index = self.getChildIndex(a:path)
if index ==# -1
return {}
else
return self.children[index]
endif
endfunction
" FUNCTION: TreeDirNode.getChildByIndex(indx, visible) {{{1
" returns the child at the given index
"
" Args:
" indx: the index to get the child from
" visible: 1 if only the visible children array should be used, 0 if all the
" children should be searched.
function! s:TreeDirNode.getChildByIndex(indx, visible)
let array_to_search = a:visible? self.getVisibleChildren() : self.children
if a:indx > len(array_to_search)
throw "NERDTree.InvalidArgumentsError: Index is out of bounds."
endif
return array_to_search[a:indx]
endfunction
" FUNCTION: TreeDirNode.getChildIndex(path) {{{1
" Returns the index of the child node of this node that has the given path or
" -1 if no such node exists.
"
" This function doesnt not recurse into child dir nodes
"
" Args:
" path: a path object
function! s:TreeDirNode.getChildIndex(path)
if stridx(a:path.str(), self.path.str(), 0) ==# -1
return -1
endif
"do a binary search for the child
let a = 0
let z = self.getChildCount()
while a < z
let mid = (a+z)/2
let diff = a:path.compareTo(self.children[mid].path)
if diff ==# -1
let z = mid
elseif diff ==# 1
let a = mid+1
else
return mid
endif
endwhile
return -1
endfunction
" FUNCTION: TreeDirNode._glob(pattern, all) {{{1
" Return a list of strings naming the descendants of the directory in this
" TreeDirNode object that match the specified glob pattern.
"
" Args:
" pattern: (string) the glob pattern to apply
" all: (0 or 1) if 1, include "." and ".." if they match "pattern"; if 0,
" always exclude them
"
" Note: If the pathnames in the result list are below the working directory,
" they are returned as pathnames relative to that directory. This is because
" this function, internally, attempts to obey 'wildignore' rules that use
" relative paths.
function! s:TreeDirNode._glob(pattern, all)
" Construct a path specification such that "globpath()" will return
" relative pathnames, if possible.
if self.path.str() == getcwd()
let l:pathSpec = ','
else
let l:pathSpec = escape(fnamemodify(self.path.str({'format': 'Glob'}), ':.'), ',')
" On Windows, the drive letter may be removed by "fnamemodify()".
if nerdtree#runningWindows() && l:pathSpec[0] == g:NERDTreePath.Slash()
let l:pathSpec = self.path.drive . l:pathSpec
endif
endif
let l:globList = []
" See ":h version7.txt" and ":h version8.txt" for details on the
" development of the "glob()" and "globpath()" functions.
if v:version > 704 || (v:version == 704 && has('patch654'))
let l:globList = globpath(l:pathSpec, a:pattern, !g:NERDTreeRespectWildIgnore, 1, 0)
elseif v:version == 704 && has('patch279')
let l:globList = globpath(l:pathSpec, a:pattern, !g:NERDTreeRespectWildIgnore, 1)
elseif v:version > 702 || (v:version == 702 && has('patch051'))
let l:globString = globpath(l:pathSpec, a:pattern, !g:NERDTreeRespectWildIgnore)
let l:globList = split(l:globString, "\n")
else
let l:globString = globpath(l:pathSpec, a:pattern)
let l:globList = split(l:globString, "\n")
endif
" If "a:all" is false, filter "." and ".." from the output.
if !a:all
let l:toRemove = []
for l:file in l:globList
let l:tail = fnamemodify(l:file, ':t')
" If l:file has a trailing slash, then its :tail will be ''. Use
" :h to drop the slash and the empty string after it; then use :t
" to get the directory name.
if l:tail == ''
let l:tail = fnamemodify(l:file, ':h:t')
endif
if l:tail == '.' || l:tail == '..'
call add(l:toRemove, l:file)
if len(l:toRemove) == 2
break
endif
endif
endfor
for l:file in l:toRemove
call remove(l:globList, index(l:globList, l:file))
endfor
endif
return l:globList
endfunction
" FUNCTION: TreeDirNode.GetSelected() {{{1
" Returns the current node if it is a dir node, or else returns the current
" nodes parent
unlet s:TreeDirNode.GetSelected
function! s:TreeDirNode.GetSelected()
let currentDir = g:NERDTreeFileNode.GetSelected()
if currentDir != {} && !currentDir.isRoot()
if currentDir.path.isDirectory ==# 0
let currentDir = currentDir.parent
endif
endif
return currentDir
endfunction
" FUNCTION: TreeDirNode.getVisibleChildCount() {{{1
" Returns the number of visible children this node has
function! s:TreeDirNode.getVisibleChildCount()
return len(self.getVisibleChildren())
endfunction
" FUNCTION: TreeDirNode.getVisibleChildren() {{{1
" Returns a list of children to display for this node, in the correct order
"
" Return:
" an array of treenodes
function! s:TreeDirNode.getVisibleChildren()
let toReturn = []
for i in self.children
if i.path.ignore(self.getNerdtree()) ==# 0
call add(toReturn, i)
endif
endfor
return toReturn
endfunction
" FUNCTION: TreeDirNode.hasVisibleChildren() {{{1
" returns 1 if this node has any childre, 0 otherwise..
function! s:TreeDirNode.hasVisibleChildren()
return self.getVisibleChildCount() != 0
endfunction
" FUNCTION: TreeDirNode.isCascadable() {{{1
" true if this dir has only one visible child - which is also a dir
function! s:TreeDirNode.isCascadable()
if g:NERDTreeCascadeSingleChildDir == 0
return 0
endif
let c = self.getVisibleChildren()
return len(c) == 1 && c[0].path.isDirectory
endfunction
" FUNCTION: TreeDirNode._initChildren() {{{1
" Removes all childen from this node and re-reads them
"
" Args:
" silent: 1 if the function should not echo any "please wait" messages for
" large directories
"
" Return: the number of child nodes read
function! s:TreeDirNode._initChildren(silent)
"remove all the current child nodes
let self.children = []
let files = self._glob('*', 1) + self._glob('.*', 0)
if !a:silent && len(files) > g:NERDTreeNotificationThreshold
call nerdtree#echo("Please wait, caching a large dir ...")
endif
let invalidFilesFound = 0
for i in files
try
let path = g:NERDTreePath.New(i)
call self.createChild(path, 0)
call g:NERDTreePathNotifier.NotifyListeners('init', path, self.getNerdtree(), {})
catch /^NERDTree.\(InvalidArguments\|InvalidFiletype\)Error/
let invalidFilesFound += 1
endtry
endfor
call self.sortChildren()
if !a:silent && len(files) > g:NERDTreeNotificationThreshold
call nerdtree#echo("Please wait, caching a large dir ... DONE (". self.getChildCount() ." nodes cached).")
endif
if invalidFilesFound
call nerdtree#echoWarning(invalidFilesFound . " file(s) could not be loaded into the NERD tree")
endif
return self.getChildCount()
endfunction
" FUNCTION: TreeDirNode.New(path, nerdtree) {{{1
" Return a new TreeDirNode object with the given path and parent.
"
" Args:
" path: dir that the node represents
" nerdtree: the tree the node belongs to
function! s:TreeDirNode.New(path, nerdtree)
if a:path.isDirectory != 1
throw "NERDTree.InvalidArgumentsError: A TreeDirNode object must be instantiated with a directory Path object."
endif
let newTreeNode = copy(self)
let newTreeNode.path = a:path
let newTreeNode.isOpen = 0
let newTreeNode.children = []
let newTreeNode.parent = {}
let newTreeNode._nerdtree = a:nerdtree
return newTreeNode
endfunction
" FUNCTION: TreeDirNode.open([options]) {{{1
" Open this directory node in the current tree or elsewhere if special options
" are provided. Return 0 if options were processed. Otherwise, return the
" number of new cached nodes.
function! s:TreeDirNode.open(...)
let l:options = a:0 ? a:1 : {}
" If special options were specified, process them and return.
if has_key(l:options, 'where') && !empty(l:options['where'])
let l:opener = g:NERDTreeOpener.New(self.path, l:options)
call l:opener.open(self)
return 0
endif
" Open any ancestors of this node that render within the same cascade.
let l:parent = self.parent
while !empty(l:parent) && !l:parent.isRoot()
if index(l:parent.getCascade(), self) >= 0
let l:parent.isOpen = 1
let l:parent = l:parent.parent
else
break
endif
endwhile
let self.isOpen = 1
let l:numChildrenCached = 0
if empty(self.children)
let l:numChildrenCached = self._initChildren(0)
endif
return l:numChildrenCached
endfunction
" FUNCTION: TreeDirNode.openAlong([opts]) {{{1
" recursive open the dir if it has only one directory child.
"
" return the level of opened directories.
function! s:TreeDirNode.openAlong(...)
let opts = a:0 ? a:1 : {}
let level = 0
let node = self
while node.path.isDirectory
call node.open(opts)
let level += 1
if node.getVisibleChildCount() == 1
let node = node.getChildByIndex(0, 1)
else
break
endif
endwhile
return level
endfunction
" FUNCTION: TreeDirNode.openExplorer() {{{1
" Open an explorer window for this node in the previous window. The explorer
" can be a NERDTree window or a netrw window.
function! s:TreeDirNode.openExplorer()
call self.open({'where': 'p'})
endfunction
" FUNCTION: TreeDirNode.openInNewTab(options) {{{1
unlet s:TreeDirNode.openInNewTab
function! s:TreeDirNode.openInNewTab(options)
call nerdtree#deprecated('TreeDirNode.openInNewTab', 'is deprecated, use open() instead')
call self.open({'where': 't'})
endfunction
" FUNCTION: TreeDirNode._openInNewTab() {{{1
function! s:TreeDirNode._openInNewTab()
tabnew
call g:NERDTreeCreator.CreateTabTree(self.path.str())
endfunction
" FUNCTION: TreeDirNode.openRecursively() {{{1
" Open this directory node and any descendant directory nodes whose pathnames
" are not ignored.
function! s:TreeDirNode.openRecursively()
silent call self.open()
for l:child in self.children
if l:child.path.isDirectory && !l:child.path.ignore(l:child.getNerdtree())
call l:child.openRecursively()
endif
endfor
endfunction
" FUNCTION: TreeDirNode.refresh() {{{1
function! s:TreeDirNode.refresh()
call self.path.refresh(self.getNerdtree())
"if this node was ever opened, refresh its children
if self.isOpen || !empty(self.children)
let files = self._glob('*', 1) + self._glob('.*', 0)
let newChildNodes = []
let invalidFilesFound = 0
for i in files
try
"create a new path and see if it exists in this nodes children
let path = g:NERDTreePath.New(i)
let newNode = self.getChild(path)
if newNode != {}
call newNode.refresh()
call add(newChildNodes, newNode)
"the node doesnt exist so create it
else
let newNode = g:NERDTreeFileNode.New(path, self.getNerdtree())
let newNode.parent = self
call add(newChildNodes, newNode)
endif
catch /^NERDTree.\(InvalidArguments\|InvalidFiletype\)Error/
let invalidFilesFound = 1
endtry
endfor
"swap this nodes children out for the children we just read/refreshed
let self.children = newChildNodes
call self.sortChildren()
if invalidFilesFound
call nerdtree#echoWarning("some files could not be loaded into the NERD tree")
endif
endif
endfunction
" FUNCTION: TreeDirNode.refreshFlags() {{{1
unlet s:TreeDirNode.refreshFlags
function! s:TreeDirNode.refreshFlags()
call self.path.refreshFlags(self.getNerdtree())
for i in self.children
call i.refreshFlags()
endfor
endfunction
" FUNCTION: TreeDirNode.refreshDirFlags() {{{1
function! s:TreeDirNode.refreshDirFlags()
call self.path.refreshFlags(self.getNerdtree())
endfunction
" FUNCTION: TreeDirNode.reveal(path) {{{1
" reveal the given path, i.e. cache and open all treenodes needed to display it
" in the UI
" Returns the revealed node
function! s:TreeDirNode.reveal(path, ...)
let opts = a:0 ? a:1 : {}
if !a:path.isUnder(self.path)
throw "NERDTree.InvalidArgumentsError: " . a:path.str() . " should be under " . self.path.str()
endif
call self.open()
if self.path.equals(a:path.getParent())
let n = self.findNode(a:path)
if has_key(opts, "open")
call n.open()
endif
return n
endif
let p = a:path
while !p.getParent().equals(self.path)
let p = p.getParent()
endwhile
let n = self.findNode(p)
return n.reveal(a:path, opts)
endfunction
" FUNCTION: TreeDirNode.removeChild(treenode) {{{1
" Remove the given treenode from "self.children".
" Throws "NERDTree.ChildNotFoundError" if the node is not found.
"
" Args:
" treenode: the node object to remove
function! s:TreeDirNode.removeChild(treenode)
for i in range(0, self.getChildCount()-1)
if self.children[i].equals(a:treenode)
call remove(self.children, i)
return
endif
endfor
throw "NERDTree.ChildNotFoundError: child node was not found"
endfunction
" FUNCTION: TreeDirNode.sortChildren() {{{1
" Sort "self.children" by alphabetical order and directory priority.
function! s:TreeDirNode.sortChildren()
if count(g:NERDTreeSortOrder, '*') < 1
call add(g:NERDTreeSortOrder, '*')
endif
let CompareFunc = function("nerdtree#compareNodesBySortKey")
call sort(self.children, CompareFunc)
let g:NERDTreeOldSortOrder = g:NERDTreeSortOrder
endfunction
" FUNCTION: TreeDirNode.toggleOpen([options]) {{{1
" Opens this directory if it is closed and vice versa
function! s:TreeDirNode.toggleOpen(...)
let opts = a:0 ? a:1 : {}
if self.isOpen ==# 1
call self.close()
else
if g:NERDTreeCascadeOpenSingleChildDir == 0
call self.open(opts)
else
call self.openAlong(opts)
endif
endif
endfunction
" FUNCTION: TreeDirNode.transplantChild(newNode) {{{1
" Replaces the child of this with the given node (where the child node's full
" path matches a:newNode's fullpath). The search for the matching node is
" non-recursive
"
" Arg:
" newNode: the node to graft into the tree
function! s:TreeDirNode.transplantChild(newNode)
for i in range(0, self.getChildCount()-1)
if self.children[i].equals(a:newNode)
let self.children[i] = a:newNode
let a:newNode.parent = self
break
endif
endfor
endfunction
" vim: set sw=4 sts=4 et fdm=marker:

View File

@ -0,0 +1,347 @@
" ============================================================================
" CLASS: TreeFileNode
"
" This class is the parent of the "TreeDirNode" class and is the "Component"
" part of the composite design pattern between the NERDTree node classes.
" ============================================================================
let s:TreeFileNode = {}
let g:NERDTreeFileNode = s:TreeFileNode
" FUNCTION: TreeFileNode.activate(...) {{{1
function! s:TreeFileNode.activate(...)
call self.open(a:0 ? a:1 : {})
endfunction
" FUNCTION: TreeFileNode.bookmark(name) {{{1
" bookmark this node with a:name
function! s:TreeFileNode.bookmark(name)
" if a bookmark exists with the same name and the node is cached then save
" it so we can update its display string
let oldMarkedNode = {}
try
let oldMarkedNode = g:NERDTreeBookmark.GetNodeForName(a:name, 1, self.getNerdtree())
catch /^NERDTree.BookmarkNotFoundError/
catch /^NERDTree.BookmarkedNodeNotFoundError/
endtry
call g:NERDTreeBookmark.AddBookmark(a:name, self.path)
call self.path.cacheDisplayString()
call g:NERDTreeBookmark.Write()
if !empty(oldMarkedNode)
call oldMarkedNode.path.cacheDisplayString()
endif
endfunction
" FUNCTION: TreeFileNode.cacheParent() {{{1
" initializes self.parent if it isnt already
function! s:TreeFileNode.cacheParent()
if empty(self.parent)
let parentPath = self.path.getParent()
if parentPath.equals(self.path)
throw "NERDTree.CannotCacheParentError: already at root"
endif
let self.parent = s:TreeFileNode.New(parentPath, self.getNerdtree())
endif
endfunction
" FUNCTION: TreeFileNode.clearBookmarks() {{{1
function! s:TreeFileNode.clearBookmarks()
for i in g:NERDTreeBookmark.Bookmarks()
if i.path.equals(self.path)
call i.delete()
end
endfor
call self.path.cacheDisplayString()
endfunction
" FUNCTION: TreeFileNode.copy(dest) {{{1
function! s:TreeFileNode.copy(dest)
call self.path.copy(a:dest)
let newPath = g:NERDTreePath.New(a:dest)
let parent = self.getNerdtree().root.findNode(newPath.getParent())
if !empty(parent)
call parent.refresh()
return parent.findNode(newPath)
else
return {}
endif
endfunction
" FUNCTION: TreeFileNode.delete {{{1
" Removes this node from the tree and calls the Delete method for its path obj
function! s:TreeFileNode.delete()
call self.path.delete()
call self.parent.removeChild(self)
endfunction
" FUNCTION: TreeFileNode.displayString() {{{1
"
" Returns a string that specifies how the node should be represented as a
" string
"
" Return:
" a string that can be used in the view to represent this node
function! s:TreeFileNode.displayString()
return self.path.flagSet.renderToString() . self.path.displayString()
endfunction
" FUNCTION: TreeFileNode.equals(treenode) {{{1
"
" Compares this treenode to the input treenode and returns 1 if they are the
" same node.
"
" Use this method instead of == because sometimes when the treenodes contain
" many children, vim seg faults when doing ==
"
" Args:
" treenode: the other treenode to compare to
function! s:TreeFileNode.equals(treenode)
return self.path.str() ==# a:treenode.path.str()
endfunction
" FUNCTION: TreeFileNode.findNode(path) {{{1
" Returns self if this node.path.Equals the given path.
" Returns {} if not equal.
"
" Args:
" path: the path object to compare against
function! s:TreeFileNode.findNode(path)
if a:path.equals(self.path)
return self
endif
return {}
endfunction
" FUNCTION: TreeFileNode.findSibling(direction) {{{1
" Find the next or previous sibling of this node.
"
" Args:
" direction: 0 for previous, 1 for next
"
" Return:
" The next/previous TreeFileNode object or an empty dictionary if not found.
function! s:TreeFileNode.findSibling(direction)
" There can be no siblings if there is no parent.
if empty(self.parent)
return {}
endif
let l:nodeIndex = self.parent.getChildIndex(self.path)
if l:nodeIndex == -1
return {}
endif
" Get the next index to begin the search.
let l:nodeIndex += a:direction ? 1 : -1
while 0 <= l:nodeIndex && l:nodeIndex < self.parent.getChildCount()
" Return the next node if it is not ignored.
if !self.parent.children[l:nodeIndex].path.ignore(self.getNerdtree())
return self.parent.children[l:nodeIndex]
endif
let l:nodeIndex += a:direction ? 1 : -1
endwhile
return {}
endfunction
" FUNCTION: TreeFileNode.getNerdtree(){{{1
function! s:TreeFileNode.getNerdtree()
return self._nerdtree
endfunction
" FUNCTION: TreeFileNode.GetRootForTab(){{{1
" get the root node for this tab
function! s:TreeFileNode.GetRootForTab()
if g:NERDTree.ExistsForTab()
return getbufvar(t:NERDTreeBufName, 'NERDTree').root
end
return {}
endfunction
" FUNCTION: TreeFileNode.GetSelected() {{{1
" If the cursor is currently positioned on a tree node, return the node.
" Otherwise, return the empty dictionary.
function! s:TreeFileNode.GetSelected()
try
let l:path = b:NERDTree.ui.getPath(line('.'))
if empty(l:path)
return {}
endif
return b:NERDTree.root.findNode(l:path)
catch
return {}
endtry
endfunction
" FUNCTION: TreeFileNode.isVisible() {{{1
" returns 1 if this node should be visible according to the tree filters and
" hidden file filters (and their on/off status)
function! s:TreeFileNode.isVisible()
return !self.path.ignore(self.getNerdtree())
endfunction
" FUNCTION: TreeFileNode.isRoot() {{{1
function! s:TreeFileNode.isRoot()
if !g:NERDTree.ExistsForBuf()
throw "NERDTree.NoTreeError: No tree exists for the current buffer"
endif
return self.equals(self.getNerdtree().root)
endfunction
" FUNCTION: TreeFileNode.New(path, nerdtree) {{{1
" Returns a new TreeNode object with the given path and parent
"
" Args:
" path: file/dir that the node represents
" nerdtree: the tree the node belongs to
function! s:TreeFileNode.New(path, nerdtree)
if a:path.isDirectory
return g:NERDTreeDirNode.New(a:path, a:nerdtree)
else
let newTreeNode = copy(self)
let newTreeNode.path = a:path
let newTreeNode.parent = {}
let newTreeNode._nerdtree = a:nerdtree
return newTreeNode
endif
endfunction
" FUNCTION: TreeFileNode.open() {{{1
function! s:TreeFileNode.open(...)
let opts = a:0 ? a:1 : {}
let opener = g:NERDTreeOpener.New(self.path, opts)
call opener.open(self)
endfunction
" FUNCTION: TreeFileNode.openSplit() {{{1
" Open this node in a new window
function! s:TreeFileNode.openSplit()
call nerdtree#deprecated('TreeFileNode.openSplit', 'is deprecated, use .open() instead.')
call self.open({'where': 'h'})
endfunction
" FUNCTION: TreeFileNode.openVSplit() {{{1
" Open this node in a new vertical window
function! s:TreeFileNode.openVSplit()
call nerdtree#deprecated('TreeFileNode.openVSplit', 'is deprecated, use .open() instead.')
call self.open({'where': 'v'})
endfunction
" FUNCTION: TreeFileNode.openInNewTab(options) {{{1
function! s:TreeFileNode.openInNewTab(options)
call nerdtree#deprecated('TreeFileNode.openinNewTab', 'is deprecated, use .open() instead.')
call self.open(extend({'where': 't'}, a:options))
endfunction
" FUNCTION: TreeFileNode.putCursorHere(isJump, recurseUpward){{{1
" Places the cursor on the line number this node is rendered on
"
" Args:
" isJump: 1 if this cursor movement should be counted as a jump by vim
" recurseUpward: try to put the cursor on the parent if the this node isnt
" visible
function! s:TreeFileNode.putCursorHere(isJump, recurseUpward)
let ln = self.getNerdtree().ui.getLineNum(self)
if ln != -1
if a:isJump
mark '
endif
call cursor(ln, col("."))
else
if a:recurseUpward
let node = self
while node != {} && self.getNerdtree().ui.getLineNum(node) ==# -1
let node = node.parent
call node.open()
endwhile
call self._nerdtree.render()
call node.putCursorHere(a:isJump, 0)
endif
endif
endfunction
" FUNCTION: TreeFileNode.refresh() {{{1
function! s:TreeFileNode.refresh()
call self.path.refresh(self.getNerdtree())
endfunction
" FUNCTION: TreeFileNode.refreshFlags() {{{1
function! s:TreeFileNode.refreshFlags()
call self.path.refreshFlags(self.getNerdtree())
endfunction
" FUNCTION: TreeFileNode.rename() {{{1
" Calls the rename method for this nodes path obj
function! s:TreeFileNode.rename(newName)
let newName = substitute(a:newName, '\(\\\|\/\)$', '', '')
call self.path.rename(newName)
call self.parent.removeChild(self)
let parentPath = self.path.getParent()
let newParent = self.getNerdtree().root.findNode(parentPath)
if newParent != {}
call newParent.createChild(self.path, 1)
call newParent.refresh()
endif
endfunction
" FUNCTION: TreeFileNode.renderToString {{{1
" returns a string representation for this tree to be rendered in the view
function! s:TreeFileNode.renderToString()
return self._renderToString(0, 0)
endfunction
" Args:
" depth: the current depth in the tree for this call
" drawText: 1 if we should actually draw the line for this node (if 0 then the
" child nodes are rendered only)
" for each depth in the tree
function! s:TreeFileNode._renderToString(depth, drawText)
let output = ""
if a:drawText ==# 1
let treeParts = repeat(' ', a:depth - 1)
if !self.path.isDirectory
let treeParts = treeParts . ' '
endif
let line = treeParts . self.displayString()
let output = output . line . "\n"
endif
" if the node is an open dir, draw its children
if self.path.isDirectory ==# 1 && self.isOpen ==# 1
let childNodesToDraw = self.getVisibleChildren()
if self.isCascadable() && a:depth > 0
let output = output . childNodesToDraw[0]._renderToString(a:depth, 0)
elseif len(childNodesToDraw) > 0
for i in childNodesToDraw
let output = output . i._renderToString(a:depth + 1, 1)
endfor
endif
endif
return output
endfunction
" vim: set sw=4 sts=4 et fdm=marker:

516
lib/nerdtree/ui.vim Normal file
View File

@ -0,0 +1,516 @@
" ============================================================================
" CLASS: UI
" ============================================================================
let s:UI = {}
let g:NERDTreeUI = s:UI
" FUNCTION: s:UI.centerView() {{{2
" centers the nerd tree window around the cursor (provided the nerd tree
" options permit)
function! s:UI.centerView()
if g:NERDTreeAutoCenter
let current_line = winline()
let lines_to_top = current_line
let lines_to_bottom = winheight(g:NERDTree.GetWinNum()) - current_line
if lines_to_top < g:NERDTreeAutoCenterThreshold || lines_to_bottom < g:NERDTreeAutoCenterThreshold
normal! zz
endif
endif
endfunction
" FUNCTION: s:UI._dumpHelp {{{1
" prints out the quick help
function! s:UI._dumpHelp()
if self.getShowHelp()
let help = "\" NERDTree (" . nerdtree#version() . ") quickhelp~\n"
let help .= "\" ============================\n"
let help .= "\" File node mappings~\n"
let help .= "\" ". (g:NERDTreeMouseMode ==# 3 ? "single" : "double") ."-click,\n"
let help .= "\" <CR>,\n"
if self.nerdtree.isTabTree()
let help .= "\" ". g:NERDTreeMapActivateNode .": open in prev window\n"
else
let help .= "\" ". g:NERDTreeMapActivateNode .": open in current window\n"
endif
if self.nerdtree.isTabTree()
let help .= "\" ". g:NERDTreeMapPreview .": preview\n"
endif
let help .= "\" ". g:NERDTreeMapOpenInTab.": open in new tab\n"
let help .= "\" ". g:NERDTreeMapOpenInTabSilent .": open in new tab silently\n"
let help .= "\" middle-click,\n"
let help .= "\" ". g:NERDTreeMapOpenSplit .": open split\n"
let help .= "\" ". g:NERDTreeMapPreviewSplit .": preview split\n"
let help .= "\" ". g:NERDTreeMapOpenVSplit .": open vsplit\n"
let help .= "\" ". g:NERDTreeMapPreviewVSplit .": preview vsplit\n"
let help .= "\"\n\" ----------------------------\n"
let help .= "\" Directory node mappings~\n"
let help .= "\" ". (g:NERDTreeMouseMode ==# 1 ? "double" : "single") ."-click,\n"
let help .= "\" ". g:NERDTreeMapActivateNode .": open & close node\n"
let help .= "\" ". g:NERDTreeMapOpenRecursively .": recursively open node\n"
let help .= "\" ". g:NERDTreeMapOpenInTab.": open in new tab\n"
let help .= "\" ". g:NERDTreeMapOpenInTabSilent .": open in new tab silently\n"
let help .= "\" ". g:NERDTreeMapCloseDir .": close parent of node\n"
let help .= "\" ". g:NERDTreeMapCloseChildren .": close all child nodes of\n"
let help .= "\" current node recursively\n"
let help .= "\" middle-click,\n"
let help .= "\" ". g:NERDTreeMapOpenExpl.": explore selected dir\n"
let help .= "\"\n\" ----------------------------\n"
let help .= "\" Bookmark table mappings~\n"
let help .= "\" double-click,\n"
let help .= "\" ". g:NERDTreeMapActivateNode .": open bookmark\n"
let help .= "\" ". g:NERDTreeMapOpenInTab.": open in new tab\n"
let help .= "\" ". g:NERDTreeMapOpenInTabSilent .": open in new tab silently\n"
let help .= "\" ". g:NERDTreeMapDeleteBookmark .": delete bookmark\n"
let help .= "\"\n\" ----------------------------\n"
let help .= "\" Tree navigation mappings~\n"
let help .= "\" ". g:NERDTreeMapJumpRoot .": go to root\n"
let help .= "\" ". g:NERDTreeMapJumpParent .": go to parent\n"
let help .= "\" ". g:NERDTreeMapJumpFirstChild .": go to first child\n"
let help .= "\" ". g:NERDTreeMapJumpLastChild .": go to last child\n"
let help .= "\" ". g:NERDTreeMapJumpNextSibling .": go to next sibling\n"
let help .= "\" ". g:NERDTreeMapJumpPrevSibling .": go to prev sibling\n"
let help .= "\"\n\" ----------------------------\n"
let help .= "\" Filesystem mappings~\n"
let help .= "\" ". g:NERDTreeMapChangeRoot .": change tree root to the\n"
let help .= "\" selected dir\n"
let help .= "\" ". g:NERDTreeMapUpdir .": move tree root up a dir\n"
let help .= "\" ". g:NERDTreeMapUpdirKeepOpen .": move tree root up a dir\n"
let help .= "\" but leave old root open\n"
let help .= "\" ". g:NERDTreeMapRefresh .": refresh cursor dir\n"
let help .= "\" ". g:NERDTreeMapRefreshRoot .": refresh current root\n"
let help .= "\" ". g:NERDTreeMapMenu .": Show menu\n"
let help .= "\" ". g:NERDTreeMapChdir .":change the CWD to the\n"
let help .= "\" selected dir\n"
let help .= "\" ". g:NERDTreeMapCWD .":change tree root to CWD\n"
let help .= "\"\n\" ----------------------------\n"
let help .= "\" Tree filtering mappings~\n"
let help .= "\" ". g:NERDTreeMapToggleHidden .": hidden files (" . (self.getShowHidden() ? "on" : "off") . ")\n"
let help .= "\" ". g:NERDTreeMapToggleFilters .": file filters (" . (self.isIgnoreFilterEnabled() ? "on" : "off") . ")\n"
let help .= "\" ". g:NERDTreeMapToggleFiles .": files (" . (self.getShowFiles() ? "on" : "off") . ")\n"
let help .= "\" ". g:NERDTreeMapToggleBookmarks .": bookmarks (" . (self.getShowBookmarks() ? "on" : "off") . ")\n"
" add quickhelp entries for each custom key map
let help .= "\"\n\" ----------------------------\n"
let help .= "\" Custom mappings~\n"
for i in g:NERDTreeKeyMap.All()
if !empty(i.quickhelpText)
let help .= "\" ". i.key .": ". i.quickhelpText ."\n"
endif
endfor
let help .= "\"\n\" ----------------------------\n"
let help .= "\" Other mappings~\n"
let help .= "\" ". g:NERDTreeMapQuit .": Close the NERDTree window\n"
let help .= "\" ". g:NERDTreeMapToggleZoom .": Zoom (maximize-minimize)\n"
let help .= "\" the NERDTree window\n"
let help .= "\" ". g:NERDTreeMapHelp .": toggle help\n"
let help .= "\"\n\" ----------------------------\n"
let help .= "\" Bookmark commands~\n"
let help .= "\" :Bookmark [<name>]\n"
let help .= "\" :BookmarkToRoot <name>\n"
let help .= "\" :RevealBookmark <name>\n"
let help .= "\" :OpenBookmark <name>\n"
let help .= "\" :ClearBookmarks [<names>]\n"
let help .= "\" :ClearAllBookmarks\n"
silent! put =help
elseif !self.isMinimal()
let help ="\" Press ". g:NERDTreeMapHelp ." for help\n"
silent! put =help
endif
endfunction
" FUNCTION: s:UI.new(nerdtree) {{{1
function! s:UI.New(nerdtree)
let newObj = copy(self)
let newObj.nerdtree = a:nerdtree
let newObj._showHelp = 0
let newObj._ignoreEnabled = 1
let newObj._showFiles = g:NERDTreeShowFiles
let newObj._showHidden = g:NERDTreeShowHidden
let newObj._showBookmarks = g:NERDTreeShowBookmarks
return newObj
endfunction
" FUNCTION: s:UI.getPath(ln) {{{1
" Return the "Path" object for the node that is rendered on the given line
" number. If the "up a dir" line is selected, return the "Path" object for
" the parent of the root. Return the empty dictionary if the given line
" does not reference a tree node.
function! s:UI.getPath(ln)
let line = getline(a:ln)
let rootLine = self.getRootLineNum()
if a:ln == rootLine
return self.nerdtree.root.path
endif
if line ==# s:UI.UpDirLine()
return self.nerdtree.root.path.getParent()
endif
if a:ln < rootLine
return {}
endif
let indent = self._indentLevelFor(line)
" remove the tree parts and the leading space
let curFile = self._stripMarkup(line)
let dir = ""
let lnum = a:ln
while lnum > 0
let lnum = lnum - 1
let curLine = getline(lnum)
let curLineStripped = self._stripMarkup(curLine)
" have we reached the top of the tree?
if lnum == rootLine
let dir = self.nerdtree.root.path.str({'format': 'UI'}) . dir
break
endif
if curLineStripped =~# '/$'
let lpindent = self._indentLevelFor(curLine)
if lpindent < indent
let indent = indent - 1
let dir = substitute (curLineStripped,'^\\', "", "") . dir
continue
endif
endif
endwhile
let curFile = self.nerdtree.root.path.drive . dir . curFile
let toReturn = g:NERDTreePath.New(curFile)
return toReturn
endfunction
" FUNCTION: s:UI.getLineNum(node) {{{1
" Return the line number where the given node is rendered. Return -1 if the
" given node is not visible.
function! s:UI.getLineNum(node)
if a:node.isRoot()
return self.getRootLineNum()
endif
let l:pathComponents = [substitute(self.nerdtree.root.path.str({'format': 'UI'}), '/\s*$', '', '')]
let l:currentPathComponent = 1
let l:fullPath = a:node.path.str({'format': 'UI'})
for l:lineNumber in range(self.getRootLineNum() + 1, line('$'))
let l:currentLine = getline(l:lineNumber)
let l:indentLevel = self._indentLevelFor(l:currentLine)
if l:indentLevel != l:currentPathComponent
continue
endif
let l:currentLine = self._stripMarkup(l:currentLine)
let l:currentPath = join(l:pathComponents, '/') . '/' . l:currentLine
" Directories: If the current path "starts with" the full path, then
" either the paths are equal or the line is a cascade containing the
" full path.
if l:fullPath[-1:] == '/' && stridx(l:currentPath, l:fullPath) == 0
return l:lineNumber
endif
" Files: The paths must exactly match.
if l:fullPath ==# l:currentPath
return l:lineNumber
endif
" Otherwise: If the full path starts with the current path and the
" current path is a directory, we add a new path component.
if stridx(l:fullPath, l:currentPath) == 0 && l:currentPath[-1:] == '/'
let l:currentLine = substitute(l:currentLine, '/\s*$', '', '')
call add(l:pathComponents, l:currentLine)
let l:currentPathComponent += 1
endif
endfor
return -1
endfunction
" FUNCTION: s:UI.getRootLineNum(){{{1
" gets the line number of the root node
function! s:UI.getRootLineNum()
let rootLine = 1
while getline(rootLine) !~# '^\(/\|<\)'
let rootLine = rootLine + 1
endwhile
return rootLine
endfunction
" FUNCTION: s:UI.getShowBookmarks() {{{1
function! s:UI.getShowBookmarks()
return self._showBookmarks
endfunction
" FUNCTION: s:UI.getShowFiles() {{{1
function! s:UI.getShowFiles()
return self._showFiles
endfunction
" FUNCTION: s:UI.getShowHelp() {{{1
function! s:UI.getShowHelp()
return self._showHelp
endfunction
" FUNCTION: s:UI.getShowHidden() {{{1
function! s:UI.getShowHidden()
return self._showHidden
endfunction
" FUNCTION: s:UI._indentLevelFor(line) {{{1
function! s:UI._indentLevelFor(line)
" have to do this work around because match() returns bytes, not chars
let numLeadBytes = match(a:line, '\M\[^ '.g:NERDTreeDirArrowExpandable.g:NERDTreeDirArrowCollapsible.']')
" The next line is a backward-compatible workaround for strchars(a:line(0:numLeadBytes-1]). strchars() is in 7.3+
let leadChars = len(split(a:line[0:numLeadBytes-1], '\zs'))
return leadChars / s:UI.IndentWid()
endfunction
" FUNCTION: s:UI.IndentWid() {{{1
function! s:UI.IndentWid()
return 2
endfunction
" FUNCTION: s:UI.isIgnoreFilterEnabled() {{{1
function! s:UI.isIgnoreFilterEnabled()
return self._ignoreEnabled == 1
endfunction
" FUNCTION: s:UI.isMinimal() {{{1
function! s:UI.isMinimal()
return g:NERDTreeMinimalUI
endfunction
" FUNCTION: s:UI.MarkupReg() {{{1
function! s:UI.MarkupReg()
return '^ *['.g:NERDTreeDirArrowExpandable.g:NERDTreeDirArrowCollapsible.']\? '
endfunction
" FUNCTION: s:UI._renderBookmarks {{{1
function! s:UI._renderBookmarks()
if !self.isMinimal()
call setline(line(".")+1, ">----------Bookmarks----------")
call cursor(line(".")+1, col("."))
endif
if g:NERDTreeBookmarksSort == 1 || g:NERDTreeBookmarksSort == 2
call g:NERDTreeBookmark.SortBookmarksList()
endif
for i in g:NERDTreeBookmark.Bookmarks()
call setline(line(".")+1, i.str())
call cursor(line(".")+1, col("."))
endfor
call setline(line(".")+1, '')
call cursor(line(".")+1, col("."))
endfunction
" FUNCTION: s:UI.restoreScreenState() {{{1
"
" Sets the screen state back to what it was when nerdtree#saveScreenState was last
" called.
"
" Assumes the cursor is in the NERDTree window
function! s:UI.restoreScreenState()
if !has_key(self, '_screenState')
return
endif
exec("silent vertical resize " . self._screenState['oldWindowSize'])
let old_scrolloff=&scrolloff
let &scrolloff=0
call cursor(self._screenState['oldTopLine'], 0)
normal! zt
call setpos(".", self._screenState['oldPos'])
let &scrolloff=old_scrolloff
endfunction
" FUNCTION: s:UI.saveScreenState() {{{1
" Saves the current cursor position in the current buffer and the window
" scroll position
function! s:UI.saveScreenState()
let win = winnr()
call g:NERDTree.CursorToTreeWin()
let self._screenState = {}
let self._screenState['oldPos'] = getpos(".")
let self._screenState['oldTopLine'] = line("w0")
let self._screenState['oldWindowSize']= winwidth("")
call nerdtree#exec(win . "wincmd w")
endfunction
" FUNCTION: s:UI.setShowHidden(val) {{{1
function! s:UI.setShowHidden(val)
let self._showHidden = a:val
endfunction
" FUNCTION: s:UI._stripMarkup(line){{{1
" find the filename in the given line, and return it.
"
" Args:
" line: the subject line
function! s:UI._stripMarkup(line)
let l:line = substitute(a:line, '^.\{-}' . g:NERDTreeNodeDelimiter, '', '')
return substitute(l:line, g:NERDTreeNodeDelimiter.'.*$', '', '')
endfunction
" FUNCTION: s:UI.render() {{{1
function! s:UI.render()
setlocal noreadonly modifiable
" remember the top line of the buffer and the current line so we can
" restore the view exactly how it was
let curLine = line(".")
let curCol = col(".")
let topLine = line("w0")
" delete all lines in the buffer (being careful not to clobber a register)
silent 1,$delete _
call self._dumpHelp()
" delete the blank line before the help and add one after it
if !self.isMinimal()
call setline(line(".")+1, "")
call cursor(line(".")+1, col("."))
endif
if self.getShowBookmarks()
call self._renderBookmarks()
endif
" add the 'up a dir' line
if !self.isMinimal()
call setline(line(".")+1, s:UI.UpDirLine())
call cursor(line(".")+1, col("."))
endif
" draw the header line
let header = self.nerdtree.root.path.str({'format': 'UI', 'truncateTo': winwidth(0)})
call setline(line(".")+1, header)
call cursor(line(".")+1, col("."))
" draw the tree
silent put =self.nerdtree.root.renderToString()
" delete the blank line at the top of the buffer
silent 1,1delete _
" restore the view
let old_scrolloff=&scrolloff
let &scrolloff=0
call cursor(topLine, 1)
normal! zt
call cursor(curLine, curCol)
let &scrolloff = old_scrolloff
setlocal readonly nomodifiable
endfunction
" FUNCTION: UI.renderViewSavingPosition {{{1
" Renders the tree and ensures the cursor stays on the current node or the
" current nodes parent if it is no longer available upon re-rendering
function! s:UI.renderViewSavingPosition()
let currentNode = g:NERDTreeFileNode.GetSelected()
" go up the tree till we find a node that will be visible or till we run
" out of nodes
while currentNode != {} && !currentNode.isVisible() && !currentNode.isRoot()
let currentNode = currentNode.parent
endwhile
call self.render()
if currentNode != {}
call currentNode.putCursorHere(0, 0)
endif
endfunction
" FUNCTION: s:UI.toggleHelp() {{{1
function! s:UI.toggleHelp()
let self._showHelp = !self._showHelp
endfunction
" FUNCTION: s:UI.toggleIgnoreFilter() {{{1
" toggles the use of the NERDTreeIgnore option
function! s:UI.toggleIgnoreFilter()
let self._ignoreEnabled = !self._ignoreEnabled
call self.renderViewSavingPosition()
call self.centerView()
endfunction
" FUNCTION: s:UI.toggleShowBookmarks() {{{1
" Toggle the visibility of the Bookmark table.
function! s:UI.toggleShowBookmarks()
let self._showBookmarks = !self._showBookmarks
if self.getShowBookmarks()
call self.nerdtree.render()
call g:NERDTree.CursorToBookmarkTable()
else
if empty(g:NERDTreeFileNode.GetSelected())
call b:NERDTree.root.putCursorHere(0, 0)
normal! 0
endif
call self.renderViewSavingPosition()
endif
call self.centerView()
endfunction
" FUNCTION: s:UI.toggleShowFiles() {{{1
" toggles the display of hidden files
function! s:UI.toggleShowFiles()
let self._showFiles = !self._showFiles
call self.renderViewSavingPosition()
call self.centerView()
endfunction
" FUNCTION: s:UI.toggleShowHidden() {{{1
" toggles the display of hidden files
function! s:UI.toggleShowHidden()
let self._showHidden = !self._showHidden
call self.renderViewSavingPosition()
call self.centerView()
endfunction
" FUNCTION: s:UI.toggleZoom() {{{1
" zoom (maximize/minimize) the NERDTree window
function! s:UI.toggleZoom()
if exists("b:NERDTreeZoomed") && b:NERDTreeZoomed
let size = exists("b:NERDTreeOldWindowSize") ? b:NERDTreeOldWindowSize : g:NERDTreeWinSize
exec "silent vertical resize ". size
let b:NERDTreeZoomed = 0
else
exec "vertical resize"
let b:NERDTreeZoomed = 1
endif
endfunction
" FUNCTION: s:UI.UpDirLine() {{{1
function! s:UI.UpDirLine()
return '.. (up a dir)'
endfunction
" vim: set sw=4 sts=4 et fdm=marker:

View File

@ -0,0 +1,40 @@
" ============================================================================
" File: exec_menuitem.vim
" Description: plugin for NERD Tree that provides an execute file menu item
" Maintainer: Martin Grenfell <martin.grenfell at gmail dot com>
" License: This program is free software. It comes without any warranty,
" to the extent permitted by applicable law. You can redistribute
" it and/or modify it under the terms of the Do What The Fuck You
" Want To Public License, Version 2, as published by Sam Hocevar.
" See http://sam.zoy.org/wtfpl/COPYING for more details.
"
" ============================================================================
if exists("g:loaded_nerdtree_exec_menuitem")
finish
endif
let g:loaded_nerdtree_exec_menuitem = 1
call NERDTreeAddMenuItem({
\ 'text': '(!)Execute file',
\ 'shortcut': '!',
\ 'callback': 'NERDTreeExecFile',
\ 'isActiveCallback': 'NERDTreeExecFileActive' })
function! NERDTreeExecFileActive()
let node = g:NERDTreeFileNode.GetSelected()
return !node.path.isDirectory && node.path.isExecutable
endfunction
function! NERDTreeExecFile()
let treenode = g:NERDTreeFileNode.GetSelected()
echo "==========================================================\n"
echo "Complete the command to execute (add arguments etc):\n"
let cmd = treenode.path.str({'escape': 1})
let cmd = input(':!', cmd . ' ')
if cmd != ''
exec ':!' . cmd
else
echo "Aborted"
endif
endfunction

368
nerdtree_plugin/fs_menu.vim Normal file
View File

@ -0,0 +1,368 @@
" ============================================================================
" File: fs_menu.vim
" Description: plugin for the NERD Tree that provides a file system menu
" Maintainer: Martin Grenfell <martin.grenfell at gmail dot com>
" License: This program is free software. It comes without any warranty,
" to the extent permitted by applicable law. You can redistribute
" it and/or modify it under the terms of the Do What The Fuck You
" Want To Public License, Version 2, as published by Sam Hocevar.
" See http://sam.zoy.org/wtfpl/COPYING for more details.
"
" ============================================================================
if exists("g:loaded_nerdtree_fs_menu")
finish
endif
let g:loaded_nerdtree_fs_menu = 1
"Automatically delete the buffer after deleting or renaming a file
if !exists("g:NERDTreeAutoDeleteBuffer")
let g:NERDTreeAutoDeleteBuffer = 0
endif
call NERDTreeAddMenuItem({'text': '(a)dd a childnode', 'shortcut': 'a', 'callback': 'NERDTreeAddNode'})
call NERDTreeAddMenuItem({'text': '(m)ove the current node', 'shortcut': 'm', 'callback': 'NERDTreeMoveNode'})
call NERDTreeAddMenuItem({'text': '(d)elete the current node', 'shortcut': 'd', 'callback': 'NERDTreeDeleteNode'})
if has("gui_mac") || has("gui_macvim") || has("mac")
call NERDTreeAddMenuItem({'text': '(r)eveal in Finder the current node', 'shortcut': 'r', 'callback': 'NERDTreeRevealInFinder'})
call NERDTreeAddMenuItem({'text': '(o)pen the current node with system editor', 'shortcut': 'o', 'callback': 'NERDTreeExecuteFile'})
call NERDTreeAddMenuItem({'text': '(q)uicklook the current node', 'shortcut': 'q', 'callback': 'NERDTreeQuickLook'})
endif
if executable("xdg-open")
call NERDTreeAddMenuItem({'text': '(r)eveal the current node in file manager', 'shortcut': 'r', 'callback': 'NERDTreeRevealFileLinux'})
call NERDTreeAddMenuItem({'text': '(o)pen the current node with system editor', 'shortcut': 'o', 'callback': 'NERDTreeExecuteFileLinux'})
endif
if g:NERDTreePath.CopyingSupported()
call NERDTreeAddMenuItem({'text': '(c)opy the current node', 'shortcut': 'c', 'callback': 'NERDTreeCopyNode'})
endif
if has("unix") || has("osx")
call NERDTreeAddMenuItem({'text': '(l)ist the current node', 'shortcut': 'l', 'callback': 'NERDTreeListNode'})
else
call NERDTreeAddMenuItem({'text': '(l)ist the current node', 'shortcut': 'l', 'callback': 'NERDTreeListNodeWin32'})
endif
"FUNCTION: s:promptToDelBuffer(bufnum, msg){{{1
"prints out the given msg and, if the user responds by pushing 'y' then the
"buffer with the given bufnum is deleted
"
"Args:
"bufnum: the buffer that may be deleted
"msg: a message that will be echoed to the user asking them if they wish to
" del the buffer
function! s:promptToDelBuffer(bufnum, msg)
echo a:msg
if g:NERDTreeAutoDeleteBuffer || nr2char(getchar()) ==# 'y'
" 1. ensure that all windows which display the just deleted filename
" now display an empty buffer (so a layout is preserved).
" Is not it better to close single tabs with this file only ?
let s:originalTabNumber = tabpagenr()
let s:originalWindowNumber = winnr()
" Go to the next buffer in buffer list if at least one extra buffer is listed
" Otherwise open a new empty buffer
if v:version >= 800
let l:listedBufferCount = len(getbufinfo({'buflisted':1}))
elseif v:version >= 702
let l:listedBufferCount = len(filter(range(1, bufnr('$')), 'buflisted(v:val)'))
else
" Ignore buffer count in this case to make sure we keep the old
" behavior
let l:listedBufferCount = 0
endif
if l:listedBufferCount > 1
exec "tabdo windo if winbufnr(0) == " . a:bufnum . " | exec ':bnext! ' | endif"
else
exec "tabdo windo if winbufnr(0) == " . a:bufnum . " | exec ':enew! ' | endif"
endif
exec "tabnext " . s:originalTabNumber
exec s:originalWindowNumber . "wincmd w"
" 3. We don't need a previous buffer anymore
exec "bwipeout! " . a:bufnum
endif
endfunction
"FUNCTION: s:renameBuffer(bufNum, newNodeName, isDirectory){{{1
"The buffer with the given bufNum is replaced with a new one
"
"Args:
"bufNum: the buffer that may be deleted
"newNodeName: the name given to the renamed node
"isDirectory: determines how to do the create the new filenames
function! s:renameBuffer(bufNum, newNodeName, isDirectory)
if a:isDirectory
let quotedFileName = fnameescape(a:newNodeName . '/' . fnamemodify(bufname(a:bufNum),':t'))
let editStr = g:NERDTreePath.New(a:newNodeName . '/' . fnamemodify(bufname(a:bufNum),':t')).str({'format': 'Edit'})
else
let quotedFileName = fnameescape(a:newNodeName)
let editStr = g:NERDTreePath.New(a:newNodeName).str({'format': 'Edit'})
endif
" 1. ensure that a new buffer is loaded
exec "badd " . quotedFileName
" 2. ensure that all windows which display the just deleted filename
" display a buffer for a new filename.
let s:originalTabNumber = tabpagenr()
let s:originalWindowNumber = winnr()
exec "tabdo windo if winbufnr(0) == " . a:bufNum . " | exec ':e! " . editStr . "' | endif"
exec "tabnext " . s:originalTabNumber
exec s:originalWindowNumber . "wincmd w"
" 3. We don't need a previous buffer anymore
exec "bwipeout! " . a:bufNum
endfunction
"FUNCTION: NERDTreeAddNode(){{{1
function! NERDTreeAddNode()
let curDirNode = g:NERDTreeDirNode.GetSelected()
let newNodeName = input("Add a childnode\n".
\ "==========================================================\n".
\ "Enter the dir/file name to be created. Dirs end with a '/'\n" .
\ "", curDirNode.path.str() . g:NERDTreePath.Slash(), "file")
if newNodeName ==# ''
call nerdtree#echo("Node Creation Aborted.")
return
endif
try
let newPath = g:NERDTreePath.Create(newNodeName)
let parentNode = b:NERDTree.root.findNode(newPath.getParent())
let newTreeNode = g:NERDTreeFileNode.New(newPath, b:NERDTree)
" Emptying g:NERDTreeOldSortOrder forces the sort to
" recalculate the cached sortKey so nodes sort correctly.
let g:NERDTreeOldSortOrder = []
if empty(parentNode)
call b:NERDTree.root.refresh()
call b:NERDTree.render()
elseif parentNode.isOpen || !empty(parentNode.children)
call parentNode.addChild(newTreeNode, 1)
call NERDTreeRender()
call newTreeNode.putCursorHere(1, 0)
endif
catch /^NERDTree/
call nerdtree#echoWarning("Node Not Created.")
endtry
endfunction
"FUNCTION: NERDTreeMoveNode(){{{1
function! NERDTreeMoveNode()
let curNode = g:NERDTreeFileNode.GetSelected()
let newNodePath = input("Rename the current node\n" .
\ "==========================================================\n" .
\ "Enter the new path for the node: \n" .
\ "", curNode.path.str(), "file")
if newNodePath ==# ''
call nerdtree#echo("Node Renaming Aborted.")
return
endif
try
if curNode.path.isDirectory
let l:openBuffers = filter(range(1,bufnr("$")),'bufexists(v:val) && fnamemodify(bufname(v:val),":p") =~# curNode.path.str() . "/.*"')
else
let l:openBuffers = filter(range(1,bufnr("$")),'bufexists(v:val) && fnamemodify(bufname(v:val),":p") ==# curNode.path.str()')
endif
call curNode.rename(newNodePath)
" Emptying g:NERDTreeOldSortOrder forces the sort to
" recalculate the cached sortKey so nodes sort correctly.
let g:NERDTreeOldSortOrder = []
call b:NERDTree.root.refresh()
call NERDTreeRender()
" If the file node is open, or files under the directory node are
" open, ask the user if they want to replace the file(s) with the
" renamed files.
if !empty(l:openBuffers)
if curNode.path.isDirectory
echo "\nDirectory renamed.\n\nFiles with the old directory name are open in buffers " . join(l:openBuffers, ', ') . ". Replace these buffers with the new files? (yN)"
else
echo "\nFile renamed.\n\nThe old file is open in buffer " . l:openBuffers[0] . ". Replace this buffer with the new file? (yN)"
endif
if g:NERDTreeAutoDeleteBuffer || nr2char(getchar()) ==# 'y'
for bufNum in l:openBuffers
call s:renameBuffer(bufNum, newNodePath, curNode.path.isDirectory)
endfor
endif
endif
call curNode.putCursorHere(1, 0)
redraw
catch /^NERDTree/
call nerdtree#echoWarning("Node Not Renamed.")
endtry
endfunction
" FUNCTION: NERDTreeDeleteNode() {{{1
function! NERDTreeDeleteNode()
let currentNode = g:NERDTreeFileNode.GetSelected()
let confirmed = 0
if currentNode.path.isDirectory && ((currentNode.isOpen && currentNode.getChildCount() > 0) ||
\ (len(currentNode._glob('*', 1)) > 0))
let choice =input("Delete the current node\n" .
\ "==========================================================\n" .
\ "STOP! Directory is not empty! To delete, type 'yes'\n" .
\ "" . currentNode.path.str() . ": ")
let confirmed = choice ==# 'yes'
else
echo "Delete the current node\n" .
\ "==========================================================\n".
\ "Are you sure you wish to delete the node:\n" .
\ "" . currentNode.path.str() . " (yN):"
let choice = nr2char(getchar())
let confirmed = choice ==# 'y'
endif
if confirmed
try
call currentNode.delete()
call NERDTreeRender()
"if the node is open in a buffer, ask the user if they want to
"close that buffer
let bufnum = bufnr("^".currentNode.path.str()."$")
if buflisted(bufnum)
let prompt = "\nNode deleted.\n\nThe file is open in buffer ". bufnum . (bufwinnr(bufnum) ==# -1 ? " (hidden)" : "") .". Delete this buffer? (yN)"
call s:promptToDelBuffer(bufnum, prompt)
endif
redraw
catch /^NERDTree/
call nerdtree#echoWarning("Could not remove node")
endtry
else
call nerdtree#echo("delete aborted")
endif
endfunction
" FUNCTION: NERDTreeListNode() {{{1
function! NERDTreeListNode()
let treenode = g:NERDTreeFileNode.GetSelected()
if !empty(treenode)
let s:uname = system("uname")
let stat_cmd = 'stat -c "%s" '
if s:uname =~? "Darwin"
let stat_cmd = 'stat -f "%z" '
endif
let cmd = 'size=$(' . stat_cmd . shellescape(treenode.path.str()) . ') && ' .
\ 'size_with_commas=$(echo $size | sed -e :a -e "s/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/;ta") && ' .
\ 'ls -ld ' . shellescape(treenode.path.str()) . ' | sed -e "s/ $size / $size_with_commas /"'
let metadata = split(system(cmd),'\n')
call nerdtree#echo(metadata[0])
else
call nerdtree#echo("No information available")
endif
endfunction
" FUNCTION: NERDTreeListNodeWin32() {{{1
function! NERDTreeListNodeWin32()
let l:node = g:NERDTreeFileNode.GetSelected()
if !empty(l:node)
let l:path = l:node.path.str()
call nerdtree#echo(printf("%s:%s MOD:%s BYTES:%d PERMISSIONS:%s",
\ toupper(getftype(l:path)),
\ fnamemodify(l:path, ':t'),
\ strftime("%c", getftime(l:path)),
\ getfsize(l:path),
\ getfperm(l:path)))
return
endif
call nerdtree#echo('node not recognized')
endfunction
" FUNCTION: NERDTreeCopyNode() {{{1
function! NERDTreeCopyNode()
let currentNode = g:NERDTreeFileNode.GetSelected()
let newNodePath = input("Copy the current node\n" .
\ "==========================================================\n" .
\ "Enter the new path to copy the node to: \n" .
\ "", currentNode.path.str(), "file")
if newNodePath != ""
"strip trailing slash
let newNodePath = substitute(newNodePath, '\/$', '', '')
let confirmed = 1
if currentNode.path.copyingWillOverwrite(newNodePath)
call nerdtree#echo("Warning: copying may overwrite files! Continue? (yN)")
let choice = nr2char(getchar())
let confirmed = choice ==# 'y'
endif
if confirmed
try
let newNode = currentNode.copy(newNodePath)
" Emptying g:NERDTreeOldSortOrder forces the sort to
" recalculate the cached sortKey so nodes sort correctly.
let g:NERDTreeOldSortOrder = []
if empty(newNode)
call b:NERDTree.root.refresh()
call b:NERDTree.render()
else
call NERDTreeRender()
call newNode.putCursorHere(0, 0)
endif
catch /^NERDTree/
call nerdtree#echoWarning("Could not copy node")
endtry
endif
else
call nerdtree#echo("Copy aborted.")
endif
redraw
endfunction
" FUNCTION: NERDTreeQuickLook() {{{1
function! NERDTreeQuickLook()
let treenode = g:NERDTreeFileNode.GetSelected()
if treenode != {}
call system("qlmanage -p 2>/dev/null '" . treenode.path.str() . "'")
endif
endfunction
" FUNCTION: NERDTreeRevealInFinder() {{{1
function! NERDTreeRevealInFinder()
let treenode = g:NERDTreeFileNode.GetSelected()
if treenode != {}
call system("open -R '" . treenode.path.str() . "'")
endif
endfunction
" FUNCTION: NERDTreeExecuteFile() {{{1
function! NERDTreeExecuteFile()
let treenode = g:NERDTreeFileNode.GetSelected()
if treenode != {}
call system("open '" . treenode.path.str() . "'")
endif
endfunction
" FUNCTION: NERDTreeRevealFileLinux() {{{1
function! NERDTreeRevealFileLinux()
let treenode = g:NERDTreeFileNode.GetSelected()
let parentnode = treenode.parent
if parentnode != {}
call system("xdg-open '" . parentnode.path.str() . "' &")
endif
endfunction
" FUNCTION: NERDTreeExecuteFileLinux() {{{1
function! NERDTreeExecuteFileLinux()
let treenode = g:NERDTreeFileNode.GetSelected()
if treenode != {}
call system("xdg-open '" . treenode.path.str() . "' &")
endif
endfunction
" vim: set sw=4 sts=4 et fdm=marker:

242
plugin/NERD_tree.vim Normal file
View File

@ -0,0 +1,242 @@
" ============================================================================
" File: NERD_tree.vim
" Maintainer: Martin Grenfell <martin.grenfell at gmail dot com>
" License: This program is free software. It comes without any warranty,
" to the extent permitted by applicable law. You can redistribute
" it and/or modify it under the terms of the Do What The Fuck You
" Want To Public License, Version 2, as published by Sam Hocevar.
" See http://sam.zoy.org/wtfpl/COPYING for more details.
"
" ============================================================================
"
" SECTION: Script init stuff {{{1
"============================================================
if exists("loaded_nerd_tree")
finish
endif
if v:version < 700
echoerr "NERDTree: this plugin requires vim >= 7. DOWNLOAD IT! You'll thank me later!"
finish
endif
let loaded_nerd_tree = 1
"for line continuation - i.e dont want C in &cpo
let s:old_cpo = &cpo
set cpo&vim
"Function: s:initVariable() function {{{2
"This function is used to initialise a given variable to a given value. The
"variable is only initialised if it does not exist prior
"
"Args:
"var: the name of the var to be initialised
"value: the value to initialise var to
"
"Returns:
"1 if the var is set, 0 otherwise
function! s:initVariable(var, value)
if !exists(a:var)
exec 'let ' . a:var . ' = ' . "'" . substitute(a:value, "'", "''", "g") . "'"
return 1
endif
return 0
endfunction
"SECTION: Init variable calls and other random constants {{{2
call s:initVariable("g:NERDTreeAutoCenter", 1)
call s:initVariable("g:NERDTreeAutoCenterThreshold", 3)
call s:initVariable("g:NERDTreeCaseSensitiveSort", 0)
call s:initVariable("g:NERDTreeNaturalSort", 0)
call s:initVariable("g:NERDTreeSortHiddenFirst", 1)
call s:initVariable("g:NERDTreeChDirMode", 0)
call s:initVariable("g:NERDTreeCreatePrefix", "silent")
call s:initVariable("g:NERDTreeMinimalUI", 0)
if !exists("g:NERDTreeIgnore")
let g:NERDTreeIgnore = ['\~$']
endif
call s:initVariable("g:NERDTreeBookmarksFile", expand('$HOME') . '/.NERDTreeBookmarks')
call s:initVariable("g:NERDTreeBookmarksSort", 1)
call s:initVariable("g:NERDTreeHighlightCursorline", 1)
call s:initVariable("g:NERDTreeHijackNetrw", 1)
call s:initVariable('g:NERDTreeMarkBookmarks', 1)
call s:initVariable("g:NERDTreeMouseMode", 1)
call s:initVariable("g:NERDTreeNotificationThreshold", 100)
call s:initVariable("g:NERDTreeQuitOnOpen", 0)
call s:initVariable("g:NERDTreeRespectWildIgnore", 0)
call s:initVariable("g:NERDTreeShowBookmarks", 0)
call s:initVariable("g:NERDTreeShowFiles", 1)
call s:initVariable("g:NERDTreeShowHidden", 0)
call s:initVariable("g:NERDTreeShowLineNumbers", 0)
call s:initVariable("g:NERDTreeSortDirs", 1)
if !nerdtree#runningWindows() && !nerdtree#runningCygwin()
call s:initVariable("g:NERDTreeDirArrowExpandable", "▸")
call s:initVariable("g:NERDTreeDirArrowCollapsible", "▾")
else
call s:initVariable("g:NERDTreeDirArrowExpandable", "+")
call s:initVariable("g:NERDTreeDirArrowCollapsible", "~")
endif
call s:initVariable("g:NERDTreeCascadeOpenSingleChildDir", 1)
call s:initVariable("g:NERDTreeCascadeSingleChildDir", 1)
if !exists("g:NERDTreeSortOrder")
let g:NERDTreeSortOrder = ['\/$', '*', '\.swp$', '\.bak$', '\~$']
endif
let g:NERDTreeOldSortOrder = []
call s:initVariable("g:NERDTreeGlyphReadOnly", "RO")
" ASCII 160: non-breaking space used to delimit items in the tree's nodes.
call s:initVariable("g:NERDTreeNodeDelimiter", "\u00a0")
if !exists('g:NERDTreeStatusline')
"the exists() crap here is a hack to stop vim spazzing out when
"loading a session that was created with an open nerd tree. It spazzes
"because it doesnt store b:NERDTree(its a b: var, and its a hash)
let g:NERDTreeStatusline = "%{exists('b:NERDTree')?b:NERDTree.root.path.str():''}"
endif
call s:initVariable("g:NERDTreeWinPos", "left")
call s:initVariable("g:NERDTreeWinSize", 31)
"init the shell commands that will be used to copy nodes, and remove dir trees
"
"Note: the space after the command is important
if nerdtree#runningWindows()
call s:initVariable("g:NERDTreeRemoveDirCmd", 'rmdir /s /q ')
call s:initVariable("g:NERDTreeCopyDirCmd", 'xcopy /s /e /i /y /q ')
call s:initVariable("g:NERDTreeCopyFileCmd", 'copy /y ')
else
call s:initVariable("g:NERDTreeRemoveDirCmd", 'rm -rf ')
call s:initVariable("g:NERDTreeCopyCmd", 'cp -r ')
endif
"SECTION: Init variable calls for key mappings {{{2
call s:initVariable("g:NERDTreeMapActivateNode", "o")
call s:initVariable("g:NERDTreeMapChangeRoot", "C")
call s:initVariable("g:NERDTreeMapChdir", "cd")
call s:initVariable("g:NERDTreeMapCloseChildren", "X")
call s:initVariable("g:NERDTreeMapCloseDir", "x")
call s:initVariable("g:NERDTreeMapDeleteBookmark", "D")
call s:initVariable("g:NERDTreeMapMenu", "m")
call s:initVariable("g:NERDTreeMapHelp", "?")
call s:initVariable("g:NERDTreeMapJumpFirstChild", "K")
call s:initVariable("g:NERDTreeMapJumpLastChild", "J")
call s:initVariable("g:NERDTreeMapJumpNextSibling", "<C-j>")
call s:initVariable("g:NERDTreeMapJumpParent", "p")
call s:initVariable("g:NERDTreeMapJumpPrevSibling", "<C-k>")
call s:initVariable("g:NERDTreeMapJumpRoot", "P")
call s:initVariable("g:NERDTreeMapOpenExpl", "e")
call s:initVariable("g:NERDTreeMapOpenInTab", "t")
call s:initVariable("g:NERDTreeMapOpenInTabSilent", "T")
call s:initVariable("g:NERDTreeMapOpenRecursively", "O")
call s:initVariable("g:NERDTreeMapOpenSplit", "i")
call s:initVariable("g:NERDTreeMapOpenVSplit", "s")
call s:initVariable("g:NERDTreeMapPreview", "g" . NERDTreeMapActivateNode)
call s:initVariable("g:NERDTreeMapPreviewSplit", "g" . NERDTreeMapOpenSplit)
call s:initVariable("g:NERDTreeMapPreviewVSplit", "g" . NERDTreeMapOpenVSplit)
call s:initVariable("g:NERDTreeMapQuit", "q")
call s:initVariable("g:NERDTreeMapRefresh", "r")
call s:initVariable("g:NERDTreeMapRefreshRoot", "R")
call s:initVariable("g:NERDTreeMapToggleBookmarks", "B")
call s:initVariable("g:NERDTreeMapToggleFiles", "F")
call s:initVariable("g:NERDTreeMapToggleFilters", "f")
call s:initVariable("g:NERDTreeMapToggleHidden", "I")
call s:initVariable("g:NERDTreeMapToggleZoom", "A")
call s:initVariable("g:NERDTreeMapUpdir", "u")
call s:initVariable("g:NERDTreeMapUpdirKeepOpen", "U")
call s:initVariable("g:NERDTreeMapCWD", "CD")
"SECTION: Load class files{{{2
call nerdtree#loadClassFiles()
" SECTION: Commands {{{1
"============================================================
call nerdtree#ui_glue#setupCommands()
" SECTION: Auto commands {{{1
"============================================================
augroup NERDTree
"Save the cursor position whenever we close the nerd tree
exec "autocmd BufLeave ". g:NERDTreeCreator.BufNamePrefix() ."* if g:NERDTree.IsOpen() | call b:NERDTree.ui.saveScreenState() | endif"
"disallow insert mode in the NERDTree
exec "autocmd BufEnter ". g:NERDTreeCreator.BufNamePrefix() ."* stopinsert"
augroup END
if g:NERDTreeHijackNetrw
augroup NERDTreeHijackNetrw
autocmd VimEnter * silent! autocmd! FileExplorer
au BufEnter,VimEnter * call nerdtree#checkForBrowse(expand("<amatch>"))
augroup END
endif
" SECTION: Public API {{{1
"============================================================
function! NERDTreeAddMenuItem(options)
call g:NERDTreeMenuItem.Create(a:options)
endfunction
function! NERDTreeAddMenuSeparator(...)
let opts = a:0 ? a:1 : {}
call g:NERDTreeMenuItem.CreateSeparator(opts)
endfunction
function! NERDTreeAddSubmenu(options)
return g:NERDTreeMenuItem.Create(a:options)
endfunction
function! NERDTreeAddKeyMap(options)
call g:NERDTreeKeyMap.Create(a:options)
endfunction
function! NERDTreeRender()
call nerdtree#renderView()
endfunction
function! NERDTreeFocus()
if g:NERDTree.IsOpen()
call g:NERDTree.CursorToTreeWin()
else
call g:NERDTreeCreator.ToggleTabTree("")
endif
endfunction
function! NERDTreeCWD()
if empty(getcwd())
call nerdtree#echoWarning('current directory does not exist')
return
endif
try
let l:cwdPath = g:NERDTreePath.New(getcwd())
catch /^NERDTree.InvalidArgumentsError/
call nerdtree#echoWarning('current directory does not exist')
return
endtry
call NERDTreeFocus()
if b:NERDTree.root.path.equals(l:cwdPath)
return
endif
let l:newRoot = g:NERDTreeFileNode.New(l:cwdPath, b:NERDTree)
call b:NERDTree.changeRoot(l:newRoot)
normal! ^
endfunction
function! NERDTreeAddPathFilter(callback)
call g:NERDTree.AddPathFilter(a:callback)
endfunction
" SECTION: Post Source Actions {{{1
call nerdtree#postSourceActions()
"reset &cpo back to users setting
let &cpo = s:old_cpo
" vim: set sw=4 sts=4 et fdm=marker:

1118
plugin/asyncrun.vim Normal file

File diff suppressed because it is too large Load Diff

132
plugin/buffergator.vim Normal file
View File

@ -0,0 +1,132 @@
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"" Buffergator
""
"" Vim document buffer navigation utility
""
"" Copyright 2011 Jeet Sukumaran.
""
"" This program is free software; you can redistribute it and/or modify
"" it under the terms of the GNU General Public License as published by
"" the Free Software Foundation; either version 3 of the License, or
"" (at your option) any later version.
""
"" This program is distributed in the hope that it will be useful,
"" but WITHOUT ANY WARRANTY; without even the implied warranty of
"" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
"" GNU General Public License <http://www.gnu.org/licenses/>
"" for more details.
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Reload and Compatibility Guard <<FOLD<<
" ============================================================================
" Reload protection.
if (exists('g:did_buffergator') && g:did_buffergator) || &cp || version < 700
finish
endif
let g:did_buffergator = 1
" avoid line continuation issues (see ':help user_41.txt')
let s:save_cpo = &cpo
set cpo&vim
" >>FOLD>>
" Global MRU Initialization <<FOLD<<
" ==============================================================================
" Moves (or adds) the given buffer number to the top of the list
if !exists("g:buffergator_mru_cycle_loop")
let g:buffergator_mru_cycle_loop = 1
endif
let g:buffergator_track_mru = 1
let g:buffergator_mru = []
function! BuffergatorUpdateMRU(acmd_bufnr)
if len(g:buffergator_mru) < 1 " maybe should be 2?
if g:buffergator_mru_cycle_loop
let g:buffergator_mru = []
for l:bni in range(bufnr("$"), 1, -1)
if buflisted(l:bni)
\ && getbufvar(l:bni, "&filetype") != "netrw"
call add(g:buffergator_mru, l:bni)
endif
endfor
endif
endif
if !exists("w:buffergator_mru")
let w:buffergator_mru = g:buffergator_mru[:]
endif
if g:buffergator_track_mru
let bnum = a:acmd_bufnr + 0
" if bnum == 0 || !buflisted(bnum) || !(empty(getbufvar(bnum, "netrw_browser_active")))
if bnum == 0 || !buflisted(bnum) || getbufvar(bnum, "&filetype") == "netrw"
return
endif
call filter(g:buffergator_mru, 'v:val !=# bnum')
call insert(g:buffergator_mru, bnum, 0)
call filter(w:buffergator_mru, 'v:val !=# bnum')
call insert(w:buffergator_mru, bnum, 0)
endif
endfunction
" Autocommands that update the most recenly used buffers
augroup BuffergatorMRU
au!
autocmd BufEnter * call BuffergatorUpdateMRU(expand('<abuf>'))
autocmd BufRead * call BuffergatorUpdateMRU(expand('<abuf>'))
autocmd BufNewFile * call BuffergatorUpdateMRU(expand('<abuf>'))
autocmd BufWritePost * call BuffergatorUpdateMRU(expand('<abuf>'))
augroup NONE
" >>FOLD>>
" Public Command and Key Maps <<FOLD<<
" ==============================================================================
" command! -nargs=0 BuffergatorToggle :call buffergator#ToggleBuffergator()
" command! -nargs=0 BuffergatorClose :call buffergator#CloseBuffergator()
" command! -nargs=0 BuffergatorOpen :call buffergator#OpenBuffergator()
" command! -nargs=0 BuffergatorTabsToggle :call buffergator#ToggleBuffergatorTabs()
" command! -nargs=0 BuffergatorTabsOpen :call buffergator#OpenBuffergatorTabs()
" command! -nargs=0 BuffergatorTabsClose :call buffergator#CloseBuffergatorTabs()
" command! -nargs=0 BuffergatorUpdate :call buffergator#UpdateBuffergator('',-1)
" command! -nargs=* BuffergatorMruCyclePrev :call buffergator#BuffergatorCycleMru(-1, "<args>")
" command! -nargs=* BuffergatorMruCycleNext :call buffergator#BuffergatorCycleMru(1, "<args>")
" command! -nargs=? -bang BuffergatorMruList :call buffergator#BuffergatorEchoMruList('<bang>')
" if !exists('g:buffergator_suppress_keymaps') || !g:buffergator_suppress_keymaps
" " nnoremap <silent> <Leader><Leader> :BuffergatorToggle<CR>
" nnoremap <silent> <Leader>b :BuffergatorOpen<CR>
" nnoremap <silent> <Leader>B :BuffergatorClose<CR>
" nnoremap <silent> <Leader>t :BuffergatorTabsOpen<CR>
" nnoremap <silent> <Leader>to :BuffergatorTabsOpen<CR>
" nnoremap <silent> <Leader>tc :BuffergatorTabsClose<CR>
" nnoremap <silent> <Leader>T :BuffergatorTabsClose<CR>
" if !exists('g:buffergator_suppress_mru_switching_keymaps') || !g:buffergator_suppress_mru_switching_keymaps
" nnoremap <silent> <M-b> :BuffergatorMruCyclePrev<CR>
" nnoremap <silent> <M-S-b> :BuffergatorMruCycleNext<CR>
" if !exists('g:buffergator_keep_old_mru_switching_keymaps') || !g:buffergator_keep_old_mru_switching_keymaps
" nnoremap <silent> gb :BuffergatorMruCyclePrev<CR>
" nnoremap <silent> gB :BuffergatorMruCycleNext<CR>
" else
" nnoremap <silent> [b :BuffergatorMruCyclePrev<CR>
" nnoremap <silent> ]b :BuffergatorMruCycleNext<CR>
" endif
" endif
" if !exists('g:buffergator_suppress_mru_switch_into_splits_keymaps') || !g:buffergator_suppress_mru_switch_into_splits_keymaps
" nnoremap <silent> <Leader><LEFT> :BuffergatorMruCyclePrev leftabove vert sbuffer<CR>
" nnoremap <silent> <Leader><UP> :BuffergatorMruCyclePrev leftabove sbuffer<CR>
" nnoremap <silent> <Leader><RIGHT> :BuffergatorMruCyclePrev rightbelow vert sbuffer<CR>
" nnoremap <silent> <Leader><DOWN> :BuffergatorMruCyclePrev rightbelow sbuffer<CR>
" nnoremap <silent> <Leader><S-LEFT> :BuffergatorMruCycleNext leftabove vert sbuffer<CR>
" nnoremap <silent> <Leader><S-UP> :BuffergatorMruCycleNext leftabove sbuffer<CR>
" nnoremap <silent> <Leader><S-RIGHT> :BuffergatorMruCycleNext rightbelow vert sbuffer<CR>
" nnoremap <silent> <Leader><S-DOWN> :BuffergatorMruCycleNext rightbelow sbuffer<CR>
" endif
" endif
" >>FOLD>>
" Restore State <<FOLD<<
" ============================================================================
" restore options
let &cpo = s:save_cpo
" >>FOLD>>
" vim:foldlevel=4:

66
plugin/template.vim Normal file
View File

@ -0,0 +1,66 @@
" File: template.vim
" Author: Wonder <wonderbeyond@gmail.com>
" Description:
" Generates template for new files.
" 这里主要根据文件名加载模板, 而不是根据 vim 识别到的文件类型.
" .c 和 .h 文件可能会被识别为相同类型, 显然它们需要不同的模板.
" Rules:
" *先看整个文件名(不含路径), 再看扩展名.
" 例如 main.cc 文件中会定义 main 函数, 其他 .cc 文件则未必然.
" *先看是否有普通的静态模板, 再看是否有动态模板.
if exists("g:enable_template") && g:enable_template == 1 && exists("g:template_dir")
augroup Template_Generator
autocmd! Template_Generator
autocmd BufNewFile * call Read_template()
augroup END
else
finish
endif
let s:common_tpl_dir = g:template_dir . "/common"
let s:dynamic_tpl_dir = g:template_dir . "/dynamic"
function! Read_template()
let filename = expand("%:t")
let extname = expand("%:e")
" 先检查是否存在[普通的][全名]匹配模板(例如 main.cc).
let common_tpl_file = expand(s:common_tpl_dir . "/full/" . filename)
if filereadable(common_tpl_file)
call Read_template_file(common_tpl_file)
return
endif
" 再检查是否存在[动态的][全名]匹配模板.
let dynamic_template_generator = expand(s:dynamic_tpl_dir . "/full/" .filename)
if executable(dynamic_template_generator)
call Read_dynamic_template(dynamic_template_generator, filename)
return
endif
" 再检查是否存在[普通的][后缀]匹配模板.
let common_tpl_file = expand(s:common_tpl_dir . "/ext/" . extname)
if filereadable(common_tpl_file)
call Read_template_file(common_tpl_file)
return
endif
" 最后检查是否存在[动态的][后缀]匹配模板.
let dynamic_template_generator = expand(s:dynamic_tpl_dir . "/ext/" . extname)
if executable(dynamic_template_generator)
call Read_dynamic_template(dynamic_template_generator, filename)
return
endif
endfunction
function! Read_template_file(filename)
silent execute "0r " . a:filename
endfunction
" 读取模板生成器动态生成的模板.
" generator参数指定生成器程序的路径.
" 同时还把文件名传递给生成器.
function! Read_dynamic_template(generator, filename)
silent execute "0r !" . a:generator . " " . a:filename
endfunction

36
syntax/c.vim Normal file
View File

@ -0,0 +1,36 @@
"========================================================
" Highlight All Function
"========================================================
syn keyword cSystemCall pid_t pthread_t pthread_mutex_t pthread_cond_t sem_t fd_set libnet_t libnet_ptag_t pcap_t size_t socklen_t
hi def link cSystemCall Type
"========================================================
" Highlight All Function
"========================================================
syn match cFunctions display"[a-zA-Z_][a-zA-Z_0-9]\{-1,}\s\{-0,}(\{1}"ms=s,me=e-1
hi def link cFunctions Special
"========================================================
" Highlight All Math Operator
"========================================================
" C math operators
syn match cMathOperator display "[-+/*\%=]"
" C pointer operators
syn match cPointerOperator display "->\|\."
" C logical operators - boolean results
syn match cLogicalOperator display "[!<>]=\="
syn match cLogicalOperator display "=="
" C bit operators
syn match cBinaryOperator display "\(&\||\|\^\|<<\|>>\)=\="
syn match cBinaryOperator display "\~"
syn match cBinaryOperatorError display "\~="
" More C logical operators - highlight in preference to binary
syn match cLogicalOperator display "&&\|||"
syn match cLogicalOperatorError display "\(&&\|||\)="
" Math Operator
hi cMathOperator guifg=#3EFFE2
hi cPointerOperator guifg=#3EFFE2
hi cLogicalOperator guifg=#3EFFE2
hi cBinaryOperator guifg=#3EFFE2
hi cBinaryOperatorError guifg=#3EFFE2
hi cLogicalOperator guifg=#3EFFE2
hi cLogicalOperatorError guifg=#3EFFE2

404
syntax/go.vim Normal file
View File

@ -0,0 +1,404 @@
" Copyright 2009 The Go Authors. All rights reserved.
" Use of this source code is governed by a BSD-style
" license that can be found in the LICENSE file.
"
" go.vim: Vim syntax file for Go.
"
" Options:
" There are some options for customizing the highlighting; the recommended
" settings are the default values, but you can write:
" let OPTION_NAME = 0
" in your ~/.vimrc file to disable particular options. You can also write:
" let OPTION_NAME = 1
" to enable particular options.
" At present, all options default to on, except highlight of:
" functions, methods, structs, operators, build constraints and interfaces.
"
" - go_highlight_array_whitespace_error
" Highlights white space after "[]".
" - go_highlight_chan_whitespace_error
" Highlights white space around the communications operator that don't follow
" the standard style.
" - go_highlight_extra_types
" Highlights commonly used library types (io.Reader, etc.).
" - go_highlight_space_tab_error
" Highlights instances of tabs following spaces.
" - go_highlight_trailing_whitespace_error
" Highlights trailing white space.
" - go_highlight_string_spellcheck
" Specifies that strings should be spell checked
" - go_highlight_format_strings
" Highlights printf-style operators inside string literals.
" Quit when a (custom) syntax file was already loaded
if exists("b:current_syntax")
finish
endif
if !exists("g:go_highlight_array_whitespace_error")
let g:go_highlight_array_whitespace_error = 1
endif
if !exists("g:go_highlight_chan_whitespace_error")
let g:go_highlight_chan_whitespace_error = 1
endif
if !exists("g:go_highlight_extra_types")
let g:go_highlight_extra_types = 1
endif
if !exists("g:go_highlight_space_tab_error")
let g:go_highlight_space_tab_error = 1
endif
if !exists("g:go_highlight_trailing_whitespace_error")
let g:go_highlight_trailing_whitespace_error = 1
endif
if !exists("g:go_highlight_operators")
let g:go_highlight_operators = 1 "Colben changed to 1
endif
if !exists("g:go_highlight_functions")
let g:go_highlight_functions = 1 "Colben changed to 1
endif
if !exists("g:go_highlight_methods")
let g:go_highlight_methods = 1 "Colben changed to 1
endif
if !exists("g:go_highlight_fields")
let g:go_highlight_fields = 1 "Colben changed to 1
endif
if !exists("g:go_highlight_types")
let g:go_highlight_types = 1 "Colben changed to 1
endif
if !exists("g:go_highlight_build_constraints")
let g:go_highlight_build_constraints = 1 "Colben changed to 1
endif
if !exists("g:go_highlight_string_spellcheck")
let g:go_highlight_string_spellcheck = 1
endif
if !exists("g:go_highlight_format_strings")
let g:go_highlight_format_strings = 1
endif
if !exists("g:go_highlight_generate_tags")
let g:go_highlight_generate_tags = 1 "Colben changed to 1
endif
syn case match
syn keyword goDirective package import
syn keyword goDeclaration var const
hi def link goDirective Statement
hi def link goDeclaration Keyword
" Keywords within functions
syn keyword goStatement defer go goto return break continue fallthrough
syn keyword goConditional if else switch select
syn keyword goLabel case default
syn keyword goRepeat for range
hi def link goStatement Statement
hi def link goConditional Conditional
hi def link goLabel Label
hi def link goRepeat Repeat
" Predefined types
syn keyword goType chan map bool string error
syn keyword goSignedInts int int8 int16 int32 int64 rune
syn keyword goUnsignedInts byte uint uint8 uint16 uint32 uint64 uintptr
syn keyword goFloats float32 float64
syn keyword goComplexes complex64 complex128
hi def link goType Type
hi def link goSignedInts Type
hi def link goUnsignedInts Type
hi def link goFloats Type
hi def link goComplexes Type
" Predefined functions and values
syn match goBuiltins /\<\v(append|cap|close|complex|copy|delete|imag|len)\ze\(/
syn match goBuiltins /\<\v(make|new|panic|print|println|real|recover)\ze\(/
syn keyword goBoolean true false
syn keyword goPredefinedIdentifiers nil iota
hi def link goBuiltins Keyword
hi def link goBoolean Boolean
hi def link goPredefinedIdentifiers goBoolean
" Comments; their contents
syn keyword goTodo contained TODO FIXME XXX BUG
syn cluster goCommentGroup contains=goTodo
syn region goComment start="/\*" end="\*/" contains=@goCommentGroup,@Spell
syn region goComment start="//" end="$" contains=goGenerate,@goCommentGroup,@Spell
hi def link goComment Comment
hi def link goTodo Todo
if g:go_highlight_generate_tags != 0
syn match goGenerateVariables contained /\(\$GOARCH\|\$GOOS\|\$GOFILE\|\$GOLINE\|\$GOPACKAGE\|\$DOLLAR\)\>/
syn region goGenerate start="^\s*//go:generate" end="$" contains=goGenerateVariables
hi def link goGenerate PreProc
hi def link goGenerateVariables Special
endif
" Go escapes
syn match goEscapeOctal display contained "\\[0-7]\{3}"
syn match goEscapeC display contained +\\[abfnrtv\\'"]+
syn match goEscapeX display contained "\\x\x\{2}"
syn match goEscapeU display contained "\\u\x\{4}"
syn match goEscapeBigU display contained "\\U\x\{8}"
syn match goEscapeError display contained +\\[^0-7xuUabfnrtv\\'"]+
hi def link goEscapeOctal goSpecialString
hi def link goEscapeC goSpecialString
hi def link goEscapeX goSpecialString
hi def link goEscapeU goSpecialString
hi def link goEscapeBigU goSpecialString
hi def link goSpecialString Special
hi def link goEscapeError Error
" Strings and their contents
syn cluster goStringGroup contains=goEscapeOctal,goEscapeC,goEscapeX,goEscapeU,goEscapeBigU,goEscapeError
if g:go_highlight_string_spellcheck != 0
syn region goString start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=@goStringGroup,@Spell
syn region goRawString start=+`+ end=+`+ contains=@Spell
else
syn region goString start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=@goStringGroup
syn region goRawString start=+`+ end=+`+
endif
if g:go_highlight_format_strings != 0
syn match goFormatSpecifier /\([^%]\(%%\)*\)\@<=%[-#0 +]*\%(\*\|\d\+\)\=\%(\.\%(\*\|\d\+\)\)*[vTtbcdoqxXUeEfgGsp]/ contained containedin=goString
hi def link goFormatSpecifier goSpecialString
endif
hi def link goString String
hi def link goRawString String
" Characters; their contents
syn cluster goCharacterGroup contains=goEscapeOctal,goEscapeC,goEscapeX,goEscapeU,goEscapeBigU
syn region goCharacter start=+'+ skip=+\\\\\|\\'+ end=+'+ contains=@goCharacterGroup
hi def link goCharacter Character
" Regions
syn region goBlock start="{" end="}" transparent fold
syn region goParen start='(' end=')' transparent
" Integers
syn match goDecimalInt "\<-\=\d\+\%([Ee][-+]\=\d\+\)\=\>"
syn match goHexadecimalInt "\<-\=0[xX]\x\+\>"
syn match goOctalInt "\<-\=0\o\+\>"
syn match goOctalError "\<-\=0\o*[89]\d*\>"
hi def link goDecimalInt Integer
hi def link goHexadecimalInt Integer
hi def link goOctalInt Integer
hi def link goOctalError Error
hi def link Integer Number
" Floating point
syn match goFloat "\<-\=\d\+\.\d*\%([Ee][-+]\=\d\+\)\=\>"
syn match goFloat "\<-\=\.\d\+\%([Ee][-+]\=\d\+\)\=\>"
hi def link goFloat Float
" Imaginary literals
syn match goImaginary "\<-\=\d\+i\>"
syn match goImaginary "\<-\=\d\+[Ee][-+]\=\d\+i\>"
syn match goImaginaryFloat "\<-\=\d\+\.\d*\%([Ee][-+]\=\d\+\)\=i\>"
syn match goImaginaryFloat "\<-\=\.\d\+\%([Ee][-+]\=\d\+\)\=i\>"
hi def link goImaginary Number
hi def link goImaginaryFloat Float
" Spaces after "[]"
if g:go_highlight_array_whitespace_error != 0
syn match goSpaceError display "\(\[\]\)\@<=\s\+"
endif
" Spacing errors around the 'chan' keyword
if g:go_highlight_chan_whitespace_error != 0
" receive-only annotation on chan type
"
" \(\<chan\>\)\@<!<- (only pick arrow when it doesn't come after a chan)
" this prevents picking up 'chan<- chan<-' but not '<- chan'
syn match goSpaceError display "\(\(\<chan\>\)\@<!<-\)\@<=\s\+\(\<chan\>\)\@="
" send-only annotation on chan type
"
" \(<-\)\@<!\<chan\> (only pick chan when it doesn't come after an arrow)
" this prevents picking up '<-chan <-chan' but not 'chan <-'
syn match goSpaceError display "\(\(<-\)\@<!\<chan\>\)\@<=\s\+\(<-\)\@="
" value-ignoring receives in a few contexts
syn match goSpaceError display "\(\(^\|[={(,;]\)\s*<-\)\@<=\s\+"
endif
" Extra types commonly seen
if g:go_highlight_extra_types != 0
syn match goExtraType /\<bytes\.\(Buffer\)\>/
syn match goExtraType /\<io\.\(Reader\|ReadSeeker\|ReadWriter\|ReadCloser\|ReadWriteCloser\|Writer\|WriteCloser\|Seeker\)\>/
syn match goExtraType /\<reflect\.\(Kind\|Type\|Value\)\>/
syn match goExtraType /\<unsafe\.Pointer\>/
endif
" Space-tab error
if g:go_highlight_space_tab_error != 0
syn match goSpaceError display " \+\t"me=e-1
endif
" Trailing white space error
if g:go_highlight_trailing_whitespace_error != 0
syn match goSpaceError display excludenl "\s\+$"
endif
hi def link goExtraType Type
hi def link goSpaceError Error
" included from: https://github.com/athom/more-colorful.vim/blob/master/after/syntax/go.vim
"
" Comments; their contents
syn keyword goTodo contained NOTE
hi def link goTodo Todo
syn match goVarArgs /\.\.\./
" Operators;
if g:go_highlight_operators != 0
" match single-char operators: - + % < > ! & | ^ * =
" and corresponding two-char operators: -= += %= <= >= != &= |= ^= *= ==
syn match goOperator /[-+%<>!&|^*=]=\?/
" match / and /=
syn match goOperator /\/\%(=\|\ze[^/*]\)/
" match two-char operators: << >> &^
" and corresponding three-char operators: <<= >>= &^=
syn match goOperator /\%(<<\|>>\|&^\)=\?/
" match remaining two-char operators: := && || <- ++ --
syn match goOperator /:=\|||\|<-\|++\|--/
" match ...
hi def link goPointerOperator goOperator
hi def link goVarArgs goOperator
endif
hi def link goOperator Operator
" Functions;
if g:go_highlight_functions != 0
syn match goDeclaration /\<func\>/ nextgroup=goReceiver,goFunction skipwhite skipnl
syn match goReceiver /(\(\w\|[ *]\)\+)/ contained nextgroup=goFunction contains=goReceiverVar skipwhite skipnl
syn match goReceiverVar /\w\+/ nextgroup=goPointerOperator,goReceiverType skipwhite skipnl contained
syn match goPointerOperator /\*/ nextgroup=goReceiverType contained skipwhite skipnl
syn match goReceiverType /\w\+/ contained
syn match goFunction /\w\+/ contained
syn match goFunctionCall /\w\+\ze(/
else
syn keyword goDeclaration func
endif
hi def link goFunction Function
hi def link goFunctionCall Type
" Methods;
if g:go_highlight_methods != 0
syn match goMethod /\.\w\+\ze(/hs=s+1
endif
hi def link goMethod Type
" Fields;
if g:go_highlight_fields != 0
syn match goField /\.\w\+\([.\ \n\r\:\)\[,]\)\@=/hs=s+1
endif
hi def link goField Identifier
" Structs & Interfaces;
if g:go_highlight_types != 0
syn match goTypeConstructor /\<\w\+{/he=e-1
syn match goTypeDecl /\<type\>/ nextgroup=goTypeName skipwhite skipnl
syn match goTypeName /\w\+/ contained nextgroup=goDeclType skipwhite skipnl
syn match goDeclType /\<interface\|struct\>/ contained skipwhite skipnl
hi def link goReceiverType Type
else
syn keyword goDeclType struct interface
syn keyword goDeclaration type
endif
hi def link goTypeConstructor Type
hi def link goTypeName Type
hi def link goTypeDecl Keyword
hi def link goDeclType Keyword
" Build Constraints
if g:go_highlight_build_constraints != 0
syn match goBuildKeyword display contained "+build"
" Highlight the known values of GOOS, GOARCH, and other +build options.
syn keyword goBuildDirectives contained
\ android darwin dragonfly freebsd linux nacl netbsd openbsd plan9
\ solaris windows 386 amd64 amd64p32 arm armbe arm64 arm64be ppc64
\ ppc64le mips mipsle mips64 mips64le mips64p32 mips64p32le ppc
\ s390 s390x sparc sparc64 cgo ignore race
" Other words in the build directive are build tags not listed above, so
" avoid highlighting them as comments by using a matchgroup just for the
" start of the comment.
" The rs=s+2 option lets the \s*+build portion be part of the inner region
" instead of the matchgroup so it will be highlighted as a goBuildKeyword.
syn region goBuildComment matchgroup=goBuildCommentStart
\ start="//\s*+build\s"rs=s+2 end="$"
\ contains=goBuildKeyword,goBuildDirectives
hi def link goBuildCommentStart Comment
hi def link goBuildDirectives Type
hi def link goBuildKeyword PreProc
" One or more line comments that are followed immediately by a "package"
" declaration are treated like package documentation, so these must be
" matched as comments to avoid looking like working build constraints.
" The he, me, and re options let the "package" itself be highlighted by
" the usual rules.
syn region goPackageComment start=/\v(\/\/.*\n)+\s*package/
\ end=/\v\n\s*package/he=e-7,me=e-7,re=e-7
\ contains=@goCommentGroup,@Spell
hi def link goPackageComment Comment
endif
" :GoCoverage commands
hi def link goCoverageNormalText Comment
function! s:hi()
" :GoSameIds
if &background == 'dark'
hi def goSameId term=bold cterm=bold ctermbg=white ctermfg=black guibg=white guifg=black
else
hi def goSameId term=bold cterm=bold ctermbg=14 guibg=Cyan
endif
" :GoCoverage commands
hi def goCoverageCovered ctermfg=green guifg=#A6E22E
hi def goCoverageUncover ctermfg=red guifg=#F92672
endfunction
augroup vim-go-hi
autocmd!
autocmd ColorScheme * call s:hi()
augroup end
call s:hi()
" Search backwards for a global declaration to start processing the syntax.
"syn sync match goSync grouphere NONE /^\(const\|var\|type\|func\)\>/
" There's a bug in the implementation of grouphere. For now, use the
" following as a more expensive/less precise workaround.
syn sync minlines=500
let b:current_syntax = "go"
" vim: sw=2 ts=2 et

91
syntax/nerdtree.vim Normal file
View File

@ -0,0 +1,91 @@
let s:tree_up_dir_line = '.. (up a dir)'
syn match NERDTreeIgnore #\~#
exec 'syn match NERDTreeIgnore #\['.g:NERDTreeGlyphReadOnly.'\]#'
"highlighting for the .. (up dir) line at the top of the tree
execute "syn match NERDTreeUp #\\V". s:tree_up_dir_line ."#"
"quickhelp syntax elements
syn match NERDTreeHelpKey #" \{1,2\}[^ ]*:#ms=s+2,me=e-1
syn match NERDTreeHelpKey #" \{1,2\}[^ ]*,#ms=s+2,me=e-1
syn match NERDTreeHelpTitle #" .*\~$#ms=s+2,me=e-1
syn match NERDTreeToggleOn #(on)#ms=s+1,he=e-1
syn match NERDTreeToggleOff #(off)#ms=e-3,me=e-1
syn match NERDTreeHelpCommand #" :.\{-}\>#hs=s+3
syn match NERDTreeHelp #^".*# contains=NERDTreeHelpKey,NERDTreeHelpTitle,NERDTreeIgnore,NERDTreeToggleOff,NERDTreeToggleOn,NERDTreeHelpCommand
"highlighting for sym links
syn match NERDTreeLinkTarget #->.*# containedin=NERDTreeDir,NERDTreeFile
syn match NERDTreeLinkFile #.* ->#me=e-3 containedin=NERDTreeFile
syn match NERDTreeLinkDir #.*/ ->#me=e-3 containedin=NERDTreeDir
"highlighing for directory nodes and file nodes
syn match NERDTreeDirSlash #/# containedin=NERDTreeDir
exec 'syn match NERDTreeClosable #' . escape(g:NERDTreeDirArrowCollapsible, '~') . '\ze .*/# containedin=NERDTreeDir,NERDTreeFile'
exec 'syn match NERDTreeOpenable #' . escape(g:NERDTreeDirArrowExpandable, '~') . '\ze .*/# containedin=NERDTreeDir,NERDTreeFile'
let s:dirArrows = escape(g:NERDTreeDirArrowCollapsible, '~]\-').escape(g:NERDTreeDirArrowExpandable, '~]\-')
exec 'syn match NERDTreeDir #[^'.s:dirArrows.' ].*/#'
syn match NERDTreeExecFile #^ .*\*\($\| \)# contains=NERDTreeRO,NERDTreeBookmark
exec 'syn match NERDTreeFile #^[^"\.'.s:dirArrows.'] *[^'.s:dirArrows.']*# contains=NERDTreeLink,NERDTreeRO,NERDTreeBookmark,NERDTreeExecFile'
"highlighting for readonly files
exec 'syn match NERDTreeRO # *\zs.*\ze \['.g:NERDTreeGlyphReadOnly.'\]# contains=NERDTreeIgnore,NERDTreeBookmark,NERDTreeFile'
syn match NERDTreeFlags #^ *\zs\[.\]# containedin=NERDTreeFile,NERDTreeExecFile
syn match NERDTreeFlags #\[.\]# containedin=NERDTreeDir
"highlighing to conceal the delimiter around the file/dir name
if has("conceal")
exec 'syn match NERDTreeNodeDelimiters #' . g:NERDTreeNodeDelimiter . '# conceal containedin=NERDTreeFile,NERDTreeLinkFile,NERDTreeExecFile,NERDTreeRO,NERDTreeDir'
setlocal conceallevel=2 concealcursor=nvic
else
exec 'syn match NERDTreeNodeDelimiters #' . g:NERDTreeNodeDelimiter . '# containedin=NERDTreeFile,NERDTreeLinkFile,NERDTreeExecFile,NERDTreeRO,NERDTreeDir'
hi! link NERDTreeNodeDelimiters Ignore
endif
syn match NERDTreeCWD #^[</].*$#
"highlighting for bookmarks
syn match NERDTreeBookmark # {.*}#hs=s+1
"highlighting for the bookmarks table
syn match NERDTreeBookmarksLeader #^>#
syn match NERDTreeBookmarksHeader #^>-\+Bookmarks-\+$# contains=NERDTreeBookmarksLeader
syn match NERDTreeBookmarkName #^>.\{-} #he=e-1 contains=NERDTreeBookmarksLeader
syn match NERDTreeBookmark #^>.*$# contains=NERDTreeBookmarksLeader,NERDTreeBookmarkName,NERDTreeBookmarksHeader
hi def link NERDTreePart Special
hi def link NERDTreePartFile Type
hi def link NERDTreeExecFile Title
hi def link NERDTreeDirSlash Identifier
hi def link NERDTreeBookmarksHeader statement
hi def link NERDTreeBookmarksLeader ignore
hi def link NERDTreeBookmarkName Identifier
hi def link NERDTreeBookmark normal
hi def link NERDTreeHelp String
hi def link NERDTreeHelpKey Identifier
hi def link NERDTreeHelpCommand Identifier
hi def link NERDTreeHelpTitle Macro
hi def link NERDTreeToggleOn Question
hi def link NERDTreeToggleOff WarningMsg
hi def link NERDTreeLinkTarget Type
hi def link NERDTreeLinkFile Macro
hi def link NERDTreeLinkDir Macro
hi def link NERDTreeDir Directory
hi def link NERDTreeUp Directory
hi def link NERDTreeFile Normal
hi def link NERDTreeCWD Statement
hi def link NERDTreeOpenable Directory
hi def link NERDTreeClosable Directory
hi def link NERDTreeIgnore ignore
hi def link NERDTreeRO WarningMsg
hi def link NERDTreeBookmark Statement
hi def link NERDTreeFlags Number
hi def link NERDTreeCurrentNode Search

10
templates/common/ext/html Normal file
View File

@ -0,0 +1,10 @@
<!DOCTYPE HTML>
<html>
<head>
<title></title>
</head>
<body>
<header></header>
<footer></footer>
</body>
</html>

9
templates/dynamic/ext/c Executable file
View File

@ -0,0 +1,9 @@
#!/bin/sh
cat<<EOF
//=========================================
// Filename : $1
// Author : Colben
// Create : `date +"%F %R"`
//=========================================
EOF

14
templates/dynamic/ext/h Executable file
View File

@ -0,0 +1,14 @@
#!/bin/sh
cat<<EOF
//=========================================
// Filename : $1
// Author : Colben
// Create : `date +"%F %R"`
//=========================================
#ifndef ____
#define ____
#endif
EOF

19
templates/dynamic/ext/py Executable file
View File

@ -0,0 +1,19 @@
#!/bin/sh
cat<<EOF
#!/usr/bin/python3
# -*- coding:utf-8 -*-
#=========================================
# Filename : $1
# Author : Colben
# Create : `date +"%F %R"`
#=========================================
def main():
return
if '__main__' == __name__:
main()
EOF

49
templates/dynamic/ext/sh Executable file
View File

@ -0,0 +1,49 @@
#!/bin/bash
cat <<-EOF
#!/bin/bash
#=========================================
# Author : Colben
# Create : $(date +"%F %R")
#=========================================
set -euo pipefail
export LANG=en_US.UTF-8
trap Quit EXIT
if [ -t 0 ]; then
function Print { echo -e "\033[32;1m\$(date +'[%F %T]') \$*\033[0m"; }
function Warn { echo -e "\033[33;1m\$(date +'[%F %T]') \$*\033[0m"; }
function Error { echo -e "\033[31;1m\$(date +'[%F %T]') \$*\033[0m"; exit 1; }
else
function Print { echo -e "\$(date +'[%F %T] INFO') \$*"; }
function Warn { echo -e "\$(date +'[%F %T] WARN') \$*"; }
function Error { echo -e "\$(date +'[%F %T] ERRRO') \$*"; exit 1; }
fi
function Quit {
local exitCode=\$?
[ 0 -ne \$exitCode ] && Error Failed to xxxx!
[ -z "\${END:-}" ] && echo && Error Interrupted manually!
Print Succeeded to xxxx.
}
function Func1 {
Print Func1 ...
}
function Func2 {
Print Func2 ...
}
function Main {
Print Main ...
Func1
Func2
END=1
}
# Start here
Main
EOF

10
templates/dynamic/full/.gitignore vendored Executable file
View File

@ -0,0 +1,10 @@
#!/bin/sh
cat<<EOF
#=========================================
# Filename : $1
# Author : Colben
# Create : `date +"%F %R"`
#=========================================
EOF

View File

@ -0,0 +1 @@
Makefile

33
templates/dynamic/full/Makefile Executable file
View File

@ -0,0 +1,33 @@
#!/bin/sh
cat<<EOF
#=========================================
# Filename : $1
# Author : Colben
# Create : `date +"%F %R"`
#=========================================
cc=gcc
source=
object=\$(source:%.c=%.o)
flags=
target=exe
\$(target):\$(object)
@\$(cc) -o \$@ \$^ \$(flags)
@echo "成功生成可执行文件: \$@ !!"
%.o:%.c
@\$(cc) -o \$@ -c \$< \$(flags)
@echo "成功编译 \$< 生成 \$@ 文件!!"
clean:
@rm -rf \$(object)
clear:
@rm -rf \$(object) \$(target)
EOF

View File

@ -0,0 +1 @@
Makefile

425
vimrc Normal file
View File

@ -0,0 +1,425 @@
"----------------------------------------------------------------
" New Filetypes
""""""""""""""""""""""""
au BufNewFile,BufRead *.h setf c
"----------------------------------------------------------------
" Common
""""""""""""""""""""""""
set fileencodings=utf-8,gb18030 " 兼容txt
set nocompatible " 关闭 vi 兼容模式
syntax on " 自动语法高亮
colorscheme atom-dark-256 " 设定配色方案
set number " 显示行号
"set number relativenumber " 显示相对行号
set cursorline " 突出显示当前行
set ruler " 打开状态栏标尺
set tabstop=4 " 设定 tab 长度为 4
set softtabstop=4 " 使得按退格键时可以一次删掉 4 个空格
set shiftwidth=4 " 设定 > 命令移动时的宽度为 4
set expandtab
set nobackup " 覆盖文件时不备份
set autochdir " 自动切换当前目录为当前文件所在的目录
filetype plugin indent on " 开启插件
set smartindent " 开启新行时使用智能自动缩进
set backupcopy=yes " 设置备份时的行为为覆盖
set ignorecase smartcase " 搜索时忽略大小写,但在有一个或以上大写字母时仍保持对大小写敏感
set nowrapscan " 禁止在搜索到文件两端时重新搜索
set incsearch " 输入搜索内容时就显示搜索结果
set hlsearch " 搜索时高亮显示被找到的文本
set noerrorbells " 关闭错误信息响铃
set novisualbell " 关闭使用可视响铃代替呼叫
set t_vb= " 置空错误铃声的终端代码
"set showmatch " 插入括号时,短暂地跳转到匹配的对应括号
"set matchtime=1 " 短暂跳转到匹配括号的时间
set magic " 设置魔术
set hidden " 允许在有未保存的修改时切换缓冲区,此时的修改由 vim 负责保存
set backspace=indent,eol,start " 不设定在插入状态无法用退格键和 Delete 键删除回车符
set laststatus=2 " 显示状态栏 (默认值为 1, 无法显示状态栏)
set cmdheight=1 " 设定状态栏命令行的行数为 1
"set showtabline=2 " 显示标签栏
"set mouse=a " 开启鼠标模式
"----------------------------------------------------------------
"Status Line
""""""""""""""""""""""""
set statusline=%F " 文件的路径
set statusline+=%= " 切换到右边
set statusline+=%{&fileencoding} " 文件的编码
set statusline+=\ " 分隔符
set statusline+=%c " 当前列
set statusline+=\, " 分隔符
set statusline+=%l " 当前行
set statusline+=/ " 分隔符
set statusline+=%L " 总行数
set statusline+=\ " 分隔符
set statusline+=%P " 当前位置
"----------------------------------------------------------------
" Vim Shotcuts
""""""""""""""""""""""""
inoremap <F3> <Esc>:NERDTreeToggle<CR>
nnoremap <F3> :NERDTreeToggle<CR>
nnoremap <C-w><C-n> :tabp<CR>
nnoremap <C-w>n :tabn<CR>
nnoremap <C-w><C-l> :vertical resize +2<CR>
nnoremap <C-w><C-h> :vertical resize -2<CR>
nnoremap <C-w><C-j> :resize +2<CR>
nnoremap <C-w><C-k> :resize -2<CR>
au Syntax python set makeprg=python3\ -u\ %\
au Syntax go set makeprg=go\ install\
au Syntax rust set makeprg=rustc\ %\
au Syntax lua set makeprg=lua5.1\ %\
au Syntax sh set makeprg=bash\ %\
au Syntax c,python,go,rust,lua,sh nnoremap <F7> :execute "normal! ".QuickFix()<CR>
au Syntax c,go,rust nnoremap e :cn<CR>
au Syntax c,go,rust nnoremap E :cp<CR>
au Syntax go nnoremap H :!go doc <cword><CR>
au Syntax python nnoremap H :!pydoc3 <cword><CR>
"----------------------------------------------------------------
" Fold
""""""""""""""""""""""""
set fdm=marker
set foldmarker=<<FOLD<<,>>FOLD>>
nnoremap <space> @=((foldclosed(line('.')) < 0) ? 'zc' : 'zo')<CR>
"----------------------------------------------------------------
" Complement
""""""""""""""""""""""""
" HTML
au Syntax html,css,javascript,xml inoremap ><space> ><Esc>%lyiwh%a</<Esc>pa><Esc>%i
au Syntax html,css,javascript,xml inoremap ><CR> ><Esc>%lyiwo</<Esc>pa><Esc>^d0k^y0j0Pk$
au Syntax html,css,javascript,xml inoremap {<CR> <Esc>:s/ *$//g<CR>:nohls<CR>A {<CR><BS>}<ESC>O
au Syntax html,css,javascript,xml inoremap ;<CR> <Esc>A;<CR>
" PHP
au Syntax php inoremap ><space> ><Esc>%lyiwh%a</<Esc>pa><Esc>%i
au Syntax php inoremap ><CR> ><Esc>%lyiwo</<Esc>pa><Esc>^d0k^y0j0Pk$
au Syntax php inoremap >p <?php ?><Esc>2hi
au Syntax php inoremap >P <?php<CR>?><Esc>O
au Syntax php inoremap #I include '';<Esc>hi
au Syntax php inoremap #R require '';<Esc>hi
au Syntax php inoremap ;<CR> <Esc>A;<CR>
" SQL
au Syntax sql,plsql inoremap #I IF THEN<CR>END IF;<ESC>khhhi
au Syntax sql,plsql inoremap #C CASE <CR>WHEN THEN<CR>ELSE<CR>END CASE;<ESC>kkkA
au Syntax sql,plsql inoremap #L LOOP<CR>END LOOP;<ESC>O
au Syntax sql,plsql inoremap #P DBMS_OUTPUT.PUT_LINE();<ESC>hi
au Syntax sql,plsql inoremap ;<CR> <Esc>A;<CR>
" C
au Syntax c inoremap #< #include<><Esc>i
au Syntax c inoremap #" #include ""<Esc>i
au Syntax c inoremap #M int main(int argc,char *argv[]){<CR>return 0;<CR>}<Esc>kO
au Syntax c inoremap {<CR> <Esc>:s/ *$//g<CR>:nohls<CR>A{<CR>}<ESC>O
au Syntax c inoremap ;<CR> <Esc>A;<CR>
" GO
au Syntax go inoremap {<CR> <Esc>:s/ *$//g<CR>:nohls<CR>A {<CR><BS>}<ESC>O
au Syntax go inoremap {<space> {<CR><BS>}<ESC>O
au Syntax go inoremap (<CR> <Esc>:s/ *$//g<CR>:nohls<CR>A (<CR>)<ESC>O
au Syntax go inoremap ;<CR> <Esc>A;<CR>
" RUST
au Syntax rust inoremap {<CR> <Esc>:s/ *$//g<CR>:nohls<CR>A {<CR><BS>}<ESC>O
au Syntax rust inoremap ;<CR> <Esc>A;<CR>
" SH
au Syntax sh inoremap {<CR> <Esc>:s/ *$//g<CR>:nohls<CR>A {<CR><BS>}<ESC>O
" PYTHON
au Syntax python inoremap :<CR> <C-r>=PythonColon()<CR>
" LUA
au Syntax lua inoremap #fu function ()<CR>end<Esc>Oreturn <Esc>k$F(i
au Syntax lua inoremap #if if then<CR>end<Esc>k$F i
au Syntax lua inoremap #fo for do<CR>end<Esc>k$F i
au Syntax lua inoremap #wh while do<CR>end<Esc>k$F i
"----------------------------------------------------------------
" Operators
""""""""""""""""""""""""
" PHP
au Syntax php inoremap .= <space>.=<space>
au Syntax php inoremap === <space>===<space>
au Syntax php inoremap !== <space>!==<space>
au Syntax php inoremap <= <space><=<space>
au Syntax php inoremap >= <space>>=<space>
au Syntax php inoremap != <space>!=<space>
au Syntax php inoremap \|\| <space>\|\|<space>
au Syntax php inoremap == <space>==<space>
au Syntax php inoremap += <space>+=<space>
au Syntax php inoremap -= <space>-=<space>
au Syntax php inoremap *= <space>*=<space>
au Syntax php inoremap /= <space>/=<space>
au Syntax php inoremap && <space>&&<space>
" C
au Syntax c inoremap <= <space><=<space>
au Syntax c inoremap >= <space>>=<space>
au Syntax c inoremap != <space>!=<space>
au Syntax c inoremap \|\| <space>\|\|<space>
au Syntax c inoremap == <space>==<space>
au Syntax c inoremap += <space>+=<space>
au Syntax c inoremap -= <space>-=<space>
au Syntax c inoremap *= <space>*=<space>
au Syntax c inoremap /= <space>/=<space>
au Syntax c inoremap &= <space>&=<space>
au Syntax c inoremap \|= <space>\|=<space>
au Syntax c inoremap ~= <space>~=<space>
au Syntax c inoremap ^= <space>^=<space>
au Syntax c inoremap && <space>&&<space>
au Syntax c inoremap -> <space>-><space>
au Syntax c inoremap >> <space>>><space>
au Syntax c inoremap << <space><<<space>
" GO
au Syntax go inoremap := <space>:=<space>
au Syntax go inoremap <= <space><=<space>
au Syntax go inoremap >= <space>>=<space>
au Syntax go inoremap != <space>!=<space>
au Syntax go inoremap \|\| <space>\|\|<space>
au Syntax go inoremap == <space>==<space>
au Syntax go inoremap += <space>+=<space>
au Syntax go inoremap -= <space>-=<space>
au Syntax go inoremap *= <space>*=<space>
au Syntax go inoremap /= <space>/=<space>
au Syntax go inoremap &= <space>&=<space>
au Syntax go inoremap \|= <space>\|=<space>
au Syntax go inoremap ~= <space>~=<space>
au Syntax go inoremap ^= <space>^=<space>
au Syntax go inoremap && <space>&&<space>
au Syntax go inoremap -> <space>-><space>
au Syntax go inoremap >> <space>>><space>
au Syntax go inoremap << <space><<<space>
" RUST
au Syntax rust inoremap <= <space><=<space>
au Syntax rust inoremap >= <space>>=<space>
au Syntax rust inoremap != <space>!=<space>
au Syntax rust inoremap \|\| <space>\|\|<space>
au Syntax rust inoremap == <space>==<space>
au Syntax rust inoremap += <space>+=<space>
au Syntax rust inoremap -= <space>-=<space>
au Syntax rust inoremap *= <space>*=<space>
au Syntax rust inoremap /= <space>/=<space>
au Syntax rust inoremap &= <space>&=<space>
au Syntax rust inoremap \|= <space>\|=<space>
au Syntax rust inoremap ~= <space>~=<space>
au Syntax rust inoremap ^= <space>^=<space>
au Syntax rust inoremap && <space>&&<space>
au Syntax rust inoremap -> <space>-><space>
au Syntax rust inoremap >> <space>>><space>
au Syntax rust inoremap << <space><<<space>
" PYTHON
au Syntax python inoremap <= <space><=<space>
au Syntax python inoremap >= <space>>=<space>
au Syntax python inoremap != <space>!=<space>
au Syntax python inoremap \|\| <space>\|\|<space>
au Syntax python inoremap == <space>==<space>
au Syntax python inoremap += <space>+=<space>
au Syntax python inoremap -= <space>-=<space>
au Syntax python inoremap *= <space>*=<space>
au Syntax python inoremap /= <space>/=<space>
au Syntax python inoremap &= <space>&=<space>
au Syntax python inoremap \|= <space>\|=<space>
au Syntax python inoremap ~= <space>~=<space>
au Syntax python inoremap ^= <space>^=<space>
au Syntax python inoremap && <space>&&<space>
" LUA
au Syntax lua inoremap <= <space><=<space>
au Syntax lua inoremap >= <space>>=<space>
au Syntax lua inoremap != <space>!=<space>
au Syntax lua inoremap \|\| <space>\|\|<space>
au Syntax lua inoremap == <space>==<space>
au Syntax lua inoremap += <space>+=<space>
au Syntax lua inoremap -= <space>-=<space>
au Syntax lua inoremap *= <space>*=<space>
au Syntax lua inoremap /= <space>/=<space>
au Syntax lua inoremap &= <space>&=<space>
au Syntax lua inoremap \|= <space>\|=<space>
au Syntax lua inoremap ~= <space>~=<space>
au Syntax lua inoremap ^= <space>^=<space>
au Syntax lua inoremap && <space>&&<space>
" SQL
au Syntax sql,plsql inoremap := <space>:=<space>
au Syntax sql,plsql inoremap <= <space><=<space>
au Syntax sql,plsql inoremap >= <space>>=<space>
au Syntax sql,plsql inoremap != <space>!=<space>
au Syntax sql,plsql inoremap \|\| <space>\|\|<space>
"----------------------------------------------------------------
" Comments
""""""""""""""""""""""""
" Html
au Syntax html nnoremap - V
au Syntax html vnoremap - <Esc>:call setpos(".",[0,line("'<"),0,0])<CR>I<!--<Esc>:call setpos(".",[0,line("'>"),0,0])<CR>A--><Esc>
au Syntax html nnoremap == $?<!--<CR>4x/--><CR>3x:nohls<CR>
" Sql
au Syntax sql,plsql nnoremap - 0<C-v>
au Syntax sql,plsql nnoremap = 0<C-v>
au Syntax sql,plsql vnoremap - I--<Esc>
au Syntax sql,plsql vnoremap = :s:--::<CR>:nohls<CR>0
" C
au Syntax c nnoremap - 0<C-v>
au Syntax c nnoremap = 0<C-v>
au Syntax c vnoremap - I//<Esc>
au Syntax c vnoremap = :s://::<CR><CR>:nohls<CR>0
au Syntax c nnoremap - 0<C-v>
au Syntax c nnoremap = 0<C-v>
" GO
au Syntax go nnoremap - 0<C-v>
au Syntax go nnoremap = 0<C-v>
au Syntax go vnoremap - I//<Esc>
au Syntax go vnoremap = :s://::<CR><CR>:nohls<CR>0
" RUST
au Syntax rust nnoremap - 0<C-v>
au Syntax rust nnoremap = 0<C-v>
au Syntax rust vnoremap - I//<Esc>
au Syntax rust vnoremap = :s://::<CR><CR>:nohls<CR>0
" LUA
au Syntax lua nnoremap - 0<C-v>
au Syntax lua nnoremap = 0<C-v>
au Syntax lua vnoremap - I--<Esc>
au Syntax lua vnoremap = :s:--::<CR>:nohls<CR>0
"-----------------------------------------------------------------
" Matching Pairs
"""""""""""""""""""""""""
inoremap " <c-r>=QuoteDelim('"')<CR>
inoremap ' <c-r>=QuoteDelim("'")<CR>
inoremap ( ()<Esc>i
inoremap ) <c-r>=ClosePair(')')<CR>
inoremap [ []<Esc>i
inoremap ] <c-r>=ClosePair(']')<CR>
inoremap { {}<Esc>i
inoremap } <c-r>=ClosePair('}')<CR>
au Syntax html,css,js,php,xml set mps+=<:>
au Syntax html,css,js,php,xml inoremap > <c-r>=ClosePair('>')<CR>
au Syntax vim inoremap " "
"------------------------------------------------------------------------------
" Ctags
"""""""""""""""""""""""
" C
au syntax c nnoremap <C-w>t <Esc>:let $SRC=input("Enter source dir:")<CR>
au syntax c nnoremap <C-w>T <Esc>:!ctags -R -f /tmp/c_sys_tags -I __THROW --extra=+f --languages=c --langmap=c:+.h --c-kinds=+px --fields=+aiKSz --exclude=/usr/include/c++ --exclude=/usr/include/libio.h /usr/include<CR><CR>
au syntax c set tags=/tmp/c_cur_tags,/tmp/c_sys_tags
au BufWrite *.c,*.h !ctags -R -f /tmp/c_cur_tags --extra=+f --languages=c --langmap=c:+.h --c-kinds=+px --fields=+aiKSz $SRC
" GO
"au syntax go nnoremap <C-w>t <Esc>:let $GOPATH=input("Enter GOPATH dir:")<CR>
au syntax go nnoremap <C-w>t <Esc>:!ctags -R -f /tmp/go_sys_tags --languages=Go /usr/lib/go/src<CR><CR>
au syntax go set tags=/tmp/go_cur_tags,/tmp/go_sys_tags
au BufWrite *.go !ctags -R -f /tmp/go_cur_tags --languages=Go $GOPATH
" PYTHON
au syntax python nnoremap <C-w>t <Esc>:let $SRC=input("Enter source dir:")<CR>
au syntax python nnoremap <C-w>T <Esc>:!ctags -R -f /tmp/python_sys_tags --languages=Python /usr/lib/python3.7<CR><CR>
au syntax python set tags=/tmp/python_cur_tags,/tmp/python_sys_tags
au BufWrite *.py !ctags -R -f /tmp/python_cur_tags --languages=python $SRC
"------------------------------------------------------------------------------
" Cscope
""""""""""""""""""""""""
set cst
set csto=1
set cscopequickfix=s-,g-,c-,d-,i-,t-,e-
"au BufNewFile,BufRead *.c,*.h nnoremap #SS <ESC>:cs add $SRC/cscope.out<CR>
"au BufWrite *.c,*.h !find $SRC -type f|cscope -bk -i -;mv cscope.out $SRC/cscope.out
"au BufNewFile,BufRead *.c,*.h nnoremap #CC <ESC>:!echo 'Generating cs tags ...';find $SRC -type f\|cscope -bk -i -;mv cscope.out $SRC<CR>
"nnoremap <C-_>s :cs find s <C-R>=expand("<cword>")<CR><CR> "查找本C符号跳过注释
"nnoremap <C-_>g :cs find g <C-R>=expand("<cword>")<CR><CR> "查找本定义
"nnoremap <C-_>d :cs find d <C-R>=expand("<cword>")<CR><CR> "查找本函数调用的函数
"nnoremap <C-_>c :cs find c <C-R>=expand("<cword>")<CR><CR> "查找调用本函数的函数
"nnoremap <C-_>t :cs find t <C-R>=expand("<cword>")<CR><CR> "查找本字符串
"nnoremap <C-_>e :cs find e <C-R>=expand("<cword>")<CR><CR> "查找本 egrep 模式
"nnoremap <C-_>f :cs find f <C-R>=expand("<cfile>")<CR><CR> "查找本文件
"nnoremap <C-_>i :cs find i <C-R>=expand("<cfile>")<CR><CR> "查找包含本文件的文件
"------------------------------------------------------------------------------
" NERDTree
"""""""""""""""""""""""
let NERDChristmasTree = 1
let NERDTreeAutoCenter = 1
let NERDTreeQuitOnOpen = 1
let NERDTreeShowBookmarks = 1
let NERDTreeHighlightCursorline = 1
let NERDTreeShowFiles = 1
let NERDTreeStatusline = 1
"let NERDTreeShowHidden=1
"let NERDTreeShowLineNumbers=1
"let NERDTreeWinSize=30
" t.......在新Tab中打开选中文件/书签并跳到新Tab
" T.......在新Tab中打开选中文件/书签但不跳到新Tab
" i.......split一个新窗口打开选中文件并跳到该窗口
" gi......split一个新窗口打开选中文件但不跳到该窗口
" s.......vsp一个新窗口打开选中文件并跳到该窗口
" gs......vsp一个新窗口打开选中文件但不跳到该窗口
" !.......执行当前文件
" O.......递归打开选中结点下的所有目录
" x.......合拢选中结点的父目录
" X.......递归合拢选中结点下的所有目录
"------------------------------------------------------------------------------
" Templates
"""""""""""""""""""""""
let g:enable_template=1
let g:template_dir="~/.vim/templates"
"------------------------------------------------------------------------------
" Functions
"""""""""""""""""""""""
function QuickFix()
if exists('g:QuickFixState') && g:QuickFixState
if exists('g:asyncrun_status') && 'running' == g:asyncrun_status
return ":AsyncStop!\<CR>"
endif
let g:QuickFixState = 0
if 'c' == &filetype
return ":cclose\<CR>:make clean\<CR>\<CR>"
elseif 'go' == &filetype
return ":cclose\<CR>:!go clean\<CR>\<CR>"
else
return ":cclose\<CR>"
endif
else
let g:QuickFixState = 1
if 0 <= index(['c', 'python', 'go', 'rust', 'lua', 'sh'], &filetype)
let b:argvs = input("Enter arguments:")
if matchstr(v:version, '^8')
return ":w!\<CR>\<CR>\<CR>:copen 15\<CR>\<C-w>k:AsyncRun ".&makeprg.b:argvs."\<CR>"
else
return ":w!\<CR>\<CR>\<CR>:make! ".b:argvs."\<CR>\<CR>:copen 15\<CR>\<C-w>k"
endif
else
let g:QuickFixState = 0
return "\<Esc>"
endif
endif
endf
function PythonColon()
let KeyWords = ['if', 'elif', 'else', 'for', 'while', 'class', 'def', 'with', 'try', 'except', 'finally']
let FirstWord = split(getline('.'))[0]
if FirstWord == 'try'
return "\<Esc>A:\<CR>except Exception, e:\<Esc><<O"
elseif 0 <= index(KeyWords, FirstWord)
return "\<Esc>A:\<CR>"
endif
endf
function ClosePair(char)
if getline('.')[col('.') - 1] == a:char
return "\<Right>"
else
return a:char
endif
endf
function QuoteDelim(char)
let line = getline('.')
let col = col('.')
if line[col - 2] == "\\"
return a:char
elseif line[col - 1] == a:char
return "\<Right>"
else
return a:char.a:char."\<Left>"
endif
endf
"------------------------------------------------------------------------------
"------------------------------------------------------------------------------