nerdtree

A tree explorer plugin for vim.
Index Commits Files Refs
lib/nerdtree/creator.vim (12383B)
   1 " ============================================================================
   2 " CLASS: Creator
   3 "
   4 " This class is responsible for creating NERDTree instances.  The new NERDTree
   5 " may be a tab tree, a window tree, or a mirrored tree.  In the process of
   6 " creating a NERDTree, it sets up all of the window and buffer options and key
   7 " mappings etc.
   8 " ============================================================================
   9 
  10 
  11 let s:Creator = {}
  12 let g:NERDTreeCreator = s:Creator
  13 
  14 " FUNCTION: s:Creator._bindMappings() {{{1
  15 function! s:Creator._bindMappings()
  16     call g:NERDTreeKeyMap.BindAll()
  17 
  18     command! -buffer -nargs=? Bookmark :call nerdtree#ui_glue#bookmarkNode('<args>')
  19     command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=1 RevealBookmark :call nerdtree#ui_glue#revealBookmark('<args>')
  20     command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=1 OpenBookmark call nerdtree#ui_glue#openBookmark('<args>')
  21     command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=* ClearBookmarks call nerdtree#ui_glue#clearBookmarks('<args>')
  22     command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=+ BookmarkToRoot call g:NERDTreeBookmark.ToRoot('<args>', b:NERDTree)
  23     command! -buffer -nargs=0 ClearAllBookmarks call g:NERDTreeBookmark.ClearAll() <bar> call b:NERDTree.render()
  24     command! -buffer -nargs=0 ReadBookmarks call g:NERDTreeBookmark.CacheBookmarks(0) <bar> call b:NERDTree.render()
  25     command! -buffer -nargs=0 WriteBookmarks call g:NERDTreeBookmark.Write()
  26     command! -buffer -nargs=0 EditBookmarks call g:NERDTreeBookmark.Edit()
  27 endfunction
  28 
  29 " FUNCTION: s:Creator._broadcastInitEvent() {{{1
  30 function! s:Creator._broadcastInitEvent()
  31     if exists('#User#NERDTreeInit')
  32         doautocmd User NERDTreeInit
  33     endif
  34 endfunction
  35 
  36 " FUNCTION: s:Creator.BufNamePrefix() {{{1
  37 function! s:Creator.BufNamePrefix()
  38     return 'NERD_tree_'
  39 endfunction
  40 
  41 " FUNCTION: s:Creator.CreateTabTree(a:name) {{{1
  42 function! s:Creator.CreateTabTree(name)
  43     let creator = s:Creator.New()
  44     call creator.createTabTree(a:name)
  45 endfunction
  46 
  47 " FUNCTION: s:Creator.createTabTree(a:name) {{{1
  48 " name: the name of a bookmark or a directory
  49 function! s:Creator.createTabTree(name)
  50     let l:path = self._pathForString(a:name)
  51 
  52     " Abort if an exception was thrown (i.e., if the bookmark or directory
  53     " does not exist).
  54     if empty(l:path)
  55         return
  56     endif
  57 
  58     " Obey the user's preferences for changing the working directory.
  59     if g:NERDTreeChDirMode != 0
  60         call l:path.changeToDir()
  61     endif
  62 
  63     if g:NERDTree.ExistsForTab()
  64         call g:NERDTree.Close()
  65         call self._removeTreeBufForTab()
  66     endif
  67 
  68     call self._createTreeWin()
  69     call self._createNERDTree(l:path, 'tab')
  70     call b:NERDTree.render()
  71     call b:NERDTree.root.putCursorHere(0, 0)
  72 
  73     call self._broadcastInitEvent()
  74 endfunction
  75 
  76 " FUNCTION: s:Creator.CreateWindowTree(dir) {{{1
  77 function! s:Creator.CreateWindowTree(dir)
  78     let creator = s:Creator.New()
  79     call creator.createWindowTree(a:dir)
  80 endfunction
  81 
  82 " FUNCTION: s:Creator.createWindowTree(dir) {{{1
  83 function! s:Creator.createWindowTree(dir)
  84     try
  85         let path = g:NERDTreePath.New(a:dir)
  86     catch /^NERDTree.InvalidArgumentsError/
  87         call nerdtree#echo('Invalid directory name:' . a:dir)
  88         return
  89     endtry
  90 
  91     "we want the directory buffer to disappear when we do the :edit below
  92     setlocal bufhidden=wipe
  93 
  94     let previousBuf = expand('#')
  95 
  96     "we need a unique name for each window tree buffer to ensure they are
  97     "all independent
  98     exec g:NERDTreeCreatePrefix . ' edit ' . self._nextBufferName()
  99 
 100     call self._createNERDTree(path, 'window')
 101     let b:NERDTree._previousBuf = bufnr(previousBuf)
 102     call self._setCommonBufOptions()
 103 
 104     call b:NERDTree.render()
 105 
 106     call self._broadcastInitEvent()
 107 endfunction
 108 
 109 " FUNCTION: s:Creator._createNERDTree(path) {{{1
 110 function! s:Creator._createNERDTree(path, type)
 111     let b:NERDTree = g:NERDTree.New(a:path, a:type)
 112 
 113     " TODO: This assignment is kept for compatibility reasons.  Many other
 114     " plugins use b:NERDTreeRoot instead of b:NERDTree.root.  Remove this
 115     " assignment in the future.
 116     let b:NERDTreeRoot = b:NERDTree.root
 117 
 118     call b:NERDTree.root.open()
 119 endfunction
 120 
 121 " FUNCTION: s:Creator.CreateMirror() {{{1
 122 function! s:Creator.CreateMirror()
 123     let creator = s:Creator.New()
 124     call creator.createMirror()
 125 endfunction
 126 
 127 " FUNCTION: s:Creator.createMirror() {{{1
 128 function! s:Creator.createMirror()
 129     "get the names off all the nerd tree buffers
 130     let treeBufNames = []
 131     for i in range(1, tabpagenr('$'))
 132         let nextName = self._tabpagevar(i, 'NERDTreeBufName')
 133         if nextName != -1 && (!exists('t:NERDTreeBufName') || nextName != t:NERDTreeBufName)
 134             call add(treeBufNames, nextName)
 135         endif
 136     endfor
 137     let treeBufNames = self._uniq(treeBufNames)
 138 
 139     "map the option names (that the user will be prompted with) to the nerd
 140     "tree buffer names
 141     let options = {}
 142     let i = 0
 143     while i < len(treeBufNames)
 144         let bufName = treeBufNames[i]
 145         let treeRoot = getbufvar(bufName, 'NERDTree').root
 146         let options[i+1 . '. ' . treeRoot.path.str() . '  (buf name: ' . bufName . ')'] = bufName
 147         let i = i + 1
 148     endwhile
 149 
 150     "work out which tree to mirror, if there is more than 1 then ask the user
 151     let bufferName = ''
 152     if len(keys(options)) > 1
 153         let choices = ['Choose a tree to mirror']
 154         let choices = extend(choices, sort(keys(options)))
 155         let choice = inputlist(choices)
 156         if choice < 1 || choice > len(options) || choice ==# ''
 157             return
 158         endif
 159 
 160         let bufferName = options[sort(keys(options))[choice-1]]
 161     elseif len(keys(options)) ==# 1
 162         let bufferName = values(options)[0]
 163     else
 164         call nerdtree#echo('No trees to mirror')
 165         return
 166     endif
 167 
 168     if g:NERDTree.ExistsForTab() && g:NERDTree.IsOpen()
 169         call g:NERDTree.Close()
 170     endif
 171 
 172     let t:NERDTreeBufName = bufferName
 173     call self._createTreeWin()
 174     exec 'buffer ' .  bufferName
 175     call b:NERDTree.ui.restoreScreenState()
 176     if !&hidden
 177         call b:NERDTree.render()
 178     endif
 179 endfunction
 180 
 181 " FUNCTION: s:Creator._createTreeWin() {{{1
 182 " Initialize the NERDTree window.  Open the window, size it properly, set all
 183 " local options, etc.
 184 function! s:Creator._createTreeWin()
 185     let l:splitLocation = g:NERDTreeWinPos ==# 'left' || g:NERDTreeWinPos ==# 'top' ? 'topleft ' : 'botright '
 186     let l:splitDirection = g:NERDTreeWinPos ==# 'left' || g:NERDTreeWinPos ==# 'right' ? 'vertical' : ''
 187     let l:splitSize = g:NERDTreeWinSize
 188 
 189     if !g:NERDTree.ExistsForTab()
 190         let t:NERDTreeBufName = self._nextBufferName()
 191         silent! execute l:splitLocation . l:splitDirection . ' ' . l:splitSize . ' new'
 192         silent! execute 'edit ' . t:NERDTreeBufName
 193         silent! execute l:splitDirection . ' resize '. l:splitSize
 194     else
 195         silent! execute l:splitLocation . l:splitDirection . ' ' . l:splitSize . ' split'
 196         silent! execute 'buffer ' . t:NERDTreeBufName
 197     endif
 198 
 199     setlocal winfixwidth
 200 
 201     call self._setCommonBufOptions()
 202 
 203     if has('patch-7.4.1925')
 204         clearjumps
 205     endif
 206 
 207 endfunction
 208 
 209 " FUNCTION: s:Creator._isBufHidden(nr) {{{1
 210 function! s:Creator._isBufHidden(nr)
 211     redir => bufs
 212     silent ls!
 213     redir END
 214 
 215     return bufs =~ a:nr . '..h'
 216 endfunction
 217 
 218 " FUNCTION: s:Creator.New() {{{1
 219 function! s:Creator.New()
 220     let newCreator = copy(self)
 221     return newCreator
 222 endfunction
 223 
 224 " FUNCTION: s:Creator._nextBufferName() {{{1
 225 " returns the buffer name for the next nerd tree
 226 function! s:Creator._nextBufferName()
 227     let name = s:Creator.BufNamePrefix() . self._nextBufferNumber()
 228     return name
 229 endfunction
 230 
 231 " FUNCTION: s:Creator._nextBufferNumber() {{{1
 232 " the number to add to the nerd tree buffer name to make the buf name unique
 233 function! s:Creator._nextBufferNumber()
 234     if !exists('s:Creator._NextBufNum')
 235         let s:Creator._NextBufNum = 1
 236     else
 237         let s:Creator._NextBufNum += 1
 238     endif
 239 
 240     return s:Creator._NextBufNum
 241 endfunction
 242 
 243 " FUNCTION: s:Creator._pathForString(str) {{{1
 244 " find a bookmark or adirectory for the given string
 245 function! s:Creator._pathForString(str)
 246     let path = {}
 247     if g:NERDTreeBookmark.BookmarkExistsFor(a:str)
 248         let path = g:NERDTreeBookmark.BookmarkFor(a:str).path
 249     else
 250         let dir = a:str ==# '' ? getcwd() : a:str
 251 
 252         "hack to get an absolute path if a relative path is given
 253         if dir =~# '^\.'
 254             let dir = getcwd() . nerdtree#slash() . dir
 255         endif
 256 
 257         "hack to prevent removing slash if dir is the root of the file system.
 258         if dir !=# '/'
 259             let dir = g:NERDTreePath.Resolve(dir)
 260         endif
 261 
 262         try
 263             let path = g:NERDTreePath.New(dir)
 264         catch /^NERDTree.InvalidArgumentsError/
 265             call nerdtree#echo('No bookmark or directory found for: ' . a:str)
 266             return {}
 267         endtry
 268     endif
 269     if !path.isDirectory
 270         let path = path.getParent()
 271     endif
 272 
 273     return path
 274 endfunction
 275 
 276 " Function: s:Creator._removeTreeBufForTab()   {{{1
 277 function! s:Creator._removeTreeBufForTab()
 278     let buf = bufnr(t:NERDTreeBufName)
 279 
 280     "if &hidden is not set then it will already be gone
 281     if buf != -1
 282 
 283         "nerdtree buf may be mirrored/displayed elsewhere
 284         if self._isBufHidden(buf)
 285             exec 'bwipeout ' . buf
 286         endif
 287 
 288     endif
 289 
 290     unlet t:NERDTreeBufName
 291 endfunction
 292 
 293 " FUNCTION: s:Creator._setCommonBufOptions() {{{1
 294 function! s:Creator._setCommonBufOptions()
 295 
 296     " Options for a non-file/control buffer.
 297     setlocal bufhidden=hide
 298     setlocal buftype=nofile
 299     setlocal noswapfile
 300 
 301     " Options for controlling buffer/window appearance.
 302     setlocal foldcolumn=0
 303     setlocal foldmethod=manual
 304     setlocal nobuflisted
 305     setlocal nofoldenable
 306     setlocal nolist
 307     setlocal nospell
 308     setlocal nowrap
 309 
 310     if g:NERDTreeShowLineNumbers
 311         setlocal number
 312     else
 313         setlocal nonumber
 314         if v:version >= 703
 315             setlocal norelativenumber
 316         endif
 317     endif
 318 
 319     iabc <buffer>
 320 
 321     if g:NERDTreeHighlightCursorline
 322         setlocal cursorline
 323     endif
 324 
 325     call self._setupStatusline()
 326     call self._bindMappings()
 327 
 328     setlocal filetype=nerdtree
 329 endfunction
 330 
 331 " FUNCTION: s:Creator._setupStatusline() {{{1
 332 function! s:Creator._setupStatusline()
 333     if g:NERDTreeStatusline != -1
 334         let &l:statusline = g:NERDTreeStatusline
 335     endif
 336 endfunction
 337 
 338 " FUNCTION: s:Creator._tabpagevar(tabnr, var) {{{1
 339 function! s:Creator._tabpagevar(tabnr, var)
 340     let currentTab = tabpagenr()
 341     let old_ei = &eventignore
 342     set eventignore=all
 343 
 344     try
 345         exec 'tabnext ' . a:tabnr
 346         let v = -1
 347         if exists('t:' . a:var)
 348             exec 'let v = t:' . a:var
 349         endif
 350         exec 'tabnext ' . currentTab
 351 
 352     finally
 353         let &eventignore = old_ei
 354     endtry
 355 
 356     return v
 357 endfunction
 358 
 359 " FUNCTION: s:Creator.ToggleTabTree(dir) {{{1
 360 function! s:Creator.ToggleTabTree(dir)
 361     let creator = s:Creator.New()
 362     call creator.toggleTabTree(a:dir)
 363 endfunction
 364 
 365 " FUNCTION: s:Creator.toggleTabTree(dir) {{{1
 366 " Toggles the NERD tree. I.e if the NERD tree is open, it is closed. If it is
 367 " closed, it is restored or initialized. If dir is not empty, it will be set
 368 " as the new root.
 369 "
 370 " Args:
 371 " dir: the full path for the root node (is used if the NERD tree is being
 372 " initialized, or to change the root to a new dir.)
 373 function! s:Creator.toggleTabTree(dir)
 374     if g:NERDTree.ExistsForTab()
 375         if !g:NERDTree.IsOpen()
 376             call self._createTreeWin()
 377             if !empty(a:dir) && a:dir !=# b:NERDTree.root.path.str()
 378                 call self.createTabTree(a:dir)
 379             elseif !&hidden
 380                 call b:NERDTree.render()
 381             endif
 382             call b:NERDTree.ui.restoreScreenState()
 383         else
 384             call g:NERDTree.Close()
 385         endif
 386     else
 387         call self.createTabTree(a:dir)
 388     endif
 389 endfunction
 390 
 391 " Function: s:Creator._uniq(list)   {{{1
 392 " returns a:list without duplicates
 393 function! s:Creator._uniq(list)
 394   let uniqlist = []
 395   for elem in a:list
 396     if index(uniqlist, elem) ==# -1
 397       let uniqlist += [elem]
 398     endif
 399   endfor
 400   return uniqlist
 401 endfunction
 402 
 403 " vim: set sw=4 sts=4 et fdm=marker: