tomkersten-vixploder 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
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: