nerdtree

A tree explorer plugin for vim.
Index Commits Files Refs
commit 6251ab1e6377f302c0c9b9337af6855b3638db98
parent 4ebbb533c3faf2c480211db2b547972bb3b60f2b
Author: Maxim Bublis <b@codemonkey.ru>
Date:   Tue, 19 Jan 2016 00:21:13 -0800

Add support for natural sorting order.

Diffstat:
Mautoload/nerdtree.vim | 28++++++++++++++++++++++++++--
Mdoc/NERD_tree.txt | 30++++++++++++++++++++++++++++++
Mlib/nerdtree/path.vim | 29+++++++++++++++++++++--------
Mplugin/NERD_tree.vim | 1+
4 files changed, 78 insertions(+), 10 deletions(-)
diff --git a/autoload/nerdtree.vim b/autoload/nerdtree.vim
@@ -36,9 +36,33 @@ endfunction
 
 "FUNCTION: nerdtree#compareNodesBySortKey(n1, n2) {{{2
 function! nerdtree#compareNodesBySortKey(n1, n2)
-    if a:n1.path.getSortKey() <# a:n2.path.getSortKey()
+    let sortKey1 = a:n1.path.getSortKey()
+    let sortKey2 = a:n2.path.getSortKey()
+
+    let i = 0
+    while i < min([len(sortKey1), len(sortKey2)])
+        " Compare chunks upto common length.
+        " If chunks have different type, the one which has
+        " integer type is the lesser.
+        if type(sortKey1[i]) == type(sortKey2[i])
+            if sortKey1[i] <# sortKey2[i]
+                return - 1
+            elseif sortKey1[i] ># sortKey2[i]
+                return 1
+            endif
+        elseif sortKey1[i] == type(0)
+            return -1
+        elseif sortKey2[i] == type(0)
+            return 1
+        endif
+        let i = i + 1
+    endwhile
+
+    " Keys are identical upto common length.
+    " The key which has smaller chunks is the lesser one.
+    if len(sortKey1) < len(sortKey2)
         return -1
-    elseif a:n1.path.getSortKey() ># a:n2.path.getSortKey()
+    elseif len(sortKey1) > len(sortKey2)
         return 1
     else
         return 0
diff --git a/doc/NERD_tree.txt b/doc/NERD_tree.txt
@@ -618,6 +618,9 @@ NERD tree. These options should be set in your vimrc.
 |'NERDTreeCaseSensitiveSort'|   Tells the NERD tree whether to be case
                                 sensitive or not when sorting nodes.
 
+|'NERDTreeNaturalSort'|         Tells the NERD tree whether to use
+                                natural sort order or not when sorting nodes.
+
 |'NERDTreeSortHiddenFirst'|     Tells the NERD tree whether to take the dot
                                 at the beginning of the hidden file names
                                 into account when sorting nodes.
@@ -735,6 +738,33 @@ account. The above nodes would then be sorted like this: >
     boner.c
 <
 ------------------------------------------------------------------------------
+                                                       *'NERDTreeNaturalSort'*
+Values: 0 or 1.
+Default: 0.
+
+By default the NERD tree does not sort nodes in natural sort order, i.e. nodes
+could appear like this: >
+    z1.txt
+    z10.txt
+    z100.txt
+    z11.txt
+    z110.txt
+    z2.txt
+    z20.txt
+    z3.txt
+<
+But if you set this option to 1 then the natural sort order will be used. The
+above nodes would then be sorted like this: >
+    z1.txt
+    z2.txt
+    z3.txt
+    z10.txt
+    z11.txt
+    z20.txt
+    z100.txt
+    z110.txt
+<
+------------------------------------------------------------------------------
                                                          *'NERDTreeChDirMode'*
 
 Values: 0, 1 or 2.
diff --git a/lib/nerdtree/path.vim b/lib/nerdtree/path.vim
@@ -1,12 +1,6 @@
 "we need to use this number many times for sorting... so we calculate it only
 "once here
 let s:NERDTreeSortStarIndex = index(g:NERDTreeSortOrder, '*')
-" used in formating sortKey, e.g. '%04d'
-if exists("log10")
-    let s:sortKeyFormat = "%0" . float2nr(ceil(log10(len(g:NERDTreeSortOrder)))) . "d"
-else
-    let s:sortKeyFormat = "%04d"
-endif
 
 "CLASS: Path
 "============================================================
@@ -365,8 +359,23 @@ function! s:Path.getSortOrderIndex()
     return s:NERDTreeSortStarIndex
 endfunction
 
+"FUNCTION: Path._splitChunks(path) {{{1
+"returns a list of path chunks
+function! s:Path._splitChunks(path)
+    let chunks = split(a:path, '\(\D\+\|\d\+\)\zs')
+    let i = 0
+    while i < len(chunks)
+        "convert number literals to numbers
+        if match(chunks[i], '^\d\+$') == 0
+            let chunks[i] = str2nr(chunks[i])
+        endif
+        let i = i + 1
+    endwhile
+    return chunks
+endfunction
+
 "FUNCTION: Path.getSortKey() {{{1
-"returns a string used in compare function for sorting
+"returns a key used in compare function for sorting
 function! s:Path.getSortKey()
     if !exists("self._sortKey")
         let path = self.getLastPathComponent(1)
@@ -376,7 +385,11 @@ function! s:Path.getSortKey()
         if !g:NERDTreeCaseSensitiveSort
             let path = tolower(path)
         endif
-        let self._sortKey = printf(s:sortKeyFormat, self.getSortOrderIndex()) . path
+        if !g:NERDTreeNaturalSort
+            let self._sortKey = [self.getSortOrderIndex(), path]
+        else
+            let self._sortKey = [self.getSortOrderIndex()] + self._splitChunks(path)
+        endif
     endif
 
     return self._sortKey
diff --git a/plugin/NERD_tree.vim b/plugin/NERD_tree.vim
@@ -46,6 +46,7 @@ endfunction
 call s:initVariable("g:NERDTreeAutoCenter", 1)
 call s:initVariable("g:NERDTreeAutoCenterThreshold", 3)
 call s:initVariable("g:NERDTreeCaseSensitiveSort", 0)
+call s:initVariable("g:NERDTreeNaturalSort", 0)
 call s:initVariable("g:NERDTreeSortHiddenFirst", 1)
 call s:initVariable("g:NERDTreeChDirMode", 0)
 call s:initVariable("g:NERDTreeMinimalUI", 0)