nerdtree

A tree explorer plugin for vim.
Index Commits Files Refs
commit a7428eba38fcd23a50f1cf5c26938c68ffd62673
parent d162c08fd7fa618d0f576a02134a54799adbc772
Author: Martin Grenfell <martin.grenfell@gmail.com>
Date:   Sat,  5 Jul 2014 00:29:45 +0100

add proof of concept for path flags API and add git modified flags

Diffstat:
Mautoload/nerdtree.vim | 4++++
Mlib/nerdtree/creator.vim | 6+++---
Mlib/nerdtree/path.vim | 32++++++++++++++++++++++++++++++--
Alib/nerdtree/refresh_notifier.vim | 21+++++++++++++++++++++
Mlib/nerdtree/tree_dir_node.vim | 1+
Anerdtree_plugin/git.vim | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 124 insertions(+), 5 deletions(-)
diff --git a/autoload/nerdtree.vim b/autoload/nerdtree.vim
@@ -238,6 +238,7 @@ function! nerdtree#loadClassFiles()
     runtime lib/nerdtree/tree_dir_node.vim
     runtime lib/nerdtree/opener.vim
     runtime lib/nerdtree/creator.vim
+    runtime lib/nerdtree/refresh_notifier.vim
 endfunction
 
 " FUNCTION: nerdtree#postSourceActions() {{{2
@@ -941,6 +942,9 @@ function! nerdtree#stripMarkupFromLine(line, removeLeadingSpaces)
     "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
diff --git a/lib/nerdtree/creator.vim b/lib/nerdtree/creator.vim
@@ -56,17 +56,17 @@ function! s:Creator.createPrimary(name)
         unlet t:NERDTreeBufName
     endif
 
+    call self._createTreeWin()
     let newRoot = g:NERDTreeDirNode.New(path)
+    let b:NERDTreeRoot = newRoot
+    let b:NERDTreeType = "primary"
     call newRoot.open()
 
-    call self._createTreeWin()
     let b:treeShowHelp = 0
     let b:NERDTreeIgnoreEnabled = 1
     let b:NERDTreeShowFiles = g:NERDTreeShowFiles
     let b:NERDTreeShowHidden = g:NERDTreeShowHidden
     let b:NERDTreeShowBookmarks = g:NERDTreeShowBookmarks
-    let b:NERDTreeRoot = newRoot
-    let b:NERDTreeType = "primary"
 
     call nerdtree#renderView()
     call b:NERDTreeRoot.putCursorHere(0, 0)
diff --git a/lib/nerdtree/path.vim b/lib/nerdtree/path.vim
@@ -24,6 +24,13 @@ function! s:Path.AbsolutePathFor(str)
     return toReturn
 endfunction
 
+"FUNCTION: Path.addFlag(flag) {{{1
+function! s:Path.addFlag(flag)
+    if index(self._flags, a:flag) == -1
+        call add(self._flags, a:flag)
+    endif
+endfunction
+
 "FUNCTION: Path.bookmarkNames() {{{1
 function! s:Path.bookmarkNames()
     if !exists("self._bookmarkNames")
@@ -33,8 +40,10 @@ function! s:Path.bookmarkNames()
 endfunction
 
 "FUNCTION: Path.cacheDisplayString() {{{1
-function! s:Path.cacheDisplayString()
-    let self.cachedDisplayString = self.getLastPathComponent(1)
+function! s:Path.cacheDisplayString() abort
+    let self.cachedDisplayString = self._flagString()
+
+    let self.cachedDisplayString .= self.getLastPathComponent(1)
 
     if self.isExecutable
         let self.cachedDisplayString = self.cachedDisplayString . '*'
@@ -350,6 +359,15 @@ function! s:Path.getSortOrderIndex()
     return s:NERDTreeSortStarIndex
 endfunction
 
+"FUNCTION: Path._flagString() {{{1
+function! s:Path._flagString()
+    if empty(self._flags)
+        return ""
+    endif
+
+    return '[' . join(self._flags, ',') . ']'
+endfunction
+
 "FUNCTION: Path.isUnixHiddenFile() {{{1
 "check for unix hidden files
 function! s:Path.isUnixHiddenFile()
@@ -460,6 +478,7 @@ function! s:Path.New(path)
     call newPath.readInfoFromDisk(s:Path.AbsolutePathFor(a:path))
 
     let newPath.cachedDisplayString = ""
+    let newPath._flags = []
 
     return newPath
 endfunction
@@ -480,6 +499,14 @@ function! s:Path.Resolve(path)
     return tmp =~# '.\+/$' ? substitute(tmp, '/$', '', '') : tmp
 endfunction
 
+"FUNCTION: Path.removeFlag(flag) {{{1
+function! s:Path.removeFlag(flag)
+    let i = index(self._flags, a:flag)
+    if i >= 0
+        call remove(self._flags, i)
+    endif
+endfunction
+
 "FUNCTION: Path.readInfoFromDisk(fullpath) {{{1
 "
 "
@@ -537,6 +564,7 @@ endfunction
 "FUNCTION: Path.refresh() {{{1
 function! s:Path.refresh()
     call self.readInfoFromDisk(self.str())
+    call g:NERDTreeRefreshNotifier.NotifyListeners(self)
     call self.cacheDisplayString()
 endfunction
 
diff --git a/lib/nerdtree/refresh_notifier.vim b/lib/nerdtree/refresh_notifier.vim
@@ -0,0 +1,21 @@
+"CLASS: RefreshNotifier
+"============================================================
+let s:RefreshNotifier = {}
+let g:NERDTreeRefreshNotifier = s:RefreshNotifier
+
+function! s:RefreshNotifier.AddListener(funcname)
+    call add(s:RefreshNotifier.GetListeners(), a:funcname)
+endfunction
+
+function! s:RefreshNotifier.NotifyListeners(refreshedPath)
+    for listener in s:RefreshNotifier.GetListeners()
+        call {listener}(a:refreshedPath)
+    endfor
+endfunction
+
+function! s:RefreshNotifier.GetListeners()
+    if !exists("s:refreshListeners")
+        let s:refreshListeners = []
+    endif
+    return s:refreshListeners
+endfunction
diff --git a/lib/nerdtree/tree_dir_node.vim b/lib/nerdtree/tree_dir_node.vim
@@ -252,6 +252,7 @@ function! s:TreeDirNode._initChildren(silent)
             try
                 let path = g:NERDTreePath.New(i)
                 call self.createChild(path, 0)
+                call g:NERDTreeRefreshNotifier.NotifyListeners(path)
             catch /^NERDTree.\(InvalidArguments\|InvalidFiletype\)Error/
                 let invalidFilesFound += 1
             endtry
diff --git a/nerdtree_plugin/git.vim b/nerdtree_plugin/git.vim
@@ -0,0 +1,65 @@
+" ============================================================================
+" File:        git.vim
+" Description: Expt. plugin to add git flags to the UI
+" Maintainer:
+" License:     This program is free software. It comes without any warranty,
+"              to the extent permitted by applicable law. You can redistribute
+"              it and/or modify it under the terms of the Do What The Fuck You
+"              Want To Public License, Version 2, as published by Sam Hocevar.
+"              See http://sam.zoy.org/wtfpl/COPYING for more details.
+"
+" ============================================================================
+if exists("g:loaded_nerdtree_git")
+    finish
+endif
+let g:loaded_nerdtree_git = 1
+
+call g:NERDTreeRefreshNotifier.AddListener("g:NERDTreeGitRefreshListener")
+
+function! g:NERDTreeGitRefreshListener(path)
+    if !isdirectory(b:NERDTreeRoot.path.str() . '/.git')
+        return
+    end
+
+    let modifiedFiles = s:GetModifiedFiles()
+    if index(modifiedFiles, a:path.str()) >= 0
+        call a:path.addFlag("+")
+    else
+        call a:path.removeFlag("+")
+    endif
+endfunction
+
+"Cache the list of modified files for a few seconds - otherwise we must shell
+"out to get it for every path that is refreshed which takes ages
+function! s:GetModifiedFiles()
+    if !exists('s:modifiedFiles') || (localtime() - s:modifiedFilesTime > 2)
+        let s:modifiedFiles = split(system('git -C ' . b:NERDTreeRoot.path.str() . ' ls-files -m'))
+        let s:modifiedFilesTime = localtime()
+        call map(s:modifiedFiles, 'b:NERDTreeRoot.path.str() . "/" . v:val')
+    endif
+
+    return s:modifiedFiles
+endfunction
+
+autocmd filetype nerdtree call s:AddHighlighting()
+function! s:AddHighlighting()
+    syn match NERDTreeGitflag #^ *\zs\[+\]# containedin=NERDTreeFile
+    hi link NERDTreeGitFlag error
+endfunction
+
+"when a buffer is saved, refresh it in nerdtree
+autocmd bufwritepost * call s:FileUpdated(expand("%"))
+function! s:FileUpdated(fname)
+    if !nerdtree#isTreeOpen()
+        return
+    endif
+
+    call nerdtree#putCursorInTreeWin()
+    let node = b:NERDTreeRoot.findNode(g:NERDTreePath.New(a:fname))
+    if !empty(node)
+        call node.refresh()
+    endif
+
+    call NERDTreeRender()
+endfunction
+