diff options
Diffstat (limited to '.vim/plugin/NERD_tree.vim')
-rw-r--r-- | .vim/plugin/NERD_tree.vim | 3917 |
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 |