From b7cdc191ca25aef5525a39acfdc938dee5a26674 Mon Sep 17 00:00:00 2001 From: Martin Grenfell Date: Thu, 5 Jan 2012 10:54:21 +0000 Subject: [PATCH] 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. --- plugin/NERD_tree.vim | 198 ++++++++++++++++++++++++++++++------------- 1 file changed, 140 insertions(+), 58 deletions(-) diff --git a/plugin/NERD_tree.vim b/plugin/NERD_tree.vim index b1a6445..74cb0ca 100644 --- 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