Add an option to open NERDTree in current window

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 #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.
This commit is contained in:
Zefei Xuan 2018-05-14 15:25:23 -07:00
parent 6188c5ea5f
commit be15e4dace
6 changed files with 150 additions and 51 deletions

View File

@ -10,42 +10,18 @@ endfunction
" SECTION: General Functions {{{1 " SECTION: General Functions {{{1
"============================================================ "============================================================
"FUNCTION: nerdtree#checkForBrowse(dir) {{{2 " FUNCTION: nerdtree#checkForBrowse(dir) {{{2
"inits a window tree in the current buffer if appropriate " inits a window tree in the current buffer if appropriate
function! nerdtree#checkForBrowse(dir) function! nerdtree#checkForBrowse(dir)
if !isdirectory(a:dir) if !isdirectory(a:dir)
return return
endif endif
" wipe current directory buffer before opening NERDTree buffer
if s:reuseWin(a:dir) setlocal bufhidden=wipe
return buffer #
endif
call g:NERDTreeCreator.CreateWindowTree(a:dir) call g:NERDTreeCreator.CreateWindowTree(a:dir)
endfunction 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 " FUNCTION: nerdtree#completeBookmarks(A,L,P) {{{2
" completion function for the bookmark commands " completion function for the bookmark commands
function! nerdtree#completeBookmarks(A,L,P) function! nerdtree#completeBookmarks(A,L,P)

View File

@ -270,7 +270,7 @@ function! s:findAndRevealPath(pathStr)
return return
endtry endtry
if !g:NERDTree.ExistsForTab() if !g:NERDTree.ExistsForTab() && !g:NERDTreeUseCurrentWindow
try try
let l:cwd = g:NERDTreePath.New(getcwd()) let l:cwd = g:NERDTreePath.New(getcwd())
catch /^NERDTree.InvalidArgumentsError/ catch /^NERDTree.InvalidArgumentsError/
@ -569,16 +569,43 @@ endfunction
" FUNCTION: nerdtree#ui_glue#setupCommands() {{{1 " FUNCTION: nerdtree#ui_glue#setupCommands() {{{1
function! nerdtree#ui_glue#setupCommands() function! nerdtree#ui_glue#setupCommands()
command! -n=? -complete=dir -bar NERDTree :call g:NERDTreeCreator.CreateTabTree('<args>') command! -n=? -complete=dir -bar NERDTree :call <SID>createTree('<args>')
command! -n=? -complete=dir -bar NERDTreeToggle :call g:NERDTreeCreator.ToggleTabTree('<args>') command! -n=? -complete=dir -bar NERDTreeToggle :call <SID>toggleTree('<args>')
command! -n=0 -bar NERDTreeClose :call g:NERDTree.Close() command! -n=0 -bar NERDTreeClose :call <SID>closeTree()
command! -n=1 -complete=customlist,nerdtree#completeBookmarks -bar NERDTreeFromBookmark call g:NERDTreeCreator.CreateTabTree('<args>') command! -n=1 -complete=customlist,nerdtree#completeBookmarks -bar NERDTreeFromBookmark call <SID>createTree('<args>')
command! -n=0 -bar NERDTreeMirror call g:NERDTreeCreator.CreateMirror() command! -n=0 -bar NERDTreeMirror call g:NERDTreeCreator.CreateMirror()
command! -n=? -complete=file -bar NERDTreeFind call s:findAndRevealPath('<args>') command! -n=? -complete=file -bar NERDTreeFind call s:findAndRevealPath('<args>')
command! -n=0 -bar NERDTreeFocus call NERDTreeFocus() command! -n=0 -bar NERDTreeFocus call NERDTreeFocus()
command! -n=0 -bar NERDTreeCWD call NERDTreeCWD() command! -n=0 -bar NERDTreeCWD call NERDTreeCWD()
endfunction 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() {{{1
function s:SID() function s:SID()
if !exists("s:sid") if !exists("s:sid")

View File

@ -639,6 +639,9 @@ NERD tree. These options should be set in your vimrc.
|'NERDTreeHijackNetrw'| Tell the NERD tree whether to replace the netrw |'NERDTreeHijackNetrw'| Tell the NERD tree whether to replace the netrw
autocommands for exploring local directories. 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. |'NERDTreeIgnore'| Tells the NERD tree which files to ignore.
|'NERDTreeRespectWildIgnore'| Tells the NERD tree to respect |'wildignore'|. |'NERDTreeRespectWildIgnore'| Tells the NERD tree to respect |'wildignore'|.
@ -833,6 +836,14 @@ following respects:
replacing it. replacing it.
2. you can have one tree per window - instead of per tab. 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'* *'NERDTreeIgnore'*
Values: a list of regular expressions. Values: a list of regular expressions.

View File

@ -73,32 +73,35 @@ function! s:Creator.createTabTree(name)
call self._broadcastInitEvent() call self._broadcastInitEvent()
endfunction endfunction
" FUNCTION: s:Creator.CreateWindowTree(dir) {{{1 " FUNCTION: s:Creator.CreateWindowTree(name) {{{1
function! s:Creator.CreateWindowTree(dir) function! s:Creator.CreateWindowTree(name)
let creator = s:Creator.New() let creator = s:Creator.New()
call creator.createWindowTree(a:dir) call creator.createWindowTree(a:name)
endfunction endfunction
" FUNCTION: s:Creator.createWindowTree(dir) {{{1 " FUNCTION: s:Creator.createWindowTree(name) {{{1
function! s:Creator.createWindowTree(dir) function! s:Creator.createWindowTree(name)
try let l:path = self._pathForString(a:name)
let path = g:NERDTreePath.New(a:dir)
catch /^NERDTree.InvalidArgumentsError/ " Abort if an exception was thrown (i.e., if the bookmark or directory
call nerdtree#echo("Invalid directory name:" . a:name) " does not exist).
if empty(l:path)
return return
endtry endif
"we want the directory buffer to disappear when we do the :edit below if (self._reuseWin(l:path))
setlocal bufhidden=wipe return
endif
let previousBuf = expand("#") let previousBuf = bufnr("%")
"we need a unique name for each window tree buffer to ensure they are " We need a unique name for each window tree buffer to ensure they are all
"all independent " independent
exec g:NERDTreeCreatePrefix . " edit " . self._nextBufferName() exec g:NERDTreeCreatePrefix . " edit " . self._nextBufferName()
call self._createNERDTree(path, "window") call self._createNERDTree(l:path, "window")
let b:NERDTree._previousBuf = bufnr(previousBuf) call b:NERDTree.setPreviousBuf(previousBuf)
let w:NERDTreeBufName = bufname("%")
call self._setCommonBufOptions() call self._setCommonBufOptions()
call b:NERDTree.render() call b:NERDTree.render()
@ -106,6 +109,29 @@ function! s:Creator.createWindowTree(dir)
call self._broadcastInitEvent() call self._broadcastInitEvent()
endfunction 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) {{{1
function! s:Creator._createNERDTree(path, type) function! s:Creator._createNERDTree(path, type)
let b:NERDTree = g:NERDTree.New(a:path, a:type) let b:NERDTree = g:NERDTree.New(a:path, a:type)
@ -364,6 +390,34 @@ function! s:Creator.toggleTabTree(dir)
endif endif
endfunction 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 " Function: s:Creator._uniq(list) {{{1
" returns a:list without duplicates " returns a:list without duplicates
function! s:Creator._uniq(list) function! s:Creator._uniq(list)

View File

@ -71,6 +71,13 @@ function! s:NERDTree.CloseIfQuitOnOpen()
endif endif
endfunction 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 "FUNCTION: s:NERDTree.CursorToBookmarkTable(){{{1
"Places the cursor at the top of the bookmarks table "Places the cursor at the top of the bookmarks table
function! s:NERDTree.CursorToBookmarkTable() function! s:NERDTree.CursorToBookmarkTable()
@ -118,6 +125,17 @@ function! s:NERDTree.ExistsForTab()
return !empty(getbufvar(bufnr(t:NERDTreeBufName), 'NERDTree')) return !empty(getbufvar(bufnr(t:NERDTreeBufName), 'NERDTree'))
endfunction 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() function! s:NERDTree.ForCurrentBuf()
if s:NERDTree.ExistsForBuf() if s:NERDTree.ExistsForBuf()
return b:NERDTree return b:NERDTree
@ -156,6 +174,12 @@ function! s:NERDTree.IsOpen()
return s:NERDTree.GetWinNum() != -1 return s:NERDTree.GetWinNum() != -1
endfunction 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() {{{1
function! s:NERDTree.isTabTree() function! s:NERDTree.isTabTree()
return self._type == "tab" return self._type == "tab"

View File

@ -68,6 +68,7 @@ call s:initVariable("g:NERDTreeShowFiles", 1)
call s:initVariable("g:NERDTreeShowHidden", 0) call s:initVariable("g:NERDTreeShowHidden", 0)
call s:initVariable("g:NERDTreeShowLineNumbers", 0) call s:initVariable("g:NERDTreeShowLineNumbers", 0)
call s:initVariable("g:NERDTreeSortDirs", 1) call s:initVariable("g:NERDTreeSortDirs", 1)
call s:initVariable("g:NERDTreeUseCurrentWindow", 0)
if !nerdtree#runningWindows() && !nerdtree#runningCygwin() if !nerdtree#runningWindows() && !nerdtree#runningCygwin()
call s:initVariable("g:NERDTreeDirArrowExpandable", "▸") call s:initVariable("g:NERDTreeDirArrowExpandable", "▸")
@ -198,6 +199,12 @@ function! NERDTreeRender()
endfunction endfunction
function! NERDTreeFocus() function! NERDTreeFocus()
if g:NERDTreeUseCurrentWindow
if !g:NERDTree.IsWindowTreeOpen()
call g:NERDTreeCreator.ToggleWindowTree("")
endif
return
endif
if g:NERDTree.IsOpen() if g:NERDTree.IsOpen()
call g:NERDTree.CursorToTreeWin() call g:NERDTree.CursorToTreeWin()
else else