Support unusual characters in file and directory names (#868)

* Use a delimiter in node to separate file/dir name from the rest.

* Switch warning message to use nerdtree#deprecated function.

* Compress the space between the tree symbols and the node.

* Include the delimiter when calculating indent or getting filename.

* Don't need to strip leading delimiter. It will already be gone.

* Simplify the way the delimiter is being used.

I don't know what I was thinking. The delimiter doesn't need to be used
to separate every indicator on the node's text, ie.

Bad:    Tree|GenericFlags|Filename|ExecutableFlag|Link|ReadonlyFlag
Better: Tree GenericFlags|Filename|ExecutableFlag Link ReadonlyFlag

This was unnecessary, given that we're only interested in the filename.
So, just one pair of delimiters is all we need. That greatly simplifies
the _stripMarkup function, and restores a bunch of other statements to
what they already are in the master branch.

* Add syntax highlighting to conceal the delimiter

* Put a if has("conceal") check around the syntax statement using it.

* Make concealment work correctly for LinkFile and readonly files.

* Use highlight Ignore if conceal isn't available.

This is probably the best we can do, especially if some other character
must be used in place of nbsp.

* Make the regex better match the original, but more compact.

It was allowing 2+ spaces, instead of only 1+.

* Fix the syntax highlighing of delimiters around NERDTreeExecFile.

* Bug fix: Parse . and .. from path string with trailing slash.

* Fix unresponsive cascaded directories.

Using ':' as a more visible delimiter, when directories are cascaded,
the line appears in NERDTree like so:

▾ :lib/::nerdtree/:

Before this commit, the s:UI._stripMarkup function was leaving the
internal delimiters in place (lib/::nerdtree/). Now they are removed,
resulting in a valid path (lib/nerdtree/).

* Use .= to shorten statement. Use clearer substitutes to get node name.

* Remove node delimiters that terminate the line.

* If flags are needed after the node name, then put another delimiter
before them.
* When joining directory nodes for cascaded display, strip off the
delimiter from the child node(s).
* Remove the unnecessary substitution of doubled intermediate
delimiters, since they're not in there anymore.

* DRY up the addition of the 2nd delimiter, and use only 1 for all tags.
This commit is contained in:
Phil Runninger 2018-10-24 22:41:13 -04:00 committed by GitHub
parent c372911c4a
commit 91e0f2253f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 33 additions and 28 deletions

View File

@ -39,10 +39,10 @@ endfunction
" FUNCTION: Path.cacheDisplayString() {{{1 " FUNCTION: Path.cacheDisplayString() {{{1
function! s:Path.cacheDisplayString() abort function! s:Path.cacheDisplayString() abort
let self.cachedDisplayString = self.getLastPathComponent(1) let self.cachedDisplayString = g:NERDTreeNodeDelimiter . self.getLastPathComponent(1)
if self.isExecutable if self.isExecutable
let self.cachedDisplayString = self.cachedDisplayString . '*' let self.cachedDisplayString = self.addDelimiter(self.cachedDisplayString) . '*'
endif endif
let self._bookmarkNames = [] let self._bookmarkNames = []
@ -52,15 +52,24 @@ function! s:Path.cacheDisplayString() abort
endif endif
endfor endfor
if !empty(self._bookmarkNames) && g:NERDTreeMarkBookmarks == 1 if !empty(self._bookmarkNames) && g:NERDTreeMarkBookmarks == 1
let self.cachedDisplayString .= ' {' . join(self._bookmarkNames) . '}' let self.cachedDisplayString = self.addDelimiter(self.cachedDisplayString) . ' {' . join(self._bookmarkNames) . '}'
endif endif
if self.isSymLink if self.isSymLink
let self.cachedDisplayString .= ' -> ' . self.symLinkDest let self.cachedDisplayString = self.addDelimiter(self.cachedDisplayString) . ' -> ' . self.symLinkDest
endif endif
if self.isReadOnly if self.isReadOnly
let self.cachedDisplayString .= ' ['.g:NERDTreeGlyphReadOnly.']' let self.cachedDisplayString = self.addDelimiter(self.cachedDisplayString) . ' ['.g:NERDTreeGlyphReadOnly.']'
endif
endfunction
" FUNCTION: Path.addDelimiter() {{{1
function! s:Path.addDelimiter(line)
if a:line =~# '\(.*' . g:NERDTreeNodeDelimiter . '\)\{2}'
return a:line
else
return a:line . g:NERDTreeNodeDelimiter
endif endif
endfunction endfunction

View File

@ -99,7 +99,8 @@ function! s:TreeDirNode.displayString()
let l:label = '' let l:label = ''
let l:cascade = self.getCascade() let l:cascade = self.getCascade()
for l:dirNode in l:cascade for l:dirNode in l:cascade
let l:label .= l:dirNode.path.displayString() let l:next = l:dirNode.path.displayString()
let l:label .= l:label == '' ? l:next : strcharpart(l:next,1)
endfor endfor
" Select the appropriate open/closed status indicator symbol. " Select the appropriate open/closed status indicator symbol.

View File

@ -242,7 +242,7 @@ endfunction
" FUNCTION: TreeFileNode.openInNewTab(options) {{{1 " FUNCTION: TreeFileNode.openInNewTab(options) {{{1
function! s:TreeFileNode.openInNewTab(options) function! s:TreeFileNode.openInNewTab(options)
echomsg 'TreeFileNode.openInNewTab is deprecated' call nerdtree#deprecated('TreeFileNode.openinNewTab', 'is deprecated, use .open() instead.')
call self.open(extend({'where': 't'}, a:options)) call self.open(extend({'where': 't'}, a:options))
endfunction endfunction

View File

@ -300,7 +300,7 @@ endfunction
" FUNCTION: s:UI.MarkupReg() {{{1 " FUNCTION: s:UI.MarkupReg() {{{1
function! s:UI.MarkupReg() function! s:UI.MarkupReg()
return '^\(['.g:NERDTreeDirArrowExpandable.g:NERDTreeDirArrowCollapsible.'] \| \+['.g:NERDTreeDirArrowExpandable.g:NERDTreeDirArrowCollapsible.'] \| \+\)' return '^ *['.g:NERDTreeDirArrowExpandable.g:NERDTreeDirArrowCollapsible.']\? '
endfunction endfunction
" FUNCTION: s:UI._renderBookmarks {{{1 " FUNCTION: s:UI._renderBookmarks {{{1
@ -363,30 +363,13 @@ function! s:UI.setShowHidden(val)
endfunction endfunction
" FUNCTION: s:UI._stripMarkup(line){{{1 " FUNCTION: s:UI._stripMarkup(line){{{1
" returns the given line with all the tree parts stripped off " find the filename in the given line, and return it.
" "
" Args: " Args:
" line: the subject line " line: the subject line
function! s:UI._stripMarkup(line) function! s:UI._stripMarkup(line)
let line = a:line let l:line = substitute(a:line, '^.\{-}' . g:NERDTreeNodeDelimiter, '', '')
" remove the tree parts and the leading space return substitute(l:line, g:NERDTreeNodeDelimiter.'.*$', '', '')
let line = substitute (line, g:NERDTreeUI.MarkupReg(),"","")
" strip off any read only flag
let line = substitute (line, ' \['.g:NERDTreeGlyphReadOnly.'\]', "","")
" strip off any bookmark flags
let line = substitute (line, ' {[^}]*}', "","")
" strip off any executable flags
let line = substitute (line, '*\ze\($\| \)', "","")
" strip off any generic flags
let line = substitute (line, '\[[^]]*\]', "","")
let line = substitute (line,' -> .*',"","") " remove link to
return line
endfunction endfunction
" FUNCTION: s:UI.render() {{{1 " FUNCTION: s:UI.render() {{{1

View File

@ -86,6 +86,9 @@ let g:NERDTreeOldSortOrder = []
call s:initVariable("g:NERDTreeGlyphReadOnly", "RO") call s:initVariable("g:NERDTreeGlyphReadOnly", "RO")
" ASCII 160: non-breaking space used to delimit items in the tree's nodes.
call s:initVariable("g:NERDTreeNodeDelimiter", "\u00a0")
if !exists('g:NERDTreeStatusline') if !exists('g:NERDTreeStatusline')
"the exists() crap here is a hack to stop vim spazzing out when "the exists() crap here is a hack to stop vim spazzing out when

View File

@ -36,6 +36,15 @@ exec 'syn match NERDTreeRO # *\zs.*\ze \['.g:NERDTreeGlyphReadOnly.'\]# contains
syn match NERDTreeFlags #^ *\zs\[.\]# containedin=NERDTreeFile,NERDTreeExecFile syn match NERDTreeFlags #^ *\zs\[.\]# containedin=NERDTreeFile,NERDTreeExecFile
syn match NERDTreeFlags #\[.\]# containedin=NERDTreeDir syn match NERDTreeFlags #\[.\]# containedin=NERDTreeDir
"highlighing to conceal the delimiter around the file/dir name
if has("conceal")
exec 'syn match NERDTreeNodeDelimiters #' . g:NERDTreeNodeDelimiter . '# conceal containedin=NERDTreeFile,NERDTreeLinkFile,NERDTreeExecFile,NERDTreeRO,NERDTreeDir'
setlocal conceallevel=2 concealcursor=nvic
else
exec 'syn match NERDTreeNodeDelimiters #' . g:NERDTreeNodeDelimiter . '# containedin=NERDTreeFile,NERDTreeLinkFile,NERDTreeExecFile,NERDTreeRO,NERDTreeDir'
hi! link NERDTreeNodeDelimiters Ignore
endif
syn match NERDTreeCWD #^[</].*$# syn match NERDTreeCWD #^[</].*$#
"highlighting for bookmarks "highlighting for bookmarks