nerdtree

A tree explorer plugin for vim.
Index Commits Files Refs
commit d2989eb3e0b8d8faa2fd778778fa418a4c51f15e
parent 73be034d5ed3ce0ee2230def7c1f389147a64c2a
Author: Martin Grenfell <martin_grenfell@msn.com>
Date:   Sun, 29 Jun 2008 00:23:02 +1200

huge refactor, add bookmark class

Diffstat:
Mplugin/NERD_tree.vim | 340++++++++++++++++++++++++++++++++++++++++++-------------------------------------
1 file changed, 182 insertions(+), 158 deletions(-)
diff --git 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('<args>')
 command! -n=? -complete=dir NERDTreeToggle :call s:Toggle('<args>')
 command! -n=0 NERDTreeClose :call s:CloseTreeIfOpen()
-command! -n=1 -complete=customlist,s:FindBookmarks NERDTreeFromBookmark call s:InitNerdTree('<args>')
+command! -n=1 -complete=customlist,s:CompleteBookmarks NERDTreeFromBookmark call s:InitNerdTree('<args>')
 " SECTION: Auto commands {{{1
 "============================================================
 "Save the cursor position whenever we close the nerd tree
 exec "autocmd BufWinLeave *". s:NERDTreeWinName ."* :call <SID>SaveScreenState()"
 "cache bookmarks when vim loads
-autocmd VimEnter * call <SID>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 <silent> <buffer> ". g:NERDTreeMapOpenExpl ." :call <SID>OpenExplorer()<cr>"
 
     command! -buffer -nargs=1 Bookmark :call <SID>BookmarkNode('<args>')
-    command! -buffer -complete=customlist,s:FindBookmarks -nargs=1 RevealBookmark :call <SID>RevealBookmark('<args>')
-    command! -buffer -complete=customlist,s:FindBookmarks -nargs=1 OpenBookmark :call <SID>OpenBookmark('<args>')
-    command! -buffer -complete=customlist,s:FindBookmarks -nargs=* ClearBookmarks call <SID>ClearBookmarks('<args>')
-    command! -buffer -complete=customlist,s:FindBookmarks -nargs=+ BookmarkToRoot call <SID>BookmarkToRoot('<args>')
-    command! -buffer -nargs=0 ClearAllBookmarks call <SID>ClearAllBookmarks() <bar> call <SID>RenderView()
-    command! -buffer -nargs=0 ReadBookmarks call <SID>ReadBookmarks() <bar> call <SID>RenderView()
-    command! -buffer -nargs=0 WriteBookmarks call <SID>WriteBookmarks()
+    command! -buffer -complete=customlist,s:CompleteBookmarks -nargs=1 RevealBookmark :call <SID>RevealBookmark('<args>')
+    command! -buffer -complete=customlist,s:CompleteBookmarks -nargs=1 OpenBookmark :call <SID>OpenBookmark('<args>')
+    command! -buffer -complete=customlist,s:CompleteBookmarks -nargs=* ClearBookmarks call <SID>ClearBookmarks('<args>')
+    command! -buffer -complete=customlist,s:CompleteBookmarks -nargs=+ BookmarkToRoot call <SID>BookmarkToRoot('<args>')
+    command! -buffer -nargs=0 ClearAllBookmarks call s:oBookmark.ClearAll() <bar> call <SID>RenderView()
+    command! -buffer -nargs=0 ReadBookmarks call s:oBookmark.CacheBookmarks() <bar> call <SID>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")