From d2989eb3e0b8d8faa2fd778778fa418a4c51f15e Mon Sep 17 00:00:00 2001 From: Martin Grenfell Date: Sun, 29 Jun 2008 00:23:02 +1200 Subject: [PATCH] huge refactor, add bookmark class --- plugin/NERD_tree.vim | 340 +++++++++++++++++++++++-------------------- 1 file changed, 182 insertions(+), 158 deletions(-) diff --git a/plugin/NERD_tree.vim b/plugin/NERD_tree.vim index 8427a6e..758ac98 100644 --- a/plugin/NERD_tree.vim +++ b/plugin/NERD_tree.vim @@ -54,7 +54,7 @@ call s:InitVariable("g:NERDTreeBookmarksFile", expand('$HOME') . '/.NERDTreeBook call s:InitVariable("g:NERDTreeMouseMode", 1) call s:InitVariable("g:NERDTreeNotificationThreshold", 100) call s:InitVariable("g:NERDTreeQuitOnOpen", 0) -call s:InitVariable("g:NERDTreeShowBookmarks", 0) +call s:InitVariable("g:NERDTreeShowBookmarks", 1) call s:InitVariable("g:NERDTreeShowFiles", 1) call s:InitVariable("g:NERDTreeShowHidden", 0) call s:InitVariable("g:NERDTreeShowLineNumbers", 0) @@ -143,22 +143,156 @@ endif command! -n=? -complete=dir NERDTree :call s:InitNerdTree('') command! -n=? -complete=dir NERDTreeToggle :call s:Toggle('') command! -n=0 NERDTreeClose :call s:CloseTreeIfOpen() -command! -n=1 -complete=customlist,s:FindBookmarks NERDTreeFromBookmark call s:InitNerdTree('') +command! -n=1 -complete=customlist,s:CompleteBookmarks NERDTreeFromBookmark call s:InitNerdTree('') " SECTION: Auto commands {{{1 "============================================================ "Save the cursor position whenever we close the nerd tree exec "autocmd BufWinLeave *". s:NERDTreeWinName ."* :call SaveScreenState()" "cache bookmarks when vim loads -autocmd VimEnter * call ReadBookmarks() +autocmd VimEnter * call s:oBookmark.CacheBookmarks() "SECTION: Classes {{{1 "============================================================ +"CLASS: oBookmark {{{2 +"============================================================ +let s:oBookmark = {} +"FUNCTION: oBookmark.AddBookmark(name, path) {{{3 +function! s:oBookmark.AddBookmark(name, path) dict + for i in s:oBookmark.Bookmarks() + if i.name == a:name + let i.path = a:path + return + endif + endfor + call add(s:oBookmark.Bookmarks(), s:oBookmark.New(a:name, a:path)) +endfunction +"FUNCTION: oBookmark.CacheBookmarks() {{{3 +function! s:oBookmark.CacheBookmarks() dict + if filereadable(g:NERDTreeBookmarksFile) + let bookmarks = [] + let bookmarkStrings = readfile(g:NERDTreeBookmarksFile) + let invalidBookmarksFound = 0 + for i in bookmarkStrings + let name = substitute(i, '^\(\w\{-}\) .*$', '\1', '') + let path = substitute(i, '^\w\{-} \(.*\)$', '\1', '') + + try + let bookmark = s:oBookmark.New(name, s:oPath.New(path)) + catch /NERDTree.Path.InvalidArguments/ + let invalidBookmarksFound += 1 + endtry + call add(bookmarks, bookmark) + endfor + let g:NERDTreeBookmarks = bookmarks + if invalidBookmarksFound + call s:Echo(invalidBookmarksFound . " invalid bookmarks were read and discarded") + call s:WriteBookmarks() + endif + endif +endfunction +"FUNCTION: oBookmark.New(name, path) {{{3 +function! s:oBookmark.New(name, path) dict + if a:name !~ '^[0-9a-zA-Z_]*$' + throw "NERDTree.IllegalBookmarkName illegal name:" a:name + endif + + let newBookmark = copy(self) + let newBookmark.name = a:name + let newBookmark.path = a:path + return newBookmark +endfunction +" Function: oBookmark.Write() {{{3 +function! s:oBookmark.Write() dict + let bookmarkStrings = [] + for i in s:oBookmark.Bookmarks() + call add(bookmarkStrings, i.name . ' ' . i.path.StrForOS(0)) + endfor + call writefile(bookmarkStrings, g:NERDTreeBookmarksFile) +endfunction +" Function: oBookmark.Bookmarks() {{{3 +function! s:oBookmark.Bookmarks() dict + if !exists("g:NERDTreeBookmarks") + let g:NERDTreeBookmarks = [] + endif + return g:NERDTreeBookmarks +endfunction +" Function: oBookmark.BookmarkNames() {{{3 +function! s:oBookmark.BookmarkNames() dict + let names = [] + for i in s:oBookmark.Bookmarks() + call add(names, i.name) + endfor + return names +endfunction +" Function: oBookmark.BookmarkFor(name) {{{3 +function! s:oBookmark.BookmarkFor(name) dict + for i in s:oBookmark.Bookmarks() + if i.name == a:name + return i + endif + endfor + return {} +endfunction +"FUNCTION: oBookmark.ClearAll() {{{3 +function! s:oBookmark.ClearAll() dict + for i in s:oBookmark.Bookmarks() + call i.Delete() + endfor + call s:oBookmark.Write() +endfunction +"FUNCTION: oBookmark.GetNode(searchFromAbsoluteRoot) {{{3 +"get the treenode this bookmark +" +"Args: +"searchFromAbsoluteRoot: specifies wheather we should search from the current +"tree root, or the highest cached node +function! s:oBookmark.GetNode(searchFromAbsoluteRoot) dict + let searchRoot = a:searchFromAbsoluteRoot ? s:AbsoluteTreeRoot() : t:NERDTreeRoot + let targetNode = searchRoot.FindNode(self.path) + if empty(targetNode) + throw "NERDTree.BookmarkNodeNotFound no node was found for bookmark: " . self.name + endif + return targetNode +endfunction +"FUNCTION: oBookmark.GetNodeForName(name, searchFromAbsoluteRoot) {{{3 +function! s:oBookmark.GetNodeForName(name, searchFromAbsoluteRoot) dict + let bookmark = s:oBookmark.BookmarkFor(a:name) + if bookmark == {} + throw "NERDTree.BookmarkNotFound no node was found for bookmark: " . a:name + endif + return bookmark.GetNode(a:searchFromAbsoluteRoot) +endfunction +"FUNCTION: oBookmark.Delete() {{{3 +function! s:oBookmark.Delete() dict + let node = {} + try + let node = self.GetNode(1) + catch /NERDTree.BookmarkNodeNotFound/ + endtry + call remove(s:oBookmark.Bookmarks(), index(s:oBookmark.Bookmarks(), self)) + if !empty(node) + call node.path.CacheBookmarks() + endif +endfunction "CLASS: oTreeFileNode {{{2 "This class is the parent of the oTreeDirNode class and constitures the "'Component' part of the composite design pattern between the treenode "classes. "============================================================ let s:oTreeFileNode = {} +"FUNCTION: oTreeFileNode.Bookmark(name) {{{3 +"bookmark this node with a:name +function! s:oTreeFileNode.Bookmark(name) dict + try + let oldMarkedNode = s:oBookmark.GetNodeForName(a:name, 1) + call oldMarkedNode.path.UncacheBookmark(a:name) + catch /NERDTree.Bookmark\(DoesntExist\|NotFound\)/ + endtry + + call s:oBookmark.AddBookmark(a:name, self.path) + call self.path.CacheBookmarks() + call s:oBookmark.Write() +endfunction "FUNCTION: oTreeFileNode.CacheParent {{{3 "initializes self.parent if it isnt already function! s:oTreeFileNode.CacheParent() dict @@ -184,13 +318,12 @@ endfunction "FUNCTION: oTreeFileNode.ClearBookmarks() {{{3 function! s:oTreeFileNode.ClearBookmarks() dict - let bookmarks = s:GetBookmarks() - for i in keys(bookmarks) - if bookmarks[i].Equals(self.path) - call remove(bookmarks, i) + for i in s:oBookmark.Bookmarks() + if i.path.Equals(self.path) + call i.Delete() end endfor - call self.path.CacheBookmarkNames() + call self.path.CacheBookmarks() endfunction "FUNCTION: oTreeFileNode.Copy(dest) {{{3 function! s:oTreeFileNode.Copy(dest) dict @@ -816,18 +949,17 @@ endfunction let s:oPath = {} "FUNCTION: oPath.BookmarkNames() {{{3 function! s:oPath.BookmarkNames() dict - if !exists("self.bookmarkNames") - call self.CacheBookmarkNames() + if !exists("self.bookmark") + call self.CacheBookmarks() endif return self.bookmarkNames endfunction -"FUNCTION: oPath.CacheBookmarkNames() {{{3 -function! s:oPath.CacheBookmarkNames() dict +"FUNCTION: oPath.CacheBookmarks() {{{3 +function! s:oPath.CacheBookmarks() dict let self.bookmarkNames = [] - let bookmarks = s:GetBookmarks() - for k in keys(bookmarks) - if bookmarks[k].Equals(self) - call add(self.bookmarkNames, k) + for i in s:oBookmark.Bookmarks() + if i.path.Equals(self) + call add(self.bookmarkNames, i.name) endif endfor return self.bookmarkNames @@ -1193,7 +1325,7 @@ endfunction "FUNCTION: oPath.Refresh() {{{3 function! s:oPath.Refresh() dict call self.ReadInfoFromDisk(self.StrForOS(0)) - call self.CacheBookmarkNames() + call self.CacheBookmarks() endfunction "FUNCTION: oPath.Rename() {{{3 @@ -1266,9 +1398,8 @@ function! s:oPath.StrDisplay() dict let toReturn = toReturn . '*' endif - let bookmarks = self.BookmarkNames() - if !empty(bookmarks) - let toReturn .= ' {' . join(bookmarks, ',') . '}' + if !empty(self.BookmarkNames()) + let toReturn .= ' {' . join(self.BookmarkNames(), ',') . '}' endif if self.isSymLink @@ -1421,42 +1552,10 @@ function! s:BufInWindows(bnum) return cnt endfunction " >>> -"FUNCTION: s:ClearAllBookmarks() {{{2 -"delete all bookmarks -function! s:ClearAllBookmarks() - for name in keys(g:NERDTreeBookmarks) - let node = {} - try - let node = s:GetNodeForBookmark(name, 1) - catch /NERDTree/ - endtry - call remove(g:NERDTreeBookmarks, name) - if !empty(node) - call node.path.CacheBookmarkNames() - endif - endfor - call s:WriteBookmarks() -endfunction -"FUNCTION: s:GetNodeForBookmark(name, searchFromAbsoluteRoot) {{{2 -"get the treenode for the bookmark with the given name -" -"Args: -"name: name of bookmark -"searchFromAbsoluteRoot: specifies wheather we should search from the current -"tree root, or the highest cached node -function! s:GetNodeForBookmark(name, searchFromAbsoluteRoot) - try - let bookmark = s:GetBookmarks()[a:name] - catch /E716/ "key not in dictionary error - throw "NERDTree.BookmarkDoesntExist no bookmark found with name: " . a:name - endtry - - let searchRoot = a:searchFromAbsoluteRoot ? s:AbsoluteTreeRoot() : t:NERDTreeRoot - let targetNode = searchRoot.FindNode(bookmark) - if empty(targetNode) - throw "NERDTree.BookmarkNotFound no node was found for bookmark: " . a:name - endif - return targetNode +" FUNCTION: s:CompleteBookmarks(A,L,P) {{{2 +" completion function for the bookmark commands +function! s:CompleteBookmarks(A,L,P) + return filter(s:oBookmark.BookmarkNames(), 'v:val =~ "^' . a:A . '"') endfunction "FUNCTION: s:InitNerdTree(name) {{{2 "Initialise the nerd tree for this tab. The tree will start in either the @@ -1466,8 +1565,8 @@ endfunction "name: the name of a bookmark or a directory function! s:InitNerdTree(name) let path = {} - if count(keys(s:GetBookmarks()), a:name) - let path = s:GetBookmarks()[a:name] + if s:oBookmark.BookmarkFor(a:name) != {} + let path = s:oBookmark.BookmarkFor(a:name).path else let dir = a:name == '' ? expand('%:p:h') : a:name let dir = resolve(dir) @@ -1505,43 +1604,11 @@ function! s:InitNerdTree(name) call s:RenderView() call s:PutCursorOnNode(t:NERDTreeRoot, 0, 0) endfunction -" Function: s:ReadBookmarks() {{{2 -function! s:ReadBookmarks() - if filereadable(g:NERDTreeBookmarksFile) - let bookmarks = s:GetBookmarks() - let bookmarkStrings = readfile(g:NERDTreeBookmarksFile) - let invalidBookmarksFound = 0 - for i in bookmarkStrings - let key = substitute(i, '^\(\w\{-}\) .*$', '\1', '') - let path = substitute(i, '^\w\{-} \(.*\)$', '\1', '') - - try - let bookmarks[key] = s:oPath.New(path) - catch /NERDTree.Path.InvalidArguments/ - let invalidBookmarksFound += 1 - endtry - endfor - if invalidBookmarksFound - call s:Echo(invalidBookmarksFound . " invalid bookmarks were read and discarded") - call s:WriteBookmarks() - endif - endif -endfunction " Function: s:TreeExistsForTab() {{{2 " Returns 1 if a nerd tree root exists in the current tab function! s:TreeExistsForTab() return exists("t:NERDTreeRoot") endfunction -" Function: s:WriteBookmarks() {{{2 -function! s:WriteBookmarks() - let bookmarks = s:GetBookmarks() - let bookmarkStrings = [] - for k in keys(bookmarks) - call add(bookmarkStrings, k . ' ' . bookmarks[k].StrForOS(0)) - endfor - call writefile(bookmarkStrings, g:NERDTreeBookmarksFile) -endfunction - " SECTION: Public Functions {{{1 "============================================================ "Returns the node that the cursor is currently on. @@ -1848,12 +1915,6 @@ function! s:EchoError(msg) call s:Echo(a:msg) echohl normal endfunction -" FUNCTION: s:FindBookmarks(A,L,P) {{{2 -" completion function for the bookmark commands -function! s:FindBookmarks(A,L,P) - let keys = keys(s:GetBookmarks()) - return filter(keys, 'v:val =~ "^' . a:A . '"') -endfunction "FUNCTION: s:FindNodeLineNumber(treenode){{{2 "Finds the line number for the given tree node " @@ -1916,14 +1977,6 @@ function! s:FindRootNodeLineNumber() return rootLine endfunction -" FUNCTION: s:GetBookmarks(name) {{{2 -" getter/lazy initializer for the g:NERDTreeBookmarks hash -function! s:GetBookmarks() - if !exists("g:NERDTreeBookmarks") - let g:NERDTreeBookmarks = {} - endif - return g:NERDTreeBookmarks -endfunction "FUNCTION: s:GetPath(ln) {{{2 "Gets the full path to the node that is rendered on the given line number " @@ -1999,7 +2052,7 @@ function! s:GetSelectedBookmark() let line = getline(".") let name = substitute(line, '^>\(.\{-}\) \[.*\]$', '\1', '') if name != line - return name + return s:oBookmark.BookmarkFor(name) endif endfunction @@ -2293,23 +2346,20 @@ function! s:RenderBookmarks() call setline(line(".")+1, ">----------Bookmarks----------") call cursor(line(".")+1, col(".")) - let bookmarks = s:GetBookmarks() - for i in keys(bookmarks) + for i in s:oBookmark.Bookmarks() - let pathStrMaxLen = 26 - len(i) - let pathStr = bookmarks[i].StrForOS(0) + let pathStrMaxLen = 26 - len(i.name) + let pathStr = i.path.StrForOS(0) if len(pathStr) > pathStrMaxLen let pathStr = '<' . strpart(pathStr, len(pathStr) - pathStrMaxLen) endif - "call setline(line(".")+1,'>' . i . ' [' . bookmarks[i].StrForOS(0) . ']') - call setline(line(".")+1,'>' . i . ' [' . pathStr . ']') + call setline(line(".")+1,'>' . i.name . ' [' . pathStr . ']') call cursor(line(".")+1, col(".")) endfor call setline(line(".")+1, '') call cursor(line(".")+1, col(".")) - endfunction "FUNCTION: s:RenderView {{{2 "The entry function for rendering the tree. Renders the root then calls @@ -2618,8 +2668,8 @@ function! s:ActivateNode() endif else let bookmark = s:GetSelectedBookmark() - if bookmark != "" - call s:BookmarkToRoot(bookmark) + if !empty(bookmark) + call s:BookmarkToRoot(bookmark.name) endif endif endfunction @@ -2677,36 +2727,21 @@ function! s:BindMappings() exec "nnoremap ". g:NERDTreeMapOpenExpl ." :call OpenExplorer()" command! -buffer -nargs=1 Bookmark :call BookmarkNode('') - command! -buffer -complete=customlist,s:FindBookmarks -nargs=1 RevealBookmark :call RevealBookmark('') - command! -buffer -complete=customlist,s:FindBookmarks -nargs=1 OpenBookmark :call OpenBookmark('') - command! -buffer -complete=customlist,s:FindBookmarks -nargs=* ClearBookmarks call ClearBookmarks('') - command! -buffer -complete=customlist,s:FindBookmarks -nargs=+ BookmarkToRoot call BookmarkToRoot('') - command! -buffer -nargs=0 ClearAllBookmarks call ClearAllBookmarks() call RenderView() - command! -buffer -nargs=0 ReadBookmarks call ReadBookmarks() call RenderView() - command! -buffer -nargs=0 WriteBookmarks call WriteBookmarks() + command! -buffer -complete=customlist,s:CompleteBookmarks -nargs=1 RevealBookmark :call RevealBookmark('') + command! -buffer -complete=customlist,s:CompleteBookmarks -nargs=1 OpenBookmark :call OpenBookmark('') + command! -buffer -complete=customlist,s:CompleteBookmarks -nargs=* ClearBookmarks call ClearBookmarks('') + command! -buffer -complete=customlist,s:CompleteBookmarks -nargs=+ BookmarkToRoot call BookmarkToRoot('') + command! -buffer -nargs=0 ClearAllBookmarks call s:oBookmark.ClearAll() call RenderView() + command! -buffer -nargs=0 ReadBookmarks call s:oBookmark.CacheBookmarks() call RenderView() + command! -buffer -nargs=0 WriteBookmarks call s:oBookmark.Write() endfunction " FUNCTION: s:BookmarkNode(name) {{{2 " Associate the current node with the given name function! s:BookmarkNode(name) - if a:name !~ '^[0-9a-zA-Z_]*$' - call s:Echo("Bookmarks must be named using numbers, letters and underscores only") - return - endif - let currentNode = s:GetSelectedNode() if currentNode != {} - - try - let oldMarkedNode = s:GetNodeForBookmark(a:name, 1) - call oldMarkedNode.path.UncacheBookmark(a:name) - catch /NERDTree.Bookmark\(DoesntExist\|NotFound\)/ - endtry - - let bookmarks = s:GetBookmarks() - let bookmarks[a:name] = currentNode.path - call currentNode.path.CacheBookmarkNames() - call s:WriteBookmarks() + call currentNode.Bookmark(a:name) call s:RenderView() else call s:Echo("select a node first") @@ -2716,10 +2751,9 @@ endfunction " Make the node for the given bookmark the new tree root function! s:BookmarkToRoot(name) try - let targetNode = s:GetNodeForBookmark(a:name, 1) - catch /NERDTree.BookmarkNotFound/ - let bookmarks = s:GetBookmarks() - let targetNode = s:oTreeFileNode.New(bookmarks[a:name]) + let targetNode = s:oBookmark.GetNodeForName(a:name, 1) + catch /NERDTree.BookmarkNodeNotFound/ + let targetNode = s:oTreeFileNode.New(s:oBookmark.BookmarkFor(a:name).path) endtry call targetNode.MakeRoot() call s:RenderView() @@ -2785,7 +2819,6 @@ endfunction " FUNCTION: s:ClearBookmarks(bookmarks) {{{2 function! s:ClearBookmarks(bookmarks) - let bookmarks = s:GetBookmarks() if a:bookmarks == '' let currentNode = s:GetSelectedNode() if currentNode != {} @@ -2793,20 +2826,11 @@ function! s:ClearBookmarks(bookmarks) endif else for name in split(a:bookmarks, ' ') - if count(keys(bookmarks), name) - let node = {} - try - let node = s:GetNodeForBookmark(name, 1) - catch /NERDTree/ - endtry - call remove(bookmarks, name) - if !empty(node) - call node.path.CacheBookmarkNames() - endif - endif + let bookmark = s:oBookmark.BookmarkFor(name) + call bookmark.Delete() endfor endif - call s:WriteBookmarks() + call s:oBookmark.Write() call s:RenderView() endfunction " FUNCTION: s:CloseChildren() {{{2 @@ -3068,13 +3092,13 @@ endfunction " put the cursor on the given bookmark and, if its a file, open it function! s:OpenBookmark(name) try - let targetNode = s:GetNodeForBookmark(a:name, 0) + let targetNode = s:oBookmark.GetNodeForName(a:name, 0) call s:PutCursorOnNode(targetNode, 0, 1) redraw! catch /NERDTree.BookmarkNotFound/ call s:Echo("note - target node is not cached") - let bookmarks = s:GetBookmarks() - let targetNode = s:oTreeFileNode.New(bookmarks[a:name]) + let bookmark = s:oBookmark.BookmarkFor(a:name) + let targetNode = s:oTreeFileNode.New(bookmark.path) endtry if targetNode.path.isDirectory call s:OpenExplorerFor(targetNode) @@ -3163,7 +3187,7 @@ endfunction " put the cursor on the node associate with the given name function! s:RevealBookmark(name) try - let targetNode = s:GetNodeForBookmark(a:name, 0) + let targetNode = s:oBookmark.GetNodeForName(a:name, 0) call s:PutCursorOnNode(targetNode, 0, 1) catch /NERDTree.BookmarkDoesntExist/ call s:Echo("Bookmark isnt cached under the current root")