nerdtree

A tree explorer plugin for vim.
Index Commits Files Refs
commit cd1f2c803ec485074af070a2fe942a029775e5bd
parent e9d3f72d9c955d12630278a823614af49fbe9c5b
Author: Jason Franklin <lifecrisis@users.noreply.github.com>
Date:   Sat, 15 Sep 2018 10:18:09 -0400

Fix the <C-J>, <C-K>, J, and K default mappings (#886)

These mappings currently fail on cascades.  This pull request fixes
this problem.

Diffstat:
Mautoload/nerdtree/ui_glue.vim | 106+++++++++++++++++++++++++++++++++++--------------------------------------------
Mlib/nerdtree/tree_dir_node.vim | 26++++++++++++++++++++++++++
Mlib/nerdtree/tree_file_node.vim | 70+++++++++++++++++++++-------------------------------------------------
3 files changed, 94 insertions(+), 108 deletions(-)
diff --git a/autoload/nerdtree/ui_glue.vim b/autoload/nerdtree/ui_glue.vim
@@ -348,35 +348,6 @@ function! s:handleMiddleMouse()
     endif
 endfunction
 
-" FUNCTION: s:jumpToChild(direction) {{{2
-" Args:
-" direction: 0 if going to first child, 1 if going to last
-function! s:jumpToChild(currentNode, direction)
-    if a:currentNode.isRoot()
-        return nerdtree#echo("cannot jump to " . (a:direction ? "last" : "first") .  " child")
-    end
-    let dirNode = a:currentNode.parent
-    let childNodes = dirNode.getVisibleChildren()
-
-    let targetNode = childNodes[0]
-    if a:direction
-        let targetNode = childNodes[len(childNodes) - 1]
-    endif
-
-    if targetNode.equals(a:currentNode)
-        let siblingDir = a:currentNode.parent.findOpenDirSiblingWithVisibleChildren(a:direction)
-        if siblingDir != {}
-            let indx = a:direction ? siblingDir.getVisibleChildCount()-1 : 0
-            let targetNode = siblingDir.getChildByIndex(indx, 1)
-        endif
-    endif
-
-    call targetNode.putCursorHere(1, 0)
-
-    call b:NERDTree.ui.centerView()
-endfunction
-
-
 " FUNCTION: nerdtree#ui_glue#invokeKeyMap(key) {{{1
 "this is needed since I cant figure out how to invoke dict functions from a
 "key map
@@ -384,41 +355,55 @@ function! nerdtree#ui_glue#invokeKeyMap(key)
     call g:NERDTreeKeyMap.Invoke(a:key)
 endfunction
 
-" FUNCTION: s:jumpToFirstChild() {{{1
-" wrapper for the jump to child method
+" FUNCTION: s:jumpToFirstChild(node) {{{1
 function! s:jumpToFirstChild(node)
     call s:jumpToChild(a:node, 0)
 endfunction
 
-" FUNCTION: s:jumpToLastChild() {{{1
-" wrapper for the jump to child method
+" FUNCTION: s:jumpToLastChild(node) {{{1
 function! s:jumpToLastChild(node)
     call s:jumpToChild(a:node, 1)
 endfunction
 
+" FUNCTION: s:jumpToChild(node, last) {{{2
+" Jump to the first or last child node at the same file system level.
+"
+" Args:
+" node: the node on which the cursor currently sits
+" last: 1 (true) if jumping to last child, 0 (false) if jumping to first
+function! s:jumpToChild(node, last)
+    let l:node = a:node.path.isDirectory ? a:node.getCascadeRoot() : a:node
+
+    if l:node.isRoot()
+        return
+    endif
+
+    let l:parent = l:node.parent
+    let l:children = l:parent.getVisibleChildren()
+
+    let l:target = a:last ? l:children[len(l:children) - 1] : l:children[0]
+
+    call l:target.putCursorHere(1, 0)
+    call b:NERDTree.ui.centerView()
+endfunction
+
 " FUNCTION: s:jumpToParent(node) {{{1
-" Move the cursor to the parent of the specified node. For a cascade, move to
-" the parent of the cascade's highest node. At the root, do nothing.
+" Move the cursor to the parent of the specified node.  For a cascade, move to
+" the parent of the cascade's first node.  At the root node, do nothing.
 function! s:jumpToParent(node)
-    let l:parent = a:node.parent
+    let l:node = a:node.path.isDirectory ? a:node.getCascadeRoot() : a:node
 
-    " If "a:node" represents a directory, back out of its cascade.
-    if a:node.path.isDirectory
-        while !empty(l:parent) && !l:parent.isRoot()
-            if index(l:parent.getCascade(), a:node) >= 0
-                let l:parent = l:parent.parent
-            else
-                break
-            endif
-        endwhile
+    if l:node.isRoot()
+        return
     endif
 
-    if !empty(l:parent)
-        call l:parent.putCursorHere(1, 0)
-        call b:NERDTree.ui.centerView()
-    else
+    if empty(l:node.parent)
         call nerdtree#echo('could not jump to parent node')
+        return
     endif
+
+    call l:node.parent.putCursorHere(1, 0)
+    call b:NERDTree.ui.centerView()
 endfunction
 
 " FUNCTION: s:jumpToRoot() {{{1
@@ -438,19 +423,22 @@ function! s:jumpToPrevSibling(node)
     call s:jumpToSibling(a:node, 0)
 endfunction
 
-" FUNCTION: s:jumpToSibling(currentNode, forward) {{{2
-" moves the cursor to the sibling of the current node in the given direction
+" FUNCTION: s:jumpToSibling(node, forward) {{{2
+" Move the cursor to the next or previous node at the same file system level.
 "
 " Args:
-" forward: 1 if the cursor should move to the next sibling, 0 if it should
-" move back to the previous sibling
-function! s:jumpToSibling(currentNode, forward)
-    let sibling = a:currentNode.findSibling(a:forward)
-
-    if !empty(sibling)
-        call sibling.putCursorHere(1, 0)
-        call b:NERDTree.ui.centerView()
+" node: the node on which the cursor currently sits
+" forward: 0 to jump to previous sibling, 1 to jump to next sibling
+function! s:jumpToSibling(node, forward)
+    let l:node = a:node.path.isDirectory ? a:node.getCascadeRoot() : a:node
+    let l:sibling = l:node.findSibling(a:forward)
+
+    if empty(l:sibling)
+        return
     endif
+
+    call l:sibling.putCursorHere(1, 0)
+    call b:NERDTree.ui.centerView()
 endfunction
 
 " FUNCTION: nerdtree#ui_glue#openBookmark(name) {{{1
diff --git a/lib/nerdtree/tree_dir_node.vim b/lib/nerdtree/tree_dir_node.vim
@@ -153,6 +153,32 @@ function! s:TreeDirNode.getCascade()
     return [self] + visChild.getCascade()
 endfunction
 
+" FUNCTION: TreeDirNode.getCascadeRoot() {{{1
+" Return the first directory node in the cascade in which this directory node
+" is rendered.
+function! s:TreeDirNode.getCascadeRoot()
+
+    " Don't search above the current NERDTree root node.
+    if self.isRoot()
+        return self
+    endif
+
+    let l:cascadeRoot = self
+    let l:parent = self.parent
+
+    while !empty(l:parent) && !l:parent.isRoot()
+
+        if index(l:parent.getCascade(), self) == -1
+            break
+        endif
+
+        let l:cascadeRoot = l:parent
+        let l:parent = l:parent.parent
+    endwhile
+
+    return l:cascadeRoot
+endfunction
+
 " FUNCTION: TreeDirNode.getChildCount() {{{1
 " Returns the number of children this node has
 function! s:TreeDirNode.getChildCount()
diff --git a/lib/nerdtree/tree_file_node.vim b/lib/nerdtree/tree_file_node.vim
@@ -116,67 +116,39 @@ function! s:TreeFileNode.findNode(path)
     return {}
 endfunction
 
-" FUNCTION: TreeFileNode.findOpenDirSiblingWithVisibleChildren(direction) {{{1
-"
-" Finds the next sibling for this node in the indicated direction. This sibling
-" must be a directory and may/may not have children as specified.
-"
-" Args:
-" direction: 0 if you want to find the previous sibling, 1 for the next sibling
-"
-" Return:
-" a treenode object or {} if no appropriate sibling could be found
-function! s:TreeFileNode.findOpenDirSiblingWithVisibleChildren(direction)
-    " if we have no parent then we can have no siblings
-    if self.parent != {}
-        let nextSibling = self.findSibling(a:direction)
-
-        while nextSibling != {}
-            if nextSibling.path.isDirectory && nextSibling.hasVisibleChildren() && nextSibling.isOpen
-                return nextSibling
-            endif
-            let nextSibling = nextSibling.findSibling(a:direction)
-        endwhile
-    endif
-
-    return {}
-endfunction
-
 " FUNCTION: TreeFileNode.findSibling(direction) {{{1
-"
-" Finds the next sibling for this node in the indicated direction
+" Find the next or previous sibling of this node.
 "
 " Args:
-" direction: 0 if you want to find the previous sibling, 1 for the next sibling
+" direction: 0 for previous, 1 for next
 "
 " Return:
-" a treenode object or {} if no sibling could be found
+" The next/previous TreeFileNode object or an empty dictionary if not found.
 function! s:TreeFileNode.findSibling(direction)
-    " if we have no parent then we can have no siblings
-    if self.parent != {}
 
-        " get the index of this node in its parents children
-        let siblingIndx = self.parent.getChildIndex(self.path)
+    " There can be no siblings if there is no parent.
+    if empty(self.parent)
+        return {}
+    endif
+
+    let l:nodeIndex = self.parent.getChildIndex(self.path)
 
-        if siblingIndx != -1
-            " move a long to the next potential sibling node
-            let siblingIndx = a:direction ==# 1 ? siblingIndx+1 : siblingIndx-1
+    if l:nodeIndex == -1
+        return {}
+    endif
 
-            " keep moving along to the next sibling till we find one that is valid
-            let numSiblings = self.parent.getChildCount()
-            while siblingIndx >= 0 && siblingIndx < numSiblings
+    " Get the next index to begin the search.
+    let l:nodeIndex += a:direction ? 1 : -1
 
-                " if the next node is not an ignored node (i.e. wont show up in the
-                " view) then return it
-                if self.parent.children[siblingIndx].path.ignore(self.getNerdtree()) ==# 0
-                    return self.parent.children[siblingIndx]
-                endif
+    while 0 <= l:nodeIndex && l:nodeIndex < self.parent.getChildCount()
 
-                " go to next node
-                let siblingIndx = a:direction ==# 1 ? siblingIndx+1 : siblingIndx-1
-            endwhile
+        " Return the next node if it is not ignored.
+        if !self.parent.children[l:nodeIndex].path.ignore(self.getNerdtree())
+            return self.parent.children[l:nodeIndex]
         endif
-    endif
+
+        let l:nodeIndex += a:direction ? 1 : -1
+    endwhile
 
     return {}
 endfunction