tomkersten-vixploder 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. data/History.txt +4 -0
  2. data/Manifest.txt +105 -0
  3. data/PostInstall.txt +21 -0
  4. data/README.rdoc +131 -0
  5. data/Rakefile +21 -0
  6. data/bin/256colors2.pl +63 -0
  7. data/bin/colortest +365 -0
  8. data/bin/vixplode +10 -0
  9. data/lib/dotfiles/aliases +30 -0
  10. data/lib/dotfiles/gvimrc +20 -0
  11. data/lib/dotfiles/vim/.VimballRecord +2 -0
  12. data/lib/dotfiles/vim/after/ftplugin/actionscript_snippets.vim +9 -0
  13. data/lib/dotfiles/vim/after/ftplugin/aspvbs_snippets.vim +17 -0
  14. data/lib/dotfiles/vim/after/ftplugin/c_snippets.vim +58 -0
  15. data/lib/dotfiles/vim/after/ftplugin/css_snippets.vim +30 -0
  16. data/lib/dotfiles/vim/after/ftplugin/django_model_snippets.vim +61 -0
  17. data/lib/dotfiles/vim/after/ftplugin/django_template_snippets.vim +32 -0
  18. data/lib/dotfiles/vim/after/ftplugin/f-script_snippets.vim +14 -0
  19. data/lib/dotfiles/vim/after/ftplugin/haskell_snippets.vim +9 -0
  20. data/lib/dotfiles/vim/after/ftplugin/html_snippets.vim +57 -0
  21. data/lib/dotfiles/vim/after/ftplugin/java_snippets.vim +52 -0
  22. data/lib/dotfiles/vim/after/ftplugin/javascript_snippets.vim +10 -0
  23. data/lib/dotfiles/vim/after/ftplugin/latex_snippets.vim +13 -0
  24. data/lib/dotfiles/vim/after/ftplugin/logo_snippets.vim +9 -0
  25. data/lib/dotfiles/vim/after/ftplugin/markdown_snippets.vim +10 -0
  26. data/lib/dotfiles/vim/after/ftplugin/movable_type_snippets.vim +14 -0
  27. data/lib/dotfiles/vim/after/ftplugin/objc_snippets.vim +53 -0
  28. data/lib/dotfiles/vim/after/ftplugin/ocaml_snippets.vim +26 -0
  29. data/lib/dotfiles/vim/after/ftplugin/perl_snippets.vim +23 -0
  30. data/lib/dotfiles/vim/after/ftplugin/php_snippets.vim +30 -0
  31. data/lib/dotfiles/vim/after/ftplugin/phpdoc_snippets.vim +19 -0
  32. data/lib/dotfiles/vim/after/ftplugin/propel_snippets.vim +14 -0
  33. data/lib/dotfiles/vim/after/ftplugin/python_snippets.vim +202 -0
  34. data/lib/dotfiles/vim/after/ftplugin/rails_snippets.vim +54 -0
  35. data/lib/dotfiles/vim/after/ftplugin/ruby_snippets.vim +32 -0
  36. data/lib/dotfiles/vim/after/ftplugin/sh_snippets.vim +12 -0
  37. data/lib/dotfiles/vim/after/ftplugin/slate_snippets.vim +19 -0
  38. data/lib/dotfiles/vim/after/ftplugin/smarty_snippets.vim +35 -0
  39. data/lib/dotfiles/vim/after/ftplugin/symfony_snippets.vim +21 -0
  40. data/lib/dotfiles/vim/after/ftplugin/tcl_snippets.vim +14 -0
  41. data/lib/dotfiles/vim/after/ftplugin/template_toolkit_snippets.vim +13 -0
  42. data/lib/dotfiles/vim/after/ftplugin/tex_snippets.vim +13 -0
  43. data/lib/dotfiles/vim/after/ftplugin/xhtml_snippets.vim +48 -0
  44. data/lib/dotfiles/vim/autoload/fakeclip.vim +253 -0
  45. data/lib/dotfiles/vim/autoload/rails.vim +4377 -0
  46. data/lib/dotfiles/vim/autoload/rubycomplete.vim +802 -0
  47. data/lib/dotfiles/vim/colors/inkpot.vim +212 -0
  48. data/lib/dotfiles/vim/colors/ir_black.vim +212 -0
  49. data/lib/dotfiles/vim/colors/ir_black_mod.vim +213 -0
  50. data/lib/dotfiles/vim/colors/railscasts.vim +100 -0
  51. data/lib/dotfiles/vim/colors/rubyblue.vim +74 -0
  52. data/lib/dotfiles/vim/colors/twilight.vim +75 -0
  53. data/lib/dotfiles/vim/colors/twilight2.vim +74 -0
  54. data/lib/dotfiles/vim/colors/wombat256.vim +302 -0
  55. data/lib/dotfiles/vim/compiler/eruby.vim +41 -0
  56. data/lib/dotfiles/vim/compiler/ruby.vim +68 -0
  57. data/lib/dotfiles/vim/compiler/rubyunit.vim +35 -0
  58. data/lib/dotfiles/vim/doc/NERD_tree.txt +1235 -0
  59. data/lib/dotfiles/vim/doc/fakeclip.txt +190 -0
  60. data/lib/dotfiles/vim/doc/matchit.txt +406 -0
  61. data/lib/dotfiles/vim/doc/project.txt +710 -0
  62. data/lib/dotfiles/vim/doc/rails.txt +1123 -0
  63. data/lib/dotfiles/vim/doc/snippets_emu.txt +354 -0
  64. data/lib/dotfiles/vim/doc/surround.txt +218 -0
  65. data/lib/dotfiles/vim/doc/tags +433 -0
  66. data/lib/dotfiles/vim/filetype.vim +13 -0
  67. data/lib/dotfiles/vim/ftdetect/gist.vim +3 -0
  68. data/lib/dotfiles/vim/ftdetect/ruby.vim +14 -0
  69. data/lib/dotfiles/vim/ftplugin/eruby.vim +101 -0
  70. data/lib/dotfiles/vim/ftplugin/ruby.vim +230 -0
  71. data/lib/dotfiles/vim/indent/eruby.vim +73 -0
  72. data/lib/dotfiles/vim/indent/ruby.vim +373 -0
  73. data/lib/dotfiles/vim/plugin/NERD_tree.vim +3536 -0
  74. data/lib/dotfiles/vim/plugin/comments.vim +321 -0
  75. data/lib/dotfiles/vim/plugin/fakeclip.vim +174 -0
  76. data/lib/dotfiles/vim/plugin/fuzzyfinder.vim +1676 -0
  77. data/lib/dotfiles/vim/plugin/fuzzyfinder_textmate.vim +150 -0
  78. data/lib/dotfiles/vim/plugin/gist.vim +241 -0
  79. data/lib/dotfiles/vim/plugin/gitdiff.vim +141 -0
  80. data/lib/dotfiles/vim/plugin/matchit.vim +812 -0
  81. data/lib/dotfiles/vim/plugin/mru.vim +787 -0
  82. data/lib/dotfiles/vim/plugin/rails.vim +310 -0
  83. data/lib/dotfiles/vim/plugin/rspec.vim +12 -0
  84. data/lib/dotfiles/vim/plugin/snippets.vim +17 -0
  85. data/lib/dotfiles/vim/plugin/snippetsEmu.vim +973 -0
  86. data/lib/dotfiles/vim/plugin/supertab.vim +531 -0
  87. data/lib/dotfiles/vim/plugin/surround.vim +632 -0
  88. data/lib/dotfiles/vim/ref_vimrc +80 -0
  89. data/lib/dotfiles/vim/ruby/fuzzy_file_finder.rb +353 -0
  90. data/lib/dotfiles/vim/syntax/eruby.vim +85 -0
  91. data/lib/dotfiles/vim/syntax/haml.vim +113 -0
  92. data/lib/dotfiles/vim/syntax/mkd.vim +86 -0
  93. data/lib/dotfiles/vim/syntax/ruby.vim +324 -0
  94. data/lib/dotfiles/vim/syntax/sass.vim +93 -0
  95. data/lib/dotfiles/vimrc +269 -0
  96. data/lib/vixplode/cli.rb +73 -0
  97. data/lib/vixploder.rb +6 -0
  98. data/script/console +10 -0
  99. data/script/destroy +14 -0
  100. data/script/generate +14 -0
  101. data/spec/spec.opts +1 -0
  102. data/spec/spec_helper.rb +10 -0
  103. data/spec/vixplode_cli_spec.rb +15 -0
  104. data/spec/vixploder_spec.rb +7 -0
  105. data/tasks/rspec.rake +21 -0
  106. metadata +202 -8
@@ -0,0 +1,3536 @@
1
+ " ============================================================================
2
+ " File: NERD_tree.vim
3
+ " Description: vim global plugin that provides a nice tree explorer
4
+ " Maintainer: Martin Grenfell <martin_grenfell at msn dot com>
5
+ " Last Change: 20 July, 2008
6
+ " License: This program is free software. It comes without any warranty,
7
+ " to the extent permitted by applicable law. You can redistribute
8
+ " it and/or modify it under the terms of the Do What The Fuck You
9
+ " Want To Public License, Version 2, as published by Sam Hocevar.
10
+ " See http://sam.zoy.org/wtfpl/COPYING for more details.
11
+ "
12
+ " ============================================================================
13
+ let s:NERD_tree_version = '2.14.0'
14
+
15
+ " SECTION: Script init stuff {{{1
16
+ "============================================================
17
+ if exists("loaded_nerd_tree")
18
+ finish
19
+ endif
20
+ if v:version < 700
21
+ echoerr "NERDTree: this plugin requires vim >= 7. DOWNLOAD IT! You'll thank me later!"
22
+ finish
23
+ endif
24
+ let loaded_nerd_tree = 1
25
+
26
+ "for line continuation - i.e dont want C in &cpo
27
+ let s:old_cpo = &cpo
28
+ set cpo&vim
29
+
30
+ "Function: s:initVariable() function {{{2
31
+ "This function is used to initialise a given variable to a given value. The
32
+ "variable is only initialised if it does not exist prior
33
+ "
34
+ "Args:
35
+ "var: the name of the var to be initialised
36
+ "value: the value to initialise var to
37
+ "
38
+ "Returns:
39
+ "1 if the var is set, 0 otherwise
40
+ function! s:initVariable(var, value)
41
+ if !exists(a:var)
42
+ exec 'let ' . a:var . ' = ' . "'" . a:value . "'"
43
+ return 1
44
+ endif
45
+ return 0
46
+ endfunction
47
+
48
+ "SECTION: Init variable calls and other random constants {{{2
49
+ call s:initVariable("g:NERDChristmasTree", 1)
50
+ call s:initVariable("g:NERDTreeAutoCenter", 1)
51
+ call s:initVariable("g:NERDTreeAutoCenterThreshold", 3)
52
+ call s:initVariable("g:NERDTreeCaseSensitiveSort", 0)
53
+ call s:initVariable("g:NERDTreeChDirMode", 0)
54
+ if !exists("g:NERDTreeIgnore")
55
+ let g:NERDTreeIgnore = ['\~$']
56
+ endif
57
+ call s:initVariable("g:NERDTreeHighlightCursorline", 1)
58
+ call s:initVariable("g:NERDTreeBookmarksFile", expand('$HOME') . '/.NERDTreeBookmarks')
59
+ call s:initVariable("g:NERDTreeMouseMode", 1)
60
+ call s:initVariable("g:NERDTreeNotificationThreshold", 100)
61
+ call s:initVariable("g:NERDTreeQuitOnOpen", 0)
62
+ call s:initVariable("g:NERDTreeShowBookmarks", 0)
63
+ call s:initVariable("g:NERDTreeShowFiles", 1)
64
+ call s:initVariable("g:NERDTreeShowHidden", 0)
65
+ call s:initVariable("g:NERDTreeShowLineNumbers", 0)
66
+ call s:initVariable("g:NERDTreeSortDirs", 1)
67
+
68
+ if !exists("g:NERDTreeSortOrder")
69
+ let g:NERDTreeSortOrder = ['\/$', '*', '\.swp$', '\.bak$', '\~$']
70
+ else
71
+ "if there isnt a * in the sort sequence then add one
72
+ if count(g:NERDTreeSortOrder, '*') < 1
73
+ call add(g:NERDTreeSortOrder, '*')
74
+ endif
75
+ endif
76
+
77
+ "we need to use this number many times for sorting... so we calculate it only
78
+ "once here
79
+ let s:NERDTreeSortStarIndex = index(g:NERDTreeSortOrder, '*')
80
+
81
+ call s:initVariable("g:NERDTreeWinPos", "left")
82
+ call s:initVariable("g:NERDTreeWinSize", 31)
83
+
84
+ let s:running_windows = has("win16") || has("win32") || has("win64")
85
+
86
+ "init the shell commands that will be used to copy nodes, and remove dir trees
87
+ "
88
+ "Note: the space after the command is important
89
+ if s:running_windows
90
+ call s:initVariable("g:NERDTreeRemoveDirCmd", 'rmdir /s /q ')
91
+ else
92
+ call s:initVariable("g:NERDTreeRemoveDirCmd", 'rm -rf ')
93
+ call s:initVariable("g:NERDTreeCopyCmd", 'cp -r ')
94
+ endif
95
+
96
+
97
+ "SECTION: Init variable calls for key mappings {{{2
98
+ call s:initVariable("g:NERDTreeMapActivateNode", "o")
99
+ call s:initVariable("g:NERDTreeMapChangeRoot", "C")
100
+ call s:initVariable("g:NERDTreeMapChdir", "cd")
101
+ call s:initVariable("g:NERDTreeMapCloseChildren", "X")
102
+ call s:initVariable("g:NERDTreeMapCloseDir", "x")
103
+ call s:initVariable("g:NERDTreeMapDeleteBookmark", "D")
104
+ call s:initVariable("g:NERDTreeMapExecute", "!")
105
+ call s:initVariable("g:NERDTreeMapFilesystemMenu", "m")
106
+ call s:initVariable("g:NERDTreeMapHelp", "?")
107
+ call s:initVariable("g:NERDTreeMapJumpFirstChild", "K")
108
+ call s:initVariable("g:NERDTreeMapJumpLastChild", "J")
109
+ call s:initVariable("g:NERDTreeMapJumpNextSibling", "<C-j>")
110
+ call s:initVariable("g:NERDTreeMapJumpParent", "p")
111
+ call s:initVariable("g:NERDTreeMapJumpPrevSibling", "<C-k>")
112
+ call s:initVariable("g:NERDTreeMapJumpRoot", "P")
113
+ call s:initVariable("g:NERDTreeMapOpenExpl", "e")
114
+ call s:initVariable("g:NERDTreeMapOpenInTab", "t")
115
+ call s:initVariable("g:NERDTreeMapOpenInTabSilent", "T")
116
+ call s:initVariable("g:NERDTreeMapOpenRecursively", "O")
117
+ call s:initVariable("g:NERDTreeMapOpenSplit", "<tab>")
118
+ call s:initVariable("g:NERDTreeMapPreview", "g" . NERDTreeMapActivateNode)
119
+ call s:initVariable("g:NERDTreeMapPreviewSplit", "g" . NERDTreeMapOpenSplit)
120
+ call s:initVariable("g:NERDTreeMapQuit", "q")
121
+ call s:initVariable("g:NERDTreeMapRefresh", "r")
122
+ call s:initVariable("g:NERDTreeMapRefreshRoot", "R")
123
+ call s:initVariable("g:NERDTreeMapToggleBookmarks", "B")
124
+ call s:initVariable("g:NERDTreeMapToggleFiles", "F")
125
+ call s:initVariable("g:NERDTreeMapToggleFilters", "f")
126
+ call s:initVariable("g:NERDTreeMapToggleHidden", "H")
127
+ call s:initVariable("g:NERDTreeMapUpdir", "u")
128
+ call s:initVariable("g:NERDTreeMapUpdirKeepOpen", "U")
129
+
130
+ "SECTION: Script level variable declaration{{{2
131
+ let s:escape_chars = " \\`\|\"#%&,?()\*^<>"
132
+ let s:NERDTreeWinName = '_NERD_tree_'
133
+
134
+ let s:tree_wid = 2
135
+ let s:tree_markup_reg = '[ \-+~`|]'
136
+ let s:tree_markup_reg_neg = '[^ \-+~`|]'
137
+ let s:tree_up_dir_line = '.. (up a dir)'
138
+
139
+ let s:os_slash = '/'
140
+ if s:running_windows
141
+ let s:os_slash = '\'
142
+ endif
143
+
144
+
145
+ " SECTION: Commands {{{1
146
+ "============================================================
147
+ "init the command that users start the nerd tree with
148
+ command! -n=? -complete=dir NERDTree :call s:initNerdTree('<args>')
149
+ command! -n=? -complete=dir NERDTreeToggle :call s:toggle('<args>')
150
+ command! -n=0 NERDTreeClose :call s:closeTreeIfOpen()
151
+ command! -n=1 -complete=customlist,s:completeBookmarks NERDTreeFromBookmark call s:initNerdTree('<args>')
152
+ " SECTION: Auto commands {{{1
153
+ "============================================================
154
+ "Save the cursor position whenever we close the nerd tree
155
+ exec "autocmd BufWinLeave *". s:NERDTreeWinName ." call <SID>saveScreenState()"
156
+ "cache bookmarks when vim loads
157
+ autocmd VimEnter * call s:Bookmark.CacheBookmarks(0)
158
+
159
+ "SECTION: Classes {{{1
160
+ "============================================================
161
+ "CLASS: Bookmark {{{2
162
+ "============================================================
163
+ let s:Bookmark = {}
164
+ " FUNCTION: Bookmark.AddBookmark(name, path) {{{3
165
+ " Class method to add a new bookmark to the list, if a previous bookmark exists
166
+ " with the same name, just update the path for that bookmark
167
+ function! s:Bookmark.AddBookmark(name, path)
168
+ for i in s:Bookmark.Bookmarks()
169
+ if i.name == a:name
170
+ let i.path = a:path
171
+ return
172
+ endif
173
+ endfor
174
+ call add(s:Bookmark.Bookmarks(), s:Bookmark.New(a:name, a:path))
175
+ call s:Bookmark.Sort()
176
+ endfunction
177
+ " Function: Bookmark.Bookmarks() {{{3
178
+ " Class method to get all bookmarks. Lazily initializes the bookmarks global
179
+ " variable
180
+ function! s:Bookmark.Bookmarks()
181
+ if !exists("g:NERDTreeBookmarks")
182
+ let g:NERDTreeBookmarks = []
183
+ endif
184
+ return g:NERDTreeBookmarks
185
+ endfunction
186
+ " Function: Bookmark.BookmarkExistsFor(name) {{{3
187
+ " class method that returns 1 if a bookmark with the given name is found, 0
188
+ " otherwise
189
+ function! s:Bookmark.BookmarkExistsFor(name)
190
+ try
191
+ call s:Bookmark.BookmarkFor(a:name)
192
+ return 1
193
+ catch /NERDTree.BookmarkNotFound/
194
+ return 0
195
+ endtry
196
+ endfunction
197
+ " Function: Bookmark.BookmarkFor(name) {{{3
198
+ " Class method to get the bookmark that has the given name. {} is return if no
199
+ " bookmark is found
200
+ function! s:Bookmark.BookmarkFor(name)
201
+ for i in s:Bookmark.Bookmarks()
202
+ if i.name == a:name
203
+ return i
204
+ endif
205
+ endfor
206
+ throw "NERDTree.BookmarkNotFound exception: no bookmark found for name: \"". a:name .'"'
207
+ endfunction
208
+ " Function: Bookmark.BookmarkNames() {{{3
209
+ " Class method to return an array of all bookmark names
210
+ function! s:Bookmark.BookmarkNames()
211
+ let names = []
212
+ for i in s:Bookmark.Bookmarks()
213
+ call add(names, i.name)
214
+ endfor
215
+ return names
216
+ endfunction
217
+ " FUNCTION: Bookmark.CacheBookmarks(silent) {{{3
218
+ " Class method to read all bookmarks from the bookmarks file intialize
219
+ " bookmark objects for each one.
220
+ "
221
+ " Args:
222
+ " silent - dont echo an error msg if invalid bookmarks are found
223
+ function! s:Bookmark.CacheBookmarks(silent)
224
+ if filereadable(g:NERDTreeBookmarksFile)
225
+ let g:NERDTreeBookmarks = []
226
+ let g:NERDTreeInvalidBookmarks = []
227
+ let bookmarkStrings = readfile(g:NERDTreeBookmarksFile)
228
+ let invalidBookmarksFound = 0
229
+ for i in bookmarkStrings
230
+
231
+ "ignore blank lines
232
+ if i != ''
233
+
234
+ let name = substitute(i, '^\(.\{-}\) .*$', '\1', '')
235
+ let path = substitute(i, '^.\{-} \(.*\)$', '\1', '')
236
+
237
+ try
238
+ let bookmark = s:Bookmark.New(name, s:Path.New(path))
239
+ call add(g:NERDTreeBookmarks, bookmark)
240
+ catch /NERDTree.Path.InvalidArguments/
241
+ call add(g:NERDTreeInvalidBookmarks, i)
242
+ let invalidBookmarksFound += 1
243
+ endtry
244
+ endif
245
+ endfor
246
+ if invalidBookmarksFound
247
+ call s:Bookmark.Write()
248
+ if !a:silent
249
+ call s:echo(invalidBookmarksFound . " invalid bookmarks were read. See :help NERDTreeInvalidBookmarks for info.")
250
+ endif
251
+ endif
252
+ call s:Bookmark.Sort()
253
+ endif
254
+ endfunction
255
+ " FUNCTION: Bookmark.compareTo(otherbookmark) {{{3
256
+ " Compare these two bookmarks for sorting purposes
257
+ function! s:Bookmark.compareTo(otherbookmark)
258
+ return a:otherbookmark.name < self.name
259
+ endfunction
260
+ " FUNCTION: Bookmark.ClearAll() {{{3
261
+ " Class method to delete all bookmarks.
262
+ function! s:Bookmark.ClearAll()
263
+ for i in s:Bookmark.Bookmarks()
264
+ call i.delete()
265
+ endfor
266
+ call s:Bookmark.Write()
267
+ endfunction
268
+ " FUNCTION: Bookmark.delete() {{{3
269
+ " Delete this bookmark. If the node for this bookmark is under the current
270
+ " root, then recache bookmarks for its Path object
271
+ function! s:Bookmark.delete()
272
+ let node = {}
273
+ try
274
+ let node = self.getNode(1)
275
+ catch /NERDTree.BookmarkedNodeNotFound/
276
+ endtry
277
+ call remove(s:Bookmark.Bookmarks(), index(s:Bookmark.Bookmarks(), self))
278
+ if !empty(node)
279
+ call node.path.cacheDisplayString()
280
+ endif
281
+ call s:Bookmark.Write()
282
+ endfunction
283
+ " FUNCTION: Bookmark.getNode(searchFromAbsoluteRoot) {{{3
284
+ " Gets the treenode for this bookmark
285
+ "
286
+ " Args:
287
+ " searchFromAbsoluteRoot: specifies whether we should search from the current
288
+ " tree root, or the highest cached node
289
+ function! s:Bookmark.getNode(searchFromAbsoluteRoot)
290
+ let searchRoot = a:searchFromAbsoluteRoot ? s:TreeDirNode.AbsoluteTreeRoot() : t:NERDTreeRoot
291
+ let targetNode = searchRoot.findNode(self.path)
292
+ if empty(targetNode)
293
+ throw "NERDTree.BookmarkedNodeNotFound no node was found for bookmark: " . self.name
294
+ endif
295
+ return targetNode
296
+ endfunction
297
+ " FUNCTION: Bookmark.GetNodeForName(name, searchFromAbsoluteRoot) {{{3
298
+ " Class method that finds the bookmark with the given name and returns the
299
+ " treenode for it.
300
+ function! s:Bookmark.GetNodeForName(name, searchFromAbsoluteRoot)
301
+ let bookmark = s:Bookmark.BookmarkFor(a:name)
302
+ return bookmark.getNode(a:searchFromAbsoluteRoot)
303
+ endfunction
304
+ " Function: Bookmark.InvalidBookmarks() {{{3
305
+ " Class method to get all invalid bookmark strings read from the bookmarks
306
+ " file
307
+ function! s:Bookmark.InvalidBookmarks()
308
+ if !exists("g:NERDTreeInvalidBookmarks")
309
+ let g:NERDTreeInvalidBookmarks = []
310
+ endif
311
+ return g:NERDTreeInvalidBookmarks
312
+ endfunction
313
+ " FUNCTION: Bookmark.mustExist() {{{3
314
+ function! s:Bookmark.mustExist()
315
+ if !self.path.exists()
316
+ call s:Bookmark.CacheBookmarks(1)
317
+ throw "NERDTree.BookmarkPointsToInvalidLocation exception: the bookmark \"".
318
+ \ self.name ."\" points to a non existing location: \"". self.path.strForOS(0)
319
+ endif
320
+ endfunction
321
+ " FUNCTION: Bookmark.New(name, path) {{{3
322
+ " Create a new bookmark object with the given name and path object
323
+ function! s:Bookmark.New(name, path)
324
+ if a:name =~ ' '
325
+ throw "NERDTree.IllegalBookmarkName illegal name:" . a:name
326
+ endif
327
+
328
+ let newBookmark = copy(self)
329
+ let newBookmark.name = a:name
330
+ let newBookmark.path = a:path
331
+ return newBookmark
332
+ endfunction
333
+ " Function: Bookmark.setPath(path) {{{3
334
+ " makes this bookmark point to the given path
335
+ function! s:Bookmark.setPath(path)
336
+ let self.path = a:path
337
+ endfunction
338
+ " Function: Bookmark.Sort() {{{3
339
+ " Class method that sorts all bookmarks
340
+ function! s:Bookmark.Sort()
341
+ let CompareFunc = function("s:compareBookmarks")
342
+ call sort(s:Bookmark.Bookmarks(), CompareFunc)
343
+ endfunction
344
+ " Function: Bookmark.str() {{{3
345
+ " Get the string that should be rendered in the view for this bookmark
346
+ function! s:Bookmark.str()
347
+ let pathStrMaxLen = winwidth(s:getTreeWinNum()) - 4 - len(self.name)
348
+ if &nu
349
+ let pathStrMaxLen = pathStrMaxLen - &numberwidth
350
+ endif
351
+
352
+ let pathStr = self.path.strForOS(0)
353
+ if len(pathStr) > pathStrMaxLen
354
+ let pathStr = '<' . strpart(pathStr, len(pathStr) - pathStrMaxLen)
355
+ endif
356
+ return '>' . self.name . ' ' . pathStr
357
+ endfunction
358
+ " FUNCTION: Bookmark.toRoot() {{{3
359
+ " Make the node for this bookmark the new tree root
360
+ function! s:Bookmark.toRoot()
361
+ if self.validate()
362
+ try
363
+ let targetNode = self.getNode(1)
364
+ catch /NERDTree.BookmarkedNodeNotFound/
365
+ let targetNode = s:TreeFileNode.New(s:Bookmark.BookmarkFor(self.name).path)
366
+ endtry
367
+ call targetNode.makeRoot()
368
+ call s:renderView()
369
+ call s:putCursorOnNode(targetNode, 0, 0)
370
+ endif
371
+ endfunction
372
+ " FUNCTION: Bookmark.ToRoot(name) {{{3
373
+ " Make the node for this bookmark the new tree root
374
+ function! s:Bookmark.ToRoot(name)
375
+ let bookmark = s:Bookmark.BookmarkFor(a:name)
376
+ call bookmark.toRoot()
377
+ endfunction
378
+
379
+
380
+ "FUNCTION: Bookmark.validate() {{{3
381
+ function! s:Bookmark.validate()
382
+ if self.path.exists()
383
+ return 1
384
+ else
385
+ call s:Bookmark.CacheBookmarks(1)
386
+ call s:renderView()
387
+ call s:echo(self.name . "now points to an invalid location. See :help NERDTreeInvalidBookmarks for info.")
388
+ return 0
389
+ endif
390
+ endfunction
391
+
392
+ " Function: Bookmark.Write() {{{3
393
+ " Class method to write all bookmarks to the bookmarks file
394
+ function! s:Bookmark.Write()
395
+ let bookmarkStrings = []
396
+ for i in s:Bookmark.Bookmarks()
397
+ call add(bookmarkStrings, i.name . ' ' . i.path.strForOS(0))
398
+ endfor
399
+
400
+ "add a blank line before the invalid ones
401
+ call add(bookmarkStrings, "")
402
+
403
+ for j in s:Bookmark.InvalidBookmarks()
404
+ call add(bookmarkStrings, j)
405
+ endfor
406
+ call writefile(bookmarkStrings, g:NERDTreeBookmarksFile)
407
+ endfunction
408
+ "CLASS: TreeFileNode {{{2
409
+ "This class is the parent of the TreeDirNode class and constitures the
410
+ "'Component' part of the composite design pattern between the treenode
411
+ "classes.
412
+ "============================================================
413
+ let s:TreeFileNode = {}
414
+ "FUNCTION: TreeFileNode.bookmark(name) {{{3
415
+ "bookmark this node with a:name
416
+ function! s:TreeFileNode.bookmark(name)
417
+ try
418
+ let oldMarkedNode = s:Bookmark.GetNodeForName(a:name, 1)
419
+ call oldMarkedNode.path.cacheDisplayString()
420
+ catch /NERDTree.Bookmark\(DoesntExist\|NotFound\)/
421
+ endtry
422
+
423
+ call s:Bookmark.AddBookmark(a:name, self.path)
424
+ call self.path.cacheDisplayString()
425
+ call s:Bookmark.Write()
426
+ endfunction
427
+ "FUNCTION: TreeFileNode.cacheParent() {{{3
428
+ "initializes self.parent if it isnt already
429
+ function! s:TreeFileNode.cacheParent()
430
+ if empty(self.parent)
431
+ let parentPath = self.path.getParent()
432
+ if parentPath.equals(self.path)
433
+ throw "NERDTree.CannotCacheParent exception: already at root"
434
+ endif
435
+ let self.parent = s:TreeFileNode.New(parentPath)
436
+ endif
437
+ endfunction
438
+ "FUNCTION: TreeFileNode.compareNodes {{{3
439
+ "This is supposed to be a class level method but i cant figure out how to
440
+ "get func refs to work from a dict..
441
+ "
442
+ "A class level method that compares two nodes
443
+ "
444
+ "Args:
445
+ "n1, n2: the 2 nodes to compare
446
+ function! s:compareNodes(n1, n2)
447
+ return a:n1.path.compareTo(a:n2.path)
448
+ endfunction
449
+
450
+ "FUNCTION: TreeFileNode.clearBoomarks() {{{3
451
+ function! s:TreeFileNode.clearBoomarks()
452
+ for i in s:Bookmark.Bookmarks()
453
+ if i.path.equals(self.path)
454
+ call i.delete()
455
+ end
456
+ endfor
457
+ call self.path.cacheDisplayString()
458
+ endfunction
459
+ "FUNCTION: TreeFileNode.copy(dest) {{{3
460
+ function! s:TreeFileNode.copy(dest)
461
+ call self.path.copy(a:dest)
462
+ let newPath = s:Path.New(a:dest)
463
+ let parent = t:NERDTreeRoot.findNode(newPath.getParent())
464
+ if !empty(parent)
465
+ call parent.refresh()
466
+ endif
467
+ return parent.findNode(newPath)
468
+ endfunction
469
+
470
+ "FUNCTION: TreeFileNode.delete {{{3
471
+ "Removes this node from the tree and calls the Delete method for its path obj
472
+ function! s:TreeFileNode.delete()
473
+ call self.path.delete()
474
+ call self.parent.removeChild(self)
475
+ endfunction
476
+
477
+ "FUNCTION: TreeFileNode.equals(treenode) {{{3
478
+ "
479
+ "Compares this treenode to the input treenode and returns 1 if they are the
480
+ "same node.
481
+ "
482
+ "Use this method instead of == because sometimes when the treenodes contain
483
+ "many children, vim seg faults when doing ==
484
+ "
485
+ "Args:
486
+ "treenode: the other treenode to compare to
487
+ function! s:TreeFileNode.equals(treenode)
488
+ return self.path.str(1) == a:treenode.path.str(1)
489
+ endfunction
490
+
491
+ "FUNCTION: TreeFileNode.findNode(path) {{{3
492
+ "Returns self if this node.path.Equals the given path.
493
+ "Returns {} if not equal.
494
+ "
495
+ "Args:
496
+ "path: the path object to compare against
497
+ function! s:TreeFileNode.findNode(path)
498
+ if a:path.equals(self.path)
499
+ return self
500
+ endif
501
+ return {}
502
+ endfunction
503
+ "FUNCTION: TreeFileNode.findOpenDirSiblingWithVisibleChildren(direction) {{{3
504
+ "
505
+ "Finds the next sibling for this node in the indicated direction. This sibling
506
+ "must be a directory and may/may not have children as specified.
507
+ "
508
+ "Args:
509
+ "direction: 0 if you want to find the previous sibling, 1 for the next sibling
510
+ "
511
+ "Return:
512
+ "a treenode object or {} if no appropriate sibling could be found
513
+ function! s:TreeFileNode.findOpenDirSiblingWithVisibleChildren(direction)
514
+ "if we have no parent then we can have no siblings
515
+ if self.parent != {}
516
+ let nextSibling = self.findSibling(a:direction)
517
+
518
+ while nextSibling != {}
519
+ if nextSibling.path.isDirectory && nextSibling.hasVisibleChildren() && nextSibling.isOpen
520
+ return nextSibling
521
+ endif
522
+ let nextSibling = nextSibling.findSibling(a:direction)
523
+ endwhile
524
+ endif
525
+
526
+ return {}
527
+ endfunction
528
+ "FUNCTION: TreeFileNode.findSibling(direction) {{{3
529
+ "
530
+ "Finds the next sibling for this node in the indicated direction
531
+ "
532
+ "Args:
533
+ "direction: 0 if you want to find the previous sibling, 1 for the next sibling
534
+ "
535
+ "Return:
536
+ "a treenode object or {} if no sibling could be found
537
+ function! s:TreeFileNode.findSibling(direction)
538
+ "if we have no parent then we can have no siblings
539
+ if self.parent != {}
540
+
541
+ "get the index of this node in its parents children
542
+ let siblingIndx = self.parent.getChildIndex(self.path)
543
+
544
+ if siblingIndx != -1
545
+ "move a long to the next potential sibling node
546
+ let siblingIndx = a:direction == 1 ? siblingIndx+1 : siblingIndx-1
547
+
548
+ "keep moving along to the next sibling till we find one that is valid
549
+ let numSiblings = self.parent.getChildCount()
550
+ while siblingIndx >= 0 && siblingIndx < numSiblings
551
+
552
+ "if the next node is not an ignored node (i.e. wont show up in the
553
+ "view) then return it
554
+ if self.parent.children[siblingIndx].path.ignore() == 0
555
+ return self.parent.children[siblingIndx]
556
+ endif
557
+
558
+ "go to next node
559
+ let siblingIndx = a:direction == 1 ? siblingIndx+1 : siblingIndx-1
560
+ endwhile
561
+ endif
562
+ endif
563
+
564
+ return {}
565
+ endfunction
566
+
567
+ "FUNCTION: TreeFileNode.isVisible() {{{3
568
+ "returns 1 if this node should be visible according to the tree filters and
569
+ "hidden file filters (and their on/off status)
570
+ function! s:TreeFileNode.isVisible()
571
+ return !self.path.ignore()
572
+ endfunction
573
+
574
+
575
+ "FUNCTION: TreeFileNode.isRoot() {{{3
576
+ "returns 1 if this node is t:NERDTreeRoot
577
+ function! s:TreeFileNode.isRoot()
578
+ if !s:treeExistsForTab()
579
+ throw "NERDTree.TreeFileNode.IsRoot exception: No tree exists for the current tab"
580
+ endif
581
+ return self.equals(t:NERDTreeRoot)
582
+ endfunction
583
+
584
+ "FUNCTION: TreeFileNode.makeRoot() {{{3
585
+ "Make this node the root of the tree
586
+ function! s:TreeFileNode.makeRoot()
587
+ if self.path.isDirectory
588
+ let t:NERDTreeRoot = self
589
+ else
590
+ call self.cacheParent()
591
+ let t:NERDTreeRoot = self.parent
592
+ endif
593
+
594
+ call t:NERDTreeRoot.open()
595
+
596
+ "change dir to the dir of the new root if instructed to
597
+ if g:NERDTreeChDirMode == 2
598
+ exec "cd " . t:NERDTreeRoot.path.strForEditCmd()
599
+ endif
600
+ endfunction
601
+ "FUNCTION: TreeFileNode.New(path) {{{3
602
+ "Returns a new TreeNode object with the given path and parent
603
+ "
604
+ "Args:
605
+ "path: a path object representing the full filesystem path to the file/dir that the node represents
606
+ function! s:TreeFileNode.New(path)
607
+ if a:path.isDirectory
608
+ return s:TreeDirNode.New(a:path)
609
+ else
610
+ let newTreeNode = {}
611
+ let newTreeNode = copy(self)
612
+ let newTreeNode.path = a:path
613
+ let newTreeNode.parent = {}
614
+ return newTreeNode
615
+ endif
616
+ endfunction
617
+
618
+ "FUNCTION: TreeFileNode.refresh() {{{3
619
+ function! s:TreeFileNode.refresh()
620
+ call self.path.refresh()
621
+ endfunction
622
+ "FUNCTION: TreeFileNode.rename() {{{3
623
+ "Calls the rename method for this nodes path obj
624
+ function! s:TreeFileNode.rename(newName)
625
+ let newName = substitute(a:newName, '\(\\\|\/\)$', '', '')
626
+ call self.path.rename(newName)
627
+ call self.parent.removeChild(self)
628
+
629
+ let parentPath = self.path.getPathTrunk()
630
+ let newParent = t:NERDTreeRoot.findNode(parentPath)
631
+
632
+ if newParent != {}
633
+ call newParent.createChild(self.path, 1)
634
+ call newParent.refresh()
635
+ endif
636
+ endfunction
637
+ "FUNCTION: TreeFileNode.strDisplay() {{{3
638
+ "
639
+ "Returns a string that specifies how the node should be represented as a
640
+ "string
641
+ "
642
+ "Return:
643
+ "a string that can be used in the view to represent this node
644
+ function! s:TreeFileNode.strDisplay()
645
+ return self.path.strDisplay()
646
+ endfunction
647
+
648
+ "CLASS: TreeDirNode {{{2
649
+ "This class is a child of the TreeFileNode class and constitutes the
650
+ "'Composite' part of the composite design pattern between the treenode
651
+ "classes.
652
+ "============================================================
653
+ let s:TreeDirNode = copy(s:TreeFileNode)
654
+ "FUNCTION: TreeDirNode.AbsoluteTreeRoot(){{{3
655
+ "class method that returns the highest cached ancestor of the current root
656
+ function! s:TreeDirNode.AbsoluteTreeRoot()
657
+ let currentNode = t:NERDTreeRoot
658
+ while currentNode.parent != {}
659
+ let currentNode = currentNode.parent
660
+ endwhile
661
+ return currentNode
662
+ endfunction
663
+ "FUNCTION: TreeDirNode.addChild(treenode, inOrder) {{{3
664
+ "Adds the given treenode to the list of children for this node
665
+ "
666
+ "Args:
667
+ "-treenode: the node to add
668
+ "-inOrder: 1 if the new node should be inserted in sorted order
669
+ function! s:TreeDirNode.addChild(treenode, inOrder)
670
+ call add(self.children, a:treenode)
671
+ let a:treenode.parent = self
672
+
673
+ if a:inOrder
674
+ call self.sortChildren()
675
+ endif
676
+ endfunction
677
+
678
+ "FUNCTION: TreeDirNode.close() {{{3
679
+ "Closes this directory
680
+ function! s:TreeDirNode.close()
681
+ let self.isOpen = 0
682
+ endfunction
683
+
684
+ "FUNCTION: TreeDirNode.closeChildren() {{{3
685
+ "Closes all the child dir nodes of this node
686
+ function! s:TreeDirNode.closeChildren()
687
+ for i in self.children
688
+ if i.path.isDirectory
689
+ call i.close()
690
+ call i.closeChildren()
691
+ endif
692
+ endfor
693
+ endfunction
694
+
695
+ "FUNCTION: TreeDirNode.createChild(path, inOrder) {{{3
696
+ "Instantiates a new child node for this node with the given path. The new
697
+ "nodes parent is set to this node.
698
+ "
699
+ "Args:
700
+ "path: a Path object that this node will represent/contain
701
+ "inOrder: 1 if the new node should be inserted in sorted order
702
+ "
703
+ "Returns:
704
+ "the newly created node
705
+ function! s:TreeDirNode.createChild(path, inOrder)
706
+ let newTreeNode = s:TreeFileNode.New(a:path)
707
+ call self.addChild(newTreeNode, a:inOrder)
708
+ return newTreeNode
709
+ endfunction
710
+
711
+ "FUNCTION: TreeDirNode.findNode(path) {{{3
712
+ "Will find one of the children (recursively) that has the given path
713
+ "
714
+ "Args:
715
+ "path: a path object
716
+ function! s:TreeDirNode.findNode(path)
717
+ if a:path.equals(self.path)
718
+ return self
719
+ endif
720
+ if stridx(a:path.str(1), self.path.str(1), 0) == -1
721
+ return {}
722
+ endif
723
+
724
+ if self.path.isDirectory
725
+ for i in self.children
726
+ let retVal = i.findNode(a:path)
727
+ if retVal != {}
728
+ return retVal
729
+ endif
730
+ endfor
731
+ endif
732
+ return {}
733
+ endfunction
734
+
735
+ "FUNCTION: TreeDirNode.getChildCount() {{{3
736
+ "Returns the number of children this node has
737
+ function! s:TreeDirNode.getChildCount()
738
+ return len(self.children)
739
+ endfunction
740
+
741
+ "FUNCTION: TreeDirNode.getChild(path) {{{3
742
+ "Returns child node of this node that has the given path or {} if no such node
743
+ "exists.
744
+ "
745
+ "This function doesnt not recurse into child dir nodes
746
+ "
747
+ "Args:
748
+ "path: a path object
749
+ function! s:TreeDirNode.getChild(path)
750
+ if stridx(a:path.str(1), self.path.str(1), 0) == -1
751
+ return {}
752
+ endif
753
+
754
+ let index = self.getChildIndex(a:path)
755
+ if index == -1
756
+ return {}
757
+ else
758
+ return self.children[index]
759
+ endif
760
+
761
+ endfunction
762
+
763
+ "FUNCTION: TreeDirNode.getChildByIndex(indx, visible) {{{3
764
+ "returns the child at the given index
765
+ "Args:
766
+ "indx: the index to get the child from
767
+ "visible: 1 if only the visible children array should be used, 0 if all the
768
+ "children should be searched.
769
+ function! s:TreeDirNode.getChildByIndex(indx, visible)
770
+ let array_to_search = a:visible? self.getVisibleChildren() : self.children
771
+ if a:indx > len(array_to_search)
772
+ throw "NERDTree.TreeDirNode.InvalidArguments exception. Index is out of bounds."
773
+ endif
774
+ return array_to_search[a:indx]
775
+ endfunction
776
+
777
+ "FUNCTION: TreeDirNode.getChildIndex(path) {{{3
778
+ "Returns the index of the child node of this node that has the given path or
779
+ "-1 if no such node exists.
780
+ "
781
+ "This function doesnt not recurse into child dir nodes
782
+ "
783
+ "Args:
784
+ "path: a path object
785
+ function! s:TreeDirNode.getChildIndex(path)
786
+ if stridx(a:path.str(1), self.path.str(1), 0) == -1
787
+ return -1
788
+ endif
789
+
790
+ "do a binary search for the child
791
+ let a = 0
792
+ let z = self.getChildCount()
793
+ while a < z
794
+ let mid = (a+z)/2
795
+ let diff = a:path.compareTo(self.children[mid].path)
796
+
797
+ if diff == -1
798
+ let z = mid
799
+ elseif diff == 1
800
+ let a = mid+1
801
+ else
802
+ return mid
803
+ endif
804
+ endwhile
805
+ return -1
806
+ endfunction
807
+
808
+ "FUNCTION: TreeDirNode.getVisibleChildCount() {{{3
809
+ "Returns the number of visible children this node has
810
+ function! s:TreeDirNode.getVisibleChildCount()
811
+ return len(self.getVisibleChildren())
812
+ endfunction
813
+
814
+ "FUNCTION: TreeDirNode.getVisibleChildren() {{{3
815
+ "Returns a list of children to display for this node, in the correct order
816
+ "
817
+ "Return:
818
+ "an array of treenodes
819
+ function! s:TreeDirNode.getVisibleChildren()
820
+ let toReturn = []
821
+ for i in self.children
822
+ if i.path.ignore() == 0
823
+ call add(toReturn, i)
824
+ endif
825
+ endfor
826
+ return toReturn
827
+ endfunction
828
+
829
+ "FUNCTION: TreeDirNode.hasVisibleChildren() {{{3
830
+ "returns 1 if this node has any childre, 0 otherwise..
831
+ function! s:TreeDirNode.hasVisibleChildren()
832
+ return self.getVisibleChildCount() != 0
833
+ endfunction
834
+
835
+ "FUNCTION: TreeDirNode._initChildren() {{{3
836
+ "Removes all childen from this node and re-reads them
837
+ "
838
+ "Args:
839
+ "silent: 1 if the function should not echo any "please wait" messages for
840
+ "large directories
841
+ "
842
+ "Return: the number of child nodes read
843
+ function! s:TreeDirNode._initChildren(silent)
844
+ "remove all the current child nodes
845
+ let self.children = []
846
+
847
+ "get an array of all the files in the nodes dir
848
+ let dir = self.path
849
+ let filesStr = globpath(dir.strForGlob(), '*') . "\n" . globpath(dir.strForGlob(), '.*')
850
+ let files = split(filesStr, "\n")
851
+
852
+ if !a:silent && len(files) > g:NERDTreeNotificationThreshold
853
+ call s:echo("Please wait, caching a large dir ...")
854
+ endif
855
+
856
+ let invalidFilesFound = 0
857
+ for i in files
858
+
859
+ "filter out the .. and . directories
860
+ "Note: we must match .. AND ../ cos sometimes the globpath returns
861
+ "../ for path with strange chars (eg $)
862
+ if i !~ '\.\.\/\?$' && i !~ '\.\/\?$'
863
+
864
+ "put the next file in a new node and attach it
865
+ try
866
+ let path = s:Path.New(i)
867
+ call self.createChild(path, 0)
868
+ catch /^NERDTree.Path.\(InvalidArguments\|InvalidFiletype\)/
869
+ let invalidFilesFound += 1
870
+ endtry
871
+ endif
872
+ endfor
873
+
874
+ call self.sortChildren()
875
+
876
+ if !a:silent && len(files) > g:NERDTreeNotificationThreshold
877
+ call s:echo("Please wait, caching a large dir ... DONE (". self.getChildCount() ." nodes cached).")
878
+ endif
879
+
880
+ if invalidFilesFound
881
+ call s:echoWarning(invalidFilesFound . " file(s) could not be loaded into the NERD tree")
882
+ endif
883
+ return self.getChildCount()
884
+ endfunction
885
+ "FUNCTION: TreeDirNode.New(path) {{{3
886
+ "Returns a new TreeNode object with the given path and parent
887
+ "
888
+ "Args:
889
+ "path: a path object representing the full filesystem path to the file/dir that the node represents
890
+ function! s:TreeDirNode.New(path)
891
+ if a:path.isDirectory != 1
892
+ throw "NERDTree.TreeDirNode.InvalidArguments exception. A TreeDirNode object must be instantiated with a directory Path object."
893
+ endif
894
+
895
+ let newTreeNode = copy(self)
896
+ let newTreeNode.path = a:path
897
+
898
+ let newTreeNode.isOpen = 0
899
+ let newTreeNode.children = []
900
+
901
+ let newTreeNode.parent = {}
902
+
903
+ return newTreeNode
904
+ endfunction
905
+ "FUNCTION: TreeDirNode.open() {{{3
906
+ "Reads in all this nodes children
907
+ "
908
+ "Return: the number of child nodes read
909
+ function! s:TreeDirNode.open()
910
+ let self.isOpen = 1
911
+ if self.children == []
912
+ return self._initChildren(0)
913
+ else
914
+ return 0
915
+ endif
916
+ endfunction
917
+
918
+ "FUNCTION: TreeDirNode.openRecursively() {{{3
919
+ "Opens this treenode and all of its children whose paths arent 'ignored'
920
+ "because of the file filters.
921
+ "
922
+ "This method is actually a wrapper for the OpenRecursively2 method which does
923
+ "the work.
924
+ function! s:TreeDirNode.openRecursively()
925
+ call self._openRecursively2(1)
926
+ endfunction
927
+
928
+ "FUNCTION: TreeDirNode._openRecursively2() {{{3
929
+ "Opens this all children of this treenode recursively if either:
930
+ " *they arent filtered by file filters
931
+ " *a:forceOpen is 1
932
+ "
933
+ "Args:
934
+ "forceOpen: 1 if this node should be opened regardless of file filters
935
+ function! s:TreeDirNode._openRecursively2(forceOpen)
936
+ if self.path.ignore() == 0 || a:forceOpen
937
+ let self.isOpen = 1
938
+ if self.children == []
939
+ call self._initChildren(1)
940
+ endif
941
+
942
+ for i in self.children
943
+ if i.path.isDirectory == 1
944
+ call i._openRecursively2(0)
945
+ endif
946
+ endfor
947
+ endif
948
+ endfunction
949
+
950
+ "FUNCTION: TreeDirNode.refresh() {{{3
951
+ function! s:TreeDirNode.refresh()
952
+ call self.path.refresh()
953
+
954
+ "if this node was ever opened, refresh its children
955
+ if self.isOpen || !empty(self.children)
956
+ "go thru all the files/dirs under this node
957
+ let newChildNodes = []
958
+ let invalidFilesFound = 0
959
+ let dir = self.path
960
+ let filesStr = globpath(dir.strForGlob(), '*') . "\n" . globpath(dir.strForGlob(), '.*')
961
+ let files = split(filesStr, "\n")
962
+ for i in files
963
+ if i !~ '\.\.$' && i !~ '\.$'
964
+
965
+ try
966
+ "create a new path and see if it exists in this nodes children
967
+ let path = s:Path.New(i)
968
+ let newNode = self.getChild(path)
969
+ if newNode != {}
970
+ call newNode.refresh()
971
+ call add(newChildNodes, newNode)
972
+
973
+ "the node doesnt exist so create it
974
+ else
975
+ let newNode = s:TreeFileNode.New(path)
976
+ let newNode.parent = self
977
+ call add(newChildNodes, newNode)
978
+ endif
979
+
980
+
981
+ catch /^NERDTree.InvalidArguments/
982
+ let invalidFilesFound = 1
983
+ endtry
984
+ endif
985
+ endfor
986
+
987
+ "swap this nodes children out for the children we just read/refreshed
988
+ let self.children = newChildNodes
989
+ call self.sortChildren()
990
+
991
+ if invalidFilesFound
992
+ call s:echoWarning("some files could not be loaded into the NERD tree")
993
+ endif
994
+ endif
995
+ endfunction
996
+
997
+ "FUNCTION: TreeDirNode.removeChild(treenode) {{{3
998
+ "
999
+ "Removes the given treenode from this nodes set of children
1000
+ "
1001
+ "Args:
1002
+ "treenode: the node to remove
1003
+ "
1004
+ "Throws a NERDTree.TreeDirNode exception if the given treenode is not found
1005
+ function! s:TreeDirNode.removeChild(treenode)
1006
+ for i in range(0, self.getChildCount()-1)
1007
+ if self.children[i].equals(a:treenode)
1008
+ call remove(self.children, i)
1009
+ return
1010
+ endif
1011
+ endfor
1012
+
1013
+ throw "NERDTree.TreeDirNode exception: child node was not found"
1014
+ endfunction
1015
+
1016
+ "FUNCTION: TreeDirNode.sortChildren() {{{3
1017
+ "
1018
+ "Sorts the children of this node according to alphabetical order and the
1019
+ "directory priority.
1020
+ "
1021
+ function! s:TreeDirNode.sortChildren()
1022
+ let CompareFunc = function("s:compareNodes")
1023
+ call sort(self.children, CompareFunc)
1024
+ endfunction
1025
+
1026
+ "FUNCTION: TreeDirNode.toggleOpen() {{{3
1027
+ "Opens this directory if it is closed and vice versa
1028
+ function! s:TreeDirNode.toggleOpen()
1029
+ if self.isOpen == 1
1030
+ call self.close()
1031
+ else
1032
+ call self.open()
1033
+ endif
1034
+ endfunction
1035
+
1036
+ "FUNCTION: TreeDirNode.transplantChild(newNode) {{{3
1037
+ "Replaces the child of this with the given node (where the child node's full
1038
+ "path matches a:newNode's fullpath). The search for the matching node is
1039
+ "non-recursive
1040
+ "
1041
+ "Arg:
1042
+ "newNode: the node to graft into the tree
1043
+ function! s:TreeDirNode.transplantChild(newNode)
1044
+ for i in range(0, self.getChildCount()-1)
1045
+ if self.children[i].equals(a:newNode)
1046
+ let self.children[i] = a:newNode
1047
+ let a:newNode.parent = self
1048
+ break
1049
+ endif
1050
+ endfor
1051
+ endfunction
1052
+ "============================================================
1053
+ "CLASS: Path {{{2
1054
+ "============================================================
1055
+ let s:Path = {}
1056
+ "FUNCTION: Path.bookmarkNames() {{{3
1057
+ function! s:Path.bookmarkNames()
1058
+ if !exists("self._bookmarkNames")
1059
+ call self.cacheDisplayString()
1060
+ endif
1061
+ return self._bookmarkNames
1062
+ endfunction
1063
+ "FUNCTION: Path.cacheDisplayString() {{{3
1064
+ function! s:Path.cacheDisplayString()
1065
+ let self.cachedDisplayString = self.getLastPathComponent(1)
1066
+
1067
+ if self.isExecutable
1068
+ let self.cachedDisplayString = self.cachedDisplayString . '*'
1069
+ endif
1070
+
1071
+ let self._bookmarkNames = []
1072
+ for i in s:Bookmark.Bookmarks()
1073
+ if i.path.equals(self)
1074
+ call add(self._bookmarkNames, i.name)
1075
+ endif
1076
+ endfor
1077
+ if !empty(self._bookmarkNames)
1078
+ let self.cachedDisplayString .= ' {' . join(self._bookmarkNames) . '}'
1079
+ endif
1080
+
1081
+ if self.isSymLink
1082
+ let self.cachedDisplayString .= ' -> ' . self.symLinkDest
1083
+ endif
1084
+
1085
+ if self.isReadOnly
1086
+ let self.cachedDisplayString .= ' [RO]'
1087
+ endif
1088
+ endfunction
1089
+ "FUNCTION: Path.changeToDir() {{{3
1090
+ function! s:Path.changeToDir()
1091
+ let dir = self.strForCd()
1092
+ if self.isDirectory == 0
1093
+ let dir = self.getPathTrunk().strForCd()
1094
+ endif
1095
+
1096
+ try
1097
+ execute "cd " . dir
1098
+ call s:echo("CWD is now: " . getcwd())
1099
+ catch
1100
+ throw "NERDTree.Path.Change exception: cannot change to " . dir
1101
+ endtry
1102
+ endfunction
1103
+
1104
+ "FUNCTION: Path.compareTo() {{{3
1105
+ "
1106
+ "Compares this Path to the given path and returns 0 if they are equal, -1 if
1107
+ "this Path is "less than" the given path, or 1 if it is "greater".
1108
+ "
1109
+ "Args:
1110
+ "path: the path object to compare this to
1111
+ "
1112
+ "Return:
1113
+ "1, -1 or 0
1114
+ function! s:Path.compareTo(path)
1115
+ let thisPath = self.getLastPathComponent(1)
1116
+ let thatPath = a:path.getLastPathComponent(1)
1117
+
1118
+ "if the paths are the same then clearly we return 0
1119
+ if thisPath == thatPath
1120
+ return 0
1121
+ endif
1122
+
1123
+ let thisSS = self.getSortOrderIndex()
1124
+ let thatSS = a:path.getSortOrderIndex()
1125
+
1126
+ "compare the sort sequences, if they are different then the return
1127
+ "value is easy
1128
+ if thisSS < thatSS
1129
+ return -1
1130
+ elseif thisSS > thatSS
1131
+ return 1
1132
+ else
1133
+ "if the sort sequences are the same then compare the paths
1134
+ "alphabetically
1135
+ let pathCompare = g:NERDTreeCaseSensitiveSort ? thisPath <# thatPath : thisPath <? thatPath
1136
+ if pathCompare
1137
+ return -1
1138
+ else
1139
+ return 1
1140
+ endif
1141
+ endif
1142
+ endfunction
1143
+
1144
+ "FUNCTION: Path.Create(fullpath) {{{3
1145
+ "
1146
+ "Factory method.
1147
+ "
1148
+ "Creates a path object with the given path. The path is also created on the
1149
+ "filesystem. If the path already exists, a NERDTree.Path.Exists exception is
1150
+ "thrown. If any other errors occur, a NERDTree.Path exception is thrown.
1151
+ "
1152
+ "Args:
1153
+ "fullpath: the full filesystem path to the file/dir to create
1154
+ function! s:Path.Create(fullpath)
1155
+ "bail if the a:fullpath already exists
1156
+ if isdirectory(a:fullpath) || filereadable(a:fullpath)
1157
+ throw "NERDTree.Path.Exists Exception: Directory Exists: '" . a:fullpath . "'"
1158
+ endif
1159
+
1160
+ try
1161
+
1162
+ "if it ends with a slash, assume its a dir create it
1163
+ if a:fullpath =~ '\(\\\|\/\)$'
1164
+ "whack the trailing slash off the end if it exists
1165
+ let fullpath = substitute(a:fullpath, '\(\\\|\/\)$', '', '')
1166
+
1167
+ call mkdir(fullpath, 'p')
1168
+
1169
+ "assume its a file and create
1170
+ else
1171
+ call writefile([], a:fullpath)
1172
+ endif
1173
+ catch /.*/
1174
+ throw "NERDTree.Path Exception: Could not create path: '" . a:fullpath . "'"
1175
+ endtry
1176
+
1177
+ return s:Path.New(a:fullpath)
1178
+ endfunction
1179
+
1180
+ "FUNCTION: Path.copy(dest) {{{3
1181
+ "
1182
+ "Copies the file/dir represented by this Path to the given location
1183
+ "
1184
+ "Args:
1185
+ "dest: the location to copy this dir/file to
1186
+ function! s:Path.copy(dest)
1187
+ if !s:Path.CopyingSupported()
1188
+ throw "NERDTree.Path.CopyingNotSupported Exception: Copying is not supported on this OS"
1189
+ endif
1190
+
1191
+ let dest = s:Path.WinToUnixPath(a:dest)
1192
+
1193
+ let cmd = g:NERDTreeCopyCmd . " " . self.strForOS(0) . " " . dest
1194
+ let success = system(cmd)
1195
+ if success != 0
1196
+ throw "NERDTree.Path Exception: Could not copy ''". self.strForOS(0) ."'' to: '" . a:dest . "'"
1197
+ endif
1198
+ endfunction
1199
+
1200
+ "FUNCTION: Path.CopyingSupported() {{{3
1201
+ "
1202
+ "returns 1 if copying is supported for this OS
1203
+ function! s:Path.CopyingSupported()
1204
+ return exists('g:NERDTreeCopyCmd')
1205
+ endfunction
1206
+
1207
+
1208
+ "FUNCTION: Path.copyingWillOverwrite(dest) {{{3
1209
+ "
1210
+ "returns 1 if copy this path to the given location will cause files to
1211
+ "overwritten
1212
+ "
1213
+ "Args:
1214
+ "dest: the location this path will be copied to
1215
+ function! s:Path.copyingWillOverwrite(dest)
1216
+ if filereadable(a:dest)
1217
+ return 1
1218
+ endif
1219
+
1220
+ if isdirectory(a:dest)
1221
+ let path = s:Path.JoinPathStrings(a:dest, self.getLastPathComponent(0))
1222
+ if filereadable(path)
1223
+ return 1
1224
+ endif
1225
+ endif
1226
+ endfunction
1227
+
1228
+ "FUNCTION: Path.delete() {{{3
1229
+ "
1230
+ "Deletes the file represented by this path.
1231
+ "Deletion of directories is not supported
1232
+ "
1233
+ "Throws NERDTree.Path.Deletion exceptions
1234
+ function! s:Path.delete()
1235
+ if self.isDirectory
1236
+
1237
+ let cmd = ""
1238
+ if s:running_windows
1239
+ "if we are runnnig windows then put quotes around the pathstring
1240
+ let cmd = g:NERDTreeRemoveDirCmd . self.strForOS(1)
1241
+ else
1242
+ let cmd = g:NERDTreeRemoveDirCmd . self.strForOS(1)
1243
+ endif
1244
+ let success = system(cmd)
1245
+
1246
+ if v:shell_error != 0
1247
+ throw "NERDTree.Path.Deletion Exception: Could not delete directory: '" . self.strForOS(0) . "'"
1248
+ endif
1249
+ else
1250
+ let success = delete(self.strForOS(0))
1251
+ if success != 0
1252
+ throw "NERDTree.Path.Deletion Exception: Could not delete file: '" . self.str(0) . "'"
1253
+ endif
1254
+ endif
1255
+
1256
+ "delete all bookmarks for this path
1257
+ for i in self.bookmarkNames()
1258
+ let bookmark = s:Bookmark.BookmarkFor(i)
1259
+ call bookmark.delete()
1260
+ endfor
1261
+ endfunction
1262
+
1263
+ "FUNCTION: Path.extractDriveLetter(fullpath) {{{3
1264
+ "
1265
+ "If running windows, cache the drive letter for this path
1266
+ function! s:Path.extractDriveLetter(fullpath)
1267
+ if s:running_windows
1268
+ let self.drive = substitute(a:fullpath, '\(^[a-zA-Z]:\).*', '\1', '')
1269
+ else
1270
+ let self.drive = ''
1271
+ endif
1272
+
1273
+ endfunction
1274
+ "FUNCTION: Path.exists() {{{3
1275
+ "return 1 if this path points to a location that is readable or is a directory
1276
+ function! s:Path.exists()
1277
+ return filereadable(self.strForOS(0)) || isdirectory(self.strForOS(0))
1278
+ endfunction
1279
+ "FUNCTION: Path.getDir() {{{3
1280
+ "
1281
+ "Returns this path if it is a directory, else this paths parent.
1282
+ "
1283
+ "Return:
1284
+ "a Path object
1285
+ function! s:Path.getDir()
1286
+ if self.isDirectory
1287
+ return self
1288
+ else
1289
+ return self.getParent()
1290
+ endif
1291
+ endfunction
1292
+ "FUNCTION: Path.getParent() {{{3
1293
+ "
1294
+ "Returns a new path object for this paths parent
1295
+ "
1296
+ "Return:
1297
+ "a new Path object
1298
+ function! s:Path.getParent()
1299
+ let path = '/'. join(self.pathSegments[0:-2], '/')
1300
+ return s:Path.New(path)
1301
+ endfunction
1302
+ "FUNCTION: Path.getLastPathComponent(dirSlash) {{{3
1303
+ "
1304
+ "Gets the last part of this path.
1305
+ "
1306
+ "Args:
1307
+ "dirSlash: if 1 then a trailing slash will be added to the returned value for
1308
+ "directory nodes.
1309
+ function! s:Path.getLastPathComponent(dirSlash)
1310
+ if empty(self.pathSegments)
1311
+ return ''
1312
+ endif
1313
+ let toReturn = self.pathSegments[-1]
1314
+ if a:dirSlash && self.isDirectory
1315
+ let toReturn = toReturn . '/'
1316
+ endif
1317
+ return toReturn
1318
+ endfunction
1319
+
1320
+ "FUNCTION: Path.getPathTrunk() {{{3
1321
+ "Gets the path without the last segment on the end.
1322
+ function! s:Path.getPathTrunk()
1323
+ return s:Path.New(self.strTrunk())
1324
+ endfunction
1325
+
1326
+ "FUNCTION: Path.getSortOrderIndex() {{{3
1327
+ "returns the index of the pattern in g:NERDTreeSortOrder that this path matches
1328
+ function! s:Path.getSortOrderIndex()
1329
+ let i = 0
1330
+ while i < len(g:NERDTreeSortOrder)
1331
+ if self.getLastPathComponent(1) =~ g:NERDTreeSortOrder[i]
1332
+ return i
1333
+ endif
1334
+ let i = i + 1
1335
+ endwhile
1336
+ return s:NERDTreeSortStarIndex
1337
+ endfunction
1338
+
1339
+ "FUNCTION: Path.ignore() {{{3
1340
+ "returns true if this path should be ignored
1341
+ function! s:Path.ignore()
1342
+ let lastPathComponent = self.getLastPathComponent(0)
1343
+
1344
+ "filter out the user specified paths to ignore
1345
+ if t:NERDTreeIgnoreEnabled
1346
+ for i in g:NERDTreeIgnore
1347
+ if lastPathComponent =~ i
1348
+ return 1
1349
+ endif
1350
+ endfor
1351
+ endif
1352
+
1353
+ "dont show hidden files unless instructed to
1354
+ if t:NERDTreeShowHidden == 0 && lastPathComponent =~ '^\.'
1355
+ return 1
1356
+ endif
1357
+
1358
+ if t:NERDTreeShowFiles == 0 && self.isDirectory == 0
1359
+ return 1
1360
+ endif
1361
+
1362
+ return 0
1363
+ endfunction
1364
+
1365
+ "FUNCTION: Path.JoinPathStrings(...) {{{3
1366
+ function! s:Path.JoinPathStrings(...)
1367
+ let components = []
1368
+ for i in a:000
1369
+ let components = extend(components, split(i, '/'))
1370
+ endfor
1371
+ return '/' . join(components, '/')
1372
+ endfunction
1373
+
1374
+ "FUNCTION: Path.equals() {{{3
1375
+ "
1376
+ "Determines whether 2 path objects are "equal".
1377
+ "They are equal if the paths they represent are the same
1378
+ "
1379
+ "Args:
1380
+ "path: the other path obj to compare this with
1381
+ function! s:Path.equals(path)
1382
+ return self.str(0) == a:path.str(0)
1383
+ endfunction
1384
+
1385
+ "FUNCTION: Path.New() {{{3
1386
+ "
1387
+ "The Constructor for the Path object
1388
+ "Throws NERDTree.Path.InvalidArguments exception.
1389
+ function! s:Path.New(fullpath)
1390
+ let newPath = copy(self)
1391
+
1392
+ call newPath.readInfoFromDisk(a:fullpath)
1393
+
1394
+ let newPath.cachedDisplayString = ""
1395
+
1396
+ return newPath
1397
+ endfunction
1398
+
1399
+ "FUNCTION: Path.readInfoFromDisk(fullpath) {{{3
1400
+ "
1401
+ "
1402
+ "Throws NERDTree.Path.InvalidArguments exception.
1403
+ function! s:Path.readInfoFromDisk(fullpath)
1404
+ call self.extractDriveLetter(a:fullpath)
1405
+
1406
+ let fullpath = s:Path.WinToUnixPath(a:fullpath)
1407
+
1408
+ if getftype(fullpath) == "fifo"
1409
+ throw "NERDTree.Path.InvalidFiletype Exception: Cant handle FIFO files: " . a:fullpath
1410
+ endif
1411
+
1412
+ let self.pathSegments = split(fullpath, '/')
1413
+
1414
+
1415
+ let self.isReadOnly = 0
1416
+ if isdirectory(a:fullpath)
1417
+ let self.isDirectory = 1
1418
+ elseif filereadable(a:fullpath)
1419
+ let self.isDirectory = 0
1420
+ let self.isReadOnly = filewritable(a:fullpath) == 0
1421
+ else
1422
+ throw "NERDTree.Path.InvalidArguments Exception: Invalid path = " . a:fullpath
1423
+ endif
1424
+
1425
+ let self.isExecutable = 0
1426
+ if !self.isDirectory
1427
+ let self.isExecutable = getfperm(a:fullpath) =~ 'x'
1428
+ endif
1429
+
1430
+ "grab the last part of the path (minus the trailing slash)
1431
+ let lastPathComponent = self.getLastPathComponent(0)
1432
+
1433
+ "get the path to the new node with the parent dir fully resolved
1434
+ let hardPath = resolve(self.strTrunk()) . '/' . lastPathComponent
1435
+
1436
+ "if the last part of the path is a symlink then flag it as such
1437
+ let self.isSymLink = (resolve(hardPath) != hardPath)
1438
+ if self.isSymLink
1439
+ let self.symLinkDest = resolve(fullpath)
1440
+
1441
+ "if the link is a dir then slap a / on the end of its dest
1442
+ if isdirectory(self.symLinkDest)
1443
+
1444
+ "we always wanna treat MS windows shortcuts as files for
1445
+ "simplicity
1446
+ if hardPath !~ '\.lnk$'
1447
+
1448
+ let self.symLinkDest = self.symLinkDest . '/'
1449
+ endif
1450
+ endif
1451
+ endif
1452
+ endfunction
1453
+
1454
+ "FUNCTION: Path.refresh() {{{3
1455
+ function! s:Path.refresh()
1456
+ call self.readInfoFromDisk(self.strForOS(0))
1457
+ call self.cacheDisplayString()
1458
+ endfunction
1459
+
1460
+ "FUNCTION: Path.rename() {{{3
1461
+ "
1462
+ "Renames this node on the filesystem
1463
+ function! s:Path.rename(newPath)
1464
+ if a:newPath == ''
1465
+ throw "NERDTree.Path.InvalidArguments exception. Invalid newPath for renaming = ". a:newPath
1466
+ endif
1467
+
1468
+ let success = rename(self.strForOS(0), a:newPath)
1469
+ if success != 0
1470
+ throw "NERDTree.Path.Rename Exception: Could not rename: '" . self.strForOS(0) . "'" . 'to:' . a:newPath
1471
+ endif
1472
+ call self.readInfoFromDisk(a:newPath)
1473
+
1474
+ for i in self.bookmarkNames()
1475
+ let b = s:Bookmark.BookmarkFor(i)
1476
+ call b.setPath(copy(self))
1477
+ endfor
1478
+ call s:Bookmark.Write()
1479
+ endfunction
1480
+
1481
+ "FUNCTION: Path.str(esc) {{{3
1482
+ "
1483
+ "Gets the actual string path that this obj represents.
1484
+ "
1485
+ "Args:
1486
+ "esc: if 1 then all the tricky chars in the returned string will be escaped
1487
+ function! s:Path.str(esc)
1488
+ let toReturn = '/' . join(self.pathSegments, '/')
1489
+ if self.isDirectory && toReturn != '/'
1490
+ let toReturn = toReturn . '/'
1491
+ endif
1492
+
1493
+ if a:esc
1494
+ let toReturn = escape(toReturn, s:escape_chars)
1495
+ endif
1496
+ return toReturn
1497
+ endfunction
1498
+
1499
+ "FUNCTION: Path.strAbs() {{{3
1500
+ "
1501
+ "Returns a string representing this path with all the symlinks resolved
1502
+ "
1503
+ "Return:
1504
+ "string
1505
+ function! s:Path.strAbs()
1506
+ return resolve(self.str(1))
1507
+ endfunction
1508
+
1509
+ "FUNCTION: Path.strForCd() {{{3
1510
+ "
1511
+ " returns a string that can be used with :cd
1512
+ "
1513
+ "Return:
1514
+ "a string that can be used in the view to represent this path
1515
+ function! s:Path.strForCd()
1516
+ if s:running_windows
1517
+ return self.strForOS(0)
1518
+ else
1519
+ return self.strForOS(1)
1520
+ endif
1521
+ endfunction
1522
+ "FUNCTION: Path.strDisplay() {{{3
1523
+ "
1524
+ "Returns a string that specifies how the path should be represented as a
1525
+ "string
1526
+ "
1527
+ "Return:
1528
+ "a string that can be used in the view to represent this path
1529
+ function! s:Path.strDisplay()
1530
+ if self.cachedDisplayString == ""
1531
+ call self.cacheDisplayString()
1532
+ endif
1533
+
1534
+ return self.cachedDisplayString
1535
+ endfunction
1536
+
1537
+ "FUNCTION: Path.strForEditCmd() {{{3
1538
+ "
1539
+ "Return: the string for this path that is suitable to be used with the :edit
1540
+ "command
1541
+ function! s:Path.strForEditCmd()
1542
+ if s:running_windows
1543
+ return self.strForOS(0)
1544
+ else
1545
+ return self.str(1)
1546
+ endif
1547
+
1548
+ endfunction
1549
+ "FUNCTION: Path.strForGlob() {{{3
1550
+ function! s:Path.strForGlob()
1551
+ let lead = s:os_slash
1552
+
1553
+ "if we are running windows then slap a drive letter on the front
1554
+ if s:running_windows
1555
+ let lead = self.drive . '\'
1556
+ endif
1557
+
1558
+ let toReturn = lead . join(self.pathSegments, s:os_slash)
1559
+
1560
+ if !s:running_windows
1561
+ let toReturn = escape(toReturn, s:escape_chars)
1562
+ endif
1563
+ return toReturn
1564
+ endfunction
1565
+ "FUNCTION: Path.strForOS(esc) {{{3
1566
+ "
1567
+ "Gets the string path for this path object that is appropriate for the OS.
1568
+ "EG, in windows c:\foo\bar
1569
+ " in *nix /foo/bar
1570
+ "
1571
+ "Args:
1572
+ "esc: if 1 then all the tricky chars in the returned string will be
1573
+ " escaped. If we are running windows then the str is double quoted instead.
1574
+ function! s:Path.strForOS(esc)
1575
+ let lead = s:os_slash
1576
+
1577
+ "if we are running windows then slap a drive letter on the front
1578
+ if s:running_windows
1579
+ let lead = self.drive . '\'
1580
+ endif
1581
+
1582
+ let toReturn = lead . join(self.pathSegments, s:os_slash)
1583
+
1584
+ if a:esc
1585
+ if s:running_windows
1586
+ let toReturn = '"' . toReturn . '"'
1587
+ else
1588
+ let toReturn = escape(toReturn, s:escape_chars)
1589
+ endif
1590
+ endif
1591
+ return toReturn
1592
+ endfunction
1593
+
1594
+ "FUNCTION: Path.strTrunk() {{{3
1595
+ "Gets the path without the last segment on the end.
1596
+ function! s:Path.strTrunk()
1597
+ return self.drive . '/' . join(self.pathSegments[0:-2], '/')
1598
+ endfunction
1599
+
1600
+ "FUNCTION: Path.WinToUnixPath(pathstr){{{3
1601
+ "Takes in a windows path and returns the unix equiv
1602
+ "
1603
+ "A class level method
1604
+ "
1605
+ "Args:
1606
+ "pathstr: the windows path to convert
1607
+ function! s:Path.WinToUnixPath(pathstr)
1608
+ if !s:running_windows
1609
+ return a:pathstr
1610
+ endif
1611
+
1612
+ let toReturn = a:pathstr
1613
+
1614
+ "remove the x:\ of the front
1615
+ let toReturn = substitute(toReturn, '^.*:\(\\\|/\)\?', '/', "")
1616
+
1617
+ "convert all \ chars to /
1618
+ let toReturn = substitute(toReturn, '\', '/', "g")
1619
+
1620
+ return toReturn
1621
+ endfunction
1622
+
1623
+ " SECTION: General Functions {{{1
1624
+ "============================================================
1625
+ "FUNCTION: s:bufInWindows(bnum){{{2
1626
+ "[[STOLEN FROM VTREEEXPLORER.VIM]]
1627
+ "Determine the number of windows open to this buffer number.
1628
+ "Care of Yegappan Lakshman. Thanks!
1629
+ "
1630
+ "Args:
1631
+ "bnum: the subject buffers buffer number
1632
+ function! s:bufInWindows(bnum)
1633
+ let cnt = 0
1634
+ let winnum = 1
1635
+ while 1
1636
+ let bufnum = winbufnr(winnum)
1637
+ if bufnum < 0
1638
+ break
1639
+ endif
1640
+ if bufnum == a:bnum
1641
+ let cnt = cnt + 1
1642
+ endif
1643
+ let winnum = winnum + 1
1644
+ endwhile
1645
+
1646
+ return cnt
1647
+ endfunction " >>>
1648
+
1649
+ "FUNCTION: s:compareBookmarks(first, second) {{{2
1650
+ "Compares two bookmarks
1651
+ function! s:compareBookmarks(first, second)
1652
+ return a:first.compareTo(a:second)
1653
+ endfunction
1654
+
1655
+ " FUNCTION: s:completeBookmarks(A,L,P) {{{2
1656
+ " completion function for the bookmark commands
1657
+ function! s:completeBookmarks(A,L,P)
1658
+ return filter(s:Bookmark.BookmarkNames(), 'v:val =~ "^' . a:A . '"')
1659
+ endfunction
1660
+ "FUNCTION: s:initNerdTree(name) {{{2
1661
+ "Initialise the nerd tree for this tab. The tree will start in either the
1662
+ "given directory, or the directory associated with the given bookmark
1663
+ "
1664
+ "Args:
1665
+ "name: the name of a bookmark or a directory
1666
+ function! s:initNerdTree(name)
1667
+ let path = {}
1668
+ if s:Bookmark.BookmarkExistsFor(a:name)
1669
+ let path = s:Bookmark.BookmarkFor(a:name).path
1670
+ else
1671
+ let dir = a:name == '' ? expand('%:p:h') : a:name
1672
+ let dir = resolve(dir)
1673
+ try
1674
+ let path = s:Path.New(dir)
1675
+ catch /NERDTree.Path.InvalidArguments/
1676
+ call s:echo("No bookmark or directory found for: " . a:name)
1677
+ return
1678
+ endtry
1679
+ endif
1680
+ if !path.isDirectory
1681
+ let path = path.getParent()
1682
+ endif
1683
+
1684
+ "if instructed to, then change the vim CWD to the dir the NERDTree is
1685
+ "inited in
1686
+ if g:NERDTreeChDirMode != 0
1687
+ exec 'cd ' . path.strForCd()
1688
+ endif
1689
+
1690
+ let t:treeShowHelp = 0
1691
+ let t:NERDTreeIgnoreEnabled = 1
1692
+ let t:NERDTreeShowFiles = g:NERDTreeShowFiles
1693
+ let t:NERDTreeShowHidden = g:NERDTreeShowHidden
1694
+ let t:NERDTreeShowBookmarks = g:NERDTreeShowBookmarks
1695
+
1696
+ if s:treeExistsForTab()
1697
+ if s:isTreeOpen()
1698
+ call s:closeTree()
1699
+ endif
1700
+ unlet t:NERDTreeRoot
1701
+ endif
1702
+
1703
+ let t:NERDTreeRoot = s:TreeDirNode.New(path)
1704
+ call t:NERDTreeRoot.open()
1705
+
1706
+ call s:createTreeWin()
1707
+ call s:renderView()
1708
+ call s:putCursorOnNode(t:NERDTreeRoot, 0, 0)
1709
+ endfunction
1710
+ " Function: s:treeExistsForTab() {{{2
1711
+ " Returns 1 if a nerd tree root exists in the current tab
1712
+ function! s:treeExistsForTab()
1713
+ return exists("t:NERDTreeRoot")
1714
+ endfunction
1715
+ " SECTION: Public Functions {{{1
1716
+ "============================================================
1717
+ "Returns the node that the cursor is currently on.
1718
+ "
1719
+ "If the cursor is not in the NERDTree window, it is temporarily put there.
1720
+ "
1721
+ "If no NERD tree window exists for the current tab, a NERDTree.NoTreeForTab
1722
+ "exception is thrown.
1723
+ "
1724
+ "If the cursor is not on a node then an empty dictionary {} is returned.
1725
+ function! NERDTreeGetCurrentNode()
1726
+ if !s:treeExistsForTab() || !s:isTreeOpen()
1727
+ throw "NERDTree.NoTreeForTab exception: there is no NERD tree open for the current tab"
1728
+ endif
1729
+
1730
+ let winnr = winnr()
1731
+ if winnr != s:getTreeWinNum()
1732
+ call s:putCursorInTreeWin()
1733
+ endif
1734
+
1735
+ let treenode = s:getSelectedNode()
1736
+
1737
+ if winnr != winnr()
1738
+ wincmd w
1739
+ endif
1740
+
1741
+ return treenode
1742
+ endfunction
1743
+
1744
+ "Returns the path object for the current node.
1745
+ "
1746
+ "Subject to the same conditions as NERDTreeGetCurrentNode
1747
+ function! NERDTreeGetCurrentPath()
1748
+ let node = NERDTreeGetCurrentNode()
1749
+ if node != {}
1750
+ return node.path
1751
+ else
1752
+ return {}
1753
+ endif
1754
+ endfunction
1755
+
1756
+ " SECTION: View Functions {{{1
1757
+ "============================================================
1758
+ "FUNCTION: s:centerView() {{{2
1759
+ "centers the nerd tree window around the cursor (provided the nerd tree
1760
+ "options permit)
1761
+ function! s:centerView()
1762
+ if g:NERDTreeAutoCenter
1763
+ let current_line = winline()
1764
+ let lines_to_top = current_line
1765
+ let lines_to_bottom = winheight(s:getTreeWinNum()) - current_line
1766
+ if lines_to_top < g:NERDTreeAutoCenterThreshold || lines_to_bottom < g:NERDTreeAutoCenterThreshold
1767
+ normal! zz
1768
+ endif
1769
+ endif
1770
+ endfunction
1771
+ "FUNCTION: s:closeTree() {{{2
1772
+ "Closes the NERD tree window
1773
+ function! s:closeTree()
1774
+ if !s:isTreeOpen()
1775
+ throw "NERDTree.view.closeTree exception: no NERDTree is open"
1776
+ endif
1777
+
1778
+ if winnr("$") != 1
1779
+ execute s:getTreeWinNum() . " wincmd w"
1780
+ close
1781
+ execute "wincmd p"
1782
+ else
1783
+ :q
1784
+ endif
1785
+ endfunction
1786
+
1787
+ "FUNCTION: s:closeTreeIfOpen() {{{2
1788
+ "Closes the NERD tree window if it is open
1789
+ function! s:closeTreeIfOpen()
1790
+ if s:isTreeOpen()
1791
+ call s:closeTree()
1792
+ endif
1793
+ endfunction
1794
+ "FUNCTION: s:closeTreeIfQuitOnOpen() {{{2
1795
+ "Closes the NERD tree window if the close on open option is set
1796
+ function! s:closeTreeIfQuitOnOpen()
1797
+ if g:NERDTreeQuitOnOpen
1798
+ call s:closeTree()
1799
+ endif
1800
+ endfunction
1801
+ "FUNCTION: s:createTreeWin() {{{2
1802
+ "Inits the NERD tree window. ie. opens it, sizes it, sets all the local
1803
+ "options etc
1804
+ function! s:createTreeWin()
1805
+ "create the nerd tree window
1806
+ let splitLocation = (g:NERDTreeWinPos == "top" || g:NERDTreeWinPos == "left") ? "topleft " : "botright "
1807
+ let splitMode = s:shouldSplitVertically() ? "vertical " : ""
1808
+ let splitSize = g:NERDTreeWinSize
1809
+ let t:NERDTreeWinName = localtime() . s:NERDTreeWinName
1810
+ let cmd = splitLocation . splitMode . splitSize . ' new ' . t:NERDTreeWinName
1811
+ silent! execute cmd
1812
+
1813
+ setlocal winfixwidth
1814
+
1815
+ "throwaway buffer options
1816
+ setlocal noswapfile
1817
+ setlocal buftype=nofile
1818
+ setlocal bufhidden=delete
1819
+ setlocal nowrap
1820
+ setlocal foldcolumn=0
1821
+ setlocal nobuflisted
1822
+ setlocal nospell
1823
+ if g:NERDTreeShowLineNumbers
1824
+ setlocal nu
1825
+ else
1826
+ setlocal nonu
1827
+ endif
1828
+
1829
+ iabc <buffer>
1830
+
1831
+ if g:NERDTreeHighlightCursorline
1832
+ setlocal cursorline
1833
+ endif
1834
+
1835
+
1836
+
1837
+ call s:bindMappings()
1838
+ setfiletype nerdtree
1839
+ " syntax highlighting
1840
+ if has("syntax") && exists("g:syntax_on") && !has("syntax_items")
1841
+ call s:setupSyntaxHighlighting()
1842
+ endif
1843
+ endfunction
1844
+
1845
+ "FUNCTION: s:drawTree {{{2
1846
+ "Draws the given node recursively
1847
+ "
1848
+ "Args:
1849
+ "curNode: the node that is being rendered with this call
1850
+ "depth: the current depth in the tree for this call
1851
+ "drawText: 1 if we should actually draw the line for this node (if 0 then the
1852
+ "child nodes are rendered only)
1853
+ "vertMap: a binary array that indicates whether a vertical bar should be draw
1854
+ "for each depth in the tree
1855
+ "isLastChild:true if this curNode is the last child of its parent
1856
+ function! s:drawTree(curNode, depth, drawText, vertMap, isLastChild)
1857
+ if a:drawText == 1
1858
+
1859
+ let treeParts = ''
1860
+
1861
+ "get all the leading spaces and vertical tree parts for this line
1862
+ if a:depth > 1
1863
+ for j in a:vertMap[0:-2]
1864
+ if j == 1
1865
+ let treeParts = treeParts . '| '
1866
+ else
1867
+ let treeParts = treeParts . ' '
1868
+ endif
1869
+ endfor
1870
+ endif
1871
+
1872
+ "get the last vertical tree part for this line which will be different
1873
+ "if this node is the last child of its parent
1874
+ if a:isLastChild
1875
+ let treeParts = treeParts . '`'
1876
+ else
1877
+ let treeParts = treeParts . '|'
1878
+ endif
1879
+
1880
+
1881
+ "smack the appropriate dir/file symbol on the line before the file/dir
1882
+ "name itself
1883
+ if a:curNode.path.isDirectory
1884
+ if a:curNode.isOpen
1885
+ let treeParts = treeParts . '~'
1886
+ else
1887
+ let treeParts = treeParts . '+'
1888
+ endif
1889
+ else
1890
+ let treeParts = treeParts . '-'
1891
+ endif
1892
+ let line = treeParts . a:curNode.strDisplay()
1893
+
1894
+ call setline(line(".")+1, line)
1895
+ call cursor(line(".")+1, col("."))
1896
+ endif
1897
+
1898
+ "if the node is an open dir, draw its children
1899
+ if a:curNode.path.isDirectory == 1 && a:curNode.isOpen == 1
1900
+
1901
+ let childNodesToDraw = a:curNode.getVisibleChildren()
1902
+ if len(childNodesToDraw) > 0
1903
+
1904
+ "draw all the nodes children except the last
1905
+ let lastIndx = len(childNodesToDraw)-1
1906
+ if lastIndx > 0
1907
+ for i in childNodesToDraw[0:lastIndx-1]
1908
+ call s:drawTree(i, a:depth + 1, 1, add(copy(a:vertMap), 1), 0)
1909
+ endfor
1910
+ endif
1911
+
1912
+ "draw the last child, indicating that it IS the last
1913
+ call s:drawTree(childNodesToDraw[lastIndx], a:depth + 1, 1, add(copy(a:vertMap), 0), 1)
1914
+ endif
1915
+ endif
1916
+ endfunction
1917
+
1918
+
1919
+ "FUNCTION: s:dumpHelp {{{2
1920
+ "prints out the quick help
1921
+ function! s:dumpHelp()
1922
+ let old_h = @h
1923
+ if t:treeShowHelp == 1
1924
+ let @h= "\" NERD tree (" . s:NERD_tree_version . ") quickhelp~\n"
1925
+ let @h=@h."\" ============================\n"
1926
+ let @h=@h."\" File node mappings~\n"
1927
+ let @h=@h."\" ". (g:NERDTreeMouseMode == 3 ? "single" : "double") ."-click,\n"
1928
+ let @h=@h."\" ". g:NERDTreeMapActivateNode .": open in prev window\n"
1929
+ let @h=@h."\" ". g:NERDTreeMapPreview .": preview\n"
1930
+ let @h=@h."\" ". g:NERDTreeMapOpenInTab.": open in new tab\n"
1931
+ let @h=@h."\" ". g:NERDTreeMapOpenInTabSilent .": open in new tab silently\n"
1932
+ let @h=@h."\" middle-click,\n"
1933
+ let @h=@h."\" ". g:NERDTreeMapOpenSplit .": open split\n"
1934
+ let @h=@h."\" ". g:NERDTreeMapPreviewSplit .": preview split\n"
1935
+ let @h=@h."\" ". g:NERDTreeMapExecute.": Execute file\n"
1936
+
1937
+ let @h=@h."\"\n\" ----------------------------\n"
1938
+ let @h=@h."\" Directory node mappings~\n"
1939
+ let @h=@h."\" ". (g:NERDTreeMouseMode == 1 ? "double" : "single") ."-click,\n"
1940
+ let @h=@h."\" ". g:NERDTreeMapActivateNode .": open & close node\n"
1941
+ let @h=@h."\" ". g:NERDTreeMapOpenRecursively .": recursively open node\n"
1942
+ let @h=@h."\" ". g:NERDTreeMapCloseDir .": close parent of node\n"
1943
+ let @h=@h."\" ". g:NERDTreeMapCloseChildren .": close all child nodes of\n"
1944
+ let @h=@h."\" current node recursively\n"
1945
+ let @h=@h."\" middle-click,\n"
1946
+ let @h=@h."\" ". g:NERDTreeMapOpenExpl.": Open netrw for selected\n"
1947
+ let @h=@h."\" node\n"
1948
+
1949
+ let @h=@h."\"\n\" ----------------------------\n"
1950
+ let @h=@h."\" Bookmark table mappings~\n"
1951
+ let @h=@h."\" double-click,\n"
1952
+ let @h=@h."\" ". g:NERDTreeMapActivateNode .": open bookmark\n"
1953
+ let @h=@h."\" ". g:NERDTreeMapOpenInTab.": open in new tab\n"
1954
+ let @h=@h."\" ". g:NERDTreeMapOpenInTabSilent .": open in new tab silently\n"
1955
+ let @h=@h."\" ". g:NERDTreeMapDeleteBookmark .": delete bookmark\n"
1956
+
1957
+ let @h=@h."\"\n\" ----------------------------\n"
1958
+ let @h=@h."\" Tree navigation mappings~\n"
1959
+ let @h=@h."\" ". g:NERDTreeMapJumpRoot .": go to root\n"
1960
+ let @h=@h."\" ". g:NERDTreeMapJumpParent .": go to parent\n"
1961
+ let @h=@h."\" ". g:NERDTreeMapJumpFirstChild .": go to first child\n"
1962
+ let @h=@h."\" ". g:NERDTreeMapJumpLastChild .": go to last child\n"
1963
+ let @h=@h."\" ". g:NERDTreeMapJumpNextSibling .": go to next sibling\n"
1964
+ let @h=@h."\" ". g:NERDTreeMapJumpPrevSibling .": go to prev sibling\n"
1965
+
1966
+ let @h=@h."\"\n\" ----------------------------\n"
1967
+ let @h=@h."\" Filesystem mappings~\n"
1968
+ let @h=@h."\" ". g:NERDTreeMapChangeRoot .": change tree root to the\n"
1969
+ let @h=@h."\" selected dir\n"
1970
+ let @h=@h."\" ". g:NERDTreeMapUpdir .": move tree root up a dir\n"
1971
+ let @h=@h."\" ". g:NERDTreeMapUpdirKeepOpen .": move tree root up a dir\n"
1972
+ let @h=@h."\" but leave old root open\n"
1973
+ let @h=@h."\" ". g:NERDTreeMapRefresh .": refresh cursor dir\n"
1974
+ let @h=@h."\" ". g:NERDTreeMapRefreshRoot .": refresh current root\n"
1975
+ let @h=@h."\" ". g:NERDTreeMapFilesystemMenu .": Show filesystem menu\n"
1976
+ let @h=@h."\" ". g:NERDTreeMapChdir .":change the CWD to the\n"
1977
+ let @h=@h."\" selected dir\n"
1978
+
1979
+ let @h=@h."\"\n\" ----------------------------\n"
1980
+ let @h=@h."\" Tree filtering mappings~\n"
1981
+ let @h=@h."\" ". g:NERDTreeMapToggleHidden .": hidden files (" . (t:NERDTreeShowHidden ? "on" : "off") . ")\n"
1982
+ let @h=@h."\" ". g:NERDTreeMapToggleFilters .": file filters (" . (t:NERDTreeIgnoreEnabled ? "on" : "off") . ")\n"
1983
+ let @h=@h."\" ". g:NERDTreeMapToggleFiles .": files (" . (t:NERDTreeShowFiles ? "on" : "off") . ")\n"
1984
+ let @h=@h."\" ". g:NERDTreeMapToggleBookmarks .": bookmarks (" . (t:NERDTreeShowBookmarks ? "on" : "off") . ")\n"
1985
+
1986
+ let @h=@h."\"\n\" ----------------------------\n"
1987
+ let @h=@h."\" Other mappings~\n"
1988
+ let @h=@h."\" ". g:NERDTreeMapQuit .": Close the NERDTree window\n"
1989
+ let @h=@h."\" ". g:NERDTreeMapHelp .": toggle help\n"
1990
+ let @h=@h."\"\n\" ----------------------------\n"
1991
+ let @h=@h."\" Bookmark commands~\n"
1992
+ let @h=@h."\" :Bookmark <name>\n"
1993
+ let @h=@h."\" :BookmarkToRoot <name>\n"
1994
+ let @h=@h."\" :RevealBookmark <name>\n"
1995
+ let @h=@h."\" :OpenBookmark <name>\n"
1996
+ let @h=@h."\" :ClearBookmarks [<names>]\n"
1997
+ let @h=@h."\" :ClearAllBookmarks\n"
1998
+ else
1999
+ let @h="\" Press ". g:NERDTreeMapHelp ." for help\n"
2000
+ endif
2001
+
2002
+ silent! put h
2003
+
2004
+ let @h = old_h
2005
+ endfunction
2006
+ "FUNCTION: s:echo {{{2
2007
+ "A wrapper for :echo. Appends 'NERDTree:' on the front of all messages
2008
+ "
2009
+ "Args:
2010
+ "msg: the message to echo
2011
+ function! s:echo(msg)
2012
+ redraw
2013
+ echomsg "NERDTree: " . a:msg
2014
+ endfunction
2015
+ "FUNCTION: s:echoWarning {{{2
2016
+ "Wrapper for s:echo, sets the message type to warningmsg for this message
2017
+ "Args:
2018
+ "msg: the message to echo
2019
+ function! s:echoWarning(msg)
2020
+ echohl warningmsg
2021
+ call s:echo(a:msg)
2022
+ echohl normal
2023
+ endfunction
2024
+ "FUNCTION: s:echoError {{{2
2025
+ "Wrapper for s:echo, sets the message type to errormsg for this message
2026
+ "Args:
2027
+ "msg: the message to echo
2028
+ function! s:echoError(msg)
2029
+ echohl errormsg
2030
+ call s:echo(a:msg)
2031
+ echohl normal
2032
+ endfunction
2033
+ "FUNCTION: s:findNodeLineNumber(treenode){{{2
2034
+ "Finds the line number for the given tree node
2035
+ "
2036
+ "Args:
2037
+ "treenode: the node to find the line no. for
2038
+ function! s:findNodeLineNumber(treenode)
2039
+ "if the node is the root then return the root line no.
2040
+ if a:treenode.isRoot()
2041
+ return s:findRootNodeLineNumber()
2042
+ endif
2043
+
2044
+ let totalLines = line("$")
2045
+
2046
+ "the path components we have matched so far
2047
+ let pathcomponents = [substitute(t:NERDTreeRoot.path.str(0), '/ *$', '', '')]
2048
+ "the index of the component we are searching for
2049
+ let curPathComponent = 1
2050
+
2051
+ let fullpath = a:treenode.path.str(0)
2052
+
2053
+
2054
+ let lnum = s:findRootNodeLineNumber()
2055
+ while lnum > 0
2056
+ let lnum = lnum + 1
2057
+ "have we reached the bottom of the tree?
2058
+ if lnum == totalLines+1
2059
+ return -1
2060
+ endif
2061
+
2062
+ let curLine = getline(lnum)
2063
+
2064
+ let indent = match(curLine,s:tree_markup_reg_neg) / s:tree_wid
2065
+ if indent == curPathComponent
2066
+ let curLine = s:stripMarkupFromLine(curLine, 1)
2067
+
2068
+ let curPath = join(pathcomponents, '/') . '/' . curLine
2069
+ if stridx(fullpath, curPath, 0) == 0
2070
+ if fullpath == curPath || strpart(fullpath, len(curPath)-1,1) == '/'
2071
+ let curLine = substitute(curLine, '/ *$', '', '')
2072
+ call add(pathcomponents, curLine)
2073
+ let curPathComponent = curPathComponent + 1
2074
+
2075
+ if fullpath == curPath
2076
+ return lnum
2077
+ endif
2078
+ endif
2079
+ endif
2080
+ endif
2081
+ endwhile
2082
+ return -1
2083
+ endfunction
2084
+
2085
+ "FUNCTION: s:findRootNodeLineNumber(){{{2
2086
+ "Finds the line number of the root node
2087
+ function! s:findRootNodeLineNumber()
2088
+ let rootLine = 1
2089
+ while getline(rootLine) !~ '^/'
2090
+ let rootLine = rootLine + 1
2091
+ endwhile
2092
+ return rootLine
2093
+ endfunction
2094
+
2095
+ "FUNCTION: s:getPath(ln) {{{2
2096
+ "Gets the full path to the node that is rendered on the given line number
2097
+ "
2098
+ "Args:
2099
+ "ln: the line number to get the path for
2100
+ "
2101
+ "Return:
2102
+ "A path if a node was selected, {} if nothing is selected.
2103
+ "If the 'up a dir' line was selected then the path to the parent of the
2104
+ "current root is returned
2105
+ function! s:getPath(ln)
2106
+ let line = getline(a:ln)
2107
+
2108
+ "check to see if we have the root node
2109
+ if line =~ '^\/'
2110
+ return t:NERDTreeRoot.path
2111
+ endif
2112
+
2113
+ " in case called from outside the tree
2114
+ if line !~ '^ *[|`]' || line =~ '^$'
2115
+ return {}
2116
+ endif
2117
+
2118
+ if line == s:tree_up_dir_line
2119
+ return t:NERDTreeRoot.path.getParent()
2120
+ endif
2121
+
2122
+ "get the indent level for the file (i.e. how deep in the tree it is)
2123
+ let indent = match(line, s:tree_markup_reg_neg) / s:tree_wid
2124
+
2125
+
2126
+ "remove the tree parts and the leading space
2127
+ let curFile = s:stripMarkupFromLine(line, 0)
2128
+
2129
+ let wasdir = 0
2130
+ if curFile =~ '/$'
2131
+ let wasdir = 1
2132
+ let curFile = substitute(curFile, '/\?$', '/', "")
2133
+ endif
2134
+
2135
+
2136
+ let dir = ""
2137
+ let lnum = a:ln
2138
+ while lnum > 0
2139
+ let lnum = lnum - 1
2140
+ let curLine = getline(lnum)
2141
+ let curLineStripped = s:stripMarkupFromLine(curLine, 1)
2142
+
2143
+ "have we reached the top of the tree?
2144
+ if curLine =~ '^/'
2145
+ let dir = substitute (curLine, ' *$', "", "") . dir
2146
+ break
2147
+ endif
2148
+ if curLineStripped =~ '/$'
2149
+ let lpindent = match(curLine,s:tree_markup_reg_neg) / s:tree_wid
2150
+ if lpindent < indent
2151
+ let indent = indent - 1
2152
+
2153
+ let dir = substitute (curLineStripped,'^\\', "", "") . dir
2154
+ continue
2155
+ endif
2156
+ endif
2157
+ endwhile
2158
+ let curFile = t:NERDTreeRoot.path.drive . dir . curFile
2159
+ let toReturn = s:Path.New(curFile)
2160
+ return toReturn
2161
+ endfunction
2162
+
2163
+ "FUNCTION: s:getSelectedBookmark() {{{2
2164
+ "returns the bookmark the cursor is over in the bookmarks table or {}
2165
+ function! s:getSelectedBookmark()
2166
+ let line = getline(".")
2167
+ let name = substitute(line, '^>\(.\{-}\) .\+$', '\1', '')
2168
+ if name != line
2169
+ try
2170
+ return s:Bookmark.BookmarkFor(name)
2171
+ catch /NERDTree.BookmarkNotFound/
2172
+ return {}
2173
+ endtry
2174
+ endif
2175
+ return {}
2176
+ endfunction
2177
+
2178
+ "FUNCTION: s:getSelectedDir() {{{2
2179
+ "Returns the current node if it is a dir node, or else returns the current
2180
+ "nodes parent
2181
+ function! s:getSelectedDir()
2182
+ let currentDir = s:getSelectedNode()
2183
+ if currentDir != {} && !currentDir.isRoot()
2184
+ if currentDir.path.isDirectory == 0
2185
+ let currentDir = currentDir.parent
2186
+ endif
2187
+ endif
2188
+ return currentDir
2189
+ endfunction
2190
+ "FUNCTION: s:getSelectedNode() {{{2
2191
+ "gets the treenode that the cursor is currently over
2192
+ function! s:getSelectedNode()
2193
+ try
2194
+ let path = s:getPath(line("."))
2195
+ if path == {}
2196
+ return {}
2197
+ endif
2198
+ return t:NERDTreeRoot.findNode(path)
2199
+ catch /^NERDTree/
2200
+ return {}
2201
+ endtry
2202
+ endfunction
2203
+ "FUNCTION: s:getTreeWinNum() {{{2
2204
+ "gets the nerd tree window number for this tab
2205
+ function! s:getTreeWinNum()
2206
+ if exists("t:NERDTreeWinName")
2207
+ return bufwinnr(t:NERDTreeWinName)
2208
+ else
2209
+ return -1
2210
+ endif
2211
+ endfunction
2212
+
2213
+ "FUNCTION: s:isTreeOpen() {{{2
2214
+ function! s:isTreeOpen()
2215
+ return s:getTreeWinNum() != -1
2216
+ endfunction
2217
+
2218
+ " FUNCTION: s:jumpToChild(direction) {{{2
2219
+ " Args:
2220
+ " direction: 0 if going to first child, 1 if going to last
2221
+ function! s:jumpToChild(direction)
2222
+ let currentNode = s:getSelectedNode()
2223
+ if currentNode == {} || currentNode.isRoot()
2224
+ call s:echo("cannot jump to " . (a:direction ? "last" : "first") . " child")
2225
+ return
2226
+ end
2227
+ let dirNode = currentNode.parent
2228
+ let childNodes = dirNode.getVisibleChildren()
2229
+
2230
+ let targetNode = childNodes[0]
2231
+ if a:direction
2232
+ let targetNode = childNodes[len(childNodes) - 1]
2233
+ endif
2234
+
2235
+ if targetNode.equals(currentNode)
2236
+ let siblingDir = currentNode.parent.findOpenDirSiblingWithVisibleChildren(a:direction)
2237
+ if siblingDir != {}
2238
+ let indx = a:direction ? siblingDir.getVisibleChildCount()-1 : 0
2239
+ let targetNode = siblingDir.getChildByIndex(indx, 1)
2240
+ endif
2241
+ endif
2242
+
2243
+ call s:putCursorOnNode(targetNode, 1, 0)
2244
+
2245
+ call s:centerView()
2246
+ endfunction
2247
+
2248
+
2249
+ "FUNCTION: s:openDirNodeSplit(treenode) {{{2
2250
+ "Open the file represented by the given node in a new window.
2251
+ "No action is taken for file nodes
2252
+ "
2253
+ "ARGS:
2254
+ "treenode: file node to open
2255
+ function! s:openDirNodeSplit(treenode)
2256
+ if a:treenode.path.isDirectory == 1
2257
+ call s:openNodeSplit(a:treenode)
2258
+ endif
2259
+ endfunction
2260
+
2261
+ " FUNCTION: s:openExplorerFor(treenode) {{{2
2262
+ " opens a netrw window for the given dir treenode
2263
+ function! s:openExplorerFor(treenode)
2264
+ let oldwin = winnr()
2265
+ wincmd p
2266
+ if oldwin == winnr() || (&modified && s:bufInWindows(winbufnr(winnr())) < 2)
2267
+ wincmd p
2268
+ call s:openDirNodeSplit(a:treenode)
2269
+ else
2270
+ exec ("silent edit " . a:treenode.path.strForEditCmd())
2271
+ endif
2272
+ endfunction
2273
+ "FUNCTION: s:openFileNode(treenode) {{{2
2274
+ "Open the file represented by the given node in the current window, splitting
2275
+ "the window if needed
2276
+ "
2277
+ "ARGS:
2278
+ "treenode: file node to open
2279
+ function! s:openFileNode(treenode)
2280
+ call s:putCursorInTreeWin()
2281
+
2282
+ "if the file is already open in this tab then just stick the cursor in it
2283
+ let winnr = bufwinnr('^' . a:treenode.path.strForOS(0) . '$')
2284
+ if winnr != -1
2285
+ exec winnr . "wincmd w"
2286
+
2287
+ elseif s:shouldSplitToOpen(winnr("#"))
2288
+ call s:openFileNodeSplit(a:treenode)
2289
+ else
2290
+ try
2291
+ wincmd p
2292
+ exec ("edit " . a:treenode.path.strForEditCmd())
2293
+ catch /^Vim\%((\a\+)\)\=:E37/
2294
+ call s:putCursorInTreeWin()
2295
+ call s:echo("Cannot open file, it is already open and modified")
2296
+ catch /^Vim\%((\a\+)\)\=:/
2297
+ echo v:exception
2298
+ endtry
2299
+ endif
2300
+ endfunction
2301
+
2302
+ "FUNCTION: s:openFileNodeSplit(treenode) {{{2
2303
+ "Open the file represented by the given node in a new window.
2304
+ "No action is taken for dir nodes
2305
+ "
2306
+ "ARGS:
2307
+ "treenode: file node to open
2308
+ function! s:openFileNodeSplit(treenode)
2309
+ if a:treenode.path.isDirectory == 0
2310
+ try
2311
+ call s:openNodeSplit(a:treenode)
2312
+ catch /^NERDTree.view.FileOpen/
2313
+ call s:echo("Cannot open file, it is already open and modified" )
2314
+ endtry
2315
+ endif
2316
+ endfunction
2317
+
2318
+ "FUNCTION: s:openNodeSplit(treenode) {{{2
2319
+ "Open the file/dir represented by the given node in a new window
2320
+ "
2321
+ "ARGS:
2322
+ "treenode: file node to open
2323
+ function! s:openNodeSplit(treenode)
2324
+ call s:putCursorInTreeWin()
2325
+
2326
+ " Save the user's settings for splitbelow and splitright
2327
+ let savesplitbelow=&splitbelow
2328
+ let savesplitright=&splitright
2329
+
2330
+ " Figure out how to do the split based on the user's preferences.
2331
+ " We want to split to the (left,right,top,bottom) of the explorer
2332
+ " window, but we want to extract the screen real-estate from the
2333
+ " window next to the explorer if possible.
2334
+ "
2335
+ " 'there' will be set to a command to move from the split window
2336
+ " back to the explorer window
2337
+ "
2338
+ " 'back' will be set to a command to move from the explorer window
2339
+ " back to the newly split window
2340
+ "
2341
+ " 'right' and 'below' will be set to the settings needed for
2342
+ " splitbelow and splitright IF the explorer is the only window.
2343
+ "
2344
+ if s:shouldSplitVertically()
2345
+ let there= g:NERDTreeWinPos == "left" ? "wincmd h" : "wincmd l"
2346
+ let back = g:NERDTreeWinPos == "left" ? "wincmd l" : "wincmd h"
2347
+ let right= g:NERDTreeWinPos == "left"
2348
+ let below=0
2349
+ else
2350
+ let there= g:NERDTreeWinPos == "top" ? "wincmd k" : "wincmd j"
2351
+ let back = g:NERDTreeWinPos == "top" ? "wincmd j" : "wincmd k"
2352
+ let below= g:NERDTreeWinPos == "top"
2353
+ let right=0
2354
+ endif
2355
+
2356
+ " Attempt to go to adjacent window
2357
+ exec(back)
2358
+
2359
+ let onlyOneWin = (winnr() == s:getTreeWinNum())
2360
+
2361
+ " If no adjacent window, set splitright and splitbelow appropriately
2362
+ if onlyOneWin
2363
+ let &splitright=right
2364
+ let &splitbelow=below
2365
+ else
2366
+ " found adjacent window - invert split direction
2367
+ let &splitright=!right
2368
+ let &splitbelow=!below
2369
+ endif
2370
+
2371
+ " Create a variable to use if splitting vertically
2372
+ let splitMode = ""
2373
+ if (onlyOneWin && s:shouldSplitVertically()) || (!onlyOneWin && !s:shouldSplitVertically())
2374
+ let splitMode = "vertical"
2375
+ endif
2376
+
2377
+ echomsg splitMode
2378
+
2379
+ " Open the new window
2380
+ try
2381
+ exec(splitMode." sp " . a:treenode.path.strForEditCmd())
2382
+ catch /^Vim\%((\a\+)\)\=:E37/
2383
+ call s:putCursorInTreeWin()
2384
+ throw "NERDTree.view.FileOpen exception: ". a:treenode.path.str(0) ." is already open and modified."
2385
+ catch /^Vim\%((\a\+)\)\=:/
2386
+ "do nothing
2387
+ endtry
2388
+
2389
+ "resize the tree window if no other window was open before
2390
+ if onlyOneWin
2391
+ let size = exists("t:NERDTreeOldWindowSize") ? t:NERDTreeOldWindowSize : g:NERDTreeWinSize
2392
+ exec(there)
2393
+ exec("silent ". splitMode ." resize ". size)
2394
+ wincmd p
2395
+ endif
2396
+
2397
+ " Restore splitmode settings
2398
+ let &splitbelow=savesplitbelow
2399
+ let &splitright=savesplitright
2400
+ endfunction
2401
+
2402
+ "FUNCTION: s:promptToDelBuffer(bufnum, msg){{{2
2403
+ "prints out the given msg and, if the user responds by pushing 'y' then the
2404
+ "buffer with the given bufnum is deleted
2405
+ "
2406
+ "Args:
2407
+ "bufnum: the buffer that may be deleted
2408
+ "msg: a message that will be echoed to the user asking them if they wish to
2409
+ " del the buffer
2410
+ function! s:promptToDelBuffer(bufnum, msg)
2411
+ echo a:msg
2412
+ if nr2char(getchar()) == 'y'
2413
+ exec "silent bdelete! " . a:bufnum
2414
+ endif
2415
+ endfunction
2416
+
2417
+ "FUNCTION: s:putCursorOnBookmarkTable(){{{2
2418
+ "Places the cursor at the top of the bookmarks table
2419
+ function! s:putCursorOnBookmarkTable()
2420
+ if !t:NERDTreeShowBookmarks
2421
+ throw "NERDTree.IllegalOperation exception: cant find bookmark table, bookmarks arent active"
2422
+ endif
2423
+
2424
+ let rootNodeLine = s:findRootNodeLineNumber()
2425
+
2426
+ let line = 1
2427
+ while getline(line) !~ '^>-\+Bookmarks-\+$'
2428
+ let line = line + 1
2429
+ if line >= rootNodeLine
2430
+ throw "NERDTree.BookmarkTableNotFound exception: didnt find the bookmarks table"
2431
+ endif
2432
+ endwhile
2433
+ call cursor(line, 0)
2434
+ endfunction
2435
+
2436
+ "FUNCTION: s:putCursorOnNode(treenode, isJump, recurseUpward){{{2
2437
+ "Places the cursor on the line number representing the given node
2438
+ "
2439
+ "Args:
2440
+ "treenode: the node to put the cursor on
2441
+ "isJump: 1 if this cursor movement should be counted as a jump by vim
2442
+ "recurseUpward: try to put the cursor on the parent if the this node isnt
2443
+ "visible
2444
+ function! s:putCursorOnNode(treenode, isJump, recurseUpward)
2445
+ let ln = s:findNodeLineNumber(a:treenode)
2446
+ if ln != -1
2447
+ if a:isJump
2448
+ mark '
2449
+ endif
2450
+ call cursor(ln, col("."))
2451
+ else
2452
+ if a:recurseUpward
2453
+ let node = a:treenode
2454
+ while s:findNodeLineNumber(node) == -1 && node != {}
2455
+ let node = node.parent
2456
+ call node.open()
2457
+ endwhile
2458
+ call s:renderView()
2459
+ call s:putCursorOnNode(a:treenode, a:isJump, 0)
2460
+ endif
2461
+ endif
2462
+ endfunction
2463
+
2464
+ "FUNCTION: s:putCursorInTreeWin(){{{2
2465
+ "Places the cursor in the nerd tree window
2466
+ function! s:putCursorInTreeWin()
2467
+ if !s:isTreeOpen()
2468
+ throw "NERDTree.view.InvalidOperation Exception: No NERD tree window exists"
2469
+ endif
2470
+
2471
+ exec s:getTreeWinNum() . "wincmd w"
2472
+ endfunction
2473
+
2474
+ "FUNCTION: s:renderBookmarks {{{2
2475
+ function! s:renderBookmarks()
2476
+
2477
+ call setline(line(".")+1, ">----------Bookmarks----------")
2478
+ call cursor(line(".")+1, col("."))
2479
+
2480
+ for i in s:Bookmark.Bookmarks()
2481
+ call setline(line(".")+1, i.str())
2482
+ call cursor(line(".")+1, col("."))
2483
+ endfor
2484
+
2485
+ call setline(line(".")+1, '')
2486
+ call cursor(line(".")+1, col("."))
2487
+ endfunction
2488
+ "FUNCTION: s:renderView {{{2
2489
+ "The entry function for rendering the tree. Renders the root then calls
2490
+ "s:drawTree to draw the children of the root
2491
+ "
2492
+ "Args:
2493
+ function! s:renderView()
2494
+ execute s:getTreeWinNum() . "wincmd w"
2495
+
2496
+ setlocal modifiable
2497
+
2498
+ "remember the top line of the buffer and the current line so we can
2499
+ "restore the view exactly how it was
2500
+ let curLine = line(".")
2501
+ let curCol = col(".")
2502
+ let topLine = line("w0")
2503
+
2504
+ "delete all lines in the buffer (being careful not to clobber a register)
2505
+ silent 1,$delete _
2506
+
2507
+ call s:dumpHelp()
2508
+
2509
+ "delete the blank line before the help and add one after it
2510
+ call setline(line(".")+1, "")
2511
+ call cursor(line(".")+1, col("."))
2512
+
2513
+ if t:NERDTreeShowBookmarks
2514
+ call s:renderBookmarks()
2515
+ endif
2516
+
2517
+ "add the 'up a dir' line
2518
+ call setline(line(".")+1, s:tree_up_dir_line)
2519
+ call cursor(line(".")+1, col("."))
2520
+
2521
+ "draw the header line
2522
+ call setline(line(".")+1, t:NERDTreeRoot.path.str(0))
2523
+ call cursor(line(".")+1, col("."))
2524
+
2525
+ "draw the tree
2526
+ call s:drawTree(t:NERDTreeRoot, 0, 0, [], t:NERDTreeRoot.getChildCount() == 1)
2527
+
2528
+ "delete the blank line at the top of the buffer
2529
+ silent 1,1delete _
2530
+
2531
+ "restore the view
2532
+ let old_scrolloff=&scrolloff
2533
+ let &scrolloff=0
2534
+ call cursor(topLine, 1)
2535
+ normal! zt
2536
+ call cursor(curLine, curCol)
2537
+ let &scrolloff = old_scrolloff
2538
+
2539
+ setlocal nomodifiable
2540
+ endfunction
2541
+
2542
+ "FUNCTION: s:renderViewSavingPosition {{{2
2543
+ "Renders the tree and ensures the cursor stays on the current node or the
2544
+ "current nodes parent if it is no longer available upon re-rendering
2545
+ function! s:renderViewSavingPosition()
2546
+ let currentNode = s:getSelectedNode()
2547
+
2548
+ "go up the tree till we find a node that will be visible or till we run
2549
+ "out of nodes
2550
+ while currentNode != {} && !currentNode.isVisible() && !currentNode.isRoot()
2551
+ let currentNode = currentNode.parent
2552
+ endwhile
2553
+
2554
+ call s:renderView()
2555
+
2556
+ if currentNode != {}
2557
+ call s:putCursorOnNode(currentNode, 0, 0)
2558
+ endif
2559
+ endfunction
2560
+ "FUNCTION: s:restoreScreenState() {{{2
2561
+ "
2562
+ "Sets the screen state back to what it was when s:saveScreenState was last
2563
+ "called.
2564
+ "
2565
+ "Assumes the cursor is in the NERDTree window
2566
+ function! s:restoreScreenState()
2567
+ if !exists("t:NERDTreeOldTopLine") || !exists("t:NERDTreeOldPos") || !exists("t:NERDTreeOldWindowSize")
2568
+ return
2569
+ endif
2570
+ exec("silent ". (s:shouldSplitVertically() ? "vertical" : "") ." resize ".t:NERDTreeOldWindowSize)
2571
+
2572
+ let old_scrolloff=&scrolloff
2573
+ let &scrolloff=0
2574
+ call cursor(t:NERDTreeOldTopLine, 0)
2575
+ normal! zt
2576
+ call setpos(".", t:NERDTreeOldPos)
2577
+ let &scrolloff=old_scrolloff
2578
+ endfunction
2579
+
2580
+ "FUNCTION: s:saveScreenState() {{{2
2581
+ "Saves the current cursor position in the current buffer and the window
2582
+ "scroll position
2583
+ function! s:saveScreenState()
2584
+ let win = winnr()
2585
+ call s:putCursorInTreeWin()
2586
+ let t:NERDTreeOldPos = getpos(".")
2587
+ let t:NERDTreeOldTopLine = line("w0")
2588
+ let t:NERDTreeOldWindowSize = s:shouldSplitVertically() ? winwidth("") : winheight("")
2589
+ exec win . "wincmd w"
2590
+ endfunction
2591
+
2592
+ "FUNCTION: s:setupSyntaxHighlighting() {{{2
2593
+ function! s:setupSyntaxHighlighting()
2594
+ "treeFlags are syntax items that should be invisible, but give clues as to
2595
+ "how things should be highlighted
2596
+ syn match treeFlag #\~#
2597
+ syn match treeFlag #\[RO\]#
2598
+
2599
+ "highlighting for the .. (up dir) line at the top of the tree
2600
+ execute "syn match treeUp #". s:tree_up_dir_line ."#"
2601
+
2602
+ "highlighting for the ~/+ symbols for the directory nodes
2603
+ syn match treeClosable #\~\<#
2604
+ syn match treeClosable #\~\.#
2605
+ syn match treeOpenable #+\<#
2606
+ syn match treeOpenable #+\.#he=e-1
2607
+
2608
+ "highlighting for the tree structural parts
2609
+ syn match treePart #|#
2610
+ syn match treePart #`#
2611
+ syn match treePartFile #[|`]-#hs=s+1 contains=treePart
2612
+
2613
+ "quickhelp syntax elements
2614
+ syn match treeHelpKey #" \{1,2\}[^ ]*:#hs=s+2,he=e-1
2615
+ syn match treeHelpKey #" \{1,2\}[^ ]*,#hs=s+2,he=e-1
2616
+ syn match treeHelpTitle #" .*\~#hs=s+2,he=e-1 contains=treeFlag
2617
+ syn match treeToggleOn #".*(on)#hs=e-2,he=e-1 contains=treeHelpKey
2618
+ syn match treeToggleOff #".*(off)#hs=e-3,he=e-1 contains=treeHelpKey
2619
+ syn match treeHelpCommand #" :.\{-}\>#hs=s+3
2620
+ syn match treeHelp #^".*# contains=treeHelpKey,treeHelpTitle,treeFlag,treeToggleOff,treeToggleOn,treeHelpCommand
2621
+
2622
+ "highlighting for readonly files
2623
+ syn match treeRO #[\/0-9a-zA-Z]\+.*\[RO\]# contains=treeFlag,treeBookmark
2624
+
2625
+ "highlighting for sym links
2626
+ syn match treeLink #[^-| `].* -> # contains=treeBookmark,treeOpenable,treeClosable,treeDirSlash
2627
+
2628
+ "highlighing for directory nodes and file nodes
2629
+ syn match treeDirSlash #/#
2630
+ syn match treeDir #[^-| `].*/# contains=treeLink,treeDirSlash,treeOpenable,treeClosable
2631
+ syn match treeExecFile #[|`]-.*\*\($\| \)# contains=treeLink,treePart,treeRO,treePartFile,treeBookmark
2632
+ syn match treeFile #|-.*# contains=treeLink,treePart,treeRO,treePartFile,treeBookmark,treeExecFile
2633
+ syn match treeFile #`-.*# contains=treeLink,treePart,treeRO,treePartFile,treeBookmark,treeExecFile
2634
+ syn match treeCWD #^/.*$#
2635
+
2636
+ "highlighting for bookmarks
2637
+ syn match treeBookmark # {.*}#hs=s+1
2638
+
2639
+ "highlighting for the bookmarks table
2640
+ syn match treeBookmarksLeader #^>#
2641
+ syn match treeBookmarksHeader #^>-\+Bookmarks-\+$# contains=treeBookmarksLeader
2642
+ syn match treeBookmarkName #^>.\{-} #he=e-1 contains=treeBookmarksLeader
2643
+ syn match treeBookmark #^>.*$# contains=treeBookmarksLeader,treeBookmarkName,treeBookmarksHeader
2644
+
2645
+ if g:NERDChristmasTree
2646
+ hi def link treePart Special
2647
+ hi def link treePartFile Type
2648
+ hi def link treeFile Normal
2649
+ hi def link treeExecFile Title
2650
+ hi def link treeDirSlash Identifier
2651
+ hi def link treeClosable Type
2652
+ else
2653
+ hi def link treePart Normal
2654
+ hi def link treePartFile Normal
2655
+ hi def link treeFile Normal
2656
+ hi def link treeClosable Title
2657
+ endif
2658
+
2659
+ hi def link treeBookmarksHeader statement
2660
+ hi def link treeBookmarksLeader ignore
2661
+ hi def link treeBookmarkName Identifier
2662
+ hi def link treeBookmark normal
2663
+
2664
+ hi def link treeHelp String
2665
+ hi def link treeHelpKey Identifier
2666
+ hi def link treeHelpCommand Identifier
2667
+ hi def link treeHelpTitle Macro
2668
+ hi def link treeToggleOn Question
2669
+ hi def link treeToggleOff WarningMsg
2670
+
2671
+ hi def link treeDir Directory
2672
+ hi def link treeUp Directory
2673
+ hi def link treeCWD Statement
2674
+ hi def link treeLink Macro
2675
+ hi def link treeOpenable Title
2676
+ hi def link treeFlag ignore
2677
+ hi def link treeRO WarningMsg
2678
+ hi def link treeBookmark Statement
2679
+
2680
+ hi def link NERDTreeCurrentNode Search
2681
+ endfunction
2682
+
2683
+ "FUNCTION: s:shouldSplitToOpen() {{{2
2684
+ "Returns 1 if opening a file from the tree in the given window requires it to
2685
+ "be split
2686
+ "
2687
+ "Args:
2688
+ "winnumber: the number of the window in question
2689
+ function! s:shouldSplitToOpen(winnumber)
2690
+ "gotta split if theres only one window (i.e. the NERD tree)
2691
+ if winnr("$") == 1
2692
+ return 1
2693
+ endif
2694
+
2695
+ let oldwinnr = winnr()
2696
+ exec a:winnumber . "wincmd p"
2697
+ let specialWindow = getbufvar("%", '&buftype') != '' || getwinvar('%', '&previewwindow')
2698
+ let modified = &modified
2699
+ exec oldwinnr . "wincmd p"
2700
+
2701
+ "if its a special window e.g. quickfix or another explorer plugin then we
2702
+ "have to split
2703
+ if specialWindow
2704
+ return 1
2705
+ endif
2706
+
2707
+ if &hidden
2708
+ return 0
2709
+ endif
2710
+
2711
+ return modified && s:bufInWindows(winbufnr(a:winnumber)) < 2
2712
+ endfunction
2713
+
2714
+ " Function: s:shouldSplitVertically() {{{2
2715
+ " Returns 1 if g:NERDTreeWinPos is 'left' or 'right'
2716
+ function! s:shouldSplitVertically()
2717
+ return g:NERDTreeWinPos == 'left' || g:NERDTreeWinPos == 'right'
2718
+ endfunction
2719
+ "FUNCTION: s:stripMarkupFromLine(line, removeLeadingSpaces){{{2
2720
+ "returns the given line with all the tree parts stripped off
2721
+ "
2722
+ "Args:
2723
+ "line: the subject line
2724
+ "removeLeadingSpaces: 1 if leading spaces are to be removed (leading spaces =
2725
+ "any spaces before the actual text of the node)
2726
+ function! s:stripMarkupFromLine(line, removeLeadingSpaces)
2727
+ let line = a:line
2728
+ "remove the tree parts and the leading space
2729
+ let line = substitute (line,"^" . s:tree_markup_reg . "*","","")
2730
+
2731
+ "strip off any read only flag
2732
+ let line = substitute (line, ' \[RO\]', "","")
2733
+
2734
+ "strip off any bookmark flags
2735
+ let line = substitute (line, ' {[^}]*}', "","")
2736
+
2737
+ "strip off any executable flags
2738
+ let line = substitute (line, '*\ze\($\| \)', "","")
2739
+
2740
+ let wasdir = 0
2741
+ if line =~ '/$'
2742
+ let wasdir = 1
2743
+ endif
2744
+ let line = substitute (line,' -> .*',"","") " remove link to
2745
+ if wasdir == 1
2746
+ let line = substitute (line, '/\?$', '/', "")
2747
+ endif
2748
+
2749
+ if a:removeLeadingSpaces
2750
+ let line = substitute (line, '^ *', '', '')
2751
+ endif
2752
+
2753
+ return line
2754
+ endfunction
2755
+
2756
+ "FUNCTION: s:toggle(dir) {{{2
2757
+ "Toggles the NERD tree. I.e the NERD tree is open, it is closed, if it is
2758
+ "closed it is restored or initialized (if it doesnt exist)
2759
+ "
2760
+ "Args:
2761
+ "dir: the full path for the root node (is only used if the NERD tree is being
2762
+ "initialized.
2763
+ function! s:toggle(dir)
2764
+ if s:treeExistsForTab()
2765
+ if !s:isTreeOpen()
2766
+ call s:createTreeWin()
2767
+ call s:renderView()
2768
+
2769
+ call s:restoreScreenState()
2770
+ else
2771
+ call s:closeTree()
2772
+ endif
2773
+ else
2774
+ call s:initNerdTree(a:dir)
2775
+ endif
2776
+ endfunction
2777
+ "SECTION: Interface bindings {{{1
2778
+ "============================================================
2779
+ "FUNCTION: s:activateNode(forceKeepWindowOpen) {{{2
2780
+ "If the current node is a file, open it in the previous window (or a new one
2781
+ "if the previous is modified). If it is a directory then it is opened.
2782
+ "
2783
+ "args:
2784
+ "forceKeepWindowOpen - dont close the window even if NERDTreeQuitOnOpen is set
2785
+ function! s:activateNode(forceKeepWindowOpen)
2786
+ if getline(".") == s:tree_up_dir_line
2787
+ return s:upDir(0)
2788
+ endif
2789
+
2790
+ let treenode = s:getSelectedNode()
2791
+ if treenode != {}
2792
+ if treenode.path.isDirectory
2793
+ call treenode.toggleOpen()
2794
+ call s:renderView()
2795
+ call s:putCursorOnNode(treenode, 0, 0)
2796
+ else
2797
+ call s:openFileNode(treenode)
2798
+ if !a:forceKeepWindowOpen
2799
+ call s:closeTreeIfQuitOnOpen()
2800
+ end
2801
+ endif
2802
+ else
2803
+ let bookmark = s:getSelectedBookmark()
2804
+ if !empty(bookmark)
2805
+ if bookmark.path.isDirectory
2806
+ call bookmark.toRoot()
2807
+ else
2808
+ if bookmark.validate()
2809
+ call s:openFileNode(s:TreeFileNode.New(bookmark.path))
2810
+ endif
2811
+ endif
2812
+ endif
2813
+ endif
2814
+ endfunction
2815
+
2816
+ "FUNCTION: s:bindMappings() {{{2
2817
+ function! s:bindMappings()
2818
+ " set up mappings and commands for this buffer
2819
+ nnoremap <silent> <buffer> <middlerelease> :call <SID>handleMiddleMouse()<cr>
2820
+ nnoremap <silent> <buffer> <leftrelease> <leftrelease>:call <SID>checkForActivate()<cr>
2821
+ nnoremap <silent> <buffer> <2-leftmouse> :call <SID>activateNode(0)<cr>
2822
+
2823
+ exec "nnoremap <silent> <buffer> ". g:NERDTreeMapActivateNode . " :call <SID>activateNode(0)<cr>"
2824
+ exec "nnoremap <silent> <buffer> ". g:NERDTreeMapOpenSplit ." :call <SID>openEntrySplit(0)<cr>"
2825
+
2826
+ exec "nnoremap <silent> <buffer> ". g:NERDTreeMapPreview ." :call <SID>previewNode(0)<cr>"
2827
+ exec "nnoremap <silent> <buffer> ". g:NERDTreeMapPreviewSplit ." :call <SID>previewNode(1)<cr>"
2828
+
2829
+
2830
+ exec "nnoremap <silent> <buffer> ". g:NERDTreeMapExecute ." :call <SID>executeNode()<cr>"
2831
+
2832
+ exec "nnoremap <silent> <buffer> ". g:NERDTreeMapOpenRecursively ." :call <SID>openNodeRecursively()<cr>"
2833
+
2834
+ exec "nnoremap <silent> <buffer> ". g:NERDTreeMapUpdirKeepOpen ." :call <SID>upDir(1)<cr>"
2835
+ exec "nnoremap <silent> <buffer> ". g:NERDTreeMapUpdir ." :call <SID>upDir(0)<cr>"
2836
+ exec "nnoremap <silent> <buffer> ". g:NERDTreeMapChangeRoot ." :call <SID>chRoot()<cr>"
2837
+
2838
+ exec "nnoremap <silent> <buffer> ". g:NERDTreeMapChdir ." :call <SID>chCwd()<cr>"
2839
+
2840
+ exec "nnoremap <silent> <buffer> ". g:NERDTreeMapQuit ." :NERDTreeToggle<cr>"
2841
+
2842
+ exec "nnoremap <silent> <buffer> ". g:NERDTreeMapRefreshRoot ." :call <SID>refreshRoot()<cr>"
2843
+ exec "nnoremap <silent> <buffer> ". g:NERDTreeMapRefresh ." :call <SID>refreshCurrent()<cr>"
2844
+
2845
+ exec "nnoremap <silent> <buffer> ". g:NERDTreeMapHelp ." :call <SID>displayHelp()<cr>"
2846
+ exec "nnoremap <silent> <buffer> ". g:NERDTreeMapToggleHidden ." :call <SID>toggleShowHidden()<cr>"
2847
+ exec "nnoremap <silent> <buffer> ". g:NERDTreeMapToggleFilters ." :call <SID>toggleIgnoreFilter()<cr>"
2848
+ exec "nnoremap <silent> <buffer> ". g:NERDTreeMapToggleFiles ." :call <SID>toggleShowFiles()<cr>"
2849
+ exec "nnoremap <silent> <buffer> ". g:NERDTreeMapToggleBookmarks ." :call <SID>toggleShowBookmarks()<cr>"
2850
+
2851
+ exec "nnoremap <silent> <buffer> ". g:NERDTreeMapCloseDir ." :call <SID>closeCurrentDir()<cr>"
2852
+ exec "nnoremap <silent> <buffer> ". g:NERDTreeMapCloseChildren ." :call <SID>closeChildren()<cr>"
2853
+
2854
+ exec "nnoremap <silent> <buffer> ". g:NERDTreeMapFilesystemMenu ." :call <SID>showFileSystemMenu()<cr>"
2855
+
2856
+ exec "nnoremap <silent> <buffer> ". g:NERDTreeMapJumpParent ." :call <SID>jumpToParent()<cr>"
2857
+ exec "nnoremap <silent> <buffer> ". g:NERDTreeMapJumpNextSibling ." :call <SID>jumpToSibling(1)<cr>"
2858
+ exec "nnoremap <silent> <buffer> ". g:NERDTreeMapJumpPrevSibling ." :call <SID>jumpToSibling(0)<cr>"
2859
+ exec "nnoremap <silent> <buffer> ". g:NERDTreeMapJumpFirstChild ." :call <SID>jumpToFirstChild()<cr>"
2860
+ exec "nnoremap <silent> <buffer> ". g:NERDTreeMapJumpLastChild ." :call <SID>jumpToLastChild()<cr>"
2861
+ exec "nnoremap <silent> <buffer> ". g:NERDTreeMapJumpRoot ." :call <SID>jumpToRoot()<cr>"
2862
+
2863
+ exec "nnoremap <silent> <buffer> ". g:NERDTreeMapOpenInTab ." :call <SID>openInNewTab(0)<cr>"
2864
+ exec "nnoremap <silent> <buffer> ". g:NERDTreeMapOpenInTabSilent ." :call <SID>openInNewTab(1)<cr>"
2865
+
2866
+ exec "nnoremap <silent> <buffer> ". g:NERDTreeMapOpenExpl ." :call <SID>openExplorer()<cr>"
2867
+
2868
+ exec "nnoremap <silent> <buffer> ". g:NERDTreeMapDeleteBookmark ." :call <SID>deleteBookmark()<cr>"
2869
+
2870
+ command! -buffer -nargs=1 Bookmark :call <SID>bookmarkNode('<args>')
2871
+ command! -buffer -complete=customlist,s:completeBookmarks -nargs=1 RevealBookmark :call <SID>revealBookmark('<args>')
2872
+ command! -buffer -complete=customlist,s:completeBookmarks -nargs=1 OpenBookmark :call <SID>openBookmark('<args>')
2873
+ command! -buffer -complete=customlist,s:completeBookmarks -nargs=* ClearBookmarks call <SID>clearBookmarks('<args>')
2874
+ command! -buffer -complete=customlist,s:completeBookmarks -nargs=+ BookmarkToRoot call s:Bookmark.ToRoot('<args>')
2875
+ command! -buffer -nargs=0 ClearAllBookmarks call s:Bookmark.ClearAll() <bar> call <SID>renderView()
2876
+ command! -buffer -nargs=0 ReadBookmarks call s:Bookmark.CacheBookmarks(0) <bar> call <SID>renderView()
2877
+ command! -buffer -nargs=0 WriteBookmarks call s:Bookmark.Write()
2878
+ endfunction
2879
+
2880
+ " FUNCTION: s:bookmarkNode(name) {{{2
2881
+ " Associate the current node with the given name
2882
+ function! s:bookmarkNode(name)
2883
+ let currentNode = s:getSelectedNode()
2884
+ if currentNode != {}
2885
+ try
2886
+ call currentNode.bookmark(a:name)
2887
+ call s:renderView()
2888
+ catch /NERDTree.IllegalBookmarkName/
2889
+ call s:echo("bookmark names must not contain spaces")
2890
+ endtry
2891
+ else
2892
+ call s:echo("select a node first")
2893
+ endif
2894
+ endfunction
2895
+ "FUNCTION: s:checkForActivate() {{{2
2896
+ "Checks if the click should open the current node, if so then activate() is
2897
+ "called (directories are automatically opened if the symbol beside them is
2898
+ "clicked)
2899
+ function! s:checkForActivate()
2900
+ let currentNode = s:getSelectedNode()
2901
+ if currentNode != {}
2902
+ let startToCur = strpart(getline(line(".")), 0, col("."))
2903
+ let char = strpart(startToCur, strlen(startToCur)-1, 1)
2904
+
2905
+ "if they clicked a dir, check if they clicked on the + or ~ sign
2906
+ "beside it
2907
+ if currentNode.path.isDirectory
2908
+ let reg = '^' . s:tree_markup_reg .'*[~+]$'
2909
+ if startToCur =~ reg
2910
+ call s:activateNode(0)
2911
+ return
2912
+ endif
2913
+ endif
2914
+
2915
+ if (g:NERDTreeMouseMode == 2 && currentNode.path.isDirectory) || g:NERDTreeMouseMode == 3
2916
+ if char !~ s:tree_markup_reg && startToCur !~ '\/$'
2917
+ call s:activateNode(0)
2918
+ return
2919
+ endif
2920
+ endif
2921
+ endif
2922
+ endfunction
2923
+
2924
+ " FUNCTION: s:chCwd() {{{2
2925
+ function! s:chCwd()
2926
+ let treenode = s:getSelectedNode()
2927
+ if treenode == {}
2928
+ call s:echo("Select a node first")
2929
+ return
2930
+ endif
2931
+
2932
+ try
2933
+ call treenode.path.changeToDir()
2934
+ catch /^NERDTree.Path.Change/
2935
+ call s:echoWarning("could not change cwd")
2936
+ endtry
2937
+ endfunction
2938
+
2939
+ " FUNCTION: s:chRoot() {{{2
2940
+ " changes the current root to the selected one
2941
+ function! s:chRoot()
2942
+ let treenode = s:getSelectedNode()
2943
+ if treenode == {}
2944
+ call s:echo("Select a node first")
2945
+ return
2946
+ endif
2947
+
2948
+ call treenode.makeRoot()
2949
+ call s:renderView()
2950
+ call s:putCursorOnNode(t:NERDTreeRoot, 0, 0)
2951
+ endfunction
2952
+
2953
+ " FUNCTION: s:clearBookmarks(bookmarks) {{{2
2954
+ function! s:clearBookmarks(bookmarks)
2955
+ if a:bookmarks == ''
2956
+ let currentNode = s:getSelectedNode()
2957
+ if currentNode != {}
2958
+ call currentNode.clearBoomarks()
2959
+ endif
2960
+ else
2961
+ for name in split(a:bookmarks, ' ')
2962
+ let bookmark = s:Bookmark.BookmarkFor(name)
2963
+ call bookmark.delete()
2964
+ endfor
2965
+ endif
2966
+ call s:renderView()
2967
+ endfunction
2968
+ " FUNCTION: s:closeChildren() {{{2
2969
+ " closes all childnodes of the current node
2970
+ function! s:closeChildren()
2971
+ let currentNode = s:getSelectedDir()
2972
+ if currentNode == {}
2973
+ call s:echo("Select a node first")
2974
+ return
2975
+ endif
2976
+
2977
+ call currentNode.closeChildren()
2978
+ call s:renderView()
2979
+ call s:putCursorOnNode(currentNode, 0, 0)
2980
+ endfunction
2981
+ " FUNCTION: s:closeCurrentDir() {{{2
2982
+ " closes the parent dir of the current node
2983
+ function! s:closeCurrentDir()
2984
+ let treenode = s:getSelectedNode()
2985
+ if treenode == {}
2986
+ call s:echo("Select a node first")
2987
+ return
2988
+ endif
2989
+
2990
+ let parent = treenode.parent
2991
+ if parent.isRoot()
2992
+ call s:echo("cannot close tree root")
2993
+ else
2994
+ call treenode.parent.close()
2995
+ call s:renderView()
2996
+ call s:putCursorOnNode(treenode.parent, 0, 0)
2997
+ endif
2998
+ endfunction
2999
+
3000
+ " FUNCTION: s:copyNode() {{{2
3001
+ function! s:copyNode()
3002
+ let currentNode = s:getSelectedNode()
3003
+ if currentNode == {}
3004
+ call s:echo("Put the cursor on a file node first")
3005
+ return
3006
+ endif
3007
+
3008
+ let newNodePath = input("Copy the current node\n" .
3009
+ \ "==========================================================\n" .
3010
+ \ "Enter the new path to copy the node to: \n" .
3011
+ \ "", currentNode.path.str(0))
3012
+
3013
+ if newNodePath != ""
3014
+ "strip trailing slash
3015
+ let newNodePath = substitute(newNodePath, '\/$', '', '')
3016
+
3017
+ let confirmed = 1
3018
+ if currentNode.path.copyingWillOverwrite(newNodePath)
3019
+ call s:echo("\nWarning: copying may overwrite files! Continue? (yN)")
3020
+ let choice = nr2char(getchar())
3021
+ let confirmed = choice == 'y'
3022
+ endif
3023
+
3024
+ if confirmed
3025
+ try
3026
+ let newNode = currentNode.copy(newNodePath)
3027
+ call s:renderView()
3028
+ call s:putCursorOnNode(newNode, 0, 0)
3029
+ catch /^NERDTree/
3030
+ call s:echoWarning("Could not copy node")
3031
+ endtry
3032
+ endif
3033
+ else
3034
+ call s:echo("Copy aborted.")
3035
+ endif
3036
+ redraw
3037
+ endfunction
3038
+
3039
+ " FUNCTION: s:deleteBookmark() {{{2
3040
+ " if the cursor is on a bookmark, prompt to delete
3041
+ function! s:deleteBookmark()
3042
+ let bookmark = s:getSelectedBookmark()
3043
+ if bookmark == {}
3044
+ call s:echo("Put the cursor on a bookmark")
3045
+ return
3046
+ endif
3047
+
3048
+ echo "Are you sure you wish to delete the bookmark:\n\"" . bookmark.name . "\" (yN):"
3049
+
3050
+ if nr2char(getchar()) == 'y'
3051
+ try
3052
+ call bookmark.delete()
3053
+ call s:renderView()
3054
+ redraw
3055
+ catch /^NERDTree/
3056
+ call s:echoWarning("Could not remove bookmark")
3057
+ endtry
3058
+ else
3059
+ call s:echo("delete aborted" )
3060
+ endif
3061
+
3062
+ endfunction
3063
+
3064
+ " FUNCTION: s:deleteNode() {{{2
3065
+ " if the current node is a file, pops up a dialog giving the user the option
3066
+ " to delete it
3067
+ function! s:deleteNode()
3068
+ let currentNode = s:getSelectedNode()
3069
+ if currentNode == {}
3070
+ call s:echo("Put the cursor on a file node first")
3071
+ return
3072
+ endif
3073
+
3074
+ let confirmed = 0
3075
+
3076
+ if currentNode.path.isDirectory
3077
+ let choice =input("Delete the current node\n" .
3078
+ \ "==========================================================\n" .
3079
+ \ "STOP! To delete this entire directory, type 'yes'\n" .
3080
+ \ "" . currentNode.path.strForOS(0) . ": ")
3081
+ let confirmed = choice == 'yes'
3082
+ else
3083
+ echo "Delete the current node\n" .
3084
+ \ "==========================================================\n".
3085
+ \ "Are you sure you wish to delete the node:\n" .
3086
+ \ "" . currentNode.path.strForOS(0) . " (yN):"
3087
+ let choice = nr2char(getchar())
3088
+ let confirmed = choice == 'y'
3089
+ endif
3090
+
3091
+
3092
+ if confirmed
3093
+ try
3094
+ call currentNode.delete()
3095
+ call s:renderView()
3096
+
3097
+ "if the node is open in a buffer, ask the user if they want to
3098
+ "close that buffer
3099
+ let bufnum = bufnr(currentNode.path.str(0))
3100
+ if buflisted(bufnum)
3101
+ let prompt = "\nNode deleted.\n\nThe file is open in buffer ". bufnum . (bufwinnr(bufnum) == -1 ? " (hidden)" : "") .". Delete this buffer? (yN)"
3102
+ call s:promptToDelBuffer(bufnum, prompt)
3103
+ endif
3104
+
3105
+ redraw
3106
+ catch /^NERDTree/
3107
+ call s:echoWarning("Could not remove node")
3108
+ endtry
3109
+ else
3110
+ call s:echo("delete aborted" )
3111
+ endif
3112
+
3113
+ endfunction
3114
+
3115
+ " FUNCTION: s:displayHelp() {{{2
3116
+ " toggles the help display
3117
+ function! s:displayHelp()
3118
+ let t:treeShowHelp = t:treeShowHelp ? 0 : 1
3119
+ call s:renderView()
3120
+ call s:centerView()
3121
+ endfunction
3122
+
3123
+ " FUNCTION: s:executeNode() {{{2
3124
+ function! s:executeNode()
3125
+ let treenode = s:getSelectedNode()
3126
+ if treenode == {} || treenode.path.isDirectory
3127
+ call s:echo("Select an executable file node first" )
3128
+ else
3129
+ echo "NERDTree executor\n" .
3130
+ \ "==========================================================\n".
3131
+ \ "Complete the command to execute (add arguments etc): \n\n"
3132
+ let cmd = treenode.path.strForOS(1)
3133
+ let cmd = input(':!', cmd . ' ')
3134
+
3135
+ if cmd != ''
3136
+ exec ':!' . cmd
3137
+ else
3138
+ call s:echo("command aborted")
3139
+ endif
3140
+ endif
3141
+ endfunction
3142
+
3143
+ " FUNCTION: s:handleMiddleMouse() {{{2
3144
+ function! s:handleMiddleMouse()
3145
+ let curNode = s:getSelectedNode()
3146
+ if curNode == {}
3147
+ call s:echo("Put the cursor on a node first" )
3148
+ return
3149
+ endif
3150
+
3151
+ if curNode.path.isDirectory
3152
+ call s:openExplorer()
3153
+ else
3154
+ call s:openEntrySplit(0)
3155
+ endif
3156
+ endfunction
3157
+
3158
+
3159
+ " FUNCTION: s:insertNewNode() {{{2
3160
+ " Adds a new node to the filesystem and then into the tree
3161
+ function! s:insertNewNode()
3162
+ let curDirNode = s:getSelectedDir()
3163
+ if curDirNode == {}
3164
+ call s:echo("Put the cursor on a node first" )
3165
+ return
3166
+ endif
3167
+
3168
+ let newNodeName = input("Add a childnode\n".
3169
+ \ "==========================================================\n".
3170
+ \ "Enter the dir/file name to be created. Dirs end with a '/'\n" .
3171
+ \ "", curDirNode.path.strForGlob() . s:os_slash)
3172
+
3173
+ if newNodeName == ''
3174
+ call s:echo("Node Creation Aborted.")
3175
+ return
3176
+ endif
3177
+
3178
+ try
3179
+ let newPath = s:Path.Create(newNodeName)
3180
+ let parentNode = t:NERDTreeRoot.findNode(newPath.getPathTrunk())
3181
+
3182
+ let newTreeNode = s:TreeFileNode.New(newPath)
3183
+ if parentNode.isOpen || !empty(parentNode.children)
3184
+ call parentNode.addChild(newTreeNode, 1)
3185
+ call s:renderView()
3186
+ call s:putCursorOnNode(newTreeNode, 1, 0)
3187
+ endif
3188
+ catch /^NERDTree/
3189
+ call s:echoWarning("Node Not Created.")
3190
+ endtry
3191
+ endfunction
3192
+
3193
+ " FUNCTION: s:jumpToFirstChild() {{{2
3194
+ " wrapper for the jump to child method
3195
+ function! s:jumpToFirstChild()
3196
+ call s:jumpToChild(0)
3197
+ endfunction
3198
+
3199
+ " FUNCTION: s:jumpToLastChild() {{{2
3200
+ " wrapper for the jump to child method
3201
+ function! s:jumpToLastChild()
3202
+ call s:jumpToChild(1)
3203
+ endfunction
3204
+
3205
+ " FUNCTION: s:jumpToParent() {{{2
3206
+ " moves the cursor to the parent of the current node
3207
+ function! s:jumpToParent()
3208
+ let currentNode = s:getSelectedNode()
3209
+ if !empty(currentNode)
3210
+ if !empty(currentNode.parent)
3211
+ call s:putCursorOnNode(currentNode.parent, 1, 0)
3212
+ call s:centerView()
3213
+ else
3214
+ call s:echo("cannot jump to parent")
3215
+ endif
3216
+ else
3217
+ call s:echo("put the cursor on a node first")
3218
+ endif
3219
+ endfunction
3220
+
3221
+ " FUNCTION: s:jumpToRoot() {{{2
3222
+ " moves the cursor to the root node
3223
+ function! s:jumpToRoot()
3224
+ call s:putCursorOnNode(t:NERDTreeRoot, 1, 0)
3225
+ call s:centerView()
3226
+ endfunction
3227
+
3228
+ " FUNCTION: s:jumpToSibling() {{{2
3229
+ " moves the cursor to the sibling of the current node in the given direction
3230
+ "
3231
+ " Args:
3232
+ " forward: 1 if the cursor should move to the next sibling, 0 if it should
3233
+ " move back to the previous sibling
3234
+ function! s:jumpToSibling(forward)
3235
+ let currentNode = s:getSelectedNode()
3236
+ if !empty(currentNode)
3237
+ let sibling = currentNode.findSibling(a:forward)
3238
+
3239
+ if !empty(sibling)
3240
+ call s:putCursorOnNode(sibling, 1, 0)
3241
+ call s:centerView()
3242
+ endif
3243
+ else
3244
+ call s:echo("put the cursor on a node first")
3245
+ endif
3246
+ endfunction
3247
+
3248
+ " FUNCTION: s:openBookmark(name) {{{2
3249
+ " put the cursor on the given bookmark and, if its a file, open it
3250
+ function! s:openBookmark(name)
3251
+ try
3252
+ let targetNode = s:Bookmark.GetNodeForName(a:name, 0)
3253
+ call s:putCursorOnNode(targetNode, 0, 1)
3254
+ redraw!
3255
+ catch /NERDTree.BookmarkedNodeNotFound/
3256
+ call s:echo("note - target node is not cached")
3257
+ let bookmark = s:Bookmark.BookmarkFor(a:name)
3258
+ let targetNode = s:TreeFileNode.New(bookmark.path)
3259
+ endtry
3260
+ if targetNode.path.isDirectory
3261
+ call s:openExplorerFor(targetNode)
3262
+ else
3263
+ call s:openFileNode(targetNode)
3264
+ endif
3265
+ endfunction
3266
+ " FUNCTION: s:openEntrySplit(forceKeepWindowOpen) {{{2
3267
+ "Opens the currently selected file from the explorer in a
3268
+ "new window
3269
+ "
3270
+ "args:
3271
+ "forceKeepWindowOpen - dont close the window even if NERDTreeQuitOnOpen is set
3272
+ function! s:openEntrySplit(forceKeepWindowOpen)
3273
+ let treenode = s:getSelectedNode()
3274
+ if treenode != {}
3275
+ call s:openFileNodeSplit(treenode)
3276
+ if !a:forceKeepWindowOpen
3277
+ call s:closeTreeIfQuitOnOpen()
3278
+ endif
3279
+ else
3280
+ call s:echo("select a node first")
3281
+ endif
3282
+ endfunction
3283
+
3284
+ " FUNCTION: s:openExplorer() {{{2
3285
+ function! s:openExplorer()
3286
+ let treenode = s:getSelectedDir()
3287
+ if treenode != {}
3288
+ call s:openExplorerFor(treenode)
3289
+ else
3290
+ call s:echo("select a node first")
3291
+ endif
3292
+ endfunction
3293
+
3294
+ " FUNCTION: s:openInNewTab(stayCurrentTab) {{{2
3295
+ " Opens the selected node or bookmark in a new tab
3296
+ " Args:
3297
+ " stayCurrentTab: if 1 then vim will stay in the current tab, if 0 then vim
3298
+ " will go to the tab where the new file is opened
3299
+ function! s:openInNewTab(stayCurrentTab)
3300
+ let currentTab = tabpagenr()
3301
+
3302
+ let treenode = s:getSelectedNode()
3303
+ if treenode != {}
3304
+ if treenode.path.isDirectory
3305
+ tabnew
3306
+ call s:initNerdTree(treenode.path.strForOS(0))
3307
+ else
3308
+ exec "tabedit " . treenode.path.strForEditCmd()
3309
+ endif
3310
+ else
3311
+ let bookmark = s:getSelectedBookmark()
3312
+ if bookmark != {}
3313
+ if bookmark.path.isDirectory
3314
+ tabnew
3315
+ call s:initNerdTree(bookmark.name)
3316
+ else
3317
+ exec "tabedit " . bookmark.path.strForEditCmd()
3318
+ endif
3319
+ endif
3320
+ endif
3321
+ if a:stayCurrentTab
3322
+ exec "tabnext " . currentTab
3323
+ endif
3324
+ endfunction
3325
+
3326
+ " FUNCTION: s:openNodeRecursively() {{{2
3327
+ function! s:openNodeRecursively()
3328
+ let treenode = s:getSelectedNode()
3329
+ if treenode == {} || treenode.path.isDirectory == 0
3330
+ call s:echo("Select a directory node first" )
3331
+ else
3332
+ call s:echo("Recursively opening node. Please wait...")
3333
+ call treenode.openRecursively()
3334
+ call s:renderView()
3335
+ redraw
3336
+ call s:echo("Recursively opening node. Please wait... DONE")
3337
+ endif
3338
+
3339
+ endfunction
3340
+
3341
+ "FUNCTION: s:previewNode() {{{2
3342
+ function! s:previewNode(openNewWin)
3343
+ if a:openNewWin
3344
+ call s:openEntrySplit(1)
3345
+ else
3346
+ call s:activateNode(1)
3347
+ end
3348
+ call s:putCursorInTreeWin()
3349
+ endfunction
3350
+
3351
+ " FUNCTION: s:revealBookmark(name) {{{2
3352
+ " put the cursor on the node associate with the given name
3353
+ function! s:revealBookmark(name)
3354
+ try
3355
+ let targetNode = s:Bookmark.GetNodeForName(a:name, 0)
3356
+ call s:putCursorOnNode(targetNode, 0, 1)
3357
+ catch /NERDTree.BookmarkDoesntExist/
3358
+ call s:echo("Bookmark isnt cached under the current root")
3359
+ endtry
3360
+ endfunction
3361
+ " FUNCTION: s:refreshRoot() {{{2
3362
+ " Reloads the current root. All nodes below this will be lost and the root dir
3363
+ " will be reloaded.
3364
+ function! s:refreshRoot()
3365
+ call s:echo("Refreshing the root node. This could take a while...")
3366
+ call t:NERDTreeRoot.refresh()
3367
+ call s:renderView()
3368
+ redraw
3369
+ call s:echo("Refreshing the root node. This could take a while... DONE")
3370
+ endfunction
3371
+
3372
+ " FUNCTION: s:refreshCurrent() {{{2
3373
+ " refreshes the root for the current node
3374
+ function! s:refreshCurrent()
3375
+ let treenode = s:getSelectedDir()
3376
+ if treenode == {}
3377
+ call s:echo("Refresh failed. Select a node first")
3378
+ return
3379
+ endif
3380
+
3381
+ call s:echo("Refreshing node. This could take a while...")
3382
+ call treenode.refresh()
3383
+ call s:renderView()
3384
+ redraw
3385
+ call s:echo("Refreshing node. This could take a while... DONE")
3386
+ endfunction
3387
+ " FUNCTION: s:renameCurrent() {{{2
3388
+ " allows the user to rename the current node
3389
+ function! s:renameCurrent()
3390
+ let curNode = s:getSelectedNode()
3391
+ if curNode == {}
3392
+ call s:echo("Put the cursor on a node first" )
3393
+ return
3394
+ endif
3395
+
3396
+ let newNodePath = input("Rename the current node\n" .
3397
+ \ "==========================================================\n" .
3398
+ \ "Enter the new path for the node: \n" .
3399
+ \ "", curNode.path.strForOS(0))
3400
+
3401
+ if newNodePath == ''
3402
+ call s:echo("Node Renaming Aborted.")
3403
+ return
3404
+ endif
3405
+
3406
+ try
3407
+ let bufnum = bufnr(curNode.path.str(0))
3408
+
3409
+ call curNode.rename(newNodePath)
3410
+ call s:renderView()
3411
+
3412
+ "if the node is open in a buffer, ask the user if they want to
3413
+ "close that buffer
3414
+ if bufnum != -1
3415
+ let prompt = "\nNode renamed.\n\nThe old file is open in buffer ". bufnum . (bufwinnr(bufnum) == -1 ? " (hidden)" : "") .". Delete this buffer? (yN)"
3416
+ call s:promptToDelBuffer(bufnum, prompt)
3417
+ endif
3418
+
3419
+ call s:putCursorOnNode(curNode, 1, 0)
3420
+
3421
+ redraw
3422
+ catch /^NERDTree/
3423
+ call s:echoWarning("Node Not Renamed.")
3424
+ endtry
3425
+ endfunction
3426
+
3427
+ " FUNCTION: s:showFileSystemMenu() {{{2
3428
+ function! s:showFileSystemMenu()
3429
+ let curNode = s:getSelectedNode()
3430
+ if curNode == {}
3431
+ call s:echo("Put the cursor on a node first" )
3432
+ return
3433
+ endif
3434
+
3435
+
3436
+ let prompt = "NERDTree Filesystem Menu\n" .
3437
+ \ "==========================================================\n".
3438
+ \ "Select the desired operation: \n" .
3439
+ \ " (a)dd a childnode\n".
3440
+ \ " (m)ove the current node\n".
3441
+ \ " (d)elete the current node\n"
3442
+ if s:Path.CopyingSupported()
3443
+ let prompt = prompt . " (c)opy the current node\n\n"
3444
+ else
3445
+ let prompt = prompt . " \n"
3446
+ endif
3447
+
3448
+ echo prompt
3449
+
3450
+ let choice = nr2char(getchar())
3451
+
3452
+ if choice ==? "a"
3453
+ call s:insertNewNode()
3454
+ elseif choice ==? "m"
3455
+ call s:renameCurrent()
3456
+ elseif choice ==? "d"
3457
+ call s:deleteNode()
3458
+ elseif choice ==? "c" && s:Path.CopyingSupported()
3459
+ call s:copyNode()
3460
+ endif
3461
+ endfunction
3462
+
3463
+ " FUNCTION: s:toggleIgnoreFilter() {{{2
3464
+ " toggles the use of the NERDTreeIgnore option
3465
+ function! s:toggleIgnoreFilter()
3466
+ let t:NERDTreeIgnoreEnabled = !t:NERDTreeIgnoreEnabled
3467
+ call s:renderViewSavingPosition()
3468
+ call s:centerView()
3469
+ endfunction
3470
+
3471
+ " FUNCTION: s:toggleShowBookmarks() {{{2
3472
+ " toggles the display of bookmarks
3473
+ function! s:toggleShowBookmarks()
3474
+ let t:NERDTreeShowBookmarks = !t:NERDTreeShowBookmarks
3475
+ if t:NERDTreeShowBookmarks
3476
+ call s:renderView()
3477
+ call s:putCursorOnBookmarkTable()
3478
+ else
3479
+ call s:renderViewSavingPosition()
3480
+ endif
3481
+ call s:centerView()
3482
+ endfunction
3483
+ " FUNCTION: s:toggleShowFiles() {{{2
3484
+ " toggles the display of hidden files
3485
+ function! s:toggleShowFiles()
3486
+ let t:NERDTreeShowFiles = !t:NERDTreeShowFiles
3487
+ call s:renderViewSavingPosition()
3488
+ call s:centerView()
3489
+ endfunction
3490
+
3491
+ " FUNCTION: s:toggleShowHidden() {{{2
3492
+ " toggles the display of hidden files
3493
+ function! s:toggleShowHidden()
3494
+ let t:NERDTreeShowHidden = !t:NERDTreeShowHidden
3495
+ call s:renderViewSavingPosition()
3496
+ call s:centerView()
3497
+ endfunction
3498
+
3499
+ "FUNCTION: s:upDir(keepState) {{{2
3500
+ "moves the tree up a level
3501
+ "
3502
+ "Args:
3503
+ "keepState: 1 if the current root should be left open when the tree is
3504
+ "re-rendered
3505
+ function! s:upDir(keepState)
3506
+ let cwd = t:NERDTreeRoot.path.str(0)
3507
+ if cwd == "/" || cwd =~ '^[^/]..$'
3508
+ call s:echo("already at top dir")
3509
+ else
3510
+ if !a:keepState
3511
+ call t:NERDTreeRoot.close()
3512
+ endif
3513
+
3514
+ let oldRoot = t:NERDTreeRoot
3515
+
3516
+ if empty(t:NERDTreeRoot.parent)
3517
+ let path = t:NERDTreeRoot.path.getPathTrunk()
3518
+ let newRoot = s:TreeDirNode.New(path)
3519
+ call newRoot.open()
3520
+ call newRoot.transplantChild(t:NERDTreeRoot)
3521
+ let t:NERDTreeRoot = newRoot
3522
+ else
3523
+ let t:NERDTreeRoot = t:NERDTreeRoot.parent
3524
+
3525
+ endif
3526
+
3527
+ call s:renderView()
3528
+ call s:putCursorOnNode(oldRoot, 0, 0)
3529
+ endif
3530
+ endfunction
3531
+
3532
+
3533
+ "reset &cpo back to users setting
3534
+ let &cpo = s:old_cpo
3535
+
3536
+ " vim: set sw=4 sts=4 et fdm=marker: