nerdtree

A tree explorer plugin for vim.
Index Commits Files Refs
commit fb030bcb1c4da84308516d1094336530d28748ce
parent 6ccf83df24ac3044117e10b99be43d00923dbeea
Author: Phil Runninger <PhilRunninger@users.noreply.github.com>
Date:   Thu, 12 Nov 2015 16:11:56 -0500

Merge pull request #1 from scrooloose/master

Merge official code into my fork
Diffstat:
MREADME.markdown | 60+++++++++++++++++++++++++++++++++++-------------------------
Mautoload/nerdtree.vim | 282++++---------------------------------------------------------------------------
Mautoload/nerdtree/ui_glue.vim | 24++++++++++++------------
Mdoc/NERD_tree.txt | 44+++++++++++++++++++++++++++++++++++++++++++-
Mlib/nerdtree/bookmark.vim | 5+++--
Mlib/nerdtree/creator.vim | 23++++++++++++++++-------
Mlib/nerdtree/nerdtree.vim | 100++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Mlib/nerdtree/opener.vim | 50+++++++++++++++++++++++++++++++++-----------------
Mlib/nerdtree/path.vim | 69+++++++++++++++++++++++++++++++++++++++++++++------------------------
Mlib/nerdtree/tree_dir_node.vim | 16++++++++++++----
Mlib/nerdtree/tree_file_node.vim | 4++--
Mlib/nerdtree/ui.vim | 236++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
Mnerdtree_plugin/fs_menu.vim | 21++++++++++++++++++---
Mplugin/NERD_tree.vim | 13++++++++++---
Msyntax/nerdtree.vim | 11++++++-----
15 files changed, 550 insertions(+), 408 deletions(-)
diff --git a/README.markdown b/README.markdown
@@ -55,7 +55,7 @@ The following features and functionality are provided by the NERD tree:
 Installation
 ------------
 
-[pathogen.vim](https://github.com/tpope/vim-pathogen) is the recommended way to install nerdtree.
+####[pathogen.vim](https://github.com/tpope/vim-pathogen)
 
     cd ~/.vim/bundle
     git clone https://github.com/scrooloose/nerdtree.git
@@ -63,49 +63,59 @@ Installation
 Then reload vim, run `:Helptags`, and check out `:help NERD_tree.txt`.
 
 
+####[apt-vim](https://github.com/egalpin/apt-vim)
+
+    apt-vim install -y https://github.com/scrooloose/nerdtree.git
+
+
+
 Faq
 ---
 
-__Q. Can I have the nerdtree on every tab automatically?__
+> Is there any support for `git` flags?
 
-A. 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
+Yes, install [nerdtree-git-plugin](https://github.com/Xuyuanp/nerdtree-git-plugin).
 
-   If you are interested in this behaviour then consider [vim-nerdtree-tabs](https://github.com/jistr/vim-nerdtree-tabs)
 
-__Q. How can I open a NERDTree automatically when vim starts up?__
+> Can I have the nerdtree on every tab automatically?
 
-A. Stick this in your vimrc: `autocmd vimenter * NERDTree`
+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
 
-__Q. How can I open a NERDTree automatically when vim starts up if no files were specified?__
+If you are interested in this behaviour then consider [vim-nerdtree-tabs](https://github.com/jistr/vim-nerdtree-tabs)
 
-A. Stick this in your vimrc
+> 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
 
-__Q. How can I map a specific key or shortcut to open NERDTree?__
+> 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):
 
-A. Stick this in your vimrc to open NERDTree with `Ctrl+n` (you can set whatever key you want): `map <C-n> :NERDTreeToggle<CR>`
+    map <C-n> :NERDTreeToggle<CR>
 
-__Q. How can I close vim if the only window left open is a NERDTree?__
+> How can I close vim if the only window left open is a NERDTree?
 
-A. Stick this in your vimrc:
+Stick this in your vimrc:
 
-   `autocmd bufenter * if (winnr("$") == 1 && exists("b:NERDTreeType") && b:NERDTreeType == "primary") | q | endif`
+    autocmd bufenter * if (winnr("$") == 1 && exists("b:NERDTreeType") && b:NERDTreeType == "primary") | q | endif
 
+> Can I have different highlighting for different file extensions?
 
-Changelog
----------
+See here: https://github.com/scrooloose/nerdtree/issues/433#issuecomment-92590696
 
-4.2.0 (2011-12-28)
+> How can I change default arrows?
 
- * 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!)
+Use these variables in your vimrc. Note that below are default arrow symbols
 
+    let g:NERDTreeDirArrows = 1
+    let g:NERDTreeDirArrowExpandable = '▸'
+    let g:NERDTreeDirArrowCollapsible = '▾'
diff --git a/autoload/nerdtree.vim b/autoload/nerdtree.vim
@@ -34,6 +34,17 @@ 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)
+    if a:n1.path.getSortKey() <# a:n2.path.getSortKey()
+        return -1
+    elseif a:n1.path.getSortKey() ># a:n2.path.getSortKey()
+        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
@@ -95,175 +106,9 @@ function! nerdtree#runningWindows()
     return has("win16") || has("win32") || has("win64")
 endfunction
 
-"FUNCTION: nerdtree#treeMarkupReg(dir) {{{2
-function! nerdtree#treeMarkupReg()
-    if g:NERDTreeDirArrows
-        return '^\([▾▸] \| \+[▾▸] \| \+\)'
-    endif
-
-    return '^[ `|]*[\-+~]'
-endfunction
-
-"FUNCTION: nerdtree#treeUpDirLine(dir) {{{2
-function! nerdtree#treeUpDirLine()
-    return '.. (up a dir)'
-endfunction
-
-"FUNCTION: nerdtree#treeWid(dir) {{{2
-function! nerdtree#treeWid()
-    return 2
-endfunction
-
 " SECTION: View Functions {{{1
 "============================================================
 
-"FUNCTION: nerdtree#closeTree() {{{2
-"Closes the primary NERD tree window for this tab
-function! nerdtree#closeTree()
-    if !nerdtree#isTreeOpen()
-        throw "NERDTree.NoTreeFoundError: no NERDTree is open"
-    endif
-
-    if winnr("$") != 1
-        if winnr() == nerdtree#getTreeWinNum()
-            call nerdtree#exec("wincmd p")
-            let bufnr = bufnr("")
-            call nerdtree#exec("wincmd p")
-        else
-            let bufnr = bufnr("")
-        endif
-
-        call nerdtree#exec(nerdtree#getTreeWinNum() . " wincmd w")
-        close
-        call nerdtree#exec(bufwinnr(bufnr) . " wincmd w")
-    else
-        close
-    endif
-endfunction
-
-"FUNCTION: nerdtree#closeTreeIfOpen() {{{2
-"Closes the NERD tree window if it is open
-function! nerdtree#closeTreeIfOpen()
-   if nerdtree#isTreeOpen()
-      call nerdtree#closeTree()
-   endif
-endfunction
-
-"FUNCTION: nerdtree#closeTreeIfQuitOnOpen() {{{2
-"Closes the NERD tree window if the close on open option is set
-function! nerdtree#closeTreeIfQuitOnOpen()
-    if g:NERDTreeQuitOnOpen && nerdtree#isTreeOpen()
-        call nerdtree#closeTree()
-    endif
-endfunction
-
-"FUNCTION: nerdtree#dumpHelp  {{{2
-"prints out the quick help
-function! nerdtree#dumpHelp()
-    let old_h = @h
-    if b:treeShowHelp ==# 1
-        let @h=   "\" NERD tree (" . nerdtree#version() . ") quickhelp~\n"
-        let @h=@h."\" ============================\n"
-        let @h=@h."\" File node mappings~\n"
-        let @h=@h."\" ". (g:NERDTreeMouseMode ==# 3 ? "single" : "double") ."-click,\n"
-        let @h=@h."\" <CR>,\n"
-        if b:NERDTreeType ==# "primary"
-            let @h=@h."\" ". g:NERDTreeMapActivateNode .": open in prev window\n"
-        else
-            let @h=@h."\" ". g:NERDTreeMapActivateNode .": open in current window\n"
-        endif
-        if b:NERDTreeType ==# "primary"
-            let @h=@h."\" ". g:NERDTreeMapPreview .": preview\n"
-        endif
-        let @h=@h."\" ". g:NERDTreeMapOpenInTab.": open in new tab\n"
-        let @h=@h."\" ". g:NERDTreeMapOpenInTabSilent .": open in new tab silently\n"
-        let @h=@h."\" middle-click,\n"
-        let @h=@h."\" ". g:NERDTreeMapOpenSplit .": open split\n"
-        let @h=@h."\" ". g:NERDTreeMapPreviewSplit .": preview split\n"
-        let @h=@h."\" ". g:NERDTreeMapOpenVSplit .": open vsplit\n"
-        let @h=@h."\" ". g:NERDTreeMapPreviewVSplit .": preview vsplit\n"
-
-        let @h=@h."\"\n\" ----------------------------\n"
-        let @h=@h."\" Directory node mappings~\n"
-        let @h=@h."\" ". (g:NERDTreeMouseMode ==# 1 ? "double" : "single") ."-click,\n"
-        let @h=@h."\" ". g:NERDTreeMapActivateNode .": open & close node\n"
-        let @h=@h."\" ". g:NERDTreeMapOpenRecursively .": recursively open node\n"
-        let @h=@h."\" ". g:NERDTreeMapCloseDir .": close parent of node\n"
-        let @h=@h."\" ". g:NERDTreeMapCloseChildren .": close all child nodes of\n"
-        let @h=@h."\"    current node recursively\n"
-        let @h=@h."\" middle-click,\n"
-        let @h=@h."\" ". g:NERDTreeMapOpenExpl.": explore selected dir\n"
-
-        let @h=@h."\"\n\" ----------------------------\n"
-        let @h=@h."\" Bookmark table mappings~\n"
-        let @h=@h."\" double-click,\n"
-        let @h=@h."\" ". g:NERDTreeMapActivateNode .": open bookmark\n"
-        let @h=@h."\" ". g:NERDTreeMapOpenInTab.": open in new tab\n"
-        let @h=@h."\" ". g:NERDTreeMapOpenInTabSilent .": open in new tab silently\n"
-        let @h=@h."\" ". g:NERDTreeMapDeleteBookmark .": delete bookmark\n"
-
-        let @h=@h."\"\n\" ----------------------------\n"
-        let @h=@h."\" Tree navigation mappings~\n"
-        let @h=@h."\" ". g:NERDTreeMapJumpRoot .": go to root\n"
-        let @h=@h."\" ". g:NERDTreeMapJumpParent .": go to parent\n"
-        let @h=@h."\" ". g:NERDTreeMapJumpFirstChild  .": go to first child\n"
-        let @h=@h."\" ". g:NERDTreeMapJumpLastChild   .": go to last child\n"
-        let @h=@h."\" ". g:NERDTreeMapJumpNextSibling .": go to next sibling\n"
-        let @h=@h."\" ". g:NERDTreeMapJumpPrevSibling .": go to prev sibling\n"
-
-        let @h=@h."\"\n\" ----------------------------\n"
-        let @h=@h."\" Filesystem mappings~\n"
-        let @h=@h."\" ". g:NERDTreeMapChangeRoot .": change tree root to the\n"
-        let @h=@h."\"    selected dir\n"
-        let @h=@h."\" ". g:NERDTreeMapUpdir .": move tree root up a dir\n"
-        let @h=@h."\" ". g:NERDTreeMapUpdirKeepOpen .": move tree root up a dir\n"
-        let @h=@h."\"    but leave old root open\n"
-        let @h=@h."\" ". g:NERDTreeMapRefresh .": refresh cursor dir\n"
-        let @h=@h."\" ". g:NERDTreeMapRefreshRoot .": refresh current root\n"
-        let @h=@h."\" ". g:NERDTreeMapMenu .": Show menu\n"
-        let @h=@h."\" ". g:NERDTreeMapChdir .":change the CWD to the\n"
-        let @h=@h."\"    selected dir\n"
-        let @h=@h."\" ". g:NERDTreeMapCWD .":change tree root to CWD\n"
-
-        let @h=@h."\"\n\" ----------------------------\n"
-        let @h=@h."\" Tree filtering mappings~\n"
-        let @h=@h."\" ". g:NERDTreeMapToggleHidden .": hidden files (" . (b:NERDTreeShowHidden ? "on" : "off") . ")\n"
-        let @h=@h."\" ". g:NERDTreeMapToggleFilters .": file filters (" . (b:NERDTreeIgnoreEnabled ? "on" : "off") . ")\n"
-        let @h=@h."\" ". g:NERDTreeMapToggleFiles .": files (" . (b:NERDTreeShowFiles ? "on" : "off") . ")\n"
-        let @h=@h."\" ". g:NERDTreeMapToggleBookmarks .": bookmarks (" . (b:NERDTreeShowBookmarks ? "on" : "off") . ")\n"
-
-        "add quickhelp entries for each custom key map
-        let @h=@h."\"\n\" ----------------------------\n"
-        let @h=@h."\" Custom mappings~\n"
-        for i in g:NERDTreeKeyMap.All()
-            if !empty(i.quickhelpText)
-                let @h=@h."\" ". i.key .": ". i.quickhelpText ."\n"
-            endif
-        endfor
-
-        let @h=@h."\"\n\" ----------------------------\n"
-        let @h=@h."\" Other mappings~\n"
-        let @h=@h."\" ". g:NERDTreeMapQuit .": Close the NERDTree window\n"
-        let @h=@h."\" ". g:NERDTreeMapToggleZoom .": Zoom (maximize-minimize)\n"
-        let @h=@h."\"    the NERDTree window\n"
-        let @h=@h."\" ". g:NERDTreeMapHelp .": toggle help\n"
-        let @h=@h."\"\n\" ----------------------------\n"
-        let @h=@h."\" Bookmark commands~\n"
-        let @h=@h."\" :Bookmark [<name>]\n"
-        let @h=@h."\" :BookmarkToRoot <name>\n"
-        let @h=@h."\" :RevealBookmark <name>\n"
-        let @h=@h."\" :OpenBookmark <name>\n"
-        let @h=@h."\" :ClearBookmarks [<names>]\n"
-        let @h=@h."\" :ClearAllBookmarks\n"
-        silent! put h
-    elseif g:NERDTreeMinimalUI == 0
-        let @h="\" Press ". g:NERDTreeMapHelp ." for help\n"
-        silent! put h
-    endif
-
-    let @h = old_h
-endfunction
-
 "FUNCTION: nerdtree#echo  {{{2
 "A wrapper for :echo. Appends 'NERDTree:' on the front of all messages
 "
@@ -294,114 +139,9 @@ function! nerdtree#echoWarning(msg)
     echohl normal
 endfunction
 
-"FUNCTION: nerdtree#getTreeWinNum() {{{2
-"gets the nerd tree window number for this tab
-function! nerdtree#getTreeWinNum()
-    if exists("t:NERDTreeBufName")
-        return bufwinnr(t:NERDTreeBufName)
-    else
-        return -1
-    endif
-endfunction
-
-"FUNCTION: nerdtree#isTreeOpen() {{{2
-function! nerdtree#isTreeOpen()
-    return nerdtree#getTreeWinNum() != -1
-endfunction
-
-"FUNCTION: nerdtree#putCursorOnBookmarkTable(){{{2
-"Places the cursor at the top of the bookmarks table
-function! nerdtree#putCursorOnBookmarkTable()
-    if !b:NERDTreeShowBookmarks
-        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: nerdtree#putCursorInTreeWin(){{{2
-"Places the cursor in the nerd tree window
-function! nerdtree#putCursorInTreeWin()
-    if !nerdtree#isTreeOpen()
-        throw "NERDTree.InvalidOperationError: cant put cursor in NERD tree window, no window exists"
-    endif
-
-    call nerdtree#exec(nerdtree#getTreeWinNum() . "wincmd w")
-endfunction
-
-"FUNCTION: nerdtree#renderBookmarks {{{2
-function! nerdtree#renderBookmarks()
-
-    if g:NERDTreeMinimalUI == 0
-        call setline(line(".")+1, ">----------Bookmarks----------")
-        call cursor(line(".")+1, col("."))
-    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: nerdtree#renderView {{{2
 function! nerdtree#renderView()
     call b:NERDTree.render()
 endfunction
-"
-"FUNCTION: nerdtree#stripMarkupFromLine(line, removeLeadingSpaces){{{2
-"returns the given line with all the tree parts stripped off
-"
-"Args:
-"line: the subject line
-"removeLeadingSpaces: 1 if leading spaces are to be removed (leading spaces =
-"any spaces before the actual text of the node)
-function! nerdtree#stripMarkupFromLine(line, removeLeadingSpaces)
-    let line = a:line
-    "remove the tree parts and the leading space
-    let line = substitute (line, nerdtree#treeMarkupReg(),"","")
-
-    "strip off any read only flag
-    let line = substitute (line, ' \[RO\]', "","")
-
-    "strip off any bookmark flags
-    let line = substitute (line, ' {[^}]*}', "","")
-
-    "strip off any executable flags
-    let line = substitute (line, '*\ze\($\| \)', "","")
-
-    "strip off any generic flags
-    let line = substitute (line, '\[[^]]*\]', "","")
-
-    let wasdir = 0
-    if line =~# '/$'
-        let wasdir = 1
-    endif
-    let line = substitute (line,' -> .*',"","") " remove link to
-    if wasdir ==# 1
-        let line = substitute (line, '/\?$', '/', "")
-    endif
-
-    if a:removeLeadingSpaces
-        let line = substitute (line, '^ *', '', '')
-    endif
-
-    return line
-endfunction
 
 " vim: set sw=4 sts=4 et fdm=marker:
diff --git a/autoload/nerdtree/ui_glue.vim b/autoload/nerdtree/ui_glue.vim
@@ -85,7 +85,7 @@ endfunction
 "FUNCTION: s:activateAll() {{{1
 "handle the user activating the updir line
 function! s:activateAll()
-    if getline(".") ==# nerdtree#treeUpDirLine()
+    if getline(".") ==# g:NERDTreeUI.UpDirLine()
         return nerdtree#ui_glue#upDir(0)
     endif
 endfunction
@@ -93,13 +93,13 @@ endfunction
 "FUNCTION: s:activateDirNode() {{{1
 "handle the user activating a tree node
 function! s:activateDirNode(node)
-    call a:node.activate({'reuse': 1})
+    call a:node.activate()
 endfunction
 
 "FUNCTION: s:activateFileNode() {{{1
 "handle the user activating a tree node
 function! s:activateFileNode(node)
-    call a:node.activate({'reuse': 1, 'where': 'p'})
+    call a:node.activate({'reuse': 'all', 'where': 'p'})
 endfunction
 
 "FUNCTION: s:activateBookmark() {{{1
@@ -212,7 +212,7 @@ function! s:closeTreeWindow()
         exec "buffer " . b:NERDTreePreviousBuf
     else
         if winnr("$") > 1
-            call nerdtree#closeTree()
+            call g:NERDTree.Close()
         else
             call nerdtree#echo("Cannot close last window")
         endif
@@ -275,20 +275,20 @@ function! s:findAndRevealPath()
         endif
     else
         if !p.isUnder(g:NERDTreeFileNode.GetRootForTab().path)
-            if !nerdtree#isTreeOpen()
+            if !g:NERDTree.IsOpen()
                 call g:NERDTreeCreator.TogglePrimary('')
             else
-                call nerdtree#putCursorInTreeWin()
+                call g:NERDTree.CursorToTreeWin()
             endif
             let b:NERDTreeShowHidden = g:NERDTreeShowHidden
             call s:chRoot(g:NERDTreeDirNode.New(p.getParent()))
         else
-            if !nerdtree#isTreeOpen()
+            if !g:NERDTree.IsOpen()
                 call g:NERDTreeCreator.TogglePrimary("")
             endif
         endif
     endif
-    call nerdtree#putCursorInTreeWin()
+    call g:NERDTree.CursorToTreeWin()
     call b:NERDTreeRoot.reveal(p)
 
     if p.isUnixHiddenFile()
@@ -312,7 +312,7 @@ function! s:handleLeftClick()
         endfor
 
         if currentNode.path.isDirectory
-            if startToCur =~# nerdtree#treeMarkupReg() && startToCur =~# '[+~▾▸] \?$'
+            if startToCur =~# g:NERDTreeUI.MarkupReg() && startToCur =~# '[+~'.g:NERDTreeDirArrowExpandable.g:NERDTreeDirArrowCollapsible.'] \?$'
                 call currentNode.activate()
                 return
             endif
@@ -320,11 +320,11 @@ function! s:handleLeftClick()
 
         if (g:NERDTreeMouseMode ==# 2 && currentNode.path.isDirectory) || g:NERDTreeMouseMode ==# 3
             let char = strpart(startToCur, strlen(startToCur)-1, 1)
-            if char !~# nerdtree#treeMarkupReg()
+            if char !~# g:NERDTreeUI.MarkupReg()
                 if currentNode.path.isDirectory
                     call currentNode.activate()
                 else
-                    call currentNode.activate({'reuse': 1, 'where': 'p'})
+                    call currentNode.activate({'reuse': 'all', 'where': 'p'})
                 endif
                 return
             endif
@@ -547,7 +547,7 @@ endfunction
 function! nerdtree#ui_glue#setupCommands()
     command! -n=? -complete=dir -bar NERDTree :call g:NERDTreeCreator.CreatePrimary('<args>')
     command! -n=? -complete=dir -bar NERDTreeToggle :call g:NERDTreeCreator.TogglePrimary('<args>')
-    command! -n=0 -bar NERDTreeClose :call nerdtree#closeTreeIfOpen()
+    command! -n=0 -bar NERDTreeClose :call g:NERDTree.Close()
     command! -n=1 -complete=customlist,nerdtree#completeBookmarks -bar NERDTreeFromBookmark call g:NERDTreeCreator.CreatePrimary('<args>')
     command! -n=0 -bar NERDTreeMirror call g:NERDTreeCreator.CreateMirror()
     command! -n=0 -bar NERDTreeFind call s:findAndRevealPath()
diff --git a/doc/NERD_tree.txt b/doc/NERD_tree.txt
@@ -34,6 +34,8 @@ CONTENTS                                                   *NERDTree-contents*
     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.Changelog...............................|NERDTreeChangelog|
     7.Credits.................................|NERDTreeCredits|
@@ -131,7 +133,7 @@ The following features and functionality are provided by the NERD tree:
 :NERDTreeFind                                                  *:NERDTreeFind*
     Find the current file in the tree.
 
-    If not tree exists and the current file is under vim's CWD, then init a
+    If no tree exists and the current file is under vim's CWD, then init a
     tree at the CWD and reveal the file. Otherwise init a tree in the current
     file's directory.
 
@@ -1174,6 +1176,44 @@ 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 path in question. 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.
@@ -1203,6 +1243,8 @@ Next
     - add 'scope' argument to the key map API
     - add NERDTreeCustomIgnoreFilter hook - needs doc
     - add magic [[dir]] and [[file]] flags to NERDTreeIgnore
+    - add support for custom path filters. See :help NERDTreeAddPathFilter()
+    - add path listener API. See :help NERDTreePathListenerAPI.
 
 4.2.0
     - Add NERDTreeDirArrows option to make the UI use pretty arrow chars
diff --git a/lib/nerdtree/bookmark.vim b/lib/nerdtree/bookmark.vim
@@ -87,6 +87,7 @@ function! s:Bookmark.CacheBookmarks(silent)
 
                 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))
@@ -253,7 +254,7 @@ 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(nerdtree#getTreeWinNum()) - 4 - len(self.name)
+    let pathStrMaxLen = winwidth(g:NERDTree.GetWinNum()) - 4 - len(self.name)
     if &nu
         let pathStrMaxLen = pathStrMaxLen - &numberwidth
     endif
@@ -304,7 +305,7 @@ endfunction
 function! s:Bookmark.Write()
     let bookmarkStrings = []
     for i in s:Bookmark.Bookmarks()
-        call add(bookmarkStrings, i.name . ' ' . i.path.str())
+        call add(bookmarkStrings, i.name . ' ' . fnamemodify(i.path.str(), ':~'))
     endfor
 
     "add a blank line before the invalid ones
diff --git a/lib/nerdtree/creator.vim b/lib/nerdtree/creator.vim
@@ -42,6 +42,15 @@ endfunction
 "name: the name of a bookmark or a directory
 function! s:Creator.createPrimary(name)
     let path = self._pathForString(a:name)
+    
+    "abort if exception was thrown (bookmark/dir doesn't exist)
+    if empty(path)
+        return
+    endif
+
+    if path == {}
+        return
+    endif
 
     "if instructed to, then change the vim CWD to the dir the NERDTree is
     "inited in
@@ -50,8 +59,8 @@ function! s:Creator.createPrimary(name)
     endif
 
     if g:NERDTree.ExistsForTab()
-        if nerdtree#isTreeOpen()
-            call nerdtree#closeTree()
+        if g:NERDTree.IsOpen()
+            call g:NERDTree.Close()
         endif
         unlet t:NERDTreeBufName
     endif
@@ -163,8 +172,8 @@ function! s:Creator.createMirror()
         return
     endif
 
-    if g:NERDTree.ExistsForTab() && nerdtree#isTreeOpen()
-        call nerdtree#closeTree()
+    if g:NERDTree.ExistsForTab() && g:NERDTree.IsOpen()
+        call g:NERDTree.Close()
     endif
 
     let t:NERDTreeBufName = bufferName
@@ -240,7 +249,7 @@ function! s:Creator._pathForString(str)
             let path = g:NERDTreePath.New(dir)
         catch /^NERDTree.InvalidArgumentsError/
             call nerdtree#echo("No bookmark or directory found for: " . a:str)
-            return
+            return {}
         endtry
     endif
     if !path.isDirectory
@@ -328,14 +337,14 @@ endfunction
 "initialized.
 function! s:Creator.togglePrimary(dir)
     if g:NERDTree.ExistsForTab()
-        if !nerdtree#isTreeOpen()
+        if !g:NERDTree.IsOpen()
             call self._createTreeWin()
             if !&hidden
                 call b:NERDTree.render()
             endif
             call b:NERDTree.ui.restoreScreenState()
         else
-            call nerdtree#closeTree()
+            call g:NERDTree.Close()
         endif
     else
         call self.createPrimary(a:dir)
diff --git a/lib/nerdtree/nerdtree.vim b/lib/nerdtree/nerdtree.vim
@@ -3,6 +3,73 @@
 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.Close() {{{1
+"Closes the primary NERD tree window for this tab
+function! s:NERDTree.Close()
+    if !s:NERDTree.IsOpen()
+        return
+    endif
+
+    if winnr("$") != 1
+        if winnr() == s:NERDTree.GetWinNum()
+            call nerdtree#exec("wincmd p")
+            let bufnr = bufnr("")
+            call nerdtree#exec("wincmd p")
+        else
+            let bufnr = bufnr("")
+        endif
+
+        call nerdtree#exec(s:NERDTree.GetWinNum() . " wincmd w")
+        close
+        call nerdtree#exec(bufwinnr(bufnr) . " wincmd w")
+    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:NERDTreeShowBookmarks
+        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()
@@ -23,6 +90,29 @@ function! s:NERDTree.ForCurrentBuf()
     endif
 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)
+    else
+        return -1
+    endif
+endfunction
+
+"FUNCTION: s:NERDTree.IsOpen() {{{1
+function! s:NERDTree.IsOpen()
+    return s:NERDTree.GetWinNum() != -1
+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)
     let newObj = copy(self)
     let newObj.ui = g:NERDTreeUI.New(newObj)
@@ -31,9 +121,17 @@ function! s:NERDTree.New(path)
     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.render() {{{1
 "A convenience function - since this is called often
 function! s:NERDTree.render()
     call self.ui.render()
 endfunction
-
diff --git a/lib/nerdtree/opener.vim b/lib/nerdtree/opener.vim
@@ -40,7 +40,7 @@ function! s:Opener._checkToCloseTree(newtab)
     endif
 
     if (a:newtab && self._where == 't') || !a:newtab
-        call nerdtree#closeTreeIfQuitOnOpen()
+        call g:NERDTree.CloseIfQuitOnOpen()
     endif
 endfunction
 
@@ -131,7 +131,8 @@ endfunction
 "  'where': Specifies whether the node should be opened in new split/tab or in
 "           the previous window. Can be either 'v' or 'h' or 't' (for open in
 "           new tab)
-"  'reuse': if a window is displaying the file then jump the cursor there
+"  'reuse': if a window is displaying the file then jump the cursor there. Can
+"           'all', 'currenttab' or empty to not reuse.
 "  'keepopen': dont close the tree window
 "  'stay': open the file, but keep the cursor in the tree win
 function! s:Opener.New(path, opts)
@@ -139,7 +140,13 @@ function! s:Opener.New(path, opts)
 
     let newObj._path = a:path
     let newObj._stay = nerdtree#has_opt(a:opts, 'stay')
-    let newObj._reuse = nerdtree#has_opt(a:opts, 'reuse')
+
+    if has_key(a:opts, 'reuse')
+        let newObj._reuse = a:opts['reuse']
+    else
+        let newObj._reuse = ''
+    endif
+
     let newObj._keepopen = nerdtree#has_opt(a:opts, 'keepopen')
     let newObj._where = has_key(a:opts, 'where') ? a:opts['where'] : ''
     let newObj._treetype = b:NERDTreeType
@@ -189,7 +196,7 @@ function! s:Opener._newSplit()
     try
         exec(splitMode." sp ")
     catch /^Vim\%((\a\+)\)\=:E37/
-        call nerdtree#putCursorInTreeWin()
+        call g:NERDTree.CursorToTreeWin()
         throw "NERDTree.FileAlreadyOpenAndModifiedError: ". self._path.str() ." is already open and modified."
     catch /^Vim\%((\a\+)\)\=:/
         "do nothing
@@ -219,7 +226,7 @@ function! s:Opener._newVSplit()
     vnew
 
     "resize the nerd tree back to the original size
-    call nerdtree#putCursorInTreeWin()
+    call g:NERDTree.CursorToTreeWin()
     exec("silent vertical resize ". winwidth)
     call nerdtree#exec('wincmd p')
 endfunction
@@ -235,7 +242,7 @@ endfunction
 
 "FUNCTION: Opener._openFile() {{{1
 function! s:Opener._openFile()
-    if self._reuse && self._reuseWindow()
+    if self._reuseWindow()
         return
     endif
 
@@ -288,7 +295,7 @@ function! s:Opener._previousWindow()
                 call nerdtree#exec('wincmd p')
             endif
         catch /^Vim\%((\a\+)\)\=:E37/
-            call nerdtree#putCursorInTreeWin()
+            call g:NERDTree.CursorToTreeWin()
             throw "NERDTree.FileAlreadyOpenAndModifiedError: ". self._path.str() ." is already open and modified."
         catch /^Vim\%((\a\+)\)\=:/
             echo v:exception
@@ -307,23 +314,32 @@ endfunction
 "
 "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
-    else
-        "check other tabs
-        let tabnr = self._path.tabnr()
-        if tabnr
-            call self._checkToCloseTree(1)
-            call nerdtree#exec('normal! ' . tabnr . 'gt')
-            let winnr = bufwinnr('^' . self._path.str() . '$')
-            call nerdtree#exec(winnr . "wincmd w")
-            return 1
-        endif
     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('normal! ' . tabnr . 'gt')
+        let winnr = bufwinnr('^' . self._path.str() . '$')
+        call nerdtree#exec(winnr . "wincmd w")
+        return 1
+    endif
+
     return 0
 endfunction
 
diff --git a/lib/nerdtree/path.vim b/lib/nerdtree/path.vim
@@ -1,6 +1,12 @@
 "we need to use this number many times for sorting... so we calculate it only
 "once here
 let s:NERDTreeSortStarIndex = index(g:NERDTreeSortOrder, '*')
+" used in formating sortKey, e.g. '%04d'
+if exists("log10")
+    let s:sortKeyFormat = "%0" . float2nr(ceil(log10(len(g:NERDTreeSortOrder)))) . "d"
+else
+    let s:sortKeyFormat = "%04d"
+endif
 
 "CLASS: Path
 "============================================================
@@ -361,6 +367,24 @@ function! s:Path.getSortOrderIndex()
     return s:NERDTreeSortStarIndex
 endfunction
 
+"FUNCTION: Path.getSortKey() {{{1
+"returns a string used in compare function for sorting
+function! s:Path.getSortKey()
+    if !exists("self._sortKey")
+        let path = self.getLastPathComponent(1)
+        if !g:NERDTreeSortHiddenFirst
+            let path = substitute(path, '^[._]', '', '')
+        endif
+        if !g:NERDTreeCaseSensitiveSort
+            let path = tolower(path)
+        endif
+        let self._sortKey = printf(s:sortKeyFormat, self.getSortOrderIndex()) . path
+    endif
+
+    return self._sortKey
+endfunction
+
+
 "FUNCTION: Path.isUnixHiddenFile() {{{1
 "check for unix hidden files
 function! s:Path.isUnixHiddenFile()
@@ -392,6 +416,12 @@ function! s:Path.ignore()
                 return 1
             endif
         endfor
+
+        for callback in g:NERDTree.PathFilters()
+            if {callback}({'path': self, 'nerdtree': b:NERDTree})
+                return 1
+            endif
+        endfor
     endif
 
     "dont show hidden files unless instructed to
@@ -403,10 +433,6 @@ function! s:Path.ignore()
         return 1
     endif
 
-    if exists("*NERDTreeCustomIgnoreFilter") && NERDTreeCustomIgnoreFilter(self)
-        return 1
-    endif
-
     return 0
 endfunction
 
@@ -611,7 +637,7 @@ function! s:Path.str(...)
         if has_key(self, '_strFor' . format)
             exec 'let toReturn = self._strFor' . format . '()'
         else
-            raise 'NERDTree.UnknownFormatError: unknown format "'. format .'"'
+            throw 'NERDTree.UnknownFormatError: unknown format "'. format .'"'
         endif
     else
         let toReturn = self._str()
@@ -623,8 +649,13 @@ function! s:Path.str(...)
 
     if has_key(options, 'truncateTo')
         let limit = options['truncateTo']
-        if len(toReturn) > limit
-            let toReturn = "<" . strpart(toReturn, len(toReturn) - limit + 1)
+        if len(toReturn) > limit-1
+            let toReturn = toReturn[(len(toReturn)-limit+1):]
+            if len(split(toReturn, '/')) > 1
+                let toReturn = '</' . join(split(toReturn, '/')[1:], '/') . '/'
+            else
+                let toReturn = '<' . toReturn
+            endif
         endif
     endif
 
@@ -652,25 +683,15 @@ endfunction
 "Return: the string for this path that is suitable to be used with the :edit
 "command
 function! s:Path._strForEdit()
-    let p = escape(self.str({'format': 'UI'}), self._escChars())
-    let cwd = getcwd() . s:Path.Slash()
+    let p = escape(self.str(), self._escChars())
 
-    "return a relative path if we can
-    let isRelative = 0
-    if nerdtree#runningWindows()
-        let isRelative = stridx(tolower(p), tolower(cwd)) == 0
-    else
-        let isRelative = stridx(p, cwd) == 0
-    endif
+    "make it relative
+    let p = fnamemodify(p, ':.')
 
-    if isRelative
-        let p = strpart(p, strlen(cwd))
-
-        "handle the edge case where the file begins with a + (vim interprets
-        "the +foo in `:e +foo` as an option to :edit)
-        if p[0] == "+"
-            let p = '\' . p
-        endif
+    "handle the edge case where the file begins with a + (vim interprets
+    "the +foo in `:e +foo` as an option to :edit)
+    if p[0] == "+"
+        let p = '\' . p
     endif
 
     if p ==# ''
diff --git a/lib/nerdtree/tree_dir_node.vim b/lib/nerdtree/tree_dir_node.vim
@@ -246,8 +246,12 @@ function! s:TreeDirNode._initChildren(silent)
         "filter out the .. and . directories
         "Note: we must match .. AND ../ cos sometimes the globpath returns
         "../ for path with strange chars (eg $)
-        if i !~# '\/\.\.\/\?$' && i !~# '\/\.\/\?$'
-
+"        if i !~# '\/\.\.\/\?$' && i !~# '\/\.\/\?$'
+"
+        " Regular expression is too expensive. Use simply string comparison
+        " instead
+        if i[len(i)-3:2] != ".." && i[len(i)-2:2] != ".." && 
+         \ i[len(i)-2:1] != "." && i[len(i)-1] != "."
             "put the next file in a new node and attach it
             try
                 let path = g:NERDTreePath.New(i)
@@ -405,8 +409,12 @@ function! s:TreeDirNode.refresh()
             "filter out the .. and . directories
             "Note: we must match .. AND ../ cos sometimes the globpath returns
             "../ for path with strange chars (eg $)
-            if i !~# '\/\.\.\/\?$' && i !~# '\/\.\/\?$'
+            "if i !~# '\/\.\.\/\?$' && i !~# '\/\.\/\?$'
 
+            " Regular expression is too expensive. Use simply string comparison
+            " instead
+            if i[len(i)-3:2] != ".." && i[len(i)-2:2] != ".." && 
+             \ i[len(i)-2:1] != "." && i[len(i)-1] != "."
                 try
                     "create a new path and see if it exists in this nodes children
                     let path = g:NERDTreePath.New(i)
@@ -504,7 +512,7 @@ endfunction
 "directory priority.
 "
 function! s:TreeDirNode.sortChildren()
-    let CompareFunc = function("nerdtree#compareNodes")
+    let CompareFunc = function("nerdtree#compareNodesBySortKey")
     call sort(self.children, CompareFunc)
 endfunction
 
diff --git a/lib/nerdtree/tree_file_node.vim b/lib/nerdtree/tree_file_node.vim
@@ -383,13 +383,13 @@ function! s:TreeFileNode._renderToString(depth, drawText, vertMap, isLastChild)
         if self.path.isDirectory
             if self.isOpen
                 if g:NERDTreeDirArrows
-                    let treeParts = treeParts . '▾ '
+                    let treeParts = treeParts . g:NERDTreeDirArrowCollapsible . ' '
                 else
                     let treeParts = treeParts . '~'
                 endif
             else
                 if g:NERDTreeDirArrows
-                    let treeParts = treeParts . '▸ '
+                    let treeParts = treeParts . g:NERDTreeDirArrowExpandable . ' '
                 else
                     let treeParts = treeParts . '+'
                 endif
diff --git a/lib/nerdtree/ui.vim b/lib/nerdtree/ui.vim
@@ -3,11 +3,6 @@
 let s:UI = {}
 let g:NERDTreeUI = s:UI
 
-
-function! s:UI.lolcats()
-    echomsg "lolcats"
-endfunction
-
 "FUNCTION: s:UI.centerView() {{{2
 "centers the nerd tree window around the cursor (provided the nerd tree
 "options permit)
@@ -15,13 +10,121 @@ function! s:UI.centerView()
     if g:NERDTreeAutoCenter
         let current_line = winline()
         let lines_to_top = current_line
-        let lines_to_bottom = winheight(nerdtree#getTreeWinNum()) - 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()
+    let old_h = @h
+    if b:treeShowHelp ==# 1
+        let @h=   "\" NERD tree (" . nerdtree#version() . ") quickhelp~\n"
+        let @h=@h."\" ============================\n"
+        let @h=@h."\" File node mappings~\n"
+        let @h=@h."\" ". (g:NERDTreeMouseMode ==# 3 ? "single" : "double") ."-click,\n"
+        let @h=@h."\" <CR>,\n"
+        if b:NERDTreeType ==# "primary"
+            let @h=@h."\" ". g:NERDTreeMapActivateNode .": open in prev window\n"
+        else
+            let @h=@h."\" ". g:NERDTreeMapActivateNode .": open in current window\n"
+        endif
+        if b:NERDTreeType ==# "primary"
+            let @h=@h."\" ". g:NERDTreeMapPreview .": preview\n"
+        endif
+        let @h=@h."\" ". g:NERDTreeMapOpenInTab.": open in new tab\n"
+        let @h=@h."\" ". g:NERDTreeMapOpenInTabSilent .": open in new tab silently\n"
+        let @h=@h."\" middle-click,\n"
+        let @h=@h."\" ". g:NERDTreeMapOpenSplit .": open split\n"
+        let @h=@h."\" ". g:NERDTreeMapPreviewSplit .": preview split\n"
+        let @h=@h."\" ". g:NERDTreeMapOpenVSplit .": open vsplit\n"
+        let @h=@h."\" ". g:NERDTreeMapPreviewVSplit .": preview vsplit\n"
+
+        let @h=@h."\"\n\" ----------------------------\n"
+        let @h=@h."\" Directory node mappings~\n"
+        let @h=@h."\" ". (g:NERDTreeMouseMode ==# 1 ? "double" : "single") ."-click,\n"
+        let @h=@h."\" ". g:NERDTreeMapActivateNode .": open & close node\n"
+        let @h=@h."\" ". g:NERDTreeMapOpenRecursively .": recursively open node\n"
+        let @h=@h."\" ". g:NERDTreeMapCloseDir .": close parent of node\n"
+        let @h=@h."\" ". g:NERDTreeMapCloseChildren .": close all child nodes of\n"
+        let @h=@h."\"    current node recursively\n"
+        let @h=@h."\" middle-click,\n"
+        let @h=@h."\" ". g:NERDTreeMapOpenExpl.": explore selected dir\n"
+
+        let @h=@h."\"\n\" ----------------------------\n"
+        let @h=@h."\" Bookmark table mappings~\n"
+        let @h=@h."\" double-click,\n"
+        let @h=@h."\" ". g:NERDTreeMapActivateNode .": open bookmark\n"
+        let @h=@h."\" ". g:NERDTreeMapOpenInTab.": open in new tab\n"
+        let @h=@h."\" ". g:NERDTreeMapOpenInTabSilent .": open in new tab silently\n"
+        let @h=@h."\" ". g:NERDTreeMapDeleteBookmark .": delete bookmark\n"
+
+        let @h=@h."\"\n\" ----------------------------\n"
+        let @h=@h."\" Tree navigation mappings~\n"
+        let @h=@h."\" ". g:NERDTreeMapJumpRoot .": go to root\n"
+        let @h=@h."\" ". g:NERDTreeMapJumpParent .": go to parent\n"
+        let @h=@h."\" ". g:NERDTreeMapJumpFirstChild  .": go to first child\n"
+        let @h=@h."\" ". g:NERDTreeMapJumpLastChild   .": go to last child\n"
+        let @h=@h."\" ". g:NERDTreeMapJumpNextSibling .": go to next sibling\n"
+        let @h=@h."\" ". g:NERDTreeMapJumpPrevSibling .": go to prev sibling\n"
+
+        let @h=@h."\"\n\" ----------------------------\n"
+        let @h=@h."\" Filesystem mappings~\n"
+        let @h=@h."\" ". g:NERDTreeMapChangeRoot .": change tree root to the\n"
+        let @h=@h."\"    selected dir\n"
+        let @h=@h."\" ". g:NERDTreeMapUpdir .": move tree root up a dir\n"
+        let @h=@h."\" ". g:NERDTreeMapUpdirKeepOpen .": move tree root up a dir\n"
+        let @h=@h."\"    but leave old root open\n"
+        let @h=@h."\" ". g:NERDTreeMapRefresh .": refresh cursor dir\n"
+        let @h=@h."\" ". g:NERDTreeMapRefreshRoot .": refresh current root\n"
+        let @h=@h."\" ". g:NERDTreeMapMenu .": Show menu\n"
+        let @h=@h."\" ". g:NERDTreeMapChdir .":change the CWD to the\n"
+        let @h=@h."\"    selected dir\n"
+        let @h=@h."\" ". g:NERDTreeMapCWD .":change tree root to CWD\n"
+
+        let @h=@h."\"\n\" ----------------------------\n"
+        let @h=@h."\" Tree filtering mappings~\n"
+        let @h=@h."\" ". g:NERDTreeMapToggleHidden .": hidden files (" . (b:NERDTreeShowHidden ? "on" : "off") . ")\n"
+        let @h=@h."\" ". g:NERDTreeMapToggleFilters .": file filters (" . (b:NERDTreeIgnoreEnabled ? "on" : "off") . ")\n"
+        let @h=@h."\" ". g:NERDTreeMapToggleFiles .": files (" . (b:NERDTreeShowFiles ? "on" : "off") . ")\n"
+        let @h=@h."\" ". g:NERDTreeMapToggleBookmarks .": bookmarks (" . (b:NERDTreeShowBookmarks ? "on" : "off") . ")\n"
+
+        "add quickhelp entries for each custom key map
+        let @h=@h."\"\n\" ----------------------------\n"
+        let @h=@h."\" Custom mappings~\n"
+        for i in g:NERDTreeKeyMap.All()
+            if !empty(i.quickhelpText)
+                let @h=@h."\" ". i.key .": ". i.quickhelpText ."\n"
+            endif
+        endfor
+
+        let @h=@h."\"\n\" ----------------------------\n"
+        let @h=@h."\" Other mappings~\n"
+        let @h=@h."\" ". g:NERDTreeMapQuit .": Close the NERDTree window\n"
+        let @h=@h."\" ". g:NERDTreeMapToggleZoom .": Zoom (maximize-minimize)\n"
+        let @h=@h."\"    the NERDTree window\n"
+        let @h=@h."\" ". g:NERDTreeMapHelp .": toggle help\n"
+        let @h=@h."\"\n\" ----------------------------\n"
+        let @h=@h."\" Bookmark commands~\n"
+        let @h=@h."\" :Bookmark [<name>]\n"
+        let @h=@h."\" :BookmarkToRoot <name>\n"
+        let @h=@h."\" :RevealBookmark <name>\n"
+        let @h=@h."\" :OpenBookmark <name>\n"
+        let @h=@h."\" :ClearBookmarks [<names>]\n"
+        let @h=@h."\" :ClearAllBookmarks\n"
+        silent! put h
+    elseif g:NERDTreeMinimalUI == 0
+        let @h="\" Press ". g:NERDTreeMapHelp ." for help\n"
+        silent! put h
+    endif
+
+    let @h = old_h
+endfunction
+
+
 "FUNCTION: s:UI.new(nerdtree) {{{1
 function! s:UI.New(nerdtree)
     let newObj = copy(self)
@@ -51,19 +154,19 @@ function! s:UI.getPath(ln)
 
     if !g:NERDTreeDirArrows
         " in case called from outside the tree
-        if line !~# '^ *[|`▸▾ ]' || line =~# '^$'
+        if line !~# '^ *[|`'.g:NERDTreeDirArrowExpandable.g:NERDTreeDirArrowCollapsible.' ]' || line =~# '^$'
             return {}
         endif
     endif
 
-    if line ==# nerdtree#treeUpDirLine()
+    if line ==# s:UI.UpDirLine()
         return b:NERDTreeRoot.path.getParent()
     endif
 
     let indent = self._indentLevelFor(line)
 
     "remove the tree parts and the leading space
-    let curFile = nerdtree#stripMarkupFromLine(line, 0)
+    let curFile = self._stripMarkup(line, 0)
 
     let wasdir = 0
     if curFile =~# '/$'
@@ -76,7 +179,7 @@ function! s:UI.getPath(ln)
     while lnum > 0
         let lnum = lnum - 1
         let curLine = getline(lnum)
-        let curLineStripped = nerdtree#stripMarkupFromLine(curLine, 1)
+        let curLineStripped = self._stripMarkup(curLine, 1)
 
         "have we reached the top of the tree?
         if lnum == rootLine
@@ -127,7 +230,7 @@ function! s:UI.getLineNum(file_node)
 
         let indent = self._indentLevelFor(curLine)
         if indent ==# curPathComponent
-            let curLine = nerdtree#stripMarkupFromLine(curLine, 1)
+            let curLine = self._stripMarkup(curLine, 1)
 
             let curPath =  join(pathcomponents, '/') . '/' . curLine
             if stridx(fullpath, curPath, 0) ==# 0
@@ -146,7 +249,6 @@ function! s:UI.getLineNum(file_node)
     return -1
 endfunction
 
-
 "FUNCTION: s:UI.getRootLineNum(){{{1
 "gets the line number of the root node
 function! s:UI.getRootLineNum()
@@ -157,19 +259,49 @@ function! s:UI.getRootLineNum()
     return rootLine
 endfunction
 
-"FUNCTION: s:UI._indentLevelFor(line) {{{2
+"FUNCTION: s:UI._indentLevelFor(line) {{{1
 function! s:UI._indentLevelFor(line)
-    let level = match(a:line, '[^ \-+~▸▾`|]') / nerdtree#treeWid()
+    let level = match(a:line, '[^ \-+~'.g:NERDTreeDirArrowExpandable.g:NERDTreeDirArrowCollapsible.'`|]') / s:UI.IndentWid()
     " check if line includes arrows
-    if match(a:line, '[▸▾]') > -1
+    if match(a:line, '['.g:NERDTreeDirArrowExpandable.g:NERDTreeDirArrowCollapsible.']') > -1
         " decrement level as arrow uses 3 ascii chars
         let level = level - 1
     endif
     return level
 endfunction
 
+"FUNCTION: s:UI.IndentWid() {{{1
+function! s:UI.IndentWid()
+    return 2
+endfunction
+
+"FUNCTION: s:UI.MarkupReg() {{{1
+function! s:UI.MarkupReg()
+    if g:NERDTreeDirArrows
+        return '^\(['.g:NERDTreeDirArrowExpandable.g:NERDTreeDirArrowCollapsible.'] \| \+['.g:NERDTreeDirArrowExpandable.g:NERDTreeDirArrowCollapsible.'] \| \+\)'
+    endif
+
+    return '^[ `|]*[\-+~]'
+endfunction
+
+"FUNCTION: s:UI._renderBookmarks {{{1
+function! s:UI._renderBookmarks()
+
+    if g:NERDTreeMinimalUI == 0
+        call setline(line(".")+1, ">----------Bookmarks----------")
+        call cursor(line(".")+1, col("."))
+    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() {{{2
+"FUNCTION: s:UI.restoreScreenState() {{{1
 "
 "Sets the screen state back to what it was when nerdtree#saveScreenState was last
 "called.
@@ -189,23 +321,60 @@ function! s:UI.restoreScreenState()
     let &scrolloff=old_scrolloff
 endfunction
 
-"FUNCTION: s:UI.saveScreenState() {{{2
+"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()
-    try
-        call nerdtree#putCursorInTreeWin()
-        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")
-    catch /^NERDTree.InvalidOperationError/
-    endtry
+    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.render() {{{2
+"FUNCTION: s:UI._stripMarkup(line, removeLeadingSpaces){{{1
+"returns the given line with all the tree parts stripped off
+"
+"Args:
+"line: the subject line
+"removeLeadingSpaces: 1 if leading spaces are to be removed (leading spaces =
+"any spaces before the actual text of the node)
+function! s:UI._stripMarkup(line, removeLeadingSpaces)
+    let line = a:line
+    "remove the tree parts and the leading space
+    let line = substitute (line, g:NERDTreeUI.MarkupReg(),"","")
+
+    "strip off any read only flag
+    let line = substitute (line, ' \[RO\]', "","")
+
+    "strip off any bookmark flags
+    let line = substitute (line, ' {[^}]*}', "","")
+
+    "strip off any executable flags
+    let line = substitute (line, '*\ze\($\| \)', "","")
+
+    "strip off any generic flags
+    let line = substitute (line, '\[[^]]*\]', "","")
+
+    let wasdir = 0
+    if line =~# '/$'
+        let wasdir = 1
+    endif
+    let line = substitute (line,' -> .*',"","") " remove link to
+    if wasdir ==# 1
+        let line = substitute (line, '/\?$', '/', "")
+    endif
+
+    if a:removeLeadingSpaces
+        let line = substitute (line, '^ *', '', '')
+    endif
+
+    return line
+endfunction
+
+"FUNCTION: s:UI.render() {{{1
 function! s:UI.render()
     setlocal modifiable
 
@@ -218,7 +387,7 @@ function! s:UI.render()
     "delete all lines in the buffer (being careful not to clobber a register)
     silent 1,$delete _
 
-    call nerdtree#dumpHelp()
+    call self._dumpHelp()
 
     "delete the blank line before the help and add one after it
     if g:NERDTreeMinimalUI == 0
@@ -227,12 +396,12 @@ function! s:UI.render()
     endif
 
     if b:NERDTreeShowBookmarks
-        call nerdtree#renderBookmarks()
+        call self._renderBookmarks()
     endif
 
     "add the 'up a dir' line
     if !g:NERDTreeMinimalUI
-        call setline(line(".")+1, nerdtree#treeUpDirLine())
+        call setline(line(".")+1, s:UI.UpDirLine())
         call cursor(line(".")+1, col("."))
     endif
 
@@ -295,7 +464,7 @@ function! s:UI.toggleShowBookmarks()
     let b:NERDTreeShowBookmarks = !b:NERDTreeShowBookmarks
     if b:NERDTreeShowBookmarks
         call b:NERDTree.render()
-        call nerdtree#putCursorOnBookmarkTable()
+        call g:NERDTree.CursorToBookmarkTable()
     else
         call b:NERDTree.ui.renderViewSavingPosition()
     endif
@@ -330,3 +499,8 @@ function! s:UI.toggleZoom()
         let b:NERDTreeZoomed = 1
     endif
 endfunction
+
+"FUNCTION: s:UI.UpDirLine() {{{1
+function! s:UI.UpDirLine()
+    return '.. (up a dir)'
+endfunction
diff --git a/nerdtree_plugin/fs_menu.vim b/nerdtree_plugin/fs_menu.vim
@@ -25,7 +25,7 @@ call NERDTreeAddMenuItem({'text': '(m)ove the current node', 'shortcut': 'm', 'c
 call NERDTreeAddMenuItem({'text': '(d)elete the current node', 'shortcut': 'd', 'callback': 'NERDTreeDeleteNode'})
 call NERDTreeAddMenuItem({'text': 'show (p)roperties of the current node', 'shortcut': 'p', 'callback': 'NERDTreeNodeProperties'})
 
-if has("gui_mac") || has("gui_macvim") 
+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'})
@@ -35,6 +35,10 @@ 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'})
+endif
+
 "FUNCTION: s:echo(msg){{{1
 function! s:echo(msg)
     redraw
@@ -87,10 +91,11 @@ function! s:promptToRenameBuffer(bufnum, msg, newFileName)
         " 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. 
+        " 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! " . quotedFileName . "\" | endif"
+        let editStr = g:NERDTreePath.New(a:newFileName).str({'format': 'Edit'})
+        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
@@ -273,4 +278,14 @@ function! NERDTreeExecuteFile()
     endif
 endfunction
 
+function! NERDTreeListNode()
+    let treenode = g:NERDTreeFileNode.GetSelected()
+    if treenode != {}
+        let metadata = split(system('ls -ld ' . shellescape(treenode.path.str())), '\n')
+        call s:echo(metadata[0])
+    else
+        call s:echo("No information avaialable")
+    endif
+endfunction
+
 " vim: set sw=4 sts=4 et fdm=marker:
diff --git a/plugin/NERD_tree.vim b/plugin/NERD_tree.vim
@@ -68,6 +68,8 @@ call s:initVariable("g:NERDTreeShowHidden", 0)
 call s:initVariable("g:NERDTreeShowLineNumbers", 0)
 call s:initVariable("g:NERDTreeSortDirs", 1)
 call s:initVariable("g:NERDTreeDirArrows", !nerdtree#runningWindows())
+call s:initVariable("g:NERDTreeDirArrowExpandable", "▸")
+call s:initVariable("g:NERDTreeDirArrowCollapsible", "▾")
 call s:initVariable("g:NERDTreeCascadeOpenSingleChildDir", 1)
 
 if !exists("g:NERDTreeSortOrder")
@@ -148,7 +150,7 @@ call nerdtree#ui_glue#setupCommands()
 "============================================================
 augroup NERDTree
     "Save the cursor position whenever we close the nerd tree
-    exec "autocmd BufLeave ". g:NERDTreeCreator.BufNamePrefix() ."* call b:NERDTree.ui.saveScreenState()"
+    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"
@@ -185,8 +187,8 @@ function! NERDTreeRender()
 endfunction
 
 function! NERDTreeFocus()
-    if nerdtree#isTreeOpen()
-        call nerdtree#putCursorInTreeWin()
+    if g:NERDTree.IsOpen()
+        call g:NERDTree.CursorToTreeWin()
     else
         call g:NERDTreeCreator.TogglePrimary("")
     endif
@@ -196,6 +198,11 @@ function! NERDTreeCWD()
     call NERDTreeFocus()
     call nerdtree#ui_glue#chRootCwd()
 endfunction
+
+function! NERDTreeAddPathFilter(callback)
+    call g:NERDTree.AddPathFilter(a:callback)
+endfunction
+
 " SECTION: Post Source Actions {{{1
 call nerdtree#postSourceActions()
 
diff --git a/syntax/nerdtree.vim b/syntax/nerdtree.vim
@@ -23,17 +23,18 @@ syn match NERDTreeLinkDir #.*/ ->#me=e-3 containedin=NERDTreeDir
 syn match NERDTreeDirSlash #/# containedin=NERDTreeDir
 
 if g:NERDTreeDirArrows
-    syn match NERDTreeClosable #▾# containedin=NERDTreeDir,NERDTreeFile
-    syn match NERDTreeOpenable #▸# containedin=NERDTreeDir,NERDTreeFile
+    exec 'syn match NERDTreeClosable #'.escape(g:NERDTreeDirArrowCollapsible, '~').'# containedin=NERDTreeDir,NERDTreeFile'
+    exec 'syn match NERDTreeOpenable #'.escape(g:NERDTreeDirArrowExpandable, '~').'# containedin=NERDTreeDir,NERDTreeFile'
 
-    syn match NERDTreeDir #[^▾▸ ].*/#
+    let s:dirArrows = escape(g:NERDTreeDirArrowCollapsible, '~').escape(g:NERDTreeDirArrowExpandable, '~')
+    exec 'syn match NERDTreeDir #[^'.s:dirArrows.' ].*/#'
     syn match NERDTreeExecFile  #^ .*\*\($\| \)# contains=NERDTreeRO,NERDTreeBookmark
-    syn match NERDTreeFile  #^[^"\.▾▸] *[^▾▸]*# contains=NERDTreeLink,NERDTreeRO,NERDTreeBookmark,NERDTreeExecFile
+    exec 'syn match NERDTreeFile  #^[^"\.'.s:dirArrows.'] *[^'.s:dirArrows.']*# contains=NERDTreeLink,NERDTreeRO,NERDTreeBookmark,NERDTreeExecFile'
 
     "highlighting for readonly files
     syn match NERDTreeRO # *\zs.*\ze \[RO\]# contains=NERDTreeIgnore,NERDTreeBookmark,NERDTreeFile
 
-    syn match NERDTreeFlags #^ *\zs\[.\]# containedin=NERDTreeFile
+    syn match NERDTreeFlags #^ *\zs\[.\]# containedin=NERDTreeFile,NERDTreeExecFile
     syn match NERDTreeFlags #\[.\]# containedin=NERDTreeDir
 else
     "highlighting for the ~/+ symbols for the directory nodes