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:
