diff --git a/bundle/nerdtree/.github/ISSUE_TEMPLATE.md b/bundle/nerdtree/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..c3ca5ef --- /dev/null +++ b/bundle/nerdtree/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,28 @@ + + +### Environment + + +* Operating System: +* Vim version `:version`: +* NERDTree version `git rev-parse --short HEAD`: +* NERDTree settings applied in your vimrc, if any: + ```vim + ``` + +### Process + + +1. + +### Current Result + + +### Expected Result + + +### Screenshot(s) + +### Possible Fix + + diff --git a/bundle/nerdtree/.gitignore b/bundle/nerdtree/.gitignore new file mode 100644 index 0000000..3698c0e --- /dev/null +++ b/bundle/nerdtree/.gitignore @@ -0,0 +1,3 @@ +*~ +*.swp +tags diff --git a/bundle/nerdtree/CHANGELOG b/bundle/nerdtree/CHANGELOG new file mode 100644 index 0000000..6dac46d --- /dev/null +++ b/bundle/nerdtree/CHANGELOG @@ -0,0 +1,179 @@ +Next + - Fix broken "t" and "T" mappings, tabs now open at end (lifecrisis) #759 + - Update doc with already existing mapping variables (asnr) #699 + - Fix the broken g:NERDTreeBookmarksSort setting (lifecrisis) #696 + - Correct NERDTreeIgnore pattern in doc (cntoplolicon) #648 + - Remove empty segments when splitting path (sooth-sayer) #574 + - Suppress autocmds less agressively (wincent) #578 #691 + - Add an Issues template to ask for more info initially. + - Fix markdown headers in readme (josephfrazier) #676 + - Don't touch @o and @h registers when rendering + - Fix bug with files and directories with dollar signs (alegen) #649 + - Reuse/reopen existing window trees where possible #244 + - Remove NERDTree.previousBuf() + - Change color of arrow (Leeiio) #630 + - Improved a tip in README.markdown (ggicci) #628 + - Shorten delete confimration of empty directory to 'y' (mikeperri) #530 + - Fix API call to open directory tree in window (devm33) #533 + - Change default arrows on non-Windows platforms (gwilk) #546 + - Update to README - combine cd and git clone (zwhitchcox) #584 + - Update to README - Tip: start NERDTree when vim starts (therealplato) #593 + - Escape filename when moving an open buffer (zacharyvoase) #595 + - Fixed incorrect :helptags command in README (curran) #619 + - Fixed incomplete escaping of folder arrows (adityanatraj) #548 + - Added NERDTreeCascadeSingleChildDir option (juanibiapina) #558 + - Replace strchars() with backward compatible workaround. + - Add support for copy command in Windows (SkylerLipthay) #231 + - Fixed typo in README.markdown - :Helptags -> :helptags + - Rename "primary" and "secondary" trees to "tab" and "window" trees. + - Move a bunch of buffer level variables into the NERDTree and UI classes. + - Display cascading dirs on one line to save vertical/horizontal space (@matt-gardner: brainstorming/testing) + - Remove the old style UI - Remove 'NERDTreeDirArrows' option. + - On windows default to + and ~ for expand/collapse directory symbols. + - Lots more refactoring. Move a bunch of b: level vars into b:NERDTree and friends. + +5.0.0 + - Refactor the code significantly: + * Break the classes out into their own files. + * Make the majority of the code OO - previously large parts were + effectively a tangle of "global" methods. + - Add an API to assign flags to nodes. This allows VCS plugins like + https://github.com/Xuyuanp/nerdtree-git-plugin to exist. Thanks to + Xuyuanp for helping design/test/build said API. + - add 'scope' argument to the key map API see :help NERDTreeAddKeyMap() + - add magic [[dir]] and [[file]] flags to NERDTreeIgnore + - add support for custom path filters. See :help NERDTreeAddPathFilter() + - add path listener API. See :help NERDTreePathListenerAPI. + - expand the fs menu functionality to list file properties (PhilRunninger, + apbarrero, JESii) + - make bookmarks work with `~` home shortcuts (hiberabyss) + - show OSX specific fsmenu options in regular vim on mac (evindor) + - make dir arrow icons configurable (PickRelated) + - optimise node sorting performance when opening large dirs (vtsang) + - make the root note render prettier by truncating it at a path slash (gcmt) + - remove NERDChristmasTree option - its always christmas now + - add "cascade" open and closing for dirs containing only another single + dir. See :help NERDTreeCascadeOpenSingleChildDir (pendulm) + + Many other fixes, doc updates and contributions from: + actionshrimp + SchDen + egalpin + cperl82 - many small fixes + toiffel + WoLpH + handcraftedbits + devmanhinton + xiaodili + zhangoose + gastropoda + mixvin + alvan + lucascaton + kelaban + shanesmith + staeff + pendulm + stephenprater + franksort + agrussellknives + AndrewRadev + Twinside + +4.2.0 + - Add NERDTreeDirArrows option to make the UI use pretty arrow chars + instead of the old +~| chars to define the tree structure (sickill) + - shift the syntax highlighting out into its own syntax file (gnap) + - add some mac specific options to the filesystem menu - for macvim + only (andersonfreitas) + - Add NERDTreeMinimalUI option to remove some non functional parts of the + nerdtree ui (camthompson) + - tweak the behaviour of :NERDTreeFind - see :help :NERDTreeFind for the + new behaviour (benjamingeiger) + - if no name is given to :Bookmark, make it default to the name of the + target file/dir (minyoung) + - use 'file' completion when doing copying, create, and move + operations (EvanDotPro) + - lots of misc bug fixes (paddyoloughlin, sdewald, camthompson, Vitaly + Bogdanov, AndrewRadev, mathias, scottstvnsn, kml, wycats, me RAWR!) + +4.1.0 + features: + - NERDTreeFind to reveal the node for the current buffer in the tree, + see |NERDTreeFind|. This effectively merges the FindInNERDTree plugin (by + Doug McInnes) into the script. + - make NERDTreeQuitOnOpen apply to the t/T keymaps too. Thanks to Stefan + Ritter and Rémi Prévost. + - truncate the root node if wider than the tree window. Thanks to Victor + Gonzalez. + + bugfixes: + - really fix window state restoring + - fix some win32 path escaping issues. Thanks to Stephan Baumeister, Ricky, + jfilip1024, and Chris Chambers + +4.0.0 + - add a new programmable menu system (see :help NERDTreeMenu). + - add new APIs to add menus/menu-items to the menu system as well as + custom key mappings to the NERD tree buffer (see :help NERDTreeAPI). + - removed the old API functions + - added a mapping to maximize/restore the size of nerd tree window, thanks + to Guillaume Duranceau for the patch. See :help NERDTree-A for details. + + - fix a bug where secondary nerd trees (netrw hijacked trees) and + NERDTreeQuitOnOpen didnt play nicely, thanks to Curtis Harvey. + - fix a bug where the script ignored directories whose name ended in a dot, + thanks to Aggelos Orfanakos for the patch. + - fix a bug when using the x mapping on the tree root, thanks to Bryan + Venteicher for the patch. + - fix a bug where the cursor position/window size of the nerd tree buffer + wasnt being stored on closing the window, thanks to Richard Hart. + - fix a bug where NERDTreeMirror would mirror the wrong tree + +3.1.1 + - fix a bug where a non-listed no-name buffer was getting created every + time the tree windows was created, thanks to Derek Wyatt and owen1 + - make behave the same as the 'o' mapping + - some helptag fixes in the doc, thanks strull + - fix a bug when using :set nohidden and opening a file where the previous + buf was modified. Thanks iElectric + - other minor fixes + +3.1.0 + New features: + - add mappings to open files in a vsplit, see :help NERDTree-s and :help + NERDTree-gs + - make the statusline for the nerd tree window default to something + hopefully more useful. See :help 'NERDTreeStatusline' + Bugfixes: + - make the hijack netrw functionality work when vim is started with "vim + " (thanks to Alf Mikula for the patch). + - fix a bug where the CWD wasnt being changed for some operations even when + NERDTreeChDirMode==2 (thanks to Lucas S. Buchala) + - add -bar to all the nerd tree :commands so they can chain with other + :commands (thanks to tpope) + - fix bugs when ignorecase was set (thanks to nach) + - fix a bug with the relative path code (thanks to nach) + - fix a bug where doing a :cd would cause :NERDTreeToggle to fail (thanks nach) + + +3.0.1 + Bugfixes: + - fix bugs with :NERDTreeToggle and :NERDTreeMirror when 'hidden + was not set + - fix a bug where :NERDTree would fail if was relative and + didnt start with a ./ or ../ Thanks to James Kanze. + - make the q mapping work with secondary (:e style) trees, + thanks to jamessan + - fix a bunch of small bugs with secondary trees + + More insane refactoring. + +3.0.0 + - hijack netrw so that doing an :edit will put a NERD tree in + the window rather than a netrw browser. See :help 'NERDTreeHijackNetrw' + - allow sharing of trees across tabs, see :help :NERDTreeMirror + - remove "top" and "bottom" as valid settings for NERDTreeWinPos + - change the '' mapping to 'i' + - change the 'H' mapping to 'I' + - lots of refactoring diff --git a/bundle/nerdtree/LICENCE b/bundle/nerdtree/LICENCE new file mode 100644 index 0000000..8b1a9d8 --- /dev/null +++ b/bundle/nerdtree/LICENCE @@ -0,0 +1,13 @@ + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + Version 2, December 2004 + +Copyright (C) 2004 Sam Hocevar + +Everyone is permitted to copy and distribute verbatim or modified +copies of this license document, and changing it is allowed as long +as the name is changed. + + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. You just DO WHAT THE FUCK YOU WANT TO. diff --git a/bundle/nerdtree/README.markdown b/bundle/nerdtree/README.markdown new file mode 100644 index 0000000..6efeb0b --- /dev/null +++ b/bundle/nerdtree/README.markdown @@ -0,0 +1,96 @@ +The NERDTree +============= + +Introduction +------------ + +The NERDTree is a file system explorer for the Vim editor. Using this plugin, +users can visually browse complex directory hierarchies, quickly open files for +reading or editing, and perform basic file system operations. + +This plugin can also be extended with custom mappings using a special API. The +details of this API and of other NERDTree features are described in the +included documentation. + +![NERDTree Screenshot](https://github.com/scrooloose/nerdtree/raw/master/screenshot.png) + +Installation +------------ + +#### [pathogen.vim](https://github.com/tpope/vim-pathogen) + + git clone https://github.com/scrooloose/nerdtree.git ~/.vim/bundle/nerdtree + +Then reload Vim, run `:helptags ~/.vim/bundle/nerdtree/doc/` or `:Helptags`, and check out `:help NERDTree.txt`. + + +#### [apt-vim](https://github.com/egalpin/apt-vim) + + apt-vim install -y https://github.com/scrooloose/nerdtree.git + +F.A.Q. +------ + +> Is there any support for `git` flags? + +Yes, install [nerdtree-git-plugin](https://github.com/Xuyuanp/nerdtree-git-plugin). + +--- + +> Can I have the nerdtree on every tab automatically? + +Nope. If this is something you want then chances are you aren't using tabs and +buffers as they were intended to be used. Read this +http://stackoverflow.com/questions/102384/using-vims-tabs-like-buffers + +If you are interested in this behaviour then consider [vim-nerdtree-tabs](https://github.com/jistr/vim-nerdtree-tabs) + +--- +> How can I open a NERDTree automatically when vim starts up? + +Stick this in your vimrc: `autocmd vimenter * NERDTree` + +--- +> How can I open a NERDTree automatically when vim starts up if no files were specified? + +Stick this in your vimrc: + + autocmd StdinReadPre * let s:std_in=1 + autocmd VimEnter * if argc() == 0 && !exists("s:std_in") | NERDTree | endif + +Note: Now start vim with plain `vim`, not `vim .` + +--- +> How can I open NERDTree automatically when vim starts up on opening a directory? + + autocmd StdinReadPre * let s:std_in=1 + autocmd VimEnter * if argc() == 1 && isdirectory(argv()[0]) && !exists("s:std_in") | exe 'NERDTree' argv()[0] | wincmd p | ene | endif + +This window is tab-specific, meaning it's used by all windows in the tab. This trick also prevents NERDTree from hiding when first selecting a file. + +--- +> How can I map a specific key or shortcut to open NERDTree? + +Stick this in your vimrc to open NERDTree with `Ctrl+n` (you can set whatever key you want): + + map :NERDTreeToggle + +--- +> How can I close vim if the only window left open is a NERDTree? + +Stick this in your vimrc: + + autocmd bufenter * if (winnr("$") == 1 && exists("b:NERDTree") && b:NERDTree.isTabTree()) | q | endif + +--- +> Can I have different highlighting for different file extensions? + +See here: https://github.com/scrooloose/nerdtree/issues/433#issuecomment-92590696 + +--- +> How can I change default arrows? + +Use these variables in your vimrc. Note that below are default arrow symbols + + let g:NERDTreeDirArrowExpandable = '▸' + let g:NERDTreeDirArrowCollapsible = '▾' diff --git a/bundle/nerdtree/autoload/nerdtree.vim b/bundle/nerdtree/autoload/nerdtree.vim new file mode 100644 index 0000000..bdf3deb --- /dev/null +++ b/bundle/nerdtree/autoload/nerdtree.vim @@ -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: diff --git a/bundle/nerdtree/autoload/nerdtree/ui_glue.vim b/bundle/nerdtree/autoload/nerdtree/ui_glue.vim new file mode 100644 index 0000000..12dd9ae --- /dev/null +++ b/bundle/nerdtree/autoload/nerdtree/ui_glue.vim @@ -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 = '' . s:SID() . '_' + + call NERDTreeAddKeyMap({ 'key': '', 'scope': 'all', 'callback': s . 'handleMiddleMouse' }) + call NERDTreeAddKeyMap({ 'key': '', '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! \" + + 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('') + command! -n=? -complete=dir -bar NERDTreeToggle :call g:NERDTreeCreator.ToggleTabTree('') + command! -n=0 -bar NERDTreeClose :call g:NERDTree.Close() + command! -n=1 -complete=customlist,nerdtree#completeBookmarks -bar NERDTreeFromBookmark call g:NERDTreeCreator.CreateTabTree('') + command! -n=0 -bar NERDTreeMirror call g:NERDTreeCreator.CreateMirror() + command! -n=? -complete=file -bar NERDTreeFind call s:findAndRevealPath('') + 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(''), '\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: diff --git a/bundle/nerdtree/doc/NERDTree.txt b/bundle/nerdtree/doc/NERDTree.txt new file mode 100644 index 0000000..5b2ef68 --- /dev/null +++ b/bundle/nerdtree/doc/NERDTree.txt @@ -0,0 +1,1402 @@ +*NERDTree.txt* A tree explorer plugin to rule the Vim world. Bwahahaha!! + + # #### #### ~ + ### \/#|### |/#### ~ + d8 888 ##\/#/ \||/##/_/##/_# ~ + d88 888 ee ,e e, ### \/###|/ \/ # ### ~ + d88888 888 88b d88 88b ##_\_#\_\## | #/###_/_#### ~ + 888 888 888 888 , ## #### # \ #| / #### ##/## ~ + 888 888 888 "YeeP" __#_--###`. |{,###---###-~ ~ + \ % @% ~ + Y88b Y88 888'Y88 888 88e 888 88e \%@% 88P'888'Y88 ~ + Y88b Y8 888 ,'Y 888 888D 888 888b %o% P' 888 'Y 888,8, ,e e, ,e e, ~ + b Y88b Y 888C8 888 88" 888 8888D %@% 888 888 " d88 88b d88 88b ~ + 8b Y88b 888 ",d 888 b, 888 888P %@% 888 888 888 , 888 , ~ + 88b Y88b 888,d88 888 88b, 888 88" %@% 888 888 "YeeP" "YeeP" ~ + , -=-%{@%-^- _ ~ + ejm `} Reference Manual ~ + { ~ +============================================================================== +CONTENTS *NERDTree-contents* + + 1.Intro...................................|NERDTree| + 2.Functionality provided..................|NERDTreeFunctionality| + 2.1.Global commands...................|NERDTreeGlobalCommands| + 2.2.Bookmarks.........................|NERDTreeBookmarks| + 2.2.1.The bookmark table..........|NERDTreeBookmarkTable| + 2.2.2.Bookmark commands...........|NERDTreeBookmarkCommands| + 2.2.3.Invalid bookmarks...........|NERDTreeInvalidBookmarks| + 2.3.NERD tree mappings................|NERDTreeMappings| + 2.4.The NERD tree menu................|NERDTreeMenu| + 3.Settings................................|NERDTreeSettings| + 3.1.Settings summary..................|NERDTreeSettingsSummary| + 3.2.Settings details..................|NERDTreeSettingsDetails| + 4.The NERD tree API.......................|NERDTreeAPI| + 4.1.Key map API.......................|NERDTreeKeymapAPI| + 4.2.Menu API..........................|NERDTreeMenuAPI| + 4.3.Menu API..........................|NERDTreeAddPathFilter()| + 4.4.Path Listener API.................|NERDTreePathListenerAPI| + 5.About...................................|NERDTreeAbout| + 6.License.................................|NERDTreeLicense| + +============================================================================== +1. Intro *NERDTree* + +What is this "NERD tree"?? + +The NERD tree allows you to explore your filesystem and to open files and +directories. It presents the filesystem to you in the form of a tree which you +manipulate with the keyboard and/or mouse. It also allows you to perform +simple filesystem operations. + +The following features and functionality are provided by the NERD tree: + * Files and directories are displayed in a hierarchical tree structure + * Different highlighting is provided for the following types of nodes: + * files + * directories + * sym-links + * windows .lnk files + * read-only files + * executable files + * Many (customisable) mappings are provided to manipulate the tree: + * Mappings to open/close/explore directory nodes + * Mappings to open files in new/existing windows/tabs + * Mappings to change the current root of the tree + * Mappings to navigate around the tree + * ... + * Directories and files can be bookmarked. + * Most NERD tree navigation can also be done with the mouse + * Filtering of tree content (can be toggled at runtime) + * custom file filters to prevent e.g. vim backup files being displayed + * optional displaying of hidden files (. files) + * files can be "turned off" so that only directories are displayed + * The position and size of the NERD tree window can be customised + * The order in which the nodes in the tree are listed can be customised. + * A model of your filesystem is created/maintained as you explore it. This + has several advantages: + * All filesystem information is cached and is only re-read on demand + * If you revisit a part of the tree that you left earlier in your + session, the directory nodes will be opened/closed as you left them + * The script remembers the cursor position and window position in the NERD + tree so you can toggle it off (or just close the tree window) and then + reopen it (with NERDTreeToggle) the NERD tree window will appear exactly + as you left it + * You can have a separate NERD tree for each tab, share trees across tabs, + or a mix of both. + * By default the script overrides the default file browser (netrw), so if + you :edit a directory a (slightly modified) NERD tree will appear in the + current window + * A programmable menu system is provided (simulates right clicking on a + node) + * one default menu plugin is provided to perform basic filesystem + operations (create/delete/move/copy files/directories) + * There's an API for adding your own keymappings + + +============================================================================== +2. Functionality provided *NERDTreeFunctionality* + +------------------------------------------------------------------------------ +2.1. Global Commands *NERDTreeGlobalCommands* + +:NERDTree [ | ] *:NERDTree* + Opens a fresh NERD tree. The root of the tree depends on the argument + given. There are 3 cases: If no argument is given, the current directory + will be used. If a directory is given, that will be used. If a bookmark + name is given, the corresponding directory will be used. For example: > + :NERDTree /home/marty/vim7/src + :NERDTree foo (foo is the name of a bookmark) +< +:NERDTreeVCS [ | ] *:NERDTreeVCS* + Like |:NERDTree|, but searches up the directory tree to find the top of + the version control system repository, and roots the NERD tree there. It + works with Git, Subversion, Mercurial, Bazaar, and Darcs repositories. A + couple of examples: > + :NERDTreeVCS /home/marty/nerdtree/doc (opens /home/marty/nerdtree) + :NERDTreeVCS (opens root of repository containing CWD) +< +:NERDTreeFromBookmark *:NERDTreeFromBookmark* + Opens a fresh NERD tree with the root initialized to the dir for + . The only reason to use this command over :NERDTree is for + the completion (which is for bookmarks rather than directories). + +:NERDTreeToggle [ | ] *:NERDTreeToggle* + If a NERD tree already exists for this tab, it is reopened and rendered + again. If no NERD tree exists for this tab then this command acts the + same as the |:NERDTree| command. + +:NERDTreeFocus *:NERDTreeFocus* + Opens (or reopens) the NERD Tree if it is not currently visible; + otherwise, the cursor is moved to the already-open NERD Tree. + +:NERDTreeMirror *:NERDTreeMirror* + Shares an existing NERD tree, from another tab, in the current tab. + Changes made to one tree are reflected in both as they are actually the + same buffer. + + If only one other NERD tree exists, that tree is automatically mirrored. + If more than one exists, the script will ask which tree to mirror. + +:NERDTreeClose *:NERDTreeClose* + Close the NERD tree in this tab. + +:NERDTreeFind [] *:NERDTreeFind* + Without the optional argument, find and reveal the file for the active + buffer in the NERDTree window. With the argument, find and + reveal the specified path. + + Focus will be shifted to the NERDTree window, and the cursor will be + placed on the tree node for the determined path. If a NERDTree for the + current tab does not exist, a new one will be initialized. + +:NERDTreeCWD *:NERDTreeCWD* + Change the NERDTree root to the current working directory. If no + NERDTree exists for this tab, a new one is opened. + +:NERDTreeRefreshRoot *:NERDTreeRefreshRoot* + Refreshes the NERD tree root node. + +------------------------------------------------------------------------------ +2.2. Bookmarks *NERDTreeBookmarks* + +Bookmarks in the NERD tree are a way to tag files or directories of interest. +For example, you could use bookmarks to tag all of your project directories. + +------------------------------------------------------------------------------ +2.2.1. The Bookmark Table *NERDTreeBookmarkTable* + +If the bookmark table is active (see |NERDTree-B| and +|NERDTreeShowBookmarks|), it will be rendered above the tree. You can double +click bookmarks or use the |NERDTree-o| mapping to activate them. See also, +|NERDTree-t| and |NERDTree-T| + +------------------------------------------------------------------------------ +2.2.2. Bookmark commands *NERDTreeBookmarkCommands* + +Note: The following commands are only available within the NERDTree buffer. + +:Bookmark [] + Bookmark the current node as . If there is already a + bookmark, it is overwritten. must not contain spaces. + If is not provided, it defaults to the file or directory name. + For directories, a trailing slash is present. + +:BookmarkToRoot + Make the directory corresponding to the new root. If a treenode + corresponding to is already cached somewhere in the tree then + the current tree will be used, otherwise a fresh tree will be opened. + Note that if points to a file then its parent will be used + instead. + +:RevealBookmark + If the node is cached under the current root then it will be revealed + (i.e. directory nodes above it will be opened) and the cursor will be + placed on it. + +:OpenBookmark + The Bookmark named is opened as if |NERDTree-o| was applied to + its entry in the Bookmark table. If the Bookmark points to a directory, + it is made the new root of the current NERDTree. If the Bookmark points + to a file, that file is opened for editing in another window. + +:ClearBookmarks [] + Remove all the given bookmarks. If no bookmarks are given then remove all + bookmarks on the current node. + +:ClearAllBookmarks + Remove all bookmarks. + +:ReadBookmarks + Re-read the bookmarks in the |NERDTreeBookmarksFile|. + +See also |:NERDTree| and |:NERDTreeFromBookmark|. + +------------------------------------------------------------------------------ +2.2.3. Invalid Bookmarks *NERDTreeInvalidBookmarks* + +If invalid bookmarks are detected, the script will issue an error message and +the invalid bookmarks will become unavailable for use. + +These bookmarks will still be stored in the bookmarks file (see +|NERDTreeBookmarksFile|), down the bottom. There will always be a blank line +after the valid bookmarks but before the invalid ones. + +Each line in the bookmarks file represents one bookmark. The proper format is: + + +After you have corrected any invalid bookmarks, either restart vim, or go +:ReadBookmarks from the NERD tree window. + +------------------------------------------------------------------------------ +2.3. NERD tree Mappings *NERDTreeMappings* + +Default~ +Key Description help-tag~ + +o........Open files, directories and bookmarks......................|NERDTree-o| +go.......Open selected file, but leave cursor in the NERDTree......|NERDTree-go| +t........Open selected node/bookmark in a new tab...................|NERDTree-t| +T........Same as 't' but keep the focus on the current tab..........|NERDTree-T| +i........Open selected file in a split window.......................|NERDTree-i| +gi.......Same as i, but leave the cursor on the NERDTree...........|NERDTree-gi| +s........Open selected file in a new vsplit.........................|NERDTree-s| +gs.......Same as s, but leave the cursor on the NERDTree...........|NERDTree-gs| +O........Recursively open the selected directory....................|NERDTree-O| +x........Close the current nodes parent.............................|NERDTree-x| +X........Recursively close all children of the current node.........|NERDTree-X| +e........Edit the current dir.......................................|NERDTree-e| + +............same as |NERDTree-o|. +double-click....same as |NERDTree-o|. +middle-click....same as |NERDTree-i| for files, and |NERDTree-e| for dirs. + +D........Delete the current bookmark ...............................|NERDTree-D| + +P........Jump to the root node......................................|NERDTree-P| +p........Jump to current nodes parent...............................|NERDTree-p| +K........Jump up inside directories at the current tree depth.......|NERDTree-K| +J........Jump down inside directories at the current tree depth.....|NERDTree-J| +....Jump down to next sibling of the current directory.......|NERDTree-C-J| +....Jump up to previous sibling of the current directory.....|NERDTree-C-K| + +C........Change the tree root to the selected dir...................|NERDTree-C| +u........Move the tree root up one directory........................|NERDTree-u| +U........Same as 'u' except the old root node is left open..........|NERDTree-U| +r........Recursively refresh the current directory..................|NERDTree-r| +R........Recursively refresh the current root.......................|NERDTree-R| +m........Display the NERD tree menu.................................|NERDTree-m| +cd.......Change the CWD to the dir of the selected node............|NERDTree-cd| +CD.......Change tree root to the CWD...............................|NERDTree-CD| + +I........Toggle whether hidden files displayed......................|NERDTree-I| +f........Toggle whether the file filters are used...................|NERDTree-f| +F........Toggle whether files are displayed.........................|NERDTree-F| +B........Toggle whether the bookmark table is displayed.............|NERDTree-B| + +q........Close the NERDTree window..................................|NERDTree-q| +A........Zoom (maximize/minimize) the NERDTree window...............|NERDTree-A| +?........Toggle the display of the quick help.......................|NERDTree-?| + +------------------------------------------------------------------------------ + *NERDTree-o* +Default key: o +Map setting: NERDTreeMapActivateNode +Applies to: files and directories. + +If a file node is selected, it is opened in the previous window. + +If a directory is selected it is opened or closed depending on its current +state. + +If a bookmark that links to a directory is selected then that directory +becomes the new root. + +If a bookmark that links to a file is selected then that file is opened in the +previous window. + +------------------------------------------------------------------------------ + *NERDTree-go* +Default key: go +Map setting: NERDTreeMapPreview +Applies to: files. + +If a file node is selected, it is opened in the previous window, but the +cursor does not move. + +The default key combo for this mapping is "g" + NERDTreeMapActivateNode (see +|NERDTree-o|). + +------------------------------------------------------------------------------ + *NERDTree-t* +Default key: t +Map setting: NERDTreeMapOpenInTab +Applies to: files and directories. + +Opens the selected file in a new tab. If a directory is selected, a fresh +NERD Tree for that directory is opened in a new tab. + +If a bookmark which points to a directory is selected, open a NERD tree for +that directory in a new tab. If the bookmark points to a file, open that file +in a new tab. + +------------------------------------------------------------------------------ + *NERDTree-T* +Default key: T +Map setting: NERDTreeMapOpenInTabSilent +Applies to: files and directories. + +The same as |NERDTree-t| except that the focus is kept in the current tab. + +------------------------------------------------------------------------------ + *NERDTree-i* +Default key: i +Map setting: NERDTreeMapOpenSplit +Applies to: files. + +Opens the selected file in a new split window and puts the cursor in the new +window. + +------------------------------------------------------------------------------ + *NERDTree-gi* +Default key: gi +Map setting: NERDTreeMapPreviewSplit +Applies to: files. + +The same as |NERDTree-i| except that the cursor is not moved. + +The default key combo for this mapping is "g" + NERDTreeMapOpenSplit (see +|NERDTree-i|). + +------------------------------------------------------------------------------ + *NERDTree-s* +Default key: s +Map setting: NERDTreeMapOpenVSplit +Applies to: files. + +Opens the selected file in a new vertically split window and puts the cursor +in the new window. + +------------------------------------------------------------------------------ + *NERDTree-gs* +Default key: gs +Map setting: NERDTreeMapPreviewVSplit +Applies to: files. + +The same as |NERDTree-s| except that the cursor is not moved. + +The default key combo for this mapping is "g" + NERDTreeMapOpenVSplit (see +|NERDTree-s|). + +------------------------------------------------------------------------------ + *NERDTree-O* +Default key: O +Map setting: NERDTreeMapOpenRecursively +Applies to: directories. + +Recursively opens the selected directory. + +All files and directories are cached, but if a directory would not be +displayed due to file filters (see |NERDTreeIgnore| |NERDTree-f|) or the +hidden file filter (see |NERDTreeShowHidden|) then its contents are not +cached. This is handy, especially if you have .svn directories. + +------------------------------------------------------------------------------ + *NERDTree-x* +Default key: x +Map setting: NERDTreeMapCloseDir +Applies to: files and directories. + +Closes the parent of the selected node. + +------------------------------------------------------------------------------ + *NERDTree-X* +Default key: X +Map setting: NERDTreeMapCloseChildren +Applies to: directories. + +Recursively closes all children of the selected directory. + +Tip: To quickly "reset" the tree, use |NERDTree-P| with this mapping. + +------------------------------------------------------------------------------ + *NERDTree-e* +Default key: e +Map setting: NERDTreeMapOpenExpl +Applies to: files and directories. + +|:edit|s the selected directory, or the selected file's directory. This could +result in a NERD tree or a netrw being opened, depending on +|NERDTreeHijackNetrw|. + +------------------------------------------------------------------------------ + *NERDTree-D* +Default key: D +Map setting: NERDTreeMapDeleteBookmark +Applies to: lines in the bookmarks table + +Deletes the currently selected bookmark. + +------------------------------------------------------------------------------ + *NERDTree-P* +Default key: P +Map setting: NERDTreeMapJumpRoot +Applies to: no restrictions. + +Jump to the tree root. + +------------------------------------------------------------------------------ + *NERDTree-p* +Default key: p +Map setting: NERDTreeMapJumpParent +Applies to: files and directories. + +Jump to the parent node of the selected node. + +------------------------------------------------------------------------------ + *NERDTree-K* +Default key: K +Map setting: NERDTreeMapJumpFirstChild +Applies to: files and directories. + +Jump to the first child of the current nodes parent. + +If the cursor is already on the first node then do the following: + * loop back thru the siblings of the current nodes parent until we find an + open dir with children + * go to the first child of that node + +------------------------------------------------------------------------------ + *NERDTree-J* +Default key: J +Map setting: NERDTreeMapJumpLastChild +Applies to: files and directories. + +Jump to the last child of the current nodes parent. + +If the cursor is already on the last node then do the following: + * loop forward thru the siblings of the current nodes parent until we find + an open dir with children + * go to the last child of that node + +------------------------------------------------------------------------------ + *NERDTree-C-J* +Default key: +Map setting: NERDTreeMapJumpNextSibling +Applies to: files and directories. + +Jump to the next sibling of the selected node. + +------------------------------------------------------------------------------ + *NERDTree-C-K* +Default key: +Map setting: NERDTreeMapJumpPrevSibling +Applies to: files and directories. + +Jump to the previous sibling of the selected node. + +------------------------------------------------------------------------------ + *NERDTree-C* +Default key: C +Map setting: NERDTreeMapChangeRoot +Applies to: files and directories. + +Make the selected directory node the new tree root. If a file is selected, its +parent is used. + +------------------------------------------------------------------------------ + *NERDTree-u* +Default key: u +Map setting: NERDTreeMapUpdir +Applies to: no restrictions. + +Move the tree root up a dir (like doing a "cd .."). + +------------------------------------------------------------------------------ + *NERDTree-U* +Default key: U +Map setting: NERDTreeMapUpdirKeepOpen +Applies to: no restrictions. + +Like |NERDTree-u| except that the old tree root is kept open. + +------------------------------------------------------------------------------ + *NERDTree-r* +Default key: r +Map setting: NERDTreeMapRefresh +Applies to: files and directories. + +If a dir is selected, recursively refresh that dir, i.e. scan the filesystem +for changes and represent them in the tree. + +If a file node is selected then the above is done on it's parent. + +------------------------------------------------------------------------------ + *NERDTree-R* +Default key: R +Map setting: NERDTreeMapRefreshRoot +Applies to: no restrictions. + +Recursively refresh the tree root. + +------------------------------------------------------------------------------ + *NERDTree-m* +Default key: m +Map setting: NERDTreeMapMenu +Applies to: files and directories. + +Display the NERD tree menu. See |NERDTreeMenu| for details. + +------------------------------------------------------------------------------ + *NERDTree-cd* +Default key: cd +Map setting: NERDTreeMapChdir +Applies to: files and directories. + +Change Vim's current working directory to that of the selected node. + +------------------------------------------------------------------------------ + *NERDTree-CD* +Default key: CD +Map setting: NERDTreeMapCWD +Applies to: no restrictions. + +Change the NERDTree root to Vim's current working directory. + +------------------------------------------------------------------------------ + *NERDTree-I* +Default key: I +Map setting: NERDTreeMapToggleHidden +Applies to: no restrictions. + +Toggles whether hidden files (i.e. "dot files") are displayed. + +------------------------------------------------------------------------------ + *NERDTree-f* +Default key: f +Map setting: NERDTreeMapToggleFilters +Applies to: no restrictions. + +Toggles whether file filters are used. See |NERDTreeIgnore| for details. + +------------------------------------------------------------------------------ + *NERDTree-F* +Default key: F +Map setting: NERDTreeMapToggleFiles +Applies to: no restrictions. + +Toggles whether file nodes are displayed. + +------------------------------------------------------------------------------ + *NERDTree-B* +Default key: B +Map setting: NERDTreeMapToggleBookmarks +Applies to: no restrictions. + +Toggles whether the bookmarks table is displayed. + +------------------------------------------------------------------------------ + *NERDTree-q* +Default key: q +Map setting: NERDTreeMapQuit +Applies to: no restrictions. + +Closes the NERDTree window. + +------------------------------------------------------------------------------ + *NERDTree-A* +Default key: A +Map setting: NERDTreeMapToggleZoom +Applies to: no restrictions. + +Maximize (zoom) and minimize the NERDTree window. + +------------------------------------------------------------------------------ + *NERDTree-?* +Default key: ? +Map setting: NERDTreeMapHelp +Applies to: no restrictions. + +Toggles whether the quickhelp is displayed. + +------------------------------------------------------------------------------ +2.3. The NERD tree menu *NERDTreeMenu* + +The NERD tree has a menu that can be programmed via the an API (see +|NERDTreeMenuAPI|). The idea is to simulate the "right click" menus that most +file explorers have. + +The script comes with two default menu plugins: exec_menuitem.vim and +fs_menu.vim. fs_menu.vim adds some basic filesystem operations to the menu for +creating/deleting/moving/copying files and dirs. exec_menuitem.vim provides a +menu item to execute executable files. + +Related tags: |NERDTree-m| |NERDTreeApi| + +------------------------------------------------------------------------------ + *NERDTreeMenu-j* +Default key: j +Map option: NERDTreeMenuDown +Applies to: The NERD tree menu. + +Moves the cursor down. + +------------------------------------------------------------------------------ + *NERDTreeMenu-k* +Default key: k +Map option: NERDTreeMenuUp +Applies to: The NERD tree menu. + +Moves the cursor up. + +============================================================================== +3. Customisation *NERDTreeSettings* + + +------------------------------------------------------------------------------ +3.1. Customisation summary *NERDTreeSettingsSummary* + +The plugin provides the following settings that can customise the behaviour +the NERD tree. These settings should be set in your vimrc, using `:let`. + +|loaded_nerd_tree| Turns off the script. + +|NERDTreeAutoCenter| Controls whether the NERD tree window centers + when the cursor moves within a specified + distance to the top/bottom of the window. + +|NERDTreeAutoCenterThreshold| Controls the sensitivity of autocentering. + +|NERDTreeCaseSensitiveSort| Tells the NERD tree whether to be case + sensitive or not when sorting nodes. + +|NERDTreeNaturalSort| Tells the NERD tree whether to use natural sort + order or not when sorting nodes. + +|NERDTreeSortHiddenFirst| Tells the NERD tree whether to take the dot at + the beginning of the hidden file names into + account when sorting nodes. + +|NERDTreeChDirMode| Tells the NERD tree if/when it should change + vim's current working directory. + +|NERDTreeHighlightCursorline| Tell the NERD tree whether to highlight the + current cursor line. + +|NERDTreeHijackNetrw| Tell the NERD tree whether to replace the netrw + autocommands for exploring local directories. + +|NERDTreeIgnore| Tells the NERD tree which files to ignore. + +|NERDTreeRespectWildIgnore| Tells the NERD tree to respect `'wildignore'`. + +|NERDTreeBookmarksFile| Where the bookmarks are stored. + +|NERDTreeBookmarksSort| Control how the Bookmark table is sorted. + +|NERDTreeMarkBookmarks| Render bookmarked nodes with markers. + +|NERDTreeMouseMode| Manage the interpretation of mouse clicks. + +|NERDTreeQuitOnOpen| Closes the tree window after opening a file. + +|NERDTreeShowBookmarks| Tells the NERD tree whether to display the + bookmarks table on startup. + +|NERDTreeShowFiles| Tells the NERD tree whether to display files in + the tree on startup. + +|NERDTreeShowHidden| Tells the NERD tree whether to display hidden + files on startup. + +|NERDTreeShowLineNumbers| Tells the NERD tree whether to display line + numbers in the tree window. + +|NERDTreeSortOrder| Tell the NERD tree how to sort the nodes in the + tree. + +|NERDTreeStatusline| Set a statusline for NERD tree windows. + +|NERDTreeWinPos| Tells the script where to put the NERD tree + window. + +|NERDTreeWinSize| Sets the window size when the NERD tree is + opened. + +|NERDTreeWinSizeMax| Sets the maximum window size when the NERD tree + is zoomed. + +|NERDTreeMinimalUI| Disables display of the 'Bookmarks' label and + 'Press ? for help' text. + +|NERDTreeCascadeSingleChildDir| + Collapses on the same line directories that have + only one child directory. + +|NERDTreeCascadeOpenSingleChildDir| + Cascade open while selected directory has only + one child that also is a directory. + +|NERDTreeAutoDeleteBuffer| Tells the NERD tree to automatically remove a + buffer when a file is being deleted or renamed + via a context menu command. + +|NERDTreeCreatePrefix| Specify a prefix to be used when creating the + NERDTree window. + +|NERDTreeRemoveFileCmd| Specify a custom shell command to be used when + deleting files. Note that it should include one + space character at the end of the command and it + applies only to files. + +|NERDTreeRemoveDirCmd| Specify a custom shell command to be used when + deleting directories. Note that it should + include one space character at the end of the + command and it applies only to directories. + +|NERDTreeNodeDelimiter| A single character that is used to separate the + file or directory name from the rest of the + characters on the line of text. + +------------------------------------------------------------------------------ +3.2. Customisation details *NERDTreeSettingsDetails* + +To enable any of the below settings you should put an appropriate > + let = + + let loaded_nerd_tree=1 +< + +------------------------------------------------------------------------------ + *NERDTreeAutoCenter* +Values: 0 or 1. +Default: 1 + +If set to 1, the NERD tree window will center around the cursor if it moves to +within |NERDTreeAutoCenterThreshold| lines of the top/bottom of the window. + +This is ONLY done in response to tree navigation mappings, +i.e. |NERDTree-J| |NERDTree-K| |NERDTree-C-J| |NERDTree-C-K| |NERDTree-p| +|NERDTree-P| + +The centering is done with a |zz| operation. + +------------------------------------------------------------------------------ + *NERDTreeAutoCenterThreshold* +Values: Any natural number. +Default: 3 + +This setting controls the "sensitivity" of the NERD tree auto centering. See +|NERDTreeAutoCenter| for details. + +------------------------------------------------------------------------------ + *NERDTreeCaseSensitiveSort* +Values: 0 or 1. +Default: 0. + +By default the NERD tree does not sort nodes case sensitively, i.e. nodes +could appear like this: > + bar.c + Baz.c + blarg.c + boner.c + Foo.c +< +But, if you set this setting to 1 then the case of the nodes will be taken +into account. The above nodes would then be sorted like this: > + Baz.c + Foo.c + bar.c + blarg.c + boner.c +< +------------------------------------------------------------------------------ + *NERDTreeNaturalSort* +Values: 0 or 1. +Default: 0. + +By default the NERD tree does not sort nodes in natural sort order, i.e. nodes +could appear like this: > + z1.txt + z10.txt + z100.txt + z11.txt + z110.txt + z2.txt + z20.txt + z3.txt +< +But if you set this setting to 1 then the natural sort order will be used. The +above nodes would then be sorted like this: > + z1.txt + z2.txt + z3.txt + z10.txt + z11.txt + z20.txt + z100.txt + z110.txt +< +------------------------------------------------------------------------------ + *NERDTreeChDirMode* + +Values: 0, 1 or 2. +Default: 0. + +Use this setting to tell the script when (if at all) to change the current +working directory (CWD) for vim. + +If it is set to 0 then the CWD is never changed by the NERD tree. + +If set to 1 then the CWD is changed when the NERD tree is first loaded to the +directory it is initialized in. For example, if you start the NERD tree with > + :NERDTree /home/marty/foobar +< +then the CWD will be changed to /home/marty/foobar and will not be changed +again unless you init another NERD tree with a similar command. + +If the setting is set to 2 then it behaves the same as if set to 1 except that +the CWD is changed whenever the tree root is changed. For example, if the CWD +is /home/marty/foobar and you make the node for /home/marty/foobar/baz the new +root then the CWD will become /home/marty/foobar/baz. + +------------------------------------------------------------------------------ + *NERDTreeHighlightCursorline* +Values: 0 or 1. +Default: 1. + +If set to 1, the current cursor line in the NERD tree buffer will be +highlighted. This is done using the `'cursorline'` Vim option. + +------------------------------------------------------------------------------ + *NERDTreeHijackNetrw* +Values: 0 or 1. +Default: 1. + +If set to 1, doing a > + :edit +< +will open up a window level NERD tree instead of a netrw in the target window. + +Window level trees behaves slightly different from a regular trees in the +following respects: + 1. 'o' will open the selected file in the same window as the tree, + replacing it. + 2. you can have one tree per window - instead of per tab. + +------------------------------------------------------------------------------ + *NERDTreeIgnore* +Values: a list of regular expressions. +Default: ['\~$']. + +This setting is used to specify which files the NERD tree should ignore. It +must be a list of regular expressions. When the NERD tree is rendered, any +files/dirs that match any of the regex's in NERDTreeIgnore won't be +displayed. + +For example if you put the following line in your vimrc: > + let NERDTreeIgnore=['\.vim$', '\~$'] +< +then all files ending in .vim or ~ will be ignored. + +There are 2 magic flags that can be appended to the end of each regular +expression to specify that the regex should match only files or only dirs. +These flags are "[[dir]]" and "[[file]]". Example: > + let NERDTreeIgnore=['\.d$[[dir]]', '\.o$[[file]]'] +< +This will cause all dirs ending in ".d" to be ignored and all files ending in +".o" to be ignored. + +Note: to tell the NERD tree not to ignore any files you must use the following +line: > + let NERDTreeIgnore=[] +< + +The file filters can be turned on and off dynamically with the |NERDTree-f| +mapping. + +------------------------------------------------------------------------------ + *NERDTreeRespectWildIgnore* +Values: 0 or 1. +Default: 0. + +If set to 1, the `'wildignore'` setting is respected. + +------------------------------------------------------------------------------ + *NERDTreeBookmarksFile* +Values: a path +Default: $HOME/.NERDTreeBookmarks + +This is where bookmarks are saved. See |NERDTreeBookmarkCommands|. + +------------------------------------------------------------------------------ + *NERDTreeBookmarksSort* +Values: 0, 1, or 2 +Default: 1 + +This setting controls the method by which the list of user bookmarks is +sorted. When sorted, bookmarks will render in alphabetical order by name. + +If set to 0, the bookmarks list is not sorted. +If set to 1, the bookmarks list is sorted in a case-insensitive manner. +If set to 2, the bookmarks list is sorted in a case-sensitive manner. + +------------------------------------------------------------------------------ + *NERDTreeMarkBookmarks* +Values: 0 or 1 +Default: 1 + +If set to 1, Bookmarks will be specially marked whenever the NERDTree is +rendered. Users of the |NERDTreeMinimalUI| setting may prefer to disable +this setting for even less visual clutter. + +------------------------------------------------------------------------------ + *NERDTreeMouseMode* +Values: 1, 2 or 3. +Default: 1. + +If set to 1 then a double click on a node is required to open it. +If set to 2 then a single click will open directory nodes, while a double +click will still be required for file nodes. +If set to 3 then a single click will open any node. + +Note: a double click anywhere on a line that a tree node is on will +activate it, but all single-click activations must be done on name of the node +itself. For example, if you have the following node: > + | | |-application.rb +< +then (to single click activate it) you must click somewhere in +'application.rb'. + +------------------------------------------------------------------------------ + *NERDTreeQuitOnOpen* + +Values: 0 or 1. +Default: 0 + +If set to 1, the NERD tree window will close after opening a file with the +|NERDTree-o|, |NERDTree-i|, |NERDTree-t| and |NERDTree-T| mappings. + +------------------------------------------------------------------------------ + *NERDTreeShowBookmarks* +Values: 0 or 1. +Default: 0. + +If this setting is set to 1 then the bookmarks table will be displayed. + +This setting can be toggled dynamically, per tree, with the |NERDTree-B| +mapping. + +------------------------------------------------------------------------------ + *NERDTreeShowFiles* +Values: 0 or 1. +Default: 1. + +If this setting is set to 1 then files are displayed in the NERD tree. If it +is set to 0 then only directories are displayed. + +This setting can be toggled dynamically, per tree, with the |NERDTree-F| +mapping and is useful for drastically shrinking the tree when you are +navigating to a different part of the tree. + +------------------------------------------------------------------------------ + *NERDTreeShowHidden* +Values: 0 or 1. +Default: 0. + +This setting tells vim whether to display hidden files by default. This +setting can be dynamically toggled, per tree, with the |NERDTree-I| mapping. +Use one of the follow lines for this setting: > + let NERDTreeShowHidden=0 + let NERDTreeShowHidden=1 +< + +------------------------------------------------------------------------------ + *NERDTreeShowLineNumbers* +Values: 0 or 1. +Default: 0. + +This setting tells vim whether to display line numbers for the NERD tree +window. Use one of the follow lines for this setting: > + let NERDTreeShowLineNumbers=0 + let NERDTreeShowLineNumbers=1 +< + +------------------------------------------------------------------------------ + *NERDTreeSortOrder* +Values: a list of regular expressions. +Default: ['\/$', '*', '\.swp$', '\.bak$', '\~$'] + +This setting is a list of regular expressions which are used to specify the +order of nodes under their parent. + +For example, if the setting is: > + ['\.vim$', '\.c$', '\.h$', '*', 'foobar'] +< +then all .vim files will be placed at the top, followed by all .c files then +all .h files. All files containing the string 'foobar' will be placed at the +end. The star is a special flag: it tells the script that every node that +doesn't match any of the other regexps should be placed here. + +If no star is present in NERDTreeSortOrder then one is automatically +appended to the array. + +The regex '\/$' should be used to match directory nodes. + +A special flag can be used to sort by the modification timestamps of files and +directories. It is either '[[timestamp]]' for ascending, or '[[-timestamp]]' +for descending. If placed at the beginning of the list, files and directories +are sorted by timestamp, and then by the remaining items in the sort order +list. If this flag is in any other position of the list, timestamp sorting is +done secondarily. See examples 4, 5, and 6 below. + +After this sorting is done, the files in each group are sorted alphabetically. + +Examples: > + (1) ['*', '\/$'] + (2) [] + (3) ['\/$', '\.rb$', '\.php$', '*', '\.swp$', '\.bak$', '\~$'] + (4) ['[[timestamp]]'] + (5) ['\/$', '*', '[[-timestamp]]'] + (6) ['\.md$', '\.c$', '[[-timestamp]]', '*'] +< +1. Directories will appear last, everything else will appear above. +2. Everything will simply appear in alphabetical order. +3. Dirs will appear first, then ruby and php. Swap files, bak files and vim + backup files will appear last with everything else preceding them. +4. All files and directories are sorted by timestamp, oldest first. If any + files have identical timestamps, they are sorted alphabetically. +5. Directories are first, newest to oldest, then everything else, newest to + oldest. +6. Markdown files first, followed by C source files, then everything else. + Each group is shown newest to oldest. + +------------------------------------------------------------------------------ + *NERDTreeStatusline* +Values: Any valid `'statusline'` setting. +Default: %{exists('b:NERDTree')?b:NERDTree.root.path.str():''} + +Defines the value for the `'statusline'` setting in NERDTree windows. + +Note: The setting is actually applied using |:let-&|, not |:set|, so +escaping spaces is not necessary. + +Setting this to -1 will deactivate it so that your global `'statusline'` +setting is used. + +------------------------------------------------------------------------------ + *NERDTreeWinPos* +Values: "left" or "right" +Default: "left". + +This setting is used to determine where NERD tree window is placed on the +screen. + +This setting makes it possible to use two different explorer plugins +simultaneously. For example, you could have the taglist plugin on the left of +the window and the NERD tree on the right. + +------------------------------------------------------------------------------ + *NERDTreeWinSize* +Values: a positive integer. +Default: 31. + +This setting is used to change the size of the NERD tree when it is loaded. + +------------------------------------------------------------------------------ + *NERDTreeMinimalUI* +Values: 0 or 1 +Default: 0 + +This setting disables the 'Bookmarks' label 'Press ? for help' text. Use one +of the following lines for this setting: > + let NERDTreeMinimalUI=0 + let NERDTreeMinimalUI=1 +< + +------------------------------------------------------------------------------ + *NERDTreeCascadeSingleChildDir* +Values: 0 or 1 +Default: 1. + +When displaying dir nodes, this setting tells NERDTree to collapse dirs that +have only one child. Use one of the following lines for this setting: > + let NERDTreeCascadeSingleChildDir=0 + let NERDTreeCascadeSingleChildDir=1 +< + +------------------------------------------------------------------------------ + *NERDTreeCascadeOpenSingleChildDir* +Values: 0 or 1 +Default: 1. + +When opening dir nodes, this setting tells NERDTree to recursively open dirs +that have only one child which is also a dir. NERDTree will stop when it finds +a dir that contains anything but another single dir. This setting also causes +the |NERDTree-x| mapping to close dirs in the same manner. This setting may be +useful for Java projects. Use one of the following lines for this setting: > + let NERDTreeCascadeOpenSingleChildDir=0 + let NERDTreeCascadeOpenSingleChildDir=1 +< + +------------------------------------------------------------------------------ + *NERDTreeAutoDeleteBuffer* +Values: 0 or 1 +Default: 0. + +When using a context menu to delete or rename a file you may also want to +delete the buffer which is no more valid. If the setting is not set you will +see a confirmation if you really want to delete an old buffer. If you always +press 'y' then it's worth it to set this setting to 1. Use one of the +following lines for this setting: > + let NERDTreeAutoDeleteBuffer=0 + let NERDTreeAutoDeleteBuffer=1 +< +------------------------------------------------------------------------------ + *NERDTreeCreatePrefix* +Values: Any valid command prefix. +Default: "silent". + +Internally, NERDTree uses the |:edit| command to create a buffer in which to +display its tree view. You can augment this behavior by specifying a prefix +string such as "keepalt" or similar. For example, to have NERDTree create its +tree window using `silent keepalt keepjumps edit`: > + let NERDTreeCreatePrefix='silent keepalt keepjumps' +< +------------------------------------------------------------------------------ + *NERDTreeNodeDelimiter* +Values: Any single character. +Default: "\x07" - the non-printable character BELL. + +This character is used to separate the file or directory name from the rest of +the characters in the line of text. It allows filenames to contain special +characters that are otherwise used in the NERDTree, such as square brackets, +braces, trailing asterisk, and leading space. For more details, see the +resoponsible pull request: https://github.com/scrooloose/nerdtree/pull/868. + +The default should work in nearly every situation, but this setting exists for +those very rare cases where it doesn't. "\x07" was chosen because it's +non-printable, and very unlikely to be used purposefully in a filename or as a +flag by other NERDTree plugins. If you need to change the delimiter, be sure +to choose a character that won't appear in your filenames or any of the flags +set by your installed NERDTree plugins. The suggestions below are but a few of +the many possibilities. Remember to use double quotes when specifying by hex +or Unicode. > + let NERDTreeNodeDelimiter="\u00a0" "non-breaking space + let NERDTreeNodeDelimiter="\u00b7" "middle dot +< +The delimiter character is hidden by setting 'conceallevel' to 3. If you use +autocommands, make sure none of them change that setting in the NERDTree_* +windows. + +If your vim was not compiled with the +conceal feature, NERDTree will use the +Ignore highlight group, which doesn't hide the BELL character. In this +situation, you will need to override the delimiter character as described +above. + +============================================================================== +4. The NERD tree API *NERDTreeAPI* + +The NERD tree script allows you to add custom key mappings and menu items via +a set of API calls. Any scripts that use this API should be placed in +~/.vim/nerdtree_plugin/ (*nix) or ~/vimfiles/nerdtree_plugin (windows). + +The script exposes some prototype objects that can be used to manipulate the +tree and/or get information from it: > + g:NERDTreePath + g:NERDTreeDirNode + g:NERDTreeFileNode + g:NERDTreeBookmark +< +See the code/comments in NERD_tree.vim to find how to use these objects. The +following code conventions are used: + * class members start with a capital letter + * instance members start with a lower case letter + * private members start with an underscore + +See this blog post for more details: + http://got-ravings.blogspot.com/2008/09/vim-pr0n-prototype-based-objects.html + +------------------------------------------------------------------------------ +4.1. Key map API *NERDTreeKeymapAPI* + +NERDTreeAddKeyMap({options}) *NERDTreeAddKeyMap()* + Adds a new keymapping for all NERD tree buffers. + {options} must be a dictionary, and must contain the following keys: + "key" - the trigger key for the new mapping + "callback" - the function the new mapping will be bound to + "quickhelpText" - the text that will appear in the quickhelp (see + |NERDTree-?|) + "override" - if 1 then this new mapping will override whatever previous + mapping was defined for the key/scope combo. Useful for overriding the + default mappings. + + Additionally, a "scope" argument may be supplied. This constrains the + mapping so that it is only activated if the cursor is on a certain object. + That object is then passed into the handling method. Possible values are: + + "FileNode" .... a file node + "DirNode" ..... a directory node + "Node" ........ a file node OR a directory node + "Bookmark" .... a bookmark + "all" ......... global scope; handler receives no arguments (default) + + Example: > + call NERDTreeAddKeyMap({ + \ 'key': 'foo', + \ 'callback': 'NERDTreeCDHandler', + \ 'quickhelpText': 'echo full path of current node', + \ 'scope': 'DirNode' }) + + function! NERDTreeCDHandler(dirnode) + call a:dirnode.changeToDir() + endfunction +< + This code should sit in a file like ~/.vim/nerdtree_plugin/mymapping.vim. + It adds a (redundant) mapping on 'foo' which changes vim's CWD to that of + the current dir node. Note this mapping will only fire when the cursor is + on a directory node. + +------------------------------------------------------------------------------ +4.2. Menu API *NERDTreeMenuAPI* + +NERDTreeAddSubmenu({options}) *NERDTreeAddSubmenu()* + Creates and returns a new submenu. + + {options} must be a dictionary and must contain the following keys: + "text" - the text of the submenu that the user will see + "shortcut" - a shortcut key for the submenu (need not be unique) + + The following keys are optional: + "isActiveCallback" - a function that will be called to determine whether + this submenu item will be displayed or not. The callback function must + return 0 or 1. + "parent" - the parent submenu of the new submenu (returned from a previous + invocation of NERDTreeAddSubmenu()). If this key is left out then the new + submenu will sit under the top level menu. + + See below for an example. + +NERDTreeAddMenuItem({options}) *NERDTreeAddMenuItem()* + Adds a new menu item to the NERD tree menu (see |NERDTreeMenu|). + + {options} must be a dictionary and must contain the + following keys: + "text" - the text of the menu item which the user will see + "shortcut" - a shortcut key for the menu item (need not be unique) + "callback" - the function that will be called when the user activates the + menu item. + + The following keys are optional: + "isActiveCallback" - a function that will be called to determine whether + this menu item will be displayed or not. The callback function must return + 0 or 1. + "parent" - if the menu item belongs under a submenu then this key must be + specified. This value for this key will be the object that + was returned when the submenu was created with |NERDTreeAddSubmenu()|. + + See below for an example. + +NERDTreeAddMenuSeparator([{options}]) *NERDTreeAddMenuSeparator()* + Adds a menu separator (a row of dashes). + + {options} is an optional dictionary that may contain the following keys: + "isActiveCallback" - see description in |NERDTreeAddMenuItem()|. + +Below is an example of the menu API in action. > + call NERDTreeAddMenuSeparator() + + call NERDTreeAddMenuItem({ + \ 'text': 'a (t)op level menu item', + \ 'shortcut': 't', + \ 'callback': 'SomeFunction' }) + + let submenu = NERDTreeAddSubmenu({ + \ 'text': 'a (s)ub menu', + \ 'shortcut': 's' }) + + call NERDTreeAddMenuItem({ + \ 'text': '(n)ested item 1', + \ 'shortcut': 'n', + \ 'callback': 'SomeFunction', + \ 'parent': submenu }) + + call NERDTreeAddMenuItem({ + \ 'text': '(n)ested item 2', + \ 'shortcut': 'n', + \ 'callback': 'SomeFunction', + \ 'parent': submenu }) +< +This will create the following menu: > + -------------------- + a (t)op level menu item + a (s)ub menu +< +Where selecting "a (s)ub menu" will lead to a second menu: > + (n)ested item 1 + (n)ested item 2 +< +When any of the 3 concrete menu items are selected the function "SomeFunction" +will be called. + +------------------------------------------------------------------------------ +4.3 NERDTreeAddPathFilter(callback) *NERDTreeAddPathFilter()* + +Path filters are essentially a more powerful version of |NERDTreeIgnore|. +If the simple regex matching in |NERDTreeIgnore| is not enough then use +|NERDTreeAddPathFilter()| to add a callback function that paths will be +checked against when the decision to ignore them is made. Example > + + call NERDTreeAddPathFilter('MyFilter') + + function! MyFilter(params) + "params is a dict containing keys: 'nerdtree' and 'path' which are + "g:NERDTree and g:NERDTreePath objects + + "return 1 to ignore params['path'] or 0 otherwise + endfunction +< +------------------------------------------------------------------------------ +4.4 Path Listener API *NERDTreePathListenerAPI* + +Use this API if you want to run a callback for events on Path objects. E.G > + + call g:NERDTreePathNotifier.AddListener("init", "MyListener") + + ".... + + function! MyListener(event) + "This function will be called whenever a Path object is created. + + "a:event is an object that contains a bunch of relevant info - + "including the affected path. See lib/nerdtree/event.vim for details. + endfunction +< +Current events supported: + init ~ + refresh ~ + refreshFlags ~ + +------------------------------------------------------------------------------ +NERDTreeRender() *NERDTreeRender()* + Re-renders the NERD tree buffer. Useful if you change the state of the + tree and you want to it to be reflected in the UI. + +============================================================================== +5. About *NERDTreeAbout* + +The author of the NERD tree is a terrible terrible monster called Martyzilla +who gobbles up small children with milk and sugar for breakfast. + +He can be reached at martin.grenfell at gmail dot com. He would love to hear +from you, so feel free to send him suggestions and/or comments about this +plugin. Don't be shy --- the worst he can do is slaughter you and stuff you +in the fridge for later ;) + +Martyzilla recruited two other unwitting accomplices to become his minions in +his quest to conquer the Vim plugin world. While he may still love to receive +your emails, the best way to send suggestions, bug reports, and questions is +to submit an issue at http://github.com/scrooloose/nerdtree/issues. + +The latest stable and development versions are on Github. + Stable: http://github.com/scrooloose/nerdtree (master branch) + Development: http://github.com/scrooloose/nerdtree/branches + +Title Credit: + * http://ascii.co.uk/art/tree + + * Patrick Gillespie's Text ASCII Art Generator + http://patorjk.com/software/taag + http://patorjk.com/software/taag/#p=display&f=Rozzo&t=the%20NERD%20Tree + +============================================================================== +6. License *NERDTreeLicense* + +The NERD tree is released under the wtfpl. +See http://sam.zoy.org/wtfpl/COPYING. + +------------------------------------------------------------------------------ + vim:tw=78:ts=8:ft=help:noet:nospell diff --git a/bundle/nerdtree/lib/nerdtree/bookmark.vim b/bundle/nerdtree/lib/nerdtree/bookmark.vim new file mode 100644 index 0000000..2e0aab0 --- /dev/null +++ b/bundle/nerdtree/lib/nerdtree/bookmark.vim @@ -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 + 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: diff --git a/bundle/nerdtree/lib/nerdtree/creator.vim b/bundle/nerdtree/lib/nerdtree/creator.vim new file mode 100644 index 0000000..1afd056 --- /dev/null +++ b/bundle/nerdtree/lib/nerdtree/creator.vim @@ -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 do the same as the activate node mapping + nnoremap :call nerdtree#ui_glue#invokeKeyMap(g:NERDTreeMapActivateNode) + + call g:NERDTreeKeyMap.BindAll() + + command! -buffer -nargs=? Bookmark :call nerdtree#ui_glue#bookmarkNode('') + command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=1 RevealBookmark :call nerdtree#ui_glue#revealBookmark('') + command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=1 OpenBookmark call nerdtree#ui_glue#openBookmark('') + command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=* ClearBookmarks call nerdtree#ui_glue#clearBookmarks('') + command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=+ BookmarkToRoot call g:NERDTreeBookmark.ToRoot('', b:NERDTree) + command! -buffer -nargs=0 ClearAllBookmarks call g:NERDTreeBookmark.ClearAll() call b:NERDTree.render() + command! -buffer -nargs=0 ReadBookmarks call g:NERDTreeBookmark.CacheBookmarks(0) 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() {{{1 +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 + + 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: diff --git a/bundle/nerdtree/lib/nerdtree/event.vim b/bundle/nerdtree/lib/nerdtree/event.vim new file mode 100644 index 0000000..964e8ff --- /dev/null +++ b/bundle/nerdtree/lib/nerdtree/event.vim @@ -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 diff --git a/bundle/nerdtree/lib/nerdtree/flag_set.vim b/bundle/nerdtree/lib/nerdtree/flag_set.vim new file mode 100644 index 0000000..bc6e887 --- /dev/null +++ b/bundle/nerdtree/lib/nerdtree/flag_set.vim @@ -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: diff --git a/bundle/nerdtree/lib/nerdtree/key_map.vim b/bundle/nerdtree/lib/nerdtree/key_map.vim new file mode 100644 index 0000000..584da1f --- /dev/null +++ b/bundle/nerdtree/lib/nerdtree/key_map.vim @@ -0,0 +1,164 @@ +"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 ' notation, we + " must replace each of the '<' characters with '' 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, '\1', 'g') + else + let keymapInvokeString = self.key + endif + let keymapInvokeString = escape(keymapInvokeString, '\') + + let premap = self.key == "" ? " " : " " + + exec 'nnoremap '. self.key . premap . ':call nerdtree#ui_glue#invokeKeyMap("'. keymapInvokeString .'")' +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 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: diff --git a/bundle/nerdtree/lib/nerdtree/menu_controller.vim b/bundle/nerdtree/lib/nerdtree/menu_controller.vim new file mode 100644 index 0000000..84bdb26 --- /dev/null +++ b/bundle/nerdtree/lib/nerdtree/menu_controller.vim @@ -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 " . g:NERDTreeMenuDown . "/" . g:NERDTreeMenuUp . "/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 == g:NERDTreeMenuDown + call self._cursorDown() + elseif a:key == g:NERDTreeMenuUp + 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: diff --git a/bundle/nerdtree/lib/nerdtree/menu_item.vim b/bundle/nerdtree/lib/nerdtree/menu_item.vim new file mode 100644 index 0000000..92c1bbb --- /dev/null +++ b/bundle/nerdtree/lib/nerdtree/menu_item.vim @@ -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: diff --git a/bundle/nerdtree/lib/nerdtree/nerdtree.vim b/bundle/nerdtree/lib/nerdtree/nerdtree.vim new file mode 100644 index 0000000..fcabcb9 --- /dev/null +++ b/bundle/nerdtree/lib/nerdtree/nerdtree.vim @@ -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: diff --git a/bundle/nerdtree/lib/nerdtree/notifier.vim b/bundle/nerdtree/lib/nerdtree/notifier.vim new file mode 100644 index 0000000..d24fc8f --- /dev/null +++ b/bundle/nerdtree/lib/nerdtree/notifier.vim @@ -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) diff --git a/bundle/nerdtree/lib/nerdtree/opener.vim b/bundle/nerdtree/lib/nerdtree/opener.vim new file mode 100644 index 0000000..ef357ef --- /dev/null +++ b/bundle/nerdtree/lib/nerdtree/opener.vim @@ -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: diff --git a/bundle/nerdtree/lib/nerdtree/path.vim b/bundle/nerdtree/lib/nerdtree/path.vim new file mode 100644 index 0000000..b92eb6f --- /dev/null +++ b/bundle/nerdtree/lib/nerdtree/path.vim @@ -0,0 +1,875 @@ +" ============================================================================ +" 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() + + if l:result[-1:] == s:Path.Slash() + let l:result = l:result . a:pathStr + else + let l:result = l:result . s:Path.Slash() . a:pathStr + endif + 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 $" + 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 = ' 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 : substitute(l:next,'^.','','') + 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.getDirChildren() {{{1 +" Return a list of all child nodes from "self.children" that are of type +" TreeDirNode. This function supports http://github.com/scrooloose/nerdtree-project-plugin.git. +function! s:TreeDirNode.getDirChildren() + return filter(copy(self.children), 'v:val.path.isDirectory == 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 that is also a dir +" false if this dir is bookmarked or symlinked. Why? Two reasons: +" 1. If cascaded, we don't know which dir is bookmarked or is a symlink. +" 2. If the parent is a symlink or is bookmarked, you end up with unparsable +" text, and NERDTree cannot get the path of any child node. +function! s:TreeDirNode.isCascadable() + if g:NERDTreeCascadeSingleChildDir == 0 + return 0 + endif + + if self.path.isSymLink + return 0 + endif + + for i in g:NERDTreeBookmark.Bookmarks() + if i.path.equals(self.path) + return 0 + endif + endfor + + 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: diff --git a/bundle/nerdtree/lib/nerdtree/tree_file_node.vim b/bundle/nerdtree/lib/nerdtree/tree_file_node.vim new file mode 100644 index 0000000..d4c060f --- /dev/null +++ b/bundle/nerdtree/lib/nerdtree/tree_file_node.vim @@ -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: diff --git a/bundle/nerdtree/lib/nerdtree/ui.vim b/bundle/nerdtree/lib/nerdtree/ui.vim new file mode 100644 index 0000000..5e3fcf1 --- /dev/null +++ b/bundle/nerdtree/lib/nerdtree/ui.vim @@ -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 .= "\" ,\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 []\n" + let help .= "\" :BookmarkToRoot \n" + let help .= "\" :RevealBookmark \n" + let help .= "\" :OpenBookmark \n" + let help .= "\" :ClearBookmarks []\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 ". get(g:, 'NERDTreeWinSizeMax', '') + 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: diff --git a/bundle/nerdtree/nerdtree_plugin/exec_menuitem.vim b/bundle/nerdtree/nerdtree_plugin/exec_menuitem.vim new file mode 100644 index 0000000..c53650a --- /dev/null +++ b/bundle/nerdtree/nerdtree_plugin/exec_menuitem.vim @@ -0,0 +1,40 @@ +" ============================================================================ +" File: exec_menuitem.vim +" Description: plugin for NERD Tree that provides an execute file menu item +" Maintainer: Martin Grenfell +" 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 diff --git a/bundle/nerdtree/nerdtree_plugin/fs_menu.vim b/bundle/nerdtree/nerdtree_plugin/fs_menu.vim new file mode 100644 index 0000000..e0911e4 --- /dev/null +++ b/bundle/nerdtree/nerdtree_plugin/fs_menu.vim @@ -0,0 +1,377 @@ +" ============================================================================ +" File: fs_menu.vim +" Description: plugin for the NERD Tree that provides a file system menu +" Maintainer: Martin Grenfell +" 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 + try + exec "confirm bwipeout " . a:bufNum + catch + " This happens when answering Cancel if confirmation is needed. Do nothing. + endtry +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 l:shellslash = &shellslash + let &shellslash = 0 + 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 + let &shellslash = l:shellslash +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 l:shellslash = &shellslash + let &shellslash = 0 + 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 + let &shellslash = l:shellslash + 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: + diff --git a/bundle/nerdtree/nerdtree_plugin/vcs.vim b/bundle/nerdtree/nerdtree_plugin/vcs.vim new file mode 100644 index 0000000..c30579a --- /dev/null +++ b/bundle/nerdtree/nerdtree_plugin/vcs.vim @@ -0,0 +1,38 @@ +" ============================================================================ +" File: vcs.vim +" Description: NERDTree plugin that provides a command to open on the root of +" a version control system repository. +" Maintainer: Phil Runninger +" 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. +" +" ============================================================================ +command! -n=? -complete=dir -bar NERDTreeVCS :call CreateTabTreeVCS('') + +" FUNCTION: s:CreateTabTreeVCS(a:name) {{{1 +function! s:CreateTabTreeVCS(name) + let l:path = g:NERDTreeCreator._pathForString(a:name) + let l:path = s:FindParentVCSRoot(l:path) + call g:NERDTreeCreator.createTabTree(empty(l:path) ? "" : l:path._str()) +endfunction + +" FUNCTION: s:FindParentVCSRoot(a:path) {{{1 +" Finds the root version control system folder of the given path. If a:path is +" not part of a repository, return the original path. +function! s:FindParentVCSRoot(path) + let l:path = a:path + while !empty(l:path) && + \ l:path._str() !~ '^\(\a:\\\|\/\)$' && + \ !isdirectory(l:path._str() . '/.git') && + \ !isdirectory(l:path._str() . '/.svn') && + \ !isdirectory(l:path._str() . '/.hg') && + \ !isdirectory(l:path._str() . '/.bzr') && + \ !isdirectory(l:path._str() . '/_darcs') + let l:path = l:path.getParent() + endwhile + return (empty(l:path) || l:path._str() =~ '^\(\a:\\\|\/\)$') ? a:path : l:path +endfunction + diff --git a/bundle/nerdtree/plugin/NERD_tree.vim b/bundle/nerdtree/plugin/NERD_tree.vim new file mode 100644 index 0000000..c3de3f2 --- /dev/null +++ b/bundle/nerdtree/plugin/NERD_tree.vim @@ -0,0 +1,244 @@ +" ============================================================================ +" File: NERD_tree.vim +" Maintainer: Martin Grenfell +" 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 7: bell non-printing character used to delimit items in the tree's nodes. +call s:initVariable("g:NERDTreeNodeDelimiter", "\x07") + +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", "") +call s:initVariable("g:NERDTreeMapJumpParent", "p") +call s:initVariable("g:NERDTreeMapJumpPrevSibling", "") +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") +call s:initVariable("g:NERDTreeMenuDown", "j") +call s:initVariable("g:NERDTreeMenuUp", "k") + +"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("")) + 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: diff --git a/bundle/nerdtree/screenshot.png b/bundle/nerdtree/screenshot.png new file mode 100644 index 0000000..c410c5d Binary files /dev/null and b/bundle/nerdtree/screenshot.png differ diff --git a/bundle/nerdtree/syntax/nerdtree.vim b/bundle/nerdtree/syntax/nerdtree.vim new file mode 100644 index 0000000..99773bf --- /dev/null +++ b/bundle/nerdtree/syntax/nerdtree.vim @@ -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 #\%d' . char2nr(g:NERDTreeNodeDelimiter) . '# conceal containedin=ALL' + setlocal conceallevel=3 concealcursor=nvic +else + exec 'syn match NERDTreeNodeDelimiters #\%d' . char2nr(g:NERDTreeNodeDelimiter) . '# containedin=ALL' + hi! link NERDTreeNodeDelimiters Ignore +endif + +syn match NERDTreeCWD #^[# +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