From 6aff1b6cd3f5306a6828e20375cc0fc11cabe590 Mon Sep 17 00:00:00 2001 From: bravestarr Date: Sun, 22 Apr 2018 21:18:46 +0800 Subject: [PATCH] Display a path with multi-byte characters correctly when it is truncated When a path is rendered in the Bookmarks area or as the header line of the tree, it is truncated if there is no enough space for it. But if a path contains multi-byte characters, it should be truncated by characters, not bytes, otherwise the path may be truncated between the bytes of a multi-byte character. To deal with multi-byte characters, use strdisplaywidth() instead of len() to get the number of display cells, and use strcharpart() instead of strpart() to truncate a path. --- lib/nerdtree/bookmark.vim | 9 ++++++--- lib/nerdtree/path.vim | 6 ++++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/nerdtree/bookmark.vim b/lib/nerdtree/bookmark.vim index 45f9950..307211b 100644 --- a/lib/nerdtree/bookmark.vim +++ b/lib/nerdtree/bookmark.vim @@ -280,14 +280,17 @@ endfunction " FUNCTION: Bookmark.str() {{{1 " Get the string that should be rendered in the view for this bookmark function! s:Bookmark.str() - let pathStrMaxLen = winwidth(g:NERDTree.GetWinNum()) - 4 - len(self.name) + let pathStrMaxLen = winwidth(g:NERDTree.GetWinNum()) - 4 - strdisplaywidth(self.name) if &nu let pathStrMaxLen = pathStrMaxLen - &numberwidth endif let pathStr = self.path.str({'format': 'UI'}) - if len(pathStr) > pathStrMaxLen - let pathStr = '<' . strpart(pathStr, len(pathStr) - pathStrMaxLen) + if strdisplaywidth(pathStr) > pathStrMaxLen + while strdisplaywidth(pathStr) > pathStrMaxLen && strchars(pathStr) > 0 + let pathStr = strcharpart(pathStr, 1) + endwhile + let pathStr = '<' . pathStr endif return '>' . self.name . ' ' . pathStr endfunction diff --git a/lib/nerdtree/path.vim b/lib/nerdtree/path.vim index 7fc726e..f436d36 100644 --- a/lib/nerdtree/path.vim +++ b/lib/nerdtree/path.vim @@ -719,8 +719,10 @@ function! s:Path.str(...) if has_key(options, 'truncateTo') let limit = options['truncateTo'] - if len(toReturn) > limit-1 - let toReturn = toReturn[(len(toReturn)-limit+1):] + if strdisplaywidth(toReturn) > limit-1 + while strdisplaywidth(toReturn) > limit-1 && strchars(toReturn) > 0 + let toReturn = strcharpart(toReturn, 1) + endwhile if len(split(toReturn, '/')) > 1 let toReturn = '