Skip to content

Commit

Permalink
Add an option to open NERDTree in current window
Browse files Browse the repository at this point in the history
In a multi-window workflow, it's often desirable to make NERDTree to
work in the current window instead of its side window. See issue preservim#244
for brief discussion.

Currently it's possible to use `:e <dir>` to achieve this for
`:NERDTree` command; but there are no workarounds for other functions
like opening bookmark, toggling nerdtree, finding current file, etc.

This commit adds an option to render NERDTree in current window instead
of side window, and modifies all relevant commands to respect the
option.
  • Loading branch information
zefei committed May 15, 2018
1 parent 6188c5e commit be15e4d
Show file tree
Hide file tree
Showing 6 changed files with 150 additions and 51 deletions.
34 changes: 5 additions & 29 deletions autoload/nerdtree.vim
Original file line number Diff line number Diff line change
Expand Up @@ -10,42 +10,18 @@ endfunction
" SECTION: General Functions {{{1
"============================================================

"FUNCTION: nerdtree#checkForBrowse(dir) {{{2
"inits a window tree in the current buffer if appropriate
" FUNCTION: nerdtree#checkForBrowse(dir) {{{2
" inits a window tree in the current buffer if appropriate
function! nerdtree#checkForBrowse(dir)
if !isdirectory(a:dir)
return
endif

if s:reuseWin(a:dir)
return
endif

" wipe current directory buffer before opening NERDTree buffer
setlocal bufhidden=wipe
buffer #
call g:NERDTreeCreator.CreateWindowTree(a:dir)
endfunction

"FUNCTION: s:reuseWin(dir) {{{2
"finds a NERDTree buffer with root of dir, and opens it.
function! s:reuseWin(dir) abort
let path = g:NERDTreePath.New(fnamemodify(a:dir, ":p"))

for i in range(1, bufnr("$"))
unlet! nt
let nt = getbufvar(i, "NERDTree")
if empty(nt)
continue
endif

if nt.isWinTree() && nt.root.path.equals(path)
call nt.setPreviousBuf(bufnr("#"))
exec "buffer " . i
return 1
endif
endfor

return 0
endfunction

" FUNCTION: nerdtree#completeBookmarks(A,L,P) {{{2
" completion function for the bookmark commands
function! nerdtree#completeBookmarks(A,L,P)
Expand Down
37 changes: 32 additions & 5 deletions autoload/nerdtree/ui_glue.vim
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ function! s:findAndRevealPath(pathStr)
return
endtry

if !g:NERDTree.ExistsForTab()
if !g:NERDTree.ExistsForTab() && !g:NERDTreeUseCurrentWindow
try
let l:cwd = g:NERDTreePath.New(getcwd())
catch /^NERDTree.InvalidArgumentsError/
Expand Down Expand Up @@ -569,16 +569,43 @@ endfunction

" FUNCTION: nerdtree#ui_glue#setupCommands() {{{1
function! nerdtree#ui_glue#setupCommands()
command! -n=? -complete=dir -bar NERDTree :call g:NERDTreeCreator.CreateTabTree('<args>')
command! -n=? -complete=dir -bar NERDTreeToggle :call g:NERDTreeCreator.ToggleTabTree('<args>')
command! -n=0 -bar NERDTreeClose :call g:NERDTree.Close()
command! -n=1 -complete=customlist,nerdtree#completeBookmarks -bar NERDTreeFromBookmark call g:NERDTreeCreator.CreateTabTree('<args>')
command! -n=? -complete=dir -bar NERDTree :call <SID>createTree('<args>')
command! -n=? -complete=dir -bar NERDTreeToggle :call <SID>toggleTree('<args>')
command! -n=0 -bar NERDTreeClose :call <SID>closeTree()
command! -n=1 -complete=customlist,nerdtree#completeBookmarks -bar NERDTreeFromBookmark call <SID>createTree('<args>')
command! -n=0 -bar NERDTreeMirror call g:NERDTreeCreator.CreateMirror()
command! -n=? -complete=file -bar NERDTreeFind call s:findAndRevealPath('<args>')
command! -n=0 -bar NERDTreeFocus call NERDTreeFocus()
command! -n=0 -bar NERDTreeCWD call NERDTreeCWD()
endfunction

" Function: s:createTree(name) {{{1
function s:createTree(name)
if g:NERDTreeUseCurrentWindow
call g:NERDTreeCreator.CreateWindowTree(a:name)
else
call g:NERDTreeCreator.CreateTabTree(a:name)
endif
endfunction

" Function: s:toggleTree(name) {{{1
function s:toggleTree(name)
if g:NERDTreeUseCurrentWindow
call g:NERDTreeCreator.ToggleWindowTree(a:name)
else
call g:NERDTreeCreator.ToggleTabTree(a:name)
endif
endfunction

" Function: s:closeTree() {{{1
function s:closeTree()
if g:NERDTreeUseCurrentWindow
call g:NERDTree.CloseWindowTree()
else
call g:NERDTree.Close()
endif
endfunction

" Function: s:SID() {{{1
function s:SID()
if !exists("s:sid")
Expand Down
11 changes: 11 additions & 0 deletions doc/NERDTree.txt
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,9 @@ NERD tree. These options should be set in your vimrc.
|'NERDTreeHijackNetrw'| Tell the NERD tree whether to replace the netrw
autocommands for exploring local directories.

|'NERDTreeUseCurrentWindow'| Tells the NERD tree whether to render in side
window or current window.

|'NERDTreeIgnore'| Tells the NERD tree which files to ignore.

|'NERDTreeRespectWildIgnore'| Tells the NERD tree to respect |'wildignore'|.
Expand Down Expand Up @@ -833,6 +836,14 @@ following respects:
replacing it.
2. you can have one tree per window - instead of per tab.

------------------------------------------------------------------------------
*'NERDTreeUseCurrentWindow'*
Values: 0 or 1.
Default: 0.

If set to 1, NERD tree will open in the current window instead of a side window.
This option affects all NERD tree commands except |:NERDTreeMirror|.

------------------------------------------------------------------------------
*'NERDTreeIgnore'*
Values: a list of regular expressions.
Expand Down
88 changes: 71 additions & 17 deletions lib/nerdtree/creator.vim
Original file line number Diff line number Diff line change
Expand Up @@ -73,39 +73,65 @@ function! s:Creator.createTabTree(name)
call self._broadcastInitEvent()
endfunction

" FUNCTION: s:Creator.CreateWindowTree(dir) {{{1
function! s:Creator.CreateWindowTree(dir)
" FUNCTION: s:Creator.CreateWindowTree(name) {{{1
function! s:Creator.CreateWindowTree(name)
let creator = s:Creator.New()
call creator.createWindowTree(a:dir)
call creator.createWindowTree(a:name)
endfunction

" FUNCTION: s:Creator.createWindowTree(dir) {{{1
function! s:Creator.createWindowTree(dir)
try
let path = g:NERDTreePath.New(a:dir)
catch /^NERDTree.InvalidArgumentsError/
call nerdtree#echo("Invalid directory name:" . a:name)
" FUNCTION: s:Creator.createWindowTree(name) {{{1
function! s:Creator.createWindowTree(name)
let l:path = self._pathForString(a:name)

" Abort if an exception was thrown (i.e., if the bookmark or directory
" does not exist).
if empty(l:path)
return
endtry
endif

"we want the directory buffer to disappear when we do the :edit below
setlocal bufhidden=wipe
if (self._reuseWin(l:path))
return
endif

let previousBuf = expand("#")
let previousBuf = bufnr("%")

"we need a unique name for each window tree buffer to ensure they are
"all independent
" We need a unique name for each window tree buffer to ensure they are all
" independent
exec g:NERDTreeCreatePrefix . " edit " . self._nextBufferName()

call self._createNERDTree(path, "window")
let b:NERDTree._previousBuf = bufnr(previousBuf)
call self._createNERDTree(l:path, "window")
call b:NERDTree.setPreviousBuf(previousBuf)
let w:NERDTreeBufName = bufname("%")
call self._setCommonBufOptions()

call b:NERDTree.render()

call self._broadcastInitEvent()
endfunction

" FUNCTION: s:Creator._reuseWin(path) {{{1
" finds a NERDTree buffer with root of dir, and opens it.
function! s:Creator._reuseWin(path) abort
for i in range(1, bufnr("$"))
unlet! nt
let nt = getbufvar(i, "NERDTree")
if empty(nt)
continue
endif

if nt.isWinTree() && nt.root.path.equals(a:path)
if i != bufnr("%")
call nt.setPreviousBuf(bufnr("%"))
exec "buffer " . i
let w:NERDTreeBufName = bufname("%")
endif
return 1
endif
endfor

return 0
endfunction

" FUNCTION: s:Creator._createNERDTree(path) {{{1
function! s:Creator._createNERDTree(path, type)
let b:NERDTree = g:NERDTree.New(a:path, a:type)
Expand Down Expand Up @@ -364,6 +390,34 @@ function! s:Creator.toggleTabTree(dir)
endif
endfunction

" FUNCTION: s:Creator.ToggleWindowTree(dir) {{{1
function! s:Creator.ToggleWindowTree(dir)
let creator = s:Creator.New()
call creator.toggleWindowTree(a:dir)
endfunction

" FUNCTION: s:Creator.toggleWindowTree(dir) {{{1
" Toggles the NERD tree in current window. I.e the NERD tree is open in the
" current window, it is closed, if it is closed it is restored or initialized
" (if it doesnt exist)
"
" Args:
" dir: the full path for the root node (is only used if the NERD tree is being
" initialized.
function! s:Creator.toggleWindowTree(dir)
if g:NERDTree.IsWindowTreeOpen()
call g:NERDTree.CloseWindowTree()
return
endif
if g:NERDTree.ExistsForWindow()
let previousBuf = bufnr("%")
exec 'buffer ' . w:NERDTreeBufName
call b:NERDTree.setPreviousBuf(previousBuf)
else
call self.createWindowTree(a:dir)
endif
endfunction

" Function: s:Creator._uniq(list) {{{1
" returns a:list without duplicates
function! s:Creator._uniq(list)
Expand Down
24 changes: 24 additions & 0 deletions lib/nerdtree/nerdtree.vim
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,13 @@ function! s:NERDTree.CloseIfQuitOnOpen()
endif
endfunction

" FUNCTION: s:NERDTree.CloseWindowTree() {{{1
function! s:NERDTree.CloseWindowTree()
if s:NERDTree.IsWindowTreeOpen()
exec "buffer " . b:NERDTree.previousBuf()
endif
endfunction

"FUNCTION: s:NERDTree.CursorToBookmarkTable(){{{1
"Places the cursor at the top of the bookmarks table
function! s:NERDTree.CursorToBookmarkTable()
Expand Down Expand Up @@ -118,6 +125,17 @@ function! s:NERDTree.ExistsForTab()
return !empty(getbufvar(bufnr(t:NERDTreeBufName), 'NERDTree'))
endfunction

" Function: s:NERDTree.ExistsForWindow() {{{1
" Returns 1 if a nerd tree root exists in the current window
function! s:NERDTree.ExistsForWindow()
if !exists("w:NERDTreeBufName")
return
end

" check b:NERDTree is still there and hasn't been e.g. :bdeleted
return !empty(getbufvar(bufnr(w:NERDTreeBufName), 'NERDTree'))
endfunction

function! s:NERDTree.ForCurrentBuf()
if s:NERDTree.ExistsForBuf()
return b:NERDTree
Expand Down Expand Up @@ -156,6 +174,12 @@ function! s:NERDTree.IsOpen()
return s:NERDTree.GetWinNum() != -1
endfunction

"FUNCTION: s:NERDTree.IsWindowTreeOpen() {{{1
function! s:NERDTree.IsWindowTreeOpen()
let nerdtree = s:NERDTree.ForCurrentBuf()
return !empty(nerdtree) && nerdtree.isWinTree()
endfunction

"FUNCTION: s:NERDTree.isTabTree() {{{1
function! s:NERDTree.isTabTree()
return self._type == "tab"
Expand Down
7 changes: 7 additions & 0 deletions plugin/NERD_tree.vim
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ call s:initVariable("g:NERDTreeShowFiles", 1)
call s:initVariable("g:NERDTreeShowHidden", 0)
call s:initVariable("g:NERDTreeShowLineNumbers", 0)
call s:initVariable("g:NERDTreeSortDirs", 1)
call s:initVariable("g:NERDTreeUseCurrentWindow", 0)

if !nerdtree#runningWindows() && !nerdtree#runningCygwin()
call s:initVariable("g:NERDTreeDirArrowExpandable", "")
Expand Down Expand Up @@ -198,6 +199,12 @@ function! NERDTreeRender()
endfunction

function! NERDTreeFocus()
if g:NERDTreeUseCurrentWindow
if !g:NERDTree.IsWindowTreeOpen()
call g:NERDTreeCreator.ToggleWindowTree("")
endif
return
endif
if g:NERDTree.IsOpen()
call g:NERDTree.CursorToTreeWin()
else
Expand Down

0 comments on commit be15e4d

Please sign in to comment.