Merge pull request #717 from scrooloose/dev

Define the "TreeDirNode._glob()" method.
This commit is contained in:
Jason Franklin
2017-06-28 19:05:19 -04:00
committed by GitHub

View File

@@ -1,13 +1,17 @@
" ============================================================================
" CLASS: TreeDirNode
"
" A subclass of NERDTreeFileNode.
"
" The 'composite' part of the file/dir composite.
"============================================================
" ============================================================================
let s:TreeDirNode = copy(g:NERDTreeFileNode)
let g:NERDTreeDirNode = s:TreeDirNode
" FUNCTION: TreeDirNode.AbsoluteTreeRoot(){{{1
"class method that returns the highest cached ancestor of the current root
" Class method that returns the highest cached ancestor of the current root.
function! s:TreeDirNode.AbsoluteTreeRoot()
let currentNode = b:NERDTree.root
while currentNode.parent != {}
@@ -157,6 +161,7 @@ endfunction
" FUNCTION: TreeDirNode.getChildByIndex(indx, visible) {{{1
" returns the child at the given index
"
" Args:
" indx: the index to get the child from
" visible: 1 if only the visible children array should be used, 0 if all the
@@ -201,28 +206,80 @@ function! s:TreeDirNode.getChildIndex(path)
endfunction
" FUNCTION: TreeDirNode.getDirChildren() {{{1
"Get all children that are directories
" Return a list of all child nodes from "self.children" that are of type
" TreeDirNode.
function! s:TreeDirNode.getDirChildren()
return filter(self.children, 'v:val.path.isDirectory == 1')
endfunction
"FUNCTION: TreeDirNode._getGlobDir() {{{1
"Return a string giving the pathname related to this TreeDirNode. The returned
"pathname is in a glob-friendly format and is relative to the current working
"directory, if this TreeDirNode's path is under the current working directory.
function! s:TreeDirNode._getGlobDir()
" Gets a relative path, if possible. This ensures that 'wildignore' rules
" for relative paths will be obeyed.
let l:globDir = fnamemodify(self.path.str({'format': 'Glob'}), ':.')
" FUNCTION: TreeDirNode._glob(pattern, all) {{{1
" Return a list of strings naming the descendants of the directory in this
" TreeDirNode object that match the specified glob pattern.
"
" Args:
" pattern: (string) the glob pattern to apply
" all: (0 or 1) if 1, include "." and ".." if they match "pattern"; if 0,
" always exclude them
"
" Note: If the pathnames in the result list are below the working directory,
" they are returned as pathnames relative to that directory. This is because
" this function, internally, attempts to obey 'wildignore' rules that use
" relative paths.
function! s:TreeDirNode._glob(pattern, all)
" Calling fnamemodify() with ':.' on Windows systems strips the leading
" drive letter from paths that aren't under the working directory. Here,
" the drive letter is added back to the pathname.
if nerdtree#runningWindows() && l:globDir[0] == '\'
let l:globDir = self.path.drive . l:globDir
" Construct a path specification such that "globpath()" will return
" relative pathnames, if possible.
if self.path.str() == getcwd()
let l:pathSpec = ','
else
let l:pathSpec = fnamemodify(self.path.str({'format': 'Glob'}), ':.')
" On Windows, the drive letter may be removed by "fnamemodify()".
if nerdtree#runningWindows() && l:pathSpec[0] == '\'
let l:pathSpec = self.path.drive . l:pathSpec
endif
endif
return l:globDir
let l:globList = []
" See ":h version7.txt" for the details of the progression of the "glob()"
" and "globpath()" functions.
if v:version >= 704
let l:globList = globpath(l:pathSpec, a:pattern, !g:NERDTreeRespectWildIgnore, 1)
elseif v:version >= 703
let l:globString = globpath(l:pathSpec, a:pattern, !g:NERDTreeRespectWildIgnore)
let l:globList = split(l:globString, "\n")
else
let l:globString = globpath(l:pathSpec, a:pattern)
let l:globList = split(l:globString, "\n")
endif
" If "a:all" is false, filter "." and ".." from the output.
if !a:all
let l:toRemove = []
for l:file in l:globList
let l:tail = fnamemodify(l:file, ':t')
" Double the modifier if only a separator was stripped.
if l:tail == ''
let l:tail = fnamemodify(l:file, ':t:t')
endif
if l:tail == '.' || l:tail == '..'
call add(l:toRemove, l:file)
if len(l:toRemove) == 2
break
endif
endif
endfor
for l:file in l:toRemove
call remove(l:globList, index(l:globList, l:file))
endfor
endif
return l:globList
endfunction
" FUNCTION: TreeDirNode.GetSelected() {{{1
@@ -289,16 +346,7 @@ function! s:TreeDirNode._initChildren(silent)
"remove all the current child nodes
let self.children = []
"get an array of all the files in the nodes dir
let globDir = self._getGlobDir()
if version >= 703
let filesStr = globpath(globDir, '*', !g:NERDTreeRespectWildIgnore) . "\n" . globpath(globDir, '.*', !g:NERDTreeRespectWildIgnore)
else
let filesStr = globpath(globDir, '*') . "\n" . globpath(globDir, '.*')
endif
let files = split(filesStr, "\n")
let files = self._glob('*', 1) + self._glob('.*', 0)
if !a:silent && len(files) > g:NERDTreeNotificationThreshold
call nerdtree#echo("Please wait, caching a large dir ...")
@@ -306,13 +354,6 @@ function! s:TreeDirNode._initChildren(silent)
let invalidFilesFound = 0
for i in files
"filter out the .. and . directories
"Note: we must match .. AND ../ since sometimes the globpath returns
"../ for path with strange chars (eg $)
if i[len(i)-3:2] != ".." && i[len(i)-2:2] != ".." &&
\ i[len(i)-2:1] != "." && i[len(i)-1] != "."
"put the next file in a new node and attach it
try
let path = g:NERDTreePath.New(i)
call self.createChild(path, 0)
@@ -320,7 +361,6 @@ function! s:TreeDirNode._initChildren(silent)
catch /^NERDTree.\(InvalidArguments\|InvalidFiletype\)Error/
let invalidFilesFound += 1
endtry
endif
endfor
call self.sortChildren()
@@ -336,7 +376,7 @@ function! s:TreeDirNode._initChildren(silent)
endfunction
" FUNCTION: TreeDirNode.New(path, nerdtree) {{{1
"Returns a new TreeNode object with the given path and parent
" Return a new TreeDirNode object with the given path and parent.
"
" Args:
" path: dir that the node represents
@@ -401,8 +441,8 @@ function! s:TreeDirNode.openAlong(...)
endfunction
" FUNCTION: TreeDirNode.openExplorer() {{{1
" opens an explorer window for this node in the previous window (could be a
" nerd tree or a netrw)
" Open an explorer window for this node in the previous window. The explorer
" can be a NERDTree window or a netrw window.
function! s:TreeDirNode.openExplorer()
call self.open({'where': 'p'})
endfunction
@@ -453,28 +493,15 @@ function! s:TreeDirNode._openRecursively2(forceOpen)
endfunction
" FUNCTION: TreeDirNode.refresh() {{{1
unlet s:TreeDirNode.refresh
function! s:TreeDirNode.refresh()
call self.path.refresh(self.getNerdtree())
"if this node was ever opened, refresh its children
if self.isOpen || !empty(self.children)
"go thru all the files/dirs under this node
let files = self._glob('*', 1) + self._glob('.*', 0)
let newChildNodes = []
let invalidFilesFound = 0
let globDir = self._getGlobDir()
let filesStr = globpath(globDir, '*') . "\n" . globpath(globDir, '.*')
let files = split(filesStr, "\n")
for i in files
"filter out the .. and . directories
"Note: we must match .. AND ../ cos sometimes the globpath returns
"../ for path with strange chars (eg $)
"if i !~# '\/\.\.\/\?$' && i !~# '\/\.\/\?$'
" Regular expression is too expensive. Use simply string comparison
" instead
if i[len(i)-3:2] != ".." && i[len(i)-2:2] != ".." &&
\ i[len(i)-2:1] != "." && i[len(i)-1] != "."
try
"create a new path and see if it exists in this nodes children
let path = g:NERDTreePath.New(i)
@@ -489,12 +516,9 @@ function! s:TreeDirNode.refresh()
let newNode.parent = self
call add(newChildNodes, newNode)
endif
catch /^NERDTree.\(InvalidArguments\|InvalidFiletype\)Error/
let invalidFilesFound = 1
endtry
endif
endfor
"swap this nodes children out for the children we just read/refreshed
@@ -552,13 +576,11 @@ function! s:TreeDirNode.reveal(path, ...)
endfunction
" FUNCTION: TreeDirNode.removeChild(treenode) {{{1
"
"Removes the given treenode from this nodes set of children
" Remove the given treenode from "self.children".
" Throws "NERDTree.ChildNotFoundError" if the node is not found.
"
" Args:
"treenode: the node to remove
"
"Throws a NERDTree.ChildNotFoundError if the given treenode is not found
" treenode: the node object to remove
function! s:TreeDirNode.removeChild(treenode)
for i in range(0, self.getChildCount()-1)
if self.children[i].equals(a:treenode)
@@ -571,10 +593,7 @@ function! s:TreeDirNode.removeChild(treenode)
endfunction
" FUNCTION: TreeDirNode.sortChildren() {{{1
"
"Sorts the children of this node according to alphabetical order and the
"directory priority.
"
" Sort "self.children" by alphabetical order and directory priority.
function! s:TreeDirNode.sortChildren()
let CompareFunc = function("nerdtree#compareNodesBySortKey")
call sort(self.children, CompareFunc)