diff options
| author | Sam Chudnick <sam@chudnick.com> | 2023-06-11 07:54:59 -0400 | 
|---|---|---|
| committer | Sam Chudnick <sam@chudnick.com> | 2023-06-11 07:54:59 -0400 | 
| commit | 3adcf542289a0883924ae9b9be8b898c36702c95 (patch) | |
| tree | f02166ef4c95161ffa994eb1a3e5729c93c2c66b /.vim/pack/vendor/start/nerdtree/lib | |
| parent | dfcc303e7cc284a45f55bae81ed888dc256432b8 (diff) | |
Add some Vim plugins
Diffstat (limited to '.vim/pack/vendor/start/nerdtree/lib')
14 files changed, 4340 insertions, 0 deletions
diff --git a/.vim/pack/vendor/start/nerdtree/lib/nerdtree/bookmark.vim b/.vim/pack/vendor/start/nerdtree/lib/nerdtree/bookmark.vim new file mode 100644 index 0000000..37be451 --- /dev/null +++ b/.vim/pack/vendor/start/nerdtree/lib/nerdtree/bookmark.vim  | |||
| @@ -0,0 +1,365 @@ | |||
| 1 | " ============================================================================ | ||
| 2 | " CLASS: Bookmark | ||
| 3 | " | ||
| 4 | " The Bookmark class serves two purposes: | ||
| 5 | " (1) It is the top-level prototype for new, concrete Bookmark objects. | ||
| 6 | " (2) It provides an interface for client code to query and manipulate the | ||
| 7 | " global list of Bookmark objects within the current Vim session. | ||
| 8 | " ============================================================================ | ||
| 9 | |||
| 10 | |||
| 11 | let s:Bookmark = {} | ||
| 12 | let g:NERDTreeBookmark = s:Bookmark | ||
| 13 | |||
| 14 | " FUNCTION: Bookmark.activate(nerdtree) {{{1 | ||
| 15 | function! s:Bookmark.activate(nerdtree, ...) | ||
| 16 | call self.open(a:nerdtree, a:0 ? a:1 : {}) | ||
| 17 | endfunction | ||
| 18 | |||
| 19 | " FUNCTION: Bookmark.AddBookmark(name, path) {{{1 | ||
| 20 | " Class method to add a new bookmark to the list, if a previous bookmark exists | ||
| 21 | " with the same name, just update the path for that bookmark | ||
| 22 | function! s:Bookmark.AddBookmark(name, path) | ||
| 23 | for i in s:Bookmark.Bookmarks() | ||
| 24 | if i.name ==# a:name | ||
| 25 | let i.path = a:path | ||
| 26 | return | ||
| 27 | endif | ||
| 28 | endfor | ||
| 29 | call add(s:Bookmark.Bookmarks(), s:Bookmark.New(a:name, a:path)) | ||
| 30 | endfunction | ||
| 31 | |||
| 32 | " FUNCTION: Bookmark.Bookmarks() {{{1 | ||
| 33 | " Class method to get all bookmarks. Lazily initializes the bookmarks global | ||
| 34 | " variable | ||
| 35 | function! s:Bookmark.Bookmarks() | ||
| 36 | if !exists('g:NERDTreeBookmarks') | ||
| 37 | let g:NERDTreeBookmarks = [] | ||
| 38 | endif | ||
| 39 | return g:NERDTreeBookmarks | ||
| 40 | endfunction | ||
| 41 | |||
| 42 | " FUNCTION: Bookmark.BookmarkExistsFor(name) {{{1 | ||
| 43 | " class method that returns 1 if a bookmark with the given name is found, 0 | ||
| 44 | " otherwise | ||
| 45 | function! s:Bookmark.BookmarkExistsFor(name) | ||
| 46 | try | ||
| 47 | call s:Bookmark.BookmarkFor(a:name) | ||
| 48 | return 1 | ||
| 49 | catch /^NERDTree.BookmarkNotFoundError/ | ||
| 50 | return 0 | ||
| 51 | endtry | ||
| 52 | endfunction | ||
| 53 | |||
| 54 | " FUNCTION: Bookmark.BookmarkFor(name) {{{1 | ||
| 55 | " Class method that returns the Bookmark object having the specified name. | ||
| 56 | " Throws NERDTree.BookmarkNotFoundError if no Bookmark is found. | ||
| 57 | function! s:Bookmark.BookmarkFor(name) | ||
| 58 | let l:result = {} | ||
| 59 | for l:bookmark in s:Bookmark.Bookmarks() | ||
| 60 | if l:bookmark.name ==# a:name | ||
| 61 | let l:result = l:bookmark | ||
| 62 | break | ||
| 63 | endif | ||
| 64 | endfor | ||
| 65 | if empty(l:result) | ||
| 66 | throw 'NERDTree.BookmarkNotFoundError: "' . a:name . '" not found' | ||
| 67 | endif | ||
| 68 | return l:result | ||
| 69 | endfunction | ||
| 70 | |||
| 71 | " FUNCTION: Bookmark.BookmarkNames() {{{1 | ||
| 72 | " Class method to return an array of all bookmark names | ||
| 73 | function! s:Bookmark.BookmarkNames() | ||
| 74 | let names = [] | ||
| 75 | for i in s:Bookmark.Bookmarks() | ||
| 76 | call add(names, i.name) | ||
| 77 | endfor | ||
| 78 | return names | ||
| 79 | endfunction | ||
| 80 | |||
| 81 | " FUNCTION: Bookmark.CacheBookmarks(silent) {{{1 | ||
| 82 | " Class method to read all bookmarks from the bookmarks file initialize | ||
| 83 | " bookmark objects for each one. | ||
| 84 | " | ||
| 85 | " Args: | ||
| 86 | " silent - dont echo an error msg if invalid bookmarks are found | ||
| 87 | function! s:Bookmark.CacheBookmarks(silent) | ||
| 88 | if filereadable(g:NERDTreeBookmarksFile) | ||
| 89 | let g:NERDTreeBookmarks = [] | ||
| 90 | let g:NERDTreeInvalidBookmarks = [] | ||
| 91 | let bookmarkStrings = readfile(g:NERDTreeBookmarksFile) | ||
| 92 | let invalidBookmarksFound = 0 | ||
| 93 | for i in bookmarkStrings | ||
| 94 | |||
| 95 | "ignore blank lines | ||
| 96 | if i !=# '' | ||
| 97 | |||
| 98 | let name = substitute(i, '^\(.\{-}\) .*$', '\1', '') | ||
| 99 | let path = substitute(i, '^.\{-} \(.*\)$', '\1', '') | ||
| 100 | let path = fnamemodify(path, ':p') | ||
| 101 | |||
| 102 | try | ||
| 103 | let bookmark = s:Bookmark.New(name, g:NERDTreePath.New(path)) | ||
| 104 | call add(g:NERDTreeBookmarks, bookmark) | ||
| 105 | catch /^NERDTree.InvalidArgumentsError/ | ||
| 106 | call add(g:NERDTreeInvalidBookmarks, i) | ||
| 107 | let invalidBookmarksFound += 1 | ||
| 108 | endtry | ||
| 109 | endif | ||
| 110 | endfor | ||
| 111 | if invalidBookmarksFound | ||
| 112 | call s:Bookmark.Write() | ||
| 113 | if !a:silent | ||
| 114 | call nerdtree#echo(invalidBookmarksFound . ' invalid bookmarks were read. See :help NERDTreeInvalidBookmarks for info.') | ||
| 115 | endif | ||
| 116 | endif | ||
| 117 | endif | ||
| 118 | endfunction | ||
| 119 | |||
| 120 | " FUNCTION: Bookmark.CompareBookmarksByName(firstBookmark, secondBookmark) {{{1 | ||
| 121 | " Class method that indicates the relative position of two bookmarks when | ||
| 122 | " placed in alphabetical order by name. Case-sensitivity is determined by an | ||
| 123 | " option. Supports the s:Bookmark.SortBookmarksList() method. | ||
| 124 | function! s:Bookmark.CompareBookmarksByName(firstBookmark, secondBookmark) | ||
| 125 | let l:result = 0 | ||
| 126 | if g:NERDTreeBookmarksSort ==# 1 | ||
| 127 | if a:firstBookmark.name <? a:secondBookmark.name | ||
| 128 | let l:result = -1 | ||
| 129 | elseif a:firstBookmark.name >? a:secondBookmark.name | ||
| 130 | let l:result = 1 | ||
| 131 | endif | ||
| 132 | elseif g:NERDTreeBookmarksSort ==# 2 | ||
| 133 | if a:firstBookmark.name <# a:secondBookmark.name | ||
| 134 | let l:result = -1 | ||
| 135 | elseif a:firstBookmark.name ># a:secondBookmark.name | ||
| 136 | let l:result = 1 | ||
| 137 | endif | ||
| 138 | endif | ||
| 139 | return l:result | ||
| 140 | endfunction | ||
| 141 | |||
| 142 | " FUNCTION: Bookmark.ClearAll() {{{1 | ||
| 143 | " Class method to delete all bookmarks. | ||
| 144 | function! s:Bookmark.ClearAll() | ||
| 145 | for i in s:Bookmark.Bookmarks() | ||
| 146 | call i.delete() | ||
| 147 | endfor | ||
| 148 | call s:Bookmark.Write() | ||
| 149 | endfunction | ||
| 150 | |||
| 151 | " FUNCTION: Bookmark.delete() {{{1 | ||
| 152 | " Delete this bookmark. If the node for this bookmark is under the current | ||
| 153 | " root, then recache bookmarks for its Path object | ||
| 154 | function! s:Bookmark.delete() | ||
| 155 | call remove(s:Bookmark.Bookmarks(), index(s:Bookmark.Bookmarks(), self)) | ||
| 156 | call s:Bookmark.Write() | ||
| 157 | endfunction | ||
| 158 | |||
| 159 | " FUNCTION: s:Edit() {{{1 | ||
| 160 | " opens the NERDTreeBookmarks file for manual editing | ||
| 161 | function! s:Bookmark.Edit() | ||
| 162 | call nerdtree#exec('wincmd w', 1) | ||
| 163 | call nerdtree#exec('edit '.g:NERDTreeBookmarksFile, 1) | ||
| 164 | endfunction | ||
| 165 | |||
| 166 | " FUNCTION: Bookmark.getNode(nerdtree, searchFromAbsoluteRoot) {{{1 | ||
| 167 | " Returns the tree node object associated with this Bookmark. | ||
| 168 | " Throws NERDTree.BookmarkedNodeNotFoundError if the node is not found. | ||
| 169 | " | ||
| 170 | " Args: | ||
| 171 | " searchFromAbsoluteRoot: boolean flag, search from the highest cached node | ||
| 172 | " if true and from the current tree root if false | ||
| 173 | function! s:Bookmark.getNode(nerdtree, searchFromAbsoluteRoot) | ||
| 174 | if a:searchFromAbsoluteRoot | ||
| 175 | let l:searchRoot = a:nerdtree.root.AbsoluteTreeRoot() | ||
| 176 | else | ||
| 177 | let l:searchRoot = a:nerdtree.root | ||
| 178 | endif | ||
| 179 | let l:targetNode = l:searchRoot.findNode(self.path) | ||
| 180 | if empty(l:targetNode) | ||
| 181 | throw 'NERDTree.BookmarkedNodeNotFoundError: node for bookmark "' . self.name . '" not found' | ||
| 182 | endif | ||
| 183 | return l:targetNode | ||
| 184 | endfunction | ||
| 185 | |||
| 186 | " FUNCTION: Bookmark.GetNodeForName(name, searchFromAbsoluteRoot, nerdtree) {{{1 | ||
| 187 | " Class method that returns the tree node object for the Bookmark with the | ||
| 188 | " given name. Throws NERDTree.BookmarkNotFoundError if a Bookmark with the | ||
| 189 | " name does not exist. Throws NERDTree.BookmarkedNodeNotFoundError if a | ||
| 190 | " tree node for the named Bookmark could not be found. | ||
| 191 | function! s:Bookmark.GetNodeForName(name, searchFromAbsoluteRoot, nerdtree) | ||
| 192 | let l:bookmark = s:Bookmark.BookmarkFor(a:name) | ||
| 193 | return l:bookmark.getNode(a:nerdtree, a:searchFromAbsoluteRoot) | ||
| 194 | endfunction | ||
| 195 | |||
| 196 | " FUNCTION: Bookmark.GetSelected() {{{1 | ||
| 197 | " returns the Bookmark the cursor is over, or {} | ||
| 198 | function! s:Bookmark.GetSelected() | ||
| 199 | let line = getline('.') | ||
| 200 | let name = substitute(line, '^>\(.\{-}\) .\+$', '\1', '') | ||
| 201 | if name !=# line | ||
| 202 | try | ||
| 203 | return s:Bookmark.BookmarkFor(name) | ||
| 204 | catch /^NERDTree.BookmarkNotFoundError/ | ||
| 205 | return {} | ||
| 206 | endtry | ||
| 207 | endif | ||
| 208 | return {} | ||
| 209 | endfunction | ||
| 210 | |||
| 211 | " FUNCTION: Bookmark.InvalidBookmarks() {{{1 | ||
| 212 | " Class method to get all invalid bookmark strings read from the bookmarks | ||
| 213 | " file | ||
| 214 | function! s:Bookmark.InvalidBookmarks() | ||
| 215 | if !exists('g:NERDTreeInvalidBookmarks') | ||
| 216 | let g:NERDTreeInvalidBookmarks = [] | ||
| 217 | endif | ||
| 218 | return g:NERDTreeInvalidBookmarks | ||
| 219 | endfunction | ||
| 220 | |||
| 221 | " FUNCTION: Bookmark.mustExist() {{{1 | ||
| 222 | function! s:Bookmark.mustExist() | ||
| 223 | if !self.path.exists() | ||
| 224 | call s:Bookmark.CacheBookmarks(1) | ||
| 225 | throw 'NERDTree.BookmarkPointsToInvalidLocationError: the bookmark "'. | ||
| 226 | \ self.name .'" points to a non existing location: "'. self.path.str() | ||
| 227 | endif | ||
| 228 | endfunction | ||
| 229 | |||
| 230 | " FUNCTION: Bookmark.New(name, path) {{{1 | ||
| 231 | " Create a new bookmark object with the given name and path object | ||
| 232 | function! s:Bookmark.New(name, path) | ||
| 233 | if a:name =~# ' ' | ||
| 234 | throw 'NERDTree.IllegalBookmarkNameError: illegal name:' . a:name | ||
| 235 | endif | ||
| 236 | |||
| 237 | let newBookmark = copy(self) | ||
| 238 | let newBookmark.name = a:name | ||
| 239 | let newBookmark.path = a:path | ||
| 240 | return newBookmark | ||
| 241 | endfunction | ||
| 242 | |||
| 243 | " FUNCTION: Bookmark.open(nerdtree, [options]) {{{1 | ||
| 244 | "Args: | ||
| 245 | " | ||
| 246 | "nerdtree: the tree to load open the bookmark in | ||
| 247 | " | ||
| 248 | "A dictionary containing the following keys (all optional): | ||
| 249 | " 'where': Specifies whether the node should be opened in new split/tab or in | ||
| 250 | " the previous window. Can be either 'v' (vertical split), 'h' | ||
| 251 | " (horizontal split), 't' (new tab) or 'p' (previous window). | ||
| 252 | " 'reuse': if a window is displaying the file then jump the cursor there | ||
| 253 | " 'keepopen': dont close the tree window | ||
| 254 | " 'stay': open the file, but keep the cursor in the tree win | ||
| 255 | " | ||
| 256 | function! s:Bookmark.open(nerdtree, ...) | ||
| 257 | let opts = a:0 ? a:1 : {} | ||
| 258 | |||
| 259 | if nerdtree#closeBookmarksOnOpen() | ||
| 260 | call a:nerdtree.ui.toggleShowBookmarks() | ||
| 261 | endif | ||
| 262 | |||
| 263 | if self.path.isDirectory && !has_key(opts, 'where') | ||
| 264 | call self.toRoot(a:nerdtree) | ||
| 265 | else | ||
| 266 | let opener = g:NERDTreeOpener.New(self.path, opts) | ||
| 267 | call opener.open(self) | ||
| 268 | endif | ||
| 269 | endfunction | ||
| 270 | |||
| 271 | " FUNCTION: Bookmark.openInNewTab(options) {{{1 | ||
| 272 | " Create a new bookmark object with the given name and path object | ||
| 273 | function! s:Bookmark.openInNewTab(options) | ||
| 274 | call nerdtree#deprecated('Bookmark.openInNewTab', 'is deprecated, use open() instead') | ||
| 275 | call self.open(a:options) | ||
| 276 | endfunction | ||
| 277 | |||
| 278 | " FUNCTION: Bookmark.setPath(path) {{{1 | ||
| 279 | " makes this bookmark point to the given path | ||
| 280 | function! s:Bookmark.setPath(path) | ||
| 281 | let self.path = a:path | ||
| 282 | endfunction | ||
| 283 | |||
| 284 | " FUNCTION: Bookmark.SortBookmarksList() {{{1 | ||
| 285 | " Class method that sorts the global list of bookmarks alphabetically by name. | ||
| 286 | " Note that case-sensitivity is determined by a user option. | ||
| 287 | function! s:Bookmark.SortBookmarksList() | ||
| 288 | call sort(s:Bookmark.Bookmarks(), s:Bookmark.CompareBookmarksByName, s:Bookmark) | ||
| 289 | endfunction | ||
| 290 | |||
| 291 | " FUNCTION: Bookmark.str() {{{1 | ||
| 292 | " Get the string that should be rendered in the view for this bookmark | ||
| 293 | function! s:Bookmark.str() | ||
| 294 | let pathStrMaxLen = winwidth(g:NERDTree.GetWinNum()) - 4 - strdisplaywidth(self.name) | ||
| 295 | if &number | ||
| 296 | let pathStrMaxLen = pathStrMaxLen - &numberwidth | ||
| 297 | endif | ||
| 298 | |||
| 299 | let pathStr = self.path.str({'format': 'UI'}) | ||
| 300 | if strdisplaywidth(pathStr) > pathStrMaxLen | ||
| 301 | while strdisplaywidth(pathStr) > pathStrMaxLen && strchars(pathStr) > 0 | ||
| 302 | let pathStr = substitute(pathStr, '^.', '', '') | ||
| 303 | endwhile | ||
| 304 | let pathStr = '<' . pathStr | ||
| 305 | endif | ||
| 306 | return '>' . self.name . ' ' . pathStr | ||
| 307 | endfunction | ||
| 308 | |||
| 309 | " FUNCTION: Bookmark.toRoot(nerdtree) {{{1 | ||
| 310 | " Set the root of the given NERDTree to the node for this Bookmark. If a node | ||
| 311 | " for this Bookmark does not exist, a new one is initialized. | ||
| 312 | function! s:Bookmark.toRoot(nerdtree) | ||
| 313 | if self.validate() | ||
| 314 | try | ||
| 315 | let l:targetNode = self.getNode(a:nerdtree, 1) | ||
| 316 | call l:targetNode.closeChildren() | ||
| 317 | catch /^NERDTree.BookmarkedNodeNotFoundError/ | ||
| 318 | let l:targetNode = g:NERDTreeFileNode.New(s:Bookmark.BookmarkFor(self.name).path, a:nerdtree) | ||
| 319 | endtry | ||
| 320 | call a:nerdtree.changeRoot(l:targetNode) | ||
| 321 | endif | ||
| 322 | endfunction | ||
| 323 | |||
| 324 | " FUNCTION: Bookmark.ToRoot(name, nerdtree) {{{1 | ||
| 325 | " Class method that makes the Bookmark with the given name the root of | ||
| 326 | " specified NERDTree. | ||
| 327 | function! s:Bookmark.ToRoot(name, nerdtree) | ||
| 328 | let l:bookmark = s:Bookmark.BookmarkFor(a:name) | ||
| 329 | call l:bookmark.toRoot(a:nerdtree) | ||
| 330 | endfunction | ||
| 331 | |||
| 332 | " FUNCTION: Bookmark.validate() {{{1 | ||
| 333 | function! s:Bookmark.validate() | ||
| 334 | if self.path.exists() | ||
| 335 | return 1 | ||
| 336 | else | ||
| 337 | call s:Bookmark.CacheBookmarks(1) | ||
| 338 | call nerdtree#echo(self.name . 'now points to an invalid location. See :help NERDTreeInvalidBookmarks for info.') | ||
| 339 | return 0 | ||
| 340 | endif | ||
| 341 | endfunction | ||
| 342 | |||
| 343 | " FUNCTION: Bookmark.Write() {{{1 | ||
| 344 | " Class method to write all bookmarks to the bookmarks file | ||
| 345 | function! s:Bookmark.Write() | ||
| 346 | let bookmarkStrings = [] | ||
| 347 | for i in s:Bookmark.Bookmarks() | ||
| 348 | call add(bookmarkStrings, i.name . ' ' . fnamemodify(i.path.str(), ':~')) | ||
| 349 | endfor | ||
| 350 | |||
| 351 | "add a blank line before the invalid ones | ||
| 352 | call add(bookmarkStrings, '') | ||
| 353 | |||
| 354 | for j in s:Bookmark.InvalidBookmarks() | ||
| 355 | call add(bookmarkStrings, j) | ||
| 356 | endfor | ||
| 357 | |||
| 358 | try | ||
| 359 | call writefile(bookmarkStrings, g:NERDTreeBookmarksFile) | ||
| 360 | catch | ||
| 361 | call nerdtree#echoError('Failed to write bookmarks file. Make sure g:NERDTreeBookmarksFile points to a valid location.') | ||
| 362 | endtry | ||
| 363 | endfunction | ||
| 364 | |||
| 365 | " vim: set sw=4 sts=4 et fdm=marker: | ||
diff --git a/.vim/pack/vendor/start/nerdtree/lib/nerdtree/creator.vim b/.vim/pack/vendor/start/nerdtree/lib/nerdtree/creator.vim new file mode 100644 index 0000000..b9d45dc --- /dev/null +++ b/.vim/pack/vendor/start/nerdtree/lib/nerdtree/creator.vim  | |||
| @@ -0,0 +1,402 @@ | |||
| 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' ? 'topleft ' : 'botright ' | ||
| 186 | let l:splitSize = g:NERDTreeWinSize | ||
| 187 | |||
| 188 | if !g:NERDTree.ExistsForTab() | ||
| 189 | let t:NERDTreeBufName = self._nextBufferName() | ||
| 190 | silent! execute l:splitLocation . 'vertical ' . l:splitSize . ' new' | ||
| 191 | silent! execute 'edit ' . t:NERDTreeBufName | ||
| 192 | silent! execute 'vertical resize '. l:splitSize | ||
| 193 | else | ||
| 194 | silent! execute l:splitLocation . 'vertical ' . l:splitSize . ' split' | ||
| 195 | silent! execute 'buffer ' . t:NERDTreeBufName | ||
| 196 | endif | ||
| 197 | |||
| 198 | setlocal winfixwidth | ||
| 199 | |||
| 200 | call self._setCommonBufOptions() | ||
| 201 | |||
| 202 | if has('patch-7.4.1925') | ||
| 203 | clearjumps | ||
| 204 | endif | ||
| 205 | |||
| 206 | endfunction | ||
| 207 | |||
| 208 | " FUNCTION: s:Creator._isBufHidden(nr) {{{1 | ||
| 209 | function! s:Creator._isBufHidden(nr) | ||
| 210 | redir => bufs | ||
| 211 | silent ls! | ||
| 212 | redir END | ||
| 213 | |||
| 214 | return bufs =~ a:nr . '..h' | ||
| 215 | endfunction | ||
| 216 | |||
| 217 | " FUNCTION: s:Creator.New() {{{1 | ||
| 218 | function! s:Creator.New() | ||
| 219 | let newCreator = copy(self) | ||
| 220 | return newCreator | ||
| 221 | endfunction | ||
| 222 | |||
| 223 | " FUNCTION: s:Creator._nextBufferName() {{{1 | ||
| 224 | " returns the buffer name for the next nerd tree | ||
| 225 | function! s:Creator._nextBufferName() | ||
| 226 | let name = s:Creator.BufNamePrefix() . self._nextBufferNumber() | ||
| 227 | return name | ||
| 228 | endfunction | ||
| 229 | |||
| 230 | " FUNCTION: s:Creator._nextBufferNumber() {{{1 | ||
| 231 | " the number to add to the nerd tree buffer name to make the buf name unique | ||
| 232 | function! s:Creator._nextBufferNumber() | ||
| 233 | if !exists('s:Creator._NextBufNum') | ||
| 234 | let s:Creator._NextBufNum = 1 | ||
| 235 | else | ||
| 236 | let s:Creator._NextBufNum += 1 | ||
| 237 | endif | ||
| 238 | |||
| 239 | return s:Creator._NextBufNum | ||
| 240 | endfunction | ||
| 241 | |||
| 242 | " FUNCTION: s:Creator._pathForString(str) {{{1 | ||
| 243 | " find a bookmark or adirectory for the given string | ||
| 244 | function! s:Creator._pathForString(str) | ||
| 245 | let path = {} | ||
| 246 | if g:NERDTreeBookmark.BookmarkExistsFor(a:str) | ||
| 247 | let path = g:NERDTreeBookmark.BookmarkFor(a:str).path | ||
| 248 | else | ||
| 249 | let dir = a:str ==# '' ? getcwd() : a:str | ||
| 250 | |||
| 251 | "hack to get an absolute path if a relative path is given | ||
| 252 | if dir =~# '^\.' | ||
| 253 | let dir = getcwd() . nerdtree#slash() . dir | ||
| 254 | endif | ||
| 255 | |||
| 256 | "hack to prevent removing slash if dir is the root of the file system. | ||
| 257 | if dir !=# '/' | ||
| 258 | let dir = g:NERDTreePath.Resolve(dir) | ||
| 259 | endif | ||
| 260 | |||
| 261 | try | ||
| 262 | let path = g:NERDTreePath.New(dir) | ||
| 263 | catch /^NERDTree.InvalidArgumentsError/ | ||
| 264 | call nerdtree#echo('No bookmark or directory found for: ' . a:str) | ||
| 265 | return {} | ||
| 266 | endtry | ||
| 267 | endif | ||
| 268 | if !path.isDirectory | ||
| 269 | let path = path.getParent() | ||
| 270 | endif | ||
| 271 | |||
| 272 | return path | ||
| 273 | endfunction | ||
| 274 | |||
| 275 | " Function: s:Creator._removeTreeBufForTab() {{{1 | ||
| 276 | function! s:Creator._removeTreeBufForTab() | ||
| 277 | let buf = bufnr(t:NERDTreeBufName) | ||
| 278 | |||
| 279 | "if &hidden is not set then it will already be gone | ||
| 280 | if buf != -1 | ||
| 281 | |||
| 282 | "nerdtree buf may be mirrored/displayed elsewhere | ||
| 283 | if self._isBufHidden(buf) | ||
| 284 | exec 'bwipeout ' . buf | ||
| 285 | endif | ||
| 286 | |||
| 287 | endif | ||
| 288 | |||
| 289 | unlet t:NERDTreeBufName | ||
| 290 | endfunction | ||
| 291 | |||
| 292 | " FUNCTION: s:Creator._setCommonBufOptions() {{{1 | ||
| 293 | function! s:Creator._setCommonBufOptions() | ||
| 294 | |||
| 295 | " Options for a non-file/control buffer. | ||
| 296 | setlocal bufhidden=hide | ||
| 297 | setlocal buftype=nofile | ||
| 298 | setlocal noswapfile | ||
| 299 | |||
| 300 | " Options for controlling buffer/window appearance. | ||
| 301 | setlocal foldcolumn=0 | ||
| 302 | setlocal foldmethod=manual | ||
| 303 | setlocal nobuflisted | ||
| 304 | setlocal nofoldenable | ||
| 305 | setlocal nolist | ||
| 306 | setlocal nospell | ||
| 307 | setlocal nowrap | ||
| 308 | |||
| 309 | if g:NERDTreeShowLineNumbers | ||
| 310 | setlocal number | ||
| 311 | else | ||
| 312 | setlocal nonumber | ||
| 313 | if v:version >= 703 | ||
| 314 | setlocal norelativenumber | ||
| 315 | endif | ||
| 316 | endif | ||
| 317 | |||
| 318 | iabc <buffer> | ||
| 319 | |||
| 320 | if g:NERDTreeHighlightCursorline | ||
| 321 | setlocal cursorline | ||
| 322 | endif | ||
| 323 | |||
| 324 | call self._setupStatusline() | ||
| 325 | call self._bindMappings() | ||
| 326 | |||
| 327 | setlocal filetype=nerdtree | ||
| 328 | endfunction | ||
| 329 | |||
| 330 | " FUNCTION: s:Creator._setupStatusline() {{{1 | ||
| 331 | function! s:Creator._setupStatusline() | ||
| 332 | if g:NERDTreeStatusline != -1 | ||
| 333 | let &l:statusline = g:NERDTreeStatusline | ||
| 334 | endif | ||
| 335 | endfunction | ||
| 336 | |||
| 337 | " FUNCTION: s:Creator._tabpagevar(tabnr, var) {{{1 | ||
| 338 | function! s:Creator._tabpagevar(tabnr, var) | ||
| 339 | let currentTab = tabpagenr() | ||
| 340 | let old_ei = &eventignore | ||
| 341 | set eventignore=all | ||
| 342 | |||
| 343 | try | ||
| 344 | exec 'tabnext ' . a:tabnr | ||
| 345 | let v = -1 | ||
| 346 | if exists('t:' . a:var) | ||
| 347 | exec 'let v = t:' . a:var | ||
| 348 | endif | ||
| 349 | exec 'tabnext ' . currentTab | ||
| 350 | |||
| 351 | finally | ||
| 352 | let &eventignore = old_ei | ||
| 353 | endtry | ||
| 354 | |||
| 355 | return v | ||
| 356 | endfunction | ||
| 357 | |||
| 358 | " FUNCTION: s:Creator.ToggleTabTree(dir) {{{1 | ||
| 359 | function! s:Creator.ToggleTabTree(dir) | ||
| 360 | let creator = s:Creator.New() | ||
| 361 | call creator.toggleTabTree(a:dir) | ||
| 362 | endfunction | ||
| 363 | |||
| 364 | " FUNCTION: s:Creator.toggleTabTree(dir) {{{1 | ||
| 365 | " Toggles the NERD tree. I.e if the NERD tree is open, it is closed. If it is | ||
| 366 | " closed, it is restored or initialized. If dir is not empty, it will be set | ||
| 367 | " as the new root. | ||
| 368 | " | ||
| 369 | " Args: | ||
| 370 | " dir: the full path for the root node (is used if the NERD tree is being | ||
| 371 | " initialized, or to change the root to a new dir.) | ||
| 372 | function! s:Creator.toggleTabTree(dir) | ||
| 373 | if g:NERDTree.ExistsForTab() | ||
| 374 | if !g:NERDTree.IsOpen() | ||
| 375 | call self._createTreeWin() | ||
| 376 | if !empty(a:dir) && a:dir !=# b:NERDTree.root.path.str() | ||
| 377 | call self.createTabTree(a:dir) | ||
| 378 | elseif !&hidden | ||
| 379 | call b:NERDTree.render() | ||
| 380 | endif | ||
| 381 | call b:NERDTree.ui.restoreScreenState() | ||
| 382 | else | ||
| 383 | call g:NERDTree.Close() | ||
| 384 | endif | ||
| 385 | else | ||
| 386 | call self.createTabTree(a:dir) | ||
| 387 | endif | ||
| 388 | endfunction | ||
| 389 | |||
| 390 | " Function: s:Creator._uniq(list) {{{1 | ||
| 391 | " returns a:list without duplicates | ||
| 392 | function! s:Creator._uniq(list) | ||
| 393 | let uniqlist = [] | ||
| 394 | for elem in a:list | ||
| 395 | if index(uniqlist, elem) ==# -1 | ||
| 396 | let uniqlist += [elem] | ||
| 397 | endif | ||
| 398 | endfor | ||
| 399 | return uniqlist | ||
| 400 | endfunction | ||
| 401 | |||
| 402 | " vim: set sw=4 sts=4 et fdm=marker: | ||
diff --git a/.vim/pack/vendor/start/nerdtree/lib/nerdtree/event.vim b/.vim/pack/vendor/start/nerdtree/lib/nerdtree/event.vim new file mode 100644 index 0000000..964e8ff --- /dev/null +++ b/.vim/pack/vendor/start/nerdtree/lib/nerdtree/event.vim  | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | "CLASS: Event | ||
| 2 | "============================================================ | ||
| 3 | let s:Event = {} | ||
| 4 | let g:NERDTreeEvent = s:Event | ||
| 5 | |||
| 6 | function! s:Event.New(nerdtree, subject, action, params) abort | ||
| 7 | let newObj = copy(self) | ||
| 8 | let newObj.nerdtree = a:nerdtree | ||
| 9 | let newObj.subject = a:subject | ||
| 10 | let newObj.action = a:action | ||
| 11 | let newObj.params = a:params | ||
| 12 | return newObj | ||
| 13 | endfunction | ||
diff --git a/.vim/pack/vendor/start/nerdtree/lib/nerdtree/flag_set.vim b/.vim/pack/vendor/start/nerdtree/lib/nerdtree/flag_set.vim new file mode 100644 index 0000000..7552867 --- /dev/null +++ b/.vim/pack/vendor/start/nerdtree/lib/nerdtree/flag_set.vim  | |||
| @@ -0,0 +1,58 @@ | |||
| 1 | "CLASS: FlagSet | ||
| 2 | "============================================================ | ||
| 3 | let s:FlagSet = {} | ||
| 4 | let g:NERDTreeFlagSet = s:FlagSet | ||
| 5 | |||
| 6 | "FUNCTION: FlagSet.addFlag(scope, flag) {{{1 | ||
| 7 | function! s:FlagSet.addFlag(scope, flag) | ||
| 8 | let flags = self._flagsForScope(a:scope) | ||
| 9 | if index(flags, a:flag) == -1 | ||
| 10 | call add(flags, a:flag) | ||
| 11 | end | ||
| 12 | endfunction | ||
| 13 | |||
| 14 | "FUNCTION: FlagSet.clearFlags(scope) {{{1 | ||
| 15 | function! s:FlagSet.clearFlags(scope) | ||
| 16 | let self._flags[a:scope] = [] | ||
| 17 | endfunction | ||
| 18 | |||
| 19 | "FUNCTION: FlagSet._flagsForScope(scope) {{{1 | ||
| 20 | function! s:FlagSet._flagsForScope(scope) | ||
| 21 | if !has_key(self._flags, a:scope) | ||
| 22 | let self._flags[a:scope] = [] | ||
| 23 | endif | ||
| 24 | return self._flags[a:scope] | ||
| 25 | endfunction | ||
| 26 | |||
| 27 | "FUNCTION: FlagSet.New() {{{1 | ||
| 28 | function! s:FlagSet.New() | ||
| 29 | let newObj = copy(self) | ||
| 30 | let newObj._flags = {} | ||
| 31 | return newObj | ||
| 32 | endfunction | ||
| 33 | |||
| 34 | "FUNCTION: FlagSet.removeFlag(scope, flag) {{{1 | ||
| 35 | function! s:FlagSet.removeFlag(scope, flag) | ||
| 36 | let flags = self._flagsForScope(a:scope) | ||
| 37 | |||
| 38 | let i = index(flags, a:flag) | ||
| 39 | if i >= 0 | ||
| 40 | call remove(flags, i) | ||
| 41 | endif | ||
| 42 | endfunction | ||
| 43 | |||
| 44 | "FUNCTION: FlagSet.renderToString() {{{1 | ||
| 45 | function! s:FlagSet.renderToString() | ||
| 46 | let flagstring = '' | ||
| 47 | for i in values(self._flags) | ||
| 48 | let flagstring .= join(i) | ||
| 49 | endfor | ||
| 50 | |||
| 51 | if len(flagstring) == 0 | ||
| 52 | return '' | ||
| 53 | endif | ||
| 54 | |||
| 55 | return '[' . flagstring . ']' | ||
| 56 | endfunction | ||
| 57 | |||
| 58 | " vim: set sw=4 sts=4 et fdm=marker: | ||
diff --git a/.vim/pack/vendor/start/nerdtree/lib/nerdtree/key_map.vim b/.vim/pack/vendor/start/nerdtree/lib/nerdtree/key_map.vim new file mode 100644 index 0000000..ed79167 --- /dev/null +++ b/.vim/pack/vendor/start/nerdtree/lib/nerdtree/key_map.vim  | |||
| @@ -0,0 +1,164 @@ | |||
| 1 | "CLASS: KeyMap | ||
| 2 | "============================================================ | ||
| 3 | let s:KeyMap = {} | ||
| 4 | let g:NERDTreeKeyMap = s:KeyMap | ||
| 5 | let s:keyMaps = {} | ||
| 6 | |||
| 7 | "FUNCTION: KeyMap.All() {{{1 | ||
| 8 | function! s:KeyMap.All() | ||
| 9 | let sortedKeyMaps = values(s:keyMaps) | ||
| 10 | call sort(sortedKeyMaps, s:KeyMap.Compare, s:KeyMap) | ||
| 11 | |||
| 12 | return sortedKeyMaps | ||
| 13 | endfunction | ||
| 14 | |||
| 15 | "FUNCTION: KeyMap.Compare(keyMap1, keyMap2) {{{1 | ||
| 16 | function! s:KeyMap.Compare(keyMap1, keyMap2) | ||
| 17 | |||
| 18 | if a:keyMap1.key >? a:keyMap2.key | ||
| 19 | return 1 | ||
| 20 | endif | ||
| 21 | |||
| 22 | if a:keyMap1.key <? a:keyMap2.key | ||
| 23 | return -1 | ||
| 24 | endif | ||
| 25 | |||
| 26 | return 0 | ||
| 27 | endfunction | ||
| 28 | |||
| 29 | "FUNCTION: KeyMap.FindFor(key, scope) {{{1 | ||
| 30 | function! s:KeyMap.FindFor(key, scope) | ||
| 31 | return get(s:keyMaps, a:key . a:scope, {}) | ||
| 32 | endfunction | ||
| 33 | |||
| 34 | "FUNCTION: KeyMap.BindAll() {{{1 | ||
| 35 | function! s:KeyMap.BindAll() | ||
| 36 | for i in values(s:keyMaps) | ||
| 37 | call i.bind() | ||
| 38 | endfor | ||
| 39 | endfunction | ||
| 40 | |||
| 41 | "FUNCTION: KeyMap.bind() {{{1 | ||
| 42 | function! s:KeyMap.bind() | ||
| 43 | " If the key sequence we're trying to map contains any '<>' notation, we | ||
| 44 | " must replace each of the '<' characters with '<lt>' to ensure the string | ||
| 45 | " is not translated into its corresponding keycode during the later part | ||
| 46 | " of the map command below | ||
| 47 | " :he <> | ||
| 48 | let specialNotationRegex = '\m<\([[:alnum:]_-]\+>\)' | ||
| 49 | if self.key =~# specialNotationRegex | ||
| 50 | let keymapInvokeString = substitute(self.key, specialNotationRegex, '<lt>\1', 'g') | ||
| 51 | else | ||
| 52 | let keymapInvokeString = self.key | ||
| 53 | endif | ||
| 54 | let keymapInvokeString = escape(keymapInvokeString, '\"') | ||
| 55 | |||
| 56 | let premap = self.key ==# '<LeftRelease>' ? ' <LeftRelease>' : ' ' | ||
| 57 | |||
| 58 | exec 'nnoremap <buffer> <silent> '. self.key . premap . ':call nerdtree#ui_glue#invokeKeyMap("'. keymapInvokeString .'")<cr>' | ||
| 59 | endfunction | ||
| 60 | |||
| 61 | "FUNCTION: KeyMap.Remove(key, scope) {{{1 | ||
| 62 | function! s:KeyMap.Remove(key, scope) | ||
| 63 | return remove(s:keyMaps, a:key . a:scope) | ||
| 64 | endfunction | ||
| 65 | |||
| 66 | "FUNCTION: KeyMap.invoke() {{{1 | ||
| 67 | "Call the KeyMaps callback function | ||
| 68 | function! s:KeyMap.invoke(...) | ||
| 69 | let l:Callback = type(self.callback) ==# type(function('tr')) ? self.callback : function(self.callback) | ||
| 70 | if a:0 | ||
| 71 | call l:Callback(a:1) | ||
| 72 | else | ||
| 73 | call l:Callback() | ||
| 74 | endif | ||
| 75 | endfunction | ||
| 76 | |||
| 77 | "FUNCTION: KeyMap.Invoke() {{{1 | ||
| 78 | "Find a keymapping for a:key and the current scope invoke it. | ||
| 79 | " | ||
| 80 | "Scope is determined as follows: | ||
| 81 | " * if the cursor is on a dir node then DirNode | ||
| 82 | " * if the cursor is on a file node then FileNode | ||
| 83 | " * if the cursor is on a bookmark then Bookmark | ||
| 84 | " | ||
| 85 | "If a keymap has the scope of 'all' then it will be called if no other keymap | ||
| 86 | "is found for a:key and the scope. | ||
| 87 | function! s:KeyMap.Invoke(key) | ||
| 88 | |||
| 89 | "required because clicking the command window below another window still | ||
| 90 | "invokes the <LeftRelease> mapping - but changes the window cursor | ||
| 91 | "is in first | ||
| 92 | " | ||
| 93 | "TODO: remove this check when the vim bug is fixed | ||
| 94 | if !g:NERDTree.ExistsForBuf() | ||
| 95 | return {} | ||
| 96 | endif | ||
| 97 | |||
| 98 | let node = g:NERDTreeFileNode.GetSelected() | ||
| 99 | if !empty(node) | ||
| 100 | |||
| 101 | "try file node | ||
| 102 | if !node.path.isDirectory | ||
| 103 | let km = s:KeyMap.FindFor(a:key, 'FileNode') | ||
| 104 | if !empty(km) | ||
| 105 | return km.invoke(node) | ||
| 106 | endif | ||
| 107 | endif | ||
| 108 | |||
| 109 | "try dir node | ||
| 110 | if node.path.isDirectory | ||
| 111 | let km = s:KeyMap.FindFor(a:key, 'DirNode') | ||
| 112 | if !empty(km) | ||
| 113 | return km.invoke(node) | ||
| 114 | endif | ||
| 115 | endif | ||
| 116 | |||
| 117 | "try generic node | ||
| 118 | let km = s:KeyMap.FindFor(a:key, 'Node') | ||
| 119 | if !empty(km) | ||
| 120 | return km.invoke(node) | ||
| 121 | endif | ||
| 122 | |||
| 123 | endif | ||
| 124 | |||
| 125 | "try bookmark | ||
| 126 | let bm = g:NERDTreeBookmark.GetSelected() | ||
| 127 | if !empty(bm) | ||
| 128 | let km = s:KeyMap.FindFor(a:key, 'Bookmark') | ||
| 129 | if !empty(km) | ||
| 130 | return km.invoke(bm) | ||
| 131 | endif | ||
| 132 | endif | ||
| 133 | |||
| 134 | "try all | ||
| 135 | let km = s:KeyMap.FindFor(a:key, 'all') | ||
| 136 | if !empty(km) | ||
| 137 | return km.invoke() | ||
| 138 | endif | ||
| 139 | endfunction | ||
| 140 | |||
| 141 | "FUNCTION: KeyMap.Create(options) {{{1 | ||
| 142 | function! s:KeyMap.Create(options) | ||
| 143 | let opts = extend({'scope': 'all', 'quickhelpText': ''}, copy(a:options)) | ||
| 144 | |||
| 145 | "dont override other mappings unless the 'override' option is given | ||
| 146 | if get(opts, 'override', 0) ==# 0 && !empty(s:KeyMap.FindFor(opts['key'], opts['scope'])) | ||
| 147 | return | ||
| 148 | end | ||
| 149 | |||
| 150 | let newKeyMap = copy(self) | ||
| 151 | let newKeyMap.key = opts['key'] | ||
| 152 | let newKeyMap.quickhelpText = opts['quickhelpText'] | ||
| 153 | let newKeyMap.callback = opts['callback'] | ||
| 154 | let newKeyMap.scope = opts['scope'] | ||
| 155 | |||
| 156 | call s:KeyMap.Add(newKeyMap) | ||
| 157 | endfunction | ||
| 158 | |||
| 159 | "FUNCTION: KeyMap.Add(keymap) {{{1 | ||
| 160 | function! s:KeyMap.Add(keymap) | ||
| 161 | let s:keyMaps[a:keymap.key . a:keymap.scope] = a:keymap | ||
| 162 | endfunction | ||
| 163 | |||
| 164 | " vim: set sw=4 sts=4 et fdm=marker: | ||
diff --git a/.vim/pack/vendor/start/nerdtree/lib/nerdtree/menu_controller.vim b/.vim/pack/vendor/start/nerdtree/lib/nerdtree/menu_controller.vim new file mode 100644 index 0000000..952c67b --- /dev/null +++ b/.vim/pack/vendor/start/nerdtree/lib/nerdtree/menu_controller.vim  | |||
| @@ -0,0 +1,211 @@ | |||
| 1 | "CLASS: MenuController | ||
| 2 | "============================================================ | ||
| 3 | let s:MenuController = {} | ||
| 4 | let g:NERDTreeMenuController = s:MenuController | ||
| 5 | |||
| 6 | "FUNCTION: MenuController.New(menuItems) {{{1 | ||
| 7 | "create a new menu controller that operates on the given menu items | ||
| 8 | function! s:MenuController.New(menuItems) | ||
| 9 | let newMenuController = copy(self) | ||
| 10 | if a:menuItems[0].isSeparator() | ||
| 11 | let newMenuController.menuItems = a:menuItems[1:-1] | ||
| 12 | else | ||
| 13 | let newMenuController.menuItems = a:menuItems | ||
| 14 | endif | ||
| 15 | return newMenuController | ||
| 16 | endfunction | ||
| 17 | |||
| 18 | " FUNCTION: s:MenuController.isMinimal() {{{1 | ||
| 19 | function! s:MenuController.isMinimal() | ||
| 20 | return g:NERDTreeMinimalMenu | ||
| 21 | endfunction | ||
| 22 | |||
| 23 | " FUNCTION: MenuController.showMenu() {{{1 | ||
| 24 | " Enter the main loop of the NERDTree menu, prompting the user to select | ||
| 25 | " a menu item. | ||
| 26 | function! s:MenuController.showMenu() | ||
| 27 | call self._saveOptions() | ||
| 28 | |||
| 29 | try | ||
| 30 | let self.selection = 0 | ||
| 31 | let l:done = 0 | ||
| 32 | |||
| 33 | while !l:done | ||
| 34 | if has('nvim') | ||
| 35 | mode | ||
| 36 | else | ||
| 37 | redraw! | ||
| 38 | endif | ||
| 39 | call self._echoPrompt() | ||
| 40 | |||
| 41 | let l:key = nr2char(getchar()) | ||
| 42 | let l:done = self._handleKeypress(l:key) | ||
| 43 | endwhile | ||
| 44 | finally | ||
| 45 | call self._restoreOptions() | ||
| 46 | |||
| 47 | " Redraw when Ctrl-C or Esc is received. | ||
| 48 | if !l:done || self.selection ==# -1 | ||
| 49 | redraw! | ||
| 50 | endif | ||
| 51 | endtry | ||
| 52 | |||
| 53 | if self.selection !=# -1 | ||
| 54 | let l:m = self._current() | ||
| 55 | call l:m.execute() | ||
| 56 | endif | ||
| 57 | endfunction | ||
| 58 | |||
| 59 | "FUNCTION: MenuController._echoPrompt() {{{1 | ||
| 60 | function! s:MenuController._echoPrompt() | ||
| 61 | let navHelp = 'Use ' . g:NERDTreeMenuDown . '/' . g:NERDTreeMenuUp . '/enter' | ||
| 62 | |||
| 63 | if self.isMinimal() | ||
| 64 | let selection = self.menuItems[self.selection].text | ||
| 65 | let keyword = matchstr(selection, '[^ ]*([^ ]*') | ||
| 66 | |||
| 67 | let shortcuts = map(copy(self.menuItems), "v:val['shortcut']") | ||
| 68 | let shortcuts[self.selection] = ' ' . keyword . ' ' | ||
| 69 | |||
| 70 | echo 'Menu: [' . join(shortcuts, ',') . '] (' . navHelp . ' or shortcut): ' | ||
| 71 | else | ||
| 72 | echo 'NERDTree Menu. ' . navHelp . ', or the shortcuts indicated' | ||
| 73 | echo '=========================================================' | ||
| 74 | |||
| 75 | for i in range(0, len(self.menuItems)-1) | ||
| 76 | if self.selection ==# i | ||
| 77 | echo '> ' . self.menuItems[i].text | ||
| 78 | else | ||
| 79 | echo ' ' . self.menuItems[i].text | ||
| 80 | endif | ||
| 81 | endfor | ||
| 82 | endif | ||
| 83 | endfunction | ||
| 84 | |||
| 85 | "FUNCTION: MenuController._current(key) {{{1 | ||
| 86 | "get the MenuItem that is currently selected | ||
| 87 | function! s:MenuController._current() | ||
| 88 | return self.menuItems[self.selection] | ||
| 89 | endfunction | ||
| 90 | |||
| 91 | "FUNCTION: MenuController._handleKeypress(key) {{{1 | ||
| 92 | "change the selection (if appropriate) and return 1 if the user has made | ||
| 93 | "their choice, 0 otherwise | ||
| 94 | function! s:MenuController._handleKeypress(key) | ||
| 95 | if a:key ==# g:NERDTreeMenuDown | ||
| 96 | call self._cursorDown() | ||
| 97 | elseif a:key ==# g:NERDTreeMenuUp | ||
| 98 | call self._cursorUp() | ||
| 99 | elseif a:key ==# nr2char(27) "escape | ||
| 100 | let self.selection = -1 | ||
| 101 | return 1 | ||
| 102 | elseif a:key ==# "\r" || a:key ==# "\n" "enter and ctrl-j | ||
| 103 | return 1 | ||
| 104 | else | ||
| 105 | let index = self._nextIndexFor(a:key) | ||
| 106 | if index !=# -1 | ||
| 107 | let self.selection = index | ||
| 108 | if len(self._allIndexesFor(a:key)) ==# 1 | ||
| 109 | return 1 | ||
| 110 | endif | ||
| 111 | endif | ||
| 112 | endif | ||
| 113 | |||
| 114 | return 0 | ||
| 115 | endfunction | ||
| 116 | |||
| 117 | "FUNCTION: MenuController._allIndexesFor(shortcut) {{{1 | ||
| 118 | "get indexes to all menu items with the given shortcut | ||
| 119 | function! s:MenuController._allIndexesFor(shortcut) | ||
| 120 | let toReturn = [] | ||
| 121 | |||
| 122 | for i in range(0, len(self.menuItems)-1) | ||
| 123 | if self.menuItems[i].shortcut ==# a:shortcut | ||
| 124 | call add(toReturn, i) | ||
| 125 | endif | ||
| 126 | endfor | ||
| 127 | |||
| 128 | return toReturn | ||
| 129 | endfunction | ||
| 130 | |||
| 131 | "FUNCTION: MenuController._nextIndexFor(shortcut) {{{1 | ||
| 132 | "get the index to the next menu item with the given shortcut, starts from the | ||
| 133 | "current cursor location and wraps around to the top again if need be | ||
| 134 | function! s:MenuController._nextIndexFor(shortcut) | ||
| 135 | for i in range(self.selection+1, len(self.menuItems)-1) | ||
| 136 | if self.menuItems[i].shortcut ==# a:shortcut | ||
| 137 | return i | ||
| 138 | endif | ||
| 139 | endfor | ||
| 140 | |||
| 141 | for i in range(0, self.selection) | ||
| 142 | if self.menuItems[i].shortcut ==# a:shortcut | ||
| 143 | return i | ||
| 144 | endif | ||
| 145 | endfor | ||
| 146 | |||
| 147 | return -1 | ||
| 148 | endfunction | ||
| 149 | |||
| 150 | "FUNCTION: MenuController._setCmdheight() {{{1 | ||
| 151 | "sets &cmdheight to whatever is needed to display the menu | ||
| 152 | function! s:MenuController._setCmdheight() | ||
| 153 | if self.isMinimal() | ||
| 154 | let &cmdheight = 1 | ||
| 155 | else | ||
| 156 | let &cmdheight = len(self.menuItems) + 3 | ||
| 157 | endif | ||
| 158 | endfunction | ||
| 159 | |||
| 160 | "FUNCTION: MenuController._saveOptions() {{{1 | ||
| 161 | "set any vim options that are required to make the menu work (saving their old | ||
| 162 | "values) | ||
| 163 | function! s:MenuController._saveOptions() | ||
| 164 | let self._oldLazyredraw = &lazyredraw | ||
| 165 | let self._oldCmdheight = &cmdheight | ||
| 166 | set nolazyredraw | ||
| 167 | call self._setCmdheight() | ||
| 168 | endfunction | ||
| 169 | |||
| 170 | "FUNCTION: MenuController._restoreOptions() {{{1 | ||
| 171 | "restore the options we saved in _saveOptions() | ||
| 172 | function! s:MenuController._restoreOptions() | ||
| 173 | let &cmdheight = self._oldCmdheight | ||
| 174 | let &lazyredraw = self._oldLazyredraw | ||
| 175 | endfunction | ||
| 176 | |||
| 177 | "FUNCTION: MenuController._cursorDown() {{{1 | ||
| 178 | "move the cursor to the next menu item, skipping separators | ||
| 179 | function! s:MenuController._cursorDown() | ||
| 180 | let done = 0 | ||
| 181 | while !done | ||
| 182 | if self.selection < len(self.menuItems)-1 | ||
| 183 | let self.selection += 1 | ||
| 184 | else | ||
| 185 | let self.selection = 0 | ||
| 186 | endif | ||
| 187 | |||
| 188 | if !self._current().isSeparator() | ||
| 189 | let done = 1 | ||
| 190 | endif | ||
| 191 | endwhile | ||
| 192 | endfunction | ||
| 193 | |||
| 194 | "FUNCTION: MenuController._cursorUp() {{{1 | ||
| 195 | "move the cursor to the previous menu item, skipping separators | ||
| 196 | function! s:MenuController._cursorUp() | ||
| 197 | let done = 0 | ||
| 198 | while !done | ||
| 199 | if self.selection > 0 | ||
| 200 | let self.selection -= 1 | ||
| 201 | else | ||
| 202 | let self.selection = len(self.menuItems)-1 | ||
| 203 | endif | ||
| 204 | |||
| 205 | if !self._current().isSeparator() | ||
| 206 | let done = 1 | ||
| 207 | endif | ||
| 208 | endwhile | ||
| 209 | endfunction | ||
| 210 | |||
| 211 | " vim: set sw=4 sts=4 et fdm=marker: | ||
diff --git a/.vim/pack/vendor/start/nerdtree/lib/nerdtree/menu_item.vim b/.vim/pack/vendor/start/nerdtree/lib/nerdtree/menu_item.vim new file mode 100644 index 0000000..7f25917 --- /dev/null +++ b/.vim/pack/vendor/start/nerdtree/lib/nerdtree/menu_item.vim  | |||
| @@ -0,0 +1,118 @@ | |||
| 1 | "CLASS: MenuItem | ||
| 2 | "============================================================ | ||
| 3 | let s:MenuItem = {} | ||
| 4 | let g:NERDTreeMenuItem = s:MenuItem | ||
| 5 | |||
| 6 | "FUNCTION: MenuItem.All() {{{1 | ||
| 7 | "get all top level menu items | ||
| 8 | function! s:MenuItem.All() | ||
| 9 | if !exists('s:menuItems') | ||
| 10 | let s:menuItems = [] | ||
| 11 | endif | ||
| 12 | return s:menuItems | ||
| 13 | endfunction | ||
| 14 | |||
| 15 | "FUNCTION: MenuItem.AllEnabled() {{{1 | ||
| 16 | "get all top level menu items that are currently enabled | ||
| 17 | function! s:MenuItem.AllEnabled() | ||
| 18 | let toReturn = [] | ||
| 19 | for i in s:MenuItem.All() | ||
| 20 | if i.enabled() | ||
| 21 | call add(toReturn, i) | ||
| 22 | endif | ||
| 23 | endfor | ||
| 24 | return toReturn | ||
| 25 | endfunction | ||
| 26 | |||
| 27 | "FUNCTION: MenuItem.Create(options) {{{1 | ||
| 28 | "make a new menu item and add it to the global list | ||
| 29 | function! s:MenuItem.Create(options) | ||
| 30 | let newMenuItem = copy(self) | ||
| 31 | |||
| 32 | let newMenuItem.text = a:options['text'] | ||
| 33 | let newMenuItem.shortcut = a:options['shortcut'] | ||
| 34 | let newMenuItem.children = [] | ||
| 35 | |||
| 36 | let newMenuItem.isActiveCallback = -1 | ||
| 37 | if has_key(a:options, 'isActiveCallback') | ||
| 38 | let newMenuItem.isActiveCallback = a:options['isActiveCallback'] | ||
| 39 | endif | ||
| 40 | |||
| 41 | let newMenuItem.callback = -1 | ||
| 42 | if has_key(a:options, 'callback') | ||
| 43 | let newMenuItem.callback = a:options['callback'] | ||
| 44 | endif | ||
| 45 | |||
| 46 | if has_key(a:options, 'parent') | ||
| 47 | call add(a:options['parent'].children, newMenuItem) | ||
| 48 | else | ||
| 49 | call add(s:MenuItem.All(), newMenuItem) | ||
| 50 | endif | ||
| 51 | |||
| 52 | return newMenuItem | ||
| 53 | endfunction | ||
| 54 | |||
| 55 | "FUNCTION: MenuItem.CreateSeparator(options) {{{1 | ||
| 56 | "make a new separator menu item and add it to the global list | ||
| 57 | function! s:MenuItem.CreateSeparator(options) | ||
| 58 | let standard_options = { 'text': '--------------------', | ||
| 59 | \ 'shortcut': -1, | ||
| 60 | \ 'callback': -1 } | ||
| 61 | let options = extend(a:options, standard_options, 'force') | ||
| 62 | |||
| 63 | return s:MenuItem.Create(options) | ||
| 64 | endfunction | ||
| 65 | |||
| 66 | "FUNCTION: MenuItem.CreateSubmenu(options) {{{1 | ||
| 67 | "make a new submenu and add it to global list | ||
| 68 | function! s:MenuItem.CreateSubmenu(options) | ||
| 69 | let standard_options = { 'callback': -1 } | ||
| 70 | let options = extend(a:options, standard_options, 'force') | ||
| 71 | |||
| 72 | return s:MenuItem.Create(options) | ||
| 73 | endfunction | ||
| 74 | |||
| 75 | "FUNCTION: MenuItem.enabled() {{{1 | ||
| 76 | "return 1 if this menu item should be displayed | ||
| 77 | " | ||
| 78 | "delegates off to the isActiveCallback, and defaults to 1 if no callback was | ||
| 79 | "specified | ||
| 80 | function! s:MenuItem.enabled() | ||
| 81 | if self.isActiveCallback != -1 | ||
| 82 | return type(self.isActiveCallback) == type(function('tr')) ? self.isActiveCallback() : {self.isActiveCallback}() | ||
| 83 | endif | ||
| 84 | return 1 | ||
| 85 | endfunction | ||
| 86 | |||
| 87 | "FUNCTION: MenuItem.execute() {{{1 | ||
| 88 | "perform the action behind this menu item, if this menuitem has children then | ||
| 89 | "display a new menu for them, otherwise deletegate off to the menuitem's | ||
| 90 | "callback | ||
| 91 | function! s:MenuItem.execute() | ||
| 92 | if len(self.children) | ||
| 93 | let mc = g:NERDTreeMenuController.New(self.children) | ||
| 94 | call mc.showMenu() | ||
| 95 | else | ||
| 96 | if self.callback != -1 | ||
| 97 | if type(self.callback) == type(function('tr')) | ||
| 98 | call self.callback() | ||
| 99 | else | ||
| 100 | call {self.callback}() | ||
| 101 | endif | ||
| 102 | endif | ||
| 103 | endif | ||
| 104 | endfunction | ||
| 105 | |||
| 106 | "FUNCTION: MenuItem.isSeparator() {{{1 | ||
| 107 | "return 1 if this menuitem is a separator | ||
| 108 | function! s:MenuItem.isSeparator() | ||
| 109 | return self.callback == -1 && self.children == [] | ||
| 110 | endfunction | ||
| 111 | |||
| 112 | "FUNCTION: MenuItem.isSubmenu() {{{1 | ||
| 113 | "return 1 if this menuitem is a submenu | ||
| 114 | function! s:MenuItem.isSubmenu() | ||
| 115 | return self.callback == -1 && !empty(self.children) | ||
| 116 | endfunction | ||
| 117 | |||
| 118 | " vim: set sw=4 sts=4 et fdm=marker: | ||
diff --git a/.vim/pack/vendor/start/nerdtree/lib/nerdtree/nerdtree.vim b/.vim/pack/vendor/start/nerdtree/lib/nerdtree/nerdtree.vim new file mode 100644 index 0000000..61a11a9 --- /dev/null +++ b/.vim/pack/vendor/start/nerdtree/lib/nerdtree/nerdtree.vim  | |||
| @@ -0,0 +1,209 @@ | |||
| 1 | "CLASS: NERDTree | ||
| 2 | "============================================================ | ||
| 3 | let s:NERDTree = {} | ||
| 4 | let g:NERDTree = s:NERDTree | ||
| 5 | |||
| 6 | "FUNCTION: s:NERDTree.AddPathFilter() {{{1 | ||
| 7 | function! s:NERDTree.AddPathFilter(callback) | ||
| 8 | call add(s:NERDTree.PathFilters(), a:callback) | ||
| 9 | endfunction | ||
| 10 | |||
| 11 | "FUNCTION: s:NERDTree.changeRoot(node) {{{1 | ||
| 12 | function! s:NERDTree.changeRoot(node) | ||
| 13 | if a:node.path.isDirectory | ||
| 14 | let self.root = a:node | ||
| 15 | else | ||
| 16 | call a:node.cacheParent() | ||
| 17 | let self.root = a:node.parent | ||
| 18 | endif | ||
| 19 | |||
| 20 | call self.root.open() | ||
| 21 | |||
| 22 | "change dir to the dir of the new root if instructed to | ||
| 23 | if g:NERDTreeChDirMode >= 2 | ||
| 24 | call self.root.path.changeToDir() | ||
| 25 | endif | ||
| 26 | |||
| 27 | call self.render() | ||
| 28 | call self.root.putCursorHere(0, 0) | ||
| 29 | |||
| 30 | if exists('#User#NERDTreeNewRoot') | ||
| 31 | doautocmd User NERDTreeNewRoot | ||
| 32 | endif | ||
| 33 | endfunction | ||
| 34 | |||
| 35 | "FUNCTION: s:NERDTree.Close() {{{1 | ||
| 36 | "Closes the tab tree window for this tab | ||
| 37 | function! s:NERDTree.Close() | ||
| 38 | if !s:NERDTree.IsOpen() | ||
| 39 | return | ||
| 40 | endif | ||
| 41 | |||
| 42 | if winnr('$') !=# 1 | ||
| 43 | " Use the window ID to identify the currently active window or fall | ||
| 44 | " back on the buffer ID if win_getid/win_gotoid are not available, in | ||
| 45 | " which case we'll focus an arbitrary window showing the buffer. | ||
| 46 | let l:useWinId = exists('*win_getid') && exists('*win_gotoid') | ||
| 47 | |||
| 48 | if winnr() ==# s:NERDTree.GetWinNum() | ||
| 49 | call nerdtree#exec('wincmd p', 1) | ||
| 50 | let l:activeBufOrWin = l:useWinId ? win_getid() : bufnr('') | ||
| 51 | call nerdtree#exec('wincmd p', 1) | ||
| 52 | else | ||
| 53 | let l:activeBufOrWin = l:useWinId ? win_getid() : bufnr('') | ||
| 54 | endif | ||
| 55 | |||
| 56 | call nerdtree#exec(s:NERDTree.GetWinNum() . ' wincmd w', 1) | ||
| 57 | call nerdtree#exec('close', 0) | ||
| 58 | if l:useWinId | ||
| 59 | call nerdtree#exec('call win_gotoid(' . l:activeBufOrWin . ')', 0) | ||
| 60 | else | ||
| 61 | call nerdtree#exec(bufwinnr(l:activeBufOrWin) . ' wincmd w', 0) | ||
| 62 | endif | ||
| 63 | else | ||
| 64 | close | ||
| 65 | endif | ||
| 66 | endfunction | ||
| 67 | |||
| 68 | "FUNCTION: s:NERDTree.CursorToBookmarkTable(){{{1 | ||
| 69 | "Places the cursor at the top of the bookmarks table | ||
| 70 | function! s:NERDTree.CursorToBookmarkTable() | ||
| 71 | if !b:NERDTree.ui.getShowBookmarks() | ||
| 72 | throw 'NERDTree.IllegalOperationError: cant find bookmark table, bookmarks arent active' | ||
| 73 | endif | ||
| 74 | |||
| 75 | if g:NERDTreeMinimalUI | ||
| 76 | return cursor(1, 2) | ||
| 77 | endif | ||
| 78 | |||
| 79 | let rootNodeLine = b:NERDTree.ui.getRootLineNum() | ||
| 80 | |||
| 81 | let line = 1 | ||
| 82 | while getline(line) !~# '^>-\+Bookmarks-\+$' | ||
| 83 | let line = line + 1 | ||
| 84 | if line >= rootNodeLine | ||
| 85 | throw 'NERDTree.BookmarkTableNotFoundError: didnt find the bookmarks table' | ||
| 86 | endif | ||
| 87 | endwhile | ||
| 88 | call cursor(line, 2) | ||
| 89 | endfunction | ||
| 90 | |||
| 91 | "FUNCTION: s:NERDTree.CursorToTreeWin(){{{1 | ||
| 92 | "Places the cursor in the nerd tree window | ||
| 93 | function! s:NERDTree.CursorToTreeWin(...) | ||
| 94 | call g:NERDTree.MustBeOpen() | ||
| 95 | call nerdtree#exec(g:NERDTree.GetWinNum() . 'wincmd w', a:0 >0 ? a:1 : 1) | ||
| 96 | endfunction | ||
| 97 | |||
| 98 | " Function: s:NERDTree.ExistsForBuffer() {{{1 | ||
| 99 | " Returns 1 if a nerd tree root exists in the current buffer | ||
| 100 | function! s:NERDTree.ExistsForBuf() | ||
| 101 | return exists('b:NERDTree') | ||
| 102 | endfunction | ||
| 103 | |||
| 104 | " Function: s:NERDTree.ExistsForTab() {{{1 | ||
| 105 | " Returns 1 if a nerd tree root exists in the current tab | ||
| 106 | function! s:NERDTree.ExistsForTab() | ||
| 107 | if !exists('t:NERDTreeBufName') | ||
| 108 | return | ||
| 109 | end | ||
| 110 | |||
| 111 | "check b:NERDTree is still there and hasn't been e.g. :bdeleted | ||
| 112 | return !empty(getbufvar(bufnr(t:NERDTreeBufName), 'NERDTree')) | ||
| 113 | endfunction | ||
| 114 | |||
| 115 | function! s:NERDTree.ForCurrentBuf() | ||
| 116 | if s:NERDTree.ExistsForBuf() | ||
| 117 | return b:NERDTree | ||
| 118 | else | ||
| 119 | return {} | ||
| 120 | endif | ||
| 121 | endfunction | ||
| 122 | |||
| 123 | "FUNCTION: s:NERDTree.ForCurrentTab() {{{1 | ||
| 124 | function! s:NERDTree.ForCurrentTab() | ||
| 125 | if !s:NERDTree.ExistsForTab() | ||
| 126 | return | ||
| 127 | endif | ||
| 128 | |||
| 129 | let bufnr = bufnr(t:NERDTreeBufName) | ||
| 130 | return getbufvar(bufnr, 'NERDTree') | ||
| 131 | endfunction | ||
| 132 | |||
| 133 | "FUNCTION: s:NERDTree.getRoot() {{{1 | ||
| 134 | function! s:NERDTree.getRoot() | ||
| 135 | return self.root | ||
| 136 | endfunction | ||
| 137 | |||
| 138 | "FUNCTION: s:NERDTree.GetWinNum() {{{1 | ||
| 139 | "gets the nerd tree window number for this tab | ||
| 140 | function! s:NERDTree.GetWinNum() | ||
| 141 | if exists('t:NERDTreeBufName') | ||
| 142 | return bufwinnr(t:NERDTreeBufName) | ||
| 143 | endif | ||
| 144 | |||
| 145 | " If WindowTree, there is no t:NERDTreeBufName variable. Search all windows. | ||
| 146 | for w in range(1,winnr('$')) | ||
| 147 | if bufname(winbufnr(w)) =~# '^' . g:NERDTreeCreator.BufNamePrefix() . '\d\+$' | ||
| 148 | return w | ||
| 149 | endif | ||
| 150 | endfor | ||
| 151 | |||
| 152 | return -1 | ||
| 153 | endfunction | ||
| 154 | |||
| 155 | "FUNCTION: s:NERDTree.IsOpen() {{{1 | ||
| 156 | function! s:NERDTree.IsOpen() | ||
| 157 | return s:NERDTree.GetWinNum() !=# -1 | ||
| 158 | endfunction | ||
| 159 | |||
| 160 | "FUNCTION: s:NERDTree.isTabTree() {{{1 | ||
| 161 | function! s:NERDTree.isTabTree() | ||
| 162 | return self._type ==# 'tab' | ||
| 163 | endfunction | ||
| 164 | |||
| 165 | "FUNCTION: s:NERDTree.isWinTree() {{{1 | ||
| 166 | function! s:NERDTree.isWinTree() | ||
| 167 | return self._type ==# 'window' | ||
| 168 | endfunction | ||
| 169 | |||
| 170 | "FUNCTION: s:NERDTree.MustBeOpen() {{{1 | ||
| 171 | function! s:NERDTree.MustBeOpen() | ||
| 172 | if !s:NERDTree.IsOpen() | ||
| 173 | throw 'NERDTree.TreeNotOpen' | ||
| 174 | endif | ||
| 175 | endfunction | ||
| 176 | |||
| 177 | "FUNCTION: s:NERDTree.New() {{{1 | ||
| 178 | function! s:NERDTree.New(path, type) | ||
| 179 | let newObj = copy(self) | ||
| 180 | let newObj.ui = g:NERDTreeUI.New(newObj) | ||
| 181 | let newObj.root = g:NERDTreeDirNode.New(a:path, newObj) | ||
| 182 | let newObj._type = a:type | ||
| 183 | return newObj | ||
| 184 | endfunction | ||
| 185 | |||
| 186 | "FUNCTION: s:NERDTree.PathFilters() {{{1 | ||
| 187 | function! s:NERDTree.PathFilters() | ||
| 188 | if !exists('s:NERDTree._PathFilters') | ||
| 189 | let s:NERDTree._PathFilters = [] | ||
| 190 | endif | ||
| 191 | return s:NERDTree._PathFilters | ||
| 192 | endfunction | ||
| 193 | |||
| 194 | "FUNCTION: s:NERDTree.previousBuf() {{{1 | ||
| 195 | function! s:NERDTree.previousBuf() | ||
| 196 | return self._previousBuf | ||
| 197 | endfunction | ||
| 198 | |||
| 199 | function! s:NERDTree.setPreviousBuf(bnum) | ||
| 200 | let self._previousBuf = a:bnum | ||
| 201 | endfunction | ||
| 202 | |||
| 203 | "FUNCTION: s:NERDTree.render() {{{1 | ||
| 204 | "A convenience function - since this is called often | ||
| 205 | function! s:NERDTree.render() | ||
| 206 | call self.ui.render() | ||
| 207 | endfunction | ||
| 208 | |||
| 209 | " vim: set sw=4 sts=4 et fdm=marker: | ||
diff --git a/.vim/pack/vendor/start/nerdtree/lib/nerdtree/notifier.vim b/.vim/pack/vendor/start/nerdtree/lib/nerdtree/notifier.vim new file mode 100644 index 0000000..ffa2853 --- /dev/null +++ b/.vim/pack/vendor/start/nerdtree/lib/nerdtree/notifier.vim  | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | "CLASS: Notifier | ||
| 2 | "============================================================ | ||
| 3 | let s:Notifier = {} | ||
| 4 | |||
| 5 | function! s:Notifier.AddListener(event, funcname) | ||
| 6 | let listeners = s:Notifier.GetListenersForEvent(a:event) | ||
| 7 | if listeners == [] | ||
| 8 | let listenersMap = s:Notifier.GetListenersMap() | ||
| 9 | let listenersMap[a:event] = listeners | ||
| 10 | endif | ||
| 11 | call add(listeners, a:funcname) | ||
| 12 | endfunction | ||
| 13 | |||
| 14 | function! s:Notifier.NotifyListeners(event, path, nerdtree, params) | ||
| 15 | let event = g:NERDTreeEvent.New(a:nerdtree, a:path, a:event, a:params) | ||
| 16 | |||
| 17 | for Listener in s:Notifier.GetListenersForEvent(a:event) | ||
| 18 | let l:Callback = type(Listener) == type(function('tr')) ? Listener : function(Listener) | ||
| 19 | call l:Callback(event) | ||
| 20 | endfor | ||
| 21 | endfunction | ||
| 22 | |||
| 23 | function! s:Notifier.GetListenersMap() | ||
| 24 | if !exists('s:refreshListenersMap') | ||
| 25 | let s:refreshListenersMap = {} | ||
| 26 | endif | ||
| 27 | return s:refreshListenersMap | ||
| 28 | endfunction | ||
| 29 | |||
| 30 | function! s:Notifier.GetListenersForEvent(name) | ||
| 31 | let listenersMap = s:Notifier.GetListenersMap() | ||
| 32 | return get(listenersMap, a:name, []) | ||
| 33 | endfunction | ||
| 34 | |||
| 35 | let g:NERDTreePathNotifier = deepcopy(s:Notifier) | ||
diff --git a/.vim/pack/vendor/start/nerdtree/lib/nerdtree/opener.vim b/.vim/pack/vendor/start/nerdtree/lib/nerdtree/opener.vim new file mode 100644 index 0000000..27993ac --- /dev/null +++ b/.vim/pack/vendor/start/nerdtree/lib/nerdtree/opener.vim  | |||
| @@ -0,0 +1,326 @@ | |||
| 1 | " ============================================================================ | ||
| 2 | " CLASS: Opener | ||
| 3 | " | ||
| 4 | " The Opener class defines an API for 'opening' operations. | ||
| 5 | " ============================================================================ | ||
| 6 | |||
| 7 | |||
| 8 | let s:Opener = {} | ||
| 9 | let g:NERDTreeOpener = s:Opener | ||
| 10 | |||
| 11 | " FUNCTION: s:Opener._bufInWindows(bnum) {{{1 | ||
| 12 | " [[STOLEN FROM VTREEEXPLORER.VIM]] | ||
| 13 | " Determine the number of windows open to this buffer number. | ||
| 14 | " Care of Yegappan Lakshman. Thanks! | ||
| 15 | " | ||
| 16 | " Args: | ||
| 17 | " bnum: the subject buffers buffer number | ||
| 18 | function! s:Opener._bufInWindows(bnum) | ||
| 19 | let cnt = 0 | ||
| 20 | let winnum = 1 | ||
| 21 | while 1 | ||
| 22 | let bufnum = winbufnr(winnum) | ||
| 23 | if bufnum < 0 | ||
| 24 | break | ||
| 25 | endif | ||
| 26 | if bufnum ==# a:bnum | ||
| 27 | let cnt = cnt + 1 | ||
| 28 | endif | ||
| 29 | let winnum = winnum + 1 | ||
| 30 | endwhile | ||
| 31 | |||
| 32 | return cnt | ||
| 33 | endfunction | ||
| 34 | |||
| 35 | " FUNCTION: Opener._checkToCloseTree(newtab) {{{1 | ||
| 36 | " Check the class options to see if the tree should be closed now. | ||
| 37 | " | ||
| 38 | " Args: | ||
| 39 | " a:newtab - boolean. If set, only close the tree now if we are opening the | ||
| 40 | " target in a new tab. This is needed because we have to close tree before we | ||
| 41 | " leave the tab | ||
| 42 | function! s:Opener._checkToCloseTree(newtab) | ||
| 43 | if self._keepopen | ||
| 44 | return | ||
| 45 | endif | ||
| 46 | |||
| 47 | if (a:newtab && self._where ==# 't') || !a:newtab | ||
| 48 | call g:NERDTree.Close() | ||
| 49 | endif | ||
| 50 | endfunction | ||
| 51 | |||
| 52 | " FUNCTION: s:Opener._firstUsableWindow() {{{1 | ||
| 53 | " find the window number of the first normal window | ||
| 54 | function! s:Opener._firstUsableWindow() | ||
| 55 | let i = 1 | ||
| 56 | while i <= winnr('$') | ||
| 57 | let bnum = winbufnr(i) | ||
| 58 | if bnum !=# -1 && getbufvar(bnum, '&buftype') ==# '' | ||
| 59 | \ && !getwinvar(i, '&previewwindow') | ||
| 60 | \ && (!getbufvar(bnum, '&modified') || &hidden) | ||
| 61 | return i | ||
| 62 | endif | ||
| 63 | |||
| 64 | let i += 1 | ||
| 65 | endwhile | ||
| 66 | return -1 | ||
| 67 | endfunction | ||
| 68 | |||
| 69 | " FUNCTION: Opener._gotoTargetWin() {{{1 | ||
| 70 | function! s:Opener._gotoTargetWin() | ||
| 71 | if b:NERDTree.isWinTree() | ||
| 72 | if self._where ==# 'v' | ||
| 73 | call self._newVSplit() | ||
| 74 | elseif self._where ==# 'h' | ||
| 75 | call self._newSplit() | ||
| 76 | elseif self._where ==# 't' | ||
| 77 | tabnew | ||
| 78 | endif | ||
| 79 | else | ||
| 80 | call self._checkToCloseTree(1) | ||
| 81 | |||
| 82 | if self._where ==# 'v' | ||
| 83 | call self._newVSplit() | ||
| 84 | elseif self._where ==# 'h' | ||
| 85 | call self._newSplit() | ||
| 86 | elseif self._where ==# 't' | ||
| 87 | tabnew | ||
| 88 | elseif self._where ==# 'p' | ||
| 89 | call self._previousWindow() | ||
| 90 | endif | ||
| 91 | |||
| 92 | call self._checkToCloseTree(0) | ||
| 93 | endif | ||
| 94 | endfunction | ||
| 95 | |||
| 96 | " FUNCTION: s:Opener._isWindowUsable(winnumber) {{{1 | ||
| 97 | " Returns 0 if opening a file from the tree in the given window requires it to | ||
| 98 | " be split, 1 otherwise | ||
| 99 | " | ||
| 100 | " Args: | ||
| 101 | " winnumber: the number of the window in question | ||
| 102 | function! s:Opener._isWindowUsable(winnumber) | ||
| 103 | "gotta split if theres only one window (i.e. the NERD tree) | ||
| 104 | if winnr('$') ==# 1 | ||
| 105 | return 0 | ||
| 106 | endif | ||
| 107 | |||
| 108 | let oldwinnr = winnr() | ||
| 109 | call nerdtree#exec(a:winnumber . 'wincmd p', 1) | ||
| 110 | let specialWindow = getbufvar('%', '&buftype') !=# '' || getwinvar('%', '&previewwindow') | ||
| 111 | let modified = &modified | ||
| 112 | call nerdtree#exec(oldwinnr . 'wincmd p', 1) | ||
| 113 | |||
| 114 | "if its a special window e.g. quickfix or another explorer plugin then we | ||
| 115 | "have to split | ||
| 116 | if specialWindow | ||
| 117 | return 0 | ||
| 118 | endif | ||
| 119 | |||
| 120 | if &hidden | ||
| 121 | return 1 | ||
| 122 | endif | ||
| 123 | |||
| 124 | return !modified || self._bufInWindows(winbufnr(a:winnumber)) >= 2 | ||
| 125 | endfunction | ||
| 126 | |||
| 127 | " FUNCTION: Opener.New(path, opts) {{{1 | ||
| 128 | " Instantiate a new NERDTreeOpener object. | ||
| 129 | " Args: | ||
| 130 | " a:path: the path object that is to be opened | ||
| 131 | " a:opts: a dictionary containing the following optional keys... | ||
| 132 | " 'where': specifies whether the node should be opened in new split, in | ||
| 133 | " a new tab or, in the last window; takes values 'v', 'h', or 't' | ||
| 134 | " 'reuse': if file is already shown in a window, jump there; takes values | ||
| 135 | " 'all', 'currenttab', or empty | ||
| 136 | " 'keepopen': boolean (0 or 1); if true, the tree window will not be closed | ||
| 137 | " 'stay': boolean (0 or 1); if true, remain in tree window after opening | ||
| 138 | function! s:Opener.New(path, opts) | ||
| 139 | let l:newOpener = copy(self) | ||
| 140 | |||
| 141 | let l:newOpener._keepopen = nerdtree#has_opt(a:opts, 'keepopen') | ||
| 142 | let l:newOpener._nerdtree = b:NERDTree | ||
| 143 | let l:newOpener._path = a:path | ||
| 144 | let l:newOpener._reuse = has_key(a:opts, 'reuse') ? a:opts['reuse'] : '' | ||
| 145 | let l:newOpener._stay = nerdtree#has_opt(a:opts, 'stay') | ||
| 146 | let l:newOpener._where = has_key(a:opts, 'where') ? a:opts['where'] : '' | ||
| 147 | |||
| 148 | call l:newOpener._saveCursorPos() | ||
| 149 | |||
| 150 | return l:newOpener | ||
| 151 | endfunction | ||
| 152 | |||
| 153 | " FUNCTION: Opener._newSplit() {{{1 | ||
| 154 | function! s:Opener._newSplit() | ||
| 155 | let onlyOneWin = (winnr('$') ==# 1) | ||
| 156 | let savesplitright = &splitright | ||
| 157 | if onlyOneWin | ||
| 158 | let &splitright = (g:NERDTreeWinPos ==# 'left') | ||
| 159 | endif | ||
| 160 | " If only one window (ie. NERDTree), split vertically instead. | ||
| 161 | let splitMode = onlyOneWin ? 'vertical' : '' | ||
| 162 | |||
| 163 | " Open the new window | ||
| 164 | try | ||
| 165 | call nerdtree#exec('wincmd p', 1) | ||
| 166 | call nerdtree#exec(splitMode . ' split',1) | ||
| 167 | catch /^Vim\%((\a\+)\)\=:E37/ | ||
| 168 | call g:NERDTree.CursorToTreeWin() | ||
| 169 | throw 'NERDTree.FileAlreadyOpenAndModifiedError: '. self._path.str() .' is already open and modified.' | ||
| 170 | catch /^Vim\%((\a\+)\)\=:/ | ||
| 171 | "do nothing | ||
| 172 | endtry | ||
| 173 | |||
| 174 | "resize the tree window if no other window was open before | ||
| 175 | if onlyOneWin | ||
| 176 | call nerdtree#exec('wincmd p', 1) | ||
| 177 | call nerdtree#exec('silent '. splitMode .' resize '. g:NERDTreeWinSize, 1) | ||
| 178 | call nerdtree#exec('wincmd p', 0) | ||
| 179 | endif | ||
| 180 | |||
| 181 | let &splitright=savesplitright | ||
| 182 | endfunction | ||
| 183 | |||
| 184 | " FUNCTION: Opener._newVSplit() {{{1 | ||
| 185 | function! s:Opener._newVSplit() | ||
| 186 | let l:winwidth = winwidth('.') | ||
| 187 | |||
| 188 | let onlyOneWin = (winnr('$') ==# 1) | ||
| 189 | let savesplitright = &splitright | ||
| 190 | if onlyOneWin | ||
| 191 | let &splitright = (g:NERDTreeWinPos ==# 'left') | ||
| 192 | let l:winwidth = g:NERDTreeWinSize | ||
| 193 | endif | ||
| 194 | |||
| 195 | call nerdtree#exec('wincmd p', 1) | ||
| 196 | call nerdtree#exec('vsplit', 1) | ||
| 197 | |||
| 198 | let l:currentWindowNumber = winnr() | ||
| 199 | |||
| 200 | " Restore the NERDTree to its original width. | ||
| 201 | call g:NERDTree.CursorToTreeWin() | ||
| 202 | execute 'silent vertical resize ' . l:winwidth | ||
| 203 | |||
| 204 | call nerdtree#exec(l:currentWindowNumber . 'wincmd w', 0) | ||
| 205 | let &splitright=savesplitright | ||
| 206 | endfunction | ||
| 207 | |||
| 208 | " FUNCTION: Opener.open(target) {{{1 | ||
| 209 | function! s:Opener.open(target) | ||
| 210 | if self._path.isDirectory | ||
| 211 | call self._openDirectory(a:target) | ||
| 212 | return | ||
| 213 | endif | ||
| 214 | |||
| 215 | call self._openFile() | ||
| 216 | endfunction | ||
| 217 | |||
| 218 | " FUNCTION: Opener._openFile() {{{1 | ||
| 219 | function! s:Opener._openFile() | ||
| 220 | if !self._stay && self._keepopen && get(b:, 'NERDTreeZoomed', 0) | ||
| 221 | call b:NERDTree.ui.toggleZoom() | ||
| 222 | endif | ||
| 223 | |||
| 224 | if self._reuseWindow() | ||
| 225 | return | ||
| 226 | endif | ||
| 227 | |||
| 228 | call self._gotoTargetWin() | ||
| 229 | |||
| 230 | if self._stay | ||
| 231 | silent call self._path.edit() | ||
| 232 | call self._restoreCursorPos() | ||
| 233 | return | ||
| 234 | endif | ||
| 235 | |||
| 236 | call self._path.edit() | ||
| 237 | endfunction | ||
| 238 | |||
| 239 | " FUNCTION: Opener._openDirectory(node) {{{1 | ||
| 240 | function! s:Opener._openDirectory(node) | ||
| 241 | call self._gotoTargetWin() | ||
| 242 | |||
| 243 | if self._nerdtree.isWinTree() | ||
| 244 | call g:NERDTreeCreator.CreateWindowTree(a:node.path.str()) | ||
| 245 | else | ||
| 246 | if empty(self._where) | ||
| 247 | call b:NERDTree.changeRoot(a:node) | ||
| 248 | elseif self._where ==# 't' | ||
| 249 | call g:NERDTreeCreator.CreateTabTree(a:node.path.str()) | ||
| 250 | else | ||
| 251 | call g:NERDTreeCreator.CreateWindowTree(a:node.path.str()) | ||
| 252 | endif | ||
| 253 | endif | ||
| 254 | |||
| 255 | if self._stay | ||
| 256 | call self._restoreCursorPos() | ||
| 257 | endif | ||
| 258 | endfunction | ||
| 259 | |||
| 260 | " FUNCTION: Opener._previousWindow() {{{1 | ||
| 261 | function! s:Opener._previousWindow() | ||
| 262 | if !self._isWindowUsable(winnr('#')) && self._firstUsableWindow() ==# -1 | ||
| 263 | call self._newSplit() | ||
| 264 | else | ||
| 265 | try | ||
| 266 | if !self._isWindowUsable(winnr('#')) | ||
| 267 | call nerdtree#exec(self._firstUsableWindow() . 'wincmd w', 1) | ||
| 268 | else | ||
| 269 | call nerdtree#exec('wincmd p', 1) | ||
| 270 | endif | ||
| 271 | catch /^Vim\%((\a\+)\)\=:E37/ | ||
| 272 | call g:NERDTree.CursorToTreeWin() | ||
| 273 | throw 'NERDTree.FileAlreadyOpenAndModifiedError: '. self._path.str() .' is already open and modified.' | ||
| 274 | catch /^Vim\%((\a\+)\)\=:/ | ||
| 275 | echo v:exception | ||
| 276 | endtry | ||
| 277 | endif | ||
| 278 | endfunction | ||
| 279 | |||
| 280 | " FUNCTION: Opener._restoreCursorPos() {{{1 | ||
| 281 | function! s:Opener._restoreCursorPos() | ||
| 282 | call nerdtree#exec(self._tabnr . 'tabnext', 1) | ||
| 283 | call nerdtree#exec(bufwinnr(self._bufnr) . 'wincmd w', 1) | ||
| 284 | endfunction | ||
| 285 | |||
| 286 | " FUNCTION: Opener._reuseWindow() {{{1 | ||
| 287 | " put the cursor in the first window we find for this file | ||
| 288 | " | ||
| 289 | " return 1 if we were successful | ||
| 290 | function! s:Opener._reuseWindow() | ||
| 291 | if empty(self._reuse) | ||
| 292 | return 0 | ||
| 293 | endif | ||
| 294 | |||
| 295 | "check the current tab for the window | ||
| 296 | let winnr = bufwinnr('^' . self._path.str() . '$') | ||
| 297 | if winnr !=# -1 | ||
| 298 | call nerdtree#exec(winnr . 'wincmd w', 0) | ||
| 299 | call self._checkToCloseTree(0) | ||
| 300 | return 1 | ||
| 301 | endif | ||
| 302 | |||
| 303 | if self._reuse ==# 'currenttab' | ||
| 304 | return 0 | ||
| 305 | endif | ||
| 306 | |||
| 307 | "check other tabs | ||
| 308 | let tabnr = self._path.tabnr() | ||
| 309 | if tabnr | ||
| 310 | call self._checkToCloseTree(1) | ||
| 311 | call nerdtree#exec(tabnr . 'tabnext', 1) | ||
| 312 | let winnr = bufwinnr('^' . self._path.str() . '$') | ||
| 313 | call nerdtree#exec(winnr . 'wincmd w', 0) | ||
| 314 | return 1 | ||
| 315 | endif | ||
| 316 | |||
| 317 | return 0 | ||
| 318 | endfunction | ||
| 319 | |||
| 320 | " FUNCTION: Opener._saveCursorPos() {{{1 | ||
| 321 | function! s:Opener._saveCursorPos() | ||
| 322 | let self._bufnr = bufnr('') | ||
| 323 | let self._tabnr = tabpagenr() | ||
| 324 | endfunction | ||
| 325 | |||
| 326 | " vim: set sw=4 sts=4 et fdm=marker: | ||
diff --git a/.vim/pack/vendor/start/nerdtree/lib/nerdtree/path.vim b/.vim/pack/vendor/start/nerdtree/lib/nerdtree/path.vim new file mode 100644 index 0000000..997abf3 --- /dev/null +++ b/.vim/pack/vendor/start/nerdtree/lib/nerdtree/path.vim  | |||
| @@ -0,0 +1,852 @@ | |||
| 1 | " ============================================================================ | ||
| 2 | " CLASS: Path | ||
| 3 | " | ||
| 4 | " The Path class provides an abstracted representation of a file system | ||
| 5 | " pathname. Various operations on pathnames are provided and a number of | ||
| 6 | " representations of a given path name can be accessed here. | ||
| 7 | " ============================================================================ | ||
| 8 | |||
| 9 | |||
| 10 | let s:Path = {} | ||
| 11 | let g:NERDTreePath = s:Path | ||
| 12 | |||
| 13 | " FUNCTION: Path.AbsolutePathFor(pathStr) {{{1 | ||
| 14 | function! s:Path.AbsolutePathFor(pathStr) | ||
| 15 | let l:prependWorkingDir = 0 | ||
| 16 | |||
| 17 | if nerdtree#runningWindows() | ||
| 18 | let l:prependWorkingDir = a:pathStr !~# '^.:\(\\\|\/\)\?' && a:pathStr !~# '^\(\\\\\|\/\/\)' | ||
| 19 | else | ||
| 20 | let l:prependWorkingDir = a:pathStr !~# '^/' | ||
| 21 | endif | ||
| 22 | |||
| 23 | let l:result = a:pathStr | ||
| 24 | |||
| 25 | if l:prependWorkingDir | ||
| 26 | let l:result = getcwd() | ||
| 27 | |||
| 28 | if l:result[-1:] == nerdtree#slash() | ||
| 29 | let l:result = l:result . a:pathStr | ||
| 30 | else | ||
| 31 | let l:result = l:result . nerdtree#slash() . a:pathStr | ||
| 32 | endif | ||
| 33 | endif | ||
| 34 | |||
| 35 | return l:result | ||
| 36 | endfunction | ||
| 37 | |||
| 38 | " FUNCTION: Path.bookmarkNames() {{{1 | ||
| 39 | function! s:Path.bookmarkNames() | ||
| 40 | if !exists('self._bookmarkNames') | ||
| 41 | call self.cacheDisplayString() | ||
| 42 | endif | ||
| 43 | return self._bookmarkNames | ||
| 44 | endfunction | ||
| 45 | |||
| 46 | " FUNCTION: Path.cacheDisplayString() {{{1 | ||
| 47 | function! s:Path.cacheDisplayString() abort | ||
| 48 | let self.cachedDisplayString = g:NERDTreeNodeDelimiter . self.getLastPathComponent(1) | ||
| 49 | |||
| 50 | if self.isExecutable | ||
| 51 | let self.cachedDisplayString = self.addDelimiter(self.cachedDisplayString) . '*' | ||
| 52 | endif | ||
| 53 | |||
| 54 | let self._bookmarkNames = [] | ||
| 55 | for i in g:NERDTreeBookmark.Bookmarks() | ||
| 56 | if i.path.equals(self) | ||
| 57 | call add(self._bookmarkNames, i.name) | ||
| 58 | endif | ||
| 59 | endfor | ||
| 60 | if !empty(self._bookmarkNames) && g:NERDTreeMarkBookmarks ==# 1 | ||
| 61 | let self.cachedDisplayString = self.addDelimiter(self.cachedDisplayString) . ' {' . join(self._bookmarkNames) . '}' | ||
| 62 | endif | ||
| 63 | |||
| 64 | if self.isSymLink | ||
| 65 | let self.cachedDisplayString = self.addDelimiter(self.cachedDisplayString) . ' -> ' . self.symLinkDest | ||
| 66 | endif | ||
| 67 | |||
| 68 | if self.isReadOnly | ||
| 69 | let self.cachedDisplayString = self.addDelimiter(self.cachedDisplayString) . ' ['.g:NERDTreeGlyphReadOnly.']' | ||
| 70 | endif | ||
| 71 | endfunction | ||
| 72 | |||
| 73 | " FUNCTION: Path.addDelimiter() {{{1 | ||
| 74 | function! s:Path.addDelimiter(line) | ||
| 75 | if a:line =~# '\(.*' . g:NERDTreeNodeDelimiter . '\)\{2}' | ||
| 76 | return a:line | ||
| 77 | else | ||
| 78 | return a:line . g:NERDTreeNodeDelimiter | ||
| 79 | endif | ||
| 80 | endfunction | ||
| 81 | |||
| 82 | " FUNCTION: Path.changeToDir() {{{1 | ||
| 83 | function! s:Path.changeToDir() | ||
| 84 | let dir = self.str({'format': 'Cd'}) | ||
| 85 | if self.isDirectory ==# 0 | ||
| 86 | let dir = self.getParent().str({'format': 'Cd'}) | ||
| 87 | endif | ||
| 88 | |||
| 89 | try | ||
| 90 | if g:NERDTreeUseTCD && exists(':tcd') ==# 2 | ||
| 91 | execute 'tcd ' . dir | ||
| 92 | call nerdtree#echo("Tab's CWD is now: " . getcwd()) | ||
| 93 | else | ||
| 94 | execute 'cd ' . dir | ||
| 95 | call nerdtree#echo('CWD is now: ' . getcwd()) | ||
| 96 | endif | ||
| 97 | catch | ||
| 98 | throw 'NERDTree.PathChangeError: cannot change CWD to ' . dir | ||
| 99 | endtry | ||
| 100 | endfunction | ||
| 101 | |||
| 102 | " FUNCTION: Path.Create(fullpath) {{{1 | ||
| 103 | " | ||
| 104 | " Factory method. | ||
| 105 | " | ||
| 106 | " Creates a path object with the given path. The path is also created on the | ||
| 107 | " filesystem. If the path already exists, a NERDTree.Path.Exists exception is | ||
| 108 | " thrown. If any other errors occur, a NERDTree.Path exception is thrown. | ||
| 109 | " | ||
| 110 | " Args: | ||
| 111 | " fullpath: the full filesystem path to the file/dir to create | ||
| 112 | function! s:Path.Create(fullpath) | ||
| 113 | "bail if the a:fullpath already exists | ||
| 114 | if isdirectory(a:fullpath) || filereadable(a:fullpath) | ||
| 115 | throw "NERDTree.CreatePathError: Directory Exists: '" . a:fullpath . "'" | ||
| 116 | endif | ||
| 117 | |||
| 118 | try | ||
| 119 | |||
| 120 | "if it ends with a slash, assume its a dir create it | ||
| 121 | if a:fullpath =~# '\(\\\|\/\)$' | ||
| 122 | "whack the trailing slash off the end if it exists | ||
| 123 | let fullpath = substitute(a:fullpath, '\(\\\|\/\)$', '', '') | ||
| 124 | |||
| 125 | call mkdir(fullpath, 'p') | ||
| 126 | |||
| 127 | "assume its a file and create | ||
| 128 | else | ||
| 129 | call s:Path.createParentDirectories(a:fullpath) | ||
| 130 | call writefile([], a:fullpath) | ||
| 131 | endif | ||
| 132 | catch | ||
| 133 | throw "NERDTree.CreatePathError: Could not create path: '" . a:fullpath . "'" | ||
| 134 | endtry | ||
| 135 | |||
| 136 | return s:Path.New(a:fullpath) | ||
| 137 | endfunction | ||
| 138 | |||
| 139 | " FUNCTION: Path.copy(dest) {{{1 | ||
| 140 | " | ||
| 141 | " Copies the file/dir represented by this Path to the given location | ||
| 142 | " | ||
| 143 | " Args: | ||
| 144 | " dest: the location to copy this dir/file to | ||
| 145 | function! s:Path.copy(dest) | ||
| 146 | if !s:Path.CopyingSupported() | ||
| 147 | throw 'NERDTree.CopyingNotSupportedError: Copying is not supported on this OS' | ||
| 148 | endif | ||
| 149 | |||
| 150 | call s:Path.createParentDirectories(a:dest) | ||
| 151 | |||
| 152 | if exists('g:NERDTreeCopyCmd') | ||
| 153 | let cmd_prefix = g:NERDTreeCopyCmd | ||
| 154 | else | ||
| 155 | let cmd_prefix = (self.isDirectory ? g:NERDTreeCopyDirCmd : g:NERDTreeCopyFileCmd) | ||
| 156 | endif | ||
| 157 | |||
| 158 | let cmd = cmd_prefix . ' ' . shellescape(self.str()) . ' ' . shellescape(a:dest) | ||
| 159 | let success = system(cmd) | ||
| 160 | if v:shell_error !=# 0 | ||
| 161 | throw "NERDTree.CopyError: Could not copy '". self.str() ."' to: '" . a:dest . "'" | ||
| 162 | endif | ||
| 163 | endfunction | ||
| 164 | |||
| 165 | " FUNCTION: Path.CopyingSupported() {{{1 | ||
| 166 | " | ||
| 167 | " returns 1 if copying is supported for this OS | ||
| 168 | function! s:Path.CopyingSupported() | ||
| 169 | return exists('g:NERDTreeCopyCmd') || (exists('g:NERDTreeCopyDirCmd') && exists('g:NERDTreeCopyFileCmd')) | ||
| 170 | endfunction | ||
| 171 | |||
| 172 | " FUNCTION: Path.copyingWillOverwrite(dest) {{{1 | ||
| 173 | " | ||
| 174 | " returns 1 if copy this path to the given location will cause files to | ||
| 175 | " overwritten | ||
| 176 | " | ||
| 177 | " Args: | ||
| 178 | " dest: the location this path will be copied to | ||
| 179 | function! s:Path.copyingWillOverwrite(dest) | ||
| 180 | if filereadable(a:dest) | ||
| 181 | return 1 | ||
| 182 | endif | ||
| 183 | |||
| 184 | if isdirectory(a:dest) | ||
| 185 | let path = s:Path.JoinPathStrings(a:dest, self.getLastPathComponent(0)) | ||
| 186 | if filereadable(path) | ||
| 187 | return 1 | ||
| 188 | endif | ||
| 189 | endif | ||
| 190 | endfunction | ||
| 191 | |||
| 192 | " FUNCTION: Path.createParentDirectories(path) {{{1 | ||
| 193 | " | ||
| 194 | " create parent directories for this path if needed | ||
| 195 | " without throwing any errors if those directories already exist | ||
| 196 | " | ||
| 197 | " Args: | ||
| 198 | " path: full path of the node whose parent directories may need to be created | ||
| 199 | function! s:Path.createParentDirectories(path) | ||
| 200 | let dir_path = fnamemodify(a:path, ':h') | ||
| 201 | if !isdirectory(dir_path) | ||
| 202 | call mkdir(dir_path, 'p') | ||
| 203 | endif | ||
| 204 | endfunction | ||
| 205 | |||
| 206 | " FUNCTION: Path.delete() {{{1 | ||
| 207 | " | ||
| 208 | " Deletes the file or directory represented by this path. | ||
| 209 | " | ||
| 210 | " Throws NERDTree.Path.Deletion exceptions | ||
| 211 | function! s:Path.delete() | ||
| 212 | if self.isDirectory | ||
| 213 | |||
| 214 | let cmd = g:NERDTreeRemoveDirCmd . self.str({'escape': 1}) | ||
| 215 | let success = system(cmd) | ||
| 216 | |||
| 217 | if v:shell_error !=# 0 | ||
| 218 | throw "NERDTree.PathDeletionError: Could not delete directory: '" . self.str() . "'" | ||
| 219 | endif | ||
| 220 | else | ||
| 221 | if exists('g:NERDTreeRemoveFileCmd') | ||
| 222 | let cmd = g:NERDTreeRemoveFileCmd . self.str({'escape': 1}) | ||
| 223 | let success = system(cmd) | ||
| 224 | else | ||
| 225 | let success = delete(self.str()) | ||
| 226 | endif | ||
| 227 | |||
| 228 | if success !=# 0 | ||
| 229 | throw "NERDTree.PathDeletionError: Could not delete file: '" . self.str() . "'" | ||
| 230 | endif | ||
| 231 | endif | ||
| 232 | |||
| 233 | "delete all bookmarks for this path | ||
| 234 | for i in self.bookmarkNames() | ||
| 235 | let bookmark = g:NERDTreeBookmark.BookmarkFor(i) | ||
| 236 | call bookmark.delete() | ||
| 237 | endfor | ||
| 238 | endfunction | ||
| 239 | |||
| 240 | " FUNCTION: Path.displayString() {{{1 | ||
| 241 | " | ||
| 242 | " Returns a string that specifies how the path should be represented as a | ||
| 243 | " string | ||
| 244 | function! s:Path.displayString() | ||
| 245 | if self.cachedDisplayString ==# '' | ||
| 246 | call self.cacheDisplayString() | ||
| 247 | endif | ||
| 248 | |||
| 249 | return self.cachedDisplayString | ||
| 250 | endfunction | ||
| 251 | |||
| 252 | " FUNCTION: Path.edit() {{{1 | ||
| 253 | function! s:Path.edit() | ||
| 254 | let l:bufname = self.str({'format': 'Edit'}) | ||
| 255 | if bufname('%') !=# l:bufname | ||
| 256 | exec 'edit ' . l:bufname | ||
| 257 | endif | ||
| 258 | endfunction | ||
| 259 | |||
| 260 | " FUNCTION: Path.extractDriveLetter(fullpath) {{{1 | ||
| 261 | " | ||
| 262 | " If running windows, cache the drive letter for this path | ||
| 263 | function! s:Path.extractDriveLetter(fullpath) | ||
| 264 | if nerdtree#runningWindows() | ||
| 265 | if a:fullpath =~# '^\(\\\\\|\/\/\)' | ||
| 266 | "For network shares, the 'drive' consists of the first two parts of the path, i.e. \\boxname\share | ||
| 267 | let self.drive = substitute(a:fullpath, '^\(\(\\\\\|\/\/\)[^\\\/]*\(\\\|\/\)[^\\\/]*\).*', '\1', '') | ||
| 268 | let self.drive = substitute(self.drive, '/', '\', 'g') | ||
| 269 | else | ||
| 270 | let self.drive = substitute(a:fullpath, '\(^[a-zA-Z]:\).*', '\1', '') | ||
| 271 | endif | ||
| 272 | else | ||
| 273 | let self.drive = '' | ||
| 274 | endif | ||
| 275 | |||
| 276 | endfunction | ||
| 277 | |||
| 278 | " FUNCTION: Path.exists() {{{1 | ||
| 279 | " return 1 if this path points to a location that is readable or is a directory | ||
| 280 | function! s:Path.exists() | ||
| 281 | let p = self.str() | ||
| 282 | return filereadable(p) || isdirectory(p) | ||
| 283 | endfunction | ||
| 284 | |||
| 285 | " FUNCTION: Path._escChars() {{{1 | ||
| 286 | function! s:Path._escChars() | ||
| 287 | if nerdtree#runningWindows() | ||
| 288 | return " `\|\"#%&,?()\*^<>$" | ||
| 289 | endif | ||
| 290 | |||
| 291 | return " \\`\|\"#%&,?()\*^<>[]{}$" | ||
| 292 | endfunction | ||
| 293 | |||
| 294 | " FUNCTION: Path.getDir() {{{1 | ||
| 295 | " | ||
| 296 | " Returns this path if it is a directory, else this paths parent. | ||
| 297 | " | ||
| 298 | " Return: | ||
| 299 | " a Path object | ||
| 300 | function! s:Path.getDir() | ||
| 301 | if self.isDirectory | ||
| 302 | return self | ||
| 303 | else | ||
| 304 | return self.getParent() | ||
| 305 | endif | ||
| 306 | endfunction | ||
| 307 | |||
| 308 | " FUNCTION: Path.getParent() {{{1 | ||
| 309 | " | ||
| 310 | " Returns a new path object for this paths parent | ||
| 311 | " | ||
| 312 | " Return: | ||
| 313 | " a new Path object | ||
| 314 | function! s:Path.getParent() | ||
| 315 | if nerdtree#runningWindows() | ||
| 316 | let path = self.drive . '\' . join(self.pathSegments[0:-2], '\') | ||
| 317 | else | ||
| 318 | let path = '/'. join(self.pathSegments[0:-2], '/') | ||
| 319 | endif | ||
| 320 | |||
| 321 | return s:Path.New(path) | ||
| 322 | endfunction | ||
| 323 | |||
| 324 | " FUNCTION: Path.getLastPathComponent(dirSlash) {{{1 | ||
| 325 | " | ||
| 326 | " Gets the last part of this path. | ||
| 327 | " | ||
| 328 | " Args: | ||
| 329 | " dirSlash: if 1 then a trailing slash will be added to the returned value for | ||
| 330 | " directory nodes. | ||
| 331 | function! s:Path.getLastPathComponent(dirSlash) | ||
| 332 | if empty(self.pathSegments) | ||
| 333 | return '' | ||
| 334 | endif | ||
| 335 | let toReturn = self.pathSegments[-1] | ||
| 336 | if a:dirSlash && self.isDirectory | ||
| 337 | let toReturn = toReturn . '/' | ||
| 338 | endif | ||
| 339 | return toReturn | ||
| 340 | endfunction | ||
| 341 | |||
| 342 | " FUNCTION: Path.getSortOrderIndex() {{{1 | ||
| 343 | " returns the index of the pattern in g:NERDTreeSortOrder that this path matches | ||
| 344 | function! s:Path.getSortOrderIndex() | ||
| 345 | let i = 0 | ||
| 346 | while i < len(g:NERDTreeSortOrder) | ||
| 347 | if g:NERDTreeSortOrder[i] !~? '\[\[-\?\(timestamp\|size\|extension\)\]\]' && | ||
| 348 | \ self.getLastPathComponent(1) =~# g:NERDTreeSortOrder[i] | ||
| 349 | return i | ||
| 350 | endif | ||
| 351 | let i = i + 1 | ||
| 352 | endwhile | ||
| 353 | |||
| 354 | return index(g:NERDTreeSortOrder, '*') | ||
| 355 | endfunction | ||
| 356 | |||
| 357 | " FUNCTION: Path._splitChunks(path) {{{1 | ||
| 358 | " returns a list of path chunks | ||
| 359 | function! s:Path._splitChunks(path) | ||
| 360 | let chunks = split(a:path, '\(\D\+\|\d\+\)\zs') | ||
| 361 | let i = 0 | ||
| 362 | while i < len(chunks) | ||
| 363 | "convert number literals to numbers | ||
| 364 | if match(chunks[i], '^\d\+$') ==# 0 | ||
| 365 | let chunks[i] = str2nr(chunks[i]) | ||
| 366 | endif | ||
| 367 | let i = i + 1 | ||
| 368 | endwhile | ||
| 369 | return chunks | ||
| 370 | endfunction | ||
| 371 | |||
| 372 | " FUNCTION: Path.getSortKey() {{{1 | ||
| 373 | " returns a key used in compare function for sorting | ||
| 374 | function! s:Path.getSortKey() | ||
| 375 | if !exists('self._sortKey') || g:NERDTreeSortOrder !=# g:NERDTreeOldSortOrder | ||
| 376 | " Look for file metadata tags: [[timestamp]], [[extension]], [[size]] | ||
| 377 | let metadata = [] | ||
| 378 | for tag in g:NERDTreeSortOrder | ||
| 379 | if tag =~? '\[\[-\?timestamp\]\]' | ||
| 380 | let metadata += [self.isDirectory ? 0 : getftime(self.str()) * (tag =~# '-' ? -1 : 1)] | ||
| 381 | elseif tag =~? '\[\[-\?size\]\]' | ||
| 382 | let metadata += [self.isDirectory ? 0 : getfsize(self.str()) * (tag =~# '-' ? -1 : 1)] | ||
| 383 | elseif tag =~? '\[\[extension\]\]' | ||
| 384 | let extension = matchstr(self.getLastPathComponent(0), '[^.]\+\.\zs[^.]\+$') | ||
| 385 | let metadata += [self.isDirectory ? '' : (extension ==# '' ? nr2char(str2nr('0x10ffff',16)) : extension)] | ||
| 386 | endif | ||
| 387 | endfor | ||
| 388 | |||
| 389 | if g:NERDTreeSortOrder[0] =~# '\[\[.*\]\]' | ||
| 390 | " Apply tags' sorting first if specified first. | ||
| 391 | let self._sortKey = metadata + [self.getSortOrderIndex()] | ||
| 392 | else | ||
| 393 | " Otherwise, do regex grouping first. | ||
| 394 | let self._sortKey = [self.getSortOrderIndex()] + metadata | ||
| 395 | endif | ||
| 396 | |||
| 397 | let path = self.getLastPathComponent(0) | ||
| 398 | if !g:NERDTreeSortHiddenFirst | ||
| 399 | let path = substitute(path, '^[._]', '', '') | ||
| 400 | endif | ||
| 401 | if !g:NERDTreeCaseSensitiveSort | ||
| 402 | let path = tolower(path) | ||
| 403 | endif | ||
| 404 | |||
| 405 | call extend(self._sortKey, (g:NERDTreeNaturalSort ? self._splitChunks(path) : [path])) | ||
| 406 | endif | ||
| 407 | return self._sortKey | ||
| 408 | endfunction | ||
| 409 | |||
| 410 | " FUNCTION: Path.isHiddenUnder(path) {{{1 | ||
| 411 | function! s:Path.isHiddenUnder(path) | ||
| 412 | |||
| 413 | if !self.isUnder(a:path) | ||
| 414 | return 0 | ||
| 415 | endif | ||
| 416 | |||
| 417 | let l:startIndex = len(a:path.pathSegments) | ||
| 418 | let l:segments = self.pathSegments[l:startIndex : ] | ||
| 419 | |||
| 420 | for l:segment in l:segments | ||
| 421 | |||
| 422 | if l:segment =~# '^\.' | ||
| 423 | return 1 | ||
| 424 | endif | ||
| 425 | endfor | ||
| 426 | |||
| 427 | return 0 | ||
| 428 | endfunction | ||
| 429 | |||
| 430 | " FUNCTION: Path.isUnixHiddenFile() {{{1 | ||
| 431 | " check for unix hidden files | ||
| 432 | function! s:Path.isUnixHiddenFile() | ||
| 433 | return self.getLastPathComponent(0) =~# '^\.' | ||
| 434 | endfunction | ||
| 435 | |||
| 436 | " FUNCTION: Path.isUnixHiddenPath() {{{1 | ||
| 437 | " check for unix path with hidden components | ||
| 438 | function! s:Path.isUnixHiddenPath() | ||
| 439 | if self.getLastPathComponent(0) =~# '^\.' | ||
| 440 | return 1 | ||
| 441 | else | ||
| 442 | for segment in self.pathSegments | ||
| 443 | if segment =~# '^\.' | ||
| 444 | return 1 | ||
| 445 | endif | ||
| 446 | endfor | ||
| 447 | return 0 | ||
| 448 | endif | ||
| 449 | endfunction | ||
| 450 | |||
| 451 | " FUNCTION: Path.ignore(nerdtree) {{{1 | ||
| 452 | " returns true if this path should be ignored | ||
| 453 | function! s:Path.ignore(nerdtree) | ||
| 454 | "filter out the user specified paths to ignore | ||
| 455 | if a:nerdtree.ui.isIgnoreFilterEnabled() | ||
| 456 | for i in g:NERDTreeIgnore | ||
| 457 | if self._ignorePatternMatches(i) | ||
| 458 | return 1 | ||
| 459 | endif | ||
| 460 | endfor | ||
| 461 | |||
| 462 | for l:Callback in g:NERDTree.PathFilters() | ||
| 463 | let l:Callback = type(l:Callback) ==# type(function('tr')) ? l:Callback : function(l:Callback) | ||
| 464 | if l:Callback({'path': self, 'nerdtree': a:nerdtree}) | ||
| 465 | return 1 | ||
| 466 | endif | ||
| 467 | endfor | ||
| 468 | endif | ||
| 469 | |||
| 470 | "dont show hidden files unless instructed to | ||
| 471 | if !a:nerdtree.ui.getShowHidden() && self.isUnixHiddenFile() | ||
| 472 | return 1 | ||
| 473 | endif | ||
| 474 | |||
| 475 | if a:nerdtree.ui.getShowFiles() ==# 0 && self.isDirectory ==# 0 | ||
| 476 | return 1 | ||
| 477 | endif | ||
| 478 | |||
| 479 | return 0 | ||
| 480 | endfunction | ||
| 481 | |||
| 482 | " FUNCTION: Path._ignorePatternMatches(pattern) {{{1 | ||
| 483 | " returns true if this path matches the given ignore pattern | ||
| 484 | function! s:Path._ignorePatternMatches(pattern) | ||
| 485 | let pat = a:pattern | ||
| 486 | if strpart(pat,len(pat)-8) ==# '[[path]]' | ||
| 487 | let pat = strpart(pat,0, len(pat)-8) | ||
| 488 | return self.str() =~# pat | ||
| 489 | elseif strpart(pat,len(pat)-7) ==# '[[dir]]' | ||
| 490 | if !self.isDirectory | ||
| 491 | return 0 | ||
| 492 | endif | ||
| 493 | let pat = strpart(pat,0, len(pat)-7) | ||
| 494 | elseif strpart(pat,len(pat)-8) ==# '[[file]]' | ||
| 495 | if self.isDirectory | ||
| 496 | return 0 | ||
| 497 | endif | ||
| 498 | let pat = strpart(pat,0, len(pat)-8) | ||
| 499 | endif | ||
| 500 | |||
| 501 | return self.getLastPathComponent(0) =~# pat | ||
| 502 | endfunction | ||
| 503 | |||
| 504 | " FUNCTION: Path.isAncestor(path) {{{1 | ||
| 505 | " return 1 if this path is somewhere above the given path in the filesystem. | ||
| 506 | " | ||
| 507 | " a:path should be a dir | ||
| 508 | function! s:Path.isAncestor(child) | ||
| 509 | return a:child.isUnder(self) | ||
| 510 | endfunction | ||
| 511 | |||
| 512 | " FUNCTION: Path.isUnder(path) {{{1 | ||
| 513 | " return 1 if this path is somewhere under the given path in the filesystem. | ||
| 514 | function! s:Path.isUnder(parent) | ||
| 515 | if a:parent.isDirectory ==# 0 | ||
| 516 | return 0 | ||
| 517 | endif | ||
| 518 | if nerdtree#runningWindows() && a:parent.drive !=# self.drive | ||
| 519 | return 0 | ||
| 520 | endif | ||
| 521 | let l:this_count = len(self.pathSegments) | ||
| 522 | if l:this_count ==# 0 | ||
| 523 | return 0 | ||
| 524 | endif | ||
| 525 | let l:that_count = len(a:parent.pathSegments) | ||
| 526 | if l:that_count ==# 0 | ||
| 527 | return 1 | ||
| 528 | endif | ||
| 529 | if l:that_count >= l:this_count | ||
| 530 | return 0 | ||
| 531 | endif | ||
| 532 | for i in range(0, l:that_count-1) | ||
| 533 | if self.pathSegments[i] !=# a:parent.pathSegments[i] | ||
| 534 | return 0 | ||
| 535 | endif | ||
| 536 | endfor | ||
| 537 | return 1 | ||
| 538 | endfunction | ||
| 539 | |||
| 540 | " FUNCTION: Path.JoinPathStrings(...) {{{1 | ||
| 541 | function! s:Path.JoinPathStrings(...) | ||
| 542 | let components = [] | ||
| 543 | for i in a:000 | ||
| 544 | let components = extend(components, split(i, '/')) | ||
| 545 | endfor | ||
| 546 | return '/' . join(components, '/') | ||
| 547 | endfunction | ||
| 548 | |||
| 549 | " FUNCTION: Path.equals() {{{1 | ||
| 550 | " | ||
| 551 | " Determines whether 2 path objects are "equal". | ||
| 552 | " They are equal if the paths they represent are the same | ||
| 553 | " | ||
| 554 | " Args: | ||
| 555 | " path: the other path obj to compare this with | ||
| 556 | function! s:Path.equals(path) | ||
| 557 | if nerdtree#runningWindows() | ||
| 558 | return self.str() ==? a:path.str() | ||
| 559 | else | ||
| 560 | return self.str() ==# a:path.str() | ||
| 561 | endif | ||
| 562 | endfunction | ||
| 563 | |||
| 564 | " FUNCTION: Path.New(pathStr) {{{1 | ||
| 565 | function! s:Path.New(pathStr) | ||
| 566 | let l:newPath = copy(self) | ||
| 567 | |||
| 568 | call l:newPath.readInfoFromDisk(s:Path.AbsolutePathFor(a:pathStr)) | ||
| 569 | |||
| 570 | let l:newPath.cachedDisplayString = '' | ||
| 571 | let l:newPath.flagSet = g:NERDTreeFlagSet.New() | ||
| 572 | |||
| 573 | return l:newPath | ||
| 574 | endfunction | ||
| 575 | |||
| 576 | " FUNCTION: Path.Resolve() {{{1 | ||
| 577 | " Invoke the vim resolve() function and return the result | ||
| 578 | " This is necessary because in some versions of vim resolve() removes trailing | ||
| 579 | " slashes while in other versions it doesn't. This always removes the trailing | ||
| 580 | " slash | ||
| 581 | function! s:Path.Resolve(path) | ||
| 582 | let tmp = resolve(a:path) | ||
| 583 | return tmp =~# '.\+/$' ? substitute(tmp, '/$', '', '') : tmp | ||
| 584 | endfunction | ||
| 585 | |||
| 586 | " FUNCTION: Path.readInfoFromDisk(fullpath) {{{1 | ||
| 587 | " | ||
| 588 | " | ||
| 589 | " Throws NERDTree.Path.InvalidArguments exception. | ||
| 590 | function! s:Path.readInfoFromDisk(fullpath) | ||
| 591 | call self.extractDriveLetter(a:fullpath) | ||
| 592 | |||
| 593 | let fullpath = s:Path.WinToUnixPath(a:fullpath) | ||
| 594 | |||
| 595 | if getftype(fullpath) ==# 'fifo' | ||
| 596 | throw 'NERDTree.InvalidFiletypeError: Cant handle FIFO files: ' . a:fullpath | ||
| 597 | endif | ||
| 598 | |||
| 599 | let self.pathSegments = filter(split(fullpath, '/'), '!empty(v:val)') | ||
| 600 | |||
| 601 | let self.isReadOnly = 0 | ||
| 602 | if isdirectory(a:fullpath) | ||
| 603 | let self.isDirectory = 1 | ||
| 604 | elseif filereadable(a:fullpath) | ||
| 605 | let self.isDirectory = 0 | ||
| 606 | let self.isReadOnly = filewritable(a:fullpath) ==# 0 | ||
| 607 | else | ||
| 608 | throw 'NERDTree.InvalidArgumentsError: Invalid path = ' . a:fullpath | ||
| 609 | endif | ||
| 610 | |||
| 611 | let self.isExecutable = 0 | ||
| 612 | if !self.isDirectory | ||
| 613 | let self.isExecutable = getfperm(a:fullpath) =~# 'x' | ||
| 614 | endif | ||
| 615 | |||
| 616 | "grab the last part of the path (minus the trailing slash) | ||
| 617 | let lastPathComponent = self.getLastPathComponent(0) | ||
| 618 | |||
| 619 | "get the path to the new node with the parent dir fully resolved | ||
| 620 | let hardPath = s:Path.Resolve(self.strTrunk()) . '/' . lastPathComponent | ||
| 621 | |||
| 622 | "if the last part of the path is a symlink then flag it as such | ||
| 623 | let self.isSymLink = (s:Path.Resolve(hardPath) !=# hardPath) | ||
| 624 | if self.isSymLink | ||
| 625 | let self.symLinkDest = s:Path.Resolve(fullpath) | ||
| 626 | |||
| 627 | "if the link is a dir then slap a / on the end of its dest | ||
| 628 | if isdirectory(self.symLinkDest) | ||
| 629 | |||
| 630 | "we always wanna treat MS windows shortcuts as files for | ||
| 631 | "simplicity | ||
| 632 | if hardPath !~# '\.lnk$' | ||
| 633 | |||
| 634 | let self.symLinkDest = self.symLinkDest . '/' | ||
| 635 | endif | ||
| 636 | endif | ||
| 637 | endif | ||
| 638 | endfunction | ||
| 639 | |||
| 640 | " FUNCTION: Path.refresh(nerdtree) {{{1 | ||
| 641 | function! s:Path.refresh(nerdtree) | ||
| 642 | call self.readInfoFromDisk(self.str()) | ||
| 643 | call g:NERDTreePathNotifier.NotifyListeners('refresh', self, a:nerdtree, {}) | ||
| 644 | call self.cacheDisplayString() | ||
| 645 | endfunction | ||
| 646 | |||
| 647 | " FUNCTION: Path.refreshFlags(nerdtree) {{{1 | ||
| 648 | function! s:Path.refreshFlags(nerdtree) | ||
| 649 | call g:NERDTreePathNotifier.NotifyListeners('refreshFlags', self, a:nerdtree, {}) | ||
| 650 | call self.cacheDisplayString() | ||
| 651 | endfunction | ||
| 652 | |||
| 653 | " FUNCTION: Path.rename() {{{1 | ||
| 654 | " | ||
| 655 | " Renames this node on the filesystem | ||
| 656 | function! s:Path.rename(newPath) | ||
| 657 | if a:newPath ==# '' | ||
| 658 | throw 'NERDTree.InvalidArgumentsError: Invalid newPath for renaming = '. a:newPath | ||
| 659 | endif | ||
| 660 | |||
| 661 | call s:Path.createParentDirectories(a:newPath) | ||
| 662 | |||
| 663 | let success = rename(self.str(), a:newPath) | ||
| 664 | if success !=# 0 | ||
| 665 | throw "NERDTree.PathRenameError: Could not rename: '" . self.str() . "'" . 'to:' . a:newPath | ||
| 666 | endif | ||
| 667 | call self.readInfoFromDisk(a:newPath) | ||
| 668 | |||
| 669 | for i in self.bookmarkNames() | ||
| 670 | let b = g:NERDTreeBookmark.BookmarkFor(i) | ||
| 671 | call b.setPath(copy(self)) | ||
| 672 | endfor | ||
| 673 | call g:NERDTreeBookmark.Write() | ||
| 674 | endfunction | ||
| 675 | |||
| 676 | " FUNCTION: Path.str() {{{1 | ||
| 677 | " Return a string representation of this Path object. | ||
| 678 | " | ||
| 679 | " Args: | ||
| 680 | " This function takes a single dictionary (optional) with keys and values that | ||
| 681 | " specify how the returned pathname should be formatted. | ||
| 682 | " | ||
| 683 | " The dictionary may have the following keys: | ||
| 684 | " 'format' | ||
| 685 | " 'escape' | ||
| 686 | " 'truncateTo' | ||
| 687 | " | ||
| 688 | " The 'format' key may have a value of: | ||
| 689 | " 'Cd' - a string to be used with ":cd" and similar commands | ||
| 690 | " 'Edit' - a string to be used with ":edit" and similar commands | ||
| 691 | " 'UI' - a string to be displayed in the NERDTree user interface | ||
| 692 | " | ||
| 693 | " The 'escape' key, if specified, will cause the output to be escaped with | ||
| 694 | " Vim's internal "shellescape()" function. | ||
| 695 | " | ||
| 696 | " The 'truncateTo' key shortens the length of the path to that given by the | ||
| 697 | " value associated with 'truncateTo'. A '<' is prepended. | ||
| 698 | function! s:Path.str(...) | ||
| 699 | let options = a:0 ? a:1 : {} | ||
| 700 | let toReturn = '' | ||
| 701 | |||
| 702 | if has_key(options, 'format') | ||
| 703 | let format = options['format'] | ||
| 704 | if has_key(self, '_strFor' . format) | ||
| 705 | exec 'let toReturn = self._strFor' . format . '()' | ||
| 706 | else | ||
| 707 | throw 'NERDTree.UnknownFormatError: unknown format "'. format .'"' | ||
| 708 | endif | ||
| 709 | else | ||
| 710 | let toReturn = self._str() | ||
| 711 | endif | ||
| 712 | |||
| 713 | if nerdtree#has_opt(options, 'escape') | ||
| 714 | let toReturn = shellescape(toReturn) | ||
| 715 | endif | ||
| 716 | |||
| 717 | if has_key(options, 'truncateTo') | ||
| 718 | let limit = options['truncateTo'] | ||
| 719 | if strdisplaywidth(toReturn) > limit-1 | ||
| 720 | while strdisplaywidth(toReturn) > limit-1 && strchars(toReturn) > 0 | ||
| 721 | let toReturn = substitute(toReturn, '^.', '', '') | ||
| 722 | endwhile | ||
| 723 | if len(split(toReturn, '/')) > 1 | ||
| 724 | let toReturn = '</' . join(split(toReturn, '/')[1:], '/') . '/' | ||
| 725 | else | ||
| 726 | let toReturn = '<' . toReturn | ||
| 727 | endif | ||
| 728 | endif | ||
| 729 | endif | ||
| 730 | |||
| 731 | return toReturn | ||
| 732 | endfunction | ||
| 733 | |||
| 734 | " FUNCTION: Path._strForUI() {{{1 | ||
| 735 | function! s:Path._strForUI() | ||
| 736 | let toReturn = '/' . join(self.pathSegments, '/') | ||
| 737 | if self.isDirectory && toReturn !=# '/' | ||
| 738 | let toReturn = toReturn . '/' | ||
| 739 | endif | ||
| 740 | return toReturn | ||
| 741 | endfunction | ||
| 742 | |||
| 743 | " FUNCTION: Path._strForCd() {{{1 | ||
| 744 | " Return a string representation of this Path that is suitable for use as an | ||
| 745 | " argument to Vim's internal ":cd" command. | ||
| 746 | function! s:Path._strForCd() | ||
| 747 | return fnameescape(self.str()) | ||
| 748 | endfunction | ||
| 749 | |||
| 750 | " FUNCTION: Path._strForEdit() {{{1 | ||
| 751 | " Return a string representation of this Path that is suitable for use as an | ||
| 752 | " argument to Vim's internal ":edit" command. | ||
| 753 | function! s:Path._strForEdit() | ||
| 754 | |||
| 755 | " Make the path relative to the current working directory, if possible. | ||
| 756 | let l:result = fnamemodify(self.str(), ':.') | ||
| 757 | |||
| 758 | " On Windows, the drive letter may be removed by "fnamemodify()". Add it | ||
| 759 | " back, if necessary. | ||
| 760 | if nerdtree#runningWindows() && l:result[0] == nerdtree#slash() | ||
| 761 | let l:result = self.drive . l:result | ||
| 762 | endif | ||
| 763 | |||
| 764 | let l:result = fnameescape(l:result) | ||
| 765 | |||
| 766 | if empty(l:result) | ||
| 767 | let l:result = '.' | ||
| 768 | endif | ||
| 769 | |||
| 770 | return l:result | ||
| 771 | endfunction | ||
| 772 | |||
| 773 | " FUNCTION: Path._strForGlob() {{{1 | ||
| 774 | function! s:Path._strForGlob() | ||
| 775 | let lead = nerdtree#slash() | ||
| 776 | |||
| 777 | "if we are running windows then slap a drive letter on the front | ||
| 778 | if nerdtree#runningWindows() | ||
| 779 | let lead = self.drive . '\' | ||
| 780 | endif | ||
| 781 | |||
| 782 | let toReturn = lead . join(self.pathSegments, nerdtree#slash()) | ||
| 783 | |||
| 784 | if !nerdtree#runningWindows() | ||
| 785 | let toReturn = escape(toReturn, self._escChars()) | ||
| 786 | endif | ||
| 787 | return toReturn | ||
| 788 | endfunction | ||
| 789 | |||
| 790 | " FUNCTION: Path._str() {{{1 | ||
| 791 | " Return the absolute pathname associated with this Path object. The pathname | ||
| 792 | " returned is appropriate for the underlying file system. | ||
| 793 | function! s:Path._str() | ||
| 794 | let l:separator = nerdtree#slash() | ||
| 795 | let l:leader = l:separator | ||
| 796 | |||
| 797 | if nerdtree#runningWindows() | ||
| 798 | let l:leader = self.drive . l:separator | ||
| 799 | endif | ||
| 800 | |||
| 801 | return l:leader . join(self.pathSegments, l:separator) | ||
| 802 | endfunction | ||
| 803 | |||
| 804 | " FUNCTION: Path.strTrunk() {{{1 | ||
| 805 | " Gets the path without the last segment on the end. | ||
| 806 | function! s:Path.strTrunk() | ||
| 807 | return self.drive . '/' . join(self.pathSegments[0:-2], '/') | ||
| 808 | endfunction | ||
| 809 | |||
| 810 | " FUNCTION: Path.tabnr() {{{1 | ||
| 811 | " return the number of the first tab that is displaying this file | ||
| 812 | " | ||
| 813 | " return 0 if no tab was found | ||
| 814 | function! s:Path.tabnr() | ||
| 815 | let str = self.str() | ||
| 816 | for t in range(tabpagenr('$')) | ||
| 817 | for b in tabpagebuflist(t+1) | ||
| 818 | if str ==# expand('#' . b . ':p') | ||
| 819 | return t+1 | ||
| 820 | endif | ||
| 821 | endfor | ||
| 822 | endfor | ||
| 823 | return 0 | ||
| 824 | endfunction | ||
| 825 | |||
| 826 | " FUNCTION: Path.WinToUnixPath(pathstr){{{1 | ||
| 827 | " Takes in a windows path and returns the unix equiv | ||
| 828 | " | ||
| 829 | " A class level method | ||
| 830 | " | ||
| 831 | " Args: | ||
| 832 | " pathstr: the windows path to convert | ||
| 833 | function! s:Path.WinToUnixPath(pathstr) | ||
| 834 | if !nerdtree#runningWindows() | ||
| 835 | return a:pathstr | ||
| 836 | endif | ||
| 837 | |||
| 838 | let toReturn = a:pathstr | ||
| 839 | |||
| 840 | "remove the x:\ of the front | ||
| 841 | let toReturn = substitute(toReturn, '^.*:\(\\\|/\)\?', '/', '') | ||
| 842 | |||
| 843 | "remove the \\ network share from the front | ||
| 844 | let toReturn = substitute(toReturn, '^\(\\\\\|\/\/\)[^\\\/]*\(\\\|\/\)[^\\\/]*\(\\\|\/\)\?', '/', '') | ||
| 845 | |||
| 846 | "convert all \ chars to / | ||
| 847 | let toReturn = substitute(toReturn, '\', '/', 'g') | ||
| 848 | |||
| 849 | return toReturn | ||
| 850 | endfunction | ||
| 851 | |||
| 852 | " vim: set sw=4 sts=4 et fdm=marker: | ||
diff --git a/.vim/pack/vendor/start/nerdtree/lib/nerdtree/tree_dir_node.vim b/.vim/pack/vendor/start/nerdtree/lib/nerdtree/tree_dir_node.vim new file mode 100644 index 0000000..f5f7682 --- /dev/null +++ b/.vim/pack/vendor/start/nerdtree/lib/nerdtree/tree_dir_node.vim  | |||
| @@ -0,0 +1,706 @@ | |||
| 1 | " ============================================================================ | ||
| 2 | " CLASS: TreeDirNode | ||
| 3 | " | ||
| 4 | " A subclass of NERDTreeFileNode. | ||
| 5 | " | ||
| 6 | " The 'composite' part of the file/dir composite. | ||
| 7 | " ============================================================================ | ||
| 8 | |||
| 9 | |||
| 10 | let s:TreeDirNode = copy(g:NERDTreeFileNode) | ||
| 11 | let g:NERDTreeDirNode = s:TreeDirNode | ||
| 12 | |||
| 13 | " FUNCTION: TreeDirNode.AbsoluteTreeRoot(){{{1 | ||
| 14 | " Class method that returns the highest cached ancestor of the current root. | ||
| 15 | function! s:TreeDirNode.AbsoluteTreeRoot() | ||
| 16 | let currentNode = b:NERDTree.root | ||
| 17 | while currentNode.parent !=# {} | ||
| 18 | let currentNode = currentNode.parent | ||
| 19 | endwhile | ||
| 20 | return currentNode | ||
| 21 | endfunction | ||
| 22 | |||
| 23 | " FUNCTION: TreeDirNode.activate([options]) {{{1 | ||
| 24 | function! s:TreeDirNode.activate(...) | ||
| 25 | let l:options = (a:0 > 0) ? a:1 : {} | ||
| 26 | |||
| 27 | call self.toggleOpen(l:options) | ||
| 28 | |||
| 29 | " Note that we only re-render the NERDTree for this node if we did NOT | ||
| 30 | " create a new node and render it in a new window or tab. In the latter | ||
| 31 | " case, rendering the NERDTree for this node could overwrite the text of | ||
| 32 | " the new NERDTree! | ||
| 33 | if !has_key(l:options, 'where') || empty(l:options['where']) | ||
| 34 | call self.getNerdtree().render() | ||
| 35 | call self.putCursorHere(0, 0) | ||
| 36 | endif | ||
| 37 | endfunction | ||
| 38 | |||
| 39 | " FUNCTION: TreeDirNode.addChild(treenode, inOrder) {{{1 | ||
| 40 | " Adds the given treenode to the list of children for this node | ||
| 41 | " | ||
| 42 | " Args: | ||
| 43 | " -treenode: the node to add | ||
| 44 | " -inOrder: 1 if the new node should be inserted in sorted order | ||
| 45 | function! s:TreeDirNode.addChild(treenode, inOrder) | ||
| 46 | call add(self.children, a:treenode) | ||
| 47 | let a:treenode.parent = self | ||
| 48 | |||
| 49 | if a:inOrder | ||
| 50 | call self.sortChildren() | ||
| 51 | endif | ||
| 52 | endfunction | ||
| 53 | |||
| 54 | " FUNCTION: TreeDirNode.close() {{{1 | ||
| 55 | " Mark this TreeDirNode as closed. | ||
| 56 | function! s:TreeDirNode.close() | ||
| 57 | |||
| 58 | " Close all directories in this directory node's cascade. This is | ||
| 59 | " necessary to ensure consistency when cascades are rendered. | ||
| 60 | for l:dirNode in self.getCascade() | ||
| 61 | let l:dirNode.isOpen = 0 | ||
| 62 | endfor | ||
| 63 | endfunction | ||
| 64 | |||
| 65 | " FUNCTION: TreeDirNode.closeChildren() {{{1 | ||
| 66 | " Recursively close any directory nodes that are descendants of this node. | ||
| 67 | function! s:TreeDirNode.closeChildren() | ||
| 68 | for l:child in self.children | ||
| 69 | if l:child.path.isDirectory | ||
| 70 | call l:child.close() | ||
| 71 | call l:child.closeChildren() | ||
| 72 | endif | ||
| 73 | endfor | ||
| 74 | endfunction | ||
| 75 | |||
| 76 | " FUNCTION: TreeDirNode.createChild(path, inOrder) {{{1 | ||
| 77 | " Instantiates a new child node for this node with the given path. The new | ||
| 78 | " nodes parent is set to this node. | ||
| 79 | " | ||
| 80 | " Args: | ||
| 81 | " path: a Path object that this node will represent/contain | ||
| 82 | " inOrder: 1 if the new node should be inserted in sorted order | ||
| 83 | " | ||
| 84 | " Returns: | ||
| 85 | " the newly created node | ||
| 86 | function! s:TreeDirNode.createChild(path, inOrder) | ||
| 87 | let newTreeNode = g:NERDTreeFileNode.New(a:path, self.getNerdtree()) | ||
| 88 | call self.addChild(newTreeNode, a:inOrder) | ||
| 89 | return newTreeNode | ||
| 90 | endfunction | ||
| 91 | |||
| 92 | " FUNCTION: TreeDirNode.displayString() {{{1 | ||
| 93 | " Assemble and return a string that can represent this TreeDirNode object in | ||
| 94 | " the NERDTree window. | ||
| 95 | function! s:TreeDirNode.displayString() | ||
| 96 | let l:result = '' | ||
| 97 | |||
| 98 | " Build a label that identifies this TreeDirNode. | ||
| 99 | let l:label = '' | ||
| 100 | let l:cascade = self.getCascade() | ||
| 101 | for l:dirNode in l:cascade | ||
| 102 | let l:next = l:dirNode.path.displayString() | ||
| 103 | let l:label .= l:label ==# '' ? l:next : substitute(l:next,'^.','','') | ||
| 104 | endfor | ||
| 105 | |||
| 106 | " Select the appropriate open/closed status indicator symbol. | ||
| 107 | let l:symbol = (l:cascade[-1].isOpen ? g:NERDTreeDirArrowCollapsible : g:NERDTreeDirArrowExpandable ) | ||
| 108 | let l:symbol .= (g:NERDTreeDirArrowExpandable ==# '' ? '' : ' ') | ||
| 109 | let l:flags = l:cascade[-1].path.flagSet.renderToString() | ||
| 110 | |||
| 111 | return l:symbol . l:flags . l:label | ||
| 112 | endfunction | ||
| 113 | |||
| 114 | " FUNCTION: TreeDirNode.findNode(path) {{{1 | ||
| 115 | " Will find one of the children (recursively) that has the given path | ||
| 116 | " | ||
| 117 | " Args: | ||
| 118 | " path: a path object | ||
| 119 | unlet s:TreeDirNode.findNode | ||
| 120 | function! s:TreeDirNode.findNode(path) | ||
| 121 | if a:path.equals(self.path) | ||
| 122 | return self | ||
| 123 | endif | ||
| 124 | if stridx(a:path.str(), self.path.str(), 0) ==# -1 | ||
| 125 | return {} | ||
| 126 | endif | ||
| 127 | |||
| 128 | if self.path.isDirectory | ||
| 129 | for i in self.children | ||
| 130 | let retVal = i.findNode(a:path) | ||
| 131 | if retVal !=# {} | ||
| 132 | return retVal | ||
| 133 | endif | ||
| 134 | endfor | ||
| 135 | endif | ||
| 136 | return {} | ||
| 137 | endfunction | ||
| 138 | |||
| 139 | " FUNCTION: TreeDirNode.getCascade() {{{1 | ||
| 140 | " Return an array of dir nodes (starting from self) that can be cascade opened. | ||
| 141 | function! s:TreeDirNode.getCascade() | ||
| 142 | if !self.isCascadable() | ||
| 143 | return [self] | ||
| 144 | endif | ||
| 145 | |||
| 146 | let vc = self.getVisibleChildren() | ||
| 147 | let visChild = vc[0] | ||
| 148 | |||
| 149 | return [self] + visChild.getCascade() | ||
| 150 | endfunction | ||
| 151 | |||
| 152 | " FUNCTION: TreeDirNode.getCascadeRoot() {{{1 | ||
| 153 | " Return the first directory node in the cascade in which this directory node | ||
| 154 | " is rendered. | ||
| 155 | function! s:TreeDirNode.getCascadeRoot() | ||
| 156 | |||
| 157 | " Don't search above the current NERDTree root node. | ||
| 158 | if self.isRoot() | ||
| 159 | return self | ||
| 160 | endif | ||
| 161 | |||
| 162 | let l:cascadeRoot = self | ||
| 163 | let l:parent = self.parent | ||
| 164 | |||
| 165 | while !empty(l:parent) && !l:parent.isRoot() | ||
| 166 | |||
| 167 | if index(l:parent.getCascade(), self) ==# -1 | ||
| 168 | break | ||
| 169 | endif | ||
| 170 | |||
| 171 | let l:cascadeRoot = l:parent | ||
| 172 | let l:parent = l:parent.parent | ||
| 173 | endwhile | ||
| 174 | |||
| 175 | return l:cascadeRoot | ||
| 176 | endfunction | ||
| 177 | |||
| 178 | " FUNCTION: TreeDirNode.getChildCount() {{{1 | ||
| 179 | " Returns the number of children this node has | ||
| 180 | function! s:TreeDirNode.getChildCount() | ||
| 181 | return len(self.children) | ||
| 182 | endfunction | ||
| 183 | |||
| 184 | " FUNCTION: TreeDirNode.getChild(path) {{{1 | ||
| 185 | " Returns child node of this node that has the given path or {} if no such node | ||
| 186 | " exists. | ||
| 187 | " | ||
| 188 | " This function doesnt not recurse into child dir nodes | ||
| 189 | " | ||
| 190 | " Args: | ||
| 191 | " path: a path object | ||
| 192 | function! s:TreeDirNode.getChild(path) | ||
| 193 | if stridx(a:path.str(), self.path.str(), 0) ==# -1 | ||
| 194 | return {} | ||
| 195 | endif | ||
| 196 | |||
| 197 | let index = self.getChildIndex(a:path) | ||
| 198 | if index ==# -1 | ||
| 199 | return {} | ||
| 200 | else | ||
| 201 | return self.children[index] | ||
| 202 | endif | ||
| 203 | |||
| 204 | endfunction | ||
| 205 | |||
| 206 | " FUNCTION: TreeDirNode.getChildByIndex(indx, visible) {{{1 | ||
| 207 | " returns the child at the given index | ||
| 208 | " | ||
| 209 | " Args: | ||
| 210 | " indx: the index to get the child from | ||
| 211 | " visible: 1 if only the visible children array should be used, 0 if all the | ||
| 212 | " children should be searched. | ||
| 213 | function! s:TreeDirNode.getChildByIndex(indx, visible) | ||
| 214 | let array_to_search = a:visible? self.getVisibleChildren() : self.children | ||
| 215 | if a:indx > len(array_to_search) | ||
| 216 | throw 'NERDTree.InvalidArgumentsError: Index is out of bounds.' | ||
| 217 | endif | ||
| 218 | return array_to_search[a:indx] | ||
| 219 | endfunction | ||
| 220 | |||
| 221 | " FUNCTION: TreeDirNode.getChildIndex(path) {{{1 | ||
| 222 | " Returns the index of the child node of this node that has the given path or | ||
| 223 | " -1 if no such node exists. | ||
| 224 | " | ||
| 225 | " This function doesnt not recurse into child dir nodes | ||
| 226 | " | ||
| 227 | " Args: | ||
| 228 | " path: a path object | ||
| 229 | function! s:TreeDirNode.getChildIndex(path) | ||
| 230 | if stridx(a:path.str(), self.path.str(), 0) ==# -1 | ||
| 231 | return -1 | ||
| 232 | endif | ||
| 233 | |||
| 234 | "do a binary search for the child | ||
| 235 | let a = 0 | ||
| 236 | let z = self.getChildCount() | ||
| 237 | while a < z | ||
| 238 | let mid = (a+z)/2 | ||
| 239 | let diff = nerdtree#compareNodePaths(a:path, self.children[mid].path) | ||
| 240 | |||
| 241 | if diff ==# -1 | ||
| 242 | let z = mid | ||
| 243 | elseif diff ==# 1 | ||
| 244 | let a = mid+1 | ||
| 245 | else | ||
| 246 | return mid | ||
| 247 | endif | ||
| 248 | endwhile | ||
| 249 | return -1 | ||
| 250 | endfunction | ||
| 251 | |||
| 252 | " FUNCTION: TreeDirNode.getDirChildren() {{{1 | ||
| 253 | " Return a list of all child nodes from 'self.children' that are of type | ||
| 254 | " TreeDirNode. This function supports http://github.com/scrooloose/nerdtree-project-plugin.git. | ||
| 255 | function! s:TreeDirNode.getDirChildren() | ||
| 256 | return filter(copy(self.children), 'v:val.path.isDirectory ==# 1') | ||
| 257 | endfunction | ||
| 258 | |||
| 259 | " FUNCTION: TreeDirNode._glob(pattern, all) {{{1 | ||
| 260 | " Return a list of strings naming the descendants of the directory in this | ||
| 261 | " TreeDirNode object that match the specified glob pattern. | ||
| 262 | " | ||
| 263 | " Args: | ||
| 264 | " pattern: (string) the glob pattern to apply | ||
| 265 | " all: (0 or 1) if 1, include '.' and '..' if they match 'pattern'; if 0, | ||
| 266 | " always exclude them | ||
| 267 | " | ||
| 268 | " Note: If the pathnames in the result list are below the working directory, | ||
| 269 | " they are returned as pathnames relative to that directory. This is because | ||
| 270 | " this function, internally, attempts to obey 'wildignore' rules that use | ||
| 271 | " relative paths. | ||
| 272 | function! s:TreeDirNode._glob(pattern, all) | ||
| 273 | |||
| 274 | " Construct a path specification such that globpath() will return | ||
| 275 | " relative pathnames, if possible. | ||
| 276 | if self.path.str() ==# getcwd() | ||
| 277 | let l:pathSpec = ',' | ||
| 278 | else | ||
| 279 | let l:pathSpec = escape(fnamemodify(self.path.str({'format': 'Glob'}), ':.'), ',') | ||
| 280 | |||
| 281 | " On Windows, the drive letter may be removed by "fnamemodify()". | ||
| 282 | if nerdtree#runningWindows() && l:pathSpec[0] == nerdtree#slash() | ||
| 283 | let l:pathSpec = self.path.drive . l:pathSpec | ||
| 284 | endif | ||
| 285 | endif | ||
| 286 | |||
| 287 | let l:globList = [] | ||
| 288 | |||
| 289 | " See ':h version7.txt' and ':h version8.txt' for details on the | ||
| 290 | " development of the glob() and globpath() functions. | ||
| 291 | if v:version > 704 || (v:version ==# 704 && has('patch654')) | ||
| 292 | let l:globList = globpath(l:pathSpec, a:pattern, !g:NERDTreeRespectWildIgnore, 1, 0) | ||
| 293 | elseif v:version ==# 704 && has('patch279') | ||
| 294 | let l:globList = globpath(l:pathSpec, a:pattern, !g:NERDTreeRespectWildIgnore, 1) | ||
| 295 | elseif v:version > 702 || (v:version ==# 702 && has('patch051')) | ||
| 296 | let l:globString = globpath(l:pathSpec, a:pattern, !g:NERDTreeRespectWildIgnore) | ||
| 297 | let l:globList = split(l:globString, "\n") | ||
| 298 | else | ||
| 299 | let l:globString = globpath(l:pathSpec, a:pattern) | ||
| 300 | let l:globList = split(l:globString, "\n") | ||
| 301 | endif | ||
| 302 | |||
| 303 | " If a:all is false, filter '.' and '..' from the output. | ||
| 304 | if !a:all | ||
| 305 | let l:toRemove = [] | ||
| 306 | |||
| 307 | for l:file in l:globList | ||
| 308 | let l:tail = fnamemodify(l:file, ':t') | ||
| 309 | |||
| 310 | " If l:file has a trailing slash, then its :tail will be ''. Use | ||
| 311 | " :h to drop the slash and the empty string after it; then use :t | ||
| 312 | " to get the directory name. | ||
| 313 | if l:tail ==# '' | ||
| 314 | let l:tail = fnamemodify(l:file, ':h:t') | ||
| 315 | endif | ||
| 316 | |||
| 317 | if l:tail ==# '.' || l:tail ==# '..' | ||
| 318 | call add(l:toRemove, l:file) | ||
| 319 | if len(l:toRemove) ==# 2 | ||
| 320 | break | ||
| 321 | endif | ||
| 322 | endif | ||
| 323 | endfor | ||
| 324 | |||
| 325 | for l:file in l:toRemove | ||
| 326 | call remove(l:globList, index(l:globList, l:file)) | ||
| 327 | endfor | ||
| 328 | endif | ||
| 329 | |||
| 330 | return l:globList | ||
| 331 | endfunction | ||
| 332 | |||
| 333 | " FUNCTION: TreeDirNode.GetSelected() {{{1 | ||
| 334 | " Returns the current node if it is a dir node, or else returns the current | ||
| 335 | " nodes parent | ||
| 336 | unlet s:TreeDirNode.GetSelected | ||
| 337 | function! s:TreeDirNode.GetSelected() | ||
| 338 | let currentDir = g:NERDTreeFileNode.GetSelected() | ||
| 339 | if currentDir !=# {} && !currentDir.isRoot() | ||
| 340 | if currentDir.path.isDirectory ==# 0 | ||
| 341 | let currentDir = currentDir.parent | ||
| 342 | endif | ||
| 343 | endif | ||
| 344 | return currentDir | ||
| 345 | endfunction | ||
| 346 | |||
| 347 | " FUNCTION: TreeDirNode.getVisibleChildCount() {{{1 | ||
| 348 | " Returns the number of visible children this node has | ||
| 349 | function! s:TreeDirNode.getVisibleChildCount() | ||
| 350 | return len(self.getVisibleChildren()) | ||
| 351 | endfunction | ||
| 352 | |||
| 353 | " FUNCTION: TreeDirNode.getVisibleChildren() {{{1 | ||
| 354 | " Returns a list of children to display for this node, in the correct order | ||
| 355 | " | ||
| 356 | " Return: | ||
| 357 | " an array of treenodes | ||
| 358 | function! s:TreeDirNode.getVisibleChildren() | ||
| 359 | let toReturn = [] | ||
| 360 | for i in self.children | ||
| 361 | if i.path.ignore(self.getNerdtree()) ==# 0 | ||
| 362 | call add(toReturn, i) | ||
| 363 | endif | ||
| 364 | endfor | ||
| 365 | return toReturn | ||
| 366 | endfunction | ||
| 367 | |||
| 368 | " FUNCTION: TreeDirNode.hasVisibleChildren() {{{1 | ||
| 369 | " returns 1 if this node has any childre, 0 otherwise.. | ||
| 370 | function! s:TreeDirNode.hasVisibleChildren() | ||
| 371 | return self.getVisibleChildCount() !=# 0 | ||
| 372 | endfunction | ||
| 373 | |||
| 374 | " FUNCTION: TreeDirNode.isCascadable() {{{1 | ||
| 375 | " true if this dir has only one visible child that is also a dir | ||
| 376 | " false if this dir is bookmarked or symlinked. Why? Two reasons: | ||
| 377 | " 1. If cascaded, we don't know which dir is bookmarked or is a symlink. | ||
| 378 | " 2. If the parent is a symlink or is bookmarked, you end up with unparsable | ||
| 379 | " text, and NERDTree cannot get the path of any child node. | ||
| 380 | " Also, return false if this directory is the tree root, which should never be | ||
| 381 | " part of a cascade. | ||
| 382 | function! s:TreeDirNode.isCascadable() | ||
| 383 | if g:NERDTreeCascadeSingleChildDir ==# 0 | ||
| 384 | return 0 | ||
| 385 | endif | ||
| 386 | |||
| 387 | if self.isRoot() | ||
| 388 | return 0 | ||
| 389 | endif | ||
| 390 | |||
| 391 | if self.path.isSymLink | ||
| 392 | return 0 | ||
| 393 | endif | ||
| 394 | |||
| 395 | for i in g:NERDTreeBookmark.Bookmarks() | ||
| 396 | if i.path.equals(self.path) | ||
| 397 | return 0 | ||
| 398 | endif | ||
| 399 | endfor | ||
| 400 | |||
| 401 | let c = self.getVisibleChildren() | ||
| 402 | return len(c) ==# 1 && c[0].path.isDirectory | ||
| 403 | endfunction | ||
| 404 | |||
| 405 | " FUNCTION: TreeDirNode._initChildren() {{{1 | ||
| 406 | " Removes all childen from this node and re-reads them | ||
| 407 | " | ||
| 408 | " Args: | ||
| 409 | " silent: 1 if the function should not echo any 'please wait' messages for | ||
| 410 | " large directories | ||
| 411 | " | ||
| 412 | " Return: the number of child nodes read | ||
| 413 | function! s:TreeDirNode._initChildren(silent) | ||
| 414 | "remove all the current child nodes | ||
| 415 | let self.children = [] | ||
| 416 | |||
| 417 | let files = self._glob('*', 1) + self._glob('.*', 0) | ||
| 418 | |||
| 419 | if !a:silent && len(files) > g:NERDTreeNotificationThreshold | ||
| 420 | call nerdtree#echo('Please wait, caching a large dir ...') | ||
| 421 | endif | ||
| 422 | |||
| 423 | let invalidFilesFound = 0 | ||
| 424 | for i in files | ||
| 425 | try | ||
| 426 | let path = g:NERDTreePath.New(i) | ||
| 427 | call self.createChild(path, 0) | ||
| 428 | call g:NERDTreePathNotifier.NotifyListeners('init', path, self.getNerdtree(), {}) | ||
| 429 | catch /^NERDTree.\(InvalidArguments\|InvalidFiletype\)Error/ | ||
| 430 | let invalidFilesFound += 1 | ||
| 431 | endtry | ||
| 432 | endfor | ||
| 433 | |||
| 434 | let g:NERDTreeOldSortOrder = g:NERDTreeSortOrder | ||
| 435 | call self.sortChildren() | ||
| 436 | |||
| 437 | call nerdtree#echo('') | ||
| 438 | |||
| 439 | if invalidFilesFound | ||
| 440 | call nerdtree#echoWarning(invalidFilesFound . ' file(s) could not be loaded into the NERD tree') | ||
| 441 | endif | ||
| 442 | return self.getChildCount() | ||
| 443 | endfunction | ||
| 444 | |||
| 445 | " FUNCTION: TreeDirNode.New(path, nerdtree) {{{1 | ||
| 446 | " Return a new TreeDirNode object with the given path and parent. | ||
| 447 | " | ||
| 448 | " Args: | ||
| 449 | " path: dir that the node represents | ||
| 450 | " nerdtree: the tree the node belongs to | ||
| 451 | function! s:TreeDirNode.New(path, nerdtree) | ||
| 452 | if a:path.isDirectory !=# 1 | ||
| 453 | throw 'NERDTree.InvalidArgumentsError: A TreeDirNode object must be instantiated with a directory Path object.' | ||
| 454 | endif | ||
| 455 | |||
| 456 | let newTreeNode = copy(self) | ||
| 457 | let newTreeNode.path = a:path | ||
| 458 | |||
| 459 | let newTreeNode.isOpen = 0 | ||
| 460 | let newTreeNode.children = [] | ||
| 461 | |||
| 462 | let newTreeNode.parent = {} | ||
| 463 | let newTreeNode._nerdtree = a:nerdtree | ||
| 464 | |||
| 465 | return newTreeNode | ||
| 466 | endfunction | ||
| 467 | |||
| 468 | " FUNCTION: TreeDirNode.open([options]) {{{1 | ||
| 469 | " Open this directory node in the current tree or elsewhere if special options | ||
| 470 | " are provided. Return 0 if options were processed. Otherwise, return the | ||
| 471 | " number of new cached nodes. | ||
| 472 | function! s:TreeDirNode.open(...) | ||
| 473 | let l:options = a:0 ? a:1 : {} | ||
| 474 | |||
| 475 | " If special options were specified, process them and return. | ||
| 476 | if has_key(l:options, 'where') && !empty(l:options['where']) | ||
| 477 | let l:opener = g:NERDTreeOpener.New(self.path, l:options) | ||
| 478 | call l:opener.open(self) | ||
| 479 | return 0 | ||
| 480 | endif | ||
| 481 | |||
| 482 | " Open any ancestors of this node that render within the same cascade. | ||
| 483 | let l:parent = self.parent | ||
| 484 | while !empty(l:parent) && !l:parent.isRoot() | ||
| 485 | if index(l:parent.getCascade(), self) >= 0 | ||
| 486 | let l:parent.isOpen = 1 | ||
| 487 | let l:parent = l:parent.parent | ||
| 488 | else | ||
| 489 | break | ||
| 490 | endif | ||
| 491 | endwhile | ||
| 492 | |||
| 493 | let self.isOpen = 1 | ||
| 494 | |||
| 495 | let l:numChildrenCached = 0 | ||
| 496 | if empty(self.children) | ||
| 497 | let l:numChildrenCached = self._initChildren(0) | ||
| 498 | endif | ||
| 499 | |||
| 500 | return l:numChildrenCached | ||
| 501 | endfunction | ||
| 502 | |||
| 503 | " FUNCTION: TreeDirNode.openAlong([opts]) {{{1 | ||
| 504 | " recursive open the dir if it has only one directory child. | ||
| 505 | " | ||
| 506 | " return the level of opened directories. | ||
| 507 | function! s:TreeDirNode.openAlong(...) | ||
| 508 | let opts = a:0 ? a:1 : {} | ||
| 509 | let level = 0 | ||
| 510 | |||
| 511 | let node = self | ||
| 512 | while node.path.isDirectory | ||
| 513 | call node.open(opts) | ||
| 514 | let level += 1 | ||
| 515 | if node.getVisibleChildCount() ==# 1 | ||
| 516 | let node = node.getChildByIndex(0, 1) | ||
| 517 | else | ||
| 518 | break | ||
| 519 | endif | ||
| 520 | endwhile | ||
| 521 | return level | ||
| 522 | endfunction | ||
| 523 | |||
| 524 | " FUNCTION: TreeDirNode.openExplorer() {{{1 | ||
| 525 | " Open an explorer window for this node in the previous window. The explorer | ||
| 526 | " can be a NERDTree window or a netrw window. | ||
| 527 | function! s:TreeDirNode.openExplorer() | ||
| 528 | execute 'wincmd p' | ||
| 529 | execute 'edit '.self.path.str({'format':'Edit'}) | ||
| 530 | endfunction | ||
| 531 | |||
| 532 | " FUNCTION: TreeDirNode.openInNewTab(options) {{{1 | ||
| 533 | unlet s:TreeDirNode.openInNewTab | ||
| 534 | function! s:TreeDirNode.openInNewTab(options) | ||
| 535 | call nerdtree#deprecated('TreeDirNode.openInNewTab', 'is deprecated, use open() instead') | ||
| 536 | call self.open({'where': 't'}) | ||
| 537 | endfunction | ||
| 538 | |||
| 539 | " FUNCTION: TreeDirNode._openInNewTab() {{{1 | ||
| 540 | function! s:TreeDirNode._openInNewTab() | ||
| 541 | tabnew | ||
| 542 | call g:NERDTreeCreator.CreateTabTree(self.path.str()) | ||
| 543 | endfunction | ||
| 544 | |||
| 545 | " FUNCTION: TreeDirNode.openRecursively() {{{1 | ||
| 546 | " Open this directory node and any descendant directory nodes whose pathnames | ||
| 547 | " are not ignored. | ||
| 548 | function! s:TreeDirNode.openRecursively() | ||
| 549 | silent call self.open() | ||
| 550 | |||
| 551 | for l:child in self.children | ||
| 552 | if l:child.path.isDirectory && !l:child.path.ignore(l:child.getNerdtree()) | ||
| 553 | call l:child.openRecursively() | ||
| 554 | endif | ||
| 555 | endfor | ||
| 556 | endfunction | ||
| 557 | |||
| 558 | " FUNCTION: TreeDirNode.refresh() {{{1 | ||
| 559 | function! s:TreeDirNode.refresh() | ||
| 560 | call self.path.refresh(self.getNerdtree()) | ||
| 561 | |||
| 562 | "if this node was ever opened, refresh its children | ||
| 563 | if self.isOpen || !empty(self.children) | ||
| 564 | let files = self._glob('*', 1) + self._glob('.*', 0) | ||
| 565 | let newChildNodes = [] | ||
| 566 | let invalidFilesFound = 0 | ||
| 567 | for i in files | ||
| 568 | try | ||
| 569 | "create a new path and see if it exists in this nodes children | ||
| 570 | let path = g:NERDTreePath.New(i) | ||
| 571 | let newNode = self.getChild(path) | ||
| 572 | if newNode !=# {} | ||
| 573 | call newNode.refresh() | ||
| 574 | call add(newChildNodes, newNode) | ||
| 575 | |||
| 576 | "the node doesnt exist so create it | ||
| 577 | else | ||
| 578 | let newNode = g:NERDTreeFileNode.New(path, self.getNerdtree()) | ||
| 579 | let newNode.parent = self | ||
| 580 | call add(newChildNodes, newNode) | ||
| 581 | endif | ||
| 582 | catch /^NERDTree.\(InvalidArguments\|InvalidFiletype\)Error/ | ||
| 583 | let invalidFilesFound = 1 | ||
| 584 | endtry | ||
| 585 | endfor | ||
| 586 | |||
| 587 | "swap this nodes children out for the children we just read/refreshed | ||
| 588 | let self.children = newChildNodes | ||
| 589 | call self.sortChildren() | ||
| 590 | |||
| 591 | if invalidFilesFound | ||
| 592 | call nerdtree#echoWarning('some files could not be loaded into the NERD tree') | ||
| 593 | endif | ||
| 594 | endif | ||
| 595 | endfunction | ||
| 596 | |||
| 597 | " FUNCTION: TreeDirNode.refreshFlags() {{{1 | ||
| 598 | unlet s:TreeDirNode.refreshFlags | ||
| 599 | function! s:TreeDirNode.refreshFlags() | ||
| 600 | call self.path.refreshFlags(self.getNerdtree()) | ||
| 601 | for i in self.children | ||
| 602 | call i.refreshFlags() | ||
| 603 | endfor | ||
| 604 | endfunction | ||
| 605 | |||
| 606 | " FUNCTION: TreeDirNode.refreshDirFlags() {{{1 | ||
| 607 | function! s:TreeDirNode.refreshDirFlags() | ||
| 608 | call self.path.refreshFlags(self.getNerdtree()) | ||
| 609 | endfunction | ||
| 610 | |||
| 611 | " FUNCTION: TreeDirNode.reveal(path) {{{1 | ||
| 612 | " reveal the given path, i.e. cache and open all treenodes needed to display it | ||
| 613 | " in the UI | ||
| 614 | " Returns the revealed node | ||
| 615 | function! s:TreeDirNode.reveal(path, ...) | ||
| 616 | let opts = a:0 ? a:1 : {} | ||
| 617 | |||
| 618 | if !a:path.isUnder(self.path) | ||
| 619 | throw 'NERDTree.InvalidArgumentsError: ' . a:path.str() . ' should be under ' . self.path.str() | ||
| 620 | endif | ||
| 621 | |||
| 622 | call self.open() | ||
| 623 | |||
| 624 | if self.path.equals(a:path.getParent()) | ||
| 625 | let n = self.findNode(a:path) | ||
| 626 | " We may be looking for a newly-saved file that isn't in the tree yet. | ||
| 627 | if n ==# {} | ||
| 628 | call self.refresh() | ||
| 629 | let n = self.findNode(a:path) | ||
| 630 | endif | ||
| 631 | if has_key(opts, 'open') | ||
| 632 | call n.open() | ||
| 633 | endif | ||
| 634 | return n | ||
| 635 | endif | ||
| 636 | |||
| 637 | let p = a:path | ||
| 638 | while !p.getParent().equals(self.path) | ||
| 639 | let p = p.getParent() | ||
| 640 | endwhile | ||
| 641 | |||
| 642 | let n = self.findNode(p) | ||
| 643 | return n.reveal(a:path, opts) | ||
| 644 | endfunction | ||
| 645 | |||
| 646 | " FUNCTION: TreeDirNode.removeChild(treenode) {{{1 | ||
| 647 | " Remove the given treenode from self.children. | ||
| 648 | " Throws NERDTree.ChildNotFoundError if the node is not found. | ||
| 649 | " | ||
| 650 | " Args: | ||
| 651 | " treenode: the node object to remove | ||
| 652 | function! s:TreeDirNode.removeChild(treenode) | ||
| 653 | for i in range(0, self.getChildCount()-1) | ||
| 654 | if self.children[i].equals(a:treenode) | ||
| 655 | call remove(self.children, i) | ||
| 656 | return | ||
| 657 | endif | ||
| 658 | endfor | ||
| 659 | |||
| 660 | throw 'NERDTree.ChildNotFoundError: child node was not found' | ||
| 661 | endfunction | ||
| 662 | |||
| 663 | " FUNCTION: TreeDirNode.sortChildren() {{{1 | ||
| 664 | " Sort self.children by alphabetical order and directory priority. | ||
| 665 | function! s:TreeDirNode.sortChildren() | ||
| 666 | if count(g:NERDTreeSortOrder, '*') < 1 | ||
| 667 | call add(g:NERDTreeSortOrder, '*') | ||
| 668 | endif | ||
| 669 | let CompareFunc = function('nerdtree#compareNodes') | ||
| 670 | call sort(self.children, CompareFunc) | ||
| 671 | let g:NERDTreeOldSortOrder = g:NERDTreeSortOrder | ||
| 672 | endfunction | ||
| 673 | |||
| 674 | " FUNCTION: TreeDirNode.toggleOpen([options]) {{{1 | ||
| 675 | " Opens this directory if it is closed and vice versa | ||
| 676 | function! s:TreeDirNode.toggleOpen(...) | ||
| 677 | let opts = a:0 ? a:1 : {} | ||
| 678 | if self.isOpen ==# 1 | ||
| 679 | call self.close() | ||
| 680 | else | ||
| 681 | if g:NERDTreeCascadeOpenSingleChildDir ==# 0 | ||
| 682 | call self.open(opts) | ||
| 683 | else | ||
| 684 | call self.openAlong(opts) | ||
| 685 | endif | ||
| 686 | endif | ||
| 687 | endfunction | ||
| 688 | |||
| 689 | " FUNCTION: TreeDirNode.transplantChild(newNode) {{{1 | ||
| 690 | " Replaces the child of this with the given node (where the child node's full | ||
| 691 | " path matches a:newNode's fullpath). The search for the matching node is | ||
| 692 | " non-recursive | ||
| 693 | " | ||
| 694 | " Arg: | ||
| 695 | " newNode: the node to graft into the tree | ||
| 696 | function! s:TreeDirNode.transplantChild(newNode) | ||
| 697 | for i in range(0, self.getChildCount()-1) | ||
| 698 | if self.children[i].equals(a:newNode) | ||
| 699 | let self.children[i] = a:newNode | ||
| 700 | let a:newNode.parent = self | ||
| 701 | break | ||
| 702 | endif | ||
| 703 | endfor | ||
| 704 | endfunction | ||
| 705 | |||
| 706 | " vim: set sw=4 sts=4 et fdm=marker: | ||
diff --git a/.vim/pack/vendor/start/nerdtree/lib/nerdtree/tree_file_node.vim b/.vim/pack/vendor/start/nerdtree/lib/nerdtree/tree_file_node.vim new file mode 100644 index 0000000..957b98a --- /dev/null +++ b/.vim/pack/vendor/start/nerdtree/lib/nerdtree/tree_file_node.vim  | |||
| @@ -0,0 +1,349 @@ | |||
| 1 | " ============================================================================ | ||
| 2 | " CLASS: TreeFileNode | ||
| 3 | " | ||
| 4 | " This class is the parent of the TreeDirNode class and is the 'Component' | ||
| 5 | " part of the composite design pattern between the NERDTree node classes. | ||
| 6 | " ============================================================================ | ||
| 7 | |||
| 8 | |||
| 9 | let s:TreeFileNode = {} | ||
| 10 | let g:NERDTreeFileNode = s:TreeFileNode | ||
| 11 | |||
| 12 | " FUNCTION: TreeFileNode.activate(...) {{{1 | ||
| 13 | function! s:TreeFileNode.activate(...) | ||
| 14 | call self.open(a:0 ? a:1 : {}) | ||
| 15 | endfunction | ||
| 16 | |||
| 17 | " FUNCTION: TreeFileNode.bookmark(name) {{{1 | ||
| 18 | " bookmark this node with a:name | ||
| 19 | function! s:TreeFileNode.bookmark(name) | ||
| 20 | |||
| 21 | " if a bookmark exists with the same name and the node is cached then save | ||
| 22 | " it so we can update its display string | ||
| 23 | let oldMarkedNode = {} | ||
| 24 | try | ||
| 25 | let oldMarkedNode = g:NERDTreeBookmark.GetNodeForName(a:name, 1, self.getNerdtree()) | ||
| 26 | catch /^NERDTree.BookmarkNotFoundError/ | ||
| 27 | catch /^NERDTree.BookmarkedNodeNotFoundError/ | ||
| 28 | endtry | ||
| 29 | |||
| 30 | call g:NERDTreeBookmark.AddBookmark(a:name, self.path) | ||
| 31 | call self.path.cacheDisplayString() | ||
| 32 | call g:NERDTreeBookmark.Write() | ||
| 33 | |||
| 34 | if !empty(oldMarkedNode) | ||
| 35 | call oldMarkedNode.path.cacheDisplayString() | ||
| 36 | endif | ||
| 37 | endfunction | ||
| 38 | |||
| 39 | " FUNCTION: TreeFileNode.cacheParent() {{{1 | ||
| 40 | " initializes self.parent if it isnt already | ||
| 41 | function! s:TreeFileNode.cacheParent() | ||
| 42 | if empty(self.parent) | ||
| 43 | let parentPath = self.path.getParent() | ||
| 44 | if parentPath.equals(self.path) | ||
| 45 | throw 'NERDTree.CannotCacheParentError: already at root' | ||
| 46 | endif | ||
| 47 | let self.parent = s:TreeFileNode.New(parentPath, self.getNerdtree()) | ||
| 48 | endif | ||
| 49 | endfunction | ||
| 50 | |||
| 51 | " FUNCTION: TreeFileNode.clearBookmarks() {{{1 | ||
| 52 | function! s:TreeFileNode.clearBookmarks() | ||
| 53 | for i in g:NERDTreeBookmark.Bookmarks() | ||
| 54 | if i.path.equals(self.path) | ||
| 55 | call i.delete() | ||
| 56 | end | ||
| 57 | endfor | ||
| 58 | call self.path.cacheDisplayString() | ||
| 59 | endfunction | ||
| 60 | |||
| 61 | " FUNCTION: TreeFileNode.copy(dest) {{{1 | ||
| 62 | function! s:TreeFileNode.copy(dest) | ||
| 63 | call self.path.copy(a:dest) | ||
| 64 | let newPath = g:NERDTreePath.New(a:dest) | ||
| 65 | let parent = self.getNerdtree().root.findNode(newPath.getParent()) | ||
| 66 | if !empty(parent) | ||
| 67 | call parent.refresh() | ||
| 68 | return parent.findNode(newPath) | ||
| 69 | else | ||
| 70 | return {} | ||
| 71 | endif | ||
| 72 | endfunction | ||
| 73 | |||
| 74 | " FUNCTION: TreeFileNode.delete {{{1 | ||
| 75 | " Removes this node from the tree and calls the Delete method for its path obj | ||
| 76 | function! s:TreeFileNode.delete() | ||
| 77 | call self.path.delete() | ||
| 78 | call self.parent.removeChild(self) | ||
| 79 | endfunction | ||
| 80 | |||
| 81 | " FUNCTION: TreeFileNode.displayString() {{{1 | ||
| 82 | " | ||
| 83 | " Returns a string that specifies how the node should be represented as a | ||
| 84 | " string | ||
| 85 | " | ||
| 86 | " Return: | ||
| 87 | " a string that can be used in the view to represent this node | ||
| 88 | function! s:TreeFileNode.displayString() | ||
| 89 | return self.path.flagSet.renderToString() . self.path.displayString() | ||
| 90 | endfunction | ||
| 91 | |||
| 92 | " FUNCTION: TreeFileNode.equals(treenode) {{{1 | ||
| 93 | " | ||
| 94 | " Compares this treenode to the input treenode and returns 1 if they are the | ||
| 95 | " same node. | ||
| 96 | " | ||
| 97 | " Use this method instead of == because sometimes when the treenodes contain | ||
| 98 | " many children, vim seg faults when doing == | ||
| 99 | " | ||
| 100 | " Args: | ||
| 101 | " treenode: the other treenode to compare to | ||
| 102 | function! s:TreeFileNode.equals(treenode) | ||
| 103 | return self.path.str() ==# a:treenode.path.str() | ||
| 104 | endfunction | ||
| 105 | |||
| 106 | " FUNCTION: TreeFileNode.findNode(path) {{{1 | ||
| 107 | " Returns self if this node.path.Equals the given path. | ||
| 108 | " Returns {} if not equal. | ||
| 109 | " | ||
| 110 | " Args: | ||
| 111 | " path: the path object to compare against | ||
| 112 | function! s:TreeFileNode.findNode(path) | ||
| 113 | if a:path.equals(self.path) | ||
| 114 | return self | ||
| 115 | endif | ||
| 116 | return {} | ||
| 117 | endfunction | ||
| 118 | |||
| 119 | " FUNCTION: TreeFileNode.findSibling(direction) {{{1 | ||
| 120 | " Find the next or previous sibling of this node. | ||
| 121 | " | ||
| 122 | " Args: | ||
| 123 | " direction: 0 for previous, 1 for next | ||
| 124 | " | ||
| 125 | " Return: | ||
| 126 | " The next/previous TreeFileNode object or an empty dictionary if not found. | ||
| 127 | function! s:TreeFileNode.findSibling(direction) | ||
| 128 | |||
| 129 | " There can be no siblings if there is no parent. | ||
| 130 | if empty(self.parent) | ||
| 131 | return {} | ||
| 132 | endif | ||
| 133 | |||
| 134 | let l:nodeIndex = self.parent.getChildIndex(self.path) | ||
| 135 | |||
| 136 | if l:nodeIndex == -1 | ||
| 137 | return {} | ||
| 138 | endif | ||
| 139 | |||
| 140 | " Get the next index to begin the search. | ||
| 141 | let l:nodeIndex += a:direction ? 1 : -1 | ||
| 142 | |||
| 143 | while 0 <= l:nodeIndex && l:nodeIndex < self.parent.getChildCount() | ||
| 144 | |||
| 145 | " Return the next node if it is not ignored. | ||
| 146 | if !self.parent.children[l:nodeIndex].path.ignore(self.getNerdtree()) | ||
| 147 | return self.parent.children[l:nodeIndex] | ||
| 148 | endif | ||
| 149 | |||
| 150 | let l:nodeIndex += a:direction ? 1 : -1 | ||
| 151 | endwhile | ||
| 152 | |||
| 153 | return {} | ||
| 154 | endfunction | ||
| 155 | |||
| 156 | " FUNCTION: TreeFileNode.getNerdtree(){{{1 | ||
| 157 | function! s:TreeFileNode.getNerdtree() | ||
| 158 | return self._nerdtree | ||
| 159 | endfunction | ||
| 160 | |||
| 161 | " FUNCTION: TreeFileNode.GetRootForTab(){{{1 | ||
| 162 | " get the root node for this tab | ||
| 163 | function! s:TreeFileNode.GetRootForTab() | ||
| 164 | if g:NERDTree.ExistsForTab() | ||
| 165 | return getbufvar(t:NERDTreeBufName, 'NERDTree').root | ||
| 166 | end | ||
| 167 | return {} | ||
| 168 | endfunction | ||
| 169 | |||
| 170 | " FUNCTION: TreeFileNode.GetSelected() {{{1 | ||
| 171 | " If the cursor is currently positioned on a tree node, return the node. | ||
| 172 | " Otherwise, return the empty dictionary. | ||
| 173 | function! s:TreeFileNode.GetSelected() | ||
| 174 | |||
| 175 | try | ||
| 176 | let l:path = b:NERDTree.ui.getPath(line('.')) | ||
| 177 | |||
| 178 | if empty(l:path) | ||
| 179 | return {} | ||
| 180 | endif | ||
| 181 | |||
| 182 | return b:NERDTree.root.findNode(l:path) | ||
| 183 | catch | ||
| 184 | return {} | ||
| 185 | endtry | ||
| 186 | endfunction | ||
| 187 | |||
| 188 | " FUNCTION: TreeFileNode.isVisible() {{{1 | ||
| 189 | " returns 1 if this node should be visible according to the tree filters and | ||
| 190 | " hidden file filters (and their on/off status) | ||
| 191 | function! s:TreeFileNode.isVisible() | ||
| 192 | return !self.path.ignore(self.getNerdtree()) | ||
| 193 | endfunction | ||
| 194 | |||
| 195 | " FUNCTION: TreeFileNode.isRoot() {{{1 | ||
| 196 | function! s:TreeFileNode.isRoot() | ||
| 197 | if !g:NERDTree.ExistsForBuf() | ||
| 198 | throw 'NERDTree.NoTreeError: No tree exists for the current buffer' | ||
| 199 | endif | ||
| 200 | |||
| 201 | return self.equals(self.getNerdtree().root) | ||
| 202 | endfunction | ||
| 203 | |||
| 204 | " FUNCTION: TreeFileNode.New(path, nerdtree) {{{1 | ||
| 205 | " Returns a new TreeNode object with the given path and parent | ||
| 206 | " | ||
| 207 | " Args: | ||
| 208 | " path: file/dir that the node represents | ||
| 209 | " nerdtree: the tree the node belongs to | ||
| 210 | function! s:TreeFileNode.New(path, nerdtree) | ||
| 211 | if a:path.isDirectory | ||
| 212 | return g:NERDTreeDirNode.New(a:path, a:nerdtree) | ||
| 213 | else | ||
| 214 | let newTreeNode = copy(self) | ||
| 215 | let newTreeNode.path = a:path | ||
| 216 | let newTreeNode.parent = {} | ||
| 217 | let newTreeNode._nerdtree = a:nerdtree | ||
| 218 | return newTreeNode | ||
| 219 | endif | ||
| 220 | endfunction | ||
| 221 | |||
| 222 | " FUNCTION: TreeFileNode.open() {{{1 | ||
| 223 | function! s:TreeFileNode.open(...) | ||
| 224 | let opts = a:0 ? a:1 : {} | ||
| 225 | let opener = g:NERDTreeOpener.New(self.path, opts) | ||
| 226 | call opener.open(self) | ||
| 227 | endfunction | ||
| 228 | |||
| 229 | " FUNCTION: TreeFileNode.openSplit() {{{1 | ||
| 230 | " Open this node in a new window | ||
| 231 | function! s:TreeFileNode.openSplit() | ||
| 232 | call nerdtree#deprecated('TreeFileNode.openSplit', 'is deprecated, use .open() instead.') | ||
| 233 | call self.open({'where': 'h'}) | ||
| 234 | endfunction | ||
| 235 | |||
| 236 | " FUNCTION: TreeFileNode.openVSplit() {{{1 | ||
| 237 | " Open this node in a new vertical window | ||
| 238 | function! s:TreeFileNode.openVSplit() | ||
| 239 | call nerdtree#deprecated('TreeFileNode.openVSplit', 'is deprecated, use .open() instead.') | ||
| 240 | call self.open({'where': 'v'}) | ||
| 241 | endfunction | ||
| 242 | |||
| 243 | " FUNCTION: TreeFileNode.openInNewTab(options) {{{1 | ||
| 244 | function! s:TreeFileNode.openInNewTab(options) | ||
| 245 | call nerdtree#deprecated('TreeFileNode.openinNewTab', 'is deprecated, use .open() instead.') | ||
| 246 | call self.open(extend({'where': 't'}, a:options)) | ||
| 247 | endfunction | ||
| 248 | |||
| 249 | " FUNCTION: TreeFileNode.openExplorer() | ||
| 250 | function! s:TreeFileNode.openExplorer() | ||
| 251 | execute 'wincmd p' | ||
| 252 | execute 'edit '.self.path.getParent().str({'format':'Edit'}) | ||
| 253 | endfunction | ||
| 254 | |||
| 255 | " FUNCTION: TreeFileNode.putCursorHere(isJump, recurseUpward){{{1 | ||
| 256 | " Places the cursor on the line number this node is rendered on | ||
| 257 | " | ||
| 258 | " Args: | ||
| 259 | " isJump: 1 if this cursor movement should be counted as a jump by vim | ||
| 260 | " recurseUpward: try to put the cursor on the parent if the this node isnt | ||
| 261 | " visible | ||
| 262 | function! s:TreeFileNode.putCursorHere(isJump, recurseUpward) | ||
| 263 | let ln = self.getNerdtree().ui.getLineNum(self) | ||
| 264 | if ln != -1 | ||
| 265 | if a:isJump | ||
| 266 | mark ' | ||
| 267 | endif | ||
| 268 | call cursor(ln, col('.')) | ||
| 269 | else | ||
| 270 | if a:recurseUpward | ||
| 271 | let node = self | ||
| 272 | while node != {} && self.getNerdtree().ui.getLineNum(node) ==# -1 | ||
| 273 | let node = node.parent | ||
| 274 | call node.open() | ||
| 275 | endwhile | ||
| 276 | call self._nerdtree.render() | ||
| 277 | call node.putCursorHere(a:isJump, 0) | ||
| 278 | endif | ||
| 279 | endif | ||
| 280 | endfunction | ||
| 281 | |||
| 282 | " FUNCTION: TreeFileNode.refresh() {{{1 | ||
| 283 | function! s:TreeFileNode.refresh() | ||
| 284 | call self.path.refresh(self.getNerdtree()) | ||
| 285 | endfunction | ||
| 286 | |||
| 287 | " FUNCTION: TreeFileNode.refreshFlags() {{{1 | ||
| 288 | function! s:TreeFileNode.refreshFlags() | ||
| 289 | call self.path.refreshFlags(self.getNerdtree()) | ||
| 290 | endfunction | ||
| 291 | |||
| 292 | " FUNCTION: TreeFileNode.rename() {{{1 | ||
| 293 | " Calls the rename method for this nodes path obj | ||
| 294 | function! s:TreeFileNode.rename(newName) | ||
| 295 | let newName = substitute(a:newName, '\(\\\|\/\)$', '', '') | ||
| 296 | call self.path.rename(newName) | ||
| 297 | call self.parent.removeChild(self) | ||
| 298 | |||
| 299 | let parentPath = self.path.getParent() | ||
| 300 | let newParent = self.getNerdtree().root.findNode(parentPath) | ||
| 301 | |||
| 302 | if newParent != {} | ||
| 303 | call newParent.createChild(self.path, 1) | ||
| 304 | call newParent.refresh() | ||
| 305 | endif | ||
| 306 | endfunction | ||
| 307 | |||
| 308 | " FUNCTION: TreeFileNode.renderToString {{{1 | ||
| 309 | " returns a string representation for this tree to be rendered in the view | ||
| 310 | function! s:TreeFileNode.renderToString() | ||
| 311 | return self._renderToString(0, 0) | ||
| 312 | endfunction | ||
| 313 | |||
| 314 | " Args: | ||
| 315 | " depth: the current depth in the tree for this call | ||
| 316 | " drawText: 1 if we should actually draw the line for this node (if 0 then the | ||
| 317 | " child nodes are rendered only) | ||
| 318 | " for each depth in the tree | ||
| 319 | function! s:TreeFileNode._renderToString(depth, drawText) | ||
| 320 | let output = '' | ||
| 321 | if a:drawText ==# 1 | ||
| 322 | |||
| 323 | let treeParts = repeat(' ', a:depth - 1) | ||
| 324 | let treeParts .= (self.path.isDirectory || g:NERDTreeDirArrowExpandable ==# '' ? '' : ' ') | ||
| 325 | |||
| 326 | let line = treeParts . self.displayString() | ||
| 327 | let output = output . line . "\n" | ||
| 328 | endif | ||
| 329 | |||
| 330 | " if the node is an open dir, draw its children | ||
| 331 | if self.path.isDirectory ==# 1 && self.isOpen ==# 1 | ||
| 332 | |||
| 333 | let childNodesToDraw = self.getVisibleChildren() | ||
| 334 | |||
| 335 | if self.isCascadable() && a:depth > 0 | ||
| 336 | |||
| 337 | let output = output . childNodesToDraw[0]._renderToString(a:depth, 0) | ||
| 338 | |||
| 339 | elseif len(childNodesToDraw) > 0 | ||
| 340 | for i in childNodesToDraw | ||
| 341 | let output = output . i._renderToString(a:depth + 1, 1) | ||
| 342 | endfor | ||
| 343 | endif | ||
| 344 | endif | ||
| 345 | |||
| 346 | return output | ||
| 347 | endfunction | ||
| 348 | |||
| 349 | " vim: set sw=4 sts=4 et fdm=marker: | ||
diff --git a/.vim/pack/vendor/start/nerdtree/lib/nerdtree/ui.vim b/.vim/pack/vendor/start/nerdtree/lib/nerdtree/ui.vim new file mode 100644 index 0000000..a481ba4 --- /dev/null +++ b/.vim/pack/vendor/start/nerdtree/lib/nerdtree/ui.vim  | |||
| @@ -0,0 +1,532 @@ | |||
| 1 | " ============================================================================ | ||
| 2 | " CLASS: UI | ||
| 3 | " ============================================================================ | ||
| 4 | |||
| 5 | |||
| 6 | let s:UI = {} | ||
| 7 | let g:NERDTreeUI = s:UI | ||
| 8 | |||
| 9 | " FUNCTION: s:UI.centerView() {{{1 | ||
| 10 | " centers the nerd tree window around the cursor (provided the nerd tree | ||
| 11 | " options permit) | ||
| 12 | function! s:UI.centerView() | ||
| 13 | if g:NERDTreeAutoCenter | ||
| 14 | let current_line = winline() | ||
| 15 | let lines_to_top = current_line | ||
| 16 | let lines_to_bottom = winheight(g:NERDTree.GetWinNum()) - current_line | ||
| 17 | if lines_to_top < g:NERDTreeAutoCenterThreshold || lines_to_bottom < g:NERDTreeAutoCenterThreshold | ||
| 18 | normal! zz | ||
| 19 | endif | ||
| 20 | endif | ||
| 21 | endfunction | ||
| 22 | |||
| 23 | " FUNCTION: s:UI._dumpHelp {{{1 | ||
| 24 | " prints out the quick help | ||
| 25 | function! s:UI._dumpHelp() | ||
| 26 | if self.getShowHelp() | ||
| 27 | let help = "\" NERDTree (" . nerdtree#version() . ") quickhelp~\n" | ||
| 28 | let help .= "\" ============================\n" | ||
| 29 | let help .= "\" File node mappings~\n" | ||
| 30 | let help .= '" '. (g:NERDTreeMouseMode ==# 3 ? 'single' : 'double') ."-click,\n" | ||
| 31 | if self.nerdtree.isTabTree() | ||
| 32 | let help .= '" '. g:NERDTreeMapActivateNode .": open in prev window\n" | ||
| 33 | else | ||
| 34 | let help .= '" '. g:NERDTreeMapActivateNode .": open in current window\n" | ||
| 35 | endif | ||
| 36 | if self.nerdtree.isTabTree() | ||
| 37 | let help .= '" '. g:NERDTreeMapPreview .": preview\n" | ||
| 38 | endif | ||
| 39 | let help .= '" '. g:NERDTreeMapOpenInTab.": open in new tab\n" | ||
| 40 | let help .= '" '. g:NERDTreeMapOpenInTabSilent .": open in new tab silently\n" | ||
| 41 | let help .= "\" middle-click,\n" | ||
| 42 | let help .= '" '. g:NERDTreeMapOpenSplit .": open split\n" | ||
| 43 | let help .= '" '. g:NERDTreeMapPreviewSplit .": preview split\n" | ||
| 44 | let help .= '" '. g:NERDTreeMapOpenVSplit .": open vsplit\n" | ||
| 45 | let help .= '" '. g:NERDTreeMapPreviewVSplit .": preview vsplit\n" | ||
| 46 | let help .= '" '. g:NERDTreeMapCustomOpen .": custom open\n" | ||
| 47 | |||
| 48 | let help .= "\"\n\" ----------------------------\n" | ||
| 49 | let help .= "\" Directory node mappings~\n" | ||
| 50 | let help .= '" '. (g:NERDTreeMouseMode ==# 1 ? 'double' : 'single') ."-click,\n" | ||
| 51 | let help .= '" '. g:NERDTreeMapActivateNode .": open & close node\n" | ||
| 52 | let help .= '" '. g:NERDTreeMapOpenRecursively .": recursively open node\n" | ||
| 53 | let help .= '" '. g:NERDTreeMapOpenInTab.": open in new tab\n" | ||
| 54 | let help .= '" '. g:NERDTreeMapOpenInTabSilent .": open in new tab silently\n" | ||
| 55 | let help .= '" '. g:NERDTreeMapCustomOpen .": custom open\n" | ||
| 56 | let help .= '" '. g:NERDTreeMapCloseDir .": close parent of node\n" | ||
| 57 | let help .= '" '. g:NERDTreeMapCloseChildren .": close all child nodes of\n" | ||
| 58 | let help .= "\" current node recursively\n" | ||
| 59 | let help .= "\" middle-click,\n" | ||
| 60 | let help .= '" '. g:NERDTreeMapOpenExpl.": explore selected dir\n" | ||
| 61 | |||
| 62 | let help .= "\"\n\" ----------------------------\n" | ||
| 63 | let help .= "\" Bookmark table mappings~\n" | ||
| 64 | let help .= "\" double-click,\n" | ||
| 65 | let help .= '" '. g:NERDTreeMapActivateNode .": open bookmark\n" | ||
| 66 | let help .= '" '. g:NERDTreeMapPreview .": preview file\n" | ||
| 67 | let help .= '" '. g:NERDTreeMapPreview .": find dir in tree\n" | ||
| 68 | let help .= '" '. g:NERDTreeMapOpenInTab.": open in new tab\n" | ||
| 69 | let help .= '" '. g:NERDTreeMapOpenInTabSilent .": open in new tab silently\n" | ||
| 70 | let help .= '" '. g:NERDTreeMapOpenSplit .": open split\n" | ||
| 71 | let help .= '" '. g:NERDTreeMapPreviewSplit .": preview split\n" | ||
| 72 | let help .= '" '. g:NERDTreeMapOpenVSplit .": open vsplit\n" | ||
| 73 | let help .= '" '. g:NERDTreeMapPreviewVSplit .": preview vsplit\n" | ||
| 74 | let help .= '" '. g:NERDTreeMapCustomOpen .": custom open\n" | ||
| 75 | let help .= '" '. g:NERDTreeMapDeleteBookmark .": delete bookmark\n" | ||
| 76 | |||
| 77 | let help .= "\"\n\" ----------------------------\n" | ||
| 78 | let help .= "\" Tree navigation mappings~\n" | ||
| 79 | let help .= '" '. g:NERDTreeMapJumpRoot .": go to root\n" | ||
| 80 | let help .= '" '. g:NERDTreeMapJumpParent .": go to parent\n" | ||
| 81 | let help .= '" '. g:NERDTreeMapJumpFirstChild .": go to first child\n" | ||
| 82 | let help .= '" '. g:NERDTreeMapJumpLastChild .": go to last child\n" | ||
| 83 | let help .= '" '. g:NERDTreeMapJumpNextSibling .": go to next sibling\n" | ||
| 84 | let help .= '" '. g:NERDTreeMapJumpPrevSibling .": go to prev sibling\n" | ||
| 85 | |||
| 86 | let help .= "\"\n\" ----------------------------\n" | ||
| 87 | let help .= "\" Filesystem mappings~\n" | ||
| 88 | let help .= '" '. g:NERDTreeMapChangeRoot .": change tree root to the\n" | ||
| 89 | let help .= "\" selected dir\n" | ||
| 90 | let help .= '" '. g:NERDTreeMapUpdir .": move tree root up a dir\n" | ||
| 91 | let help .= '" '. g:NERDTreeMapUpdirKeepOpen .": move tree root up a dir\n" | ||
| 92 | let help .= "\" but leave old root open\n" | ||
| 93 | let help .= '" '. g:NERDTreeMapRefresh .": refresh cursor dir\n" | ||
| 94 | let help .= '" '. g:NERDTreeMapRefreshRoot .": refresh current root\n" | ||
| 95 | let help .= '" '. g:NERDTreeMapMenu .": Show menu\n" | ||
| 96 | let help .= '" '. g:NERDTreeMapChdir .":change the CWD to the\n" | ||
| 97 | let help .= "\" selected dir\n" | ||
| 98 | let help .= '" '. g:NERDTreeMapCWD .":change tree root to CWD\n" | ||
| 99 | |||
| 100 | let help .= "\"\n\" ----------------------------\n" | ||
| 101 | let help .= "\" Tree filtering mappings~\n" | ||
| 102 | let help .= '" '. g:NERDTreeMapToggleHidden .': hidden files (' . (self.getShowHidden() ? 'on' : 'off') . ")\n" | ||
| 103 | let help .= '" '. g:NERDTreeMapToggleFilters .': file filters (' . (self.isIgnoreFilterEnabled() ? 'on' : 'off') . ")\n" | ||
| 104 | let help .= '" '. g:NERDTreeMapToggleFiles .': files (' . (self.getShowFiles() ? 'on' : 'off') . ")\n" | ||
| 105 | let help .= '" '. g:NERDTreeMapToggleBookmarks .': bookmarks (' . (self.getShowBookmarks() ? 'on' : 'off') . ")\n" | ||
| 106 | |||
| 107 | " add quickhelp entries for each custom key map | ||
| 108 | let help .= "\"\n\" ----------------------------\n" | ||
| 109 | let help .= "\" Custom mappings~\n" | ||
| 110 | for i in g:NERDTreeKeyMap.All() | ||
| 111 | if !empty(i.quickhelpText) | ||
| 112 | let help .= '" '. i.key .': '. i.quickhelpText ."\n" | ||
| 113 | endif | ||
| 114 | endfor | ||
| 115 | |||
| 116 | let help .= "\"\n\" ----------------------------\n" | ||
| 117 | let help .= "\" Other mappings~\n" | ||
| 118 | let help .= '" '. g:NERDTreeMapQuit .": Close the NERDTree window\n" | ||
| 119 | let help .= '" '. g:NERDTreeMapToggleZoom .": Zoom (maximize-minimize)\n" | ||
| 120 | let help .= "\" the NERDTree window\n" | ||
| 121 | let help .= '" '. g:NERDTreeMapHelp .": toggle help\n" | ||
| 122 | let help .= "\"\n\" ----------------------------\n" | ||
| 123 | let help .= "\" Bookmark commands~\n" | ||
| 124 | let help .= "\" :Bookmark [<name>]\n" | ||
| 125 | let help .= "\" :BookmarkToRoot <name>\n" | ||
| 126 | let help .= "\" :RevealBookmark <name>\n" | ||
| 127 | let help .= "\" :OpenBookmark <name>\n" | ||
| 128 | let help .= "\" :ClearBookmarks [<names>]\n" | ||
| 129 | let help .= "\" :ClearAllBookmarks\n" | ||
| 130 | let help .= "\" :ReadBookmarks\n" | ||
| 131 | let help .= "\" :WriteBookmarks\n" | ||
| 132 | let help .= "\" :EditBookmarks\n" | ||
| 133 | silent! put =help | ||
| 134 | elseif !self.isMinimal() | ||
| 135 | let help ='" Press '. g:NERDTreeMapHelp ." for help\n" | ||
| 136 | silent! put =help | ||
| 137 | endif | ||
| 138 | endfunction | ||
| 139 | |||
| 140 | |||
| 141 | " FUNCTION: s:UI.new(nerdtree) {{{1 | ||
| 142 | function! s:UI.New(nerdtree) | ||
| 143 | let newObj = copy(self) | ||
| 144 | let newObj.nerdtree = a:nerdtree | ||
| 145 | let newObj._showHelp = 0 | ||
| 146 | let newObj._ignoreEnabled = 1 | ||
| 147 | let newObj._showFiles = g:NERDTreeShowFiles | ||
| 148 | let newObj._showHidden = g:NERDTreeShowHidden | ||
| 149 | let newObj._showBookmarks = g:NERDTreeShowBookmarks | ||
| 150 | |||
| 151 | return newObj | ||
| 152 | endfunction | ||
| 153 | |||
| 154 | " FUNCTION: s:UI.getPath(ln) {{{1 | ||
| 155 | " Return the Path object for the node that is rendered on the given line | ||
| 156 | " number. If the 'up a dir' line is selected, return the Path object for | ||
| 157 | " the parent of the root. Return the empty dictionary if the given line | ||
| 158 | " does not reference a tree node. | ||
| 159 | function! s:UI.getPath(ln) | ||
| 160 | let line = getline(a:ln) | ||
| 161 | |||
| 162 | let rootLine = self.getRootLineNum() | ||
| 163 | |||
| 164 | if a:ln ==# rootLine | ||
| 165 | return self.nerdtree.root.path | ||
| 166 | endif | ||
| 167 | |||
| 168 | if line ==# s:UI.UpDirLine() | ||
| 169 | return self.nerdtree.root.path.getParent() | ||
| 170 | endif | ||
| 171 | |||
| 172 | if a:ln < rootLine | ||
| 173 | return {} | ||
| 174 | endif | ||
| 175 | |||
| 176 | let indent = self._indentLevelFor(line) | ||
| 177 | |||
| 178 | " remove the tree parts and the leading space | ||
| 179 | let curFile = self._stripMarkup(line) | ||
| 180 | |||
| 181 | let dir = '' | ||
| 182 | let lnum = a:ln | ||
| 183 | while lnum > 0 | ||
| 184 | let lnum = lnum - 1 | ||
| 185 | let curLine = getline(lnum) | ||
| 186 | let curLineStripped = self._stripMarkup(curLine) | ||
| 187 | |||
| 188 | " have we reached the top of the tree? | ||
| 189 | if lnum ==# rootLine | ||
| 190 | let dir = self.nerdtree.root.path.str({'format': 'UI'}) . dir | ||
| 191 | break | ||
| 192 | endif | ||
| 193 | if curLineStripped =~# '/$' | ||
| 194 | let lpindent = self._indentLevelFor(curLine) | ||
| 195 | if lpindent < indent | ||
| 196 | let indent = indent - 1 | ||
| 197 | |||
| 198 | let dir = substitute (curLineStripped,'^\\', '', '') . dir | ||
| 199 | continue | ||
| 200 | endif | ||
| 201 | endif | ||
| 202 | endwhile | ||
| 203 | let curFile = self.nerdtree.root.path.drive . dir . curFile | ||
| 204 | let toReturn = g:NERDTreePath.New(curFile) | ||
| 205 | return toReturn | ||
| 206 | endfunction | ||
| 207 | |||
| 208 | " FUNCTION: s:UI.getLineNum(node) {{{1 | ||
| 209 | " Return the line number where the given node is rendered. Return -1 if the | ||
| 210 | " given node is not visible. | ||
| 211 | function! s:UI.getLineNum(node) | ||
| 212 | |||
| 213 | if a:node.isRoot() | ||
| 214 | return self.getRootLineNum() | ||
| 215 | endif | ||
| 216 | |||
| 217 | let l:pathComponents = [substitute(self.nerdtree.root.path.str({'format': 'UI'}), '/\s*$', '', '')] | ||
| 218 | let l:currentPathComponent = 1 | ||
| 219 | |||
| 220 | let l:fullPath = a:node.path.str({'format': 'UI'}) | ||
| 221 | |||
| 222 | for l:lineNumber in range(self.getRootLineNum() + 1, line('$')) | ||
| 223 | let l:currentLine = getline(l:lineNumber) | ||
| 224 | let l:indentLevel = self._indentLevelFor(l:currentLine) | ||
| 225 | |||
| 226 | if l:indentLevel !=# l:currentPathComponent | ||
| 227 | continue | ||
| 228 | endif | ||
| 229 | |||
| 230 | let l:currentLine = self._stripMarkup(l:currentLine) | ||
| 231 | let l:currentPath = join(l:pathComponents, '/') . '/' . l:currentLine | ||
| 232 | |||
| 233 | " Directories: If the current path 'starts with' the full path, then | ||
| 234 | " either the paths are equal or the line is a cascade containing the | ||
| 235 | " full path. | ||
| 236 | if l:fullPath[-1:] ==# '/' && stridx(l:currentPath, l:fullPath) ==# 0 | ||
| 237 | return l:lineNumber | ||
| 238 | endif | ||
| 239 | |||
| 240 | " Files: The paths must exactly match. | ||
| 241 | if l:fullPath ==# l:currentPath | ||
| 242 | return l:lineNumber | ||
| 243 | endif | ||
| 244 | |||
| 245 | " Otherwise: If the full path starts with the current path and the | ||
| 246 | " current path is a directory, we add a new path component. | ||
| 247 | if stridx(l:fullPath, l:currentPath) ==# 0 && l:currentPath[-1:] ==# '/' | ||
| 248 | let l:currentLine = substitute(l:currentLine, '/\s*$', '', '') | ||
| 249 | call add(l:pathComponents, l:currentLine) | ||
| 250 | let l:currentPathComponent += 1 | ||
| 251 | endif | ||
| 252 | endfor | ||
| 253 | |||
| 254 | return -1 | ||
| 255 | endfunction | ||
| 256 | |||
| 257 | " FUNCTION: s:UI.getRootLineNum(){{{1 | ||
| 258 | " gets the line number of the root node | ||
| 259 | function! s:UI.getRootLineNum() | ||
| 260 | let rootLine = 1 | ||
| 261 | while rootLine <= line('$') && getline(rootLine) !~# '^\(/\|<\)' | ||
| 262 | let rootLine = rootLine + 1 | ||
| 263 | endwhile | ||
| 264 | return rootLine | ||
| 265 | endfunction | ||
| 266 | |||
| 267 | " FUNCTION: s:UI.getShowBookmarks() {{{1 | ||
| 268 | function! s:UI.getShowBookmarks() | ||
| 269 | return self._showBookmarks | ||
| 270 | endfunction | ||
| 271 | |||
| 272 | " FUNCTION: s:UI.getShowFiles() {{{1 | ||
| 273 | function! s:UI.getShowFiles() | ||
| 274 | return self._showFiles | ||
| 275 | endfunction | ||
| 276 | |||
| 277 | " FUNCTION: s:UI.getShowHelp() {{{1 | ||
| 278 | function! s:UI.getShowHelp() | ||
| 279 | return self._showHelp | ||
| 280 | endfunction | ||
| 281 | |||
| 282 | " FUNCTION: s:UI.getShowHidden() {{{1 | ||
| 283 | function! s:UI.getShowHidden() | ||
| 284 | return self._showHidden | ||
| 285 | endfunction | ||
| 286 | |||
| 287 | " FUNCTION: s:UI._indentLevelFor(line) {{{1 | ||
| 288 | function! s:UI._indentLevelFor(line) | ||
| 289 | " Replace multi-character DirArrows with a single space so the | ||
| 290 | " indentation calculation doesn't get messed up. | ||
| 291 | if g:NERDTreeDirArrowExpandable ==# '' | ||
| 292 | let l:line = ' '.a:line | ||
| 293 | else | ||
| 294 | let l:line = substitute(substitute(a:line, '\V'.g:NERDTreeDirArrowExpandable, ' ', ''), '\V'.g:NERDTreeDirArrowCollapsible, ' ', '') | ||
| 295 | endif | ||
| 296 | let leadChars = match(l:line, '\M\[^ ]') | ||
| 297 | return leadChars / s:UI.IndentWid() | ||
| 298 | endfunction | ||
| 299 | |||
| 300 | " FUNCTION: s:UI.IndentWid() {{{1 | ||
| 301 | function! s:UI.IndentWid() | ||
| 302 | return 2 | ||
| 303 | endfunction | ||
| 304 | |||
| 305 | " FUNCTION: s:UI.isIgnoreFilterEnabled() {{{1 | ||
| 306 | function! s:UI.isIgnoreFilterEnabled() | ||
| 307 | return self._ignoreEnabled ==# 1 | ||
| 308 | endfunction | ||
| 309 | |||
| 310 | " FUNCTION: s:UI.isMinimal() {{{1 | ||
| 311 | function! s:UI.isMinimal() | ||
| 312 | return g:NERDTreeMinimalUI | ||
| 313 | endfunction | ||
| 314 | |||
| 315 | " FUNCTION: s:UI.MarkupReg() {{{1 | ||
| 316 | function! s:UI.MarkupReg() | ||
| 317 | return '^ *['.g:NERDTreeDirArrowExpandable.g:NERDTreeDirArrowCollapsible.']\? ' | ||
| 318 | endfunction | ||
| 319 | |||
| 320 | " FUNCTION: s:UI._renderBookmarks {{{1 | ||
| 321 | function! s:UI._renderBookmarks() | ||
| 322 | |||
| 323 | if !self.isMinimal() | ||
| 324 | call setline(line('.')+1, '>----------Bookmarks----------') | ||
| 325 | call cursor(line('.')+1, col('.')) | ||
| 326 | endif | ||
| 327 | |||
| 328 | if g:NERDTreeBookmarksSort ==# 1 || g:NERDTreeBookmarksSort ==# 2 | ||
| 329 | call g:NERDTreeBookmark.SortBookmarksList() | ||
| 330 | endif | ||
| 331 | |||
| 332 | for i in g:NERDTreeBookmark.Bookmarks() | ||
| 333 | call setline(line('.')+1, i.str()) | ||
| 334 | call cursor(line('.')+1, col('.')) | ||
| 335 | endfor | ||
| 336 | |||
| 337 | call setline(line('.')+1, '') | ||
| 338 | call cursor(line('.')+1, col('.')) | ||
| 339 | endfunction | ||
| 340 | |||
| 341 | " FUNCTION: s:UI.restoreScreenState() {{{1 | ||
| 342 | " | ||
| 343 | " Sets the screen state back to what it was when nerdtree#saveScreenState was last | ||
| 344 | " called. | ||
| 345 | " | ||
| 346 | " Assumes the cursor is in the NERDTree window | ||
| 347 | function! s:UI.restoreScreenState() | ||
| 348 | if !has_key(self, '_screenState') | ||
| 349 | return | ||
| 350 | endif | ||
| 351 | call nerdtree#exec('silent vertical resize ' . self._screenState['oldWindowSize'], 1) | ||
| 352 | |||
| 353 | let old_scrolloff=&scrolloff | ||
| 354 | let &scrolloff=0 | ||
| 355 | call cursor(self._screenState['oldTopLine'], 0) | ||
| 356 | normal! zt | ||
| 357 | call setpos('.', self._screenState['oldPos']) | ||
| 358 | let &scrolloff=old_scrolloff | ||
| 359 | endfunction | ||
| 360 | |||
| 361 | " FUNCTION: s:UI.saveScreenState() {{{1 | ||
| 362 | " Saves the current cursor position in the current buffer and the window | ||
| 363 | " scroll position | ||
| 364 | function! s:UI.saveScreenState() | ||
| 365 | let win = winnr() | ||
| 366 | let self._screenState = {} | ||
| 367 | try | ||
| 368 | call g:NERDTree.CursorToTreeWin() | ||
| 369 | let self._screenState['oldPos'] = getpos('.') | ||
| 370 | let self._screenState['oldTopLine'] = line('w0') | ||
| 371 | let self._screenState['oldWindowSize'] = winnr('$')==1 ? g:NERDTreeWinSize : winwidth('') | ||
| 372 | call nerdtree#exec(win . 'wincmd w', 1) | ||
| 373 | catch | ||
| 374 | endtry | ||
| 375 | endfunction | ||
| 376 | |||
| 377 | " FUNCTION: s:UI.setShowHidden(val) {{{1 | ||
| 378 | function! s:UI.setShowHidden(val) | ||
| 379 | let self._showHidden = a:val | ||
| 380 | endfunction | ||
| 381 | |||
| 382 | " FUNCTION: s:UI._stripMarkup(line){{{1 | ||
| 383 | " find the filename in the given line, and return it. | ||
| 384 | " | ||
| 385 | " Args: | ||
| 386 | " line: the subject line | ||
| 387 | function! s:UI._stripMarkup(line) | ||
| 388 | let l:line = substitute(a:line, '^.\{-}' . g:NERDTreeNodeDelimiter, '', '') | ||
| 389 | return substitute(l:line, g:NERDTreeNodeDelimiter.'.*$', '', '') | ||
| 390 | endfunction | ||
| 391 | |||
| 392 | " FUNCTION: s:UI.render() {{{1 | ||
| 393 | function! s:UI.render() | ||
| 394 | setlocal noreadonly modifiable | ||
| 395 | |||
| 396 | " remember the top line of the buffer and the current line so we can | ||
| 397 | " restore the view exactly how it was | ||
| 398 | let curLine = line('.') | ||
| 399 | let curCol = col('.') | ||
| 400 | let topLine = line('w0') | ||
| 401 | |||
| 402 | " delete all lines in the buffer (being careful not to clobber a register) | ||
| 403 | silent 1,$delete _ | ||
| 404 | |||
| 405 | call self._dumpHelp() | ||
| 406 | |||
| 407 | " delete the blank line before the help and add one after it | ||
| 408 | if !self.isMinimal() | ||
| 409 | call setline(line('.')+1, '') | ||
| 410 | call cursor(line('.')+1, col('.')) | ||
| 411 | endif | ||
| 412 | |||
| 413 | if self.getShowBookmarks() | ||
| 414 | call self._renderBookmarks() | ||
| 415 | endif | ||
| 416 | |||
| 417 | " add the 'up a dir' line | ||
| 418 | if !self.isMinimal() | ||
| 419 | call setline(line('.')+1, s:UI.UpDirLine()) | ||
| 420 | call cursor(line('.')+1, col('.')) | ||
| 421 | endif | ||
| 422 | |||
| 423 | " draw the header line | ||
| 424 | let header = self.nerdtree.root.path.str({'format': 'UI', 'truncateTo': winwidth(0)}) | ||
| 425 | call setline(line('.')+1, header) | ||
| 426 | call cursor(line('.')+1, col('.')) | ||
| 427 | |||
| 428 | " draw the tree | ||
| 429 | silent put =self.nerdtree.root.renderToString() | ||
| 430 | |||
| 431 | " delete the blank line at the top of the buffer | ||
| 432 | silent 1,1delete _ | ||
| 433 | |||
| 434 | " restore the view | ||
| 435 | let old_scrolloff=&scrolloff | ||
| 436 | let &scrolloff=0 | ||
| 437 | call cursor(topLine, 1) | ||
| 438 | normal! zt | ||
| 439 | call cursor(curLine, curCol) | ||
| 440 | let &scrolloff = old_scrolloff | ||
| 441 | |||
| 442 | setlocal readonly nomodifiable | ||
| 443 | endfunction | ||
| 444 | |||
| 445 | |||
| 446 | " FUNCTION: UI.renderViewSavingPosition {{{1 | ||
| 447 | " Renders the tree and ensures the cursor stays on the current node or the | ||
| 448 | " current nodes parent if it is no longer available upon re-rendering | ||
| 449 | function! s:UI.renderViewSavingPosition() | ||
| 450 | let currentNode = g:NERDTreeFileNode.GetSelected() | ||
| 451 | |||
| 452 | " go up the tree till we find a node that will be visible or till we run | ||
| 453 | " out of nodes | ||
| 454 | while currentNode !=# {} && !currentNode.isVisible() && !currentNode.isRoot() | ||
| 455 | let currentNode = currentNode.parent | ||
| 456 | endwhile | ||
| 457 | |||
| 458 | call self.render() | ||
| 459 | |||
| 460 | if currentNode !=# {} | ||
| 461 | call currentNode.putCursorHere(0, 0) | ||
| 462 | endif | ||
| 463 | endfunction | ||
| 464 | |||
| 465 | " FUNCTION: s:UI.toggleHelp() {{{1 | ||
| 466 | function! s:UI.toggleHelp() | ||
| 467 | let self._showHelp = !self._showHelp | ||
| 468 | endfunction | ||
| 469 | |||
| 470 | " FUNCTION: s:UI.toggleIgnoreFilter() {{{1 | ||
| 471 | " toggles the use of the NERDTreeIgnore option | ||
| 472 | function! s:UI.toggleIgnoreFilter() | ||
| 473 | let self._ignoreEnabled = !self._ignoreEnabled | ||
| 474 | call self.renderViewSavingPosition() | ||
| 475 | call self.centerView() | ||
| 476 | endfunction | ||
| 477 | |||
| 478 | " FUNCTION: s:UI.toggleShowBookmarks() {{{1 | ||
| 479 | " Toggle the visibility of the Bookmark table. | ||
| 480 | function! s:UI.toggleShowBookmarks() | ||
| 481 | let self._showBookmarks = !self._showBookmarks | ||
| 482 | |||
| 483 | if self.getShowBookmarks() | ||
| 484 | call self.nerdtree.render() | ||
| 485 | call g:NERDTree.CursorToBookmarkTable() | ||
| 486 | else | ||
| 487 | |||
| 488 | if empty(g:NERDTreeFileNode.GetSelected()) | ||
| 489 | call b:NERDTree.root.putCursorHere(0, 0) | ||
| 490 | normal! 0 | ||
| 491 | endif | ||
| 492 | |||
| 493 | call self.renderViewSavingPosition() | ||
| 494 | endif | ||
| 495 | |||
| 496 | call self.centerView() | ||
| 497 | endfunction | ||
| 498 | |||
| 499 | " FUNCTION: s:UI.toggleShowFiles() {{{1 | ||
| 500 | " toggles the display of hidden files | ||
| 501 | function! s:UI.toggleShowFiles() | ||
| 502 | let self._showFiles = !self._showFiles | ||
| 503 | call self.renderViewSavingPosition() | ||
| 504 | call self.centerView() | ||
| 505 | endfunction | ||
| 506 | |||
| 507 | " FUNCTION: s:UI.toggleShowHidden() {{{1 | ||
| 508 | " toggles the display of hidden files | ||
| 509 | function! s:UI.toggleShowHidden() | ||
| 510 | let self._showHidden = !self._showHidden | ||
| 511 | call self.renderViewSavingPosition() | ||
| 512 | call self.centerView() | ||
| 513 | endfunction | ||
| 514 | |||
| 515 | " FUNCTION: s:UI.toggleZoom() {{{1 | ||
| 516 | " zoom (maximize/minimize) the NERDTree window | ||
| 517 | function! s:UI.toggleZoom() | ||
| 518 | if exists('b:NERDTreeZoomed') && b:NERDTreeZoomed | ||
| 519 | call nerdtree#exec('silent vertical resize '. g:NERDTreeWinSize, 1) | ||
| 520 | let b:NERDTreeZoomed = 0 | ||
| 521 | else | ||
| 522 | call nerdtree#exec('vertical resize '. get(g:, 'NERDTreeWinSizeMax', ''), 1) | ||
| 523 | let b:NERDTreeZoomed = 1 | ||
| 524 | endif | ||
| 525 | endfunction | ||
| 526 | |||
| 527 | " FUNCTION: s:UI.UpDirLine() {{{1 | ||
| 528 | function! s:UI.UpDirLine() | ||
| 529 | return '.. (up a dir)' | ||
| 530 | endfunction | ||
| 531 | |||
| 532 | " vim: set sw=4 sts=4 et fdm=marker: | ||
