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
commit 7ed79c00c1

View File

@ -1,13 +1,17 @@
" ============================================================================
" CLASS: TreeDirNode " CLASS: TreeDirNode
"
" A subclass of NERDTreeFileNode. " A subclass of NERDTreeFileNode.
" "
" The 'composite' part of the file/dir composite. " The 'composite' part of the file/dir composite.
"============================================================ " ============================================================================
let s:TreeDirNode = copy(g:NERDTreeFileNode) let s:TreeDirNode = copy(g:NERDTreeFileNode)
let g:NERDTreeDirNode = s:TreeDirNode let g:NERDTreeDirNode = s:TreeDirNode
" FUNCTION: TreeDirNode.AbsoluteTreeRoot(){{{1 " 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() function! s:TreeDirNode.AbsoluteTreeRoot()
let currentNode = b:NERDTree.root let currentNode = b:NERDTree.root
while currentNode.parent != {} while currentNode.parent != {}
@ -157,6 +161,7 @@ endfunction
" FUNCTION: TreeDirNode.getChildByIndex(indx, visible) {{{1 " FUNCTION: TreeDirNode.getChildByIndex(indx, visible) {{{1
" returns the child at the given index " returns the child at the given index
"
" Args: " Args:
" indx: the index to get the child from " indx: the index to get the child from
" visible: 1 if only the visible children array should be used, 0 if all the " 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 endfunction
" FUNCTION: TreeDirNode.getDirChildren() {{{1 " 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() function! s:TreeDirNode.getDirChildren()
return filter(self.children, 'v:val.path.isDirectory == 1') return filter(self.children, 'v:val.path.isDirectory == 1')
endfunction endfunction
"FUNCTION: TreeDirNode._getGlobDir() {{{1 " FUNCTION: TreeDirNode._glob(pattern, all) {{{1
"Return a string giving the pathname related to this TreeDirNode. The returned " Return a list of strings naming the descendants of the directory in this
"pathname is in a glob-friendly format and is relative to the current working " TreeDirNode object that match the specified glob pattern.
"directory, if this TreeDirNode's path is under the current working directory. "
function! s:TreeDirNode._getGlobDir() " Args:
" Gets a relative path, if possible. This ensures that 'wildignore' rules " pattern: (string) the glob pattern to apply
" for relative paths will be obeyed. " all: (0 or 1) if 1, include "." and ".." if they match "pattern"; if 0,
let l:globDir = fnamemodify(self.path.str({'format': 'Glob'}), ':.') " 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 " Construct a path specification such that "globpath()" will return
" drive letter from paths that aren't under the working directory. Here, " relative pathnames, if possible.
" the drive letter is added back to the pathname. if self.path.str() == getcwd()
if nerdtree#runningWindows() && l:globDir[0] == '\' let l:pathSpec = ','
let l:globDir = self.path.drive . l:globDir 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 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 endfunction
" FUNCTION: TreeDirNode.GetSelected() {{{1 " FUNCTION: TreeDirNode.GetSelected() {{{1
@ -289,16 +346,7 @@ function! s:TreeDirNode._initChildren(silent)
"remove all the current child nodes "remove all the current child nodes
let self.children = [] let self.children = []
"get an array of all the files in the nodes dir let files = self._glob('*', 1) + self._glob('.*', 0)
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")
if !a:silent && len(files) > g:NERDTreeNotificationThreshold if !a:silent && len(files) > g:NERDTreeNotificationThreshold
call nerdtree#echo("Please wait, caching a large dir ...") call nerdtree#echo("Please wait, caching a large dir ...")
@ -306,13 +354,6 @@ function! s:TreeDirNode._initChildren(silent)
let invalidFilesFound = 0 let invalidFilesFound = 0
for i in files 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 try
let path = g:NERDTreePath.New(i) let path = g:NERDTreePath.New(i)
call self.createChild(path, 0) call self.createChild(path, 0)
@ -320,7 +361,6 @@ function! s:TreeDirNode._initChildren(silent)
catch /^NERDTree.\(InvalidArguments\|InvalidFiletype\)Error/ catch /^NERDTree.\(InvalidArguments\|InvalidFiletype\)Error/
let invalidFilesFound += 1 let invalidFilesFound += 1
endtry endtry
endif
endfor endfor
call self.sortChildren() call self.sortChildren()
@ -336,7 +376,7 @@ function! s:TreeDirNode._initChildren(silent)
endfunction endfunction
" FUNCTION: TreeDirNode.New(path, nerdtree) {{{1 " 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: " Args:
" path: dir that the node represents " path: dir that the node represents
@ -401,8 +441,8 @@ function! s:TreeDirNode.openAlong(...)
endfunction endfunction
" FUNCTION: TreeDirNode.openExplorer() {{{1 " FUNCTION: TreeDirNode.openExplorer() {{{1
" opens an explorer window for this node in the previous window (could be a " Open an explorer window for this node in the previous window. The explorer
" nerd tree or a netrw) " can be a NERDTree window or a netrw window.
function! s:TreeDirNode.openExplorer() function! s:TreeDirNode.openExplorer()
call self.open({'where': 'p'}) call self.open({'where': 'p'})
endfunction endfunction
@ -453,28 +493,15 @@ function! s:TreeDirNode._openRecursively2(forceOpen)
endfunction endfunction
" FUNCTION: TreeDirNode.refresh() {{{1 " FUNCTION: TreeDirNode.refresh() {{{1
unlet s:TreeDirNode.refresh
function! s:TreeDirNode.refresh() function! s:TreeDirNode.refresh()
call self.path.refresh(self.getNerdtree()) call self.path.refresh(self.getNerdtree())
"if this node was ever opened, refresh its children "if this node was ever opened, refresh its children
if self.isOpen || !empty(self.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 newChildNodes = []
let invalidFilesFound = 0 let invalidFilesFound = 0
let globDir = self._getGlobDir()
let filesStr = globpath(globDir, '*') . "\n" . globpath(globDir, '.*')
let files = split(filesStr, "\n")
for i in files 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 try
"create a new path and see if it exists in this nodes children "create a new path and see if it exists in this nodes children
let path = g:NERDTreePath.New(i) let path = g:NERDTreePath.New(i)
@ -489,12 +516,9 @@ function! s:TreeDirNode.refresh()
let newNode.parent = self let newNode.parent = self
call add(newChildNodes, newNode) call add(newChildNodes, newNode)
endif endif
catch /^NERDTree.\(InvalidArguments\|InvalidFiletype\)Error/ catch /^NERDTree.\(InvalidArguments\|InvalidFiletype\)Error/
let invalidFilesFound = 1 let invalidFilesFound = 1
endtry endtry
endif
endfor endfor
"swap this nodes children out for the children we just read/refreshed "swap this nodes children out for the children we just read/refreshed
@ -552,13 +576,11 @@ function! s:TreeDirNode.reveal(path, ...)
endfunction endfunction
" FUNCTION: TreeDirNode.removeChild(treenode) {{{1 " FUNCTION: TreeDirNode.removeChild(treenode) {{{1
" " Remove the given treenode from "self.children".
"Removes the given treenode from this nodes set of children " Throws "NERDTree.ChildNotFoundError" if the node is not found.
" "
" Args: " Args:
"treenode: the node to remove " treenode: the node object to remove
"
"Throws a NERDTree.ChildNotFoundError if the given treenode is not found
function! s:TreeDirNode.removeChild(treenode) function! s:TreeDirNode.removeChild(treenode)
for i in range(0, self.getChildCount()-1) for i in range(0, self.getChildCount()-1)
if self.children[i].equals(a:treenode) if self.children[i].equals(a:treenode)
@ -571,10 +593,7 @@ function! s:TreeDirNode.removeChild(treenode)
endfunction endfunction
" FUNCTION: TreeDirNode.sortChildren() {{{1 " FUNCTION: TreeDirNode.sortChildren() {{{1
" " Sort "self.children" by alphabetical order and directory priority.
"Sorts the children of this node according to alphabetical order and the
"directory priority.
"
function! s:TreeDirNode.sortChildren() function! s:TreeDirNode.sortChildren()
let CompareFunc = function("nerdtree#compareNodesBySortKey") let CompareFunc = function("nerdtree#compareNodesBySortKey")
call sort(self.children, CompareFunc) call sort(self.children, CompareFunc)