first commit
This commit is contained in:
commit
6574151a51
87
autoload/gocomplete.vim
Normal file
87
autoload/gocomplete.vim
Normal 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
200
autoload/nerdtree.vim
Normal 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:
|
649
autoload/nerdtree/ui_glue.vim
Normal file
649
autoload/nerdtree/ui_glue.vim
Normal 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
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
115
colors/atom-dark.vim
Normal 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
5
ctags.conf
Normal 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
1328
doc/NERDTree.txt
Normal file
File diff suppressed because it is too large
Load Diff
1238
doc/NERD_tree.txt
Normal file
1238
doc/NERD_tree.txt
Normal file
File diff suppressed because it is too large
Load Diff
431
doc/asyncrun.txt
Normal file
431
doc/asyncrun.txt
Normal 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
335
doc/buffergator.txt
Normal 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:
|
1
ftplugin/go/gocomplete.vim
Normal file
1
ftplugin/go/gocomplete.vim
Normal file
@ -0,0 +1 @@
|
|||||||
|
setlocal omnifunc=gocomplete#Complete
|
430
gvimrc
Normal file
430
gvimrc
Normal 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
354
lib/nerdtree/bookmark.vim
Normal 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
389
lib/nerdtree/creator.vim
Normal 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
13
lib/nerdtree/event.vim
Normal 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
58
lib/nerdtree/flag_set.vim
Normal 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
163
lib/nerdtree/key_map.vim
Normal 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:
|
186
lib/nerdtree/menu_controller.vim
Normal file
186
lib/nerdtree/menu_controller.vim
Normal 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
114
lib/nerdtree/menu_item.vim
Normal 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
208
lib/nerdtree/nerdtree.vim
Normal 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
34
lib/nerdtree/notifier.vim
Normal 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
352
lib/nerdtree/opener.vim
Normal 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
869
lib/nerdtree/path.vim
Normal 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:
|
679
lib/nerdtree/tree_dir_node.vim
Normal file
679
lib/nerdtree/tree_dir_node.vim
Normal 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:
|
347
lib/nerdtree/tree_file_node.vim
Normal file
347
lib/nerdtree/tree_file_node.vim
Normal 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
516
lib/nerdtree/ui.vim
Normal 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:
|
40
nerdtree_plugin/exec_menuitem.vim
Normal file
40
nerdtree_plugin/exec_menuitem.vim
Normal 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
368
nerdtree_plugin/fs_menu.vim
Normal 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
242
plugin/NERD_tree.vim
Normal 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
1118
plugin/asyncrun.vim
Normal file
File diff suppressed because it is too large
Load Diff
132
plugin/buffergator.vim
Normal file
132
plugin/buffergator.vim
Normal 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
66
plugin/template.vim
Normal 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
36
syntax/c.vim
Normal 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
404
syntax/go.vim
Normal 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
91
syntax/nerdtree.vim
Normal 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
10
templates/common/ext/html
Normal 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
9
templates/dynamic/ext/c
Executable 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
14
templates/dynamic/ext/h
Executable 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
19
templates/dynamic/ext/py
Executable 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
49
templates/dynamic/ext/sh
Executable 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
10
templates/dynamic/full/.gitignore
vendored
Executable file
@ -0,0 +1,10 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
cat<<EOF
|
||||||
|
#=========================================
|
||||||
|
# Filename : $1
|
||||||
|
# Author : Colben
|
||||||
|
# Create : `date +"%F %R"`
|
||||||
|
#=========================================
|
||||||
|
|
||||||
|
EOF
|
1
templates/dynamic/full/MAKEFILE
Symbolic link
1
templates/dynamic/full/MAKEFILE
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
Makefile
|
33
templates/dynamic/full/Makefile
Executable file
33
templates/dynamic/full/Makefile
Executable 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
|
1
templates/dynamic/full/makefile
Symbolic link
1
templates/dynamic/full/makefile
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
Makefile
|
425
vimrc
Normal file
425
vimrc
Normal 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
|
||||||
|
|
||||||
|
"------------------------------------------------------------------------------
|
||||||
|
"------------------------------------------------------------------------------
|
Loading…
x
Reference in New Issue
Block a user