diff --git a/autoload/nerdtree.vim b/autoload/nerdtree.vim index 3591932..4139787 100644 --- 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 index b1a617f..cf1c402 100644 --- 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 index 047a72a..e034c86 100644 --- 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 new file mode 100644 index 0000000..0cc62b0 --- /dev/null +++ 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 index 520fca6..bf93c1d 100644 --- 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 new file mode 100644 index 0000000..615ebc0 --- /dev/null +++ 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 +