Skip to content

Commit a102242

Browse files
author
marty
committed
latest nerdtree
1 parent a0ded8f commit a102242

File tree

2 files changed

+170
-49
lines changed

2 files changed

+170
-49
lines changed

doc/NERD_tree.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,11 @@ The following features and functionality are provided by the NERD tree:
128128
:NERDTreeClose *:NERDTreeClose*
129129
Close the NERD tree in this tab.
130130

131+
:NERDTreeFind *:NERDTreeFind*
132+
Find the current file in the tree. If no tree exists for the current tab,
133+
or the file is not under the current root, then initialize a new tree where
134+
the root is the directory of the current file.
135+
131136
------------------------------------------------------------------------------
132137
2.2. Bookmarks *NERDTreeBookmarks*
133138

@@ -803,7 +808,7 @@ Values: 0 or 1.
803808
Default: 0
804809

805810
If set to 1, the NERD tree window will close after opening a file with the
806-
|NERDTree-o| or |NERDTree-i| mappings.
811+
|NERDTree-o|, |NERDTree-i|, |NERDTree-t| and |NERDTree-T| mappings.
807812

808813
------------------------------------------------------------------------------
809814
*'NERDTreeShowBookmarks'*

plugin/NERD_tree.vim

Lines changed: 164 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,11 @@ call s:initVariable("g:NERDTreeMapUpdir", "u")
139139
call s:initVariable("g:NERDTreeMapUpdirKeepOpen", "U")
140140

141141
"SECTION: Script level variable declaration{{{2
142-
let s:escape_chars = " \\`\|\"#%&,?()\*^<>"
142+
if s:running_windows
143+
let s:escape_chars = " `\|\"#%&,?()\*^<>"
144+
else
145+
let s:escape_chars = " \\`\|\"#%&,?()\*^<>"
146+
endif
143147
let s:NERDTreeBufName = 'NERD_tree_'
144148

145149
let s:tree_wid = 2
@@ -157,6 +161,7 @@ command! -n=? -complete=dir -bar NERDTreeToggle :call s:toggle('<args>')
157161
command! -n=0 -bar NERDTreeClose :call s:closeTreeIfOpen()
158162
command! -n=1 -complete=customlist,s:completeBookmarks -bar NERDTreeFromBookmark call s:initNerdTree('<args>')
159163
command! -n=0 -bar NERDTreeMirror call s:initNerdTreeMirror()
164+
command! -n=0 -bar NERDTreeFind call s:findAndRevealPath()
160165
" SECTION: Auto commands {{{1
161166
"============================================================
162167
augroup NERDTree
@@ -332,6 +337,21 @@ function! s:Bookmark.GetNodeForName(name, searchFromAbsoluteRoot)
332337
let bookmark = s:Bookmark.BookmarkFor(a:name)
333338
return bookmark.getNode(a:searchFromAbsoluteRoot)
334339
endfunction
340+
" FUNCTION: Bookmark.GetSelected() {{{3
341+
" returns the Bookmark the cursor is over, or {}
342+
function! s:Bookmark.GetSelected()
343+
let line = getline(".")
344+
let name = substitute(line, '^>\(.\{-}\) .\+$', '\1', '')
345+
if name != line
346+
try
347+
return s:Bookmark.BookmarkFor(name)
348+
catch /^NERDTree.BookmarkNotFoundError/
349+
return {}
350+
endtry
351+
endif
352+
return {}
353+
endfunction
354+
335355
" Function: Bookmark.InvalidBookmarks() {{{3
336356
" Class method to get all invalid bookmark strings read from the bookmarks
337357
" file
@@ -361,6 +381,21 @@ function! s:Bookmark.New(name, path)
361381
let newBookmark.path = a:path
362382
return newBookmark
363383
endfunction
384+
" FUNCTION: Bookmark.openInNewTab(options) {{{3
385+
" Create a new bookmark object with the given name and path object
386+
function! s:Bookmark.openInNewTab(options)
387+
let currentTab = tabpagenr()
388+
if self.path.isDirectory
389+
tabnew
390+
call s:initNerdTree(self.name)
391+
else
392+
exec "tabedit " . bookmark.path.str({'format': 'Edit'})
393+
endif
394+
395+
if has_key(a:options, 'stayInCurrentTab')
396+
exec "tabnext " . currentTab
397+
endif
398+
endfunction
364399
" Function: Bookmark.setPath(path) {{{3
365400
" makes this bookmark point to the given path
366401
function! s:Bookmark.setPath(path)
@@ -981,11 +1016,19 @@ function! s:TreeFileNode.getLineNum()
9811016
return -1
9821017
endfunction
9831018

1019+
"FUNCTION: TreeFileNode.GetRootForTab(){{{3
1020+
"get the root node for this tab
1021+
function! s:TreeFileNode.GetRootForTab()
1022+
if s:treeExistsForTab()
1023+
return getbufvar(t:NERDTreeBufName, 'NERDTreeRoot')
1024+
end
1025+
return {}
1026+
endfunction
9841027
"FUNCTION: TreeFileNode.GetRootLineNum(){{{3
9851028
"gets the line number of the root node
9861029
function! s:TreeFileNode.GetRootLineNum()
9871030
let rootLine = 1
988-
while getline(rootLine) !~ '^/'
1031+
while getline(rootLine) !~ '^\(/\|<\)'
9891032
let rootLine = rootLine + 1
9901033
endwhile
9911034
return rootLine
@@ -1177,6 +1220,21 @@ function! s:TreeFileNode.openVSplit()
11771220
exec("silent vertical resize ". winwidth)
11781221
call s:exec('wincmd p')
11791222
endfunction
1223+
"FUNCTION: TreeFileNode.openInNewTab(options) {{{3
1224+
function! s:TreeFileNode.openInNewTab(options)
1225+
let currentTab = tabpagenr()
1226+
1227+
if !has_key(a:options, 'keepTreeOpen')
1228+
call s:closeTreeIfQuitOnOpen()
1229+
endif
1230+
1231+
exec "tabedit " . self.path.str({'format': 'Edit'})
1232+
1233+
if has_key(a:options, 'stayInCurrentTab') && a:options['stayInCurrentTab']
1234+
exec "tabnext " . currentTab
1235+
endif
1236+
1237+
endfunction
11801238
"FUNCTION: TreeFileNode.putCursorHere(isJump, recurseUpward){{{3
11811239
"Places the cursor on the line number this node is rendered on
11821240
"
@@ -1606,6 +1664,22 @@ function! s:TreeDirNode.openExplorer()
16061664
exec ("silent edit " . self.path.str({'format': 'Edit'}))
16071665
endif
16081666
endfunction
1667+
"FUNCTION: TreeDirNode.openInNewTab(options) {{{3
1668+
unlet s:TreeDirNode.openInNewTab
1669+
function! s:TreeDirNode.openInNewTab(options)
1670+
let currentTab = tabpagenr()
1671+
1672+
if !has_key(a:options, 'keepTreeOpen') || !a:options['keepTreeOpen']
1673+
call s:closeTreeIfQuitOnOpen()
1674+
endif
1675+
1676+
tabnew
1677+
call s:initNerdTree(self.path.str())
1678+
1679+
if has_key(a:options, 'stayInCurrentTab') && a:options['stayInCurrentTab']
1680+
exec "tabnext " . currentTab
1681+
endif
1682+
endfunction
16091683
"FUNCTION: TreeDirNode.openRecursively() {{{3
16101684
"Opens this treenode and all of its children whose paths arent 'ignored'
16111685
"because of the file filters.
@@ -1690,6 +1764,31 @@ function! s:TreeDirNode.refresh()
16901764
endif
16911765
endfunction
16921766

1767+
"FUNCTION: TreeDirNode.reveal(path) {{{3
1768+
"reveal the given path, i.e. cache and open all treenodes needed to display it
1769+
"in the UI
1770+
function! s:TreeDirNode.reveal(path)
1771+
if !a:path.isUnder(self.path)
1772+
throw "NERDTree.InvalidArgumentsError: " . a:path.str() . " should be under " . self.path.str()
1773+
endif
1774+
1775+
call self.open()
1776+
1777+
if self.path.equals(a:path.getParent())
1778+
let n = self.findNode(a:path)
1779+
call s:renderView()
1780+
call n.putCursorHere(1,0)
1781+
return
1782+
endif
1783+
1784+
let p = a:path
1785+
while !p.getParent().equals(self.path)
1786+
let p = p.getParent()
1787+
endwhile
1788+
1789+
let n = self.findNode(p)
1790+
call n.reveal(a:path)
1791+
endfunction
16931792
"FUNCTION: TreeDirNode.removeChild(treenode) {{{3
16941793
"
16951794
"Removes the given treenode from this nodes set of children
@@ -2079,6 +2178,20 @@ function! s:Path.ignore()
20792178
return 0
20802179
endfunction
20812180

2181+
"FUNCTION: Path.isUnder(path) {{{3
2182+
"return 1 if this path is somewhere under the given path in the filesystem.
2183+
"
2184+
"a:path should be a dir
2185+
function! s:Path.isUnder(path)
2186+
if a:path.isDirectory == 0
2187+
return 0
2188+
endif
2189+
2190+
let this = self.str()
2191+
let that = a:path.str()
2192+
return stridx(this, that . s:Path.Slash()) == 0
2193+
endfunction
2194+
20822195
"FUNCTION: Path.JoinPathStrings(...) {{{3
20832196
function! s:Path.JoinPathStrings(...)
20842197
let components = []
@@ -2208,16 +2321,18 @@ endfunction
22082321
"The dict may have the following keys:
22092322
" 'format'
22102323
" 'escape'
2324+
" 'truncateTo'
22112325
"
22122326
"The 'format' key may have a value of:
22132327
" 'Cd' - a string to be used with the :cd command
22142328
" 'Edit' - a string to be used with :e :sp :new :tabedit etc
22152329
" 'UI' - a string used in the NERD tree UI
22162330
"
2217-
"If not specified, a generic unix style path string will be returned
2218-
"
22192331
"The 'escape' key, if specified will cause the output to be escaped with
22202332
"shellescape()
2333+
"
2334+
"The 'truncateTo' key causes the resulting string to be truncated to the value
2335+
"'truncateTo' maps to. A '<' char will be prepended.
22212336
function! s:Path.str(...)
22222337
let options = a:0 ? a:1 : {}
22232338
let toReturn = ""
@@ -2237,6 +2352,13 @@ function! s:Path.str(...)
22372352
let toReturn = shellescape(toReturn)
22382353
endif
22392354

2355+
if has_key(options, 'truncateTo')
2356+
let limit = options['truncateTo']
2357+
if len(toReturn) > limit
2358+
let toReturn = "<" . strpart(toReturn, len(toReturn) - limit + 1)
2359+
endif
2360+
endif
2361+
22402362
return toReturn
22412363
endfunction
22422364

@@ -2396,6 +2518,29 @@ function! s:exec(cmd)
23962518
exec a:cmd
23972519
let &ei = old_ei
23982520
endfunction
2521+
" FUNCTION: s:findAndRevealPath() {{{2
2522+
function! s:findAndRevealPath()
2523+
try
2524+
let p = s:Path.New(expand("%"))
2525+
catch /^NERDTree.InvalidArgumentsError/
2526+
call s:echo("no file for the current buffer")
2527+
return
2528+
endtry
2529+
2530+
if !s:treeExistsForTab()
2531+
call s:initNerdTree(p.getParent().str())
2532+
else
2533+
if !p.isUnder(s:TreeFileNode.GetRootForTab().path)
2534+
call s:initNerdTree(p.getParent().str())
2535+
else
2536+
if !s:isTreeOpen()
2537+
call s:toggle("")
2538+
endif
2539+
endif
2540+
endif
2541+
call s:putCursorInTreeWin()
2542+
call b:NERDTreeRoot.reveal(p)
2543+
endfunction
23992544
"FUNCTION: s:initNerdTree(name) {{{2
24002545
"Initialise the nerd tree for this tab. The tree will start in either the
24012546
"given directory, or the directory associated with the given bookmark
@@ -2898,8 +3043,10 @@ endfunction
28983043
function! s:getPath(ln)
28993044
let line = getline(a:ln)
29003045

3046+
let rootLine = s:TreeFileNode.GetRootLineNum()
3047+
29013048
"check to see if we have the root node
2902-
if line =~ '^\/'
3049+
if a:ln == rootLine
29033050
return b:NERDTreeRoot.path
29043051
endif
29053052

@@ -2923,7 +3070,6 @@ function! s:getPath(ln)
29233070
let curFile = substitute(curFile, '/\?$', '/', "")
29243071
endif
29253072

2926-
29273073
let dir = ""
29283074
let lnum = a:ln
29293075
while lnum > 0
@@ -2932,8 +3078,8 @@ function! s:getPath(ln)
29323078
let curLineStripped = s:stripMarkupFromLine(curLine, 1)
29333079

29343080
"have we reached the top of the tree?
2935-
if curLine =~ '^/'
2936-
let dir = substitute (curLine, ' *$', "", "") . dir
3081+
if lnum == rootLine
3082+
let dir = b:NERDTreeRoot.path.str({'format': 'UI'}) . dir
29373083
break
29383084
endif
29393085
if curLineStripped =~ '/$'
@@ -2951,21 +3097,6 @@ function! s:getPath(ln)
29513097
return toReturn
29523098
endfunction
29533099

2954-
"FUNCTION: s:getSelectedBookmark() {{{2
2955-
"returns the bookmark the cursor is over in the bookmarks table or {}
2956-
function! s:getSelectedBookmark()
2957-
let line = getline(".")
2958-
let name = substitute(line, '^>\(.\{-}\) .\+$', '\1', '')
2959-
if name != line
2960-
try
2961-
return s:Bookmark.BookmarkFor(name)
2962-
catch /^NERDTree.BookmarkNotFoundError/
2963-
return {}
2964-
endtry
2965-
endif
2966-
return {}
2967-
endfunction
2968-
29693100
"FUNCTION: s:getTreeWinNum() {{{2
29703101
"gets the nerd tree window number for this tab
29713102
function! s:getTreeWinNum()
@@ -3132,7 +3263,8 @@ function! s:renderView()
31323263
call cursor(line(".")+1, col("."))
31333264

31343265
"draw the header line
3135-
call setline(line(".")+1, b:NERDTreeRoot.path.str({'format': 'UI'}))
3266+
let header = b:NERDTreeRoot.path.str({'format': 'UI', 'truncateTo': winwidth(0)})
3267+
call setline(line(".")+1, header)
31363268
call cursor(line(".")+1, col("."))
31373269

31383270
"draw the tree
@@ -3381,7 +3513,7 @@ function! s:activateNode(forceKeepWindowOpen)
33813513
if treenode != {}
33823514
call treenode.activate(a:forceKeepWindowOpen)
33833515
else
3384-
let bookmark = s:getSelectedBookmark()
3516+
let bookmark = s:Bookmark.GetSelected()
33853517
if !empty(bookmark)
33863518
call bookmark.activate()
33873519
endif
@@ -3591,7 +3723,7 @@ endfunction
35913723
" FUNCTION: s:deleteBookmark() {{{2
35923724
" if the cursor is on a bookmark, prompt to delete
35933725
function! s:deleteBookmark()
3594-
let bookmark = s:getSelectedBookmark()
3726+
let bookmark = s:Bookmark.GetSelected()
35953727
if bookmark ==# {}
35963728
call s:echo("Put the cursor on a bookmark")
35973729
return
@@ -3748,29 +3880,13 @@ endfunction
37483880
" stayCurrentTab: if 1 then vim will stay in the current tab, if 0 then vim
37493881
" will go to the tab where the new file is opened
37503882
function! s:openInNewTab(stayCurrentTab)
3751-
let currentTab = tabpagenr()
3752-
3753-
let treenode = s:TreeFileNode.GetSelected()
3754-
if treenode != {}
3755-
if treenode.path.isDirectory
3756-
tabnew
3757-
call s:initNerdTree(treenode.path.str())
3758-
else
3759-
exec "tabedit " . treenode.path.str({'format': 'Edit'})
3760-
endif
3761-
else
3762-
let bookmark = s:getSelectedBookmark()
3763-
if bookmark != {}
3764-
if bookmark.path.isDirectory
3765-
tabnew
3766-
call s:initNerdTree(bookmark.name)
3767-
else
3768-
exec "tabedit " . bookmark.path.str({'format': 'Edit'})
3769-
endif
3770-
endif
3883+
let target = s:TreeFileNode.GetSelected()
3884+
if target == {}
3885+
let target = s:Bookmark.GetSelected()
37713886
endif
3772-
if a:stayCurrentTab
3773-
exec "tabnext " . currentTab
3887+
3888+
if target != {}
3889+
call target.openInNewTab({'stayInCurrentTab': a:stayCurrentTab})
37743890
endif
37753891
endfunction
37763892

0 commit comments

Comments
 (0)