summaryrefslogtreecommitdiff
path: root/.vim/plugin/NERD_tree.vim
diff options
context:
space:
mode:
Diffstat (limited to '.vim/plugin/NERD_tree.vim')
-rw-r--r--.vim/plugin/NERD_tree.vim3917
1 files changed, 3917 insertions, 0 deletions
diff --git a/.vim/plugin/NERD_tree.vim b/.vim/plugin/NERD_tree.vim
new file mode 100644
index 0000000..cb2d422
--- /dev/null
+++ b/.vim/plugin/NERD_tree.vim
@@ -0,0 +1,3917 @@
+" vim global plugin that provides a nice tree explorer
+" Last Change: 26 august 2007
+" Maintainer: Martin Grenfell <martin_grenfell at msn dot com>
+let s:NERD_tree_version = '2.6.2'
+
+"A help file is installed when the script is run for the first time.
+"Go :help NERD_tree.txt to see it.
+
+" SECTION: Script init stuff {{{1
+"============================================================
+if exists("loaded_nerd_tree")
+ finish
+endif
+if v:version < 700
+ echoerr "NERDTree: this plugin requires vim >= 7. DOWNLOAD IT! You'll thank me later!"
+ finish
+endif
+let loaded_nerd_tree = 1
+"Function: s:InitVariable() function {{{2
+"This function is used to initialise a given variable to a given value. The
+"variable is only initialised if it does not exist prior
+"
+"Args:
+"var: the name of the var to be initialised
+"value: the value to initialise var to
+"
+"Returns:
+"1 if the var is set, 0 otherwise
+function! s:InitVariable(var, value)
+ if !exists(a:var)
+ exec 'let ' . a:var . ' = ' . "'" . a:value . "'"
+ return 1
+ endif
+ return 0
+endfunction
+
+"SECTION: Init variable calls and other random constants {{{2
+call s:InitVariable("g:NERDChristmasTree", 1)
+call s:InitVariable("g:NERDTreeAutoCenter", 1)
+call s:InitVariable("g:NERDTreeAutoCenterThreshold", 3)
+call s:InitVariable("g:NERDTreeCaseSensitiveSort", 0)
+call s:InitVariable("g:NERDTreeChDirMode", 1)
+if !exists("g:NERDTreeIgnore")
+ let g:NERDTreeIgnore = ['\~$']
+endif
+call s:InitVariable("g:NERDTreeHighlightCursorline", 1)
+call s:InitVariable("g:NERDTreeMouseMode", 1)
+call s:InitVariable("g:NERDTreeNotificationThreshold", 100)
+call s:InitVariable("g:NERDTreeShowHidden", 0)
+call s:InitVariable("g:NERDTreeShowFiles", 1)
+call s:InitVariable("g:NERDTreeSortDirs", 1)
+
+if !exists("g:NERDTreeSortOrder")
+ let g:NERDTreeSortOrder = ['\/$', '*', '\.swp$', '\.bak$', '\~$']
+else
+ "if there isnt a * in the sort sequence then add one
+ if count(g:NERDTreeSortOrder, '*') < 1
+ call add(g:NERDTreeSortOrder, '*')
+ endif
+endif
+
+"we need to use this number many times for sorting... so we calculate it only
+"once here
+let g:NERDTreeSortStarIndex = index(g:NERDTreeSortOrder, '*')
+
+call s:InitVariable("g:NERDTreeSplitVertical", 1)
+call s:InitVariable("g:NERDTreeWinPos", 1)
+call s:InitVariable("g:NERDTreeWinSize", 31)
+
+let s:running_windows = has("win16") || has("win32") || has("win64")
+
+"init the shell command that will be used to remove dir trees
+"
+"Note: the space after the command is important
+if s:running_windows
+ call s:InitVariable("g:NERDTreeRemoveDirCmd", 'rmdir /s /q ')
+else
+ call s:InitVariable("g:NERDTreeRemoveDirCmd", 'rm -rf ')
+endif
+
+
+"SECTION: Init variable calls for key mappings {{{2
+call s:InitVariable("g:NERDTreeMapActivateNode", "o")
+call s:InitVariable("g:NERDTreeMapChangeRoot", "C")
+call s:InitVariable("g:NERDTreeMapChdir", "cd")
+call s:InitVariable("g:NERDTreeMapCloseChildren", "X")
+call s:InitVariable("g:NERDTreeMapCloseDir", "x")
+call s:InitVariable("g:NERDTreeMapExecute", "!")
+call s:InitVariable("g:NERDTreeMapFilesystemMenu", "m")
+call s:InitVariable("g:NERDTreeMapHelp", "?")
+call s:InitVariable("g:NERDTreeMapJumpFirstChild", "K")
+call s:InitVariable("g:NERDTreeMapJumpLastChild", "J")
+call s:InitVariable("g:NERDTreeMapJumpNextSibling", "<C-j>")
+call s:InitVariable("g:NERDTreeMapJumpParent", "p")
+call s:InitVariable("g:NERDTreeMapJumpPrevSibling", "<C-k>")
+call s:InitVariable("g:NERDTreeMapJumpRoot", "P")
+call s:InitVariable("g:NERDTreeMapOpenExpl", "e")
+call s:InitVariable("g:NERDTreeMapOpenInTab", "t")
+call s:InitVariable("g:NERDTreeMapOpenInTabSilent", "T")
+call s:InitVariable("g:NERDTreeMapOpenRecursively", "O")
+call s:InitVariable("g:NERDTreeMapOpenSplit", "<tab>")
+call s:InitVariable("g:NERDTreeMapPreview", "g" . NERDTreeMapActivateNode)
+call s:InitVariable("g:NERDTreeMapPreviewSplit", "g" . NERDTreeMapOpenSplit)
+call s:InitVariable("g:NERDTreeMapQuit", "q")
+call s:InitVariable("g:NERDTreeMapRefresh", "r")
+call s:InitVariable("g:NERDTreeMapRefreshRoot", "R")
+call s:InitVariable("g:NERDTreeMapToggleFiles", "F")
+call s:InitVariable("g:NERDTreeMapToggleFilters", "f")
+call s:InitVariable("g:NERDTreeMapToggleHidden", "H")
+call s:InitVariable("g:NERDTreeMapUpdir", "u")
+call s:InitVariable("g:NERDTreeMapUpdirKeepOpen", "U")
+
+"SECTION: Script level variable declaration{{{2
+let s:escape_chars = " `|\"~'#"
+let s:NERDTreeWinName = '_NERD_tree_'
+
+"init all the nerd tree markup
+let s:tree_vert = '|'
+let s:tree_vert_last = '`'
+let s:tree_wid = 2
+let s:tree_wid_str = ' '
+let s:tree_wid_strM1 = ' '
+let s:tree_dir_open = '~'
+let s:tree_dir_closed = '+'
+let s:tree_file = '-'
+let s:tree_markup_reg = '[ \-+~`|]'
+let s:tree_markup_reg_neg = '[^ \-+~`|]'
+let s:tree_up_dir_line = '.. (up a dir)'
+let s:tree_RO_str = ' [RO]'
+let s:tree_RO_str_reg = ' \[RO\]'
+
+let s:os_slash = '/'
+if s:running_windows
+ let s:os_slash = '\'
+endif
+
+
+" SECTION: Commands {{{1
+"============================================================
+"init the command that users start the nerd tree with
+command! -n=? -complete=dir NERDTree :call s:InitNerdTree('<args>')
+command! -n=? -complete=dir NERDTreeToggle :call s:Toggle('<args>')
+" SECTION: Auto commands {{{1
+"============================================================
+"Save the cursor position whenever we close the nerd tree
+exec "autocmd BufWinLeave *". s:NERDTreeWinName ."* :call <SID>SaveScreenState()"
+
+"SECTION: Classes {{{1
+"============================================================
+"CLASS: oTreeFileNode {{{2
+"This class is the parent of the oTreeDirNode class and constitures the
+"'Component' part of the composite design pattern between the treenode
+"classes.
+"============================================================
+let s:oTreeFileNode = {}
+"FUNCTION: oTreeFileNode.CompareNodes {{{3
+"This is supposed to be a class level method but i cant figure out how to
+"get func refs to work from a dict..
+"
+"A class level method that compares two nodes
+"
+"Args:
+"n1, n2: the 2 nodes to compare
+function! s:CompareNodes(n1, n2)
+ return a:n1.path.CompareTo(a:n2.path)
+endfunction
+
+"FUNCTION: oTreeFileNode.Delete {{{3
+"Removes this node from the tree and calls the Delete method for its path obj
+function! s:oTreeFileNode.Delete() dict
+ call self.path.Delete()
+ call self.parent.RemoveChild(self)
+endfunction
+
+"FUNCTION: oTreeFileNode.Equals(treenode) {{{3
+"
+"Compares this treenode to the input treenode and returns 1 if they are the
+"same node.
+"
+"Use this method instead of == because sometimes when the treenodes contain
+"many children, vim seg faults when doing ==
+"
+"Args:
+"treenode: the other treenode to compare to
+function! s:oTreeFileNode.Equals(treenode) dict
+ return self.path.Str(1) == a:treenode.path.Str(1)
+endfunction
+
+"FUNCTION: oTreeFileNode.FindNode(path) {{{3
+"Returns self if this node.path.Equals the given path.
+"Returns {} if not equal.
+"
+"Args:
+"path: the path object to compare against
+function! s:oTreeFileNode.FindNode(path) dict
+ if a:path.Equals(self.path)
+ return self
+ endif
+ return {}
+endfunction
+"FUNCTION: oTreeFileNode.FindOpenDirSiblingWithChildren(direction) {{{3
+"
+"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:oTreeFileNode.FindOpenDirSiblingWithChildren(direction) dict
+ "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: oTreeFileNode.FindSibling(direction) {{{3
+"
+"Finds the next sibling for this node in the indicated direction
+"
+"Args:
+"direction: 0 if you want to find the previous sibling, 1 for the next sibling
+"
+"Return:
+"a treenode object or {} if no sibling could be found
+function! s:oTreeFileNode.FindSibling(direction) dict
+ "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)
+
+ if siblingIndx != -1
+ "move a long to the next potential sibling node
+ let siblingIndx = a:direction == 1 ? siblingIndx+1 : siblingIndx-1
+
+ "keep moving along to the next sibling till we find one that is valid
+ let numSiblings = self.parent.GetChildCount()
+ while siblingIndx >= 0 && siblingIndx < numSiblings
+
+ "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() == 0
+ return self.parent.children[siblingIndx]
+ endif
+
+ "go to next node
+ let siblingIndx = a:direction == 1 ? siblingIndx+1 : siblingIndx-1
+ endwhile
+ endif
+ endif
+
+ return {}
+endfunction
+
+"FUNCTION: oTreeFileNode.IsVisible() {{{3
+"returns 1 if this node should be visible according to the tree filters and
+"hidden file filters (and their on/off status)
+function! s:oTreeFileNode.IsVisible() dict
+ return !self.path.Ignore()
+endfunction
+
+
+"FUNCTION: oTreeFileNode.IsRoot() {{{3
+"returns 1 if this node is t:NERDTreeRoot
+function! s:oTreeFileNode.IsRoot() dict
+ if !s:TreeExistsForTab()
+ throw "NERDTree.TreeFileNode.IsRoot exception: No tree exists for the current tab"
+ endif
+ return self.Equals(t:NERDTreeRoot)
+endfunction
+
+"FUNCTION: oTreeFileNode.New(path) {{{3
+"Returns a new TreeNode object with the given path and parent
+"
+"Args:
+"path: a path object representing the full filesystem path to the file/dir that the node represents
+function! s:oTreeFileNode.New(path) dict
+ if a:path.isDirectory
+ return s:oTreeDirNode.New(a:path)
+ else
+ let newTreeNode = {}
+ let newTreeNode = copy(self)
+ let newTreeNode.path = a:path
+ let newTreeNode.parent = {}
+ return newTreeNode
+ endif
+endfunction
+
+"FUNCTION: oTreeFileNode.Rename {{{3
+"Calls the rename method for this nodes path obj
+function! s:oTreeFileNode.Rename(newName) dict
+ call self.path.Rename(a:newName)
+ call self.parent.RemoveChild(self)
+
+ let parentPath = self.path.GetPathTrunk()
+ let newParent = t:NERDTreeRoot.FindNode(parentPath)
+
+ if newParent != {}
+ call newParent.CreateChild(self.path, 1)
+ endif
+endfunction
+
+"FUNCTION: oTreeFileNode.StrDisplay() {{{3
+"
+"Returns a string that specifies how the node should be represented as a
+"string
+"
+"Return:
+"a string that can be used in the view to represent this node
+function! s:oTreeFileNode.StrDisplay() dict
+ return self.path.StrDisplay()
+endfunction
+
+"CLASS: oTreeDirNode {{{2
+"This class is a child of the oTreeFileNode class and constitutes the
+"'Composite' part of the composite design pattern between the treenode
+"classes.
+"============================================================
+let s:oTreeDirNode = copy(s:oTreeFileNode)
+"FUNCTION: oTreeDirNode.AddChild(treenode, inOrder) {{{3
+"Adds the given treenode to the list of children for this node
+"
+"Args:
+"-treenode: the node to add
+"-inOrder: 1 if the new node should be inserted in sorted order
+function! s:oTreeDirNode.AddChild(treenode, inOrder) dict
+ call add(self.children, a:treenode)
+ let a:treenode.parent = self
+
+ if a:inOrder
+ call self.SortChildren()
+ endif
+endfunction
+
+"FUNCTION: oTreeDirNode.Close {{{3
+"Closes this directory
+function! s:oTreeDirNode.Close() dict
+ let self.isOpen = 0
+endfunction
+
+"FUNCTION: oTreeDirNode.CloseChildren {{{3
+"Closes all the child dir nodes of this node
+function! s:oTreeDirNode.CloseChildren() dict
+ for i in self.children
+ if i.path.isDirectory
+ call i.Close()
+ call i.CloseChildren()
+ endif
+ endfor
+endfunction
+
+"FUNCTION: oTreeDirNode.CreateChild(path, inOrder) {{{3
+"Instantiates a new child node for this node with the given path. The new
+"nodes parent is set to this node.
+"
+"Args:
+"path: a Path object that this node will represent/contain
+"inOrder: 1 if the new node should be inserted in sorted order
+"
+"Returns:
+"the newly created node
+function! s:oTreeDirNode.CreateChild(path, inOrder) dict
+ let newTreeNode = s:oTreeFileNode.New(a:path)
+ call self.AddChild(newTreeNode, a:inOrder)
+ return newTreeNode
+endfunction
+
+"FUNCTION: oTreeDirNode.FindNode(path) {{{3
+"Will find one of the children (recursively) that has the given path
+"
+"Args:
+"path: a path object
+unlet s:oTreeDirNode.FindNode
+function! s:oTreeDirNode.FindNode(path) dict
+ if a:path.Equals(self.path)
+ return self
+ endif
+ if stridx(a:path.Str(1), self.path.Str(1), 0) == -1
+ return {}
+ endif
+
+ if self.path.isDirectory
+ for i in self.children
+ let retVal = i.FindNode(a:path)
+ if retVal != {}
+ return retVal
+ endif
+ endfor
+ endif
+ return {}
+endfunction
+
+"FUNCTION: oTreeDirNode.GetChildDirs() {{{3
+"Returns the number of children this node has
+function! s:oTreeDirNode.GetChildCount() dict
+ return len(self.children)
+endfunction
+
+"FUNCTION: oTreeDirNode.GetChildDirs() {{{3
+"Returns an array of all children of this node that are directories
+"
+"Return:
+"an array of directory treenodes
+function! s:oTreeDirNode.GetChildDirs() dict
+ let toReturn = []
+ for i in self.children
+ if i.path.isDirectory
+ call add(toReturn, i)
+ endif
+ endfor
+ return toReturn
+endfunction
+
+"FUNCTION: oTreeDirNode.GetChildFiles() {{{3
+"Returns an array of all children of this node that are files
+"
+"Return:
+"an array of file treenodes
+function! s:oTreeDirNode.GetChildFiles() dict
+ let toReturn = []
+ for i in self.children
+ if i.path.isDirectory == 0
+ call add(toReturn, i)
+ endif
+ endfor
+ return toReturn
+endfunction
+
+"FUNCTION: oTreeDirNode.GetChild(path) {{{3
+"Returns child node of this node that has the given path or {} if no such node
+"exists.
+"
+"This function doesnt not recurse into child dir nodes
+"
+"Args:
+"path: a path object
+function! s:oTreeDirNode.GetChild(path) dict
+ if stridx(a:path.Str(1), self.path.Str(1), 0) == -1
+ return {}
+ endif
+
+ let index = self.GetChildIndex(a:path)
+ if index == -1
+ return {}
+ else
+ return self.children[index]
+ endif
+
+endfunction
+
+"FUNCTION: oTreeDirNode.GetChildByIndex(indx, visible) {{{3
+"returns the child at the given index
+"Args:
+"indx: the index to get the child from
+"visible: 1 if only the visible children array should be used, 0 if all the
+"children should be searched.
+function! s:oTreeDirNode.GetChildByIndex(indx, visible) dict
+ let array_to_search = a:visible? self.GetVisibleChildren() : self.children
+ if a:indx > len(array_to_search)
+ throw "NERDTree.TreeDirNode.InvalidArguments exception. Index is out of bounds."
+ endif
+ return array_to_search[a:indx]
+endfunction
+
+"FUNCTION: oTreeDirNode.GetChildIndex(path) {{{3
+"Returns the index of the child node of this node that has the given path or
+"-1 if no such node exists.
+"
+"This function doesnt not recurse into child dir nodes
+"
+"Args:
+"path: a path object
+function! s:oTreeDirNode.GetChildIndex(path) dict
+ if stridx(a:path.Str(1), self.path.Str(1), 0) == -1
+ return -1
+ endif
+
+ "do a binary search for the child
+ let a = 0
+ let z = self.GetChildCount()
+ while a < z
+ let mid = (a+z)/2
+ let diff = a:path.CompareTo(self.children[mid].path)
+
+ if diff == -1
+ let z = mid
+ elseif diff == 1
+ let a = mid+1
+ else
+ return mid
+ endif
+ endwhile
+ return -1
+endfunction
+
+"FUNCTION: oTreeDirNode.GetVisibleChildCount() {{{3
+"Returns the number of visible children this node has
+function! s:oTreeDirNode.GetVisibleChildCount() dict
+ return len(self.GetVisibleChildren())
+endfunction
+
+"FUNCTION: oTreeDirNode.GetVisibleChildren() {{{3
+"Returns a list of children to display for this node, in the correct order
+"
+"Return:
+"an array of treenodes
+function! s:oTreeDirNode.GetVisibleChildren() dict
+ let toReturn = []
+ for i in self.children
+ if i.path.Ignore() == 0
+ call add(toReturn, i)
+ endif
+ endfor
+ return toReturn
+endfunction
+
+"FUNCTION: oTreeDirNode.HasVisibleChildren {{{3
+"returns 1 if this node has any childre, 0 otherwise..
+function! s:oTreeDirNode.HasVisibleChildren()
+ return self.GetChildCount() != 0
+endfunction
+
+"FUNCTION: oTreeDirNode.InitChildren {{{3
+"Removes all childen from this node and re-reads them
+"
+"Args:
+"silent: 1 if the function should not echo any "please wait" messages for
+"large directories
+"
+"Return: the number of child nodes read
+function! s:oTreeDirNode.InitChildren(silent) dict
+ "remove all the current child nodes
+ let self.children = []
+
+ "get an array of all the files in the nodes dir
+ let filesStr = globpath(self.path.GetDir(0), '*') . "\n" . globpath(self.path.GetDir(0), '.*')
+ let files = split(filesStr, "\n")
+
+ if !a:silent && len(files) > g:NERDTreeNotificationThreshold
+ call s:Echo("Please wait, caching a large dir ...")
+ endif
+
+ let invalidFilesFound = 0
+ for i in files
+
+ "filter out the .. and . directories
+ if i !~ '\.\.$' && i !~ '\.$'
+
+ "put the next file in a new node and attach it
+ try
+ let path = s:oPath.New(i)
+ call self.CreateChild(path, 0)
+ catch /^NERDTree.Path.InvalidArguments/
+ let invalidFilesFound = 1
+ endtry
+ endif
+ endfor
+
+ call self.SortChildren()
+
+ if !a:silent && len(files) > g:NERDTreeNotificationThreshold
+ call s:Echo("Please wait, caching a large dir ...")
+ call s:Echo("Please wait, caching a large dir ... DONE (". self.GetChildCount() ." nodes cached).")
+ endif
+
+ if invalidFilesFound
+ call s:EchoWarning("some files could not be loaded into the NERD tree")
+ endif
+ return self.GetChildCount()
+endfunction
+"FUNCTION: oTreeDirNode.New(path) {{{3
+"Returns a new TreeNode object with the given path and parent
+"
+"Args:
+"path: a path object representing the full filesystem path to the file/dir that the node represents
+unlet s:oTreeDirNode.New
+function! s:oTreeDirNode.New(path) dict
+ if a:path.isDirectory != 1
+ throw "NERDTree.TreeDirNode.InvalidArguments exception. A TreeDirNode object must be instantiated with a directory Path object."
+ endif
+
+ let newTreeNode = copy(self)
+ let newTreeNode.path = a:path
+
+ let newTreeNode.isOpen = 0
+ let newTreeNode.children = []
+
+ let newTreeNode.parent = {}
+
+ return newTreeNode
+endfunction
+"FUNCTION: oTreeDirNode.Open {{{3
+"Reads in all this nodes children
+"
+"Return: the number of child nodes read
+function! s:oTreeDirNode.Open() dict
+ let self.isOpen = 1
+ if self.children == []
+ return self.InitChildren(0)
+ else
+ return 0
+ endif
+endfunction
+
+"FUNCTION: oTreeDirNode.OpenRecursively {{{3
+"Opens this treenode and all of its children whose paths arent 'ignored'
+"because of the file filters.
+"
+"This method is actually a wrapper for the OpenRecursively2 method which does
+"the work.
+function! s:oTreeDirNode.OpenRecursively() dict
+ call self.OpenRecursively2(1)
+endfunction
+
+"FUNCTION: oTreeDirNode.OpenRecursively2 {{{3
+"Dont call this method from outside this object.
+"
+"Opens this all children of this treenode recursively if either:
+" *they arent filtered by file filters
+" *a:forceOpen is 1
+"
+"Args:
+"forceOpen: 1 if this node should be opened regardless of file filters
+function! s:oTreeDirNode.OpenRecursively2(forceOpen) dict
+ if self.path.Ignore() == 0 || a:forceOpen
+ let self.isOpen = 1
+ if self.children == []
+ call self.InitChildren(1)
+ endif
+
+ for i in self.children
+ if i.path.isDirectory == 1
+ call i.OpenRecursively2(0)
+ endif
+ endfor
+ endif
+endfunction
+
+"FUNCTION: oTreeDirNode.Refresh {{{3
+function! s:oTreeDirNode.Refresh() dict
+ let newChildNodes = []
+ let invalidFilesFound = 0
+
+ "go thru all the files/dirs under this node
+ let filesStr = globpath(self.path.GetDir(0), '*') . "\n" . globpath(self.path.GetDir(0), '.*')
+ let files = split(filesStr, "\n")
+ for i in files
+ if i !~ '\.\.$' && i !~ '\.$'
+
+ try
+ "create a new path and see if it exists in this nodes children
+ let path = s:oPath.New(i)
+ let newNode = self.GetChild(path)
+ if newNode != {}
+
+ "if the existing node is a dir can be refreshed then
+ "refresh it
+ if newNode.path.isDirectory && (!empty(newNode.children) || newNode.isOpen == 1)
+ call newNode.Refresh()
+
+ "if we have a filenode then refresh the path
+ elseif newNode.path.isDirectory == 0
+ call newNode.path.Refresh()
+ endif
+
+ call add(newChildNodes, newNode)
+
+ "the node doesnt exist so create it
+ else
+ let newNode = s:oTreeFileNode.New(path)
+ let newNode.parent = self
+ call add(newChildNodes, newNode)
+ endif
+
+
+ catch /^NERDTree.InvalidArguments/
+ let invalidFilesFound = 1
+ endtry
+ endif
+ endfor
+
+ "swap this nodes children out for the children we just read/refreshed
+ let self.children = newChildNodes
+ call self.SortChildren()
+
+ if invalidFilesFound
+ call s:EchoWarning("some files could not be loaded into the NERD tree")
+ endif
+endfunction
+
+"FUNCTION: oTreeDirNode.RemoveChild {{{3
+"
+"Removes the given treenode from this nodes set of children
+"
+"Args:
+"treenode: the node to remove
+"
+"Throws a NERDTree.TreeDirNode exception if the given treenode is not found
+function! s:oTreeDirNode.RemoveChild(treenode) dict
+ for i in range(0, self.GetChildCount()-1)
+ if self.children[i].Equals(a:treenode)
+ call remove(self.children, i)
+ return
+ endif
+ endfor
+
+ throw "NERDTree.TreeDirNode exception: child node was not found"
+endfunction
+
+"FUNCTION: oTreeDirNode.SortChildren {{{3
+"
+"Sorts the children of this node according to alphabetical order and the
+"directory priority.
+"
+function! s:oTreeDirNode.SortChildren() dict
+ let CompareFunc = function("s:CompareNodes")
+ call sort(self.children, CompareFunc)
+endfunction
+
+"FUNCTION: oTreeDirNode.ToggleOpen {{{3
+"Opens this directory if it is closed and vice versa
+function! s:oTreeDirNode.ToggleOpen() dict
+ if self.isOpen == 1
+ call self.Close()
+ else
+ call self.Open()
+ endif
+endfunction
+
+"FUNCTION: oTreeDirNode.TransplantChild(newNode) {{{3
+"Replaces the child of this with the given node (where the child node's full
+"path matches a:newNode's fullpath). The search for the matching node is
+"non-recursive
+"
+"Arg:
+"newNode: the node to graft into the tree
+function! s:oTreeDirNode.TransplantChild(newNode) dict
+ for i in range(0, self.GetChildCount()-1)
+ if self.children[i].Equals(a:newNode)
+ let self.children[i] = a:newNode
+ let a:newNode.parent = self
+ break
+ endif
+ endfor
+endfunction
+"============================================================
+"CLASS: oPath {{{2
+"============================================================
+let s:oPath = {}
+"FUNCTION: oPath.ChangeToDir() {{{3
+function! s:oPath.ChangeToDir() dict
+ let dir = self.Str(1)
+ if self.isDirectory == 0
+ let dir = self.GetPathTrunk().Str(1)
+ endif
+
+ try
+ execute "cd " . dir
+ call s:Echo("CWD is now: " . getcwd())
+ catch
+ throw "NERDTree.Path.Change exception: cannot change to " . dir
+ endtry
+endfunction
+
+"FUNCTION: oPath.ChopTrailingSlash(str) {{{3
+function! s:oPath.ChopTrailingSlash(str) dict
+ if a:str =~ '\/$'
+ return substitute(a:str, "\/$", "", "")
+ else
+ return substitute(a:str, "\\$", "", "")
+ endif
+endfunction
+
+"FUNCTION: oPath.CompareTo() {{{3
+"
+"Compares this oPath to the given path and returns 0 if they are equal, -1 if
+"this oPath is "less than" the given path, or 1 if it is "greater".
+"
+"Args:
+"path: the path object to compare this to
+"
+"Return:
+"1, -1 or 0
+function! s:oPath.CompareTo(path) dict
+ let thisPath = self.GetLastPathComponent(1)
+ let thatPath = a:path.GetLastPathComponent(1)
+
+ "if the paths are the same then clearly we return 0
+ if thisPath == thatPath
+ return 0
+ endif
+
+ let thisSS = self.GetSortOrderIndex()
+ let thatSS = a:path.GetSortOrderIndex()
+
+ "compare the sort sequences, if they are different then the return
+ "value is easy
+ if thisSS < thatSS
+ return -1
+ elseif thisSS > thatSS
+ return 1
+ else
+ "if the sort sequences are the same then compare the paths
+ "alphabetically
+ let pathCompare = g:NERDTreeCaseSensitiveSort ? thisPath <# thatPath : thisPath <? thatPath
+ if pathCompare
+ return -1
+ else
+ return 1
+ endif
+ endif
+endfunction
+
+"FUNCTION: oPath.Create() {{{3
+"
+"Factory method.
+"
+"Creates a path object with the given path. The path is also created on the
+"filesystem. If the path already exists, a NERDTree.Path.Exists exception is
+"thrown. If any other errors occur, a NERDTree.Path exception is thrown.
+"
+"Args:
+"fullpath: the full filesystem path to the file/dir to create
+function! s:oPath.Create(fullpath) dict
+ "bail if the a:fullpath already exists
+ if isdirectory(a:fullpath) || filereadable(a:fullpath)
+ throw "NERDTree.Path.Exists Exception: Directory Exists: '" . a:fullpath . "'"
+ endif
+
+ "get the unix version of the input path
+ let fullpath = a:fullpath
+ if s:running_windows
+ let fullpath = s:oPath.WinToUnixPath(fullpath)
+ endif
+
+ try
+
+ "if it ends with a slash, assume its a dir create it
+ if fullpath =~ '\/$'
+ "whack the trailing slash off the end if it exists
+ let fullpath = substitute(fullpath, '\/$', '', '')
+
+ call mkdir(fullpath, 'p')
+
+ "assume its a file and create
+ else
+ call writefile([], fullpath)
+ endif
+ catch /.*/
+ throw "NERDTree.Path Exception: Could not create path: '" . a:fullpath . "'"
+ endtry
+
+ return s:oPath.New(fullpath)
+endfunction
+
+"FUNCTION: oPath.Delete() {{{3
+"
+"Deletes the file represented by this path.
+"Deletion of directories is not supported
+"
+"Throws NERDTree.Path.Deletion exceptions
+function! s:oPath.Delete() dict
+ if self.isDirectory
+
+ let cmd = ""
+ if s:running_windows
+ "if we are runnnig windows then put quotes around the pathstring
+ let cmd = g:NERDTreeRemoveDirCmd . self.StrForOS(1)
+ else
+ let cmd = g:NERDTreeRemoveDirCmd . self.StrForOS(0)
+ endif
+ let success = system(cmd)
+
+ if v:shell_error != 0
+ throw "NERDTree.Path.Deletion Exception: Could not delete directory: '" . self.StrForOS(0) . "'"
+ endif
+ else
+ let success = delete(self.Str(0))
+ if success != 0
+ throw "NERDTree.Path.Deletion Exception: Could not delete file: '" . self.Str(0) . "'"
+ endif
+ endif
+endfunction
+
+"FUNCTION: oPath.GetDir() {{{3
+"
+"Gets the directory part of this path. If this path IS a directory then the
+"whole thing is returned
+"
+"Args:
+"trailingSlash: 1 if a trailing slash is to be stuck on the end of the
+"returned dir
+"
+"Return:
+"string
+function! s:oPath.GetDir(trailingSlash) dict
+ let toReturn = ''
+ if self.isDirectory
+ let toReturn = '/'. join(self.pathSegments, '/')
+ else
+ let toReturn = '/'. join(self.pathSegments[0:-2], '/')
+ endif
+
+ if a:trailingSlash && toReturn !~ '\/$'
+ let toReturn = toReturn . '/'
+ endif
+
+ return toReturn
+endfunction
+
+"FUNCTION: oPath.GetFile() {{{3
+"
+"Returns the file component of this path.
+"
+"Throws NERDTree.IllegalOperation exception if the node is a directory node
+function! s:oPath.GetFile() dict
+ if self.isDirectory == 0
+ return self.GetLastPathComponent(0)
+ else
+ throw "NERDTree.Path.IllegalOperation Exception: cannot get file component of a directory path"
+ endif
+endfunction
+
+"FUNCTION: oPath.GetLastPathComponent(dirSlash) {{{3
+"
+"Gets the last part of this path.
+"
+"Args:
+"dirSlash: if 1 then a trailing slash will be added to the returned value for
+"directory nodes.
+function! s:oPath.GetLastPathComponent(dirSlash) dict
+ if empty(self.pathSegments)
+ return ''
+ endif
+ let toReturn = self.pathSegments[-1]
+ if a:dirSlash && self.isDirectory
+ let toReturn = toReturn . '/'
+ endif
+ return toReturn
+endfunction
+
+"FUNCTION: oPath.GetPathTrunk() {{{3
+"Gets the path without the last segment on the end.
+function! s:oPath.GetPathTrunk() dict
+ return s:oPath.New('/' . join(self.pathSegments[0:-2], '/'))
+endfunction
+
+"FUNCTION: oPath.GetSortOrderIndex() {{{3
+"returns the index of the pattern in g:NERDTreeSortOrder that this path matches
+function! s:oPath.GetSortOrderIndex() dict
+ let i = 0
+ while i < len(g:NERDTreeSortOrder)
+ if self.GetLastPathComponent(1) =~ g:NERDTreeSortOrder[i]
+ return i
+ endif
+ let i = i + 1
+ endwhile
+ return g:NERDTreeSortStarIndex
+endfunction
+
+"FUNCTION: oPath.Ignore() {{{3
+"returns true if this path should be ignored
+function! s:oPath.Ignore() dict
+ let lastPathComponent = self.GetLastPathComponent(0)
+
+ "filter out the user specified paths to ignore
+ if t:NERDTreeIgnoreEnabled
+ for i in g:NERDTreeIgnore
+ if lastPathComponent =~ i
+ return 1
+ endif
+ endfor
+ endif
+
+ "dont show hidden files unless instructed to
+ if g:NERDTreeShowHidden == 0 && lastPathComponent =~ '^\.'
+ return 1
+ endif
+
+ if g:NERDTreeShowFiles == 0 && self.isDirectory == 0
+ return 1
+ endif
+
+ return 0
+endfunction
+
+"FUNCTION: oPath.Equals() {{{3
+"
+"Determines whether 2 path objecs are "equal".
+"They are equal if the paths they represent are the same
+"
+"Args:
+"path: the other path obj to compare this with
+function! s:oPath.Equals(path) dict
+ let this = self.ChopTrailingSlash(self.Str(1))
+ let that = self.ChopTrailingSlash(a:path.Str(1))
+ return this == that
+endfunction
+
+"FUNCTION: oPath.New() {{{3
+"
+"The Constructor for the Path object
+"Throws NERDTree.Path.InvalidArguments exception.
+function! s:oPath.New(fullpath) dict
+ let newPath = copy(self)
+
+ call newPath.ReadInfoFromDisk(a:fullpath)
+
+ return newPath
+endfunction
+
+"FUNCTION: oPath.NewMinimal() {{{3
+function! s:oPath.NewMinimal(fullpath) dict
+ let newPath = copy(self)
+
+ let fullpath = a:fullpath
+
+ if s:running_windows
+ let fullpath = s:oPath.WinToUnixPath(fullpath)
+ endif
+
+ let newPath.pathSegments = split(fullpath, '/')
+
+ let newPath.isDirectory = isdirectory(fullpath)
+
+ return newPath
+endfunction
+
+"FUNCTION: oPath.ReadInfoFromDisk(fullpath) {{{3
+"
+"
+"Throws NERDTree.Path.InvalidArguments exception.
+function! s:oPath.ReadInfoFromDisk(fullpath) dict
+ let fullpath = a:fullpath
+
+ if s:running_windows
+ let fullpath = s:oPath.WinToUnixPath(fullpath)
+ endif
+
+ let self.pathSegments = split(fullpath, '/')
+
+ let self.isReadOnly = 0
+ if isdirectory(fullpath)
+ let self.isDirectory = 1
+ elseif filereadable(fullpath)
+ let self.isDirectory = 0
+ let self.isReadOnly = filewritable(fullpath) == 0
+ else
+ throw "NERDTree.Path.InvalidArguments Exception: Invalid path = " . fullpath
+ endif
+
+ "grab the last part of the path (minus the trailing slash)
+ let lastPathComponent = self.GetLastPathComponent(0)
+
+ "get the path to the new node with the parent dir fully resolved
+ let hardPath = resolve(self.StrTrunk()) . '/' . lastPathComponent
+
+ "if the last part of the path is a symlink then flag it as such
+ let self.isSymLink = (resolve(hardPath) != hardPath)
+ if self.isSymLink
+ let self.symLinkDest = resolve(fullpath)
+
+ "if the link is a dir then slap a / on the end of its dest
+ if isdirectory(self.symLinkDest)
+
+ "we always wanna treat MS windows shortcuts as files for
+ "simplicity
+ if hardPath !~ '\.lnk$'
+
+ let self.symLinkDest = self.symLinkDest . '/'
+ endif
+ endif
+ endif
+endfunction
+
+"FUNCTION: oPath.Refresh() {{{3
+function! s:oPath.Refresh() dict
+ call self.ReadInfoFromDisk(self.Str(0))
+endfunction
+
+"FUNCTION: oPath.Rename() {{{3
+"
+"Renames this node on the filesystem
+function! s:oPath.Rename(newPath) dict
+ if a:newPath == ''
+ throw "NERDTree.Path.InvalidArguments exception. Invalid newPath for renaming = ". a:newPath
+ endif
+
+ let success = rename(self.Str(0), a:newPath)
+ if success != 0
+ throw "NERDTree.Path.Rename Exception: Could not rename: '" . self.Str(0) . "'" . 'to:' . a:newPath
+ endif
+ let self.pathSegments = split(a:newPath, '/')
+endfunction
+
+"FUNCTION: oPath.Str(esc) {{{3
+"
+"Gets the actual string path that this obj represents.
+"
+"Args:
+"esc: if 1 then all the tricky chars in the returned string will be escaped
+function! s:oPath.Str(esc) dict
+ let toReturn = '/' . join(self.pathSegments, '/')
+ if self.isDirectory && toReturn != '/'
+ let toReturn = toReturn . '/'
+ endif
+
+ if a:esc
+ let toReturn = escape(toReturn, s:escape_chars)
+ endif
+ return toReturn