nerdtree

A tree explorer plugin for vim.
Index Commits Files Refs
commit b7cdc191ca25aef5525a39acfdc938dee5a26674
parent 54fab2f2e55e9a413e2a1f5aec0f9129036d2168
Author: Martin Grenfell <martin.grenfell@gmail.com>
Date:   Thu,  5 Jan 2012 10:54:21 +0000

refactor the TreeFileNode*open* methods

Make these all go through .open() and pass in args to control the
behaviour. Deprecate the old `openSplit`, `openVSplit` and
`openInNewTab` methods and make them private.

This makes the API a lot cleaner - it was getting pretty messy in this
regard.

Diffstat:
Mplugin/NERD_tree.vim | 198++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------
1 file changed, 140 insertions(+), 58 deletions(-)
diff --git a/plugin/NERD_tree.vim b/plugin/NERD_tree.vim
@@ -905,12 +905,9 @@ endfunction
 "classes.
 "============================================================
 let s:TreeFileNode = {}
-"FUNCTION: TreeFileNode.activate(forceKeepWinOpen) {{{3
-function! s:TreeFileNode.activate(forceKeepWinOpen)
-    call self.open()
-    if !a:forceKeepWinOpen
-        call s:closeTreeIfQuitOnOpen()
-    end
+"FUNCTION: TreeFileNode.activate(...) {{{3
+function! s:TreeFileNode.activate(...)
+    call self.open(a:0 ? a:1 : {})
 endfunction
 "FUNCTION: TreeFileNode.bookmark(name) {{{3
 "bookmark this node with a:name
@@ -1216,45 +1213,82 @@ function! s:TreeFileNode.New(path)
 endfunction
 
 "FUNCTION: TreeFileNode.open() {{{3
-"Open the file represented by the given node in the current window, splitting
-"the window if needed
+"Args:
+"A dictionary containing the following keys (all optional):
+"  'split': 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
+"  'keepopen': dont close the tree window
+"  'preview': open the file, but keep the cursor in the tree win
 "
-"ARGS:
-"treenode: file node to open
-function! s:TreeFileNode.open()
+function! s:TreeFileNode.open(...)
+    let opts = a:0 ? a:1 : {}
+
+    let currentBuf = bufnr("")
+    let currentTab = tabpagenr()
+
+    if s:has_opt(opts, 'reuse') && self._putCursorInBufWin()
+        return
+    endif
+
+    if has_key(opts, 'split')
+        if opts['split'] == 'v'
+            call self._openVSplit()
+        elseif opts['split'] == 'h'
+            call self._openSplit()
+        else
+            call self._openInNewTab(opts)
+        endif
+    else
+        call self._open()
+    endif
+
+    if !s:has_opt(opts, 'forceKeepWinOpen')
+        call s:closeTreeIfQuitOnOpen()
+    endif
+
+    if s:has_opt(opts, 'preview')
+        call s:exec('normal ' . currentTab . 'gt')
+        call s:exec(bufwinnr(currentBuf) . 'wincmd w')
+    endif
+endfunction
+
+"FUNCTION: TreeFileNode._open() {{{3
+function! s:TreeFileNode._open()
+
     if b:NERDTreeType ==# "secondary"
         exec 'edit ' . self.path.str({'format': 'Edit'})
         return
     endif
 
-    "if the file is already open in this tab then just stick the cursor in it
-    let winnr = bufwinnr('^' . self.path.str() . '$')
-    if winnr != -1
-        call s:exec(winnr . "wincmd w")
-
+    if !s:isWindowUsable(winnr("#")) && s:firstUsableWindow() ==# -1
+        call self._openSplit()
     else
-        if !s:isWindowUsable(winnr("#")) && s:firstUsableWindow() ==# -1
-            call self.openSplit()
-        else
-            try
-                if !s:isWindowUsable(winnr("#"))
-                    call s:exec(s:firstUsableWindow() . "wincmd w")
-                else
-                    call s:exec('wincmd p')
-                endif
-                exec ("edit " . self.path.str({'format': 'Edit'}))
-            catch /^Vim\%((\a\+)\)\=:E37/
-                call s:putCursorInTreeWin()
-                throw "NERDTree.FileAlreadyOpenAndModifiedError: ". self.path.str() ." is already open and modified."
-            catch /^Vim\%((\a\+)\)\=:/
-                echo v:exception
-            endtry
-        endif
+        try
+            if !s:isWindowUsable(winnr("#"))
+                call s:exec(s:firstUsableWindow() . "wincmd w")
+            else
+                call s:exec('wincmd p')
+            endif
+            exec ("edit " . self.path.str({'format': 'Edit'}))
+        catch /^Vim\%((\a\+)\)\=:E37/
+            call s:putCursorInTreeWin()
+            throw "NERDTree.FileAlreadyOpenAndModifiedError: ". self.path.str() ." is already open and modified."
+        catch /^Vim\%((\a\+)\)\=:/
+            echo v:exception
+        endtry
     endif
 endfunction
 "FUNCTION: TreeFileNode.openSplit() {{{3
 "Open this node in a new window
 function! s:TreeFileNode.openSplit()
+    call s:deprecated('TreeFileNode.openSplit', 'is deprecated, use .open() instead.')
+    call self.open({'split': 'h'})
+endfunction
+"FUNCTION: TreeFileNode._openSplit() {{{3
+"Open this node in a new window
+function! s:TreeFileNode._openSplit()
 
     if b:NERDTreeType ==# "secondary"
         exec "split " . self.path.str({'format': 'Edit'})
@@ -1321,6 +1355,12 @@ endfunction
 "FUNCTION: TreeFileNode.openVSplit() {{{3
 "Open this node in a new vertical window
 function! s:TreeFileNode.openVSplit()
+    call s:deprecated('TreeFileNode.openVSplit', 'is deprecated, use .open() instead.')
+    call self.open({'split': 'v'})
+endfunction
+"FUNCTION: TreeFileNode._openVSplit() {{{3
+"Open this node in a new vertical window
+function! s:TreeFileNode._openVSplit()
     if b:NERDTreeType ==# "secondary"
         exec "vnew " . self.path.str({'format': 'Edit'})
         return
@@ -1341,19 +1381,42 @@ function! s:TreeFileNode.openVSplit()
 endfunction
 "FUNCTION: TreeFileNode.openInNewTab(options) {{{3
 function! s:TreeFileNode.openInNewTab(options)
+    echomsg 'TreeFileNode.openInNewTab is deprecated'
+    call self.open(extend({'split': 't'}, a:options))
+endfunction
+"FUNCTION: TreeFileNode._openInNewTab(options) {{{3
+function! s:TreeFileNode._openInNewTab(options)
     let currentTab = tabpagenr()
-
-    if !s:has_opt(a:options, 'keepTreeOpen')
-        call s:closeTreeIfQuitOnOpen()
-    endif
-
     exec "tabedit " . self.path.str({'format': 'Edit'})
 
     if s:has_opt(a:options, 'stayInCurrentTab')
         exec "tabnext " . currentTab
     endif
-
 endfunction
+"FUNCTION: TreeFileNode._putCursorInBufWin(){{{3
+"put the cursor in the first window we find for this file
+"
+"return 1 if we were successful
+function! s:TreeFileNode._putCursorInBufWin(...)
+    "check the current tab for the window
+    let winnr = bufwinnr('^' . self.path.str() . '$')
+    if winnr != -1
+        call s:exec(winnr . "wincmd w")
+        return 1
+    else
+        "check other tabs
+        let tabnr = self.path.tabnr()
+        if tabnr
+            call s:exec('normal! ' . tabnr . 'gt')
+            let winnr = bufwinnr('^' . self.path.str() . '$')
+            call s:exec(winnr . "wincmd w")
+            return 1
+        endif
+    endif
+    return 0
+endfunction
+
+
 "FUNCTION: TreeFileNode.putCursorHere(isJump, recurseUpward){{{3
 "Places the cursor on the line number this node is rendered on
 "
@@ -1778,7 +1841,7 @@ endfunction
 "
 "Return: the number of child nodes read
 unlet s:TreeDirNode.open
-function! s:TreeDirNode.open()
+function! s:TreeDirNode.open(...)
     let self.isOpen = 1
     if self.children ==# []
         return self._initChildren(0)
@@ -2603,6 +2666,21 @@ function! s:Path.strTrunk()
     return self.drive . '/' . join(self.pathSegments[0:-2], '/')
 endfunction
 
+" FUNCTION: Path.tabnr() {{{3
+" return the number of the first tab that is displaying this file
+"
+" return 0 if no tab was found
+function! s:Path.tabnr()
+    let str = self.str()
+    for t in range(tabpagenr('$'))
+        for b in tabpagebuflist(t+1)
+            if str == expand('#' . b . ':p')
+                return t+1
+            endif
+        endfor
+    endfor
+    return 0
+endfunction
 "FUNCTION: Path.WinToUnixPath(pathstr){{{3
 "Takes in a windows path and returns the unix equiv
 "
@@ -2669,6 +2747,20 @@ endfunction
 function! s:completeBookmarks(A,L,P)
     return filter(s:Bookmark.BookmarkNames(), 'v:val =~# "^' . a:A . '"')
 endfunction
+" FUNCTION: s:deprecated(func, [msg]) {{{2
+" Issue a deprecation warning for a:func. If a second arg is given, use this
+" as the deprecation message
+function! s: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: s:exec(cmd) {{{2
 " same as :exec cmd  but eventignore=all is set for the duration
 function! s:exec(cmd)
@@ -3388,16 +3480,6 @@ function! s:openEntrySplit(vertical, forceKeepWindowOpen)
     endif
 endfunction
 
-"FUNCTION: s:previewNode(node, openNewWin) {{{2
-function! s:previewNode(node, openNewWin)
-    let currentBuf = bufnr("")
-    if a:openNewWin > 0
-        call s:openEntrySplit(a:openNewWin ==# 2,1)
-    else
-        call s:activateNode(a:node)
-    end
-    call s:exec(bufwinnr(currentBuf) . "wincmd w")
-endfunction
 "FUNCTION: s:promptToDelBuffer(bufnum, msg){{{2
 "prints out the given msg and, if the user responds by pushing 'y' then the
 "buffer with the given bufnum is deleted
@@ -3688,7 +3770,7 @@ endfunction
 "FUNCTION: s:activateNode() {{{2
 "handle the user activating a tree node
 function! s:activateNode(node)
-    call a:node.activate(0)
+    call a:node.activate({'reuse': 1})
 endfunction
 
 "FUNCTION: s:activateBookmark() {{{2
@@ -3994,12 +4076,12 @@ endfunction
 
 " FUNCTION: s:openHSplit(node) {{{2
 function! s:openHSplit(node)
-    call a:node.openSplit()
+    call a:node.activate({'split': 'h'})
 endfunction
 
 " FUNCTION: s:openVSplit(node) {{{2
 function! s:openVSplit(node)
-    call a:node.openVSplit()
+    call a:node.activate({'split': 'v'})
 endfunction
 
 " FUNCTION: s:openExplorer(node) {{{2
@@ -4009,12 +4091,12 @@ endfunction
 
 " FUNCTION: s:openInNewTab(target) {{{2
 function! s:openInNewTab(target)
-    call a:target.openInNewTab({})
+    call a:target.activate({'split': 't'})
 endfunction
 
 " FUNCTION: s:openInNewTabSilent(target) {{{2
 function! s:openInNewTabSilent(target)
-    call a:target.openInNewTab({'stayInCurrentTab': 1})
+    call a:target.activate({'split': 't', 'stayInCurrentTab': 1})
 endfunction
 
 " FUNCTION: s:openNodeRecursively(node) {{{2
@@ -4028,17 +4110,17 @@ endfunction
 
 "FUNCTION: s:previewNodeCurrent(node) {{{2
 function! s:previewNodeCurrent(node)
-    call s:previewNode(a:node, 0)
+    call a:node.open({'preview': 1})
 endfunction
 
 "FUNCTION: s:previewNodeHSplit(node) {{{2
 function! s:previewNodeHSplit(node)
-    call s:previewNode(a:node, 1)
+    call a:node.open({'preview': 1, 'split': 'h'})
 endfunction
 
 "FUNCTION: s:previewNodeVSplit(node) {{{2
 function! s:previewNodeVSplit(node)
-    call s:previewNode(a:node, 2)
+    call a:node.open({'preview': 1, 'split': 'v'})
 endfunction