From 91e0f2253fbecefa7e14f095950341584877ef19 Mon Sep 17 00:00:00 2001 From: Phil Runninger Date: Wed, 24 Oct 2018 22:41:13 -0400 Subject: [PATCH] Support unusual characters in file and directory names (#868) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 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. --- lib/nerdtree/path.vim | 19 ++++++++++++++----- lib/nerdtree/tree_dir_node.vim | 3 ++- lib/nerdtree/tree_file_node.vim | 2 +- lib/nerdtree/ui.vim | 25 ++++--------------------- plugin/NERD_tree.vim | 3 +++ syntax/nerdtree.vim | 9 +++++++++ 6 files changed, 33 insertions(+), 28 deletions(-) diff --git a/lib/nerdtree/path.vim b/lib/nerdtree/path.vim index 32c9cdb..d997c31 100644 --- a/lib/nerdtree/path.vim +++ b/lib/nerdtree/path.vim @@ -39,10 +39,10 @@ endfunction " FUNCTION: Path.cacheDisplayString() {{{1 function! s:Path.cacheDisplayString() abort - let self.cachedDisplayString = self.getLastPathComponent(1) + let self.cachedDisplayString = g:NERDTreeNodeDelimiter . self.getLastPathComponent(1) if self.isExecutable - let self.cachedDisplayString = self.cachedDisplayString . '*' + let self.cachedDisplayString = self.addDelimiter(self.cachedDisplayString) . '*' endif let self._bookmarkNames = [] @@ -52,15 +52,24 @@ function! s:Path.cacheDisplayString() abort endif endfor if !empty(self._bookmarkNames) && g:NERDTreeMarkBookmarks == 1 - let self.cachedDisplayString .= ' {' . join(self._bookmarkNames) . '}' + let self.cachedDisplayString = self.addDelimiter(self.cachedDisplayString) . ' {' . join(self._bookmarkNames) . '}' endif if self.isSymLink - let self.cachedDisplayString .= ' -> ' . self.symLinkDest + let self.cachedDisplayString = self.addDelimiter(self.cachedDisplayString) . ' -> ' . self.symLinkDest endif 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 endfunction diff --git a/lib/nerdtree/tree_dir_node.vim b/lib/nerdtree/tree_dir_node.vim index a36bdf8..016a5dc 100644 --- a/lib/nerdtree/tree_dir_node.vim +++ b/lib/nerdtree/tree_dir_node.vim @@ -99,7 +99,8 @@ function! s:TreeDirNode.displayString() let l:label = '' let l:cascade = self.getCascade() 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 " Select the appropriate open/closed status indicator symbol. diff --git a/lib/nerdtree/tree_file_node.vim b/lib/nerdtree/tree_file_node.vim index 52b6193..d4c060f 100644 --- a/lib/nerdtree/tree_file_node.vim +++ b/lib/nerdtree/tree_file_node.vim @@ -242,7 +242,7 @@ endfunction " FUNCTION: TreeFileNode.openInNewTab(options) {{{1 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)) endfunction diff --git a/lib/nerdtree/ui.vim b/lib/nerdtree/ui.vim index 5ea1333..32d96d9 100644 --- a/lib/nerdtree/ui.vim +++ b/lib/nerdtree/ui.vim @@ -300,7 +300,7 @@ endfunction " FUNCTION: s:UI.MarkupReg() {{{1 function! s:UI.MarkupReg() - return '^\(['.g:NERDTreeDirArrowExpandable.g:NERDTreeDirArrowCollapsible.'] \| \+['.g:NERDTreeDirArrowExpandable.g:NERDTreeDirArrowCollapsible.'] \| \+\)' + return '^ *['.g:NERDTreeDirArrowExpandable.g:NERDTreeDirArrowCollapsible.']\? ' endfunction " FUNCTION: s:UI._renderBookmarks {{{1 @@ -363,30 +363,13 @@ function! s:UI.setShowHidden(val) endfunction " 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: " line: the subject line function! s:UI._stripMarkup(line) - let line = a:line - " remove the tree parts and the leading space - 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 + let l:line = substitute(a:line, '^.\{-}' . g:NERDTreeNodeDelimiter, '', '') + return substitute(l:line, g:NERDTreeNodeDelimiter.'.*$', '', '') endfunction " FUNCTION: s:UI.render() {{{1 diff --git a/plugin/NERD_tree.vim b/plugin/NERD_tree.vim index 2abd248..62506e5 100644 --- a/plugin/NERD_tree.vim +++ b/plugin/NERD_tree.vim @@ -86,6 +86,9 @@ let g:NERDTreeOldSortOrder = [] 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') "the exists() crap here is a hack to stop vim spazzing out when diff --git a/syntax/nerdtree.vim b/syntax/nerdtree.vim index 7c80605..dddce6d 100644 --- a/syntax/nerdtree.vim +++ b/syntax/nerdtree.vim @@ -36,6 +36,15 @@ exec 'syn match NERDTreeRO # *\zs.*\ze \['.g:NERDTreeGlyphReadOnly.'\]# contains syn match NERDTreeFlags #^ *\zs\[.\]# containedin=NERDTreeFile,NERDTreeExecFile 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 #^[