Compare commits

...

438 Commits
5.0.0 ... 6.4.3

Author SHA1 Message Date
Phil Runninger
ee79ecfb67 Merge pull request #1075 from preservim/1073
Fix regex that finds keyword for minimal menu.
2020-01-06 09:21:11 -05:00
Phil Runninger
b579c7751d Fix regex that finds keyword for minimal menu. 2020-01-06 09:19:25 -05:00
Phil Runninger
8a14891241 Merge pull request #1072 from preservim/migrate
Update links to repository with new org namespace
2020-01-02 09:55:17 -05:00
Caleb Maclennan
914970157f Update links to repository with new org namespace 2020-01-02 12:09:02 +03:00
Phil Runninger
97fb849a29 Merge pull request #1071 from preservim/vint
Lint vimscript, fix errors and warnings, add CI job to review PRs
2020-01-02 02:12:21 -05:00
Caleb Maclennan
3fb31b2e81 Update changelog for 6.4.2 and add CI badge 2019-12-31 10:30:00 +03:00
Caleb Maclennan
907587f7a3 Fix lint warnings: use the full option name 2019-12-31 10:30:00 +03:00
Caleb Maclennan
38b1e5e7aa Fix lint warnings: use the abort attribute for functions in autoload 2019-12-31 09:42:19 +03:00
Caleb Maclennan
10868dd94c Fix lint warnings: use scriptencoding when multibyte char exists 2019-12-31 09:42:19 +03:00
Caleb Maclennan
a722613f36 Fix lint warnings: use robust operators 2019-12-31 09:42:19 +03:00
Caleb Maclennan
45e33f2502 Fix lint warnings: prefer single quoted strings 2019-12-31 09:42:14 +03:00
Caleb Maclennan
8d81510aa6 Fix VimL syntax error: undefined variable 2019-12-31 09:41:46 +03:00
Caleb Maclennan
d8d799a4d6 Fix VimL syntax error: escapes work differently outside quotes 2019-12-31 09:40:58 +03:00
Caleb Maclennan
ec0fca4c7d Add CI job that lints VimL and reviews PRs 2019-12-31 09:20:35 +03:00
Caleb Maclennan
fff3975608 Configure Vint linter 2019-12-31 09:20:35 +03:00
Phil Runninger
f64c0062ee Set theme jekyll-theme-cayman 2019-12-30 23:31:06 -05:00
Phil Runninger
1ab85e33be Update version in change log. 2019-12-16 09:06:45 -05:00
Phil Runninger
c962796b03 Ensure backward compatibility. v:t_func is not available before 8.0. 2019-12-16 09:04:16 -05:00
Alejandro Sanchez
a7886fb6c4 Allow use of function references as callbacks (#1067) 2019-12-14 20:25:17 -05:00
William Findlay
82b1649f2e Add a NERDTreeToggleVCS command to the vcs plugin (#1060)
* NERDTreeToggleVCS

* nerdtree toggle vcs documentation

* fix function documentation

* changelog

* Update CHANGELOG.md

* Update CHANGELOG.md

* simplify toggletreevcs

* Update CHANGELOG.md
2019-11-22 11:26:25 -05:00
Phil Runninger
8d9b8dae67 Update version number in changelog. 2019-11-13 09:00:41 -05:00
jhzn
960fda6299 Menu option, 'copy path to clipboard' is aware of VIM clipboard option (#1056)
VIM noob here, so code might not be optimal.

My setup is as follows.
NVIM v0.5.0-95-g2e14dffbb, Linux Mint 19.2.

I have this in init.vim
```vim
set clipboard=unnamedplus
```
This enables me to share clipboard between VIM and X clipboard.

The problem is that the menu option in NERDTree copies the file path to the "* register.
This means I can't access the value in the X clipboard.
2019-11-13 08:58:42 -05:00
Phil Runninger
fec3e57ad2 Closes #1050. Update README; don't show NERDTree if opening a session. 2019-10-22 01:21:23 -04:00
Phil Runninger
371feb7e54 Support tab-specific CWDs (#1032)
* Change CWD when switching tabs to the tab's NERDTree root.

* Remove commented-out code.

* List the new possible value for NERDTreeChDirMode in doc.

* Add new option to select between `:cd` and `:tcd`.

* Document the new NERDTreeUseTCD option.

* Update version number in change log.
2019-10-16 13:26:20 -04:00
Farid Ahmadian
4245517689 Add VIM built-in package management to readme (#1049) 2019-10-14 09:13:20 -04:00
Phil Runninger
926ff0ec03 Update version number instructions in PR template and change log. 2019-10-11 10:44:25 -04:00
Phil Runninger
53eef21ad6 Save/Set screen state also on WinLeave and WinEnter. (#1048)
* Save/Set screen state also on WinLeave and WinEnter.

The particular use case here is when switching tabs with `gt` and the
NERDTrees have been mirrored.

* Update version number and change log.
2019-10-11 01:04:06 -04:00
Phil Runninger
4fe24d3156 Wrap saveScreenState's statements in a try-catch block. (#1047)
* Wrap saveScreenState's statements in a try-catch block.

If you're in NERDTree, and you press : to open a command line, and then
press Ctrl+F to open the [Command Line] window, you will see errors
related to switching windows while in this function. (Those commands are
not allowed while in the [Command Line] window.) The try-catch block
handles the errors, preventing their being displayed.

* Update version number in change log.
2019-10-08 14:01:50 -04:00
Phil Runninger
2d639b70e7 Catch errors when trying to read CHANGELOG.md. (#1045)
* Catch errors when trying to read CHANGELOG.md.

The ArchLinux package
(https://www.archlinux.org/packages/community/any/vim-nerdtree/) puts
this file in the wrong location.

* Update version number in change log.
2019-10-01 09:17:32 -04:00
Phil Runninger
6318406f66 If file path doesn't exist, :NERDTreeFind its parent directory instead. (#1043)
* If file path doesn't exist, :NERDTreeFind its parent directory instead.

This happens in the following scenario:
```
:edit path/new_file
:NERDTreeFind
```
Instead of an error message about an **invalid path**, this change will
now find the parent directory instead. It will not work if the new file
is **path/new_folder/new_file**, and that's OK because even vim itself
cannot handle both the new folder and the new file; `:w` won't create
the new folder.

* Update version number in change log.

* Change version change from PATCH to MINOR.
2019-09-29 11:28:59 -04:00
Phil Runninger
496b61ead1 Give @dragonxlwang proper credit on PR #1035. 2019-09-26 08:48:57 -04:00
Phil Runninger
5af6859846 Reintroduce necessary variable mistakenly removed. (#1040)
* Reintroduce lost variable: splitMode.

* Add a space between splitMode and "split". `verticalsplit` is invalid.

* Update version number, and add attributions (PR authors)
2019-09-26 08:47:36 -04:00
Phil Runninger
bd744eab8d Make the behavior of window splits consistent (#1035)
* add option to spawn split from previous window

* Update some comments and remove debugging statement.

* Simplify the code, and make it respect NERDTreeWinPos and 'splitbelow'.

* Better logic for getting NERDTree window number when not active window.

* Use common functions for splitting windows. Make splitting respect user.

The placement of split windows now respects the user's choices for the
splitright and splitbelow settings, and the g:NERDTreeWinPos variable.

* Update version number in change log.
2019-09-24 01:19:27 -04:00
Phil Runninger
9193962ad8 Update version number in change log. 2019-09-15 14:44:09 -04:00
Chris Patuzzo
2eaedd8bf4 Fix (p)ath not displaying in the minimal menu (#1038)
The ‘copy (p)ath to clipboard’ menu item was added
recently in this pull request:
https://github.com/scrooloose/nerdtree/pull/1002/files

However, this caused the NERDTreeMinimalMenu to
display ‘copy’ instead of ‘(p)ath’ because it was
simply using the first word of the item’s text.

This change fixes that bug by using a regex to
pick out the first word beginning with ‘(’
2019-09-15 14:41:27 -04:00
Phil Runninger
60ec10b477 Enable events when closing NerdTree window. (#1037)
* Enable events when closing NT window. Triggers updates in Airline.

* Update version number in change log.
2019-09-13 10:49:26 -04:00
Phil Runninger (mac)
51fc75efdb Fix version number. I was on the wrong branch. 2019-09-09 09:40:18 -04:00
Phil Runninger (mac)
79ef87b009 Update version number in change log. 2019-09-09 05:27:48 -04:00
Phil Runninger
3d508aedce Fix the e key mapping to use netrw if desired (#1031)
* Use :edit in openExplorer to allow NERDTreeHijackNetrw to do its thing.

* Remove commented-out code.

* Make `e` work on file nodes, opening a new NERDTree or netrw buffer.

* Update change log.
2019-08-27 20:53:23 -04:00
Phil Runninger (mac)
9afab6257b Condense code: ternary operators vs. if-then-else blocks. 2019-08-19 14:39:17 -04:00
Phil Runninger (mac)
877f41e243 Update PR template with instructions to tag the release. 2019-08-19 09:36:50 -04:00
Phil Runninger
c4a7ca084e Add file extension and size to sorting capabilities (#1029)
* Add ability to sort by extension and file size.

Use the tags [[extension]], [[size]], or [[-size]] in the
g:NERDTreeSortOrder list to accomplish this sorting.

* Prevent metadata tags being misused in getSortOrderIndex().

* Apply metadata tags only to files.

* Update NERDTreeSortOrder in help file.

* Update version number in CHANGELOG.
2019-08-19 03:51:34 -04:00
Phil Runninger (mac)
184fbb6ffe Better spacing of comment in issue templates. 2019-08-09 10:27:47 -04:00
Phil Runninger (mac)
03073bb1c8 Update issue templates, moving some text into comments. 2019-08-09 10:07:14 -04:00
Phil Runninger (mac)
858b3c0004 Update PR template, moving some text into a comment. 2019-08-09 09:45:46 -04:00
Phil Runninger
ae1c0004ec Suppress events for intermediate window/tab/buffer changes (#1026)
* Add an optional parameter to neredtree#exec to suppress all events.

The value doesn't matter, but 1 is a good choice. Its presence is an
indicator that tells NERDTree to tell Vim to ignore all events. I'm not
yet sure if there needs to be an else section to that if block. It may
be OK to allow all events to fire in the right situations.

* Supress events in all intermediate nerdtree#exec calls.

Finding all the right function calls is the key here.

* Make ignoreAll a required parameter to nerdtree#exec().

* Put required ignoreAll argument (==0) in where it's now needed.

* Ignore events when creating a new vertical split.

* Ignore events when closing NERDTree. This may need to be reverted.

* Remove debugging statment and commented-out code.

* Wrap remaining buffer/window-switching commands in nerdtree#exec().

* Update version number.

* Add a space between arguments in nerdtree#exec() calls.
2019-08-08 22:00:35 -04:00
Phil Runninger
63c59208c1 Revert #1019 to fix nvim artifacts and flickering. (#1021)
* Revert "Use :mode only in neovim. MacVim still needs to use :redraw! (#1019)"

This reverts commit 4ac07f52a3.

* If not Neovim, use `:redraw!` as was done before.

* Update version number.

* Fix punctuation in NERDTree Menu instructions.
2019-07-14 15:17:56 -04:00
Phil Runninger
4ac07f52a3 Use :mode only in neovim. MacVim still needs to use :redraw! (#1019)
* Use :mode only in neovim. MacVim still needs to use :redraw!

* Make nerdtree#redraw do both redraw and redraw! based on a parameter.

* Make bang a required parameter.

* Replace all redraw statments with call nerdtree#redraw function calls.

* Update version in change log.
2019-07-10 09:45:58 -04:00
Phil Runninger (mac)
2f0d48d632 Update version in change log. 2019-07-07 03:53:06 -04:00
Phil Runninger
a460d6ef7f In CHANGELOG.md and PR template, make reference to PR a true HTML link. (#1017) 2019-07-07 03:50:59 -04:00
Phil Runninger
3b1a850b85 Use :mode instead of :redraw! when updating menu. (#1016)
* Use :mode instead of :redraw! when updating screen.

In neovim, it will actually clear the whole screen, whereas, redraw!
does not.

* Update version number in change log.
2019-07-07 03:19:17 -04:00
Phil Runninger
89a1a4355b When searching for root line num, stop at the end of the file. (#1015)
* When searching for root line num, stop at the end of the file.

When using the following NERDTreeStatusLine, Vim would lock up and not
work anymore. The problem was that when trying to find the root line
number, the loop was continuing past the end of the file, looping
"forever". The fix was to simply stop at the end of the file.

let g:NERDTreeStatusline = "%{exists('g:NERDTreeFileNode')&&" .
      \ "has_key(g:NERDTreeFileNode.GetSelected(),'path')?" .
      \ "g:NERDTreeFileNode.GetSelected().path.getLastPathComponent(0):''}"

* Update change log.
2019-07-04 00:21:50 -04:00
Phil Runninger
62b78de367 Update Change Log 2019-07-03 11:12:21 -04:00
Kebin Liu
aef6baf6e2 Update ui_glue.vim (#1014)
Fix `<CR>` key map on the bookmark
2019-07-03 11:11:25 -04:00
Phil Runninger
06c9d9c963 Make Enter work on the .. ( up a dir ) line (#1013)
* Make Enter work on the `.. ( up a dir )` line.

* Simpler instructions for getting bug info.

* Update changelog.
2019-07-02 15:45:36 -04:00
Phil Runninger
ca16df25fa Fix nerdtree#version() on Windows. 2019-07-01 23:29:56 -04:00
Phil Runninger
cce6fb373f Expand functionality of <CR> mapping (#1011)
* Define default values for new variables governing new "Default Open".

"Default Open" means to open a file with the Enter key (which of course
can be changed.) The key can be changed in the vimrc, and there is a
variable for specifying the Opener parameters for opening the node. This
lets the user decide whether Enter (or another key) will open a file in
the current tab or a new one, and whether or not to open the file again
in the tab or jump to a window where the file is already open.

* Remove the old mapping for <CR>, a duplicate of 'o'.

<CR> will be defined like all the other keys, in plugin/NERD_tree.vim

* Assign functions to the new <CR> key mapping.

Three separate functions handle directories, files, and bookmarks.

* Rename variables: NERDTreeCustomOpen and NERDTreeCustomOpenArgs

* Add documentation for NERDTreeCustomOpenArgs and NERDTree-<CR>.

* Make key mapping variables be indexed in the Vim help

* Remove angle brackets from <CR> to see if help navigation improves.

* Rename functions from defaultOpen... to customOpen...

* Use separate options for file and directory nodes.

* Update documentation for separate file/directory options.

* Update version number and change log.

* Change CR to <CR> in help tags.

* Fix missing backtick in patch number.

* Update the quickhelp text.

* Update Pull Request template.

* Update change log with simpler formatting of patch number.

* Get NERDTree version number directly from CHANGELOG.md

* Reformat the lists of contributors in the Change Log.

* Initialize the version text, just in case the while loop finds nothing.
2019-07-01 22:13:20 -04:00
Phil Runninger
1c803b36f6 Remove @mentions from PR template and change log. They weren't working. (#1009)
* Remove @mentions from PR template and change log. They weren't working.

* Update version number and change log.
2019-06-27 08:03:50 -04:00
Phil Runninger
2cbc76bbfd Fix NERDTree opening with the wrong size. (#1008)
* Fix NERDTree opening with the wrong size.

There were two commands that seemed to be causing the NERDTree window to
open in exactly half the screen width. They are:

- silent! execute 'edit ' . t:NERDTreeBufName        in _createTreeWin()
- setlocal nobuflisted                         in _setCommonBufOptions()

These commands were reseting the width of NERDTree. The solution I chose
was to resize the window after creating the new window, and then to set
winfixwidth before setting the other common buffer options.

* Update change log and version number.
2019-06-27 01:34:10 -04:00
Phil Runninger
347a58b0b0 Update Changelog and create PR Template (#1007)
* Update CHANGELOG and change it to Markdown format.

* Add PR template with checklist for advancing the version number.

* Update version number.

* Change PR number in change log and PR template.
2019-06-27 01:28:45 -04:00
Phil Runninger (mac)
33fe2fdf16 Switch to new issue template paradigm, with separate templates. 2019-06-20 08:50:48 -04:00
Phil Runninger
c46fbd21e3 Spacing changes in issue template 2019-06-20 08:17:50 -04:00
Phil Runninger (mac)
b213fae779 Update the issue template. Shout out to @ryanoasis for the inspiration. 2019-06-19 18:38:57 -04:00
Phil Runninger (mac)
b9a421b2d5 Remove the bug.md template. Not able to make multiple templates. 2019-06-19 16:02:55 -04:00
Phil Runninger (mac)
254f7678f3 Move bug.md to its proper folder. 2019-06-19 15:50:35 -04:00
Phil Runninger (mac)
318fb2d0de Add new issue template, just for bugs. 2019-06-19 15:45:22 -04:00
Phil Runninger
9bedadd062 Refresh a dir_node if the file wasn't found in it, and look once more. (#1005) 2019-06-18 10:27:00 -04:00
Phil Runninger
12dea6ccb2 Add a "copy path to clipboard" menu option (#1002)
* Add menu item to copy the node's path to the clipboard.

It works on Mac. Check Windows later.

* Handle case where clipboard is not a compiled feature of Vim.

* Change menu text if clipboard is unavailable.
2019-06-13 09:17:19 -04:00
Phil Runninger
70dc34cb69 Enable root refresh on "vim ." a different way than #999. (#1001)
* Fix "R doesn't work when doing 'vim <folder>'" a different way.

Instead of assigning a value to t:NERDTreeBufName for a window tree,
which is used to determine if NERDTree is open, simply also look at the
current buffer's name to see if it matches the NERDTree pattern.

* Replace hardcoded buffer name prefix with BufNamePrefix() function.
2019-06-13 09:16:56 -04:00
Phil Runninger
28eb47e267 Fix refreshroot (#999)
* Set t:NERDTreeBufName when creating a window tree.

* Change folding markers.
2019-06-07 21:41:47 -04:00
Daniel Manary
67fa9b3116 Change version check to look for 03 not 30 (#994)
My Vim reports as 704 when it is version 7.4, so this number should be 703 not 730
2019-05-09 16:25:36 -04:00
Phil Runninger
a3f0e66793 Change minimum vim (#991)
* Add a new function to implement and() from vim 7.4.

* Change minimum required version of vim to 7.3.
2019-05-09 10:12:25 -04:00
Phil Runninger (mac)
3c06335782 Escape the DirArrow strings in substitute function. 2019-04-23 10:26:30 -04:00
Phil Runninger
9226eab2a8 Allow multi-character DirArrows (#985)
* Add debugging messages to diagnose issue #931.

* Echo the CWD and NERDTree root too.

* Ensure DirArrows are trimmed to a single character.

Actually, it's up to the user to make sure it's a single character after
leading and trailing spaces are removed. Spaces need to be removed so
that an accurate level of indentation can be calculated.

* Remove debugging statements

* Simplify the algorithm for calculating indentation level.

1. Replace the DirArrows with a single space.
2. Count the leading spaces.
3. Divide by 2.

This allows users to specify multi-character arrows, where a spaces
prevent characters printing on top of each other.
2019-04-22 15:58:06 -04:00
Phil Runninger
e126b8745d Remove redraw! while still clearing last message empty string. (#979) 2019-04-16 09:55:20 -04:00
Phil Runninger (mac)
7513f256aa Fixes #970. Restore silent parameter to _initChildren.
https://github.com/ryanoasis/vim-devicons uses this function directly
with silent set to 1.
2019-03-26 11:57:21 -04:00
Terry Ding
839cddc750 fix _initChildren function value set to numChildrenCached error (#969) 2019-03-26 02:03:12 -04:00
Phil Runninger
e3e600608a On Windows, do a case-insensitive comparison of paths. (#967) 2019-03-25 22:32:07 -04:00
Phil Runninger
0efbdfbc5a Remove the "Please wait... DONE" messages. (#966) 2019-03-25 22:29:21 -04:00
Phil Runninger
288669db1f Smarter delimiter default (#963)
* Better default node delimiter, based on presence of +conceal feature.

* Update documentation for node delimiter.

* Fix IF logic, and remove debug statements.

* Rewrite the NERDTreeNodeDelimiter help text to reflect new behavior.

* Change "NERD tree" to "NERDTree" and fix spacing in doc file.
2019-03-07 08:24:17 -05:00
Spencer
e1916d6fe7 Update directory .vimdc readme example (#961)
* set pwd for new window

* adding 'cd '.argv()[0] explination

* spacing

* exe

* [0]
2019-03-05 11:25:49 -05:00
Chris Patuzzo
84737f2ebe Add a NERDTreeMinimalMenu feature (#938)
* Extract the menu action prompts to a function

* Add a NERDTreeMinimalMenu configuration option

If this option is set, Vim’s command line displays
a single-line version of the menu:

Which action? (a*/m/d/r/o/q/c/l):

Pressing ‘a’ will call the ‘add child node’ menu
item as that is its shortcut.

The * denotes the position of the currently
selected menu item which can be changed with
NERDTreeMenuDown and Up in the usual way.

The user may wish to set these to <left>, <right>
or h, l if they prefer.

* Minimise the text once a menu item is chosen

If NERDTreeMinimalMenu is set, then echo a single
line prompt after the menu item is chosen. This
reduces noise for users who are already familiar
with how the menu works and prevents Vim scrolling
down to accommodate the menu text.

If the directory is non-empty we display
‘Delete directory?’ instead of ‘Delete?’ and the
user must still type ‘yes’ to confirm, rather than
just pressing ‘y’.

* Document the new NERDTreeMinimalMenu feature

* Tweak the format for the minimal menu prompt

As per @PhilRunninger’s suggestions:

- The menu now shows the ‘j/k/enter’ help text
- The first word of the selected item is shown*
- Use commas between menu items so that it’s
  visually distinct from the ‘j/k/enter’ text

* I tried displaying the full menuItem text, but
this can be quite long, e.g.

> (o)pen the current node with system editor

This causes the menu to jump around a lot. We
could add another minimal versions of these, but
I think the first word seems ok for now.
2019-02-24 18:01:12 -05:00
Phil Runninger
b6cde142dd Preview bookmarks (#956)
* Add function to preview bookmarks.

File bookmarks are previewed like regular file nodes.
Directory bookmarks are located with NERDTreeFind in the current tree.

* Update help doc to include the new bookmark preview functionality.
2019-02-22 08:21:20 -05:00
Phil Runninger
9eda9ce6a1 Add new value to NERDTreeQuitOnOpen to close bookmark table (#955)
* Update documentation for new NERDTreeQuitOnOpen values.

* Modify use of NERDTreeQuitOnOpen, keeping current behavior.

* If applicable, close the bookmarks table before opening the target.
2019-02-21 07:47:15 -05:00
Phil Runninger
2e0b101d57 Add an :EditBookmarks command to edit the bookmarks file (#954)
* Add a new NERDTree buffer command to edit the bookmarks file.

* Update the mini-help panel with missing bookmark commands.

* Update the help file with the new :EditBookmarks command.
2019-02-20 23:57:51 -05:00
Phil Runninger (mac)
f4d2b301b7 Merge branch 'master' of github.com:scrooloose/nerdtree 2019-02-18 15:53:39 -05:00
Phil Runninger (mac)
4ef9967e29 Update the documentation to better explain the delimiter character. 2019-02-18 15:52:23 -05:00
Phil Runninger
842f5cabaa Before deleting, turn off &shellslash. Restore after delete is done. 2019-02-17 22:03:49 -05:00
Phil Runninger
cce52fb9c5 Before copying, turn off &shellslash. Restore after copy is finished. (#952) 2019-02-17 18:30:10 -05:00
Phil Runninger
c05615fd80 Set a maximum window size when zooming. (#950) 2019-02-15 03:10:28 -05:00
Phil Runninger
5e8aa9e721 Confirm the wipeout of a unsaved buffer whose file has been renamed. (#949) 2019-02-14 17:44:31 -05:00
Phil Runninger
74be22deb7 Escape a backslash so it can be used in a key mapping. (#948) 2019-02-14 15:28:30 -05:00
zcodes
8cc154d4b0 fixed root path error for windows (#935)
* fixed root path error for windows

* simplify condition check
2019-02-01 07:50:55 -05:00
Phil Runninger
72c3656799 Add new command to open NERDTree in the root of a VCS repository. (#872)
* Add new command to open NERDTree in the root of a VCS repository.

* Add another example to the help file.

* Refactor and make NERDTreeVCS work on Windows.

* Don't crash when NERDTreeVCS is given a nonexistent folder.

* Move VCS code to a plugin script.

* Add some documentation to the top of vcs.vim.
2018-12-12 13:30:13 -05:00
Phil Runninger
a4dd4e1dce Restore getDirChildren for use in nerdtree-project-plugin. (#929)
This function was added to support a separate plugin:
https://github.com/scrooloose/nerdtree-project-plugin.git. It was
subsequently removed without recognizing its contribution to the
external plugin. This commit restores that function so NERDTree projects
will work.
2018-12-11 22:44:55 -05:00
Phil Runninger (mac)
c1876da09c Change things up with the artwork on the "cover" of the help doc. 2018-12-06 19:29:25 -05:00
Phil Runninger (mac)
743b849dcf Add a happy little tree to the "cover" of the help document. 2018-12-06 15:07:13 -05:00
Phil Runninger
ffa8be8aa7 Document NERDTreeNodeDelimiter #912 (#926)
* Change the default node delimiter to the BELL character, \x07.

* Syntax match by ASCII code, vs. string concatenation.

* Document the NERDTreeNodeDelimiter setting.

* Clean up the documentation markup.

* Remove apostrophes, since the NERDTree settings aren't vim options.
* Use backticks to hot-link the referenced vim options.
* Add a modeline.

* Update the title and the About section of the documentation.

* Fix typo, and clarify branches of code in Github.

* Fix wrapping to 78, and remove colorcolumn setting from modeline.

* Change the ASCI Art title, and give credit for it.

* Change the word option to setting, and redo the word wrapping.

I want to reserve the word 'option' to mean only Vim options that are
changed with the `:set` command. Since we need to use `:let` to
establish the values for the NERDTree variables, I choose to call them
settings instead.

* Realign hot-links with concealed markup tags taken into account.

* Text alignment, typo fixes, and wordsmithing the About section.
2018-12-06 01:08:16 -05:00
Arvid Gerstmann
c905a5d7b8 Allow modification of menu keybindings (#923) 2018-11-29 09:17:39 -05:00
Phil Runninger
370eb5bcb4 Add two more disqualifications for isCascadable(). (#914)
* Add two more disqualifications for isCascadable().

A directory that is bookmarked or that is a symlink to another location
has trailing text indicating so. This extra text causes problem when
cascading with a directory underneath it, so disable it in this case.

* Add comments to explain the new exclusions for bookmarks and symlinks.
2018-11-20 13:33:23 -05:00
Phil Runninger (mac)
f406af39cf Merge branch 'master' of github.com:scrooloose/nerdtree 2018-11-12 11:18:07 -05:00
Phil Runninger (mac)
64c3a6aed3 Change the containedin to ALL to conceal delmiter after filename. 2018-11-12 11:17:20 -05:00
Kristijan Husak
6fe967b3b3 Allow highlighting more than one flag. (#908) 2018-11-05 10:12:07 -05:00
Phil Runninger (mac)
8d005db94f Use substitute() for backward compatibility. Change conceallevel to 3. 2018-10-31 08:45:43 -04:00
Phil Runninger
91e0f2253f Support unusual characters in file and directory names (#868)
* Use a delimiter in node to separate file/dir name from the rest.

* Switch warning message to use nerdtree#deprecated function.

* Compress the space between the tree symbols and the node.

* Include the delimiter when calculating indent or getting filename.

* Don't need to strip leading delimiter. It will already be gone.

* Simplify the way the delimiter is being used.

I don't know what I was thinking. The delimiter doesn't need to be used
to separate every indicator on the node's text, ie.

Bad:    Tree|GenericFlags|Filename|ExecutableFlag|Link|ReadonlyFlag
Better: Tree GenericFlags|Filename|ExecutableFlag Link ReadonlyFlag

This was unnecessary, given that we're only interested in the filename.
So, just one pair of delimiters is all we need. That greatly simplifies
the _stripMarkup function, and restores a bunch of other statements to
what they already are in the master branch.

* Add syntax highlighting to conceal the delimiter

* Put a if has("conceal") check around the syntax statement using it.

* Make concealment work correctly for LinkFile and readonly files.

* Use highlight Ignore if conceal isn't available.

This is probably the best we can do, especially if some other character
must be used in place of nbsp.

* Make the regex better match the original, but more compact.

It was allowing 2+ spaces, instead of only 1+.

* Fix the syntax highlighing of delimiters around NERDTreeExecFile.

* Bug fix: Parse . and .. from path string with trailing slash.

* Fix unresponsive cascaded directories.

Using ':' as a more visible delimiter, when directories are cascaded,
the line appears in NERDTree like so:

▾ :lib/::nerdtree/:

Before this commit, the s:UI._stripMarkup function was leaving the
internal delimiters in place (lib/::nerdtree/). Now they are removed,
resulting in a valid path (lib/nerdtree/).

* Use .= to shorten statement. Use clearer substitutes to get node name.

* Remove node delimiters that terminate the line.

* If flags are needed after the node name, then put another delimiter
before them.
* When joining directory nodes for cascaded display, strip off the
delimiter from the child node(s).
* Remove the unnecessary substitution of doubled intermediate
delimiters, since they're not in there anymore.

* DRY up the addition of the 2nd delimiter, and use only 1 for all tags.
2018-10-24 22:41:13 -04:00
Phil Runninger
c372911c4a Refresh buffers after m, m operation on a folder (#888)
* WIP: Wow! That's an ugly diff. I'm not done yet, though.

* Fix the ugliness of the previous commit, and finish the work.

If the node being renamed is a directory, get a list of all open buffers
whose file lives in the old directory. If that list is not empty, ask
the user if he wants to replace the old buffers with the new files. The
logic to handle renaming a file node stays the same, although the code
has been refactored a bit.
2018-10-24 22:20:59 -04:00
Phil Runninger
388623e702 Support sorting files and directories by modification time. (#901)
* Introduce a flag to to sort by the node's modification time.

This flag is part of the NERDTreeSortOrder list. '[[timestamp]]' sorts
oldest to newest, while '[[-timestamp]]' sorts newest to oldest. Its
position in the array determines whether it is the primary sort (first
position) or secondary sort (any other position). The remaining elements
in the array describe the other sort level following all prior rules. If
needed, a tertiary sort is done alphabetically on the filename.

Examples:

['[[timestamp]]']            - oldest to newest
['\/$','*','[[-timestamp]]'] - dirs, then files, each newest first.

When using this flag, performance is slowed a little because the sortKey
is always recalculated with every sort. Why? Because if a file is saved
(either in vim or by an outside program), NERDTree needs to go back out
to the shell to get the new modification time.

* Update NERDTreeSortOrder documentation.

The new `[[timestamp]]' and '[[-timestamp]]' flags are added to support
sorting by modification time.

* Fix the inequality. Must be >= to force recalculation of _sortKey.

* Move `let path=` closer to where it's used.
2018-10-24 22:18:18 -04:00
Phil Runninger
92a20c0736 Bug fix: Parse . and .. from path string with trailing slash. (#899) 2018-10-24 22:14:18 -04:00
Phil Runninger
52151fb307 Call Resolve on the file's path when calling :NERDTreeFind. (#896)
When :NERDTreeFind creates a tree, it resolves the file's path, and
makes that its root. See :h resolve() for more info; it basically
tracks down links to their ultimate source. Then :NERDTreeFind
tries to find the file under that root, so it can be revealed. The
problem is that it compares the file's unresolved path against the
resolved path in the root. Here is the scenario:

/tmp/ is a link to /private/tmp/
:e /tmp/foo will open the file as expected
:NERDTreeFind will first create a tree with a root of /private/tmp/
Then it tries to find /tmp/foo, but it can't, because the path
names don't match.

This commit resolves /tmp/foo to the actual location of
/private/tmp/foo; thus, it is able to find the file in the tree.
2018-10-24 22:13:42 -04:00
Phil Runninger
f98078d3ae Force sort to recalculate the cached sortKey. (#898)
* Force sort to recalculate the cached sortKey.

The problem in issue #880 was caused by the sort using the old sortKey.
For example, given nodes A, B, and C, if B were renamed to D, the sort
was still using B as its sortKey, thus not moving it.

It's a bit of a hack, but if we set g:NERDTreeOldSortOrder to an empty
list, the cached sortKey will be recalculated. I did the same thing for
both the Copy and Add functions as well.

* Add a comment to explain the let ... = [] statement.
2018-10-18 16:13:15 -04:00
Phil Runninger
820955e773 Catch all errors, not just NERDTree errors. (#894)
When middle-clicking, the s:TreeFileNode.GetSelected() function is
called along the way. If this is done outside of the NERDTree window,
there is not "b:NERDTree" variable, and the "E121: Undefined variable"
exception is thrown. This function was trying to catch only the NERDTree
specific errors; thus, it let the Undefined variable exception slip by.
This commit causes the function to catch all errors.
2018-10-18 11:35:00 -04:00
Werner Hofstra
5381197747 Add NERDTreeRefreshRoot command (#897)
* Add NERDTreeRefreshRoot command

* Document NERDTreeRefreshRoot
2018-10-16 11:08:23 -04:00
Phil Runninger
6b6cadf86c Use a better arg for FINDSTR when using the m,l command in Windows. (#887)
* Use a better arg for FINDSTR when using the m,l command in Windows.

* Remove trailing spaces.

* Use vim getf...() functions in place of DOS commands.

* Remove unnecessary variable.

* Put labels in the text of the file/dir listing.
2018-10-10 22:19:18 -04:00
Phil Runninger
729e8014b9 Merge pull request #892 from lvoisin/work
Fix typo in help file
2018-10-08 09:06:20 -04:00
Laurent Voisin
bba4b0087b Fix typo in help file
Remove duplicated word.
2018-10-08 13:17:33 +02:00
Jason Franklin
599238ad99 Make NERDTreeCreator set the 'nolist' option (#889) 2018-09-17 08:13:07 -04:00
Jason Franklin
cd1f2c803e Fix the <C-J>, <C-K>, J, and K default mappings (#886)
These mappings currently fail on cascades.  This pull request fixes
this problem.
2018-09-15 10:20:13 -04:00
Jason Franklin
e9d3f72d9c Function "s:UI.getLineNum()" doesn't always work on cascades. (#882)
This PR is a rewrite of the "s:UI.getLineNum()" function.  This change
improves the logic and clarity of this function, and it fixes the function's
ability to work with cascades.

Fixes #529.
2018-09-13 08:39:09 -04:00
Phil Runninger
b3804dcd71 Merge pull request #871 from scrooloose/trap_bad_bookmark_path
Make sure the path to the bookmarks file exists before writing it.
2018-09-10 17:34:06 -04:00
Phil Runninger
15d06b676d Merge pull request #878 from scrooloose/autochdir_interference
NERDTreeCWD: reset CWD if changed by NERDTreeFocus
2018-09-10 09:27:52 -04:00
Jason Franklin
2cd4331b78 Check for unknown current working directory 2018-09-10 09:00:05 -04:00
Jason Franklin
5442d5e04a Put cursor in first column 2018-09-10 08:52:43 -04:00
Jason Franklin
7e00a9971e Check for error; remove code duplication 2018-09-10 08:46:42 -04:00
Jason Franklin
7c8c811f00 Edit the help file 2018-09-10 08:33:10 -04:00
Phil Runninger (mac)
c726ec7318 Implement PR review comments. 2018-09-10 06:57:39 -04:00
Phil Runninger
129a241b22 Merge pull request #870 from scrooloose/undo_zoom_on_open
Unzoom NERDTree when opening a file
2018-09-10 06:34:05 -04:00
Phil Runninger (mac)
f78cf63627 Instead of creating the bookmark file path, show error message.
This change puts the burden on the user to make sure
g:NERDTreeBookmarksFile is correctly set and the path it contains is
present and has the proper permissions. If this is not the case, an
error message is displayed. This is a better solution than to blindly
create the path, when it may actually be impossible to do so.
2018-09-09 21:29:20 -04:00
Phil Runninger (home)
808f5b225b Escape commas in the globpath() function's path argument.
If not escaped, commas will cause globpath() to search in multiple
directories, none of which really exist.
2018-08-25 09:52:55 -04:00
Jason Franklin
b8cc044760 Merge pull request #875 from scrooloose/open_differently_cased_files
Force a case-sensitive comparison of new and existing buffers.
2018-08-25 09:36:57 -04:00
Jason Franklin
b10c61b063 Merge pull request #877 from scrooloose/replace_gt_with_tabnext
Use {count}tabnext to allow users to remap gt.
2018-08-25 09:18:08 -04:00
Phil Runninger (mac)
18071f5999 NERDTreeCWD: reset CWD if changed by NERDTreeFocus
When the user has `'autochdir'` turned on, opening a new NERDTree will
cause the current working directory to change. To prevent this
happening, remember the CWD and reset it if NERDTreeFocus caused it to
change.
2018-08-22 17:01:08 -04:00
Phil Runninger (mac)
39a89f5e50 Use <count>tabnext instead of <count>gt to allow users to remap gt. 2018-08-22 09:16:33 -04:00
Phil Runninger (mac)
026bfaf35e Do a case sensitive comparison of new/existing buffers.
When NERTDtree opens a file, it compares this new file to all open
buffers to see if it's already open. If the user has 'ignorecase' turned
on then the comparison of "file" and "File" says they're the same, and
NERDTree won't reopen the file. This commit forces a case sensitive
comparison by using the ==# operator.
2018-08-15 13:22:06 +00:00
Phil Runninger (mac)
7d9a3f0e8b Make sure the path to the bookmarks file exists before writing it. 2018-08-07 18:13:40 -04:00
Phil Runninger (mac)
b6978ecd70 Unzoom only when user want NERDTree to stay open. 2018-08-07 10:01:09 -04:00
Phil Runninger (mac)
192b07ce1f If the NERDTree is zoomed when 'o'pening a file, unzoom it.
'go' does not trigger this new behavior, because focus remains in the
NERDTree.
2018-08-07 09:00:39 -04:00
Phil Runninger
e653a68270 Merge pull request #867 from aflock/aflock/reword-renamed-buffer
Reword renamed-buffer prompt to be more clear
2018-08-04 15:13:46 -04:00
Andrew Flockhart
9e9d16a38a Reword renamed-buffer prompt to be more clear 2018-08-04 01:16:46 -04:00
Jason Franklin
43d569195c Merge pull request #866 from lifecrisis/bm_toggle 2018-08-03 14:04:57 -04:00
Jason Franklin
456367ab07 Put cursor on root when closing bookmark table
If the cursor is not already positioned on a node when the bookmark
table is closed, then the resulting position of the cursor is not
determined.  Here, we default to positioning the cursor on the
root when the bookmark table is closed.
2018-08-02 09:17:18 -04:00
Phil Runninger
eee179f0bf Merge pull request #856 from scrooloose/broken_sort_#277
Fix issues with sorting of nodes
2018-07-31 14:53:40 -04:00
Phil Runninger (mac)
e99a7a0313 Restore the cached _sortKey for faster processing.
Also add a new global variable to track when the g:NERDTreeSortOrder
changes. If it has been changed, or when the cached _sortKey value is
uninitialized, then calculate the sort key. This improves processing
speed over the previous commit, and allows on-the-fly changes to the
sort order, (without required vim to be restarted.)
2018-07-27 08:46:50 -04:00
Phil Runninger (mac)
1e2b7ef98d Remove AddDefaultGroupToSortOrder check from startup.
The call to AddDefaultGroupToSortOrder in NERD_tree.vim is redundant
because it's also done every time sortChildren is called. And since the
check is done only once, there's no need for a function either.
sortChildren now just contains the needed if statement.
2018-07-02 09:06:09 -04:00
Phil Runninger (mac)
6ef3213cd0 Fix indentation. 2018-07-02 08:55:32 -04:00
Phil Runninger (mac)
a053925279 Recalculate the node's sortkey every time.
The cached _sortkey wasn't being recalculated after changing the
NERDTreeSortOrder, resulting in incorrect sort orders.
2018-07-01 19:57:02 -04:00
Phil Runninger (mac)
703e1ef4fe Correctly check the type of the sort key's value. Fixes #842. 2018-07-01 19:55:26 -04:00
Phil Runninger
d6032c876c Merge pull request #853 from bubba-h57/master
Better OSX detection
2018-06-15 12:04:30 -04:00
Bubba
08db3a0eea Do not need to check for unix os here. 2018-06-15 12:02:58 -04:00
Bubba
a053179d6a Use the case-insensitive regex 2018-06-15 11:29:09 -04:00
Bubba
c0d87db309 Better OSX detection 2018-06-15 10:43:20 -04:00
Phil Runninger
26abd33ad9 Merge pull request #852 from mnussbaum/fix_maybe_missing_map
Bugfix - ensure keymaps dictionary exists before using it
2018-06-12 18:34:52 -04:00
mnussbaum
eb048a3070 Bugfix - ensure keymaps dictionary exists before using it
The s:KeyMap._all function isn't necessary if we initialize the
s:keyMaps dictionary at file load time.
2018-06-12 13:46:14 -07:00
Phil Runninger
bf4591c5d8 Merge pull request #851 from mnussbaum/decrease_startup_time
Decrease startup-time by avoiding linear-time iteration over key mappings
2018-06-12 11:31:03 -04:00
mnussbaum
657be6b24d Mark private function with leading underscore 2018-06-12 08:28:04 -07:00
mnussbaum
c6d757f198 Decrease startup-time by avoiding iteration over maps
This commit makes adding, removing and finding key maps an O(1)
operation instead of O(n), where n is the number of pre-existing maps.

In my testing, averaged over 100 iterations, this reduces the time spent
initializing NERDTree at Vim startup from ~73ms to ~9.7ms. That's with
only the default included key maps.
2018-06-10 23:55:04 -07:00
Jason Franklin
9af083a6d1 Merge pull request #849 from lifecrisis/sort-maps 2018-06-06 13:15:53 -04:00
Jason Franklin
57c825a169 Add code to sort mappings in quickhelp 2018-06-06 09:02:25 -04:00
Jason Franklin
0788027b55 Merge pull request #844 from lifecrisis/clearjumps
Use ":clearjumps" in new NERDTree windows.
2018-05-29 16:13:48 -04:00
Jason Franklin
80ee0897ff Add a call to ":clearjumps" to "_createTreeWin()"
Using the ":clearjumps" command wipes out the jump list for the
current window.  This means that the user can't inadvertently jump
out of the NERDTree buffer while using the NERDTree window (i.e., by
using "<C-O>").
2018-05-26 08:43:27 -04:00
Jason Franklin
35953042fb Merge pull request #840 from scrooloose/create_parent_directories_on_m-m
Like m-c did before, create parent directories if needed on m-m.
2018-05-22 09:48:37 -04:00
Phil Runninger (mac)
c4f8a0f370 Like m-c did before, create parent directories if needed on m-m. 2018-05-16 13:09:20 -04:00
Jason Franklin
6188c5ea5f Merge pull request #838 from lifecrisis/updir-fix 2018-05-07 08:22:55 -04:00
Phil Runninger
0bf429bac3 Merge pull request #837 from scrooloose/readonly-error-#831
Make the NERDTree buffer writable when rendering it.
2018-05-06 21:13:44 -04:00
Jason Franklin
f9e83ad8bd Fix a bug with the 'u' mapping
This commit refactors the "nerdtree#ui_glue#UpDir()" function to fix
a bug in the behavior of the 'u' mapping.  To reproduce the bug:

  1. Open a bookmarked directory with 'o'
  2. Press 'u' twice, observing normal behavior
  3. Open the same bookmark again with 'o'
  4. Press 'u' again, observe the new root is closed

The reason for this bug is that the parent node already existed and
was closed by the second 'u' press in step two above.

This commit fixes this bug by being careful to always open the new
root and transplant the child node properly.  Also, the internals of
the function in question were refactored to make use of valuable
NERDTree functions that ultimately help to reduce the amount of code
needed for this operation.
2018-05-06 12:19:19 -04:00
Phil Runninger (mac)
2c38519733 Make the NERDTree buffer writable when rendering it. 2018-05-06 11:34:24 -04:00
Jason Franklin
68313ef0f5 Merge pull request #835 from lifecrisis/cleanmaps
Remove unsupported bookmark table mappings.
2018-04-30 15:24:58 -04:00
Jason Franklin
2437b75479 Remove unsupported bookmark table mappings
The definitions for certain bookmark mappings reference callbacks
that don't actually support operation on bookmarks.  Furthermore,
the mappings that are defined are not documented anywhere.  Removing
them seems reasonable since they serve no real purpose.
2018-04-28 09:17:29 -04:00
Phil Runninger
925a96f58d Merge pull request #834 from bravestarr/fix-multibyte-path
Replace strcharpart() with substitute() for backward compatibility
2018-04-26 09:36:24 -04:00
bravestarr
abf200397f Merge branch 'master' into fix-multibyte-path 2018-04-26 21:20:33 +08:00
bravestarr
b45f2c27ea Replace strcharpart() with substitute() for backward compatibility 2018-04-26 17:13:06 +08:00
Phil Runninger
cc60495fe0 Merge pull request #833 from hav4ik/master
Fixed error 'unknown function strcharpart' for older versions of Vim
2018-04-25 01:25:43 -04:00
hav4ik
0972cda243 Fixed bug 'unknown function strcharpart' for older versions of Vim 2018-04-25 03:04:18 +03:00
Phil Runninger
d3a7cd20ae Merge pull request #830 from bravestarr/fix-multibyte-path
Display a path with multi-byte characters correctly when it is truncated
2018-04-24 14:19:36 -04:00
Jason Franklin
ec3c3b0fa1 Merge pull request #832 from lifecrisis/menufix
Clear output when the NERDTree menu is aborted.
2018-04-23 17:12:14 -04:00
bravestarr
6aff1b6cd3 Display a path with multi-byte characters correctly when it is truncated
When a path is rendered in the Bookmarks area or as the header line of the
tree, it is truncated if there is no enough space for it.  But if a path
contains multi-byte characters, it should be truncated by characters, not
bytes, otherwise the path may be truncated between the bytes of a
multi-byte character.  To deal with multi-byte characters, use
strdisplaywidth() instead of len() to get the number of display cells, and
use strcharpart() instead of strpart() to truncate a path.
2018-04-23 03:09:49 +08:00
Jason Franklin
164131762f Refine the internals of the "showMenu()" function 2018-04-22 10:23:16 -04:00
Jason Franklin
38d4d2288a Clean up a function comment 2018-04-22 10:21:16 -04:00
Jason Franklin
1792b6a75b Clear output when the NERDTree menu is aborted
Previously, exiting the NERDTree menu with "Ctrl-C" or "Esc" would
leave the last line of the menu visible.  We can avoid this by
redrawing the screen when the menu is aborted in this manner.
2018-04-22 10:19:13 -04:00
Phil Runninger
727770147a Merge pull request #824 from ngnmhieu/master
Support revealing file and executing file with xdg-open for Linux
2018-04-10 08:23:02 -04:00
Hieu Nguyen
435861ee69 Support revealing file and executing file with xdg-open for Linux 2018-04-09 19:08:09 +02:00
Phil Runninger
a0e49c9b11 Merge pull request #822 from scrooloose/821-better_delete_confirmation
If node isn't open, count children on disk before deleting.
2018-04-02 14:01:00 -04:00
Phil Runninger (mac)
b37495fa98 If node isn't open, count children on disk before deleting.
Fixes #821. If a node isn't opened in NERDTree, it's children aren't
known yet, so when deleting the node (with `m`, `d`), the user isn't
properly asked to confirm the delete. It was going to the less strict
`Y`/`n` confirmation, instead of the `yes` confirmation for non-empty
directories.

This change checks to see if the node is opened already. If it is, the
existing getChildCount() function is used; otherwise, the disk is read
to get the number of children there.
2018-04-02 09:26:34 -04:00
Phil Runninger (mac)
a172d7cfcb Add documentation for the NERDTreeRemoveDirCmd option. 2018-03-13 08:51:33 -04:00
Phil Runninger
b702500f77 Merge pull request #816 from kutsan/master
Add new variable g:NERDTreeRemoveFileCmd
2018-03-13 08:41:08 -04:00
Kutsan Kaplan
9afa6b3828 Add new variable g:NERDTreeRemoveFileCmd 2018-03-13 15:17:10 +03:00
Phil Runninger
ed446e5cbe Update issue template again. "Optional" isn't needed. 2018-03-06 11:31:19 -05:00
Phil Runninger
f6987b7ea6 Merge pull request #814 from scrooloose/813-bwipeout_NERDTree_buffer
Use a better check for existence of the NERDTree buffer.
2018-03-06 11:28:46 -05:00
Phil Runninger (mac)
d6fe203dec Update issue template, making it a little cleaner. 2018-03-06 09:23:11 -05:00
Phil Runninger (mac)
dc349a072a Use a better check for existence of the NERDTree buffer.
If the user wipes out or deletes (:bw or :bd) the NERDTree buffer, there
is still a tab variable that hangs onto the name of that now-missing
buffer. Checking only that variable is not enough to decide whether to
create a new NERDTree or use the existing one. Fortunately, there
already is a function with a more complete check: ExistsForTab()
2018-03-06 08:41:06 -05:00
Phil Runninger
e47e588705 Merge pull request #801 from mrubli/focus-on-close
Fix focussing previous buffer when closing NERDTree
2018-02-02 09:19:53 -05:00
Martin Rubli
a0f3bf3ed6 Focus previous window when closing NERDTree
Previously closing NERDTree while two windows were showing the same
buffer would focus the first window, which was not necessarily the
previously active one.

Instead of obtaining the buffer ID of the previous buffer and
mapping that to the window ID (which is a 1:n mapping) we obtain the
unique window ID and focus the right window after closing NERDTree.

win_getid() and win_gotoid() are available from VIM 7.4.1557 but the
old behavior is used as a fallback if the two functions are not
available.
2018-02-02 21:26:17 +08:00
Jason Franklin
68572ef461 Merge pull request #796 from lifecrisis/doc-update
Update the documentation for the "NERDTreeStatusline" setting.
2018-01-07 08:34:08 -05:00
Jason Franklin
183bb53485 Merge pull request #795 from lifecrisis/empty-line
Fix unstable behaviour in the "NERDTreeUI.getPath()" method.
2018-01-07 08:33:01 -05:00
Jason Franklin
6e26222a30 Update the docs for "NERDTreeStatusline" 2018-01-06 10:55:18 -05:00
Jason Franklin
a019486dc8 Fix unstable behavior in "NERDTreeUI.getPath()"
This commit prevents "NERDTreeUI.getPath()" from returning a "Path"
object even when no tree node was selected.  Previously, positioning
your cursor on one of the blank lines above the tree and running...

  :echo g:NERDTreeFileNode.GetSelected()

... could potentially return the path for the current working
directory (your working directory needs to be under the tree root).
This is because the constructor for "Path" objects returns a "Path"
for the current working directory when passed an empty string.  So,
we need to short circuit the "getPath()" function for lines that
cannot possibly be tree nodes.

This solves the problem for "GetSelected()" because that method uses
the "getPath()" method from the "UI" class to do its work.

Note that this bug only presented for me on *nix systems.
2018-01-06 10:31:15 -05:00
Jason Franklin
1d14961285 Remove a noise comment 2018-01-06 09:28:15 -05:00
Jason Franklin
8f052c5b47 Simplify the commentary for the "getPath()" method 2018-01-06 09:23:27 -05:00
Jason Franklin
1e93f6840a Format the commentary in "ui.vim" 2018-01-06 09:10:10 -05:00
Jason Franklin
c6a68d4b96 Improve the style in a "TreeFileNode" method
No functional changes here.
2018-01-06 09:02:10 -05:00
Jason Franklin
d745e11b42 Format the commentary in "tree_file_node.vim" 2018-01-06 08:54:28 -05:00
Jason Franklin
e6a116a9cd Improve the code style in a "Path" method
No functional changes here.  Only style improvements were made.
2018-01-06 08:41:55 -05:00
Jason Franklin
f4df038366 Refactor the "Path" constructor 2018-01-06 08:35:34 -05:00
Jason Franklin
5fc48b0b13 Merge pull request #794 from lifecrisis/reopen779
Revert the bugfix from pull request #785 and reopen issue #779.
We keep the good style changes from PR #785 intact.
2018-01-05 08:35:52 -05:00
Jason Franklin
af3ba1ef4e Revert the bugfix from pull request #785
The small change here reverts an attempted bugfix from #785.  That
change resulted in the unintended side-effect of closing other
children of the root whenever ":NERDTreeFind" was invoked.  This was
disruptive (as reported in #793), so a new method must be found to
solve the problem of ":NERDTreeFind" not opening newly created
files.

Fixes #793.
2018-01-05 08:32:03 -05:00
Jason Franklin
fa65ec60ea Merge pull request #786 from lifecrisis/find-hidden
Here, a more accurate method of determining whether or not to show
hidden files is used.  A new method, "isHiddenUnder()" is defined
for "Path" objects.  This method is then used to set the flag for
hidden files in the ":NERDTreeFind" command.  Note that this
function is likely to be useful elsewhere.

Fixes #189.
2018-01-05 08:12:59 -05:00
Jason Franklin
d90b2af474 Add a space to help the parser 2017-12-22 10:46:49 -05:00
Jason Franklin
0ff697eb40 Implement the "isHiddenUnder()" method for Path 2017-12-22 10:28:31 -05:00
Jason Franklin
57788abd6f Merge pull request #785 from lifecrisis/find-new-file
In certain cases, ":NERDTreeFind" would fail to reveal files that
were created/written after the current tab's NERDTree had been
initialized.  This pull request repairs that problem.
2017-12-22 09:44:04 -05:00
Jason Franklin
f6dad4796e Update the documentation
The docs for ":NERDTreeFind" are updated.  Some additional
formatting changes are made to other sections.
2017-12-22 09:16:16 -05:00
Jason Franklin
01b011d38e Have "finAndRevealPath()" fail on no file
If a file does not exist for the current buffer, this function
should fail with a clear warning message.

Here, I improved the messages that this function prints so that it
fails gracefully when no path can be determined in the calling
context.
2017-12-22 08:45:57 -05:00
Jason Franklin
344119439e Refresh children of directory nodes on "reveal()"
The ":NERDTreeFind" command calls the "reveal()" method on the
NERDTree root node.  The "reveal()" method would, in turn, call the
node's "open()" method.  Since the "open()" method would only
initialize the child nodes of the root (i.e., read them from disk)
when the list of child nodes was empty, new paths would not be
included in the list.

This commit will result in the refreshing of the child node list
whenever "reveal()" is called on a directory node (unless it is the
first time the node is being opened... the most efficient option).

The result is that ":NERDTreeFind" will discover newly created paths
that exist on disk but are not cached in the NERDTree.

A stray debugging message is also removed.

Fixes issue #779.
2017-12-21 10:36:16 -05:00
Jason Franklin
90d08dc626 Add a debugging message 2017-12-21 09:26:26 -05:00
Jason Franklin
5301dd24fb Improve variable naming in "findAndRevealPath" 2017-12-21 08:43:15 -05:00
Jason Franklin
496d9a17d8 Remove code duplication in "findAndRevealPath" 2017-12-21 08:28:28 -05:00
Phil Runninger
fc14b4f5df Add :Helptags to the pathogen instructions 2017-12-19 09:45:47 -05:00
Jason Franklin
509122df20 Merge pull request #782 from lifecrisis/modelines
Add a modeline to each script that needs but does not have one.
2017-12-17 08:53:01 -05:00
Jason Franklin
9f985514f0 Add modelines 2017-12-17 08:43:43 -05:00
Jason Franklin
193fed598b Merge pull request #781 from lifecrisis/find-complete
Change the type of completion used by :NERDTreeFind.
2017-12-12 09:03:53 -05:00
Jason Franklin
b4b99c39fa Change the type of completion used by NERDTreeFind
This command should complete file names, not directories.

Fixes #780.
2017-12-12 08:24:18 -05:00
Phil Runninger
461ea6d2d8 Merge pull request #778 from zhenyangze/master
change NERDTreeFind with args
2017-12-11 13:27:14 -05:00
Jason Franklin
c20ac9c27f Merge pull request #772 from skyblueee/stripMarkup_leadingSpaces
Remove useless argument in user interface function.
2017-12-09 11:33:54 -05:00
Jason Franklin
fc55d012ee Merge pull request #773 from skyblueee/wasdir_sub
Remove two useless substitutions.
2017-12-09 11:28:40 -05:00
Jason Franklin
2129740419 Add style improvements
Function-local variables, instead of script-local variables, should
be used here.  In addition, "empty()" is a better choice for testing
for the absence of an argument.  Finally, the use of "else" is
removed.

The docstring is also updated to include the new argument.
2017-12-09 11:09:10 -05:00
zhenyangze
12960b966f change NERDTreeFind with args 2017-12-09 16:58:18 +08:00
Jason Franklin
8cbea5109e Merge pull request #777 from lifecrisis/bm-confirm
Use the confirm() builtin when deleting a bookmark.
2017-12-06 11:10:51 -05:00
Jason Franklin
e48ae299f9 Update the delete bookmark map to use confirm()
I contend that we should use confirm() whenever possible.  It makes
the code cleaner and uses a builtin feature rather than a custom
one.  Doing it the "Vim way" is always preferable in my mind.
2017-12-01 08:45:18 -05:00
SkyBlueEE
ea01a691a2 remove useless removeLeadingSpaces in _stripMarkup 2017-11-28 00:04:03 +08:00
SkyBlueEE
3485b2a939 remove useless substitute when 'file =~# "/$"' 2017-11-27 23:56:41 +08:00
Jason Franklin
b89de09810 Merge pull request #769 from lifecrisis/o-map
Make the "o" mapping consistent with the "x" mapping.
2017-11-20 07:47:33 -05:00
Jason Franklin
ac94cd28c2 Make the "o" mapping consistent with "x"
The "o" mapping, which toggles directory nodes open/closed, allowed
the user to close the tree root.  This was not consistent with the
"x" mapping which stops the user from doing this.  This applies to
a double-click on the root node as well.

It should be noted that, if the root node is somehow closed, "o" and
double click can still re-open the tree, even with this change.  In
other words, I was careful.
2017-11-19 16:37:54 -05:00
Jason Franklin
e0e36c5385 Fix a problem with the "x" handler (#768)
Pressing "x" on a cascade could close the root of the tree.  This
commit prevents that from happening.
2017-11-18 10:55:43 -05:00
Jason Franklin
f526c4e652 Clean up the handler for the "x" mapping (#767)
Previously, pressing "x" on the tree root would result in
unpredictable behavior.  The user would either an receive an error
message or the parent of the tree root (which is not visible) would
be closed.  This commit repairs this problem.

In addition, some code duplication was removed.
2017-11-18 09:51:34 -05:00
Jason Franklin
70c8cb9bfa Revert change to tab opening method (#766)
Previously the "t" and "T" mappings were altered to open new tabs at
the end of the tab line.  This commit reverts that change.
2017-11-18 09:50:40 -05:00
Jason Franklin
93356cd92b Add back support for "b:NERDTreeRoot" (#765) 2017-11-14 18:36:09 -05:00
Jason Franklin
b6e3c0db30 Merge pull request #759 from lifecrisis/iss549
This pull request repairs the broken "t" and "T" mappings.
2017-11-14 08:37:09 -05:00
Jason Franklin
e59d02575e Update the CHANGELOG 2017-11-14 08:33:31 -05:00
Jason Franklin
21c470c316 Have new tabs open as the last tab (with '$') 2017-11-14 08:29:40 -05:00
Jason Franklin
4c409a1640 Add a note/warning to "TreeDirNode.activate()"
This warning makes developers aware of the possibility of
overwriting the NERDTree text in a new window when activate is used.
2017-11-11 13:23:51 -05:00
Jason Franklin
e27cd86a9b Document "t" and "T" mappings in the quick help 2017-11-11 13:09:42 -05:00
Jason Franklin
31dbf1c139 Silence messages when opening a file with "T" 2017-11-11 12:37:04 -05:00
Jason Franklin
c9f7014034 Fix handlers for "t" and "T" on bookmarks
The "t" and "T" mappings didn't work on bookmarks.  This commit
fixes this problem by making the callbacks more general.

Fixes #565.
2017-11-11 12:10:08 -05:00
Jason Franklin
ae1c95bcbc Explicitly call open() in "ui_glue.vim" callbacks
This bug is subtle!  Opening a directory node in a new tab (with the
"t" or "T" mappings) would previously fail and require a refresh
because it called the directory node's "activate()" method.

In reviewing that method (i.e., "activate()"), I discovered that the
directory node's NERDTree is rendered before the method returns,
which overwrites the content of the tree in the new tab or window.

To clarify, when "t" or "T" is used on a directory node, a new
directory node and tree must be created to be rendered in a new tab.
So, calling "self.getNerdtree().render()" at the bottom of
"activate()" will render the NERDTree instance from which "t" or "T"
was invoked, not the new NERDTree that is being displayed.  This
overwrites the new NERDTree text, and, thus, a refresh is required.

Since a call to "render()" is almost always necessary at the bottom
of "activate()" to keep everything in sync for other mappings, we
avoid this problem entirely by using the "open()" method directly
(works for files and directories) in the callbacks.

Fixes #549.
2017-11-11 11:19:16 -05:00
Jason Franklin
0a0374b826 Remove an unnecessary assignment 2017-11-11 09:09:19 -05:00
Jason Franklin
870bedef21 Clean up the Creator.createTabTree() function 2017-11-11 09:08:24 -05:00
Jason Franklin
d9074c2753 Clean up the commentary in "creator.vim" 2017-11-11 08:53:47 -05:00
Jason Franklin
3cb90cb18d Extract a common line to the top of a function 2017-11-11 08:45:34 -05:00
Jason Franklin
26168324fc Remove an unnecessary "else" clause 2017-11-11 08:34:29 -05:00
Jason Franklin
f0a97209f1 Clean up the NERDTreeOpener constructor
This method needed some love.  The internals were simplified and
reformatted, and the comment was edited for additional readability.
2017-11-11 08:29:09 -05:00
Phil Runninger
97433edd43 Merge pull request #754 from branch comma-separated-file-size
This change will display the file size (printed with the "ml"
command) in an easy-to-read format, while still displaying its
precise value.  It uses the "stat" command (with the correct
switches for Unix and OSX) to get the file size, "sed" to add the
commas, and "sed" again to replace the original size with the
modified number.
2017-11-02 08:36:07 -04:00
Mohamed Boughaba
a8c6245057 Merge pull request #756 from mboughaba/master
Previously, deleting a file in the NERDTree with "md" would cause
a new buffer to be created to fill the window(s) occupied by
a buffer on the file.  This pull request makes it so that a new
buffer is not created.  Instead, the next buffer in the buffer list
fills the window.

Fixes #755.
2017-11-02 08:26:48 -04:00
Jason Franklin
f554c20cb2 Merge pull request #751 from ashumkin/dir-arrows-on-cygwin
Introduce the "nerdtree#runningCygwin()" function.
2017-10-27 11:37:12 -04:00
Alexey Shumkin
cb9f4db6ff fixed: directory navigation does not work on Cygwin
Directory tree navigation is broken because of directory signs which is
shown in UTF-8.

Cygwin is a Windows application, so it uses ASCII codepages and so
directory signs must be in ASCII, but if to modify
"nerdtree#runningWindows" function there are many other functions break
that convert paths, e.g.

So, the quick and reliable solution is to add a
separate function "nerdtree#runningCygwin" and use it in a specific
place.
2017-10-27 10:06:51 +03:00
riyu ken
8a6ae7c633 Use a better function to change directories
When g:NERDTreeChDirMode is 2, changing the tree root will change the working
directory as well.  This change was silent because the wrong function was used to
make the switch.  This commit uses a better function that echoes a message.
2017-09-28 09:04:01 -04:00
Jason Franklin
5782b228e4 Merge pull request #734 from lifecrisis/issue733
BUGFIX: Make the NERDTree aware of the 'shellslash' setting.
2017-08-19 09:48:27 -04:00
Jason Franklin
876283b07c Improve display of shell output from menu command
This small change reverts to the previous method of breaking shell
output into lines.  The reason for this is to avoid the printing of
trailing carriage return characters on Windows.
2017-08-19 09:39:25 -04:00
Jason Franklin
f4ff6dcf84 Fix a menu command that breaks under 'shellslash'
The (l) menu command breaks on Windows systems when 'shellslash' is
set.  This is due to the fact that the menu item uses a hard coded
shell command, thus relying on the use of the default Windows shell
without the 'shellslash' setting.

The pattern used for the fix is localized to the problem function.
However, this technique could easily be abstracted into its own
function to execute Windows shell commands with the default shell
throughout the NERDTree codebase.
2017-08-19 08:58:57 -04:00
Jason Franklin
d7cf9a2a98 Fix the drive check in "TreeDirNode._glob()"
This check did not use the proper abstract method to check for a
path separator. It now does.

This fixes a problem with the 'u' macro that I noticed while working
on the fix for using the NERDTree with 'shellslash'.
2017-08-11 10:14:05 -04:00
Jason Franklin
a32a55e8d9 Rewrite the "Path._strForEdit()" method
This method used the brittle "Path._escChars()" method to do its
work.  This created problems when 'shellslash' was in use on Windows
because excessive escape characters (i.e., backslashes!) are
interpreted by Vim as additional path separators.

The above problem made it impossible to edit files with weird names
using the NERDTree on Windows with 'shellslash' set.  For example,
'+' should be escaped with ":edit", but '(' should not.  So, when
escaping '(', Vim on Windows correctly sees the start of a new
directory in the path.

This was reported in five issues which may be read for further
details and commentary.

Fixes #398, fixes #474, fixes #653, fixes #674, and fixes #733.
2017-08-11 10:09:18 -04:00
Jason Franklin
7a2fc6b6b9 Refactor the "Path._str()" method
This method was using hardcoded values rather than provided
abstractions to do its work. These improvements were necessary.
2017-08-11 09:43:57 -04:00
Jason Franklin
19b8dd7b60 Add a check for 'shellslash' in "Path.Slash()'
Several issues (namely issue #733) report problems with using the NERDTree
on Windows when 'shellslash' is set.  This commit doesn't solve all of these
problems, but it improves the NERDTree's recognition of this setting.
2017-08-11 09:32:01 -04:00
Jason Franklin
72f9135d19 Clean up the commentary for two Path methods
Especially note the improvements to the commentary on "Path.str()".
This method does too much. However, it is used heavily, and changing
its interface would be a major undertaking at this point.
2017-08-11 09:19:36 -04:00
Jason Franklin
b5e54d255e Rewrite the "Path._strForCd()" method
This commit is the first in a series of commits that will rework
some of the methods responsible for escaping pathnames. Some of
these methods simply don't use the features that Vim has properly.

The custom "Path._escChars()" method is far too rigid for our
purposes, and better options have been available for some time.

See ":h fnameescape()" for an especially helpful function in this
effort.
2017-08-11 08:46:41 -04:00
Jason Franklin
1a121337dd Clean up the script header in "path.vim"
Some code was reorganized and comments were written/rewritten.
2017-08-11 08:33:51 -04:00
Jason Franklin
a7d667b81b Add spaces after comment leaders in "path.vim"
Here, I applied the usual fix for the cramped comments I've found in
our scripts. Use this command...

 :%s/^"\ze\S/" /

to fix this problem elsewhere.
2017-08-11 08:07:23 -04:00
Jason Franklin
8cd17c1a47 Merge pull request #731 from lifecrisis/tilde
Address special cases for three highlighting rules.
2017-07-29 09:48:16 -04:00
Jason Franklin
d68c9abca8 Improve three highlighting rules
The highlighting rules "NERDTreeClosable" and "NERDTreeOpenable" did
not recognize files beginning with a "~" character. This caused bad
highlighting on systems that use "~" and "+" for the dir arrow
symbols by default. Making these rules more specific solves this
problem.

The "~" characters in quickhelp section titles also would get
confused with a custom mapping for "~". Adjusting the
"NERDTreeHelpTitle" solved this problem.

I also changed the quickhelp title in a minor way to reflect the
proper spelling of "NERDTree".
2017-07-29 09:40:11 -04:00
Jason Franklin
5af263c2df Merge pull request #729 from ParkerKemp/master
Change windows using window number when opening in new vertical
split.
2017-07-29 09:04:44 -04:00
Jason Franklin
35724ee206 Refactor the internals of "_newVSplit()"
The previous change to this function was simple. I figured that it
would be a good time to improve the style of this function with some
minor edits. The function is now cleaner and more readable.
2017-07-29 08:55:28 -04:00
Jason Franklin
719d6785d4 Edit the commentary in "opener.vim"
This commit doesn't change the content of any comments. It just
changes their appearance (leading quotes are now followed by
a space).
2017-07-29 08:37:25 -04:00
Jason Franklin
1269c070cd Divide the introductory paragraph in the README
This paragraph was too long and needed to be broken.
2017-07-28 20:56:19 -04:00
Jason Franklin
7027fd156e Merge pull request #730 from lifecrisis/issue573
Improve the appeal of the "README.markdown" file.
2017-07-28 20:42:14 -04:00
Jason Franklin
6efef8651e Edit the README file
Two key changes were made:

 1. A screenshot was added for visual appeal.
 2. The massive (and noisy) feature list was removed. This
    information is adequately covered in the docs.

Fixes #573.
2017-07-28 20:38:26 -04:00
Parker Kemp
eae5d02fa9 Use window number when opening in new vsplit 2017-07-24 15:32:59 -04:00
Jason Franklin
e2a9929bbe Merge pull request #722 from lifecrisis/open-bookmark
Have bookmarked directories open with all children closed.
2017-07-17 08:13:12 -04:00
Jason Franklin
5daec4c7b7 Edit stale commentary and add proper sigils 2017-07-14 18:02:02 -04:00
Jason Franklin
3a7694aa55 Add a call to close the children of bookmarks
When bookmarks are opened normally (i.e., when a bookmark is made
the root of the current NERDTree), any open children of that
bookmark will remain open.

This is often inconvenient, especially for users who want bookmarks
to appear "fresh" when opened.
2017-07-14 17:52:00 -04:00
Jason Franklin
1f089a362b Rework the "TreeDirNode.closeChildren()" method
This function needed polishing; in the choice of variable names and
in the leading comment.
2017-07-14 17:36:09 -04:00
Jason Franklin
3245007f0e Remove a method from the TreeDirNode class
The "TreeDirNode.getDirChildren()" method is never called and can be
safely removed.

Further, note that this method has a bug. It calls the "filter()"
builtin function, which modifies "self.children" in-place. This is
obviously not a desirable side effect of calling this function.

If the functionality is genuinely required later, "filter()" should
be called on a copy of "self.children" to achieve the desired
result.
2017-07-14 17:17:25 -04:00
Jason Franklin
a3fdf1e3c1 Merge pull request #721 from lifecrisis/issue67
UPDATE: The `p` mapping now works on cascades.
2017-07-08 11:43:38 -04:00
Jason Franklin
49c165a103 Update the function that drives the p mapping
As reported in issue #67, the function driving the `p` mapping was
not updated to work as expected when the cursor is positioned on a
cascade. This problem is addressed here.

Fixes #67.
2017-07-08 11:33:10 -04:00
Jason Franklin
ab0a3a7c24 Merge pull request #720 from lifecrisis/issue526
BUGFIX: Repair opening and closing of cascades.
2017-07-08 10:04:08 -04:00
Jason Franklin
c1b71dcfc5 Rename the help file to "NERDTree.txt"
I thought renaming this file was important so that the NERDTree name
is printed with consistency. Branding is important.
2017-07-04 10:14:35 -04:00
Jason Franklin
ef35ee8918 Remove the helper function for "openRecursively()"
The support function for this method was unnecessary, so I took the
time to remove it. Since "TreeDirNode.openRecursively()" now calls
the "open()" method, it can take advantage of the improvements made
to that function in recent commits. Specifically, this method will
reflect the bugfix provided in pull request #720.
2017-07-04 09:45:06 -04:00
Jason Franklin
7f4a7205dc Replace an equality test with an instance method
A proper instance method was substituted for the more brittle
equality test in the "TreeDirNode.open()" method.

Note that the order of the tests was reversed to account for the
fact that the "isRoot()" method can only be called after the first
test has passed.
2017-07-02 15:16:49 -04:00
Jason Franklin
ebc206e58d Refactor "TreeDirNode.close()" method
This method required adjustment to take cascades into consideration.

Since the arrow in the NERDTree window reflects the status of the
tail directory of the associated cascade, an arrow indicating open
status can be present when a higher directory in the cascade was
closed.

This commit will automatically close child nodes within the same
cascade of a closed directory node so that the arrow accurately
reflects what is rendered.
2017-07-02 12:25:15 -04:00
Jason Franklin
8660541333 Fix the "TreeDirNode.open()" method
Issues #547 and #526 reported a problem with the "open()" method in
the "TreeDirNode" class.

Specifically, opening a cascade in the NERDTree will perform the
opening operation on the tail of the cascade. This is a problem when
other operations (such as the "u" mapping) close intermediate
cascaded directories, which causes opening the tail to have no
effect (other than toggling the arrow).

Here, the "open()" method was modified to open all directories in a
cascade whenever the tail is opened. This is the only reasonable fix
for this type of problem.

Fixes #547 and fixes #526.
2017-07-02 12:25:15 -04:00
Jason Franklin
18f04e0824 Refactor the "TreeDirNode.displayString()" method
I found this method to be unreadable and cumbersome. Cleaning it up
helped me to understand the design ideas behind it.
2017-07-02 12:25:15 -04:00
Jason Franklin
2e43ad074b Merge pull request #719 from lifecrisis/issue718
This pull request fixes the bug reported in issue #718.
2017-06-30 10:21:21 -04:00
Jason Franklin
2b2b35ceda Fix an inaccurate version check
Calling the function "globpath()" is complex when one is trying to
support multiple versions of Vim because this particular function
developed rapidly (as did "glob()") during the life of Vim 7.0.

This commit makes the version check for calling "globpath()" much
clearer. It also allows for rendering dead links in the NERDTree by
changing the "globpath()" call for versions of Vim that include
patch 7.4.654. This can be done later when the effects are known and
the feature is officially requested.

Fixes #718.
2017-06-30 10:11:06 -04:00
Jason Franklin
7ed79c00c1 Merge pull request #717 from scrooloose/dev
Define the "TreeDirNode._glob()" method.
2017-06-28 19:05:19 -04:00
Jason Franklin
779e13374a Edit the filter in the TreeDirNode glob method
A better style for executing the removal of each filtered name was
chosen. This is a minor change, but I viewed it as necessary.
2017-06-28 16:56:03 -04:00
Jason Franklin
2a97fb0fda Reformat the commentary in the TreeDirNode script
The commentary in "tree_dir_node.vim" needed to be cleaned up a
little. Spaces after leading quotes are a good idea, to avoid the
"clustered" appearance that comments can sometimes have.

Use the following substitution command...

  :s/^"\ze\S/" /

to make this change to longer scripts.
2017-06-28 16:55:54 -04:00
Jason Franklin
b877fc65d8 Rename and expand the TreeDirNode glob method
Pull request #710 also brought to my attention some glaring code
duplication in the TreeDirNode class. This commit renames and
expands the glob method defined in PR #710 into a more general
purpose helper method.

The new method also ensures that 'wildignore' rules are applied
consistently. Issue #569 noted that the application of the
'wildignore' setting in populating a node's children was
unpredictable. When a node was rendered, "_initChildren()" would
load the children with its own call to "globpath()". Refreshing the
same node would then invoke "globpath()" again, but with different
arguments.

The result was that a node's children were initialized using the
'g:NERDTreeRespectWildIgnore' setting, but refreshing ignored this
setting. So, if it the setting was 0, "test.class" might render when
the parent was initialized, and then be removed on refresh (if
'wildignore' contained '*.class').

This commit solves this problem by ensuring that the NERDTree
setting mentioned above is only checked and applied to a node's
children in one place by cleaning up the duplication.

Fixes #569.
2017-06-28 16:55:43 -04:00
Jason Franklin
b0c44c7be1 Refactor the TreeDirNode glob method
Pull request #710 correctly noted that TreeDirNode directories must
be passed to "globpath()" as relative paths (i.e., to the working
directory) if 'wildignore' rules for relative paths are to be
obeyed.

The solution was to use "fnamemodify()" to get a relative path to
the TreeDirNode object's directory, if possible. However, this
method does not modify our TreeDirNode path if it IS the current
working directory. Thus, immediate children of the node are seen as
absolute paths in glob results when our PWD is pointing to their
parent. This is not consistent behavior.

This commit defines the result of this function as ',' when this
special case arises to fix this problem.

See ":h 'path'" for an explanation of how this works.
2017-06-28 16:55:24 -04:00
Jason Franklin
4a487474c4 Modify call to sort() for older versions of Vim (#714)
Older Vim versions seem to require that calls to sort() specify a
dictionary when the compare function argument is a dictionary
function. This seems to be required even when the dictionary is not
used. Since this change does not seem to affect behavior in later
Vim editions, I see no harm in including it.
2017-06-22 17:15:51 -04:00
Phil Runninger
626e80f6e4 Merge pull request #536 from satori/master
Add support for natural sorting order.
2017-06-21 11:33:47 -04:00
Phil Runninger
54b423e0f8 Merge pull request #711 from lifecrisis/issue650
BUGFIX: Broken middle click listener repaired.
2017-06-19 23:49:38 -04:00
Jason Franklin
c934b50c0d Repair the broken middle mouse click handler
Issues #597, #642, and #650 all report problems with the NERDTree
handler function for middle mouse clicks. In all cases, the problems
arose from the use of a function that didn't exist and from the use
of a bad argument in the call to the "g:NERDTreeAddKeyMap" function.
The fix for the first problem is obvious, but the solution to the
second bug merits explanation.

Previously, middle click events in the NERDTree window were
triggered with the "<MiddleRelease>" Vim key code. Since
"<MiddleMouse>" is always triggered before "<MiddleRelease>", The
error in #642 was bound to occur (because of the default behavior
for middle mouse clicks). Thus, the problem was easily solved by
using "<MiddleMouse>" instead of "<MiddleRelease>" in the mapping.

As an enhancement, I added the trigger of a "<LeftMouse>" event as
the first command in the handler function. This will cause the
middle click to reposition the cursor below the pointer before
continuing with its normal behavior. The benefits of this are clear.

This mapping has no defined behavior for bookmarks. Unless an issue
is raised to address this, it will be left just so for now.

Fixes #597, fixes #642, and fixes #650.
2017-06-19 17:28:41 -04:00
Phil Runninger
5ce9bda392 Merge pull request #710 from jason0x43/globPath-fix
Handle non-relative globDir properly in Windows
2017-06-19 08:13:35 -04:00
Jason Cheatham
1d83e4c1ce Handle non-relative globDir properly in Windows
In Windows, fnamemodify with ':.' will strip the drive letter from a
path that isn't under CWD. This update ensures such a path has the drive
letter.

references #709
2017-06-18 21:23:17 -04:00
Phil Runninger (mac)
5f3a44d066 Document the :NERDTreeFocus command. Closes #706. 2017-06-16 08:50:21 -04:00
Phil Runninger
2c3249de68 Merge pull request #675 from jason0x43/relative-paths
Use relative path with globpath
2017-06-13 09:54:42 -04:00
Phil Runninger
17713ee293 Merge pull request #704 from lifecrisis/bookmarks-markers
FEATURE: The g:NERDTreeMarkBookmarks setting
2017-06-11 23:56:34 -04:00
Phil Runninger
9bd34f9424 Merge pull request #703 from lifecrisis/issue677
BUGFIX: Repair the broken ":OpenBookmark" command
2017-06-11 23:25:09 -04:00
Jason Franklin
9b3487db64 Update the option summary
It came to my attention that the option summary has been neglected for
the past few commits. I added the new option in this feature branch and
updated the descriptions of two nearby options.

This section could use some focused editing.
2017-06-11 09:47:50 -04:00
Jason Franklin
471a03c9d9 Implement the g:NERDTreeMarkBookmarks setting
The setting is self-explanatory. See the added documentation for further
details.
2017-06-10 17:07:57 -04:00
Jason Franklin
3063dfb766 Refactor the :OpenBookmark command
I altered the behavior of the ":OpenBookmark" command to match that of
the "NERDTree-o" mapping. This is acceptable for the following reasons:

 1. It was broken, so no one was using it.
 2. The name matches its behavior.

If a bookmark is to be opened in an explorer window, we should have a
command with a matching name for that behavior (":ExploreBookmark", for
example). This can be added later if there is enough demand for the
feature. Otherwise, this is a perfectly valid change.
2017-06-10 15:59:56 -04:00
Jason Franklin
a03a639390 Refactor and re-document Bookmark.getNode()
A few minor changes were made to the "Bookmark.getNode()" function for
the purposes of improving readability and documentation clarity.

This process also led me to the conclusion that the "findNode()"
function should be refactored to throw an error if a node cannot be
found. This would lead to greater uniformity in the reporting of
failures to find a node. It is generally better style to have an error
thrown as close to the source as possible. A substantial change like
this should wait for now.
2017-06-10 13:29:27 -04:00
Jason Franklin
c0b90811b0 Add an argument sigil in a Bookmark class method
A missing argument sigil is effectively a syntax error in VimL. The
function in which the error occurred was called in the execution of at
least three buffer-local NERDTree commands:

 1. :Bookmark (specifically, when trying to overwrite a Bookmark)
 2. :OpenBookmark
 3. :RevealBookmark

Only one specific type of error message associated with these commands
is fixed here (see issue #677).

The problems with the above commands are not fully addressed by this
commit, and their behavior can be improved immensely by further
refactoring. However, no one has been able to even use these commands at
all before now because the fix given here was not in place.

More work will need to be done to improve the behavior of these commands
so that they truly function as any reasonable user would expect.

Fixes #677.
2017-06-10 11:18:14 -04:00
Jason Franklin
b0f60552ea Rewrite and expand the header in bookmark.vim
The header in "bookmark.vim" was pretty weak. It provided no description
of the class it contains and no direction for the reader. In particular
it did not note the dual purpose of the "Bookmark" class.

The fact that the "Bookmark" class serves two purposes must be noted
because many readers will expect class definitions to obey the single
responsibility principle!

If there is a chance for a major refactor of this class in the future, a
priority would be splitting the class in two so that a "BookmarkList"
class can assume the responsibility for providing a container for all
"Bookmark" objects.
2017-06-10 09:57:18 -04:00
Jason Franklin
81a42acb97 Refactor the bookmark query function
The function in "bookmark.vim" that allows the caller to query the list
of Bookmarks by name had stale commentary. In addition, the internals of
the function needed to be reworked to improve readability. Making this
function very clean is important because it is heavily used elsewhere.

As a side note, it might be beneficial to later rename this function to
something like "GetBookmarkByName" to further improve readability. That
change is not critical and can be safely delayed.
2017-06-10 09:28:14 -04:00
Phil Runninger (mac)
a9ab90198b Update CHANGELOG, giving contributors their due. 2017-06-05 09:00:31 -04:00
Phil Runninger
84c681989d Merge pull request #699 from asnr/add-keymaps-to-docs
Update docs with already existing mapping variables
2017-06-04 08:43:13 -04:00
asnr
3a7293d450 Update docs with already existing mapping variables 2017-06-04 19:11:46 +10:00
Phil Runninger
c11affabb4 Merge pull request #696 from lifecrisis/issue361
BUGFIX: Broken "g:NERDTreeBookmarksSort" setting fixed.
2017-05-26 14:27:14 -04:00
Jason Franklin
2a7a375729 Remove code duplication from sorting bookmarks
It makes the most sense to sort the global bookmarks list just before
rendering them in the NERDTree window. Since Vim's sort function is fast
and stable, and since users are very unlikely to have a number of
bookmarks that is too large, we can sort before rendering without
concern for the negligible performance penalty.

This has two benefits:
  1. Users can change their sort settings and have them take effect
     on the next render or refresh.
  2. As mentioned, code duplication is avoided.
2017-05-26 13:46:09 -04:00
Jason Franklin
0b65089122 Reimplement the bookmark comparison method
Sorting the list of user bookmarks requires care to ensure that Vim's
builtin sort function is called correctly. Previously, this function was
called incorrectly. This is why the sorting of bookmarks never worked.

The offending functions have been removed here and replaced with
"s:Bookmark.CompareBookmarksByName". To understand the necessity for
this change, read ":h sort()" for the requirements of the function
reference argument (esp., note that it must return -1, 0, or 1).

In addition to fixing this problem, the new comparison function will
inspect the "g:NERDTreeBookmarksSort" setting to determine whether
case-sensitivity is preferred in the sort. The documentation has been
modified to accurately reflect this adjustment. The change is also made
in such a way as not to break any existing configurations.

Fixes #361 ("My bookmarks aren't sorted").
2017-05-26 13:23:05 -04:00
Jason Franklin
5aec5ecfef Rename the class method for sorting bookmarks
A more intention-revealing name was chosen for the script-local sorting
function. The function comment was also rewritten.
2017-05-26 08:48:38 -04:00
Jason Franklin
519436ad20 Apply consistent spacing before fold markers
The trailing fold markers in "bookmark.vim" varied in how far they were
from the end of the line. This created an unpleasant visual effect when
folding was in use.
2017-05-26 08:27:14 -04:00
Phil Runninger
66e00e61a2 Merge pull request #695 from scrooloose/revert-626-win32unix
Revert "Determine if we're running in Cygwin on Windows."
2017-05-23 07:16:53 -04:00
Phil Runninger
d99967cadd Revert "Determine if we're running in Cygwin on Windows." 2017-05-23 07:15:35 -04:00
Phil Runninger
0b84d458d6 Merge pull request #648 from cntoplolicon/master
correct NERDTreeIgnore pattern in doc
2017-05-20 03:26:05 -04:00
Phil Runninger
fce10d1b10 Merge pull request #626 from scrooloose/win32unix
Determine if we're running in Cygwin on Windows.
2017-05-20 03:25:38 -04:00
Phil Runninger
925627536e Merge pull request #574 from sooth-sayer/master
Remove empty segments
2017-05-20 03:07:36 -04:00
Phil Runninger
23ba97d263 Merge pull request #691 from wincent/patch-1
Update stale comments
2017-05-18 12:33:11 -04:00
Greg Hurrell
0c0bde3106 Update stale comments
@lifecrisis pointed out this stale comment here:

https://github.com/scrooloose/nerdtree/pull/578#issuecomment-302392831

Closes: #640
2017-05-18 07:02:02 -07:00
Jason Cheatham
0caa466854 Use relative path with globpath
Wildignore rules that involve directories aren't handled properly (or at
least as one might expect) when globpath uses absolute paths. For
example, when wildignore contains `src/*.js`, `globpath("src", "*")`
works as expected, while `globpath("/home/user/project/src", "*")`
doesn't.
2017-04-19 10:17:45 -04:00
Phil Runninger
45f4d61f04 Merge pull request #578 from wincent/eventignore
Suppress autocmds less aggressively
2017-04-12 09:50:28 -04:00
Phil Runninger (mac)
97d2d70f6c Add an Issue template to ask for more information up front. 2017-03-29 11:27:04 -04:00
Phil Runninger
649d31384c Merge pull request #676 from josephfrazier/patch-1
Fix headers in readme
2017-03-27 09:39:22 -04:00
Joseph Frazier
bf193320f8 Fix headers in readme 2017-03-26 14:51:09 -04:00
Martin Grenfell
e671e403dd don't touch @o and @h registers when rendering
This just isn't needed, and leaves traces as it turns out:
http://stackoverflow.com/questions/42455953/ho-automatically-writes-vim-registers

Thanks @romainl
2017-02-25 15:23:12 +00:00
Phil Runninger
281701021c Merge pull request #649 from alegen/master
fix bug with files and directories that have dollar sign in name
2017-01-02 08:34:15 -05:00
Alex Geana
9c73a19f56 fix bug with files and directories that have dollar sign in name 2016-12-29 23:22:48 +01:00
cntoplolicon
dee152d08f correct NERDTreeIgnore pattern in doc 2016-12-23 17:51:36 +08:00
Martin Grenfell
eee431dbd4 really fix the previous buffer issue when closing a tree win
So :bprev was failing to jump back to the right buffer. I dont fully
understand this yet, but I'm fairly sure this is because there is a
magic <directory> buffer that we delete when creating a wintree :-/

Anyway, we are explicitly storing the prev buffer again - and updating
it when reusing treewins. It's worky, but there may be a superior way...
2016-10-21 14:48:05 +01:00
Martin Grenfell
48df6bfd6e Revert "remove NERDTree.previousBuf() and related code"
This reverts commit 2027ae03db.
2016-10-21 14:40:18 +01:00
Martin Grenfell
513bf64555 update changelog 2016-10-19 14:11:40 +01:00
Martin Grenfell
2027ae03db remove NERDTree.previousBuf() and related code
We were using this when closing a wintree - to go to the previous
buffer. Not sure why we weren't just using `:bprev` ...
2016-10-19 13:28:44 +01:00
Phil Runninger
4477078170 Unlet! the nt variable before letting it.
Some will have a "NERDTree" buffer variable and others will not. In the
ones that do, getbufvar will return a dictionary. getbufvar will return
an empty string from the other buffers. When looping through the buffers,
let will throw an error if nt already exists and is a different type than
what is trying to be put into it. This easily can be illustrated by these
two statements:

:let x = ""
:let x = {}
E706: Variable type mismatch for: x

This commit gets rid of the variable before setting it so that the
mismatch cannot occur.
2016-10-17 10:30:33 -04:00
Martin Grenfell
84e7a77a7e reuse win trees when editing the same dir again
If you do

```
:edit some/dir/
```

then do the same thing at a later point, then the same nerdtree buffer
will be loaded/shown the second time.
2016-10-14 16:34:08 +01:00
Phil Runninger
334fb0e687 Update CHANGELOG 2016-10-13 16:10:27 -04:00
Phil Runninger
25ec8b47c6 Merge pull request #630 from Leeiio/patch-1
Update NERDTreeOpenable and NERDTreeClosable color
2016-10-13 15:33:05 -04:00
瓜牛
32186f1660 Update NERDTreeOpenable and NERDTreeClosable color
It is more comfortable
2016-10-13 13:38:36 +08:00
Phil Runninger
b9b53d814b Update CHANGELOG 2016-10-10 15:18:14 -04:00
Phil Runninger
10ac799808 Update README.markdown
Adjusted the wording of one of the tips, and added a sentence about the type of NERDTree window that is displayed. See pull reqest #628.
2016-10-10 15:16:00 -04:00
Phil Runninger
148e8570df Merge pull request #628 from ggicci/master
Add note in README: trick to open NERDTree as a window on startup.
2016-10-10 15:06:53 -04:00
Ggicci
a229d8bb61 Remove a similar tip in README file. 2016-10-11 00:02:29 +08:00
Ggicci
b78fa83373 Fix opening current directory in NERDTree tab. 2016-10-09 20:28:33 +08:00
Ggicci
1c0d9efe6c Update readme, trick to open NERDTree as a tab window. 2016-10-09 15:26:48 +08:00
Ggicci
4cb9762999 Update readme, trick to avoid hiding nerdtree after first file open. 2016-10-09 15:11:27 +08:00
Phil Runninger
a9a5aec9c0 Determine if we're running in Cygwin on Windows. 2016-10-06 17:51:22 -04:00
Phil Runninger
f26eaf8355 Merge pull request #625 from scrooloose/revert-546-master
Revert "changed arrows for NERDTreeDirArrowExpandable and NERDTreeDirArrowCol…"
2016-10-04 17:52:49 -04:00
Phil Runninger
408f7a572c Revert "changed arrows for NERDTreeDirArrowExpandable and NERDTreeDirArrowCol…" 2016-10-04 17:52:12 -04:00
Martin Grenfell
08773e1e74 Merge pull request #623 from dschaub/rename-typo
Fix typo in argument usage in promptToRenameBuffer
2016-10-04 09:50:13 +01:00
Dan Schaub
682a7b64db Fix typo in argument usage in promptToRenameBuffer 2016-10-03 18:04:50 -04:00
Phil Runninger
af64474ebd Update CHANGELOG 2016-09-23 16:08:02 -04:00
Phil Runninger
26b40d162c Update CHANGELOG 2016-09-22 16:56:23 -04:00
Phil Runninger
f640646f2c Change confirmation prompt when deleting non-empty directory. 2016-09-22 16:42:17 -04:00
Phil Runninger
1a6c502f19 Merge pull request #530 from mikeperri/delete-empty-directory
Don't require user to type 'yes' to delete an empty directory
2016-09-22 16:40:25 -04:00
Phil Runninger
5d7bc3b0b8 Merge pull request #533 from devm33/fix_e_on_dir
update api call to open directory tree in window
2016-09-22 15:54:39 -04:00
Phil Runninger
f173f62c9a Merge pull request #546 from gwilk/master
changed arrows for NERDTreeDirArrowExpandable and NERDTreeDirArrowCol…
2016-09-22 15:43:19 -04:00
Phil Runninger
1993700bef Merge pull request #584 from zwhitchcox/patch-1
Save people time
2016-09-22 15:28:14 -04:00
Phil Runninger
a536498601 Merge pull request #593 from therealplato/docs/boot-other-window
[docs] faq: how to start with open nerdtree but main window focused
2016-09-22 15:27:39 -04:00
Phil Runninger
fa57b8128d Merge pull request #595 from zacharyvoase/fix_quote_file_name
Use fnameescape to quote filenames for :badd.
2016-09-22 11:22:21 -04:00
Phil Runninger
4ebd7de207 Update CHANGELOG 2016-09-22 11:19:58 -04:00
Phil Runninger
d34f3a257f Merge pull request #619 from curran/patch-1
Correct broken helptags command in docs.
2016-09-22 11:18:50 -04:00
Phil Runninger
b9ad20c0b1 Update CHANGELOG 2016-09-21 22:36:58 -04:00
Phil Runninger
9ff2096b04 Merge pull request #548 from adityanatraj/master
Issue #537: Fix dir arrows not functioning properly
2016-09-21 22:32:13 -04:00
Curran Kelleher
9aae0be318 Correct broken helptags command in docs. 2016-09-17 15:27:19 +05:30
Phil Runninger
29cf96e45b Update change log. 2016-09-08 01:57:38 -04:00
Phil Runninger
d2f8bb8e8a Merge branch 'juanibiapina-disable-cascade' 2016-09-08 01:21:07 -04:00
Phil Runninger
ac2d3b077a Merge branch 'disable-cascade' of git://github.com/juanibiapina/nerdtree into juanibiapina-disable-cascade 2016-09-08 01:02:17 -04:00
Phil Runninger
4428aba2a2 Replace strchars() with a backward compatible workaround. 2016-08-26 08:59:25 -04:00
Phil Runninger
0b73db9368 Simplify some statements. Don't convert path WinToUnix. 2016-08-26 01:32:04 -04:00
Skyler
7730c8731a Quick syntax issue fix 2016-08-25 18:20:32 -07:00
Skyler Lipthay
b5519197e9 Added support for the copy command for both file and directory nodes on Windows systems 2016-08-25 18:19:38 -07:00
Phil Runninger
40993e9010 Corrected case of :Helptags to :helptags 2016-08-25 08:23:02 -04:00
Zachary Voase
916f6b8f8f Use fnameescape to quote filenames for :badd. 2016-06-30 16:21:13 -07:00
Isaac Rogers
0ef5b6be4f Add FAQ: how to unfocus nerdtree window on start 2016-06-27 19:11:07 -04:00
Mike Perri
d2509d279e Don't require user to type 'yes' to delete an empty directory 2016-06-27 11:28:47 -05:00
Martin Grenfell
2e2b649232 Merge pull request #591 from czak/cascade-close-fix
Fix upward traversal when closing a cascade
2016-06-23 13:37:52 +01:00
Łukasz Adamczak
2924ab2071 Verify we haven't reached root when traversing cascade 2016-06-22 13:59:49 +02:00
Łukasz Adamczak
c99312442b Fix upward traversal when closing a cascade 2016-06-22 13:32:44 +02:00
Martin Grenfell
d280b15ba9 Merge pull request #544 from brookhong/master
Fix #520 E716: Key not present in Dictionary: setShowHidden
2016-06-10 12:40:20 +01:00
Zane Hitchcox
1ac98de88a Update README.markdown 2016-05-23 10:59:07 -05:00
Martin Grenfell
15445be5fb remove unneeded exec
As @mkoskar pointed out at:
https://github.com/scrooloose/nerdtree/pull/576#issuecomment-218470556
2016-05-11 16:28:34 +01:00
Martin Grenfell
5294593b14 Merge pull request #576 from mike-zueff/read-only_files_opening_fix
Read-only files opening fix
2016-05-11 16:02:01 +01:00
Greg Hurrell
35b04fa3df Suppress autocmds less aggressively
This is the counterpart to a PR I just submitted to undotree
(https://github.com/mbbill/undotree/pull/61).

I noticed that my statusline doesn't update properly when using NERDTree to move
between revisions of a file with `go` or `gi`
(https://github.com/wincent/wincent/issues/16). I established that this was
because it was using `'eventignore'` to suppress all autocmds, which in turn
prevents the statusline from updating.

Commenting out the `set eventignore=all` line makes the failure to update go
away, at the cost of firing more autocmds.

I considered adding an option for opting out of this behavior (eg. `let
g:NERDTreeEventignore=0` or something), or rearchitecting my statusline to use
an approach like vim-airline does based on CursorMoved autocmds (see
https://github.com/vim-airline/vim-airline/issues/82; see also
30f078daf5/plugin/airline.vim (L36-L50)
for current implementation), but then realized that a simpler fix is to have
NERDTree just disable only the autocmds that it uses instead of disabling all of
them.

This is probably not enough to unbreak every bit of code in the world that
depends on those autocmds, but it does at least unbreak my use case, because it
allows my `WinLeave` autocmd to run and update the statusline.
2016-05-05 09:35:16 -07:00
Mike Zueff
5458680265 Fixed read-only files opening. 2016-04-30 04:08:18 +03:00
Martin Grenfell
35c859179d update initialization of default value for g:NERDTreeCreatePrefix
Init it with the rest of the option defaults - rather than specify the
default at point of use. For consistency.

See #550.
2016-04-26 09:17:03 +01:00
Martin Grenfell
0cb999c070 Merge pull request #550 from wincent/keepalt
Make window creation command configurable
2016-04-26 09:05:57 +01:00
Martin Grenfell
7954eac006 Merge pull request #556 from acarlson1029/readonly-glyph
Allow user-defined read-only indicator.
2016-04-26 08:58:18 +01:00
Martin Grenfell
2ec9b3dd9d Merge pull request #559 from Noah-Huppert/patch-1
Added horizontal rules to FAQ section in readme
2016-04-26 08:57:04 +01:00
d.chernyatiev
1a55a93788 Remove empty segments 2016-04-25 19:05:17 +04:00
Noah Huppert
0e4c270d19 Added horizontal rules to FAQ section in readme 2016-03-05 17:03:23 -05:00
Juan Ibiapina
b2bbed41fa Add option to disable collapsing of diretory names 2016-03-05 14:20:04 -03:00
Juan Ibiapina
88946e9832 Rewrite getCascade recursively 2016-03-05 13:59:27 -03:00
Juan Ibiapina
7f6c608a35 Remove extra whitespace at the end of the line 2016-03-05 13:35:41 -03:00
Alex Carlson
dfb9111786 Allow user-defined RO indicator.
(inspired by overwriting g:NERDTreeDirArrowCollapsible/Expandable)

Replace instances of the RO string with a variable that the user can
override. Useful for custom unicode glyphs, i.e. Font Awesome.

* Initialize variable g:NERDTreeGlyphReadOnly = "RO".
   -> plugin/NERD_tree.vim
* Replace instances of 'RO' with g:NERDTreeGlyphReadOnly
2016-02-26 17:57:40 -08:00
Greg Hurrell
9843fd3686 Make window creation command configurable
This commit adds a `NERDTreeCreatePrefix` setting that can be used to
prefix the `:edit` command that is used to create the NERDTree tree
window. Defaults to "silent", meaning that out of the box the window
will be created with "silent edit".

Users may wish to configure this to produce other effects. For example,
`NERDTreeCreatePrefix` can be set to "silent keepalt keepjumps" in order
to make NERDTree create its window with "silent keepalt keepjumps edit".

This can be used to create an effect analogous to the `g:netrw_altfile`
setting in netrw. An example of why you might want to do this is
described here:

    https://github.com/tpope/vim-vinegar/issues/25

I'm not using vim-vinegar myself, but I am using something like it here:

    https://github.com/wincent/wincent/blob/3efaa8fa50895/roles/dotfiles/files/.vim/plugin/mappings.vim#L60

And having `NERDTreeCreatePrefix` enables me to map "-" to show the
current file in context, and `^-6` to jump back to it.
2016-02-09 00:17:46 -08:00
Aditya Natraj
68dce4f994 Issue #537: Fix dir arrows not functioning properly
added characters that are special when within character
classes in a regular expression to the `escape(...)` call
when building `s:dirArrows`.

this does not fix when `' '` or `''` are your `dirArrows` and you
can't open up subdirs. i think that's an issue with how nerdtree
distinguishes things to traverse in the filetree.
2016-02-06 18:11:52 -05:00
Grzegorz Wilk
28560e2e1b changed arrows for NERDTreeDirArrowExpandable and NERDTreeDirArrowCollapsible 2016-02-04 11:24:45 +01:00
brook hong
e2bbedff09 Fix #520 E716: Key not present in Dictionary: setShowHidden 2016-02-02 22:31:17 +08:00
Maxim Bublis
6251ab1e63 Add support for natural sorting order. 2016-01-19 00:21:13 -08:00
Devraj Mehta
afe99a46d8 update api call to open directory tree in window 2016-01-17 18:51:36 -05:00
Martin Grenfell
4ebbb533c3 silence bookmark errors on startup
Just disable the warning for now. The bookmark system will be replaced
with the project system soon - so no sense putting much effort into
this.

Closes #168
2015-12-02 21:17:22 +00:00
Martin Grenfell
2f8a72144f silence an ls! call 2015-11-27 10:14:45 +00:00
Martin Grenfell
bbb819d696 bugfix for win trees when using "stay in current win" command variants
Previously maps like T would not restore the cursor position. Not sure
why the code was like this in the first place... hopefully I haven't
just broken a bunch of shit.

Closes #146.
2015-11-26 19:52:40 +00:00
Martin Grenfell
0544ff524c handle tab tree buffers being :bdeleted
Closes #375
2015-11-26 19:14:51 +00:00
Martin Grenfell
73ded483a0 update FAQ about opening nerdtree automatically on startup
Closes #494
2015-11-26 18:57:58 +00:00
Martin Grenfell
fddac60afb fix a bug that occurs when opening window trees
Closes #507
2015-11-26 09:31:55 +00:00
Martin Grenfell
c800aa27e2 fix a bug with C mapping
Closes #512
2015-11-26 09:27:44 +00:00
Martin Grenfell
a2b06bbac3 remove references to NERDTreeDirArrows
Closes #515
2015-11-26 00:25:06 +00:00
Martin Grenfell
4f9e981a60 update changelog 2015-11-25 23:52:30 +00:00
Martin Grenfell
677a83b2b6 remove NERDTreeDirArrows option
Use +/~ for windows - which seems to not have the arrow chars in its
default font. TBH I don't really understand this.

Inprove the UI indent matching so that it should handle any combo of
open/close symbol lengths e.g. the fancy arrows are 3 bytes each,
whereas +/~ are 1 byte each.
2015-11-25 23:29:00 +00:00
Martin Grenfell
fb15cfbf45 fix flag rendering for cascading dirs
Use the innermost dirs flags only. Previously each dirs flags were
rendered inline i.e.

    [x]dir1/[y]dir2/[z]dir3/

This looked bad and broke the UI. Now we only render the flags for dir3
- and render them on the left side of the cascade.

Not sure if this is ultimately the right decision - but will do for now.
2015-11-25 22:12:52 +00:00
Martin Grenfell
af39458989 rework the cascading slightly to correctly show open/closed dir arrows 2015-11-24 22:06:04 +00:00
Martin Grenfell
2cef8bb602 make cascading dirs more compact
Render cascading dirs on one line i.e.

    > foo/bar/baz
      file1

instead of

    > foo
      > bar
        > baz
          > file1

This should be useful things like java projects that have deep dir
structures.

Remove the old UI view (pre the dir arrows) as this simply isnt worth
supporting for a proof of concept. This may get added back - or not.
2015-11-24 20:59:35 +00:00
Martin Grenfell
ee4d42cfed encapsulate dep on g:NERDTreeMinimalUI in a function 2015-11-22 14:02:56 +00:00
Martin Grenfell
dd754c7bc6 add path.isAncestor 2015-11-20 19:16:07 +00:00
Martin Grenfell
9eb0004278 fix a syntax issue for older versions of vim
closes #508
2015-11-20 19:15:51 +00:00
Martin Grenfell
7c6795c5a2 fix a typo 2015-11-20 16:45:05 +00:00
Martin Grenfell
a60bd34a33 add NERDTree.getroot()
Eventually 'root' will become a "private" instance var '_root'
2015-11-20 16:16:12 +00:00
Martin Grenfell
c4f8681b77 add NERDTree.getRoot() and NERDTree.ForCurrentTab() 2015-11-20 01:52:38 +00:00
Martin Grenfell
665f326577 remove dependency on b:NERDTree from classes that dont need it
Inject it where needed.
2015-11-20 01:44:12 +00:00
Martin Grenfell
a0de028688 wipeout "stale" nerdtree bufs
When :NERDTree is called several times and &hidden is set, stale
nerdtree bufs will exist. Wipe them out.
2015-11-19 23:44:39 +00:00
Martin Grenfell
cedb40b4f5 move TreeFileNode.makeRoot() to NERDTree.changeRoot(node) 2015-11-16 13:17:59 +00:00
Martin Grenfell
71ee64fed7 add TreeDirNode.getDirChildren() - using this in a plugin 2015-11-16 11:30:16 +00:00
Martin Grenfell
bf217c75f9 fix a couple of var references in UI 2015-11-16 11:29:54 +00:00
Martin Grenfell
d36b793656 dont use b:NERDTreeRoot internally, but leave the var there for compat
Use b:NERDTree.root instead. I will eventually remove  b:NERDTreeRoot
altogether - but this will break some other plugins so leave it for now.
2015-11-16 11:28:24 +00:00
Martin Grenfell
0b966aa23a refactor TreeDirNode.reveal slightly 2015-11-16 09:35:31 +00:00
Martin Grenfell
449f2c77ed update changelog 2015-11-15 11:13:28 +00:00
Martin Grenfell
b4fa33c39c remove some confusing redundancy from a few function calls 2015-11-15 01:04:03 +00:00
Martin Grenfell
83d108894e move a bunch of b:NERDTree.* vars into the b:NERDTree.ui obj 2015-11-15 00:45:57 +00:00
Martin Grenfell
4d8a0c90cb move b:NERDTreePreviousBuf into NERDTree class 2015-11-14 13:10:08 +00:00
Martin Grenfell
5c20274761 move b:NERDTreeType into the NERDTree class and add some query methods 2015-11-14 12:01:55 +00:00
Martin Grenfell
848857d18b rename "primary" and "secondary" trees to "tab" and "window" trees
This is much more accurate and descriptive.
2015-11-14 11:50:01 +00:00
33 changed files with 4791 additions and 3511 deletions

45
.github/ISSUE_TEMPLATE/bug.md vendored Normal file
View File

@@ -0,0 +1,45 @@
---
name: "Bug Report"
about: "NERDTree is misbehaving? Tell us about it."
labels: bug
---
<!-- Attention! Please Read!
Please fill out ALL the information below so that the issue can be fully
understood. Omitting information will delay the resolution of your issue. It
will be labeled "Needs More Info", and may be closed until there is enough
information.
Keep in mind that others may have the same question in the future. The better
your information, the more likely they'll be able to help themselves. -->
#### Self-Diagnosis
<!-- Check the boxes after creating the issue, or use [x]. -->
- [ ] I have searched the [issues](https://github.com/scrooloose/nerdtree/issues) for an answer to my question.
- [ ] I have reviewed the NERDTree documentation. `:h NERDTree`
- [ ] I have reviewed the [Wiki](https://github.com/scrooloose/nerdtree/wiki).
- [ ] I have searched the web for an answer to my question.
#### Environment (for bug reports)
- [ ] Operating System:
- [ ] Vim/Neovim version `:echo v:version`:
- [ ] NERDTree version, found on 1st line in NERDTree quickhelp `?`:
- [ ] vimrc settings
- [ ] NERDTree variables
```vim
```
- Other NERDTree-dependent Plugins
- [ ] jistr/vim-nerdtree-tabs
- [ ] ryanoasis/vim-devicons
- [ ] tiagofumo/vim-nerdtree-syntax-highlight
- [ ] Xuyuanp/nerdtree-git-plugin
- [ ] Others (specify):
- [ ] I've verified the issue occurs with only NERDTree installed.
#### Steps to Reproduce the Issue
1.
#### Current Result (Include screenshots where appropriate.)
#### Expected Result

View File

@@ -0,0 +1,8 @@
---
name: "Feature Request"
about: "What new feature are you requesting for NERDTree?"
labels: "feature request"
---
#### Description

24
.github/ISSUE_TEMPLATE/question.md vendored Normal file
View File

@@ -0,0 +1,24 @@
---
name: "General Question"
about: "Having trouble setting up NERDTree? Need clarification on a setting? Ask your question here."
labels: "general question"
---
<!-- Attention! Please Read!
Please fill out ALL the information below so that the issue can be fully
understood. Omitting information will delay the resolution of your issue. It
will be labeled "Needs More Info", and may be closed until there is enough
information.
Keep in mind that others may have the same question in the future. The better
your information, the more likely they'll be able to help themselves. -->
#### Self-Diagnosis
<!-- Check the boxes after creating the issue, or use [x]. -->
- [ ] I have searched the [issues](https://github.com/scrooloose/nerdtree/issues) for an answer to my question.
- [ ] I have reviewed the NERDTree documentation. `:h NERDTree`
- [ ] I have reviewed the [Wiki](https://github.com/scrooloose/nerdtree/wiki).
- [ ] I have searched the web for an answer to my question.
#### State Your Question

16
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,16 @@
### Description of Changes
Closes # <!-- Issue number this PR addresses. If none, remove this line. -->
---
### New Version Info
#### Author's Instructions
- [ ] Derive a new `MAJOR.MINOR.PATCH` version number. Increment the:
- `MAJOR` version when you make incompatible API changes
- `MINOR` version when you add functionality in a backwards-compatible manner
- `PATCH` version when you make backwards-compatible bug fixes
- [ ] Update [CHANGELOG.md](https://github.com/scrooloose/nerdtree/blob/master/CHANGELOG.md), following the established pattern.
#### Collaborator's Instructions
- [ ] Review [CHANGELOG.md](https://github.com/scrooloose/nerdtree/blob/master/CHANGELOG.md), suggesting a different version number if necessary.
- [ ] After merge, tag the merge commit, e.g. `git tag -a 3.1.4 -m "v3.1.4" && git push origin --tags`

15
.github/workflows/vint.yml vendored Normal file
View File

@@ -0,0 +1,15 @@
name: Vint
on: [push, pull_request]
jobs:
vint:
strategy:
fail-fast: false
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@master
- name: Run vint with reviewdog
uses: reviewdog/action-vint@v1.0.1
with:
github_token: ${{ secrets.github_token }}
reporter: github-pr-review

5
.vintrc.yaml Normal file
View File

@@ -0,0 +1,5 @@
cmdargs:
severity: style_problem
color: true
env:
neovim: false

145
CHANGELOG
View File

@@ -1,145 +0,0 @@
5.0.0
- Refactor the code significantly:
* Break the classes out into their own files.
* Make the majority of the code OO - previously large parts were
effectively a tangle of "global" methods.
- Add an API to assign flags to nodes. This allows VCS plugins like
https://github.com/Xuyuanp/nerdtree-git-plugin to exist. Thanks to
Xuyuanp for helping design/test/build said API.
- add 'scope' argument to the key map API see :help NERDTreeAddKeyMap()
- add magic [[dir]] and [[file]] flags to NERDTreeIgnore
- add support for custom path filters. See :help NERDTreeAddPathFilter()
- add path listener API. See :help NERDTreePathListenerAPI.
- expand the fs menu functionality to list file properties (PhilRunninger,
apbarrero, JESii)
- make bookmarks work with `~` home shortcuts (hiberabyss)
- show OSX specific fsmenu options in regular vim on mac (evindor)
- make dir arrow icons configurable (PickRelated)
- optimise node sorting performance when opening large dirs (vtsang)
- make the root note render prettier by truncating it at a path slash (gcmt)
- remove NERDChristmasTree option - its always christmas now
- add "cascade" open and closing for dirs containing only another single
dir. See :help NERDTreeCascadeOpenSingleChildDir (pendulm)
Many other fixes, doc updates and contributions from:
actionshrimp
SchDen
egalpin
cperl82 - many small fixes
toiffel
WoLpH
handcraftedbits
devmanhinton
xiaodili
zhangoose
gastropoda
mixvin
alvan
lucascaton
kelaban
shanesmith
staeff
pendulm
stephenprater
franksort
agrussellknives
AndrewRadev
Twinside
4.2.0
- Add NERDTreeDirArrows option to make the UI use pretty arrow chars
instead of the old +~| chars to define the tree structure (sickill)
- shift the syntax highlighting out into its own syntax file (gnap)
- add some mac specific options to the filesystem menu - for macvim
only (andersonfreitas)
- Add NERDTreeMinimalUI option to remove some non functional parts of the
nerdtree ui (camthompson)
- tweak the behaviour of :NERDTreeFind - see :help :NERDTreeFind for the
new behaviour (benjamingeiger)
- if no name is given to :Bookmark, make it default to the name of the
target file/dir (minyoung)
- use 'file' completion when doing copying, create, and move
operations (EvanDotPro)
- lots of misc bug fixes (paddyoloughlin, sdewald, camthompson, Vitaly
Bogdanov, AndrewRadev, mathias, scottstvnsn, kml, wycats, me RAWR!)
4.1.0
features:
- NERDTreeFind to reveal the node for the current buffer in the tree,
see |NERDTreeFind|. This effectively merges the FindInNERDTree plugin (by
Doug McInnes) into the script.
- make NERDTreeQuitOnOpen apply to the t/T keymaps too. Thanks to Stefan
Ritter and Rémi Prévost.
- truncate the root node if wider than the tree window. Thanks to Victor
Gonzalez.
bugfixes:
- really fix window state restoring
- fix some win32 path escaping issues. Thanks to Stephan Baumeister, Ricky,
jfilip1024, and Chris Chambers
4.0.0
- add a new programmable menu system (see :help NERDTreeMenu).
- add new APIs to add menus/menu-items to the menu system as well as
custom key mappings to the NERD tree buffer (see :help NERDTreeAPI).
- removed the old API functions
- added a mapping to maximize/restore the size of nerd tree window, thanks
to Guillaume Duranceau for the patch. See :help NERDTree-A for details.
- fix a bug where secondary nerd trees (netrw hijacked trees) and
NERDTreeQuitOnOpen didnt play nicely, thanks to Curtis Harvey.
- fix a bug where the script ignored directories whose name ended in a dot,
thanks to Aggelos Orfanakos for the patch.
- fix a bug when using the x mapping on the tree root, thanks to Bryan
Venteicher for the patch.
- fix a bug where the cursor position/window size of the nerd tree buffer
wasnt being stored on closing the window, thanks to Richard Hart.
- fix a bug where NERDTreeMirror would mirror the wrong tree
3.1.1
- fix a bug where a non-listed no-name buffer was getting created every
time the tree windows was created, thanks to Derek Wyatt and owen1
- make <CR> behave the same as the 'o' mapping
- some helptag fixes in the doc, thanks strull
- fix a bug when using :set nohidden and opening a file where the previous
buf was modified. Thanks iElectric
- other minor fixes
3.1.0
New features:
- add mappings to open files in a vsplit, see :help NERDTree-s and :help
NERDTree-gs
- make the statusline for the nerd tree window default to something
hopefully more useful. See :help 'NERDTreeStatusline'
Bugfixes:
- make the hijack netrw functionality work when vim is started with "vim
<some dir>" (thanks to Alf Mikula for the patch).
- fix a bug where the CWD wasnt being changed for some operations even when
NERDTreeChDirMode==2 (thanks to Lucas S. Buchala)
- add -bar to all the nerd tree :commands so they can chain with other
:commands (thanks to tpope)
- fix bugs when ignorecase was set (thanks to nach)
- fix a bug with the relative path code (thanks to nach)
- fix a bug where doing a :cd would cause :NERDTreeToggle to fail (thanks nach)
3.0.1
Bugfixes:
- fix bugs with :NERDTreeToggle and :NERDTreeMirror when 'hidden
was not set
- fix a bug where :NERDTree <path> would fail if <path> was relative and
didnt start with a ./ or ../ Thanks to James Kanze.
- make the q mapping work with secondary (:e <dir> style) trees,
thanks to jamessan
- fix a bunch of small bugs with secondary trees
More insane refactoring.
3.0.0
- hijack netrw so that doing an :edit <directory> will put a NERD tree in
the window rather than a netrw browser. See :help 'NERDTreeHijackNetrw'
- allow sharing of trees across tabs, see :help :NERDTreeMirror
- remove "top" and "bottom" as valid settings for NERDTreeWinPos
- change the '<tab>' mapping to 'i'
- change the 'H' mapping to 'I'
- lots of refactoring

251
CHANGELOG.md Normal file
View File

@@ -0,0 +1,251 @@
# NERDTree Change Log
<!--
Introduce a new MAJOR.MINOR version with a 4-hash header.
PATCH versions are listed from newest to oldest under their respective MAJOR.MINOR version
in an unordered list. The format is:
- **.PATCH**: Pull Request Title (PR Author) [PR Number](Link to PR)
-->
#### 6.4
- **.3**: Fix regex that finds keyword for minimal menu. (PhilRunninger) [#1075](https://github.com/preservim/nerdtree/pull/1075)
- **.2**: Lint vimscript, fix errors and warnings, add CI job to review PRs (Caleb Maclennan) [#1071](https://github.com/preservim/nerdtree/pull/1071)
- **.1**: Ensure backward compatibility. v:t_func is not available before Vim 8.0 (Phil Runninger)
- **.0**: Allow use of function references as callbacks (HiPhish) [#1067](https://github.com/preservim/nerdtree/pull/1067)
#### 6.3
- **.0**: Add new command that behaves like NERDTreeToggle but defaults to the root of a VCS repository. (willfindlay) [#1060](https://github.com/preservim/nerdtree/pull/1060)
#### 6.2
- **.1**: Menu option, 'copy path to clipboard' is aware of VIM clipboard option (jhzn) [#1056](https://github.com/preservim/nerdtree/pull/1056)
- **.0**: Support tab-specific CWDs (PhilRunninger) [#1032](https://github.com/preservim/nerdtree/pull/1032)
#### 6.1
- **.4**: Add VIM built-in package management to read me file. (pesarkhobeee) [#1049](https://github.com/preservim/nerdtree/pull/1049)
- **.3**: Save/Set screen state also on WinLeave and WinEnter. (PhilRunninger) [#1048](https://github.com/preservim/nerdtree/pull/1048)
- **.2**: Wrap saveScreenState's statements in a try-catch block. (PhilRunninger) [#1047](https://github.com/preservim/nerdtree/pull/1047)
- **.1**: Catch errors when trying to read CHANGELOG.md. (PhilRunninger) [#1045](https://github.com/preservim/nerdtree/pull/1045)
- **.0**: If file path doesn't exist, :NERDTreeFind its parent directory instead. (PhilRunninger) [#1043](https://github.com/preservim/nerdtree/pull/1043)
#### 6.0
- **.1**: Reintroduce necessary variable mistakenly removed. (PhilRunninger) [#1040](https://github.com/preservim/nerdtree/pull/1040)
- **.0**: Make the behavior of window splits consistent (dragonxlwang, PhilRunninger) [#1035](https://github.com/preservim/nerdtree/pull/1035)
#### 5.3
- **.3**: Fix (p)ath not displaying in the minimal menu (tuzz) [#1038](https://github.com/preservim/nerdtree/pull/1038)
- **.2**: Enable events when closing NerdTree window. (PhilRunninger) [#1037](https://github.com/preservim/nerdtree/pull/1037)
- **.1**: Fix the `e` key mapping to use netrw if desired (PhilRunninger) [#1031](https://github.com/preservim/nerdtree/pull/1031)
- **.0**: Add file extension and size to sorting capabilities (PhilRunninger) [#1029](https://github.com/preservim/nerdtree/pull/1029)
#### 5.2
- **.9**: Suppress events for intermediate window/tab/buffer changes (PhilRunninger) [#1026](https://github.com/preservim/nerdtree/pull/1026)
- **.8**: Revert [#1019](https://github.com/preservim/nerdtree/pull/1019) to fix nvim artifacts and flickering. (PhilRunninger) [#1021](https://github.com/preservim/nerdtree/pull/1021)
- **.7**: Use :mode only in neovim. MacVim still needs to use :redraw! (PhilRunninger) [#1019](https://github.com/preservim/nerdtree/pull/1019)
- **.6**: In CHANGELOG.md and PR template, make reference to PR a true HTML link. (PhilRunninger) [#1017](https://github.com/preservim/nerdtree/pull/1017)
- **.5**: Use `:mode` instead of `:redraw!` when updating menu. (PhilRunninger) [#1016](https://github.com/preservim/nerdtree/pull/1016)
- **.4**: When searching for root line num, stop at end of file. (PhilRunninger) [#1015](https://github.com/preservim/nerdtree/pull/1015)
- **.3**: Fix `<CR>` key map on the bookmark (lkebin) [#1014](https://github.com/preservim/nerdtree/pull/1014)
- **.2**: Make Enter work on the `.. ( up a dir )` line (PhilRunninger) [#1013](https://github.com/preservim/nerdtree/pull/1013)
- **.1**: Fix nerdtree#version() on Windows. (PhilRunninger)
- **.0**: Expand functionality of `<CR>` mapping. (PhilRunninger) [#1011](https://github.com/preservim/nerdtree/pull/1011)
#### 5.1
- **.3**: Remove @mentions from PR template and change log. They weren't working. (PhilRunninger) [#1009](https://github.com/preservim/nerdtree/pull/1009)
- **.2**: Fix NERDTree opening with the wrong size. (PhilRunninger) [#1008](https://github.com/preservim/nerdtree/pull/1008)
- **.1**: Update Changelog and create PR Template (PhilRunninger) [#1007](https://github.com/preservim/nerdtree/pull/1007)
- **.0**: Too many changes for one patch...
- Refresh a dir_node if the file wasn't found in it, and look once more. (PhilRunninger) [#1005](https://github.com/preservim/nerdtree/pull/1005)
- Add a "copy path to clipboard" menu option (PhilRunninger) [#1002](https://github.com/preservim/nerdtree/pull/1002)
- Enable root refresh on "vim ." a different way than [#999](https://github.com/preservim/nerdtree/pull/999). (PhilRunninger) [#1001](https://github.com/preservim/nerdtree/pull/1001)
- Fix refreshroot (PhilRunninger) [#999](https://github.com/preservim/nerdtree/pull/999)
- Change version check to look for 703 not 730 (vhalis) [#994](https://github.com/preservim/nerdtree/pull/994)
- Change minimum vim (PhilRunninger) [#991](https://github.com/preservim/nerdtree/pull/991)
- Allow multi-character DirArrows (PhilRunninger) [#985](https://github.com/preservim/nerdtree/pull/985)
- Remove redraw! while still clearing last message empty string. (PhilRunninger) [#979](https://github.com/preservim/nerdtree/pull/979)
- fix `_initChildren` function value set to numChildrenCached error (terryding77) [#969](https://github.com/preservim/nerdtree/pull/969)
- On Windows, do a case-insensitive comparison of paths. (PhilRunninger) [#967](https://github.com/preservim/nerdtree/pull/967)
- Remove the **Please wait... DONE** messages. (PhilRunninger) [#966](https://github.com/preservim/nerdtree/pull/966)
- Smarter delimiter default (PhilRunninger) [#963](https://github.com/preservim/nerdtree/pull/963)
- Update directory .vimdc readme example (spencerdcarlson) [#961](https://github.com/preservim/nerdtree/pull/961)
- Preview bookmarks (PhilRunninger) [#956](https://github.com/preservim/nerdtree/pull/956)
- Add new value to NERDTreeQuitOnOpen to close bookmark table (PhilRunninger) [#955](https://github.com/preservim/nerdtree/pull/955)
- Add an :EditBookmarks command to edit the bookmarks file (PhilRunninger) [#954](https://github.com/preservim/nerdtree/pull/954)
- Before copying, turn off &shellslash. Restore after copy is finished. (PhilRunninger) [#952](https://github.com/preservim/nerdtree/pull/952)
- Set a maximum window size when zooming. (PhilRunninger) [#950](https://github.com/preservim/nerdtree/pull/950)
- Confirm the wipeout of a unsaved buffer whose file has been renamed. (PhilRunninger) [#949](https://github.com/preservim/nerdtree/pull/949)
- Escape a backslash so it can be used in a key mapping. (PhilRunninger) [#948](https://github.com/preservim/nerdtree/pull/948)
- Add a NERDTreeMinimalMenu feature (tuzz) [#938](https://github.com/preservim/nerdtree/pull/938)
- fixed root path error for windows (zcodes) [#935](https://github.com/preservim/nerdtree/pull/935)
- Restore getDirChildren for use in nerdtree-project-plugin. (PhilRunninger) [#929](https://github.com/preservim/nerdtree/pull/929)
- Document NERDTreeNodeDelimiter [#912](https://github.com/preservim/nerdtree/pull/912) (PhilRunninger) [#926](https://github.com/preservim/nerdtree/pull/926)
- Allow modification of menu keybindings (Leandros) [#923](https://github.com/preservim/nerdtree/pull/923)
- Add two more disqualifications for isCascadable(). (PhilRunninger) [#914](https://github.com/preservim/nerdtree/pull/914)
- Allow highlighting more than one flag. (kristijanhusak) [#908](https://github.com/preservim/nerdtree/pull/908)
- Support sorting files and directories by modification time. (PhilRunninger) [#901](https://github.com/preservim/nerdtree/pull/901)
- Parse . and .. from path string with trailing slash. (PhilRunninger) [#899](https://github.com/preservim/nerdtree/pull/899)
- Force sort to recalculate the cached sortKey. (PhilRunninger) [#898](https://github.com/preservim/nerdtree/pull/898)
- Add NERDTreeRefreshRoot command (wgfm) [#897](https://github.com/preservim/nerdtree/pull/897)
- Call Resolve on the file's path when calling :NERDTreeFind. (PhilRunninger) [#896](https://github.com/preservim/nerdtree/pull/896)
- Catch all errors, not just NERDTree errors. (PhilRunninger) [#894](https://github.com/preservim/nerdtree/pull/894)
- Fix typo in help file (lvoisin) [#892](https://github.com/preservim/nerdtree/pull/892)
- Make NERDTreeCreator set the `'nolist'` option (lifecrisis) [#889](https://github.com/preservim/nerdtree/pull/889)
- Refresh buffers after `m`, `m` operation on a folder (PhilRunninger) [#888](https://github.com/preservim/nerdtree/pull/888)
- Use a better arg for FINDSTR when using the m,l command in Windows. (PhilRunninger) [#887](https://github.com/preservim/nerdtree/pull/887)
- Fix the <C-J>/<C-K> motions, which currently fail with cascades (lifecrisis) [#886](https://github.com/preservim/nerdtree/pull/886)
- Function "s:UI.getLineNum()" doesn't always work on cascades. (lifecrisis) [#882](https://github.com/preservim/nerdtree/pull/882)
- NERDTreeCWD: reset CWD if changed by NERDTreeFocus (PhilRunninger) [#878](https://github.com/preservim/nerdtree/pull/878)
- Use <count>tabnext instead of <count>gt to allow users to remap gt. (PhilRunninger) [#877](https://github.com/preservim/nerdtree/pull/877)
- Do a case sensitive comparison of new/existing buffers. (PhilRunninger) [#875](https://github.com/preservim/nerdtree/pull/875)
- Fix opening sub-directories that have commas in their name. (PhilRunninger) [#873](https://github.com/preservim/nerdtree/pull/873)
- Add new command to open NERDTree in the root of a VCS repository. (PhilRunninger) [#872](https://github.com/preservim/nerdtree/pull/872)
- Make sure the path to the bookmarks file exists before writing it. (PhilRunninger) [#871](https://github.com/preservim/nerdtree/pull/871)
- Unzoom NERDTree when opening a file (PhilRunninger) [#870](https://github.com/preservim/nerdtree/pull/870)
- Support unusual characters in file and directory names (PhilRunninger) [#868](https://github.com/preservim/nerdtree/pull/868)
- Reword renamed-buffer prompt to be more clear (aflock) [#867](https://github.com/preservim/nerdtree/pull/867)
- Default to placing cursor on root when closing bookmark table (lifecrisis) [#866](https://github.com/preservim/nerdtree/pull/866)
- Fix issues with sorting of nodes (PhilRunninger) [#856](https://github.com/preservim/nerdtree/pull/856)
- Better OSX detection (bubba-h57) [#853](https://github.com/preservim/nerdtree/pull/853)
- Bugfix - ensure keymaps dictionary exists before using it (mnussbaum) [#852](https://github.com/preservim/nerdtree/pull/852)
- Decrease startup-time by avoiding linear-time iteration over key mappings (mnussbaum) [#851](https://github.com/preservim/nerdtree/pull/851)
- Add code to sort mappings in quickhelp (lifecrisis) [#849](https://github.com/preservim/nerdtree/pull/849)
- Use ":clearjumps" in new NERDTree windows (lifecrisis) [#844](https://github.com/preservim/nerdtree/pull/844)
- Like m-c did before, create parent directories if needed on m-m. (PhilRunninger) [#840](https://github.com/preservim/nerdtree/pull/840)
- BUGFIX: Repair a problem with the `'u'` mapping. (lifecrisis) [#838](https://github.com/preservim/nerdtree/pull/838)
- Make the NERDTree buffer writable when rendering it. (PhilRunninger) [#837](https://github.com/preservim/nerdtree/pull/837)
- Code cleanup: Remove unsupported bookmark table mappings (lifecrisis) [#835](https://github.com/preservim/nerdtree/pull/835)
- Replace strcharpart() with substitute() for backward compatibility (bravestarr) [#834](https://github.com/preservim/nerdtree/pull/834)
- Fixed error `unknown function strcharpart` for older versions of Vim (hav4ik) [#833](https://github.com/preservim/nerdtree/pull/833)
- Clear output when NERDTree menu is aborted (lifecrisis) [#832](https://github.com/preservim/nerdtree/pull/832)
- Display a path with multi-byte characters correctly when it is truncated (bravestarr) [#830](https://github.com/preservim/nerdtree/pull/830)
- Support revealing file and executing file with xdg-open for Linux (ngnmhieu) [#824](https://github.com/preservim/nerdtree/pull/824)
- If node isn't open, count children on disk before deleting. (PhilRunninger) [#822](https://github.com/preservim/nerdtree/pull/822)
- Add new variable g:NERDTreeRemoveFileCmd (kutsan) [#816](https://github.com/preservim/nerdtree/pull/816)
- Use a better check for existence of the NERDTree buffer. (PhilRunninger) [#814](https://github.com/preservim/nerdtree/pull/814)
- Fix focussing previous buffer when closing NERDTree (mrubli) [#801](https://github.com/preservim/nerdtree/pull/801)
- Update the docs for "NERDTreeStatusline" (lifecrisis) [#796](https://github.com/preservim/nerdtree/pull/796)
- BUGFIX: Unstable behavior in the "getPath()" method (lifecrisis) [#795](https://github.com/preservim/nerdtree/pull/795)
- Revert the bugfix from pull request [#785](https://github.com/preservim/nerdtree/pull/785) (lifecrisis) [#794](https://github.com/preservim/nerdtree/pull/794)
- BUGFIX: Allow ":NERDTreeFind" to discover hidden files (lifecrisis) [#786](https://github.com/preservim/nerdtree/pull/786)
- BUGFIX: Allow ":NERDTreeFind" to reveal new files (lifecrisis) [#785](https://github.com/preservim/nerdtree/pull/785)
- Add modelines (lifecrisis) [#782](https://github.com/preservim/nerdtree/pull/782)
- Change the type of completion used by NERDTreeFind (lifecrisis) [#781](https://github.com/preservim/nerdtree/pull/781)
- change NERDTreeFind with args (zhenyangze) [#778](https://github.com/preservim/nerdtree/pull/778)
- Style Choice: Using confirm() when deleting a bookmark (lifecrisis) [#777](https://github.com/preservim/nerdtree/pull/777)
- remove useless substitute when `file =~# "/$"` (skyblueee) [#773](https://github.com/preservim/nerdtree/pull/773)
- remove useless removeLeadingSpaces in _stripMarkup (skyblueee) [#772](https://github.com/preservim/nerdtree/pull/772)
- Make the "o" mapping consistent with "x" (lifecrisis) [#769](https://github.com/preservim/nerdtree/pull/769)
- Fix a problem with the "x" handler (lifecrisis) [#768](https://github.com/preservim/nerdtree/pull/768)
- Clean up the handler for the "x" mapping (lifecrisis) [#767](https://github.com/preservim/nerdtree/pull/767)
- Revert change to tab opening method (lifecrisis) [#766](https://github.com/preservim/nerdtree/pull/766)
- BUGFIX: Add back support for "b:NERDTreeRoot" (lifecrisis) [#765](https://github.com/preservim/nerdtree/pull/765)
- Fix broken "t" and "T" mappings, tabs now open at end (lifecrisis) [#759](https://github.com/preservim/nerdtree/pull/759)
- Update doc with already existing mapping variables (asnr) [#699](https://github.com/preservim/nerdtree/pull/699)
- Fix the broken g:NERDTreeBookmarksSort setting (lifecrisis) [#696](https://github.com/preservim/nerdtree/pull/696)
- Correct NERDTreeIgnore pattern in doc (cntoplolicon) [#648](https://github.com/preservim/nerdtree/pull/648)
- Remove empty segments when splitting path (sooth-sayer) [#574](https://github.com/preservim/nerdtree/pull/574)
- Suppress autocmds less agressively (wincent) [#578](https://github.com/preservim/nerdtree/pull/578) [#691](https://github.com/preservim/nerdtree/pull/691)
- Add an Issues template to ask for more info initially.
- Fix markdown headers in readme (josephfrazier) [#676](https://github.com/preservim/nerdtree/pull/676)
- Don't touch `@o` and `@h` registers when rendering
- Fix bug with files and directories with dollar signs (alegen) [#649](https://github.com/preservim/nerdtree/pull/649)
- Reuse/reopen existing window trees where possible [#244](https://github.com/preservim/nerdtree/pull/244)
- Remove NERDTree.previousBuf()
- Change color of arrow (Leeiio) [#630](https://github.com/preservim/nerdtree/pull/630)
- Improved a tip in README.markdown (ggicci) [#628](https://github.com/preservim/nerdtree/pull/628)
- Shorten delete confimration of empty directory to `y` (mikeperri) [#530](https://github.com/preservim/nerdtree/pull/530)
- Fix API call to open directory tree in window (devm33) [#533](https://github.com/preservim/nerdtree/pull/533)
- Change default arrows on non-Windows platforms (gwilk) [#546](https://github.com/preservim/nerdtree/pull/546)
- Update to README - combine cd and git clone (zwhitchcox) [#584](https://github.com/preservim/nerdtree/pull/584)
- Update to README - Tip: start NERDTree when vim starts (therealplato) [#593](https://github.com/preservim/nerdtree/pull/593)
- Escape filename when moving an open buffer (zacharyvoase) [#595](https://github.com/preservim/nerdtree/pull/595)
- Fixed incorrect :helptags command in README (curran) [#619](https://github.com/preservim/nerdtree/pull/619)
- Fixed incomplete escaping of folder arrows (adityanatraj) [#548](https://github.com/preservim/nerdtree/pull/548)
- Added NERDTreeCascadeSingleChildDir option (juanibiapina) [#558](https://github.com/preservim/nerdtree/pull/558)
- Replace strchars() with backward compatible workaround.
- Add support for copy command in Windows (SkylerLipthay) [#231](https://github.com/preservim/nerdtree/pull/231)
- Fixed typo in README.markdown - :Helptags -> :helptags
- Rename "primary" and "secondary" trees to "tab" and "window" trees.
- Move a bunch of buffer level variables into the NERDTree and UI classes.
- Display cascading dirs on one line to save vertical/horizontal space (matt-gardner: brainstorming/testing)
- Remove the old style UI - Remove `NERDTreeDirArrows` option.
- On windows default to + and ~ for expand/collapse directory symbols.
- Lots more refactoring. Move a bunch of b: level vars into b:NERDTree and friends.
#### 5.0.0
- Refactor the code significantly:
* Break the classes out into their own files.
* Make the majority of the code OO - previously large parts were effectively a tangle of "global" methods.
- Add an API to assign flags to nodes. This allows VCS plugins like https://github.com/Xuyuanp/nerdtree-git-plugin to exist. Thanks to **Xuyuanp** for helping design/test/build said API.
- add `scope` argument to the key map API see :help NERDTreeAddKeyMap()
- add magic [[dir]] and [[file]] flags to NERDTreeIgnore
- add support for custom path filters. See :help NERDTreeAddPathFilter()
- add path listener API. See :help NERDTreePathListenerAPI.
- expand the fs menu functionality to list file properties (PhilRunninger, apbarrero, JESii)
- make bookmarks work with `~` home shortcuts (hiberabyss)
- show OSX specific fsmenu options in regular vim on mac (evindor)
- make dir arrow icons configurable (PickRelated)
- optimise node sorting performance when opening large dirs (vtsang)
- make the root note render prettier by truncating it at a path slash (gcmt)
- remove NERDChristmasTree option - its always christmas now
- add "cascade" open and closing for dirs containing only another single dir. See :help NERDTreeCascadeOpenSingleChildDir (pendulm)
- Many other fixes, doc updates and contributions from: **actionshrimp**, **agrussellknives**, **alvan**, **AndrewRadev**, **cperl82** (*many small fixes*), **devmanhinton**, **egalpin**, **franksort**, **gastropoda**, **handcraftedbits**, **kelaban**, **lucascaton**, **mixvin**, **pendulm**, **SchDen**, **shanesmith**, **staeff**, **stephenprater**, **toiffel**, **Twinside**, **WoLpH**, **xiaodili**, **zhangoose**
#### 4.2.0
- Add NERDTreeDirArrows option to make the UI use pretty arrow chars instead of the old +~| chars to define the tree structure (sickill)
- shift the syntax highlighting out into its own syntax file (gnap)
- add some mac specific options to the filesystem menu - for macvim only (andersonfreitas)
- Add NERDTreeMinimalUI option to remove some non functional parts of the nerdtree ui (camthompson)
- tweak the behaviour of :NERDTreeFind - see :help :NERDTreeFind for the new behaviour (benjamingeiger)
- if no name is given to :Bookmark, make it default to the name of the target file/dir (minyoung)
- use `file` completion when doing copying, create, and move operations (EvanDotPro)
- lots of misc bug fixes from: **AndrewRadev**, **Bogdanov**, **camthompson**, **kml**, **mathias**, **paddyoloughlin**, **scottstvnsn**, **sdewald**, **Vitaly**, **wycats**, me RAWR!
#### 4.1.0
- features:
- NERDTreeFind to reveal the node for the current buffer in the tree, see `|NERDTreeFind|`. This effectively merges the FindInNERDTree plugin (by **Doug McInnes**) into the script.
- make NERDTreeQuitOnOpen apply to the t/T keymaps too. Thanks to **Stefan Ritter** and **Rémi Prévost**.
- truncate the root node if wider than the tree window. Thanks to **Victor Gonzalez**.
- bugfixes:
- really fix window state restoring
- fix some win32 path escaping issues. Thanks to **Stephan Baumeister**, **Ricky**, **jfilip1024**, and **Chris Chambers**.
#### 4.0.0
- add a new programmable menu system (see `:help NERDTreeMenu`).
- add new APIs to add menus/menu-items to the menu system as well as custom key mappings to the NERD tree buffer (see `:help NERDTreeAPI`).
- removed the old API functions
- added a mapping to maximize/restore the size of nerd tree window, thanks to Guillaume Duranceau for the patch. See :help NERDTree-A for details.
- fix a bug where secondary nerd trees (netrw hijacked trees) and NERDTreeQuitOnOpen didnt play nicely, thanks to **Curtis Harvey**.
- fix a bug where the script ignored directories whose name ended in a dot, thanks to **Aggelos Orfanakos** for the patch.
- fix a bug when using the x mapping on the tree root, thanks to **Bryan Venteicher** for the patch.
- fix a bug where the cursor position/window size of the nerd tree buffer wasnt being stored on closing the window, thanks to **Richard Hart**.
- fix a bug where NERDTreeMirror would mirror the wrong tree
#### 3.1.1
- fix a bug where a non-listed no-name buffer was getting created every time the tree windows was created, thanks to **Derek Wyatt** and **owen1**
- make `<CR>` behave the same as the `o` mapping
- some helptag fixes in the doc, thanks **strull**.
- fix a bug when using `:set nohidden` and opening a file where the previous buf was modified. Thanks **iElectric**.
- other minor fixes
#### 3.1.0
- New features:
- add mappings to open files in a vsplit, see `:help NERDTree-s` and `:help NERDTree-gs`
- make the statusline for the nerd tree window default to something hopefully more useful. See `:help 'NERDTreeStatusline'`
- Bugfixes:
- make the hijack netrw functionality work when vim is started with `vim <some dir>` (thanks to **Alf Mikula** for the patch).
- fix a bug where the CWD wasnt being changed for some operations even when NERDTreeChDirMode==2 (thanks to **Lucas S. Buchala**)
- add -bar to all the nerd tree :commands so they can chain with other :commands (thanks to **tpope**)
- fix bugs when ignorecase was set (thanks to **nach**)
- fix a bug with the relative path code (thanks to **nach**)
- fix a bug where doing a `:cd` would cause `:NERDTreeToggle` to fail (thanks **nach**)
#### 3.0.1
- Bugfixes:
- fix bugs with :NERDTreeToggle and :NERDTreeMirror when `'hidden'` was not set
- fix a bug where `:NERDTree <path>` would fail if `<path>` was relative and didnt start with a `./` or `../` Thanks to **James Kanze**.
- make the `q` mapping work with secondary (`:e <dir>` style) trees, thanks to **jamessan**
- fix a bunch of small bugs with secondary trees
- More insane refactoring.
#### 3.0.0
- hijack netrw so that doing an `:edit <directory>` will put a NERD tree in the window rather than a netrw browser. See :help 'NERDTreeHijackNetrw'
- allow sharing of trees across tabs, see `:help :NERDTreeMirror`
- remove "top" and "bottom" as valid settings for NERDTreeWinPos
- change the `'<tab>'` mapping to `'i'`
- change the `'H'` mapping to `'I'`
- lots of refactoring

View File

@@ -1,83 +1,78 @@
The NERD Tree
The NERDTree [![Vint](https://github.com/preservim/nerdtree/workflows/Vint/badge.svg)](https://github.com/preservim/nerdtree/actions?workflow=Vint)
=============
Intro
-----
Introduction
------------
The NERD tree allows you to explore your filesystem and to open files and
directories. It presents the filesystem to you in the form of a tree which you
manipulate with the keyboard and/or mouse. It also allows you to perform
simple filesystem operations.
The NERDTree is a file system explorer for the Vim editor. Using this plugin,
users can visually browse complex directory hierarchies, quickly open files for
reading or editing, and perform basic file system operations.
The following features and functionality are provided by the NERD tree:
This plugin can also be extended with custom mappings using a special API. The
details of this API and of other NERDTree features are described in the
included documentation.
* Files and directories are displayed in a hierarchical tree structure
* Different highlighting is provided for the following types of nodes:
* files
* directories
* sym-links
* windows .lnk files
* read-only files
* executable files
* Many (customisable) mappings are provided to manipulate the tree:
* Mappings to open/close/explore directory nodes
* Mappings to open files in new/existing windows/tabs
* Mappings to change the current root of the tree
* Mappings to navigate around the tree
* ...
* Directories and files can be bookmarked.
* Most NERD tree navigation can also be done with the mouse
* Filtering of tree content (can be toggled at runtime)
* custom file filters to prevent e.g. vim backup files being displayed
* optional displaying of hidden files (. files)
* files can be "turned off" so that only directories are displayed
* The position and size of the NERD tree window can be customised
* The order in which the nodes in the tree are listed can be customised.
* A model of your filesystem is created/maintained as you explore it. This
has several advantages:
* All filesystem information is cached and is only re-read on demand
* If you revisit a part of the tree that you left earlier in your
session, the directory nodes will be opened/closed as you left them
* The script remembers the cursor position and window position in the NERD
tree so you can toggle it off (or just close the tree window) and then
reopen it (with NERDTreeToggle) the NERD tree window will appear exactly
as you left it
* You can have a separate NERD tree for each tab, share trees across tabs,
or a mix of both.
* By default the script overrides the default file browser (netrw), so if
you :edit a directory a (slightly modified) NERD tree will appear in the
current window
* A programmable menu system is provided (simulates right clicking on a node)
* one default menu plugin is provided to perform basic filesystem
operations (create/delete/move/copy files/directories)
* There's an API for adding your own keymappings
![NERDTree Screenshot](https://github.com/preservim/nerdtree/raw/master/screenshot.png)
Installation
------------
####[pathogen.vim](https://github.com/tpope/vim-pathogen)
Below are just some of the methods for installing NERDTree. Do not follow all of these instructions; just pick your favorite one. Other plugin managers exist, and NERDTree should install just fine with any of them.
cd ~/.vim/bundle
git clone https://github.com/scrooloose/nerdtree.git
#### Vim 8+ packages
Then reload vim, run `:Helptags`, and check out `:help NERD_tree.txt`.
If you are using VIM version 8 or higher you can use its built-in package management; see `:help packages` for more information. Just run these commands in your terminal:
```bash
git clone https://github.com/preservim/nerdtree.git ~/.vim/pack/vendor/start/nerdtree
vim -u NONE -c "helptags ~/.vim/pack/vendor/start/nerdtree/doc" -c q
```
####[apt-vim](https://github.com/egalpin/apt-vim)
Otherwise, these are some of the several 3rd-party plugin managers you can choose from. Be sure you read the instructions for your chosen plugin, as there typically are additional steps you nee d to take.
apt-vim install -y https://github.com/scrooloose/nerdtree.git
#### [pathogen.vim](https://github.com/tpope/vim-pathogen)
In the terminal,
```bash
git clone https://github.com/preservim/nerdtree.git ~/.vim/bundle/nerdtree
```
In your vimrc,
```vim
call pathogen#infect()
syntax on
filetype plugin indent on
```
Then reload vim, run `:helptags ~/.vim/bundle/nerdtree/doc/` or `:Helptags`.
Faq
---
#### [Vundle.vim](https://github.com/VundleVim/Vundle.vim)
```vim
call vundle#begin()
Plugin 'preservim/nerdtree'
call vundle#end()
```
> Is there any support for `git` flags?
#### [vim-plug](https://github.com/junegunn/vim-plug)
```vim
call plug#begin()
Plug 'preservim/nerdtree'
call plug#end()
```
#### [apt-vim](https://github.com/egalpin/apt-vim)
```bash
apt-vim install -y https://github.com/preservim/nerdtree.git
```
F.A.Q. (here, and in the [Wiki](https://github.com/preservim/nerdtree/wiki))
------
#### Is there any support for `git` flags?
Yes, install [nerdtree-git-plugin](https://github.com/Xuyuanp/nerdtree-git-plugin).
> Can I have the nerdtree on every tab automatically?
---
#### Can I have the nerdtree on every tab automatically?
Nope. If this is something you want then chances are you aren't using tabs and
buffers as they were intended to be used. Read this
@@ -85,37 +80,66 @@ http://stackoverflow.com/questions/102384/using-vims-tabs-like-buffers
If you are interested in this behaviour then consider [vim-nerdtree-tabs](https://github.com/jistr/vim-nerdtree-tabs)
> How can I open a NERDTree automatically when vim starts up?
---
#### How can I open a NERDTree automatically when vim starts up?
Stick this in your vimrc: `autocmd vimenter * NERDTree`
> How can I open a NERDTree automatically when vim starts up if no files were specified?
Stick this in your vimrc
autocmd StdinReadPre * let s:std_in=1
autocmd VimEnter * if argc() == 0 && !exists("s:std_in") | NERDTree | endif
> How can I map a specific key or shortcut to open NERDTree?
Stick this in your vimrc to open NERDTree with `Ctrl+n` (you can set whatever key you want):
map <C-n> :NERDTreeToggle<CR>
> How can I close vim if the only window left open is a NERDTree?
---
#### How can I open a NERDTree automatically when vim starts up if no files were specified?
Stick this in your vimrc:
```vim
autocmd StdinReadPre * let s:std_in=1
autocmd VimEnter * if argc() == 0 && !exists("s:std_in") | NERDTree | endif
```
autocmd bufenter * if (winnr("$") == 1 && exists("b:NERDTreeType") && b:NERDTreeType == "primary") | q | endif
Note: Now start vim with plain `vim`, not `vim .`
> Can I have different highlighting for different file extensions?
---
#### What if I'm also opening a saved session, for example `vim -S session_file.vim`? I don't want NERDTree to open in that scenario.
```vim
autocmd StdinReadPre * let s:std_in=1
autocmd VimEnter * if argc() == 0 && !exists("s:std_in") && v:this_session == "" | NERDTree | endif
```
See here: https://github.com/scrooloose/nerdtree/issues/433#issuecomment-92590696
---
#### How can I open NERDTree automatically when vim starts up on opening a directory?
```vim
autocmd StdinReadPre * let s:std_in=1
autocmd VimEnter * if argc() == 1 && isdirectory(argv()[0]) && !exists("s:std_in") | exe 'NERDTree' argv()[0] | wincmd p | ene | exe 'cd '.argv()[0] | endif
```
> How can I change default arrows?
This window is tab-specific, meaning it's used by all windows in the tab. This trick also prevents NERDTree from hiding when first selecting a file.
Note: Executing `vim ~/some-directory` will open NERDTree and a new edit window. `exe 'cd '.argv()[0]` sets the `pwd` of the new edit window to `~/some-directory`
---
#### How can I map a specific key or shortcut to open NERDTree?
Stick this in your vimrc to open NERDTree with `Ctrl+n` (you can set whatever key you want):
```vim
map <C-n> :NERDTreeToggle<CR>
```
---
#### How can I close vim if the only window left open is a NERDTree?
Stick this in your vimrc:
```vim
autocmd bufenter * if (winnr("$") == 1 && exists("b:NERDTree") && b:NERDTree.isTabTree()) | q | endif
```
---
#### Can I have different highlighting for different file extensions?
See here: https://github.com/preservim/nerdtree/issues/433#issuecomment-92590696
---
#### How can I change default arrows?
Use these variables in your vimrc. Note that below are default arrow symbols
let g:NERDTreeDirArrows = 1
let g:NERDTreeDirArrowExpandable = '▸'
let g:NERDTreeDirArrowCollapsible = '▾'
```vim
let g:NERDTreeDirArrowExpandable = '▸'
let g:NERDTreeDirArrowCollapsible = '▾'
```

1
_config.yml Normal file
View File

@@ -0,0 +1 @@
theme: jekyll-theme-cayman

View File

@@ -1,44 +1,146 @@
if exists("g:loaded_nerdtree_autoload")
if exists('g:loaded_nerdtree_autoload')
finish
endif
let g:loaded_nerdtree_autoload = 1
function! nerdtree#version()
return '5.0.0'
let s:rootNERDTreePath = resolve(expand('<sfile>:p:h:h'))
"FUNCTION: nerdtree#version(...) {{{1
" If any value is given as an argument, the entire line of text from the
" change log is shown for the current version; otherwise, only the version
" number is shown.
function! nerdtree#version(...) abort
let l:text = 'Unknown'
try
let l:changelog = readfile(join([s:rootNERDTreePath, 'CHANGELOG.md'], nerdtree#slash()))
let l:line = 0
while l:line <= len(l:changelog)
if l:changelog[l:line] =~# '\d\+\.\d\+'
let l:text = substitute(l:changelog[l:line], '.*\(\d\+.\d\+\).*', '\1', '')
let l:text .= substitute(l:changelog[l:line+1], '^.\{-}\(\.\d\+\).\{-}:\(.*\)', a:0>0 ? '\1:\2' : '\1', '')
break
endif
let l:line += 1
endwhile
catch
endtry
return l:text
endfunction
" SECTION: General Functions {{{1
"============================================================
"FUNCTION: nerdtree#checkForBrowse(dir) {{{2
"inits a secondary nerd tree in the current buffer if appropriate
function! nerdtree#checkForBrowse(dir)
if a:dir != '' && isdirectory(a:dir)
call g:NERDTreeCreator.CreateSecondary(a:dir)
"FUNCTION: nerdtree#slash() {{{2
function! nerdtree#slash() abort
if nerdtree#runningWindows()
if exists('+shellslash') && &shellslash
return '/'
endif
return '\'
endif
return '/'
endfunction
"FUNCTION: nerdtree#and(x,y) {{{2
" Implements and() function for Vim <= 7.2
function! nerdtree#and(x,y) abort
if exists('*and')
return and(a:x, a:y)
else
let l:x = a:x
let l:y = a:y
let l:n = 0
let l:result = 0
while l:x > 0 && l:y > 0
if (l:x % 2) && (l:y % 2)
let l:result += float2nr(pow(2, l:n))
endif
let l:x = float2nr(l:x / 2)
let l:y = float2nr(l:y / 2)
let l:n += 1
endwhile
return l:result
endif
endfunction
"FUNCTION: nerdtree#checkForBrowse(dir) {{{2
"inits a window tree in the current buffer if appropriate
function! nerdtree#checkForBrowse(dir) abort
if !isdirectory(a:dir)
return
endif
if s:reuseWin(a:dir)
return
endif
call g:NERDTreeCreator.CreateWindowTree(a:dir)
endfunction
"FUNCTION: s:reuseWin(dir) {{{2
"finds a NERDTree buffer with root of dir, and opens it.
function! s:reuseWin(dir) abort
let path = g:NERDTreePath.New(fnamemodify(a:dir, ':p'))
for i in range(1, bufnr('$'))
unlet! nt
let nt = getbufvar(i, 'NERDTree')
if empty(nt)
continue
endif
if nt.isWinTree() && nt.root.path.equals(path)
call nt.setPreviousBuf(bufnr('#'))
exec 'buffer ' . i
return 1
endif
endfor
return 0
endfunction
" FUNCTION: nerdtree#completeBookmarks(A,L,P) {{{2
" completion function for the bookmark commands
function! nerdtree#completeBookmarks(A,L,P)
function! nerdtree#completeBookmarks(A,L,P) abort
return filter(g:NERDTreeBookmark.BookmarkNames(), 'v:val =~# "^' . a:A . '"')
endfunction
"FUNCTION: nerdtree#compareBookmarks(dir) {{{2
function! nerdtree#compareBookmarks(first, second)
return a:first.compareTo(a:second)
endfunction
"FUNCTION: nerdtree#compareNodes(dir) {{{2
function! nerdtree#compareNodes(n1, n2)
function! nerdtree#compareNodes(n1, n2) abort
return a:n1.path.compareTo(a:n2.path)
endfunction
"FUNCTION: nerdtree#compareNodesBySortKey(n1, n2) {{{2
function! nerdtree#compareNodesBySortKey(n1, n2)
if a:n1.path.getSortKey() <# a:n2.path.getSortKey()
function! nerdtree#compareNodesBySortKey(n1, n2) abort
let sortKey1 = a:n1.path.getSortKey()
let sortKey2 = a:n2.path.getSortKey()
let i = 0
while i < min([len(sortKey1), len(sortKey2)])
" Compare chunks upto common length.
" If chunks have different type, the one which has
" integer type is the lesser.
if type(sortKey1[i]) ==# type(sortKey2[i])
if sortKey1[i] <# sortKey2[i]
return - 1
elseif sortKey1[i] ># sortKey2[i]
return 1
endif
elseif type(sortKey1[i]) ==# v:t_number
return -1
elseif type(sortKey2[i]) ==# v:t_number
return 1
endif
let i = i + 1
endwhile
" Keys are identical upto common length.
" The key which has smaller chunks is the lesser one.
if len(sortKey1) < len(sortKey2)
return -1
elseif a:n1.path.getSortKey() ># a:n2.path.getSortKey()
elseif len(sortKey1) > len(sortKey2)
return 1
else
return 0
@@ -48,7 +150,7 @@ endfunction
" FUNCTION: nerdtree#deprecated(func, [msg]) {{{2
" Issue a deprecation warning for a:func. If a second arg is given, use this
" as the deprecation message
function! nerdtree#deprecated(func, ...)
function! nerdtree#deprecated(func, ...) abort
let msg = a:0 ? a:func . ' ' . a:1 : a:func . ' is deprecated'
if !exists('s:deprecationWarnings')
@@ -60,22 +162,24 @@ function! nerdtree#deprecated(func, ...)
endif
endfunction
" FUNCTION: nerdtree#exec(cmd) {{{2
" same as :exec cmd but eventignore=all is set for the duration
function! nerdtree#exec(cmd)
let old_ei = &ei
set ei=all
" FUNCTION: nerdtree#exec(cmd, ignoreAll) {{{2
" Same as :exec cmd but, if ignoreAll is TRUE, set eventignore=all for the duration
function! nerdtree#exec(cmd, ignoreAll) abort
let old_ei = &eventignore
if a:ignoreAll
set eventignore=all
endif
exec a:cmd
let &ei = old_ei
let &eventignore = old_ei
endfunction
" FUNCTION: nerdtree#has_opt(options, name) {{{2
function! nerdtree#has_opt(options, name)
return has_key(a:options, a:name) && a:options[a:name] == 1
function! nerdtree#has_opt(options, name) abort
return has_key(a:options, a:name) && a:options[a:name] ==# 1
endfunction
" FUNCTION: nerdtree#loadClassFiles() {{{2
function! nerdtree#loadClassFiles()
function! nerdtree#loadClassFiles() abort
runtime lib/nerdtree/path.vim
runtime lib/nerdtree/menu_controller.vim
runtime lib/nerdtree/menu_item.vim
@@ -93,8 +197,8 @@ function! nerdtree#loadClassFiles()
endfunction
" FUNCTION: nerdtree#postSourceActions() {{{2
function! nerdtree#postSourceActions()
call g:NERDTreeBookmark.CacheBookmarks(0)
function! nerdtree#postSourceActions() abort
call g:NERDTreeBookmark.CacheBookmarks(1)
call nerdtree#ui_glue#createDefaultBindings()
"load all nerdtree plugins
@@ -102,8 +206,13 @@ function! nerdtree#postSourceActions()
endfunction
"FUNCTION: nerdtree#runningWindows(dir) {{{2
function! nerdtree#runningWindows()
return has("win16") || has("win32") || has("win64")
function! nerdtree#runningWindows() abort
return has('win16') || has('win32') || has('win64')
endfunction
"FUNCTION: nerdtree#runningCygwin(dir) {{{2
function! nerdtree#runningCygwin() abort
return has('win32unix')
endfunction
" SECTION: View Functions {{{1
@@ -114,16 +223,16 @@ endfunction
"
"Args:
"msg: the message to echo
function! nerdtree#echo(msg)
function! nerdtree#echo(msg) abort
redraw
echomsg "NERDTree: " . a:msg
echomsg empty(a:msg) ? '' : ('NERDTree: ' . a:msg)
endfunction
"FUNCTION: nerdtree#echoError {{{2
"Wrapper for nerdtree#echo, sets the message type to errormsg for this message
"Args:
"msg: the message to echo
function! nerdtree#echoError(msg)
function! nerdtree#echoError(msg) abort
echohl errormsg
call nerdtree#echo(a:msg)
echohl normal
@@ -133,14 +242,14 @@ endfunction
"Wrapper for nerdtree#echo, sets the message type to warningmsg for this message
"Args:
"msg: the message to echo
function! nerdtree#echoWarning(msg)
function! nerdtree#echoWarning(msg) abort
echohl warningmsg
call nerdtree#echo(a:msg)
echohl normal
endfunction
"FUNCTION: nerdtree#renderView {{{2
function! nerdtree#renderView()
function! nerdtree#renderView() abort
call b:NERDTree.render()
endfunction

View File

@@ -1,118 +1,152 @@
if exists("g:loaded_nerdtree_ui_glue_autoload")
if exists('g:loaded_nerdtree_ui_glue_autoload')
finish
endif
let g:loaded_nerdtree_ui_glue_autoload = 1
" FUNCTION: nerdtree#ui_glue#createDefaultBindings() {{{1
function! nerdtree#ui_glue#createDefaultBindings()
function! nerdtree#ui_glue#createDefaultBindings() abort
let s = '<SNR>' . s:SID() . '_'
call NERDTreeAddKeyMap({ 'key': '<MiddleRelease>', 'scope': "all", 'callback': s."handleMiddleMouse" })
call NERDTreeAddKeyMap({ 'key': '<LeftRelease>', 'scope': "all", 'callback': s."handleLeftClick" })
call NERDTreeAddKeyMap({ 'key': '<2-LeftMouse>', 'scope': "DirNode", 'callback': s."activateDirNode" })
call NERDTreeAddKeyMap({ 'key': '<2-LeftMouse>', 'scope': "FileNode", 'callback': s."activateFileNode" })
call NERDTreeAddKeyMap({ 'key': '<2-LeftMouse>', 'scope': "Bookmark", 'callback': s."activateBookmark" })
call NERDTreeAddKeyMap({ 'key': '<2-LeftMouse>', 'scope': "all", 'callback': s."activateAll" })
call NERDTreeAddKeyMap({ 'key': '<MiddleMouse>', 'scope': 'all', 'callback': s . 'handleMiddleMouse' })
call NERDTreeAddKeyMap({ 'key': '<LeftRelease>', 'scope': 'all', 'callback': s.'handleLeftClick' })
call NERDTreeAddKeyMap({ 'key': '<2-LeftMouse>', 'scope': 'DirNode', 'callback': s.'activateDirNode' })
call NERDTreeAddKeyMap({ 'key': '<2-LeftMouse>', 'scope': 'FileNode', 'callback': s.'activateFileNode' })
call NERDTreeAddKeyMap({ 'key': '<2-LeftMouse>', 'scope': 'Bookmark', 'callback': s.'activateBookmark' })
call NERDTreeAddKeyMap({ 'key': '<2-LeftMouse>', 'scope': 'all', 'callback': s.'activateAll' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapCustomOpen, 'scope':'FileNode', 'callback': s.'customOpenFile'})
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapCustomOpen, 'scope':'DirNode', 'callback': s.'customOpenDir'})
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapCustomOpen, 'scope':'Bookmark', 'callback': s.'customOpenBookmark'})
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapCustomOpen, 'scope':'all', 'callback': s.'activateAll' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapActivateNode, 'scope': "DirNode", 'callback': s."activateDirNode" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapActivateNode, 'scope': "FileNode", 'callback': s."activateFileNode" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapActivateNode, 'scope': "Bookmark", 'callback': s."activateBookmark" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapActivateNode, 'scope': "all", 'callback': s."activateAll" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapActivateNode, 'scope': 'DirNode', 'callback': s.'activateDirNode' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapActivateNode, 'scope': 'FileNode', 'callback': s.'activateFileNode' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapActivateNode, 'scope': 'Bookmark', 'callback': s.'activateBookmark' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapPreview, 'scope': 'Bookmark', 'callback': s.'previewBookmark' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapActivateNode, 'scope': 'all', 'callback': s.'activateAll' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenSplit, 'scope': "Node", 'callback': s."openHSplit" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenVSplit, 'scope': "Node", 'callback': s."openVSplit" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenSplit, 'scope': 'Node', 'callback': s.'openHSplit' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenVSplit, 'scope': 'Node', 'callback': s.'openVSplit' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenSplit, 'scope': "Bookmark", 'callback': s."openHSplit" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenVSplit, 'scope': "Bookmark", 'callback': s."openVSplit" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapPreview, 'scope': 'Node', 'callback': s.'previewNodeCurrent' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapPreviewVSplit, 'scope': 'Node', 'callback': s.'previewNodeVSplit' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapPreviewSplit, 'scope': 'Node', 'callback': s.'previewNodeHSplit' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapPreview, 'scope': "Node", 'callback': s."previewNodeCurrent" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapPreviewVSplit, 'scope': "Node", 'callback': s."previewNodeVSplit" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapPreviewSplit, 'scope': "Node", 'callback': s."previewNodeHSplit" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenRecursively, 'scope': 'DirNode', 'callback': s.'openNodeRecursively' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapPreview, 'scope': "Bookmark", 'callback': s."previewNodeCurrent" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapPreviewVSplit, 'scope': "Bookmark", 'callback': s."previewNodeVSplit" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapPreviewSplit, 'scope': "Bookmark", 'callback': s."previewNodeHSplit" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapUpdir, 'scope': 'all', 'callback': s . 'upDirCurrentRootClosed' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapUpdirKeepOpen, 'scope': 'all', 'callback': s . 'upDirCurrentRootOpen' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapChangeRoot, 'scope': 'Node', 'callback': s . 'chRoot' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenRecursively, 'scope': "DirNode", 'callback': s."openNodeRecursively" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapChdir, 'scope': 'Node', 'callback': s.'chCwd' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapUpdir, 'scope': "all", 'callback': s."upDirCurrentRootClosed" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapUpdirKeepOpen, 'scope': "all", 'callback': s."upDirCurrentRootOpen" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapChangeRoot, 'scope': "Node", 'callback': s."chRoot" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapQuit, 'scope': 'all', 'callback': s.'closeTreeWindow' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapChdir, 'scope': "Node", 'callback': s."chCwd" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapCWD, 'scope': 'all', 'callback': 'nerdtree#ui_glue#chRootCwd' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapQuit, 'scope': "all", 'callback': s."closeTreeWindow" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapRefreshRoot, 'scope': 'all', 'callback': s.'refreshRoot' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapRefresh, 'scope': 'Node', 'callback': s.'refreshCurrent' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapCWD, 'scope': "all", 'callback': "nerdtree#ui_glue#chRootCwd" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapHelp, 'scope': 'all', 'callback': s.'displayHelp' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapToggleZoom, 'scope': 'all', 'callback': s.'toggleZoom' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapToggleHidden, 'scope': 'all', 'callback': s.'toggleShowHidden' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapToggleFilters, 'scope': 'all', 'callback': s.'toggleIgnoreFilter' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapToggleFiles, 'scope': 'all', 'callback': s.'toggleShowFiles' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapToggleBookmarks, 'scope': 'all', 'callback': s.'toggleShowBookmarks' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapRefreshRoot, 'scope': "all", 'callback': s."refreshRoot" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapRefresh, 'scope': "Node", 'callback': s."refreshCurrent" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapCloseDir, 'scope': 'Node', 'callback': s.'closeCurrentDir' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapCloseChildren, 'scope': 'DirNode', 'callback': s.'closeChildren' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapHelp, 'scope': "all", 'callback': s."displayHelp" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapToggleZoom, 'scope': "all", 'callback': s."toggleZoom" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapToggleHidden, 'scope': "all", 'callback': s."toggleShowHidden" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapToggleFilters, 'scope': "all", 'callback': s."toggleIgnoreFilter" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapToggleFiles, 'scope': "all", 'callback': s."toggleShowFiles" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapToggleBookmarks, 'scope': "all", 'callback': s."toggleShowBookmarks" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapMenu, 'scope': 'Node', 'callback': s.'showMenu' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapCloseDir, 'scope': "Node", 'callback': s."closeCurrentDir" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapCloseChildren, 'scope': "DirNode", 'callback': s."closeChildren" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpParent, 'scope': 'Node', 'callback': s.'jumpToParent' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpFirstChild, 'scope': 'Node', 'callback': s.'jumpToFirstChild' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpLastChild, 'scope': 'Node', 'callback': s.'jumpToLastChild' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpRoot, 'scope': 'all', 'callback': s.'jumpToRoot' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpNextSibling, 'scope': 'Node', 'callback': s.'jumpToNextSibling' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpPrevSibling, 'scope': 'Node', 'callback': s.'jumpToPrevSibling' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapMenu, 'scope': "Node", 'callback': s."showMenu" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenInTab, 'scope': 'Node', 'callback': s . 'openInNewTab' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenInTabSilent, 'scope': 'Node', 'callback': s . 'openInNewTabSilent' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenInTab, 'scope': 'Bookmark', 'callback': s . 'openInNewTab' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenInTabSilent, 'scope': 'Bookmark', 'callback': s . 'openInNewTabSilent' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpParent, 'scope': "Node", 'callback': s."jumpToParent" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpFirstChild, 'scope': "Node", 'callback': s."jumpToFirstChild" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpLastChild, 'scope': "Node", 'callback': s."jumpToLastChild" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpRoot, 'scope': "all", 'callback': s."jumpToRoot" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpNextSibling, 'scope': "Node", 'callback': s."jumpToNextSibling" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpPrevSibling, 'scope': "Node", 'callback': s."jumpToPrevSibling" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenExpl, 'scope': 'DirNode', 'callback': s.'openExplorer' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenExpl, 'scope': 'FileNode', 'callback': s.'openExplorer' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenInTab, 'scope': "Node", 'callback': s."openInNewTab" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenInTabSilent, 'scope': "Node", 'callback': s."openInNewTabSilent" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenInTab, 'scope': "Bookmark", 'callback': s."openInNewTab" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenInTabSilent, 'scope': "Bookmark", 'callback': s."openInNewTabSilent" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenExpl, 'scope': "DirNode", 'callback': s."openExplorer" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapDeleteBookmark, 'scope': "Bookmark", 'callback': s."deleteBookmark" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapDeleteBookmark, 'scope': 'Bookmark', 'callback': s.'deleteBookmark' })
endfunction
"SECTION: Interface bindings {{{1
"============================================================
"FUNCTION: s:customOpenFile() {{{1
" Open file node with the 'custom' key, initially <CR>.
function! s:customOpenFile(node) abort
call a:node.activate(s:initCustomOpenArgs().file)
endfunction
"FUNCTION: s:customOpenDir() {{{1
" Open directory node with the 'custom' key, initially <CR>.
function! s:customOpenDir(node) abort
call s:activateDirNode(a:node, s:initCustomOpenArgs().dir)
endfunction
"FUNCTION: s:customOpenBookmark() {{{1
" Open bookmark node with the 'custom' key, initially <CR>.
function! s:customOpenBookmark(node) abort
if a:node.path.isDirectory
call a:node.activate(b:NERDTree, s:initCustomOpenArgs().dir)
else
call a:node.activate(b:NERDTree, s:initCustomOpenArgs().file)
endif
endfunction
"FUNCTION: s:initCustomOpenArgs() {{{1
" Make sure NERDTreeCustomOpenArgs has needed keys
function! s:initCustomOpenArgs() abort
let g:NERDTreeCustomOpenArgs = get(g:, 'NERDTreeCustomOpenArgs', {})
return extend(g:NERDTreeCustomOpenArgs, {'file':{'reuse': 'all', 'where': 'p'}, 'dir':{}}, 'keep')
endfunction
"FUNCTION: s:activateAll() {{{1
"handle the user activating the updir line
function! s:activateAll()
if getline(".") ==# g:NERDTreeUI.UpDirLine()
function! s:activateAll() abort
if getline('.') ==# g:NERDTreeUI.UpDirLine()
return nerdtree#ui_glue#upDir(0)
endif
endfunction
"FUNCTION: s:activateDirNode() {{{1
"handle the user activating a tree node
function! s:activateDirNode(node)
call a:node.activate()
" FUNCTION: s:activateDirNode(directoryNode, options) {{{1
" Open a directory with optional options
function! s:activateDirNode(directoryNode, ...) abort
if a:directoryNode.isRoot() && a:directoryNode.isOpen
call nerdtree#echo('cannot close tree root')
return
endif
call a:directoryNode.activate((a:0 > 0) ? a:1 : {})
endfunction
"FUNCTION: s:activateFileNode() {{{1
"handle the user activating a tree node
function! s:activateFileNode(node)
function! s:activateFileNode(node) abort
call a:node.activate({'reuse': 'all', 'where': 'p'})
endfunction
"FUNCTION: s:activateBookmark() {{{1
"FUNCTION: s:activateBookmark(bookmark) {{{1
"handle the user activating a bookmark
function! s:activateBookmark(bm)
call a:bm.activate(!a:bm.path.isDirectory ? {'where': 'p'} : {})
function! s:activateBookmark(bm) abort
call a:bm.activate(b:NERDTree, !a:bm.path.isDirectory ? {'where': 'p'} : {})
endfunction
" FUNCTION: nerdtree#ui_glue#bookmarkNode(name) {{{1
" Associate the current node with the given name
function! nerdtree#ui_glue#bookmarkNode(...)
function! nerdtree#ui_glue#bookmarkNode(...) abort
let currentNode = g:NERDTreeFileNode.GetSelected()
if currentNode != {}
if currentNode !=# {}
let name = a:1
if empty(name)
let name = currentNode.path.getLastPathComponent(0)
@@ -121,50 +155,39 @@ function! nerdtree#ui_glue#bookmarkNode(...)
call currentNode.bookmark(name)
call b:NERDTree.render()
catch /^NERDTree.IllegalBookmarkNameError/
call nerdtree#echo("bookmark names must not contain spaces")
call nerdtree#echo('bookmark names must not contain spaces')
endtry
else
call nerdtree#echo("select a node first")
call nerdtree#echo('select a node first')
endif
endfunction
" FUNCTION: s:chCwd(node) {{{1
function! s:chCwd(node)
function! s:chCwd(node) abort
try
call a:node.path.changeToDir()
catch /^NERDTree.PathChangeError/
call nerdtree#echoWarning("could not change cwd")
call nerdtree#echoWarning('could not change cwd')
endtry
endfunction
" FUNCTION: s:chRoot(node) {{{1
" changes the current root to the selected one
function! s:chRoot(node)
call a:node.makeRoot()
call b:NERDTree.render()
call b:NERDTreeRoot.putCursorHere(0, 0)
function! s:chRoot(node) abort
call b:NERDTree.changeRoot(a:node)
endfunction
" FUNCTION: s:nerdtree#ui_glue#chRootCwd() {{{1
" changes the current root to CWD
function! nerdtree#ui_glue#chRootCwd()
try
let cwd = g:NERDTreePath.New(getcwd())
catch /^NERDTree.InvalidArgumentsError/
call nerdtree#echo("current directory does not exist.")
return
endtry
if cwd.str() == g:NERDTreeFileNode.GetRootForTab().path.str()
return
endif
call s:chRoot(g:NERDTreeDirNode.New(cwd))
" Change the NERDTree root to match the current working directory.
function! nerdtree#ui_glue#chRootCwd() abort
NERDTreeCWD
endfunction
" FUNCTION: nnerdtree#ui_glue#clearBookmarks(bookmarks) {{{1
function! nerdtree#ui_glue#clearBookmarks(bookmarks)
function! nerdtree#ui_glue#clearBookmarks(bookmarks) abort
if a:bookmarks ==# ''
let currentNode = g:NERDTreeFileNode.GetSelected()
if currentNode != {}
if currentNode !=# {}
call currentNode.clearBookmarks()
endif
else
@@ -173,140 +196,152 @@ function! nerdtree#ui_glue#clearBookmarks(bookmarks)
call bookmark.delete()
endfor
endif
call b:NERDTree.root.refresh()
call b:NERDTree.render()
endfunction
" FUNCTION: s:closeChildren(node) {{{1
" closes all childnodes of the current node
function! s:closeChildren(node)
function! s:closeChildren(node) abort
call a:node.closeChildren()
call b:NERDTree.render()
call a:node.putCursorHere(0, 0)
endfunction
" FUNCTION: s:closeCurrentDir(node) {{{1
" closes the parent dir of the current node
function! s:closeCurrentDir(node)
let parent = a:node.parent
if parent ==# {} || parent.isRoot()
call nerdtree#echo("cannot close tree root")
else
while g:NERDTreeCascadeOpenSingleChildDir && !parent.parent.isRoot()
if parent.parent.getVisibleChildCount() == 1
call parent.close()
let parent = parent.parent
else
break
endif
endwhile
call parent.close()
call b:NERDTree.render()
call parent.putCursorHere(0, 0)
" Close the parent directory of the current node.
function! s:closeCurrentDir(node) abort
if a:node.isRoot()
call nerdtree#echo('cannot close parent of tree root')
return
endif
let l:parent = a:node.parent
while l:parent.isCascadable()
let l:parent = l:parent.parent
endwhile
if l:parent.isRoot()
call nerdtree#echo('cannot close tree root')
return
endif
call l:parent.close()
call b:NERDTree.render()
call l:parent.putCursorHere(0, 0)
endfunction
" FUNCTION: s:closeTreeWindow() {{{1
" close the tree window
function! s:closeTreeWindow()
if b:NERDTreeType ==# "secondary" && b:NERDTreePreviousBuf != -1
exec "buffer " . b:NERDTreePreviousBuf
function! s:closeTreeWindow() abort
if b:NERDTree.isWinTree() && b:NERDTree.previousBuf() !=# -1
exec 'buffer ' . b:NERDTree.previousBuf()
else
if winnr("$") > 1
if winnr('$') > 1
call g:NERDTree.Close()
else
call nerdtree#echo("Cannot close last window")
call nerdtree#echo('Cannot close last window')
endif
endif
endfunction
" FUNCTION: s:deleteBookmark(bm) {{{1
" if the cursor is on a bookmark, prompt to delete
function! s:deleteBookmark(bm)
echo "Are you sure you wish to delete the bookmark:\n\"" . a:bm.name . "\" (yN):"
" FUNCTION: s:deleteBookmark(bookmark) {{{1
" Prompt the user to confirm the deletion of the selected bookmark.
function! s:deleteBookmark(bookmark) abort
let l:message = 'Delete the bookmark "' . a:bookmark.name
\ . '" from the bookmark list?'
if nr2char(getchar()) ==# 'y'
try
call a:bm.delete()
call b:NERDTree.render()
redraw
catch /^NERDTree/
call nerdtree#echoWarning("Could not remove bookmark")
endtry
else
call nerdtree#echo("delete aborted" )
let l:choices = "&Yes\n&No"
echo | redraw
let l:selection = confirm(l:message, l:choices, 1, 'Warning')
if l:selection !=# 1
call nerdtree#echo('bookmark not deleted')
return
endif
try
call a:bookmark.delete()
silent call b:NERDTree.root.refresh()
call b:NERDTree.render()
echo | redraw
catch /^NERDTree/
call nerdtree#echoWarning('could not remove bookmark')
endtry
endfunction
" FUNCTION: s:displayHelp() {{{1
" toggles the help display
function! s:displayHelp()
let b:treeShowHelp = b:treeShowHelp ? 0 : 1
function! s:displayHelp() abort
call b:NERDTree.ui.toggleHelp()
call b:NERDTree.render()
call b:NERDTree.ui.centerView()
endfunction
" FUNCTION: s:findAndRevealPath() {{{1
function! s:findAndRevealPath()
" FUNCTION: s:findAndRevealPath(pathStr) {{{1
function! s:findAndRevealPath(pathStr) abort
let l:pathStr = !empty(a:pathStr) ? a:pathStr : expand('%:p')
if !filereadable(l:pathStr)
let l:pathStr = fnamemodify(l:pathStr, ':h')
endif
if empty(l:pathStr)
call nerdtree#echoWarning('no file for the current buffer')
return
endif
try
let p = g:NERDTreePath.New(expand("%:p"))
let l:pathStr = g:NERDTreePath.Resolve(l:pathStr)
let l:pathObj = g:NERDTreePath.New(l:pathStr)
catch /^NERDTree.InvalidArgumentsError/
call nerdtree#echo("no file for the current buffer")
call nerdtree#echoWarning('invalid path')
return
endtry
if p.isUnixHiddenPath()
let showhidden=g:NERDTreeShowHidden
let g:NERDTreeShowHidden = 1
endif
if !g:NERDTree.ExistsForTab()
try
let cwd = g:NERDTreePath.New(getcwd())
let l:cwd = g:NERDTreePath.New(getcwd())
catch /^NERDTree.InvalidArgumentsError/
call nerdtree#echo("current directory does not exist.")
let cwd = p.getParent()
call nerdtree#echo('current directory does not exist.')
let l:cwd = l:pathObj.getParent()
endtry
if p.isUnder(cwd)
call g:NERDTreeCreator.CreatePrimary(cwd.str())
if l:pathObj.isUnder(l:cwd)
call g:NERDTreeCreator.CreateTabTree(l:cwd.str())
else
call g:NERDTreeCreator.CreatePrimary(p.getParent().str())
call g:NERDTreeCreator.CreateTabTree(l:pathObj.getParent().str())
endif
else
if !p.isUnder(g:NERDTreeFileNode.GetRootForTab().path)
if !g:NERDTree.IsOpen()
call g:NERDTreeCreator.TogglePrimary('')
else
call g:NERDTree.CursorToTreeWin()
endif
let b:NERDTreeShowHidden = g:NERDTreeShowHidden
call s:chRoot(g:NERDTreeDirNode.New(p.getParent()))
else
if !g:NERDTree.IsOpen()
call g:NERDTreeCreator.TogglePrimary("")
endif
NERDTreeFocus
if !l:pathObj.isUnder(b:NERDTree.root.path)
call s:chRoot(g:NERDTreeDirNode.New(l:pathObj.getParent(), b:NERDTree))
endif
endif
call g:NERDTree.CursorToTreeWin()
call b:NERDTreeRoot.reveal(p)
if p.isUnixHiddenFile()
let g:NERDTreeShowHidden = showhidden
if l:pathObj.isHiddenUnder(b:NERDTree.root.path)
call b:NERDTree.ui.setShowHidden(1)
endif
let l:node = b:NERDTree.root.reveal(l:pathObj)
call b:NERDTree.render()
call l:node.putCursorHere(1, 0)
endfunction
"FUNCTION: s:handleLeftClick() {{{1
"Checks if the click should open the current node
function! s:handleLeftClick()
function! s:handleLeftClick() abort
let currentNode = g:NERDTreeFileNode.GetSelected()
if currentNode != {}
if currentNode !=# {}
"the dir arrows are multibyte chars, and vim's string functions only
"deal with single bytes - so split the line up with the hack below and
"take the line substring manually
let line = split(getline(line(".")), '\zs')
let startToCur = ""
let line = split(getline(line('.')), '\zs')
let startToCur = ''
for i in range(0,len(line)-1)
let startToCur .= line[i]
endfor
@@ -333,311 +368,327 @@ function! s:handleLeftClick()
endfunction
" FUNCTION: s:handleMiddleMouse() {{{1
function! s:handleMiddleMouse()
let curNode = g:NERDTreeFileNode.GetSelected()
if curNode ==# {}
call nerdtree#echo("Put the cursor on a node first" )
function! s:handleMiddleMouse() abort
" A middle mouse click does not automatically position the cursor as one
" would expect. Forcing the execution of a regular left mouse click here
" fixes this problem.
execute "normal! \<LeftMouse>"
let l:currentNode = g:NERDTreeFileNode.GetSelected()
if empty(l:currentNode)
call nerdtree#echoError('use the pointer to select a node')
return
endif
if curNode.path.isDirectory
call nerdtree#openExplorer(curNode)
if l:currentNode.path.isDirectory
call l:currentNode.openExplorer()
else
call curNode.open({'where': 'h'})
call l:currentNode.open({'where': 'h'})
endif
endfunction
" FUNCTION: s:jumpToChild(direction) {{{2
" Args:
" direction: 0 if going to first child, 1 if going to last
function! s:jumpToChild(currentNode, direction)
if a:currentNode.isRoot()
return nerdtree#echo("cannot jump to " . (a:direction ? "last" : "first") . " child")
end
let dirNode = a:currentNode.parent
let childNodes = dirNode.getVisibleChildren()
let targetNode = childNodes[0]
if a:direction
let targetNode = childNodes[len(childNodes) - 1]
endif
if targetNode.equals(a:currentNode)
let siblingDir = a:currentNode.parent.findOpenDirSiblingWithVisibleChildren(a:direction)
if siblingDir != {}
let indx = a:direction ? siblingDir.getVisibleChildCount()-1 : 0
let targetNode = siblingDir.getChildByIndex(indx, 1)
endif
endif
call targetNode.putCursorHere(1, 0)
call b:NERDTree.ui.centerView()
endfunction
" FUNCTION: nerdtree#ui_glue#invokeKeyMap(key) {{{1
"this is needed since I cant figure out how to invoke dict functions from a
"key map
function! nerdtree#ui_glue#invokeKeyMap(key)
function! nerdtree#ui_glue#invokeKeyMap(key) abort
call g:NERDTreeKeyMap.Invoke(a:key)
endfunction
" FUNCTION: s:jumpToFirstChild() {{{1
" wrapper for the jump to child method
function! s:jumpToFirstChild(node)
" FUNCTION: s:jumpToFirstChild(node) {{{1
function! s:jumpToFirstChild(node) abort
call s:jumpToChild(a:node, 0)
endfunction
" FUNCTION: s:jumpToLastChild() {{{1
" wrapper for the jump to child method
function! s:jumpToLastChild(node)
" FUNCTION: s:jumpToLastChild(node) {{{1
function! s:jumpToLastChild(node) abort
call s:jumpToChild(a:node, 1)
endfunction
" FUNCTION: s:jumpToParent(node) {{{1
" moves the cursor to the parent of the current node
function! s:jumpToParent(node)
if !empty(a:node.parent)
call a:node.parent.putCursorHere(1, 0)
call b:NERDTree.ui.centerView()
else
call nerdtree#echo("cannot jump to parent")
" FUNCTION: s:jumpToChild(node, last) {{{1
" Jump to the first or last child node at the same file system level.
"
" Args:
" node: the node on which the cursor currently sits
" last: 1 (true) if jumping to last child, 0 (false) if jumping to first
function! s:jumpToChild(node, last) abort
let l:node = a:node.path.isDirectory ? a:node.getCascadeRoot() : a:node
if l:node.isRoot()
return
endif
let l:parent = l:node.parent
let l:children = l:parent.getVisibleChildren()
let l:target = a:last ? l:children[len(l:children) - 1] : l:children[0]
call l:target.putCursorHere(1, 0)
call b:NERDTree.ui.centerView()
endfunction
" FUNCTION: s:jumpToParent(node) {{{1
" Move the cursor to the parent of the specified node. For a cascade, move to
" the parent of the cascade's first node. At the root node, do nothing.
function! s:jumpToParent(node) abort
let l:node = a:node.path.isDirectory ? a:node.getCascadeRoot() : a:node
if l:node.isRoot()
return
endif
if empty(l:node.parent)
call nerdtree#echo('could not jump to parent node')
return
endif
call l:node.parent.putCursorHere(1, 0)
call b:NERDTree.ui.centerView()
endfunction
" FUNCTION: s:jumpToRoot() {{{1
" moves the cursor to the root node
function! s:jumpToRoot()
call b:NERDTreeRoot.putCursorHere(1, 0)
function! s:jumpToRoot() abort
call b:NERDTree.root.putCursorHere(1, 0)
call b:NERDTree.ui.centerView()
endfunction
" FUNCTION: s:jumpToNextSibling(node) {{{1
function! s:jumpToNextSibling(node)
function! s:jumpToNextSibling(node) abort
call s:jumpToSibling(a:node, 1)
endfunction
" FUNCTION: s:jumpToPrevSibling(node) {{{1
function! s:jumpToPrevSibling(node)
function! s:jumpToPrevSibling(node) abort
call s:jumpToSibling(a:node, 0)
endfunction
" FUNCTION: s:jumpToSibling(currentNode, forward) {{{2
" moves the cursor to the sibling of the current node in the given direction
" FUNCTION: s:jumpToSibling(node, forward) {{{1
" Move the cursor to the next or previous node at the same file system level.
"
" Args:
" forward: 1 if the cursor should move to the next sibling, 0 if it should
" move back to the previous sibling
function! s:jumpToSibling(currentNode, forward)
let sibling = a:currentNode.findSibling(a:forward)
" node: the node on which the cursor currently sits
" forward: 0 to jump to previous sibling, 1 to jump to next sibling
function! s:jumpToSibling(node, forward) abort
let l:node = a:node.path.isDirectory ? a:node.getCascadeRoot() : a:node
let l:sibling = l:node.findSibling(a:forward)
if !empty(sibling)
call sibling.putCursorHere(1, 0)
call b:NERDTree.ui.centerView()
if empty(l:sibling)
return
endif
call l:sibling.putCursorHere(1, 0)
call b:NERDTree.ui.centerView()
endfunction
" FUNCTION: nerdtree#ui_glue#openBookmark(name) {{{1
" put the cursor on the given bookmark and, if its a file, open it
function! nerdtree#ui_glue#openBookmark(name)
" Open the Bookmark that has the specified name. This function provides the
" implementation for the :OpenBookmark command.
function! nerdtree#ui_glue#openBookmark(name) abort
try
let targetNode = g:NERDTreeBookmark.GetNodeForName(a:name, 0)
call targetNode.putCursorHere(0, 1)
redraw!
catch /^NERDTree.BookmarkedNodeNotFoundError/
call nerdtree#echo("note - target node is not cached")
let bookmark = g:NERDTreeBookmark.BookmarkFor(a:name)
let targetNode = g:NERDTreeFileNode.New(bookmark.path)
let l:bookmark = g:NERDTreeBookmark.BookmarkFor(a:name)
catch /^NERDTree.BookmarkNotFoundError/
call nerdtree#echoError('bookmark "' . a:name . '" not found')
return
endtry
if targetNode.path.isDirectory
call targetNode.openExplorer()
if l:bookmark.path.isDirectory
call l:bookmark.open(b:NERDTree)
else
call targetNode.open({'where': 'p'})
call l:bookmark.open(b:NERDTree, {'where': 'p'})
endif
endfunction
" FUNCTION: s:openHSplit(target) {{{1
function! s:openHSplit(target)
function! s:openHSplit(target) abort
call a:target.activate({'where': 'h'})
endfunction
" FUNCTION: s:openVSplit(target) {{{1
function! s:openVSplit(target)
function! s:openVSplit(target) abort
call a:target.activate({'where': 'v'})
endfunction
" FUNCTION: s:openExplorer(node) {{{1
function! s:openExplorer(node)
function! s:openExplorer(node) abort
call a:node.openExplorer()
endfunction
" FUNCTION: s:openInNewTab(target) {{{1
function! s:openInNewTab(target)
call a:target.activate({'where': 't'})
function! s:openInNewTab(target) abort
let l:opener = g:NERDTreeOpener.New(a:target.path, {'where': 't'})
call l:opener.open(a:target)
endfunction
" FUNCTION: s:openInNewTabSilent(target) {{{1
function! s:openInNewTabSilent(target)
call a:target.activate({'where': 't', 'stay': 1})
function! s:openInNewTabSilent(target) abort
let l:opener = g:NERDTreeOpener.New(a:target.path, {'where': 't', 'stay': 1})
call l:opener.open(a:target)
endfunction
" FUNCTION: s:openNodeRecursively(node) {{{1
function! s:openNodeRecursively(node)
call nerdtree#echo("Recursively opening node. Please wait...")
function! s:openNodeRecursively(node) abort
call nerdtree#echo('Recursively opening node. Please wait...')
call a:node.openRecursively()
call b:NERDTree.render()
redraw
call nerdtree#echo("Recursively opening node. Please wait... DONE")
call nerdtree#echo('')
endfunction
" FUNCTION: s:previewBookmark(bookmark) {{{1
function! s:previewBookmark(bookmark) abort
if a:bookmark.path.isDirectory
execute 'NERDTreeFind '.a:bookmark.path.str()
else
call a:bookmark.activate(b:NERDTree, {'stay': 1, 'where': 'p', 'keepopen': 1})
endif
endfunction
"FUNCTION: s:previewNodeCurrent(node) {{{1
function! s:previewNodeCurrent(node)
function! s:previewNodeCurrent(node) abort
call a:node.open({'stay': 1, 'where': 'p', 'keepopen': 1})
endfunction
"FUNCTION: s:previewNodeHSplit(node) {{{1
function! s:previewNodeHSplit(node)
function! s:previewNodeHSplit(node) abort
call a:node.open({'stay': 1, 'where': 'h', 'keepopen': 1})
endfunction
"FUNCTION: s:previewNodeVSplit(node) {{{1
function! s:previewNodeVSplit(node)
function! s:previewNodeVSplit(node) abort
call a:node.open({'stay': 1, 'where': 'v', 'keepopen': 1})
endfunction
" FUNCTION: nerdtree#ui_glue#revealBookmark(name) {{{1
" put the cursor on the node associate with the given name
function! nerdtree#ui_glue#revealBookmark(name)
function! nerdtree#ui_glue#revealBookmark(name) abort
try
let targetNode = g:NERDTreeBookmark.GetNodeForName(a:name, 0)
let targetNode = g:NERDTreeBookmark.GetNodeForName(a:name, 0, b:NERDTree)
call targetNode.putCursorHere(0, 1)
catch /^NERDTree.BookmarkNotFoundError/
call nerdtree#echo("Bookmark isnt cached under the current root")
call nerdtree#echo('Bookmark isnt cached under the current root')
endtry
endfunction
" FUNCTION: s:refreshRoot() {{{1
" Reloads the current root. All nodes below this will be lost and the root dir
" will be reloaded.
function! s:refreshRoot()
call nerdtree#echo("Refreshing the root node. This could take a while...")
call b:NERDTreeRoot.refresh()
function! s:refreshRoot() abort
if !g:NERDTree.IsOpen()
return
endif
call nerdtree#echo('Refreshing the root node. This could take a while...')
let l:curWin = winnr()
call nerdtree#exec(g:NERDTree.GetWinNum() . 'wincmd w', 1)
call b:NERDTree.root.refresh()
call b:NERDTree.render()
redraw
call nerdtree#echo("Refreshing the root node. This could take a while... DONE")
call nerdtree#exec(l:curWin . 'wincmd w', 1)
call nerdtree#echo('')
endfunction
" FUNCTION: s:refreshCurrent(node) {{{1
" refreshes the root for the current node
function! s:refreshCurrent(node)
function! s:refreshCurrent(node) abort
let node = a:node
if !node.path.isDirectory
let node = node.parent
endif
call nerdtree#echo("Refreshing node. This could take a while...")
call nerdtree#echo('Refreshing node. This could take a while...')
call node.refresh()
call b:NERDTree.render()
redraw
call nerdtree#echo("Refreshing node. This could take a while... DONE")
call nerdtree#echo('')
endfunction
" FUNCTION: nerdtree#ui_glue#setupCommands() {{{1
function! nerdtree#ui_glue#setupCommands()
command! -n=? -complete=dir -bar NERDTree :call g:NERDTreeCreator.CreatePrimary('<args>')
command! -n=? -complete=dir -bar NERDTreeToggle :call g:NERDTreeCreator.TogglePrimary('<args>')
function! nerdtree#ui_glue#setupCommands() abort
command! -n=? -complete=dir -bar NERDTree :call g:NERDTreeCreator.CreateTabTree('<args>')
command! -n=? -complete=dir -bar NERDTreeToggle :call g:NERDTreeCreator.ToggleTabTree('<args>')
command! -n=0 -bar NERDTreeClose :call g:NERDTree.Close()
command! -n=1 -complete=customlist,nerdtree#completeBookmarks -bar NERDTreeFromBookmark call g:NERDTreeCreator.CreatePrimary('<args>')
command! -n=1 -complete=customlist,nerdtree#completeBookmarks -bar NERDTreeFromBookmark call g:NERDTreeCreator.CreateTabTree('<args>')
command! -n=0 -bar NERDTreeMirror call g:NERDTreeCreator.CreateMirror()
command! -n=0 -bar NERDTreeFind call s:findAndRevealPath()
command! -n=? -complete=file -bar NERDTreeFind call s:findAndRevealPath('<args>')
command! -n=0 -bar NERDTreeRefreshRoot call s:refreshRoot()
command! -n=0 -bar NERDTreeFocus call NERDTreeFocus()
command! -n=0 -bar NERDTreeCWD call NERDTreeCWD()
endfunction
" Function: s:SID() {{{1
function s:SID()
if !exists("s:sid")
function! s:SID() abort
if !exists('s:sid')
let s:sid = matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze_SID$')
endif
return s:sid
endfun
" FUNCTION: s:showMenu(node) {{{1
function! s:showMenu(node)
function! s:showMenu(node) abort
let mc = g:NERDTreeMenuController.New(g:NERDTreeMenuItem.AllEnabled())
call mc.showMenu()
endfunction
" FUNCTION: s:toggleIgnoreFilter() {{{1
function! s:toggleIgnoreFilter()
function! s:toggleIgnoreFilter() abort
call b:NERDTree.ui.toggleIgnoreFilter()
endfunction
" FUNCTION: s:toggleShowBookmarks() {{{1
function! s:toggleShowBookmarks()
function! s:toggleShowBookmarks() abort
call b:NERDTree.ui.toggleShowBookmarks()
endfunction
" FUNCTION: s:toggleShowFiles() {{{1
function! s:toggleShowFiles()
function! s:toggleShowFiles() abort
call b:NERDTree.ui.toggleShowFiles()
endfunction
" FUNCTION: s:toggleShowHidden() {{{1
" toggles the display of hidden files
function! s:toggleShowHidden()
function! s:toggleShowHidden() abort
call b:NERDTree.ui.toggleShowHidden()
endfunction
" FUNCTION: s:toggleZoom() {{{1
function! s:toggleZoom()
function! s:toggleZoom() abort
call b:NERDTree.ui.toggleZoom()
endfunction
"FUNCTION: nerdtree#ui_glue#upDir(keepState) {{{1
"moves the tree up a level
" FUNCTION: nerdtree#ui_glue#upDir(preserveState) {{{1
" Move the NERDTree up one level.
"
"Args:
"keepState: 1 if the current root should be left open when the tree is
"re-rendered
function! nerdtree#ui_glue#upDir(keepState)
let cwd = b:NERDTreeRoot.path.str({'format': 'UI'})
if cwd ==# "/" || cwd =~# '^[^/]..$'
call nerdtree#echo("already at top dir")
else
if !a:keepState
call b:NERDTreeRoot.close()
endif
" Args:
" preserveState: if 1, the current root is left open when the new tree is
" rendered; if 0, the current root node is closed
function! nerdtree#ui_glue#upDir(preserveState) abort
let oldRoot = b:NERDTreeRoot
try
call b:NERDTree.root.cacheParent()
catch /^NERDTree.CannotCacheParentError/
call nerdtree#echo('already at root directory')
return
endtry
if empty(b:NERDTreeRoot.parent)
let path = b:NERDTreeRoot.path.getParent()
let newRoot = g:NERDTreeDirNode.New(path)
call newRoot.open()
call newRoot.transplantChild(b:NERDTreeRoot)
let b:NERDTreeRoot = newRoot
else
let b:NERDTreeRoot = b:NERDTreeRoot.parent
endif
let l:oldRoot = b:NERDTree.root
let l:newRoot = b:NERDTree.root.parent
if g:NERDTreeChDirMode ==# 2
call b:NERDTreeRoot.path.changeToDir()
endif
call l:newRoot.open()
call l:newRoot.transplantChild(l:oldRoot)
call b:NERDTree.render()
call oldRoot.putCursorHere(0, 0)
if !a:preserveState
call l:oldRoot.close()
endif
call b:NERDTree.changeRoot(l:newRoot)
call l:oldRoot.putCursorHere(0, 0)
endfunction
" FUNCTION: s:upDirCurrentRootOpen() {{{1
function! s:upDirCurrentRootOpen()
function! s:upDirCurrentRootOpen() abort
call nerdtree#ui_glue#upDir(1)
endfunction
" FUNCTION: s:upDirCurrentRootClosed() {{{1
function! s:upDirCurrentRootClosed()
function! s:upDirCurrentRootClosed() abort
call nerdtree#ui_glue#upDir(0)
endfunction

1521
doc/NERDTree.txt Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +1,19 @@
"CLASS: Bookmark
"============================================================
" ============================================================================
" CLASS: Bookmark
"
" The Bookmark class serves two purposes:
" (1) It is the top-level prototype for new, concrete Bookmark objects.
" (2) It provides an interface for client code to query and manipulate the
" global list of Bookmark objects within the current Vim session.
" ============================================================================
let s:Bookmark = {}
let g:NERDTreeBookmark = s:Bookmark
" FUNCTION: Bookmark.activate() {{{1
function! s:Bookmark.activate(...)
call self.open(a:0 ? a:1 : {})
" FUNCTION: Bookmark.activate(nerdtree) {{{1
function! s:Bookmark.activate(nerdtree, ...)
call self.open(a:nerdtree, a:0 ? a:1 : {})
endfunction
" FUNCTION: Bookmark.AddBookmark(name, path) {{{1
@@ -19,22 +27,19 @@ function! s:Bookmark.AddBookmark(name, path)
endif
endfor
call add(s:Bookmark.Bookmarks(), s:Bookmark.New(a:name, a:path))
if g:NERDTreeBookmarksSort ==# 1
call s:Bookmark.Sort()
endif
endfunction
" FUNCTION: Bookmark.Bookmarks() {{{1
" FUNCTION: Bookmark.Bookmarks() {{{1
" Class method to get all bookmarks. Lazily initializes the bookmarks global
" variable
function! s:Bookmark.Bookmarks()
if !exists("g:NERDTreeBookmarks")
if !exists('g:NERDTreeBookmarks')
let g:NERDTreeBookmarks = []
endif
return g:NERDTreeBookmarks
endfunction
" FUNCTION: Bookmark.BookmarkExistsFor(name) {{{1
" FUNCTION: Bookmark.BookmarkExistsFor(name) {{{1
" class method that returns 1 if a bookmark with the given name is found, 0
" otherwise
function! s:Bookmark.BookmarkExistsFor(name)
@@ -46,19 +51,24 @@ function! s:Bookmark.BookmarkExistsFor(name)
endtry
endfunction
" FUNCTION: Bookmark.BookmarkFor(name) {{{1
" Class method to get the bookmark that has the given name. {} is return if no
" bookmark is found
" FUNCTION: Bookmark.BookmarkFor(name) {{{1
" Class method that returns the Bookmark object having the specified name.
" Throws NERDTree.BookmarkNotFoundError if no Bookmark is found.
function! s:Bookmark.BookmarkFor(name)
for i in s:Bookmark.Bookmarks()
if i.name ==# a:name
return i
let l:result = {}
for l:bookmark in s:Bookmark.Bookmarks()
if l:bookmark.name ==# a:name
let l:result = l:bookmark
break
endif
endfor
throw "NERDTree.BookmarkNotFoundError: no bookmark found for name: \"". a:name .'"'
if empty(l:result)
throw 'NERDTree.BookmarkNotFoundError: "' . a:name . '" not found'
endif
return l:result
endfunction
" FUNCTION: Bookmark.BookmarkNames() {{{1
" FUNCTION: Bookmark.BookmarkNames() {{{1
" Class method to return an array of all bookmark names
function! s:Bookmark.BookmarkNames()
let names = []
@@ -83,7 +93,7 @@ function! s:Bookmark.CacheBookmarks(silent)
for i in bookmarkStrings
"ignore blank lines
if i != ''
if i !=# ''
let name = substitute(i, '^\(.\{-}\) .*$', '\1', '')
let path = substitute(i, '^.\{-} \(.*\)$', '\1', '')
@@ -101,20 +111,34 @@ function! s:Bookmark.CacheBookmarks(silent)
if invalidBookmarksFound
call s:Bookmark.Write()
if !a:silent
call nerdtree#echo(invalidBookmarksFound . " invalid bookmarks were read. See :help NERDTreeInvalidBookmarks for info.")
call nerdtree#echo(invalidBookmarksFound . ' invalid bookmarks were read. See :help NERDTreeInvalidBookmarks for info.')
endif
endif
if g:NERDTreeBookmarksSort ==# 1
call s:Bookmark.Sort()
endif
endif
endfunction
" FUNCTION: Bookmark.compareTo(otherbookmark) {{{1
" Compare these two bookmarks for sorting purposes
function! s:Bookmark.compareTo(otherbookmark)
return a:otherbookmark.name < self.name
" FUNCTION: Bookmark.CompareBookmarksByName(firstBookmark, secondBookmark) {{{1
" Class method that indicates the relative position of two bookmarks when
" placed in alphabetical order by name. Case-sensitivity is determined by an
" option. Supports the s:Bookmark.SortBookmarksList() method.
function! s:Bookmark.CompareBookmarksByName(firstBookmark, secondBookmark)
let l:result = 0
if g:NERDTreeBookmarksSort ==# 1
if a:firstBookmark.name <? a:secondBookmark.name
let l:result = -1
elseif a:firstBookmark.name >? a:secondBookmark.name
let l:result = 1
endif
elseif g:NERDTreeBookmarksSort ==# 2
if a:firstBookmark.name <# a:secondBookmark.name
let l:result = -1
elseif a:firstBookmark.name ># a:secondBookmark.name
let l:result = 1
endif
endif
return l:result
endfunction
" FUNCTION: Bookmark.ClearAll() {{{1
" Class method to delete all bookmarks.
function! s:Bookmark.ClearAll()
@@ -128,47 +152,53 @@ endfunction
" Delete this bookmark. If the node for this bookmark is under the current
" root, then recache bookmarks for its Path object
function! s:Bookmark.delete()
let node = {}
try
let node = self.getNode(1)
catch /^NERDTree.BookmarkedNodeNotFoundError/
endtry
call remove(s:Bookmark.Bookmarks(), index(s:Bookmark.Bookmarks(), self))
if !empty(node)
call node.path.cacheDisplayString()
endif
call s:Bookmark.Write()
endfunction
" FUNCTION: Bookmark.getNode(searchFromAbsoluteRoot) {{{1
" Gets the treenode for this bookmark
"
" Args:
" searchFromAbsoluteRoot: specifies whether we should search from the current
" tree root, or the highest cached node
function! s:Bookmark.getNode(searchFromAbsoluteRoot)
let searchRoot = a:searchFromAbsoluteRoot ? g:NERDTreeDirNode.AbsoluteTreeRoot() : b:NERDTreeRoot
let targetNode = searchRoot.findNode(self.path)
if empty(targetNode)
throw "NERDTree.BookmarkedNodeNotFoundError: no node was found for bookmark: " . self.name
endif
return targetNode
" FUNCTION: s:Edit() {{{1
" opens the NERDTreeBookmarks file for manual editing
function! s:Bookmark.Edit()
call nerdtree#exec('wincmd w', 1)
call nerdtree#exec('edit '.g:NERDTreeBookmarksFile, 1)
endfunction
" FUNCTION: Bookmark.GetNodeForName(name, searchFromAbsoluteRoot) {{{1
" Class method that finds the bookmark with the given name and returns the
" treenode for it.
function! s:Bookmark.GetNodeForName(name, searchFromAbsoluteRoot)
let bookmark = s:Bookmark.BookmarkFor(a:name)
return bookmark.getNode(a:searchFromAbsoluteRoot)
" FUNCTION: Bookmark.getNode(nerdtree, searchFromAbsoluteRoot) {{{1
" Returns the tree node object associated with this Bookmark.
" Throws NERDTree.BookmarkedNodeNotFoundError if the node is not found.
"
" Args:
" searchFromAbsoluteRoot: boolean flag, search from the highest cached node
" if true and from the current tree root if false
function! s:Bookmark.getNode(nerdtree, searchFromAbsoluteRoot)
if a:searchFromAbsoluteRoot
let l:searchRoot = a:nerdtree.root.AbsoluteTreeRoot()
else
let l:searchRoot = a:nerdtree.root
endif
let l:targetNode = l:searchRoot.findNode(self.path)
if empty(l:targetNode)
throw 'NERDTree.BookmarkedNodeNotFoundError: node for bookmark "' . self.name . '" not found'
endif
return l:targetNode
endfunction
" FUNCTION: Bookmark.GetNodeForName(name, searchFromAbsoluteRoot, nerdtree) {{{1
" Class method that returns the tree node object for the Bookmark with the
" given name. Throws NERDTree.BookmarkNotFoundError if a Bookmark with the
" name does not exist. Throws NERDTree.BookmarkedNodeNotFoundError if a
" tree node for the named Bookmark could not be found.
function! s:Bookmark.GetNodeForName(name, searchFromAbsoluteRoot, nerdtree)
let l:bookmark = s:Bookmark.BookmarkFor(a:name)
return l:bookmark.getNode(a:nerdtree, a:searchFromAbsoluteRoot)
endfunction
" FUNCTION: Bookmark.GetSelected() {{{1
" returns the Bookmark the cursor is over, or {}
function! s:Bookmark.GetSelected()
let line = getline(".")
let line = getline('.')
let name = substitute(line, '^>\(.\{-}\) .\+$', '\1', '')
if name != line
if name !=# line
try
return s:Bookmark.BookmarkFor(name)
catch /^NERDTree.BookmarkNotFoundError/
@@ -178,11 +208,11 @@ function! s:Bookmark.GetSelected()
return {}
endfunction
" FUNCTION: Bookmark.InvalidBookmarks() {{{1
" FUNCTION: Bookmark.InvalidBookmarks() {{{1
" Class method to get all invalid bookmark strings read from the bookmarks
" file
function! s:Bookmark.InvalidBookmarks()
if !exists("g:NERDTreeInvalidBookmarks")
if !exists('g:NERDTreeInvalidBookmarks')
let g:NERDTreeInvalidBookmarks = []
endif
return g:NERDTreeInvalidBookmarks
@@ -192,8 +222,8 @@ endfunction
function! s:Bookmark.mustExist()
if !self.path.exists()
call s:Bookmark.CacheBookmarks(1)
throw "NERDTree.BookmarkPointsToInvalidLocationError: the bookmark \"".
\ self.name ."\" points to a non existing location: \"". self.path.str()
throw 'NERDTree.BookmarkPointsToInvalidLocationError: the bookmark "'.
\ self.name .'" points to a non existing location: "'. self.path.str()
endif
endfunction
@@ -201,7 +231,7 @@ endfunction
" Create a new bookmark object with the given name and path object
function! s:Bookmark.New(name, path)
if a:name =~# ' '
throw "NERDTree.IllegalBookmarkNameError: illegal name:" . a:name
throw 'NERDTree.IllegalBookmarkNameError: illegal name:' . a:name
endif
let newBookmark = copy(self)
@@ -210,8 +240,11 @@ function! s:Bookmark.New(name, path)
return newBookmark
endfunction
" FUNCTION: Bookmark.open([options]) {{{1
" FUNCTION: Bookmark.open(nerdtree, [options]) {{{1
"Args:
"
"nerdtree: the tree to load open the bookmark in
"
"A dictionary containing the following keys (all optional):
" 'where': Specifies whether the node should be opened in new split/tab or in
" the previous window. Can be either 'v' (vertical split), 'h'
@@ -220,11 +253,15 @@ endfunction
" 'keepopen': dont close the tree window
" 'stay': open the file, but keep the cursor in the tree win
"
function! s:Bookmark.open(...)
function! s:Bookmark.open(nerdtree, ...)
let opts = a:0 ? a:1 : {}
if nerdtree#and(g:NERDTreeQuitOnOpen,2)
call a:nerdtree.ui.toggleShowBookmarks()
endif
if self.path.isDirectory && !has_key(opts, 'where')
call self.toRoot()
call self.toRoot(a:nerdtree)
else
let opener = g:NERDTreeOpener.New(self.path, opts)
call opener.open(self)
@@ -238,54 +275,58 @@ function! s:Bookmark.openInNewTab(options)
call self.open(a:options)
endfunction
" FUNCTION: Bookmark.setPath(path) {{{1
" FUNCTION: Bookmark.setPath(path) {{{1
" makes this bookmark point to the given path
function! s:Bookmark.setPath(path)
let self.path = a:path
endfunction
" FUNCTION: Bookmark.Sort() {{{1
" Class method that sorts all bookmarks
function! s:Bookmark.Sort()
let CompareFunc = function("nerdtree#compareBookmarks")
call sort(s:Bookmark.Bookmarks(), CompareFunc)
" FUNCTION: Bookmark.SortBookmarksList() {{{1
" Class method that sorts the global list of bookmarks alphabetically by name.
" Note that case-sensitivity is determined by a user option.
function! s:Bookmark.SortBookmarksList()
call sort(s:Bookmark.Bookmarks(), s:Bookmark.CompareBookmarksByName, s:Bookmark)
endfunction
" FUNCTION: Bookmark.str() {{{1
" FUNCTION: Bookmark.str() {{{1
" Get the string that should be rendered in the view for this bookmark
function! s:Bookmark.str()
let pathStrMaxLen = winwidth(g:NERDTree.GetWinNum()) - 4 - len(self.name)
if &nu
let pathStrMaxLen = winwidth(g:NERDTree.GetWinNum()) - 4 - strdisplaywidth(self.name)
if &number
let pathStrMaxLen = pathStrMaxLen - &numberwidth
endif
let pathStr = self.path.str({'format': 'UI'})
if len(pathStr) > pathStrMaxLen
let pathStr = '<' . strpart(pathStr, len(pathStr) - pathStrMaxLen)
if strdisplaywidth(pathStr) > pathStrMaxLen
while strdisplaywidth(pathStr) > pathStrMaxLen && strchars(pathStr) > 0
let pathStr = substitute(pathStr, '^.', '', '')
endwhile
let pathStr = '<' . pathStr
endif
return '>' . self.name . ' ' . pathStr
endfunction
" FUNCTION: Bookmark.toRoot() {{{1
" Make the node for this bookmark the new tree root
function! s:Bookmark.toRoot()
" FUNCTION: Bookmark.toRoot(nerdtree) {{{1
" Set the root of the given NERDTree to the node for this Bookmark. If a node
" for this Bookmark does not exist, a new one is initialized.
function! s:Bookmark.toRoot(nerdtree)
if self.validate()
try
let targetNode = self.getNode(1)
let l:targetNode = self.getNode(a:nerdtree, 1)
call l:targetNode.closeChildren()
catch /^NERDTree.BookmarkedNodeNotFoundError/
let targetNode = g:NERDTreeFileNode.New(s:Bookmark.BookmarkFor(self.name).path)
let l:targetNode = g:NERDTreeFileNode.New(s:Bookmark.BookmarkFor(self.name).path, a:nerdtree)
endtry
call targetNode.makeRoot()
call b:NERDTree.render()
call targetNode.putCursorHere(0, 0)
call a:nerdtree.changeRoot(l:targetNode)
endif
endfunction
" FUNCTION: Bookmark.ToRoot(name) {{{1
" Make the node for this bookmark the new tree root
function! s:Bookmark.ToRoot(name)
let bookmark = s:Bookmark.BookmarkFor(a:name)
call bookmark.toRoot()
" FUNCTION: Bookmark.ToRoot(name, nerdtree) {{{1
" Class method that makes the Bookmark with the given name the root of
" specified NERDTree.
function! s:Bookmark.ToRoot(name, nerdtree)
let l:bookmark = s:Bookmark.BookmarkFor(a:name)
call l:bookmark.toRoot(a:nerdtree)
endfunction
" FUNCTION: Bookmark.validate() {{{1
@@ -294,13 +335,12 @@ function! s:Bookmark.validate()
return 1
else
call s:Bookmark.CacheBookmarks(1)
call b:NERDTree.render()
call nerdtree#echo(self.name . "now points to an invalid location. See :help NERDTreeInvalidBookmarks for info.")
call nerdtree#echo(self.name . 'now points to an invalid location. See :help NERDTreeInvalidBookmarks for info.')
return 0
endif
endfunction
" FUNCTION: Bookmark.Write() {{{1
" FUNCTION: Bookmark.Write() {{{1
" Class method to write all bookmarks to the bookmarks file
function! s:Bookmark.Write()
let bookmarkStrings = []
@@ -309,12 +349,17 @@ function! s:Bookmark.Write()
endfor
"add a blank line before the invalid ones
call add(bookmarkStrings, "")
call add(bookmarkStrings, '')
for j in s:Bookmark.InvalidBookmarks()
call add(bookmarkStrings, j)
endfor
call writefile(bookmarkStrings, g:NERDTreeBookmarksFile)
try
call writefile(bookmarkStrings, g:NERDTreeBookmarksFile)
catch
call nerdtree#echoError('Failed to write bookmarks file. Make sure g:NERDTreeBookmarksFile points to a valid location.')
endtry
endfunction
" vim: set sw=4 sts=4 et fdm=marker:

View File

@@ -1,113 +1,103 @@
"CLASS: Creator
"Creates primary/secondary/mirror nerdtree windows. Sets up all the window and
"buffer options and key mappings etc.
"============================================================
" ============================================================================
" CLASS: Creator
"
" This class is responsible for creating NERDTree instances. The new NERDTree
" may be a tab tree, a window tree, or a mirrored tree. In the process of
" creating a NERDTree, it sets up all of the window and buffer options and key
" mappings etc.
" ============================================================================
let s:Creator = {}
let g:NERDTreeCreator = s:Creator
"FUNCTION: s:Creator._bindMappings() {{{1
" FUNCTION: s:Creator._bindMappings() {{{1
function! s:Creator._bindMappings()
"make <cr> do the same as the activate node mapping
nnoremap <silent> <buffer> <cr> :call nerdtree#ui_glue#invokeKeyMap(g:NERDTreeMapActivateNode)<cr>
call g:NERDTreeKeyMap.BindAll()
command! -buffer -nargs=? Bookmark :call nerdtree#ui_glue#bookmarkNode('<args>')
command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=1 RevealBookmark :call nerdtree#ui_glue#revealBookmark('<args>')
command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=1 OpenBookmark :call nerdtree#ui_glue#openBookmark('<args>')
command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=1 OpenBookmark call nerdtree#ui_glue#openBookmark('<args>')
command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=* ClearBookmarks call nerdtree#ui_glue#clearBookmarks('<args>')
command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=+ BookmarkToRoot call g:NERDTreeBookmark.ToRoot('<args>')
command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=+ BookmarkToRoot call g:NERDTreeBookmark.ToRoot('<args>', b:NERDTree)
command! -buffer -nargs=0 ClearAllBookmarks call g:NERDTreeBookmark.ClearAll() <bar> call b:NERDTree.render()
command! -buffer -nargs=0 ReadBookmarks call g:NERDTreeBookmark.CacheBookmarks(0) <bar> call b:NERDTree.render()
command! -buffer -nargs=0 WriteBookmarks call g:NERDTreeBookmark.Write()
command! -buffer -nargs=0 EditBookmarks call g:NERDTreeBookmark.Edit()
endfunction
"FUNCTION: s:Creator._broadcastInitEvent() {{{1
" FUNCTION: s:Creator._broadcastInitEvent() {{{1
function! s:Creator._broadcastInitEvent()
silent doautocmd User NERDTreeInit
endfunction
" FUNCTION: s:Creator.BufNamePrefix() {{{2
" FUNCTION: s:Creator.BufNamePrefix() {{{1
function! s:Creator.BufNamePrefix()
return 'NERD_tree_'
endfunction
"FUNCTION: s:Creator.CreatePrimary(a:name) {{{1
function! s:Creator.CreatePrimary(name)
" FUNCTION: s:Creator.CreateTabTree(a:name) {{{1
function! s:Creator.CreateTabTree(name)
let creator = s:Creator.New()
call creator.createPrimary(a:name)
call creator.createTabTree(a:name)
endfunction
"FUNCTION: s:Creator.createPrimary(a:name) {{{1
"name: the name of a bookmark or a directory
function! s:Creator.createPrimary(name)
let path = self._pathForString(a:name)
"abort if exception was thrown (bookmark/dir doesn't exist)
if empty(path)
" FUNCTION: s:Creator.createTabTree(a:name) {{{1
" name: the name of a bookmark or a directory
function! s:Creator.createTabTree(name)
let l:path = self._pathForString(a:name)
" Abort if an exception was thrown (i.e., if the bookmark or directory
" does not exist).
if empty(l:path)
return
endif
if path == {}
return
endif
"if instructed to, then change the vim CWD to the dir the NERDTree is
"inited in
" Obey the user's preferences for changing the working directory.
if g:NERDTreeChDirMode != 0
call path.changeToDir()
call l:path.changeToDir()
endif
if g:NERDTree.ExistsForTab()
if g:NERDTree.IsOpen()
call g:NERDTree.Close()
endif
unlet t:NERDTreeBufName
call g:NERDTree.Close()
call self._removeTreeBufForTab()
endif
call self._createTreeWin()
call self._createNERDTree(path)
let b:NERDTreeType = "primary"
let b:treeShowHelp = 0
let b:NERDTreeIgnoreEnabled = 1
let b:NERDTreeShowFiles = g:NERDTreeShowFiles
let b:NERDTreeShowHidden = g:NERDTreeShowHidden
let b:NERDTreeShowBookmarks = g:NERDTreeShowBookmarks
call self._createNERDTree(l:path, 'tab')
call b:NERDTree.render()
call b:NERDTreeRoot.putCursorHere(0, 0)
call b:NERDTree.root.putCursorHere(0, 0)
call self._broadcastInitEvent()
endfunction
"FUNCTION: s:Creator.CreateSecondary(dir) {{{1
function! s:Creator.CreateSecondary(dir)
" FUNCTION: s:Creator.CreateWindowTree(dir) {{{1
function! s:Creator.CreateWindowTree(dir)
let creator = s:Creator.New()
call creator.createSecondary(a:dir)
call creator.createWindowTree(a:dir)
endfunction
"FUNCTION: s:Creator.createSecondary(dir) {{{1
function! s:Creator.createSecondary(dir)
" FUNCTION: s:Creator.createWindowTree(dir) {{{1
function! s:Creator.createWindowTree(dir)
try
let path = g:NERDTreePath.New(a:dir)
catch /^NERDTree.InvalidArgumentsError/
call nerdtree#echo("Invalid directory name:" . a:name)
call nerdtree#echo('Invalid directory name:' . a:dir)
return
endtry
"we want the directory buffer to disappear when we do the :edit below
setlocal bufhidden=wipe
let previousBuf = expand("#")
let previousBuf = expand('#')
"we need a unique name for each secondary tree buffer to ensure they are
"we need a unique name for each window tree buffer to ensure they are
"all independent
exec "silent edit " . self._nextBufferName()
exec g:NERDTreeCreatePrefix . ' edit ' . self._nextBufferName()
let b:NERDTreePreviousBuf = bufnr(previousBuf)
call self._createNERDTree(path)
call self._createNERDTree(path, 'window')
let b:NERDTree._previousBuf = bufnr(previousBuf)
call self._setCommonBufOptions()
let b:NERDTreeType = "secondary"
call b:NERDTree.render()
@@ -115,11 +105,12 @@ function! s:Creator.createSecondary(dir)
endfunction
" FUNCTION: s:Creator._createNERDTree(path) {{{1
function! s:Creator._createNERDTree(path)
let b:NERDTree = g:NERDTree.New(a:path)
"TODO: This is kept for compatability only since many things use
"b:NERDTreeRoot instead of the new NERDTree.root
"Remove this one day
function! s:Creator._createNERDTree(path, type)
let b:NERDTree = g:NERDTree.New(a:path, a:type)
" TODO: This assignment is kept for compatibility reasons. Many other
" plugins use b:NERDTreeRoot instead of b:NERDTree.root. Remove this
" assignment in the future.
let b:NERDTreeRoot = b:NERDTree.root
call b:NERDTree.root.open()
@@ -135,9 +126,9 @@ endfunction
function! s:Creator.createMirror()
"get the names off all the nerd tree buffers
let treeBufNames = []
for i in range(1, tabpagenr("$"))
for i in range(1, tabpagenr('$'))
let nextName = self._tabpagevar(i, 'NERDTreeBufName')
if nextName != -1 && (!exists("t:NERDTreeBufName") || nextName != t:NERDTreeBufName)
if nextName != -1 && (!exists('t:NERDTreeBufName') || nextName != t:NERDTreeBufName)
call add(treeBufNames, nextName)
endif
endfor
@@ -149,7 +140,7 @@ function! s:Creator.createMirror()
let i = 0
while i < len(treeBufNames)
let bufName = treeBufNames[i]
let treeRoot = getbufvar(bufName, "NERDTreeRoot")
let treeRoot = getbufvar(bufName, 'NERDTree').root
let options[i+1 . '. ' . treeRoot.path.str() . ' (buf name: ' . bufName . ')'] = bufName
let i = i + 1
endwhile
@@ -157,7 +148,7 @@ function! s:Creator.createMirror()
"work out which tree to mirror, if there is more than 1 then ask the user
let bufferName = ''
if len(keys(options)) > 1
let choices = ["Choose a tree to mirror"]
let choices = ['Choose a tree to mirror']
let choices = extend(choices, sort(keys(options)))
let choice = inputlist(choices)
if choice < 1 || choice > len(options) || choice ==# ''
@@ -168,7 +159,7 @@ function! s:Creator.createMirror()
elseif len(keys(options)) ==# 1
let bufferName = values(options)[0]
else
call nerdtree#echo("No trees to mirror")
call nerdtree#echo('No trees to mirror')
return
endif
@@ -184,44 +175,59 @@ function! s:Creator.createMirror()
endif
endfunction
"FUNCTION: s:Creator._createTreeWin() {{{1
"Inits the NERD tree window. ie. opens it, sizes it, sets all the local
"options etc
" FUNCTION: s:Creator._createTreeWin() {{{1
" Initialize the NERDTree window. Open the window, size it properly, set all
" local options, etc.
function! s:Creator._createTreeWin()
"create the nerd tree window
let splitLocation = g:NERDTreeWinPos ==# "left" ? "topleft " : "botright "
let splitSize = g:NERDTreeWinSize
let l:splitLocation = g:NERDTreeWinPos ==# 'left' ? 'topleft ' : 'botright '
let l:splitSize = g:NERDTreeWinSize
if !exists('t:NERDTreeBufName')
if !g:NERDTree.ExistsForTab()
let t:NERDTreeBufName = self._nextBufferName()
silent! exec splitLocation . 'vertical ' . splitSize . ' new'
silent! exec "edit " . t:NERDTreeBufName
silent! execute l:splitLocation . 'vertical ' . l:splitSize . ' new'
silent! execute 'edit ' . t:NERDTreeBufName
silent! execute 'vertical resize '. l:splitSize
else
silent! exec splitLocation . 'vertical ' . splitSize . ' split'
silent! exec "buffer " . t:NERDTreeBufName
silent! execute l:splitLocation . 'vertical ' . l:splitSize . ' split'
silent! execute 'buffer ' . t:NERDTreeBufName
endif
setlocal winfixwidth
call self._setCommonBufOptions()
if has('patch-7.4.1925')
clearjumps
endif
endfunction
"FUNCTION: s:Creator.New() {{{1
" FUNCTION: s:Creator._isBufHidden(nr) {{{1
function! s:Creator._isBufHidden(nr)
redir => bufs
silent ls!
redir END
return bufs =~ a:nr . '..h'
endfunction
" FUNCTION: s:Creator.New() {{{1
function! s:Creator.New()
let newCreator = copy(self)
return newCreator
endfunction
" FUNCTION: s:Creator._nextBufferName() {{{2
" FUNCTION: s:Creator._nextBufferName() {{{1
" returns the buffer name for the next nerd tree
function! s:Creator._nextBufferName()
let name = s:Creator.BufNamePrefix() . self._nextBufferNumber()
return name
endfunction
" FUNCTION: s:Creator._nextBufferNumber() {{{2
" FUNCTION: s:Creator._nextBufferNumber() {{{1
" the number to add to the nerd tree buffer name to make the buf name unique
function! s:Creator._nextBufferNumber()
if !exists("s:Creator._NextBufNum")
if !exists('s:Creator._NextBufNum')
let s:Creator._NextBufNum = 1
else
let s:Creator._NextBufNum += 1
@@ -230,8 +236,8 @@ function! s:Creator._nextBufferNumber()
return s:Creator._NextBufNum
endfunction
"FUNCTION: s:Creator._pathForString(str) {{{1
"find a bookmark or adirectory for the given string
" FUNCTION: s:Creator._pathForString(str) {{{1
" find a bookmark or adirectory for the given string
function! s:Creator._pathForString(str)
let path = {}
if g:NERDTreeBookmark.BookmarkExistsFor(a:str)
@@ -248,7 +254,7 @@ function! s:Creator._pathForString(str)
try
let path = g:NERDTreePath.New(dir)
catch /^NERDTree.InvalidArgumentsError/
call nerdtree#echo("No bookmark or directory found for: " . a:str)
call nerdtree#echo('No bookmark or directory found for: ' . a:str)
return {}
endtry
endif
@@ -259,24 +265,46 @@ function! s:Creator._pathForString(str)
return path
endfunction
"FUNCTION: s:Creator._setCommonBufOptions() {{{1
" Function: s:Creator._removeTreeBufForTab() {{{1
function! s:Creator._removeTreeBufForTab()
let buf = bufnr(t:NERDTreeBufName)
"if &hidden is not set then it will already be gone
if buf != -1
"nerdtree buf may be mirrored/displayed elsewhere
if self._isBufHidden(buf)
exec 'bwipeout ' . buf
endif
endif
unlet t:NERDTreeBufName
endfunction
" FUNCTION: s:Creator._setCommonBufOptions() {{{1
function! s:Creator._setCommonBufOptions()
"throwaway buffer options
setlocal noswapfile
setlocal buftype=nofile
" Options for a non-file/control buffer.
setlocal bufhidden=hide
setlocal nowrap
setlocal buftype=nofile
setlocal noswapfile
" Options for controlling buffer/window appearance.
setlocal foldcolumn=0
setlocal foldmethod=manual
setlocal nofoldenable
setlocal nobuflisted
setlocal nofoldenable
setlocal nolist
setlocal nospell
setlocal nowrap
if g:NERDTreeShowLineNumbers
setlocal nu
setlocal number
else
setlocal nonu
setlocal nonumber
if v:version >= 703
setlocal nornu
setlocal norelativenumber
endif
endif
@@ -287,17 +315,12 @@ function! s:Creator._setCommonBufOptions()
endif
call self._setupStatusline()
let b:treeShowHelp = 0
let b:NERDTreeIgnoreEnabled = 1
let b:NERDTreeShowFiles = g:NERDTreeShowFiles
let b:NERDTreeShowHidden = g:NERDTreeShowHidden
let b:NERDTreeShowBookmarks = g:NERDTreeShowBookmarks
call self._bindMappings()
setlocal filetype=nerdtree
endfunction
"FUNCTION: s:Creator._setupStatusline() {{{1
" FUNCTION: s:Creator._setupStatusline() {{{1
function! s:Creator._setupStatusline()
if g:NERDTreeStatusline != -1
let &l:statusline = g:NERDTreeStatusline
@@ -307,35 +330,35 @@ endfunction
" FUNCTION: s:Creator._tabpagevar(tabnr, var) {{{1
function! s:Creator._tabpagevar(tabnr, var)
let currentTab = tabpagenr()
let old_ei = &ei
set ei=all
let old_ei = &eventignore
set eventignore=all
exec "tabnext " . a:tabnr
exec 'tabnext ' . a:tabnr
let v = -1
if exists('t:' . a:var)
exec 'let v = t:' . a:var
endif
exec "tabnext " . currentTab
exec 'tabnext ' . currentTab
let &ei = old_ei
let &eventignore = old_ei
return v
endfunction
"FUNCTION: s:Creator.TogglePrimary(dir) {{{1
function! s:Creator.TogglePrimary(dir)
" FUNCTION: s:Creator.ToggleTabTree(dir) {{{1
function! s:Creator.ToggleTabTree(dir)
let creator = s:Creator.New()
call creator.togglePrimary(a:dir)
call creator.toggleTabTree(a:dir)
endfunction
"FUNCTION: s:Creator.togglePrimary(dir) {{{1
"Toggles the NERD tree. I.e the NERD tree is open, it is closed, if it is
"closed it is restored or initialized (if it doesnt exist)
" FUNCTION: s:Creator.toggleTabTree(dir) {{{1
" Toggles the NERD tree. I.e the NERD tree is open, it is closed, if it is
" closed it is restored or initialized (if it doesnt exist)
"
"Args:
"dir: the full path for the root node (is only used if the NERD tree is being
"initialized.
function! s:Creator.togglePrimary(dir)
" Args:
" dir: the full path for the root node (is only used if the NERD tree is being
" initialized.
function! s:Creator.toggleTabTree(dir)
if g:NERDTree.ExistsForTab()
if !g:NERDTree.IsOpen()
call self._createTreeWin()
@@ -347,7 +370,7 @@ function! s:Creator.togglePrimary(dir)
call g:NERDTree.Close()
endif
else
call self.createPrimary(a:dir)
call self.createTabTree(a:dir)
endif
endfunction

View File

@@ -43,14 +43,16 @@ endfunction
"FUNCTION: FlagSet.renderToString() {{{1
function! s:FlagSet.renderToString()
let flagstring = ""
let flagstring = ''
for i in values(self._flags)
let flagstring .= join(i)
endfor
if len(flagstring) == 0
return ""
return ''
endif
return '[' . flagstring . ']'
endfunction
" vim: set sw=4 sts=4 et fdm=marker:

View File

@@ -2,28 +2,38 @@
"============================================================
let s:KeyMap = {}
let g:NERDTreeKeyMap = s:KeyMap
let s:keyMaps = {}
"FUNCTION: KeyMap.All() {{{1
function! s:KeyMap.All()
if !exists("s:keyMaps")
let s:keyMaps = []
let sortedKeyMaps = values(s:keyMaps)
call sort(sortedKeyMaps, s:KeyMap.Compare, s:KeyMap)
return sortedKeyMaps
endfunction
"FUNCTION: KeyMap.Compare(keyMap1, keyMap2) {{{1
function! s:KeyMap.Compare(keyMap1, keyMap2)
if a:keyMap1.key >? a:keyMap2.key
return 1
endif
return s:keyMaps
if a:keyMap1.key <? a:keyMap2.key
return -1
endif
return 0
endfunction
"FUNCTION: KeyMap.FindFor(key, scope) {{{1
function! s:KeyMap.FindFor(key, scope)
for i in s:KeyMap.All()
if i.key ==# a:key && i.scope ==# a:scope
return i
endif
endfor
return {}
return get(s:keyMaps, a:key . a:scope, {})
endfunction
"FUNCTION: KeyMap.BindAll() {{{1
function! s:KeyMap.BindAll()
for i in s:KeyMap.All()
for i in values(s:keyMaps)
call i.bind()
endfor
endfunction
@@ -41,26 +51,22 @@ function! s:KeyMap.bind()
else
let keymapInvokeString = self.key
endif
let keymapInvokeString = escape(keymapInvokeString, '\')
let premap = self.key == "<LeftRelease>" ? " <LeftRelease>" : " "
let premap = self.key ==# '<LeftRelease>' ? ' <LeftRelease>' : ' '
exec 'nnoremap <buffer> <silent> '. self.key . premap . ':call nerdtree#ui_glue#invokeKeyMap("'. keymapInvokeString .'")<cr>'
endfunction
"FUNCTION: KeyMap.Remove(key, scope) {{{1
function! s:KeyMap.Remove(key, scope)
let maps = s:KeyMap.All()
for i in range(len(maps))
if maps[i].key ==# a:key && maps[i].scope ==# a:scope
return remove(maps, i)
endif
endfor
return remove(s:keyMaps, a:key . a:scope)
endfunction
"FUNCTION: KeyMap.invoke() {{{1
"Call the KeyMaps callback function
function! s:KeyMap.invoke(...)
let Callback = function(self.callback)
let Callback = type(self.callback) ==# type(function('tr')) ? self.callback : function(self.callback)
if a:0
call Callback(a:1)
else
@@ -72,11 +78,11 @@ endfunction
"Find a keymapping for a:key and the current scope invoke it.
"
"Scope is determined as follows:
" * if the cursor is on a dir node then "DirNode"
" * if the cursor is on a file node then "FileNode"
" * if the cursor is on a bookmark then "Bookmark"
" * if the cursor is on a dir node then DirNode
" * if the cursor is on a file node then FileNode
" * if the cursor is on a bookmark then Bookmark
"
"If a keymap has the scope of "all" then it will be called if no other keymap
"If a keymap has the scope of 'all' then it will be called if no other keymap
"is found for a:key and the scope.
function! s:KeyMap.Invoke(key)
@@ -94,7 +100,7 @@ function! s:KeyMap.Invoke(key)
"try file node
if !node.path.isDirectory
let km = s:KeyMap.FindFor(a:key, "FileNode")
let km = s:KeyMap.FindFor(a:key, 'FileNode')
if !empty(km)
return km.invoke(node)
endif
@@ -102,14 +108,14 @@ function! s:KeyMap.Invoke(key)
"try dir node
if node.path.isDirectory
let km = s:KeyMap.FindFor(a:key, "DirNode")
let km = s:KeyMap.FindFor(a:key, 'DirNode')
if !empty(km)
return km.invoke(node)
endif
endif
"try generic node
let km = s:KeyMap.FindFor(a:key, "Node")
let km = s:KeyMap.FindFor(a:key, 'Node')
if !empty(km)
return km.invoke(node)
endif
@@ -119,14 +125,14 @@ function! s:KeyMap.Invoke(key)
"try bookmark
let bm = g:NERDTreeBookmark.GetSelected()
if !empty(bm)
let km = s:KeyMap.FindFor(a:key, "Bookmark")
let km = s:KeyMap.FindFor(a:key, 'Bookmark')
if !empty(km)
return km.invoke(bm)
endif
endif
"try all
let km = s:KeyMap.FindFor(a:key, "all")
let km = s:KeyMap.FindFor(a:key, 'all')
if !empty(km)
return km.invoke()
endif
@@ -137,7 +143,7 @@ function! s:KeyMap.Create(options)
let opts = extend({'scope': 'all', 'quickhelpText': ''}, copy(a:options))
"dont override other mappings unless the 'override' option is given
if get(opts, 'override', 0) == 0 && !empty(s:KeyMap.FindFor(opts['key'], opts['scope']))
if get(opts, 'override', 0) ==# 0 && !empty(s:KeyMap.FindFor(opts['key'], opts['scope']))
return
end
@@ -152,8 +158,7 @@ endfunction
"FUNCTION: KeyMap.Add(keymap) {{{1
function! s:KeyMap.Add(keymap)
call s:KeyMap.Remove(a:keymap.key, a:keymap.scope)
call add(s:KeyMap.All(), a:keymap)
let s:keyMaps[a:keymap.key . a:keymap.scope] = a:keymap
endfunction
" vim: set sw=4 sts=4 et fdm=marker:

View File

@@ -15,44 +15,71 @@ function! s:MenuController.New(menuItems)
return newMenuController
endfunction
"FUNCTION: MenuController.showMenu() {{{1
"start the main loop of the menu and get the user to choose/execute a menu
"item
" FUNCTION: s:MenuController.isMinimal() {{{1
function! s:MenuController.isMinimal()
return g:NERDTreeMinimalMenu
endfunction
" FUNCTION: MenuController.showMenu() {{{1
" Enter the main loop of the NERDTree menu, prompting the user to select
" a menu item.
function! s:MenuController.showMenu()
call self._saveOptions()
try
let self.selection = 0
let l:done = 0
let done = 0
while !done
redraw!
while !l:done
if has('nvim')
mode
else
redraw!
endif
call self._echoPrompt()
let key = nr2char(getchar())
let done = self._handleKeypress(key)
let l:key = nr2char(getchar())
let l:done = self._handleKeypress(l:key)
endwhile
finally
call self._restoreOptions()
" Redraw when Ctrl-C or Esc is received.
if !l:done || self.selection ==# -1
redraw!
endif
endtry
if self.selection != -1
let m = self._current()
call m.execute()
if self.selection !=# -1
let l:m = self._current()
call l:m.execute()
endif
endfunction
"FUNCTION: MenuController._echoPrompt() {{{1
function! s:MenuController._echoPrompt()
echo "NERDTree Menu. Use j/k/enter and the shortcuts indicated"
echo "=========================================================="
let navHelp = 'Use ' . g:NERDTreeMenuDown . '/' . g:NERDTreeMenuUp . '/enter'
for i in range(0, len(self.menuItems)-1)
if self.selection == i
echo "> " . self.menuItems[i].text
else
echo " " . self.menuItems[i].text
endif
endfor
if self.isMinimal()
let selection = self.menuItems[self.selection].text
let keyword = matchstr(selection, '[^ ]*([^ ]*')
let shortcuts = map(copy(self.menuItems), "v:val['shortcut']")
let shortcuts[self.selection] = ' ' . keyword . ' '
echo 'Menu: [' . join(shortcuts, ',') . '] (' . navHelp . ' or shortcut): '
else
echo 'NERDTree Menu. ' . navHelp . ', or the shortcuts indicated'
echo '========================================================='
for i in range(0, len(self.menuItems)-1)
if self.selection ==# i
echo '> ' . self.menuItems[i].text
else
echo ' ' . self.menuItems[i].text
endif
endfor
endif
endfunction
"FUNCTION: MenuController._current(key) {{{1
@@ -65,20 +92,20 @@ endfunction
"change the selection (if appropriate) and return 1 if the user has made
"their choice, 0 otherwise
function! s:MenuController._handleKeypress(key)
if a:key == 'j'
if a:key ==# g:NERDTreeMenuDown
call self._cursorDown()
elseif a:key == 'k'
elseif a:key ==# g:NERDTreeMenuUp
call self._cursorUp()
elseif a:key == nr2char(27) "escape
elseif a:key ==# nr2char(27) "escape
let self.selection = -1
return 1
elseif a:key == "\r" || a:key == "\n" "enter and ctrl-j
elseif a:key ==# "\r" || a:key ==# "\n" "enter and ctrl-j
return 1
else
let index = self._nextIndexFor(a:key)
if index != -1
if index !=# -1
let self.selection = index
if len(self._allIndexesFor(a:key)) == 1
if len(self._allIndexesFor(a:key)) ==# 1
return 1
endif
endif
@@ -93,7 +120,7 @@ function! s:MenuController._allIndexesFor(shortcut)
let toReturn = []
for i in range(0, len(self.menuItems)-1)
if self.menuItems[i].shortcut == a:shortcut
if self.menuItems[i].shortcut ==# a:shortcut
call add(toReturn, i)
endif
endfor
@@ -106,13 +133,13 @@ endfunction
"current cursor location and wraps around to the top again if need be
function! s:MenuController._nextIndexFor(shortcut)
for i in range(self.selection+1, len(self.menuItems)-1)
if self.menuItems[i].shortcut == a:shortcut
if self.menuItems[i].shortcut ==# a:shortcut
return i
endif
endfor
for i in range(0, self.selection)
if self.menuItems[i].shortcut == a:shortcut
if self.menuItems[i].shortcut ==# a:shortcut
return i
endif
endfor
@@ -123,7 +150,11 @@ endfunction
"FUNCTION: MenuController._setCmdheight() {{{1
"sets &cmdheight to whatever is needed to display the menu
function! s:MenuController._setCmdheight()
let &cmdheight = len(self.menuItems) + 3
if self.isMinimal()
let &cmdheight = 1
else
let &cmdheight = len(self.menuItems) + 3
endif
endfunction
"FUNCTION: MenuController._saveOptions() {{{1

View File

@@ -6,7 +6,7 @@ let g:NERDTreeMenuItem = s:MenuItem
"FUNCTION: MenuItem.All() {{{1
"get all top level menu items
function! s:MenuItem.All()
if !exists("s:menuItems")
if !exists('s:menuItems')
let s:menuItems = []
endif
return s:menuItems
@@ -58,7 +58,7 @@ function! s:MenuItem.CreateSeparator(options)
let standard_options = { 'text': '--------------------',
\ 'shortcut': -1,
\ 'callback': -1 }
let options = extend(a:options, standard_options, "force")
let options = extend(a:options, standard_options, 'force')
return s:MenuItem.Create(options)
endfunction
@@ -67,7 +67,7 @@ endfunction
"make a new submenu and add it to global list
function! s:MenuItem.CreateSubmenu(options)
let standard_options = { 'callback': -1 }
let options = extend(a:options, standard_options, "force")
let options = extend(a:options, standard_options, 'force')
return s:MenuItem.Create(options)
endfunction
@@ -79,7 +79,7 @@ endfunction
"specified
function! s:MenuItem.enabled()
if self.isActiveCallback != -1
return {self.isActiveCallback}()
return type(self.isActiveCallback) == type(function('tr')) ? self.isActiveCallback() : {self.isActiveCallback}()
endif
return 1
endfunction
@@ -94,7 +94,11 @@ function! s:MenuItem.execute()
call mc.showMenu()
else
if self.callback != -1
call {self.callback}()
if type(self.callback) == type(function('tr'))
call self.callback()
else
call {self.callback}()
endif
endif
endif
endfunction

View File

@@ -8,25 +8,56 @@ function! s:NERDTree.AddPathFilter(callback)
call add(s:NERDTree.PathFilters(), a:callback)
endfunction
"FUNCTION: s:NERDTree.changeRoot(node) {{{1
function! s:NERDTree.changeRoot(node)
if a:node.path.isDirectory
let self.root = a:node
else
call a:node.cacheParent()
let self.root = a:node.parent
endif
call self.root.open()
"change dir to the dir of the new root if instructed to
if g:NERDTreeChDirMode >= 2
call self.root.path.changeToDir()
endif
call self.render()
call self.root.putCursorHere(0, 0)
silent doautocmd User NERDTreeNewRoot
endfunction
"FUNCTION: s:NERDTree.Close() {{{1
"Closes the primary NERD tree window for this tab
"Closes the tab tree window for this tab
function! s:NERDTree.Close()
if !s:NERDTree.IsOpen()
return
endif
if winnr("$") != 1
if winnr() == s:NERDTree.GetWinNum()
call nerdtree#exec("wincmd p")
let bufnr = bufnr("")
call nerdtree#exec("wincmd p")
if winnr('$') !=# 1
" Use the window ID to identify the currently active window or fall
" back on the buffer ID if win_getid/win_gotoid are not available, in
" which case we'll focus an arbitrary window showing the buffer.
let l:useWinId = exists('*win_getid') && exists('*win_gotoid')
if winnr() ==# s:NERDTree.GetWinNum()
call nerdtree#exec('wincmd p', 1)
let l:activeBufOrWin = l:useWinId ? win_getid() : bufnr('')
call nerdtree#exec('wincmd p', 1)
else
let bufnr = bufnr("")
let l:activeBufOrWin = l:useWinId ? win_getid() : bufnr('')
endif
call nerdtree#exec(s:NERDTree.GetWinNum() . " wincmd w")
close
call nerdtree#exec(bufwinnr(bufnr) . " wincmd w")
call nerdtree#exec(s:NERDTree.GetWinNum() . ' wincmd w', 1)
call nerdtree#exec('close', 0)
if l:useWinId
call nerdtree#exec('call win_gotoid(' . l:activeBufOrWin . ')', 0)
else
call nerdtree#exec(bufwinnr(l:activeBufOrWin) . ' wincmd w', 0)
endif
else
close
endif
@@ -35,7 +66,7 @@ endfunction
"FUNCTION: s:NERDTree.CloseIfQuitOnOpen() {{{1
"Closes the NERD tree window if the close on open option is set
function! s:NERDTree.CloseIfQuitOnOpen()
if g:NERDTreeQuitOnOpen && s:NERDTree.IsOpen()
if nerdtree#and(g:NERDTreeQuitOnOpen,1) && s:NERDTree.IsOpen()
call s:NERDTree.Close()
endif
endfunction
@@ -43,8 +74,8 @@ endfunction
"FUNCTION: s:NERDTree.CursorToBookmarkTable(){{{1
"Places the cursor at the top of the bookmarks table
function! s:NERDTree.CursorToBookmarkTable()
if !b:NERDTreeShowBookmarks
throw "NERDTree.IllegalOperationError: cant find bookmark table, bookmarks arent active"
if !b:NERDTree.ui.getShowBookmarks()
throw 'NERDTree.IllegalOperationError: cant find bookmark table, bookmarks arent active'
endif
if g:NERDTreeMinimalUI
@@ -57,7 +88,7 @@ function! s:NERDTree.CursorToBookmarkTable()
while getline(line) !~# '^>-\+Bookmarks-\+$'
let line = line + 1
if line >= rootNodeLine
throw "NERDTree.BookmarkTableNotFoundError: didnt find the bookmarks table"
throw 'NERDTree.BookmarkTableNotFoundError: didnt find the bookmarks table'
endif
endwhile
call cursor(line, 2)
@@ -67,19 +98,24 @@ endfunction
"Places the cursor in the nerd tree window
function! s:NERDTree.CursorToTreeWin()
call g:NERDTree.MustBeOpen()
call nerdtree#exec(g:NERDTree.GetWinNum() . "wincmd w")
call nerdtree#exec(g:NERDTree.GetWinNum() . 'wincmd w', 1)
endfunction
" Function: s:NERDTree.ExistsForBuffer() {{{1
" Returns 1 if a nerd tree root exists in the current buffer
function! s:NERDTree.ExistsForBuf()
return exists("b:NERDTreeRoot")
return exists('b:NERDTree')
endfunction
" Function: s:NERDTree.ExistsForTab() {{{1
" Returns 1 if a nerd tree root exists in the current tab
function! s:NERDTree.ExistsForTab()
return exists("t:NERDTreeBufName")
if !exists('t:NERDTreeBufName')
return
end
"check b:NERDTree is still there and hasn't been e.g. :bdeleted
return !empty(getbufvar(bufnr(t:NERDTreeBufName), 'NERDTree'))
endfunction
function! s:NERDTree.ForCurrentBuf()
@@ -90,34 +126,66 @@ function! s:NERDTree.ForCurrentBuf()
endif
endfunction
"FUNCTION: s:NERDTree.ForCurrentTab() {{{1
function! s:NERDTree.ForCurrentTab()
if !s:NERDTree.ExistsForTab()
return
endif
let bufnr = bufnr(t:NERDTreeBufName)
return getbufvar(bufnr, 'NERDTree')
endfunction
"FUNCTION: s:NERDTree.getRoot() {{{1
function! s:NERDTree.getRoot()
return self.root
endfunction
"FUNCTION: s:NERDTree.GetWinNum() {{{1
"gets the nerd tree window number for this tab
function! s:NERDTree.GetWinNum()
if exists("t:NERDTreeBufName")
if exists('t:NERDTreeBufName')
return bufwinnr(t:NERDTreeBufName)
else
return -1
endif
" If WindowTree, there is no t:NERDTreeBufName variable. Search all windows.
for w in range(1,winnr('$'))
if bufname(winbufnr(w)) =~# '^' . g:NERDTreeCreator.BufNamePrefix() . '\d\+$'
return w
endif
endfor
return -1
endfunction
"FUNCTION: s:NERDTree.IsOpen() {{{1
function! s:NERDTree.IsOpen()
return s:NERDTree.GetWinNum() != -1
return s:NERDTree.GetWinNum() !=# -1
endfunction
"FUNCTION: s:NERDTree.isTabTree() {{{1
function! s:NERDTree.isTabTree()
return self._type ==# 'tab'
endfunction
"FUNCTION: s:NERDTree.isWinTree() {{{1
function! s:NERDTree.isWinTree()
return self._type ==# 'window'
endfunction
"FUNCTION: s:NERDTree.MustBeOpen() {{{1
function! s:NERDTree.MustBeOpen()
if !s:NERDTree.IsOpen()
throw "NERDTree.TreeNotOpen"
throw 'NERDTree.TreeNotOpen'
endif
endfunction
"FUNCTION: s:NERDTree.New() {{{1
function! s:NERDTree.New(path)
function! s:NERDTree.New(path, type)
let newObj = copy(self)
let newObj.ui = g:NERDTreeUI.New(newObj)
let newObj.root = g:NERDTreeDirNode.New(a:path)
let newObj.root = g:NERDTreeDirNode.New(a:path, newObj)
let newObj._type = a:type
return newObj
endfunction
@@ -129,9 +197,19 @@ function! s:NERDTree.PathFilters()
return s:NERDTree._PathFilters
endfunction
"FUNCTION: s:NERDTree.previousBuf() {{{1
function! s:NERDTree.previousBuf()
return self._previousBuf
endfunction
function! s:NERDTree.setPreviousBuf(bnum)
let self._previousBuf = a:bnum
endfunction
"FUNCTION: s:NERDTree.render() {{{1
"A convenience function - since this is called often
function! s:NERDTree.render()
call self.ui.render()
endfunction
" vim: set sw=4 sts=4 et fdm=marker:

View File

@@ -11,16 +11,17 @@ function! s:Notifier.AddListener(event, funcname)
call add(listeners, a:funcname)
endfunction
function! s:Notifier.NotifyListeners(event, path, params)
let event = g:NERDTreeEvent.New(b:NERDTree, a:path, a:event, a:params)
function! s:Notifier.NotifyListeners(event, path, nerdtree, params)
let event = g:NERDTreeEvent.New(a:nerdtree, a:path, a:event, a:params)
for listener in s:Notifier.GetListenersForEvent(a:event)
call {listener}(event)
for Listener in s:Notifier.GetListenersForEvent(a:event)
let Callback = type(Listener) == type(function('tr')) ? Listener : function(Listener)
call Callback(event)
endfor
endfunction
function! s:Notifier.GetListenersMap()
if !exists("s:refreshListenersMap")
if !exists('s:refreshListenersMap')
let s:refreshListenersMap = {}
endif
return s:refreshListenersMap
@@ -32,4 +33,3 @@ function! s:Notifier.GetListenersForEvent(name)
endfunction
let g:NERDTreePathNotifier = deepcopy(s:Notifier)

View File

@@ -1,15 +1,20 @@
"CLASS: Opener
"============================================================
" ============================================================================
" CLASS: Opener
"
" The Opener class defines an API for 'opening' operations.
" ============================================================================
let s:Opener = {}
let g:NERDTreeOpener = s:Opener
"FUNCTION: s:Opener._bufInWindows(bnum){{{1
"[[STOLEN FROM VTREEEXPLORER.VIM]]
"Determine the number of windows open to this buffer number.
"Care of Yegappan Lakshman. Thanks!
" FUNCTION: s:Opener._bufInWindows(bnum) {{{1
" [[STOLEN FROM VTREEEXPLORER.VIM]]
" Determine the number of windows open to this buffer number.
" Care of Yegappan Lakshman. Thanks!
"
"Args:
"bnum: the subject buffers buffer number
" Args:
" bnum: the subject buffers buffer number
function! s:Opener._bufInWindows(bnum)
let cnt = 0
let winnum = 1
@@ -26,32 +31,32 @@ function! s:Opener._bufInWindows(bnum)
return cnt
endfunction
"FUNCTION: Opener._checkToCloseTree(newtab) {{{1
"Check the class options and global options (i.e. NERDTreeQuitOnOpen) to see
"if the tree should be closed now.
" FUNCTION: Opener._checkToCloseTree(newtab) {{{1
" Check the class options and global options (i.e. NERDTreeQuitOnOpen) to see
" if the tree should be closed now.
"
"Args:
"a:newtab - boolean. If set, only close the tree now if we are opening the
"target in a new tab. This is needed because we have to close tree before we
"leave the tab
" Args:
" a:newtab - boolean. If set, only close the tree now if we are opening the
" target in a new tab. This is needed because we have to close tree before we
" leave the tab
function! s:Opener._checkToCloseTree(newtab)
if self._keepopen
return
endif
if (a:newtab && self._where == 't') || !a:newtab
if (a:newtab && self._where ==# 't') || !a:newtab
call g:NERDTree.CloseIfQuitOnOpen()
endif
endfunction
"FUNCTION: s:Opener._firstUsableWindow(){{{1
"find the window number of the first normal window
" FUNCTION: s:Opener._firstUsableWindow() {{{1
" find the window number of the first normal window
function! s:Opener._firstUsableWindow()
let i = 1
while i <= winnr("$")
while i <= winnr('$')
let bnum = winbufnr(i)
if bnum != -1 && getbufvar(bnum, '&buftype') ==# ''
if bnum !=# -1 && getbufvar(bnum, '&buftype') ==# ''
\ && !getwinvar(i, '&previewwindow')
\ && (!getbufvar(bnum, '&modified') || &hidden)
return i
@@ -62,26 +67,26 @@ function! s:Opener._firstUsableWindow()
return -1
endfunction
"FUNCTION: Opener._gotoTargetWin() {{{1
" FUNCTION: Opener._gotoTargetWin() {{{1
function! s:Opener._gotoTargetWin()
if b:NERDTreeType ==# "secondary"
if self._where == 'v'
vsplit
elseif self._where == 'h'
split
elseif self._where == 't'
if b:NERDTree.isWinTree()
if self._where ==# 'v'
call self._newVSplit()
elseif self._where ==# 'h'
call self._newSplit()
elseif self._where ==# 't'
tabnew
endif
else
call self._checkToCloseTree(1)
if self._where == 'v'
if self._where ==# 'v'
call self._newVSplit()
elseif self._where == 'h'
elseif self._where ==# 'h'
call self._newSplit()
elseif self._where == 't'
elseif self._where ==# 't'
tabnew
elseif self._where == 'p'
elseif self._where ==# 'p'
call self._previousWindow()
endif
@@ -89,23 +94,23 @@ function! s:Opener._gotoTargetWin()
endif
endfunction
"FUNCTION: s:Opener._isWindowUsable(winnumber) {{{1
"Returns 0 if opening a file from the tree in the given window requires it to
"be split, 1 otherwise
" FUNCTION: s:Opener._isWindowUsable(winnumber) {{{1
" Returns 0 if opening a file from the tree in the given window requires it to
" be split, 1 otherwise
"
"Args:
"winnumber: the number of the window in question
" Args:
" winnumber: the number of the window in question
function! s:Opener._isWindowUsable(winnumber)
"gotta split if theres only one window (i.e. the NERD tree)
if winnr("$") ==# 1
if winnr('$') ==# 1
return 0
endif
let oldwinnr = winnr()
call nerdtree#exec(a:winnumber . "wincmd p")
let specialWindow = getbufvar("%", '&buftype') != '' || getwinvar('%', '&previewwindow')
call nerdtree#exec(a:winnumber . 'wincmd p', 1)
let specialWindow = getbufvar('%', '&buftype') !=# '' || getwinvar('%', '&previewwindow')
let modified = &modified
call nerdtree#exec(oldwinnr . "wincmd p")
call nerdtree#exec(oldwinnr . 'wincmd p', 1)
"if its a special window e.g. quickfix or another explorer plugin then we
"have to split
@@ -120,161 +125,132 @@ function! s:Opener._isWindowUsable(winnumber)
return !modified || self._bufInWindows(winbufnr(a:winnumber)) >= 2
endfunction
"FUNCTION: Opener.New(path, opts) {{{1
"Args:
"
"a:path: The path object that is to be opened.
"
"a:opts:
"
"A dictionary containing the following keys (all optional):
" 'where': Specifies whether the node should be opened in new split/tab or in
" the previous window. Can be either 'v' or 'h' or 't' (for open in
" new tab)
" 'reuse': if a window is displaying the file then jump the cursor there. Can
" 'all', 'currenttab' or empty to not reuse.
" 'keepopen': dont close the tree window
" 'stay': open the file, but keep the cursor in the tree win
" FUNCTION: Opener.New(path, opts) {{{1
" Instantiate a new NERDTreeOpener object.
" Args:
" a:path: the path object that is to be opened
" a:opts: a dictionary containing the following optional keys...
" 'where': specifies whether the node should be opened in new split, in
" a new tab or, in the last window; takes values 'v', 'h', or 't'
" 'reuse': if file is already shown in a window, jump there; takes values
" 'all', 'currenttab', or empty
" 'keepopen': boolean (0 or 1); if true, the tree window will not be closed
" 'stay': boolean (0 or 1); if true, remain in tree window after opening
function! s:Opener.New(path, opts)
let newObj = copy(self)
let l:newOpener = copy(self)
let newObj._path = a:path
let newObj._stay = nerdtree#has_opt(a:opts, 'stay')
let l:newOpener._keepopen = nerdtree#has_opt(a:opts, 'keepopen')
let l:newOpener._nerdtree = b:NERDTree
let l:newOpener._path = a:path
let l:newOpener._reuse = has_key(a:opts, 'reuse') ? a:opts['reuse'] : ''
let l:newOpener._stay = nerdtree#has_opt(a:opts, 'stay')
let l:newOpener._where = has_key(a:opts, 'where') ? a:opts['where'] : ''
if has_key(a:opts, 'reuse')
let newObj._reuse = a:opts['reuse']
else
let newObj._reuse = ''
endif
call l:newOpener._saveCursorPos()
let newObj._keepopen = nerdtree#has_opt(a:opts, 'keepopen')
let newObj._where = has_key(a:opts, 'where') ? a:opts['where'] : ''
let newObj._treetype = b:NERDTreeType
call newObj._saveCursorPos()
return newObj
return l:newOpener
endfunction
"FUNCTION: Opener._newSplit() {{{1
" FUNCTION: Opener._newSplit() {{{1
function! s:Opener._newSplit()
" Save the user's settings for splitbelow and splitright
let savesplitbelow=&splitbelow
let savesplitright=&splitright
" 'there' will be set to a command to move from the split window
" back to the explorer window
"
" 'back' will be set to a command to move from the explorer window
" back to the newly split window
"
" 'right' and 'below' will be set to the settings needed for
" splitbelow and splitright IF the explorer is the only window.
"
let there= g:NERDTreeWinPos ==# "left" ? "wincmd h" : "wincmd l"
let back = g:NERDTreeWinPos ==# "left" ? "wincmd l" : "wincmd h"
let right= g:NERDTreeWinPos ==# "left"
let below=0
" Attempt to go to adjacent window
call nerdtree#exec(back)
let onlyOneWin = (winnr("$") ==# 1)
" If no adjacent window, set splitright and splitbelow appropriately
let onlyOneWin = (winnr('$') ==# 1)
let savesplitright = &splitright
if onlyOneWin
let &splitright=right
let &splitbelow=below
else
" found adjacent window - invert split direction
let &splitright=!right
let &splitbelow=!below
let &splitright = (g:NERDTreeWinPos ==# 'left')
endif
let splitMode = onlyOneWin ? "vertical" : ""
" If only one window (ie. NERDTree), split vertically instead.
let splitMode = onlyOneWin ? 'vertical' : ''
" Open the new window
try
exec(splitMode." sp ")
call nerdtree#exec('wincmd p', 1)
call nerdtree#exec(splitMode . ' split',1)
catch /^Vim\%((\a\+)\)\=:E37/
call g:NERDTree.CursorToTreeWin()
throw "NERDTree.FileAlreadyOpenAndModifiedError: ". self._path.str() ." is already open and modified."
throw 'NERDTree.FileAlreadyOpenAndModifiedError: '. self._path.str() .' is already open and modified.'
catch /^Vim\%((\a\+)\)\=:/
"do nothing
endtry
"resize the tree window if no other window was open before
if onlyOneWin
let size = exists("b:NERDTreeOldWindowSize") ? b:NERDTreeOldWindowSize : g:NERDTreeWinSize
call nerdtree#exec(there)
exec("silent ". splitMode ." resize ". size)
call nerdtree#exec('wincmd p')
let size = exists('b:NERDTreeOldWindowSize') ? b:NERDTreeOldWindowSize : g:NERDTreeWinSize
call nerdtree#exec('wincmd p', 1)
call nerdtree#exec('silent '. splitMode .' resize '. size, 1)
call nerdtree#exec('wincmd p', 0)
endif
" Restore splitmode settings
let &splitbelow=savesplitbelow
let &splitright=savesplitright
endfunction
"FUNCTION: Opener._newVSplit() {{{1
" FUNCTION: Opener._newVSplit() {{{1
function! s:Opener._newVSplit()
let winwidth = winwidth(".")
if winnr("$")==#1
let winwidth = g:NERDTreeWinSize
let l:winwidth = winwidth('.')
let onlyOneWin = (winnr('$') ==# 1)
let savesplitright = &splitright
if onlyOneWin
let &splitright = (g:NERDTreeWinPos ==# 'left')
let l:winwidth = g:NERDTreeWinSize
endif
call nerdtree#exec("wincmd p")
vnew
call nerdtree#exec('wincmd p', 1)
call nerdtree#exec('vnew', 1)
"resize the nerd tree back to the original size
let l:currentWindowNumber = winnr()
" Restore the NERDTree to its original width.
call g:NERDTree.CursorToTreeWin()
exec("silent vertical resize ". winwidth)
call nerdtree#exec('wincmd p')
execute 'silent vertical resize ' . l:winwidth
call nerdtree#exec(l:currentWindowNumber . 'wincmd w', 0)
let &splitright=savesplitright
endfunction
"FUNCTION: Opener.open(target) {{{1
" FUNCTION: Opener.open(target) {{{1
function! s:Opener.open(target)
if self._path.isDirectory
call self._openDirectory(a:target)
else
call self._openFile()
return
endif
call self._openFile()
endfunction
"FUNCTION: Opener._openFile() {{{1
" FUNCTION: Opener._openFile() {{{1
function! s:Opener._openFile()
if !self._stay && !and(g:NERDTreeQuitOnOpen,1) && exists('b:NERDTreeZoomed') && b:NERDTreeZoomed
call b:NERDTree.ui.toggleZoom()
endif
if self._reuseWindow()
return
endif
call self._gotoTargetWin()
if self._treetype ==# "secondary"
call self._path.edit()
else
call self._path.edit()
if self._stay
call self._restoreCursorPos()
endif
if self._stay
silent call self._path.edit()
call self._restoreCursorPos()
return
endif
call self._path.edit()
endfunction
"FUNCTION: Opener._openDirectory(node) {{{1
" FUNCTION: Opener._openDirectory(node) {{{1
function! s:Opener._openDirectory(node)
if self._treetype ==# "secondary"
call self._gotoTargetWin()
call g:NERDTreeCreator.CreateSecondary(a:node.path.str())
call self._gotoTargetWin()
if self._nerdtree.isWinTree()
call g:NERDTreeCreator.CreateWindowTree(a:node.path.str())
else
call self._gotoTargetWin()
if empty(self._where)
call a:node.makeRoot()
call b:NERDTree.render()
call a:node.putCursorHere(0, 0)
elseif self._where == 't'
call g:NERDTreeCreator.CreatePrimary(a:node.path.str())
call b:NERDTree.changeRoot(a:node)
elseif self._where ==# 't'
call g:NERDTreeCreator.CreateTabTree(a:node.path.str())
else
call g:NERDTreeCreator.CreateSecondary(a:node.path.str())
call g:NERDTreeCreator.CreateWindowTree(a:node.path.str())
endif
endif
@@ -283,36 +259,36 @@ function! s:Opener._openDirectory(node)
endif
endfunction
"FUNCTION: Opener._previousWindow() {{{1
" FUNCTION: Opener._previousWindow() {{{1
function! s:Opener._previousWindow()
if !self._isWindowUsable(winnr("#")) && self._firstUsableWindow() ==# -1
if !self._isWindowUsable(winnr('#')) && self._firstUsableWindow() ==# -1
call self._newSplit()
else
try
if !self._isWindowUsable(winnr("#"))
call nerdtree#exec(self._firstUsableWindow() . "wincmd w")
if !self._isWindowUsable(winnr('#'))
call nerdtree#exec(self._firstUsableWindow() . 'wincmd w', 1)
else
call nerdtree#exec('wincmd p')
call nerdtree#exec('wincmd p', 1)
endif
catch /^Vim\%((\a\+)\)\=:E37/
call g:NERDTree.CursorToTreeWin()
throw "NERDTree.FileAlreadyOpenAndModifiedError: ". self._path.str() ." is already open and modified."
throw 'NERDTree.FileAlreadyOpenAndModifiedError: '. self._path.str() .' is already open and modified.'
catch /^Vim\%((\a\+)\)\=:/
echo v:exception
endtry
endif
endfunction
"FUNCTION: Opener._restoreCursorPos(){{{1
" FUNCTION: Opener._restoreCursorPos() {{{1
function! s:Opener._restoreCursorPos()
call nerdtree#exec('normal ' . self._tabnr . 'gt')
call nerdtree#exec(bufwinnr(self._bufnr) . 'wincmd w')
call nerdtree#exec(self._tabnr . 'tabnext', 1)
call nerdtree#exec(bufwinnr(self._bufnr) . 'wincmd w', 1)
endfunction
"FUNCTION: Opener._reuseWindow(){{{1
"put the cursor in the first window we find for this file
" FUNCTION: Opener._reuseWindow() {{{1
" put the cursor in the first window we find for this file
"
"return 1 if we were successful
" return 1 if we were successful
function! s:Opener._reuseWindow()
if empty(self._reuse)
return 0
@@ -320,13 +296,13 @@ function! s:Opener._reuseWindow()
"check the current tab for the window
let winnr = bufwinnr('^' . self._path.str() . '$')
if winnr != -1
call nerdtree#exec(winnr . "wincmd w")
if winnr !=# -1
call nerdtree#exec(winnr . 'wincmd w', 0)
call self._checkToCloseTree(0)
return 1
endif
if self._reuse == 'currenttab'
if self._reuse ==# 'currenttab'
return 0
endif
@@ -334,18 +310,18 @@ function! s:Opener._reuseWindow()
let tabnr = self._path.tabnr()
if tabnr
call self._checkToCloseTree(1)
call nerdtree#exec('normal! ' . tabnr . 'gt')
call nerdtree#exec(tabnr . 'tabnext', 1)
let winnr = bufwinnr('^' . self._path.str() . '$')
call nerdtree#exec(winnr . "wincmd w")
call nerdtree#exec(winnr . 'wincmd w', 0)
return 1
endif
return 0
endfunction
"FUNCTION: Opener._saveCursorPos(){{{1
" FUNCTION: Opener._saveCursorPos() {{{1
function! s:Opener._saveCursorPos()
let self._bufnr = bufnr("")
let self._bufnr = bufnr('')
let self._tabnr = tabpagenr()
endfunction

View File

@@ -1,51 +1,54 @@
"we need to use this number many times for sorting... so we calculate it only
"once here
let s:NERDTreeSortStarIndex = index(g:NERDTreeSortOrder, '*')
" used in formating sortKey, e.g. '%04d'
if exists("log10")
let s:sortKeyFormat = "%0" . float2nr(ceil(log10(len(g:NERDTreeSortOrder)))) . "d"
else
let s:sortKeyFormat = "%04d"
endif
" ============================================================================
" CLASS: Path
"
" The Path class provides an abstracted representation of a file system
" pathname. Various operations on pathnames are provided and a number of
" representations of a given path name can be accessed here.
" ============================================================================
"CLASS: Path
"============================================================
let s:Path = {}
let g:NERDTreePath = s:Path
"FUNCTION: Path.AbsolutePathFor(str) {{{1
function! s:Path.AbsolutePathFor(str)
let prependCWD = 0
" FUNCTION: Path.AbsolutePathFor(pathStr) {{{1
function! s:Path.AbsolutePathFor(pathStr)
let l:prependWorkingDir = 0
if nerdtree#runningWindows()
let prependCWD = a:str !~# '^.:\(\\\|\/\)' && a:str !~# '^\(\\\\\|\/\/\)'
let l:prependWorkingDir = a:pathStr !~# '^.:\(\\\|\/\)\?' && a:pathStr !~# '^\(\\\\\|\/\/\)'
else
let prependCWD = a:str !~# '^/'
let l:prependWorkingDir = a:pathStr !~# '^/'
endif
let toReturn = a:str
if prependCWD
let toReturn = getcwd() . s:Path.Slash() . a:str
let l:result = a:pathStr
if l:prependWorkingDir
let l:result = getcwd()
if l:result[-1:] ==# s:Path.Slash()
let l:result = l:result . a:pathStr
else
let l:result = l:result . s:Path.Slash() . a:pathStr
endif
endif
return toReturn
return l:result
endfunction
"FUNCTION: Path.bookmarkNames() {{{1
" FUNCTION: Path.bookmarkNames() {{{1
function! s:Path.bookmarkNames()
if !exists("self._bookmarkNames")
if !exists('self._bookmarkNames')
call self.cacheDisplayString()
endif
return self._bookmarkNames
endfunction
"FUNCTION: Path.cacheDisplayString() {{{1
" FUNCTION: Path.cacheDisplayString() {{{1
function! s:Path.cacheDisplayString() abort
let self.cachedDisplayString = self.flagSet.renderToString()
let self.cachedDisplayString .= self.getLastPathComponent(1)
let self.cachedDisplayString = g:NERDTreeNodeDelimiter . self.getLastPathComponent(1)
if self.isExecutable
let self.cachedDisplayString = self.cachedDisplayString . '*'
let self.cachedDisplayString = self.addDelimiter(self.cachedDisplayString) . '*'
endif
let self._bookmarkNames = []
@@ -54,20 +57,29 @@ function! s:Path.cacheDisplayString() abort
call add(self._bookmarkNames, i.name)
endif
endfor
if !empty(self._bookmarkNames)
let self.cachedDisplayString .= ' {' . join(self._bookmarkNames) . '}'
if !empty(self._bookmarkNames) && g:NERDTreeMarkBookmarks ==# 1
let self.cachedDisplayString = self.addDelimiter(self.cachedDisplayString) . ' {' . join(self._bookmarkNames) . '}'
endif
if self.isSymLink
let self.cachedDisplayString .= ' -> ' . self.symLinkDest
let self.cachedDisplayString = self.addDelimiter(self.cachedDisplayString) . ' -> ' . self.symLinkDest
endif
if self.isReadOnly
let self.cachedDisplayString .= ' [RO]'
let self.cachedDisplayString = self.addDelimiter(self.cachedDisplayString) . ' ['.g:NERDTreeGlyphReadOnly.']'
endif
endfunction
"FUNCTION: Path.changeToDir() {{{1
" FUNCTION: Path.addDelimiter() {{{1
function! s:Path.addDelimiter(line)
if a:line =~# '\(.*' . g:NERDTreeNodeDelimiter . '\)\{2}'
return a:line
else
return a:line . g:NERDTreeNodeDelimiter
endif
endfunction
" FUNCTION: Path.changeToDir() {{{1
function! s:Path.changeToDir()
let dir = self.str({'format': 'Cd'})
if self.isDirectory ==# 0
@@ -75,23 +87,28 @@ function! s:Path.changeToDir()
endif
try
execute "cd " . dir
call nerdtree#echo("CWD is now: " . getcwd())
if g:NERDTreeUseTCD && exists(':tcd') ==# 2
execute 'tcd ' . dir
call nerdtree#echo("Tab's CWD is now: " . getcwd())
else
execute 'cd ' . dir
call nerdtree#echo('CWD is now: ' . getcwd())
endif
catch
throw "NERDTree.PathChangeError: cannot change CWD to " . dir
throw 'NERDTree.PathChangeError: cannot change CWD to ' . dir
endtry
endfunction
"FUNCTION: Path.compareTo() {{{1
" FUNCTION: Path.compareTo() {{{1
"
"Compares this Path to the given path and returns 0 if they are equal, -1 if
"this Path is "less than" the given path, or 1 if it is "greater".
" Compares this Path to the given path and returns 0 if they are equal, -1 if
" this Path is 'less than' the given path, or 1 if it is 'greater'.
"
"Args:
"path: the path object to compare this to
" Args:
" path: the path object to compare this to
"
"Return:
"1, -1 or 0
" Return:
" 1, -1 or 0
function! s:Path.compareTo(path)
let thisPath = self.getLastPathComponent(1)
let thatPath = a:path.getLastPathComponent(1)
@@ -126,16 +143,16 @@ function! s:Path.compareTo(path)
endif
endfunction
"FUNCTION: Path.Create(fullpath) {{{1
" FUNCTION: Path.Create(fullpath) {{{1
"
"Factory method.
" Factory method.
"
"Creates a path object with the given path. The path is also created on the
"filesystem. If the path already exists, a NERDTree.Path.Exists exception is
"thrown. If any other errors occur, a NERDTree.Path exception is thrown.
" Creates a path object with the given path. The path is also created on the
" filesystem. If the path already exists, a NERDTree.Path.Exists exception is
" thrown. If any other errors occur, a NERDTree.Path exception is thrown.
"
"Args:
"fullpath: the full filesystem path to the file/dir to create
" Args:
" fullpath: the full filesystem path to the file/dir to create
function! s:Path.Create(fullpath)
"bail if the a:fullpath already exists
if isdirectory(a:fullpath) || filereadable(a:fullpath)
@@ -163,42 +180,46 @@ function! s:Path.Create(fullpath)
return s:Path.New(a:fullpath)
endfunction
"FUNCTION: Path.copy(dest) {{{1
" FUNCTION: Path.copy(dest) {{{1
"
"Copies the file/dir represented by this Path to the given location
" Copies the file/dir represented by this Path to the given location
"
"Args:
"dest: the location to copy this dir/file to
" Args:
" dest: the location to copy this dir/file to
function! s:Path.copy(dest)
if !s:Path.CopyingSupported()
throw "NERDTree.CopyingNotSupportedError: Copying is not supported on this OS"
throw 'NERDTree.CopyingNotSupportedError: Copying is not supported on this OS'
endif
call s:Path.createParentDirectories(a:dest)
let dest = s:Path.WinToUnixPath(a:dest)
if exists('g:NERDTreeCopyCmd')
let cmd_prefix = g:NERDTreeCopyCmd
else
let cmd_prefix = (self.isDirectory ? g:NERDTreeCopyDirCmd : g:NERDTreeCopyFileCmd)
endif
let cmd = g:NERDTreeCopyCmd . " " . escape(self.str(), self._escChars()) . " " . escape(dest, self._escChars())
let cmd = cmd_prefix . ' ' . escape(self.str(), self._escChars()) . ' ' . escape(a:dest, self._escChars())
let success = system(cmd)
if success != 0
throw "NERDTree.CopyError: Could not copy ''". self.str() ."'' to: '" . a:dest . "'"
if v:shell_error !=# 0
throw "NERDTree.CopyError: Could not copy '". self.str() ."' to: '" . a:dest . "'"
endif
endfunction
"FUNCTION: Path.CopyingSupported() {{{1
" FUNCTION: Path.CopyingSupported() {{{1
"
"returns 1 if copying is supported for this OS
" returns 1 if copying is supported for this OS
function! s:Path.CopyingSupported()
return exists('g:NERDTreeCopyCmd')
return exists('g:NERDTreeCopyCmd') || (exists('g:NERDTreeCopyDirCmd') && exists('g:NERDTreeCopyFileCmd'))
endfunction
"FUNCTION: Path.copyingWillOverwrite(dest) {{{1
" FUNCTION: Path.copyingWillOverwrite(dest) {{{1
"
"returns 1 if copy this path to the given location will cause files to
"overwritten
" returns 1 if copy this path to the given location will cause files to
" overwritten
"
"Args:
"dest: the location this path will be copied to
" Args:
" dest: the location this path will be copied to
function! s:Path.copyingWillOverwrite(dest)
if filereadable(a:dest)
return 1
@@ -212,13 +233,13 @@ function! s:Path.copyingWillOverwrite(dest)
endif
endfunction
"FUNCTION: Path.createParentDirectories(path) {{{1
" FUNCTION: Path.createParentDirectories(path) {{{1
"
"create parent directories for this path if needed
"without throwing any errors is those directories already exist
" create parent directories for this path if needed
" without throwing any errors if those directories already exist
"
"Args:
"path: full path of the node whose parent directories may need to be created
" Args:
" path: full path of the node whose parent directories may need to be created
function! s:Path.createParentDirectories(path)
let dir_path = fnamemodify(a:path, ':h')
if !isdirectory(dir_path)
@@ -226,24 +247,29 @@ function! s:Path.createParentDirectories(path)
endif
endfunction
"FUNCTION: Path.delete() {{{1
" FUNCTION: Path.delete() {{{1
"
"Deletes the file represented by this path.
"Deletion of directories is not supported
" Deletes the file or directory represented by this path.
"
"Throws NERDTree.Path.Deletion exceptions
" Throws NERDTree.Path.Deletion exceptions
function! s:Path.delete()
if self.isDirectory
let cmd = g:NERDTreeRemoveDirCmd . self.str({'escape': 1})
let success = system(cmd)
if v:shell_error != 0
if v:shell_error !=# 0
throw "NERDTree.PathDeletionError: Could not delete directory: '" . self.str() . "'"
endif
else
let success = delete(self.str())
if success != 0
if exists('g:NERDTreeRemoveFileCmd')
let cmd = g:NERDTreeRemoveFileCmd . self.str({'escape': 1})
let success = system(cmd)
else
let success = delete(self.str())
endif
if success !=# 0
throw "NERDTree.PathDeletionError: Could not delete file: '" . self.str() . "'"
endif
endif
@@ -255,32 +281,32 @@ function! s:Path.delete()
endfor
endfunction
"FUNCTION: Path.displayString() {{{1
" FUNCTION: Path.displayString() {{{1
"
"Returns a string that specifies how the path should be represented as a
"string
" Returns a string that specifies how the path should be represented as a
" string
function! s:Path.displayString()
if self.cachedDisplayString ==# ""
if self.cachedDisplayString ==# ''
call self.cacheDisplayString()
endif
return self.cachedDisplayString
endfunction
"FUNCTION: Path.edit() {{{1
" FUNCTION: Path.edit() {{{1
function! s:Path.edit()
exec "edit " . self.str({'format': 'Edit'})
exec 'edit ' . self.str({'format': 'Edit'})
endfunction
"FUNCTION: Path.extractDriveLetter(fullpath) {{{1
" FUNCTION: Path.extractDriveLetter(fullpath) {{{1
"
"If running windows, cache the drive letter for this path
" If running windows, cache the drive letter for this path
function! s:Path.extractDriveLetter(fullpath)
if nerdtree#runningWindows()
if a:fullpath =~ '^\(\\\\\|\/\/\)'
if a:fullpath =~# '^\(\\\\\|\/\/\)'
"For network shares, the 'drive' consists of the first two parts of the path, i.e. \\boxname\share
let self.drive = substitute(a:fullpath, '^\(\(\\\\\|\/\/\)[^\\\/]*\(\\\|\/\)[^\\\/]*\).*', '\1', '')
let self.drive = substitute(self.drive, '/', '\', "g")
let self.drive = substitute(self.drive, '/', '\', 'g')
else
let self.drive = substitute(a:fullpath, '\(^[a-zA-Z]:\).*', '\1', '')
endif
@@ -290,28 +316,28 @@ function! s:Path.extractDriveLetter(fullpath)
endfunction
"FUNCTION: Path.exists() {{{1
"return 1 if this path points to a location that is readable or is a directory
" FUNCTION: Path.exists() {{{1
" return 1 if this path points to a location that is readable or is a directory
function! s:Path.exists()
let p = self.str()
return filereadable(p) || isdirectory(p)
endfunction
"FUNCTION: Path._escChars() {{{1
" FUNCTION: Path._escChars() {{{1
function! s:Path._escChars()
if nerdtree#runningWindows()
return " `\|\"#%&,?()\*^<>"
return " `\|\"#%&,?()\*^<>$"
endif
return " \\`\|\"#%&,?()\*^<>[]"
return " \\`\|\"#%&,?()\*^<>[]$"
endfunction
"FUNCTION: Path.getDir() {{{1
" FUNCTION: Path.getDir() {{{1
"
"Returns this path if it is a directory, else this paths parent.
" Returns this path if it is a directory, else this paths parent.
"
"Return:
"a Path object
" Return:
" a Path object
function! s:Path.getDir()
if self.isDirectory
return self
@@ -320,12 +346,12 @@ function! s:Path.getDir()
endif
endfunction
"FUNCTION: Path.getParent() {{{1
" FUNCTION: Path.getParent() {{{1
"
"Returns a new path object for this paths parent
" Returns a new path object for this paths parent
"
"Return:
"a new Path object
" Return:
" a new Path object
function! s:Path.getParent()
if nerdtree#runningWindows()
let path = self.drive . '\' . join(self.pathSegments[0:-2], '\')
@@ -336,13 +362,13 @@ function! s:Path.getParent()
return s:Path.New(path)
endfunction
"FUNCTION: Path.getLastPathComponent(dirSlash) {{{1
" FUNCTION: Path.getLastPathComponent(dirSlash) {{{1
"
"Gets the last part of this path.
" Gets the last part of this path.
"
"Args:
"dirSlash: if 1 then a trailing slash will be added to the returned value for
"directory nodes.
" Args:
" dirSlash: if 1 then a trailing slash will be added to the returned value for
" directory nodes.
function! s:Path.getLastPathComponent(dirSlash)
if empty(self.pathSegments)
return ''
@@ -354,23 +380,61 @@ function! s:Path.getLastPathComponent(dirSlash)
return toReturn
endfunction
"FUNCTION: Path.getSortOrderIndex() {{{1
"returns the index of the pattern in g:NERDTreeSortOrder that this path matches
" FUNCTION: Path.getSortOrderIndex() {{{1
" returns the index of the pattern in g:NERDTreeSortOrder that this path matches
function! s:Path.getSortOrderIndex()
let i = 0
while i < len(g:NERDTreeSortOrder)
if self.getLastPathComponent(1) =~# g:NERDTreeSortOrder[i]
if g:NERDTreeSortOrder[i] !~? '\[\[-\?\(timestamp\|size\|extension\)\]\]' &&
\ self.getLastPathComponent(1) =~# g:NERDTreeSortOrder[i]
return i
endif
let i = i + 1
endwhile
return s:NERDTreeSortStarIndex
return index(g:NERDTreeSortOrder, '*')
endfunction
"FUNCTION: Path.getSortKey() {{{1
"returns a string used in compare function for sorting
" FUNCTION: Path._splitChunks(path) {{{1
" returns a list of path chunks
function! s:Path._splitChunks(path)
let chunks = split(a:path, '\(\D\+\|\d\+\)\zs')
let i = 0
while i < len(chunks)
"convert number literals to numbers
if match(chunks[i], '^\d\+$') ==# 0
let chunks[i] = str2nr(chunks[i])
endif
let i = i + 1
endwhile
return chunks
endfunction
" FUNCTION: Path.getSortKey() {{{1
" returns a key used in compare function for sorting
function! s:Path.getSortKey()
if !exists("self._sortKey")
if !exists('self._sortKey') || g:NERDTreeSortOrder !=# g:NERDTreeOldSortOrder
" Look for file metadata tags: [[timestamp]], [[extension]], [[size]]
let metadata = []
for tag in g:NERDTreeSortOrder
if tag =~? '\[\[-\?timestamp\]\]'
let metadata += [self.isDirectory ? 0 : getftime(self.str()) * (tag =~# '-' ? -1 : 1)]
elseif tag =~? '\[\[-\?size\]\]'
let metadata += [self.isDirectory ? 0 : getfsize(self.str()) * (tag =~# '-' ? -1 : 1)]
elseif tag =~? '\[\[extension\]\]'
let extension = matchstr(self.getLastPathComponent(0), '[^.]\+\.\zs[^.]\+$')
let metadata += [self.isDirectory ? '' : (extension ==# '' ? nr2char(str2nr('0x10ffff',16)) : extension)]
endif
endfor
if g:NERDTreeSortOrder[0] =~# '\[\[.*\]\]'
" Apply tags' sorting first if specified first.
let self._sortKey = metadata + [self.getSortOrderIndex()]
else
" Otherwise, do regex grouping first.
let self._sortKey = [self.getSortOrderIndex()] + metadata
endif
let path = self.getLastPathComponent(1)
if !g:NERDTreeSortHiddenFirst
let path = substitute(path, '^[._]', '', '')
@@ -378,21 +442,40 @@ function! s:Path.getSortKey()
if !g:NERDTreeCaseSensitiveSort
let path = tolower(path)
endif
let self._sortKey = printf(s:sortKeyFormat, self.getSortOrderIndex()) . path
endif
call extend(self._sortKey, (g:NERDTreeNaturalSort ? self._splitChunks(path) : [path]))
endif
return self._sortKey
endfunction
" FUNCTION: Path.isHiddenUnder(path) {{{1
function! s:Path.isHiddenUnder(path)
"FUNCTION: Path.isUnixHiddenFile() {{{1
"check for unix hidden files
if !self.isUnder(a:path)
return 0
endif
let l:startIndex = len(a:path.pathSegments)
let l:segments = self.pathSegments[l:startIndex : ]
for l:segment in l:segments
if l:segment =~# '^\.'
return 1
endif
endfor
return 0
endfunction
" FUNCTION: Path.isUnixHiddenFile() {{{1
" check for unix hidden files
function! s:Path.isUnixHiddenFile()
return self.getLastPathComponent(0) =~# '^\.'
endfunction
"FUNCTION: Path.isUnixHiddenPath() {{{1
"check for unix path with hidden components
" FUNCTION: Path.isUnixHiddenPath() {{{1
" check for unix path with hidden components
function! s:Path.isUnixHiddenPath()
if self.getLastPathComponent(0) =~# '^\.'
return 1
@@ -406,46 +489,47 @@ function! s:Path.isUnixHiddenPath()
endif
endfunction
"FUNCTION: Path.ignore() {{{1
"returns true if this path should be ignored
function! s:Path.ignore()
" FUNCTION: Path.ignore(nerdtree) {{{1
" returns true if this path should be ignored
function! s:Path.ignore(nerdtree)
"filter out the user specified paths to ignore
if b:NERDTreeIgnoreEnabled
if a:nerdtree.ui.isIgnoreFilterEnabled()
for i in g:NERDTreeIgnore
if self._ignorePatternMatches(i)
return 1
endif
endfor
for callback in g:NERDTree.PathFilters()
if {callback}({'path': self, 'nerdtree': b:NERDTree})
for Callback in g:NERDTree.PathFilters()
let Callback = type(Callback) ==# type(function('tr')) ? Callback : function(Callback)
if Callback({'path': self, 'nerdtree': a:nerdtree})
return 1
endif
endfor
endif
"dont show hidden files unless instructed to
if b:NERDTreeShowHidden ==# 0 && self.isUnixHiddenFile()
if !a:nerdtree.ui.getShowHidden() && self.isUnixHiddenFile()
return 1
endif
if b:NERDTreeShowFiles ==# 0 && self.isDirectory ==# 0
if a:nerdtree.ui.getShowFiles() ==# 0 && self.isDirectory ==# 0
return 1
endif
return 0
endfunction
"FUNCTION: Path._ignorePatternMatches(pattern) {{{1
"returns true if this path matches the given ignore pattern
" FUNCTION: Path._ignorePatternMatches(pattern) {{{1
" returns true if this path matches the given ignore pattern
function! s:Path._ignorePatternMatches(pattern)
let pat = a:pattern
if strpart(pat,len(pat)-7) == '[[dir]]'
if strpart(pat,len(pat)-7) ==# '[[dir]]'
if !self.isDirectory
return 0
endif
let pat = strpart(pat,0, len(pat)-7)
elseif strpart(pat,len(pat)-8) == '[[file]]'
elseif strpart(pat,len(pat)-8) ==# '[[file]]'
if self.isDirectory
return 0
endif
@@ -455,21 +539,33 @@ function! s:Path._ignorePatternMatches(pattern)
return self.getLastPathComponent(0) =~# pat
endfunction
"FUNCTION: Path.isUnder(path) {{{1
"return 1 if this path is somewhere under the given path in the filesystem.
" FUNCTION: Path.isAncestor(path) {{{1
" return 1 if this path is somewhere above the given path in the filesystem.
"
"a:path should be a dir
function! s:Path.isUnder(path)
if a:path.isDirectory == 0
" a:path should be a dir
function! s:Path.isAncestor(path)
if !self.isDirectory
return 0
endif
let this = self.str()
let that = a:path.str()
return stridx(this, that . s:Path.Slash()) == 0
return stridx(that, this) ==# 0
endfunction
"FUNCTION: Path.JoinPathStrings(...) {{{1
" FUNCTION: Path.isUnder(path) {{{1
" return 1 if this path is somewhere under the given path in the filesystem.
function! s:Path.isUnder(path)
if a:path.isDirectory ==# 0
return 0
endif
let this = self.str()
let that = a:path.str()
return stridx(this, that . s:Path.Slash()) ==# 0
endfunction
" FUNCTION: Path.JoinPathStrings(...) {{{1
function! s:Path.JoinPathStrings(...)
let components = []
for i in a:000
@@ -478,60 +574,74 @@ function! s:Path.JoinPathStrings(...)
return '/' . join(components, '/')
endfunction
"FUNCTION: Path.equals() {{{1
" FUNCTION: Path.equals() {{{1
"
"Determines whether 2 path objects are "equal".
"They are equal if the paths they represent are the same
" Determines whether 2 path objects are "equal".
" They are equal if the paths they represent are the same
"
"Args:
"path: the other path obj to compare this with
" Args:
" path: the other path obj to compare this with
function! s:Path.equals(path)
return self.str() ==# a:path.str()
if nerdtree#runningWindows()
return self.str() ==? a:path.str()
else
return self.str() ==# a:path.str()
endif
endfunction
"FUNCTION: Path.New() {{{1
"The Constructor for the Path object
function! s:Path.New(path)
let newPath = copy(self)
" FUNCTION: Path.New(pathStr) {{{1
function! s:Path.New(pathStr)
let l:newPath = copy(self)
call newPath.readInfoFromDisk(s:Path.AbsolutePathFor(a:path))
call l:newPath.readInfoFromDisk(s:Path.AbsolutePathFor(a:pathStr))
let newPath.cachedDisplayString = ""
let newPath.flagSet = g:NERDTreeFlagSet.New()
let l:newPath.cachedDisplayString = ''
let l:newPath.flagSet = g:NERDTreeFlagSet.New()
return newPath
return l:newPath
endfunction
"FUNCTION: Path.Slash() {{{1
"return the slash to use for the current OS
" FUNCTION: Path.Slash() {{{1
" Return the path separator used by the underlying file system. Special
" consideration is taken for the use of the 'shellslash' option on Windows
" systems.
function! s:Path.Slash()
return nerdtree#runningWindows() ? '\' : '/'
if nerdtree#runningWindows()
if exists('+shellslash') && &shellslash
return '/'
endif
return '\'
endif
return '/'
endfunction
"FUNCTION: Path.Resolve() {{{1
"Invoke the vim resolve() function and return the result
"This is necessary because in some versions of vim resolve() removes trailing
"slashes while in other versions it doesn't. This always removes the trailing
"slash
" FUNCTION: Path.Resolve() {{{1
" Invoke the vim resolve() function and return the result
" This is necessary because in some versions of vim resolve() removes trailing
" slashes while in other versions it doesn't. This always removes the trailing
" slash
function! s:Path.Resolve(path)
let tmp = resolve(a:path)
return tmp =~# '.\+/$' ? substitute(tmp, '/$', '', '') : tmp
endfunction
"FUNCTION: Path.readInfoFromDisk(fullpath) {{{1
" FUNCTION: Path.readInfoFromDisk(fullpath) {{{1
"
"
"Throws NERDTree.Path.InvalidArguments exception.
" Throws NERDTree.Path.InvalidArguments exception.
function! s:Path.readInfoFromDisk(fullpath)
call self.extractDriveLetter(a:fullpath)
let fullpath = s:Path.WinToUnixPath(a:fullpath)
if getftype(fullpath) ==# "fifo"
throw "NERDTree.InvalidFiletypeError: Cant handle FIFO files: " . a:fullpath
if getftype(fullpath) ==# 'fifo'
throw 'NERDTree.InvalidFiletypeError: Cant handle FIFO files: ' . a:fullpath
endif
let self.pathSegments = split(fullpath, '/')
let self.pathSegments = filter(split(fullpath, '/'), '!empty(v:val)')
let self.isReadOnly = 0
if isdirectory(a:fullpath)
@@ -540,7 +650,7 @@ function! s:Path.readInfoFromDisk(fullpath)
let self.isDirectory = 0
let self.isReadOnly = filewritable(a:fullpath) ==# 0
else
throw "NERDTree.InvalidArgumentsError: Invalid path = " . a:fullpath
throw 'NERDTree.InvalidArgumentsError: Invalid path = ' . a:fullpath
endif
let self.isExecutable = 0
@@ -555,7 +665,7 @@ function! s:Path.readInfoFromDisk(fullpath)
let hardPath = s:Path.Resolve(self.strTrunk()) . '/' . lastPathComponent
"if the last part of the path is a symlink then flag it as such
let self.isSymLink = (s:Path.Resolve(hardPath) != hardPath)
let self.isSymLink = (s:Path.Resolve(hardPath) !=# hardPath)
if self.isSymLink
let self.symLinkDest = s:Path.Resolve(fullpath)
@@ -572,29 +682,31 @@ function! s:Path.readInfoFromDisk(fullpath)
endif
endfunction
"FUNCTION: Path.refresh() {{{1
function! s:Path.refresh()
" FUNCTION: Path.refresh(nerdtree) {{{1
function! s:Path.refresh(nerdtree)
call self.readInfoFromDisk(self.str())
call g:NERDTreePathNotifier.NotifyListeners('refresh', self, {})
call g:NERDTreePathNotifier.NotifyListeners('refresh', self, a:nerdtree, {})
call self.cacheDisplayString()
endfunction
"FUNCTION: Path.refreshFlags() {{{1
function! s:Path.refreshFlags()
call g:NERDTreePathNotifier.NotifyListeners('refreshFlags', self, {})
" FUNCTION: Path.refreshFlags(nerdtree) {{{1
function! s:Path.refreshFlags(nerdtree)
call g:NERDTreePathNotifier.NotifyListeners('refreshFlags', self, a:nerdtree, {})
call self.cacheDisplayString()
endfunction
"FUNCTION: Path.rename() {{{1
" FUNCTION: Path.rename() {{{1
"
"Renames this node on the filesystem
" Renames this node on the filesystem
function! s:Path.rename(newPath)
if a:newPath ==# ''
throw "NERDTree.InvalidArgumentsError: Invalid newPath for renaming = ". a:newPath
throw 'NERDTree.InvalidArgumentsError: Invalid newPath for renaming = '. a:newPath
endif
call s:Path.createParentDirectories(a:newPath)
let success = rename(self.str(), a:newPath)
if success != 0
if success !=# 0
throw "NERDTree.PathRenameError: Could not rename: '" . self.str() . "'" . 'to:' . a:newPath
endif
call self.readInfoFromDisk(a:newPath)
@@ -606,31 +718,31 @@ function! s:Path.rename(newPath)
call g:NERDTreeBookmark.Write()
endfunction
"FUNCTION: Path.str() {{{1
" FUNCTION: Path.str() {{{1
" Return a string representation of this Path object.
"
"Returns a string representation of this Path
" Args:
" This function takes a single dictionary (optional) with keys and values that
" specify how the returned pathname should be formatted.
"
"Takes an optional dictionary param to specify how the output should be
"formatted.
"
"The dict may have the following keys:
" The dictionary may have the following keys:
" 'format'
" 'escape'
" 'truncateTo'
"
"The 'format' key may have a value of:
" 'Cd' - a string to be used with the :cd command
" 'Edit' - a string to be used with :e :sp :new :tabedit etc
" 'UI' - a string used in the NERD tree UI
" The 'format' key may have a value of:
" 'Cd' - a string to be used with ":cd" and similar commands
" 'Edit' - a string to be used with ":edit" and similar commands
" 'UI' - a string to be displayed in the NERDTree user interface
"
"The 'escape' key, if specified will cause the output to be escaped with
"shellescape()
" The 'escape' key, if specified, will cause the output to be escaped with
" Vim's internal "shellescape()" function.
"
"The 'truncateTo' key causes the resulting string to be truncated to the value
"'truncateTo' maps to. A '<' char will be prepended.
" The 'truncateTo' key shortens the length of the path to that given by the
" value associated with 'truncateTo'. A '<' is prepended.
function! s:Path.str(...)
let options = a:0 ? a:1 : {}
let toReturn = ""
let toReturn = ''
if has_key(options, 'format')
let format = options['format']
@@ -649,8 +761,10 @@ function! s:Path.str(...)
if has_key(options, 'truncateTo')
let limit = options['truncateTo']
if len(toReturn) > limit-1
let toReturn = toReturn[(len(toReturn)-limit+1):]
if strdisplaywidth(toReturn) > limit-1
while strdisplaywidth(toReturn) > limit-1 && strchars(toReturn) > 0
let toReturn = substitute(toReturn, '^.', '', '')
endwhile
if len(split(toReturn, '/')) > 1
let toReturn = '</' . join(split(toReturn, '/')[1:], '/') . '/'
else
@@ -662,46 +776,46 @@ function! s:Path.str(...)
return toReturn
endfunction
"FUNCTION: Path._strForUI() {{{1
" FUNCTION: Path._strForUI() {{{1
function! s:Path._strForUI()
let toReturn = '/' . join(self.pathSegments, '/')
if self.isDirectory && toReturn != '/'
if self.isDirectory && toReturn !=# '/'
let toReturn = toReturn . '/'
endif
return toReturn
endfunction
"FUNCTION: Path._strForCd() {{{1
"
" returns a string that can be used with :cd
" FUNCTION: Path._strForCd() {{{1
" Return a string representation of this Path that is suitable for use as an
" argument to Vim's internal ":cd" command.
function! s:Path._strForCd()
return escape(self.str(), self._escChars())
return fnameescape(self.str())
endfunction
"FUNCTION: Path._strForEdit() {{{1
"
"Return: the string for this path that is suitable to be used with the :edit
"command
" FUNCTION: Path._strForEdit() {{{1
" Return a string representation of this Path that is suitable for use as an
" argument to Vim's internal ":edit" command.
function! s:Path._strForEdit()
let p = escape(self.str(), self._escChars())
"make it relative
let p = fnamemodify(p, ':.')
" Make the path relative to the current working directory, if possible.
let l:result = fnamemodify(self.str(), ':.')
"handle the edge case where the file begins with a + (vim interprets
"the +foo in `:e +foo` as an option to :edit)
if p[0] == "+"
let p = '\' . p
" On Windows, the drive letter may be removed by "fnamemodify()". Add it
" back, if necessary.
if nerdtree#runningWindows() && l:result[0] ==# s:Path.Slash()
let l:result = self.drive . l:result
endif
if p ==# ''
let p = '.'
let l:result = fnameescape(l:result)
if empty(l:result)
let l:result = '.'
endif
return p
return l:result
endfunction
"FUNCTION: Path._strForGlob() {{{1
" FUNCTION: Path._strForGlob() {{{1
function! s:Path._strForGlob()
let lead = s:Path.Slash()
@@ -718,24 +832,22 @@ function! s:Path._strForGlob()
return toReturn
endfunction
"FUNCTION: Path._str() {{{1
"
"Gets the string path for this path object that is appropriate for the OS.
"EG, in windows c:\foo\bar
" in *nix /foo/bar
" FUNCTION: Path._str() {{{1
" Return the absolute pathname associated with this Path object. The pathname
" returned is appropriate for the underlying file system.
function! s:Path._str()
let lead = s:Path.Slash()
let l:separator = s:Path.Slash()
let l:leader = l:separator
"if we are running windows then slap a drive letter on the front
if nerdtree#runningWindows()
let lead = self.drive . '\'
let l:leader = self.drive . l:separator
endif
return lead . join(self.pathSegments, s:Path.Slash())
return l:leader . join(self.pathSegments, l:separator)
endfunction
"FUNCTION: Path.strTrunk() {{{1
"Gets the path without the last segment on the end.
" FUNCTION: Path.strTrunk() {{{1
" Gets the path without the last segment on the end.
function! s:Path.strTrunk()
return self.drive . '/' . join(self.pathSegments[0:-2], '/')
endfunction
@@ -748,7 +860,7 @@ function! s:Path.tabnr()
let str = self.str()
for t in range(tabpagenr('$'))
for b in tabpagebuflist(t+1)
if str == expand('#' . b . ':p')
if str ==# expand('#' . b . ':p')
return t+1
endif
endfor
@@ -756,13 +868,13 @@ function! s:Path.tabnr()
return 0
endfunction
"FUNCTION: Path.WinToUnixPath(pathstr){{{1
"Takes in a windows path and returns the unix equiv
" FUNCTION: Path.WinToUnixPath(pathstr){{{1
" Takes in a windows path and returns the unix equiv
"
"A class level method
" A class level method
"
"Args:
"pathstr: the windows path to convert
" Args:
" pathstr: the windows path to convert
function! s:Path.WinToUnixPath(pathstr)
if !nerdtree#runningWindows()
return a:pathstr
@@ -771,13 +883,13 @@ function! s:Path.WinToUnixPath(pathstr)
let toReturn = a:pathstr
"remove the x:\ of the front
let toReturn = substitute(toReturn, '^.*:\(\\\|/\)\?', '/', "")
let toReturn = substitute(toReturn, '^.*:\(\\\|/\)\?', '/', '')
"remove the \\ network share from the front
let toReturn = substitute(toReturn, '^\(\\\\\|\/\/\)[^\\\/]*\(\\\|\/\)[^\\\/]*\(\\\|\/\)\?', '/', "")
let toReturn = substitute(toReturn, '^\(\\\\\|\/\/\)[^\\\/]*\(\\\|\/\)[^\\\/]*\(\\\|\/\)\?', '/', '')
"convert all \ chars to /
let toReturn = substitute(toReturn, '\', '/', "g")
let toReturn = substitute(toReturn, '\', '/', 'g')
return toReturn
endfunction

View File

@@ -1,36 +1,47 @@
"CLASS: TreeDirNode
"A subclass of NERDTreeFileNode.
" ============================================================================
" CLASS: TreeDirNode
"
"The 'composite' part of the file/dir composite.
"============================================================
" A subclass of NERDTreeFileNode.
"
" The 'composite' part of the file/dir composite.
" ============================================================================
let s:TreeDirNode = copy(g:NERDTreeFileNode)
let g:NERDTreeDirNode = s:TreeDirNode
"FUNCTION: TreeDirNode.AbsoluteTreeRoot(){{{1
"class method that returns the highest cached ancestor of the current root
" FUNCTION: TreeDirNode.AbsoluteTreeRoot(){{{1
" Class method that returns the highest cached ancestor of the current root.
function! s:TreeDirNode.AbsoluteTreeRoot()
let currentNode = b:NERDTreeRoot
while currentNode.parent != {}
let currentNode = b:NERDTree.root
while currentNode.parent !=# {}
let currentNode = currentNode.parent
endwhile
return currentNode
endfunction
"FUNCTION: TreeDirNode.activate([options]) {{{1
unlet s:TreeDirNode.activate
" FUNCTION: TreeDirNode.activate([options]) {{{1
function! s:TreeDirNode.activate(...)
let opts = a:0 ? a:1 : {}
call self.toggleOpen(opts)
call b:NERDTree.render()
call self.putCursorHere(0, 0)
let l:options = (a:0 > 0) ? a:1 : {}
call self.toggleOpen(l:options)
" Note that we only re-render the NERDTree for this node if we did NOT
" create a new node and render it in a new window or tab. In the latter
" case, rendering the NERDTree for this node could overwrite the text of
" the new NERDTree!
if !has_key(l:options, 'where') || empty(l:options['where'])
call self.getNerdtree().render()
call self.putCursorHere(0, 0)
endif
endfunction
"FUNCTION: TreeDirNode.addChild(treenode, inOrder) {{{1
"Adds the given treenode to the list of children for this node
" FUNCTION: TreeDirNode.addChild(treenode, inOrder) {{{1
" Adds the given treenode to the list of children for this node
"
"Args:
"-treenode: the node to add
"-inOrder: 1 if the new node should be inserted in sorted order
" Args:
" -treenode: the node to add
" -inOrder: 1 if the new node should be inserted in sorted order
function! s:TreeDirNode.addChild(treenode, inOrder)
call add(self.children, a:treenode)
let a:treenode.parent = self
@@ -40,44 +51,76 @@ function! s:TreeDirNode.addChild(treenode, inOrder)
endif
endfunction
"FUNCTION: TreeDirNode.close() {{{1
"Closes this directory
" FUNCTION: TreeDirNode.close() {{{1
" Mark this TreeDirNode as closed.
function! s:TreeDirNode.close()
let self.isOpen = 0
" Close all directories in this directory node's cascade. This is
" necessary to ensure consistency when cascades are rendered.
for l:dirNode in self.getCascade()
let l:dirNode.isOpen = 0
endfor
endfunction
"FUNCTION: TreeDirNode.closeChildren() {{{1
"Closes all the child dir nodes of this node
" FUNCTION: TreeDirNode.closeChildren() {{{1
" Recursively close any directory nodes that are descendants of this node.
function! s:TreeDirNode.closeChildren()
for i in self.children
if i.path.isDirectory
call i.close()
call i.closeChildren()
for l:child in self.children
if l:child.path.isDirectory
call l:child.close()
call l:child.closeChildren()
endif
endfor
endfunction
"FUNCTION: TreeDirNode.createChild(path, inOrder) {{{1
"Instantiates a new child node for this node with the given path. The new
"nodes parent is set to this node.
" FUNCTION: TreeDirNode.createChild(path, inOrder) {{{1
" Instantiates a new child node for this node with the given path. The new
" nodes parent is set to this node.
"
"Args:
"path: a Path object that this node will represent/contain
"inOrder: 1 if the new node should be inserted in sorted order
" Args:
" path: a Path object that this node will represent/contain
" inOrder: 1 if the new node should be inserted in sorted order
"
"Returns:
"the newly created node
" Returns:
" the newly created node
function! s:TreeDirNode.createChild(path, inOrder)
let newTreeNode = g:NERDTreeFileNode.New(a:path)
let newTreeNode = g:NERDTreeFileNode.New(a:path, self.getNerdtree())
call self.addChild(newTreeNode, a:inOrder)
return newTreeNode
endfunction
"FUNCTION: TreeDirNode.findNode(path) {{{1
"Will find one of the children (recursively) that has the given path
" FUNCTION: TreeDirNode.displayString() {{{1
" Assemble and return a string that can represent this TreeDirNode object in
" the NERDTree window.
function! s:TreeDirNode.displayString()
let l:result = ''
" Build a label that identifies this TreeDirNode.
let l:label = ''
let l:cascade = self.getCascade()
for l:dirNode in l:cascade
let l:next = l:dirNode.path.displayString()
let l:label .= l:label ==# '' ? l:next : substitute(l:next,'^.','','')
endfor
" Select the appropriate open/closed status indicator symbol.
if l:cascade[-1].isOpen
let l:symbol = g:NERDTreeDirArrowCollapsible
else
let l:symbol = g:NERDTreeDirArrowExpandable
endif
let l:flags = l:cascade[-1].path.flagSet.renderToString()
let l:result = l:symbol . ' ' . l:flags . l:label
return l:result
endfunction
" FUNCTION: TreeDirNode.findNode(path) {{{1
" Will find one of the children (recursively) that has the given path
"
"Args:
"path: a path object
" Args:
" path: a path object
unlet s:TreeDirNode.findNode
function! s:TreeDirNode.findNode(path)
if a:path.equals(self.path)
@@ -90,7 +133,7 @@ function! s:TreeDirNode.findNode(path)
if self.path.isDirectory
for i in self.children
let retVal = i.findNode(a:path)
if retVal != {}
if retVal !=# {}
return retVal
endif
endfor
@@ -98,20 +141,59 @@ function! s:TreeDirNode.findNode(path)
return {}
endfunction
"FUNCTION: TreeDirNode.getChildCount() {{{1
"Returns the number of children this node has
" FUNCTION: TreeDirNode.getCascade() {{{1
" Return an array of dir nodes (starting from self) that can be cascade opened.
function! s:TreeDirNode.getCascade()
if !self.isCascadable()
return [self]
endif
let vc = self.getVisibleChildren()
let visChild = vc[0]
return [self] + visChild.getCascade()
endfunction
" FUNCTION: TreeDirNode.getCascadeRoot() {{{1
" Return the first directory node in the cascade in which this directory node
" is rendered.
function! s:TreeDirNode.getCascadeRoot()
" Don't search above the current NERDTree root node.
if self.isRoot()
return self
endif
let l:cascadeRoot = self
let l:parent = self.parent
while !empty(l:parent) && !l:parent.isRoot()
if index(l:parent.getCascade(), self) ==# -1
break
endif
let l:cascadeRoot = l:parent
let l:parent = l:parent.parent
endwhile
return l:cascadeRoot
endfunction
" FUNCTION: TreeDirNode.getChildCount() {{{1
" Returns the number of children this node has
function! s:TreeDirNode.getChildCount()
return len(self.children)
endfunction
"FUNCTION: TreeDirNode.getChild(path) {{{1
"Returns child node of this node that has the given path or {} if no such node
"exists.
" FUNCTION: TreeDirNode.getChild(path) {{{1
" Returns child node of this node that has the given path or {} if no such node
" exists.
"
"This function doesnt not recurse into child dir nodes
" This function doesnt not recurse into child dir nodes
"
"Args:
"path: a path object
" Args:
" path: a path object
function! s:TreeDirNode.getChild(path)
if stridx(a:path.str(), self.path.str(), 0) ==# -1
return {}
@@ -126,28 +208,29 @@ function! s:TreeDirNode.getChild(path)
endfunction
"FUNCTION: TreeDirNode.getChildByIndex(indx, visible) {{{1
"returns the child at the given index
"Args:
"indx: the index to get the child from
"visible: 1 if only the visible children array should be used, 0 if all the
"children should be searched.
" FUNCTION: TreeDirNode.getChildByIndex(indx, visible) {{{1
" returns the child at the given index
"
" Args:
" indx: the index to get the child from
" visible: 1 if only the visible children array should be used, 0 if all the
" children should be searched.
function! s:TreeDirNode.getChildByIndex(indx, visible)
let array_to_search = a:visible? self.getVisibleChildren() : self.children
if a:indx > len(array_to_search)
throw "NERDTree.InvalidArgumentsError: Index is out of bounds."
throw 'NERDTree.InvalidArgumentsError: Index is out of bounds.'
endif
return array_to_search[a:indx]
endfunction
"FUNCTION: TreeDirNode.getChildIndex(path) {{{1
"Returns the index of the child node of this node that has the given path or
"-1 if no such node exists.
" FUNCTION: TreeDirNode.getChildIndex(path) {{{1
" Returns the index of the child node of this node that has the given path or
" -1 if no such node exists.
"
"This function doesnt not recurse into child dir nodes
" This function doesnt not recurse into child dir nodes
"
"Args:
"path: a path object
" Args:
" path: a path object
function! s:TreeDirNode.getChildIndex(path)
if stridx(a:path.str(), self.path.str(), 0) ==# -1
return -1
@@ -171,13 +254,94 @@ function! s:TreeDirNode.getChildIndex(path)
return -1
endfunction
"FUNCTION: TreeDirNode.GetSelected() {{{1
"Returns the current node if it is a dir node, or else returns the current
"nodes parent
" FUNCTION: TreeDirNode.getDirChildren() {{{1
" Return a list of all child nodes from 'self.children' that are of type
" TreeDirNode. This function supports http://github.com/scrooloose/nerdtree-project-plugin.git.
function! s:TreeDirNode.getDirChildren()
return filter(copy(self.children), 'v:val.path.isDirectory ==# 1')
endfunction
" FUNCTION: TreeDirNode._glob(pattern, all) {{{1
" Return a list of strings naming the descendants of the directory in this
" TreeDirNode object that match the specified glob pattern.
"
" Args:
" pattern: (string) the glob pattern to apply
" all: (0 or 1) if 1, include '.' and '..' if they match 'pattern'; if 0,
" always exclude them
"
" Note: If the pathnames in the result list are below the working directory,
" they are returned as pathnames relative to that directory. This is because
" this function, internally, attempts to obey 'wildignore' rules that use
" relative paths.
function! s:TreeDirNode._glob(pattern, all)
" Construct a path specification such that globpath() will return
" relative pathnames, if possible.
if self.path.str() ==# getcwd()
let l:pathSpec = ','
else
let l:pathSpec = escape(fnamemodify(self.path.str({'format': 'Glob'}), ':.'), ',')
" On Windows, the drive letter may be removed by fnamemodify().
if nerdtree#runningWindows() && l:pathSpec[0] ==# g:NERDTreePath.Slash()
let l:pathSpec = self.path.drive . l:pathSpec
endif
endif
let l:globList = []
" See ':h version7.txt' and ':h version8.txt' for details on the
" development of the glob() and globpath() functions.
if v:version > 704 || (v:version ==# 704 && has('patch654'))
let l:globList = globpath(l:pathSpec, a:pattern, !g:NERDTreeRespectWildIgnore, 1, 0)
elseif v:version ==# 704 && has('patch279')
let l:globList = globpath(l:pathSpec, a:pattern, !g:NERDTreeRespectWildIgnore, 1)
elseif v:version > 702 || (v:version ==# 702 && has('patch051'))
let l:globString = globpath(l:pathSpec, a:pattern, !g:NERDTreeRespectWildIgnore)
let l:globList = split(l:globString, "\n")
else
let l:globString = globpath(l:pathSpec, a:pattern)
let l:globList = split(l:globString, "\n")
endif
" If a:all is false, filter '.' and '..' from the output.
if !a:all
let l:toRemove = []
for l:file in l:globList
let l:tail = fnamemodify(l:file, ':t')
" If l:file has a trailing slash, then its :tail will be ''. Use
" :h to drop the slash and the empty string after it; then use :t
" to get the directory name.
if l:tail ==# ''
let l:tail = fnamemodify(l:file, ':h:t')
endif
if l:tail ==# '.' || l:tail ==# '..'
call add(l:toRemove, l:file)
if len(l:toRemove) ==# 2
break
endif
endif
endfor
for l:file in l:toRemove
call remove(l:globList, index(l:globList, l:file))
endfor
endif
return l:globList
endfunction
" FUNCTION: TreeDirNode.GetSelected() {{{1
" Returns the current node if it is a dir node, or else returns the current
" nodes parent
unlet s:TreeDirNode.GetSelected
function! s:TreeDirNode.GetSelected()
let currentDir = g:NERDTreeFileNode.GetSelected()
if currentDir != {} && !currentDir.isRoot()
if currentDir !=# {} && !currentDir.isRoot()
if currentDir.path.isDirectory ==# 0
let currentDir = currentDir.parent
endif
@@ -185,101 +349,106 @@ function! s:TreeDirNode.GetSelected()
return currentDir
endfunction
"FUNCTION: TreeDirNode.getVisibleChildCount() {{{1
"Returns the number of visible children this node has
" FUNCTION: TreeDirNode.getVisibleChildCount() {{{1
" Returns the number of visible children this node has
function! s:TreeDirNode.getVisibleChildCount()
return len(self.getVisibleChildren())
endfunction
"FUNCTION: TreeDirNode.getVisibleChildren() {{{1
"Returns a list of children to display for this node, in the correct order
" FUNCTION: TreeDirNode.getVisibleChildren() {{{1
" Returns a list of children to display for this node, in the correct order
"
"Return:
"an array of treenodes
" Return:
" an array of treenodes
function! s:TreeDirNode.getVisibleChildren()
let toReturn = []
for i in self.children
if i.path.ignore() ==# 0
if i.path.ignore(self.getNerdtree()) ==# 0
call add(toReturn, i)
endif
endfor
return toReturn
endfunction
"FUNCTION: TreeDirNode.hasVisibleChildren() {{{1
"returns 1 if this node has any childre, 0 otherwise..
" FUNCTION: TreeDirNode.hasVisibleChildren() {{{1
" returns 1 if this node has any childre, 0 otherwise..
function! s:TreeDirNode.hasVisibleChildren()
return self.getVisibleChildCount() != 0
return self.getVisibleChildCount() !=# 0
endfunction
"FUNCTION: TreeDirNode._initChildren() {{{1
"Removes all childen from this node and re-reads them
" FUNCTION: TreeDirNode.isCascadable() {{{1
" true if this dir has only one visible child that is also a dir
" false if this dir is bookmarked or symlinked. Why? Two reasons:
" 1. If cascaded, we don't know which dir is bookmarked or is a symlink.
" 2. If the parent is a symlink or is bookmarked, you end up with unparsable
" text, and NERDTree cannot get the path of any child node.
function! s:TreeDirNode.isCascadable()
if g:NERDTreeCascadeSingleChildDir ==# 0
return 0
endif
if self.path.isSymLink
return 0
endif
for i in g:NERDTreeBookmark.Bookmarks()
if i.path.equals(self.path)
return 0
endif
endfor
let c = self.getVisibleChildren()
return len(c) ==# 1 && c[0].path.isDirectory
endfunction
" FUNCTION: TreeDirNode._initChildren() {{{1
" Removes all childen from this node and re-reads them
"
"Args:
"silent: 1 if the function should not echo any "please wait" messages for
"large directories
" Args:
" silent: 1 if the function should not echo any 'please wait' messages for
" large directories
"
"Return: the number of child nodes read
" Return: the number of child nodes read
function! s:TreeDirNode._initChildren(silent)
"remove all the current child nodes
let self.children = []
"get an array of all the files in the nodes dir
let dir = self.path
let globDir = dir.str({'format': 'Glob'})
if version >= 703
let filesStr = globpath(globDir, '*', !g:NERDTreeRespectWildIgnore) . "\n" . globpath(globDir, '.*', !g:NERDTreeRespectWildIgnore)
else
let filesStr = globpath(globDir, '*') . "\n" . globpath(globDir, '.*')
endif
let files = split(filesStr, "\n")
let files = self._glob('*', 1) + self._glob('.*', 0)
if !a:silent && len(files) > g:NERDTreeNotificationThreshold
call nerdtree#echo("Please wait, caching a large dir ...")
call nerdtree#echo('Please wait, caching a large dir ...')
endif
let invalidFilesFound = 0
for i in files
"filter out the .. and . directories
"Note: we must match .. AND ../ since sometimes the globpath returns
"../ for path with strange chars (eg $)
if i[len(i)-3:2] != ".." && i[len(i)-2:2] != ".." &&
\ i[len(i)-2:1] != "." && i[len(i)-1] != "."
"put the next file in a new node and attach it
try
let path = g:NERDTreePath.New(i)
call self.createChild(path, 0)
call g:NERDTreePathNotifier.NotifyListeners('init', path, {})
catch /^NERDTree.\(InvalidArguments\|InvalidFiletype\)Error/
let invalidFilesFound += 1
endtry
endif
try
let path = g:NERDTreePath.New(i)
call self.createChild(path, 0)
call g:NERDTreePathNotifier.NotifyListeners('init', path, self.getNerdtree(), {})
catch /^NERDTree.\(InvalidArguments\|InvalidFiletype\)Error/
let invalidFilesFound += 1
endtry
endfor
call self.sortChildren()
if !a:silent && len(files) > g:NERDTreeNotificationThreshold
call nerdtree#echo("Please wait, caching a large dir ... DONE (". self.getChildCount() ." nodes cached).")
endif
call nerdtree#echo('')
if invalidFilesFound
call nerdtree#echoWarning(invalidFilesFound . " file(s) could not be loaded into the NERD tree")
call nerdtree#echoWarning(invalidFilesFound . ' file(s) could not be loaded into the NERD tree')
endif
return self.getChildCount()
endfunction
"FUNCTION: TreeDirNode.New(path) {{{1
"Returns a new TreeNode object with the given path and parent
" FUNCTION: TreeDirNode.New(path, nerdtree) {{{1
" Return a new TreeDirNode object with the given path and parent.
"
"Args:
"path: a path object representing the full filesystem path to the file/dir that the node represents
unlet s:TreeDirNode.New
function! s:TreeDirNode.New(path)
if a:path.isDirectory != 1
throw "NERDTree.InvalidArgumentsError: A TreeDirNode object must be instantiated with a directory Path object."
" Args:
" path: dir that the node represents
" nerdtree: the tree the node belongs to
function! s:TreeDirNode.New(path, nerdtree)
if a:path.isDirectory !=# 1
throw 'NERDTree.InvalidArgumentsError: A TreeDirNode object must be instantiated with a directory Path object.'
endif
let newTreeNode = copy(self)
@@ -289,35 +458,50 @@ function! s:TreeDirNode.New(path)
let newTreeNode.children = []
let newTreeNode.parent = {}
let newTreeNode._nerdtree = a:nerdtree
return newTreeNode
endfunction
"FUNCTION: TreeDirNode.open([opts]) {{{1
"Open the dir in the current tree or in a new tree elsewhere.
"
"If opening in the current tree, return the number of cached nodes.
unlet s:TreeDirNode.open
" FUNCTION: TreeDirNode.open([options]) {{{1
" Open this directory node in the current tree or elsewhere if special options
" are provided. Return 0 if options were processed. Otherwise, return the
" number of new cached nodes.
function! s:TreeDirNode.open(...)
let opts = a:0 ? a:1 : {}
let l:options = a:0 ? a:1 : {}
if has_key(opts, 'where') && !empty(opts['where'])
let opener = g:NERDTreeOpener.New(self.path, opts)
call opener.open(self)
else
let self.isOpen = 1
if self.children ==# []
return self._initChildren(0)
else
return 0
endif
" If special options were specified, process them and return.
if has_key(l:options, 'where') && !empty(l:options['where'])
let l:opener = g:NERDTreeOpener.New(self.path, l:options)
call l:opener.open(self)
return 0
endif
" Open any ancestors of this node that render within the same cascade.
let l:parent = self.parent
while !empty(l:parent) && !l:parent.isRoot()
if index(l:parent.getCascade(), self) >= 0
let l:parent.isOpen = 1
let l:parent = l:parent.parent
else
break
endif
endwhile
let self.isOpen = 1
let l:numChildrenCached = 0
if empty(self.children)
let l:numChildrenCached = self._initChildren(0)
endif
return l:numChildrenCached
endfunction
"FUNCTION: TreeDirNode.openAlong([opts]) {{{1
"recursive open the dir if it has only one directory child.
" FUNCTION: TreeDirNode.openAlong([opts]) {{{1
" recursive open the dir if it has only one directory child.
"
"return the level of opened directories.
" return the level of opened directories.
function! s:TreeDirNode.openAlong(...)
let opts = a:0 ? a:1 : {}
let level = 0
@@ -326,7 +510,7 @@ function! s:TreeDirNode.openAlong(...)
while node.path.isDirectory
call node.open(opts)
let level += 1
if node.getVisibleChildCount() == 1
if node.getVisibleChildCount() ==# 1
let node = node.getChildByIndex(0, 1)
else
break
@@ -336,101 +520,66 @@ function! s:TreeDirNode.openAlong(...)
endfunction
" FUNCTION: TreeDirNode.openExplorer() {{{1
" opens an explorer window for this node in the previous window (could be a
" nerd tree or a netrw)
" Open an explorer window for this node in the previous window. The explorer
" can be a NERDTree window or a netrw window.
function! s:TreeDirNode.openExplorer()
call self.open({'where': 'p'})
execute 'wincmd p'
execute 'edit '.self.path.str({'format':'Edit'})
endfunction
"FUNCTION: TreeDirNode.openInNewTab(options) {{{1
" FUNCTION: TreeDirNode.openInNewTab(options) {{{1
unlet s:TreeDirNode.openInNewTab
function! s:TreeDirNode.openInNewTab(options)
call nerdtree#deprecated('TreeDirNode.openInNewTab', 'is deprecated, use open() instead')
call self.open({'where': 't'})
endfunction
"FUNCTION: TreeDirNode._openInNewTab() {{{1
" FUNCTION: TreeDirNode._openInNewTab() {{{1
function! s:TreeDirNode._openInNewTab()
tabnew
call g:NERDTreeCreator.CreatePrimary(self.path.str())
call g:NERDTreeCreator.CreateTabTree(self.path.str())
endfunction
"FUNCTION: TreeDirNode.openRecursively() {{{1
"Opens this treenode and all of its children whose paths arent 'ignored'
"because of the file filters.
"
"This method is actually a wrapper for the OpenRecursively2 method which does
"the work.
" FUNCTION: TreeDirNode.openRecursively() {{{1
" Open this directory node and any descendant directory nodes whose pathnames
" are not ignored.
function! s:TreeDirNode.openRecursively()
call self._openRecursively2(1)
endfunction
silent call self.open()
"FUNCTION: TreeDirNode._openRecursively2() {{{1
"Opens this all children of this treenode recursively if either:
" *they arent filtered by file filters
" *a:forceOpen is 1
"
"Args:
"forceOpen: 1 if this node should be opened regardless of file filters
function! s:TreeDirNode._openRecursively2(forceOpen)
if self.path.ignore() ==# 0 || a:forceOpen
let self.isOpen = 1
if self.children ==# []
call self._initChildren(1)
for l:child in self.children
if l:child.path.isDirectory && !l:child.path.ignore(l:child.getNerdtree())
call l:child.openRecursively()
endif
for i in self.children
if i.path.isDirectory ==# 1
call i._openRecursively2(0)
endif
endfor
endif
endfor
endfunction
"FUNCTION: TreeDirNode.refresh() {{{1
unlet s:TreeDirNode.refresh
" FUNCTION: TreeDirNode.refresh() {{{1
function! s:TreeDirNode.refresh()
call self.path.refresh()
call self.path.refresh(self.getNerdtree())
"if this node was ever opened, refresh its children
if self.isOpen || !empty(self.children)
"go thru all the files/dirs under this node
let files = self._glob('*', 1) + self._glob('.*', 0)
let newChildNodes = []
let invalidFilesFound = 0
let dir = self.path
let globDir = dir.str({'format': 'Glob'})
let filesStr = globpath(globDir, '*') . "\n" . globpath(globDir, '.*')
let files = split(filesStr, "\n")
for i in files
"filter out the .. and . directories
"Note: we must match .. AND ../ cos sometimes the globpath returns
"../ for path with strange chars (eg $)
"if i !~# '\/\.\.\/\?$' && i !~# '\/\.\/\?$'
try
"create a new path and see if it exists in this nodes children
let path = g:NERDTreePath.New(i)
let newNode = self.getChild(path)
if newNode !=# {}
call newNode.refresh()
call add(newChildNodes, newNode)
" Regular expression is too expensive. Use simply string comparison
" instead
if i[len(i)-3:2] != ".." && i[len(i)-2:2] != ".." &&
\ i[len(i)-2:1] != "." && i[len(i)-1] != "."
try
"create a new path and see if it exists in this nodes children
let path = g:NERDTreePath.New(i)
let newNode = self.getChild(path)
if newNode != {}
call newNode.refresh()
call add(newChildNodes, newNode)
"the node doesnt exist so create it
else
let newNode = g:NERDTreeFileNode.New(path)
let newNode.parent = self
call add(newChildNodes, newNode)
endif
catch /^NERDTree.\(InvalidArguments\|InvalidFiletype\)Error/
let invalidFilesFound = 1
endtry
endif
"the node doesnt exist so create it
else
let newNode = g:NERDTreeFileNode.New(path, self.getNerdtree())
let newNode.parent = self
call add(newChildNodes, newNode)
endif
catch /^NERDTree.\(InvalidArguments\|InvalidFiletype\)Error/
let invalidFilesFound = 1
endtry
endfor
"swap this nodes children out for the children we just read/refreshed
@@ -438,40 +587,49 @@ function! s:TreeDirNode.refresh()
call self.sortChildren()
if invalidFilesFound
call nerdtree#echoWarning("some files could not be loaded into the NERD tree")
call nerdtree#echoWarning('some files could not be loaded into the NERD tree')
endif
endif
endfunction
"FUNCTION: TreeDirNode.refreshFlags() {{{1
" FUNCTION: TreeDirNode.refreshFlags() {{{1
unlet s:TreeDirNode.refreshFlags
function! s:TreeDirNode.refreshFlags()
call self.path.refreshFlags()
call self.path.refreshFlags(self.getNerdtree())
for i in self.children
call i.refreshFlags()
endfor
endfunction
"FUNCTION: TreeDirNode.refreshDirFlags() {{{1
" FUNCTION: TreeDirNode.refreshDirFlags() {{{1
function! s:TreeDirNode.refreshDirFlags()
call self.path.refreshFlags()
call self.path.refreshFlags(self.getNerdtree())
endfunction
"FUNCTION: TreeDirNode.reveal(path) {{{1
"reveal the given path, i.e. cache and open all treenodes needed to display it
"in the UI
function! s:TreeDirNode.reveal(path)
" FUNCTION: TreeDirNode.reveal(path) {{{1
" reveal the given path, i.e. cache and open all treenodes needed to display it
" in the UI
" Returns the revealed node
function! s:TreeDirNode.reveal(path, ...)
let opts = a:0 ? a:1 : {}
if !a:path.isUnder(self.path)
throw "NERDTree.InvalidArgumentsError: " . a:path.str() . " should be under " . self.path.str()
throw 'NERDTree.InvalidArgumentsError: ' . a:path.str() . ' should be under ' . self.path.str()
endif
call self.open()
if self.path.equals(a:path.getParent())
let n = self.findNode(a:path)
call b:NERDTree.render()
call n.putCursorHere(1,0)
return
" We may be looking for a newly-saved file that isn't in the tree yet.
if n ==# {}
call self.refresh()
let n = self.findNode(a:path)
endif
if has_key(opts, 'open')
call n.open()
endif
return n
endif
let p = a:path
@@ -480,17 +638,15 @@ function! s:TreeDirNode.reveal(path)
endwhile
let n = self.findNode(p)
call n.reveal(a:path)
return n.reveal(a:path, opts)
endfunction
"FUNCTION: TreeDirNode.removeChild(treenode) {{{1
" FUNCTION: TreeDirNode.removeChild(treenode) {{{1
" Remove the given treenode from self.children.
" Throws NERDTree.ChildNotFoundError if the node is not found.
"
"Removes the given treenode from this nodes set of children
"
"Args:
"treenode: the node to remove
"
"Throws a NERDTree.ChildNotFoundError if the given treenode is not found
" Args:
" treenode: the node object to remove
function! s:TreeDirNode.removeChild(treenode)
for i in range(0, self.getChildCount()-1)
if self.children[i].equals(a:treenode)
@@ -499,27 +655,28 @@ function! s:TreeDirNode.removeChild(treenode)
endif
endfor
throw "NERDTree.ChildNotFoundError: child node was not found"
throw 'NERDTree.ChildNotFoundError: child node was not found'
endfunction
"FUNCTION: TreeDirNode.sortChildren() {{{1
"
"Sorts the children of this node according to alphabetical order and the
"directory priority.
"
" FUNCTION: TreeDirNode.sortChildren() {{{1
" Sort self.children by alphabetical order and directory priority.
function! s:TreeDirNode.sortChildren()
let CompareFunc = function("nerdtree#compareNodesBySortKey")
if count(g:NERDTreeSortOrder, '*') < 1
call add(g:NERDTreeSortOrder, '*')
endif
let CompareFunc = function('nerdtree#compareNodesBySortKey')
call sort(self.children, CompareFunc)
let g:NERDTreeOldSortOrder = g:NERDTreeSortOrder
endfunction
"FUNCTION: TreeDirNode.toggleOpen([options]) {{{1
"Opens this directory if it is closed and vice versa
" FUNCTION: TreeDirNode.toggleOpen([options]) {{{1
" Opens this directory if it is closed and vice versa
function! s:TreeDirNode.toggleOpen(...)
let opts = a:0 ? a:1 : {}
if self.isOpen ==# 1
call self.close()
else
if g:NERDTreeCascadeOpenSingleChildDir == 0
if g:NERDTreeCascadeOpenSingleChildDir ==# 0
call self.open(opts)
else
call self.openAlong(opts)
@@ -527,13 +684,13 @@ function! s:TreeDirNode.toggleOpen(...)
endif
endfunction
"FUNCTION: TreeDirNode.transplantChild(newNode) {{{1
"Replaces the child of this with the given node (where the child node's full
"path matches a:newNode's fullpath). The search for the matching node is
"non-recursive
" FUNCTION: TreeDirNode.transplantChild(newNode) {{{1
" Replaces the child of this with the given node (where the child node's full
" path matches a:newNode's fullpath). The search for the matching node is
" non-recursive
"
"Arg:
"newNode: the node to graft into the tree
" Arg:
" newNode: the node to graft into the tree
function! s:TreeDirNode.transplantChild(newNode)
for i in range(0, self.getChildCount()-1)
if self.children[i].equals(a:newNode)

View File

@@ -1,25 +1,28 @@
"CLASS: TreeFileNode
"This class is the parent of the TreeDirNode class and is the
"'Component' part of the composite design pattern between the treenode
"classes.
"============================================================
" ============================================================================
" CLASS: TreeFileNode
"
" This class is the parent of the TreeDirNode class and is the 'Component'
" part of the composite design pattern between the NERDTree node classes.
" ============================================================================
let s:TreeFileNode = {}
let g:NERDTreeFileNode = s:TreeFileNode
"FUNCTION: TreeFileNode.activate(...) {{{1
" FUNCTION: TreeFileNode.activate(...) {{{1
function! s:TreeFileNode.activate(...)
call self.open(a:0 ? a:1 : {})
endfunction
"FUNCTION: TreeFileNode.bookmark(name) {{{1
"bookmark this node with a:name
" FUNCTION: TreeFileNode.bookmark(name) {{{1
" bookmark this node with a:name
function! s:TreeFileNode.bookmark(name)
"if a bookmark exists with the same name and the node is cached then save
"it so we can update its display string
" if a bookmark exists with the same name and the node is cached then save
" it so we can update its display string
let oldMarkedNode = {}
try
let oldMarkedNode = g:NERDTreeBookmark.GetNodeForName(a:name, 1)
let oldMarkedNode = g:NERDTreeBookmark.GetNodeForName(a:name, 1, self.getNerdtree())
catch /^NERDTree.BookmarkNotFoundError/
catch /^NERDTree.BookmarkedNodeNotFoundError/
endtry
@@ -33,19 +36,19 @@ function! s:TreeFileNode.bookmark(name)
endif
endfunction
"FUNCTION: TreeFileNode.cacheParent() {{{1
"initializes self.parent if it isnt already
" FUNCTION: TreeFileNode.cacheParent() {{{1
" initializes self.parent if it isnt already
function! s:TreeFileNode.cacheParent()
if empty(self.parent)
let parentPath = self.path.getParent()
if parentPath.equals(self.path)
throw "NERDTree.CannotCacheParentError: already at root"
throw 'NERDTree.CannotCacheParentError: already at root'
endif
let self.parent = s:TreeFileNode.New(parentPath)
let self.parent = s:TreeFileNode.New(parentPath, self.getNerdtree())
endif
endfunction
"FUNCTION: TreeFileNode.clearBookmarks() {{{1
" FUNCTION: TreeFileNode.clearBookmarks() {{{1
function! s:TreeFileNode.clearBookmarks()
for i in g:NERDTreeBookmark.Bookmarks()
if i.path.equals(self.path)
@@ -55,11 +58,11 @@ function! s:TreeFileNode.clearBookmarks()
call self.path.cacheDisplayString()
endfunction
"FUNCTION: TreeFileNode.copy(dest) {{{1
" FUNCTION: TreeFileNode.copy(dest) {{{1
function! s:TreeFileNode.copy(dest)
call self.path.copy(a:dest)
let newPath = g:NERDTreePath.New(a:dest)
let parent = b:NERDTreeRoot.findNode(newPath.getParent())
let parent = self.getNerdtree().root.findNode(newPath.getParent())
if !empty(parent)
call parent.refresh()
return parent.findNode(newPath)
@@ -68,44 +71,44 @@ function! s:TreeFileNode.copy(dest)
endif
endfunction
"FUNCTION: TreeFileNode.delete {{{1
"Removes this node from the tree and calls the Delete method for its path obj
" FUNCTION: TreeFileNode.delete {{{1
" Removes this node from the tree and calls the Delete method for its path obj
function! s:TreeFileNode.delete()
call self.path.delete()
call self.parent.removeChild(self)
endfunction
"FUNCTION: TreeFileNode.displayString() {{{1
" FUNCTION: TreeFileNode.displayString() {{{1
"
"Returns a string that specifies how the node should be represented as a
"string
" Returns a string that specifies how the node should be represented as a
" string
"
"Return:
"a string that can be used in the view to represent this node
" Return:
" a string that can be used in the view to represent this node
function! s:TreeFileNode.displayString()
return self.path.displayString()
return self.path.flagSet.renderToString() . self.path.displayString()
endfunction
"FUNCTION: TreeFileNode.equals(treenode) {{{1
" FUNCTION: TreeFileNode.equals(treenode) {{{1
"
"Compares this treenode to the input treenode and returns 1 if they are the
"same node.
" Compares this treenode to the input treenode and returns 1 if they are the
" same node.
"
"Use this method instead of == because sometimes when the treenodes contain
"many children, vim seg faults when doing ==
" Use this method instead of == because sometimes when the treenodes contain
" many children, vim seg faults when doing ==
"
"Args:
"treenode: the other treenode to compare to
" Args:
" treenode: the other treenode to compare to
function! s:TreeFileNode.equals(treenode)
return self.path.str() ==# a:treenode.path.str()
endfunction
"FUNCTION: TreeFileNode.findNode(path) {{{1
"Returns self if this node.path.Equals the given path.
"Returns {} if not equal.
" FUNCTION: TreeFileNode.findNode(path) {{{1
" Returns self if this node.path.Equals the given path.
" Returns {} if not equal.
"
"Args:
"path: the path object to compare against
" Args:
" path: the path object to compare against
function! s:TreeFileNode.findNode(path)
if a:path.equals(self.path)
return self
@@ -113,220 +116,188 @@ function! s:TreeFileNode.findNode(path)
return {}
endfunction
"FUNCTION: TreeFileNode.findOpenDirSiblingWithVisibleChildren(direction) {{{1
" FUNCTION: TreeFileNode.findSibling(direction) {{{1
" Find the next or previous sibling of this node.
"
"Finds the next sibling for this node in the indicated direction. This sibling
"must be a directory and may/may not have children as specified.
" Args:
" direction: 0 for previous, 1 for next
"
"Args:
"direction: 0 if you want to find the previous sibling, 1 for the next sibling
"
"Return:
"a treenode object or {} if no appropriate sibling could be found
function! s:TreeFileNode.findOpenDirSiblingWithVisibleChildren(direction)
"if we have no parent then we can have no siblings
if self.parent != {}
let nextSibling = self.findSibling(a:direction)
while nextSibling != {}
if nextSibling.path.isDirectory && nextSibling.hasVisibleChildren() && nextSibling.isOpen
return nextSibling
endif
let nextSibling = nextSibling.findSibling(a:direction)
endwhile
endif
return {}
endfunction
"FUNCTION: TreeFileNode.findSibling(direction) {{{1
"
"Finds the next sibling for this node in the indicated direction
"
"Args:
"direction: 0 if you want to find the previous sibling, 1 for the next sibling
"
"Return:
"a treenode object or {} if no sibling could be found
" Return:
" The next/previous TreeFileNode object or an empty dictionary if not found.
function! s:TreeFileNode.findSibling(direction)
"if we have no parent then we can have no siblings
if self.parent != {}
"get the index of this node in its parents children
let siblingIndx = self.parent.getChildIndex(self.path)
if siblingIndx != -1
"move a long to the next potential sibling node
let siblingIndx = a:direction ==# 1 ? siblingIndx+1 : siblingIndx-1
"keep moving along to the next sibling till we find one that is valid
let numSiblings = self.parent.getChildCount()
while siblingIndx >= 0 && siblingIndx < numSiblings
"if the next node is not an ignored node (i.e. wont show up in the
"view) then return it
if self.parent.children[siblingIndx].path.ignore() ==# 0
return self.parent.children[siblingIndx]
endif
"go to next node
let siblingIndx = a:direction ==# 1 ? siblingIndx+1 : siblingIndx-1
endwhile
endif
" There can be no siblings if there is no parent.
if empty(self.parent)
return {}
endif
let l:nodeIndex = self.parent.getChildIndex(self.path)
if l:nodeIndex == -1
return {}
endif
" Get the next index to begin the search.
let l:nodeIndex += a:direction ? 1 : -1
while 0 <= l:nodeIndex && l:nodeIndex < self.parent.getChildCount()
" Return the next node if it is not ignored.
if !self.parent.children[l:nodeIndex].path.ignore(self.getNerdtree())
return self.parent.children[l:nodeIndex]
endif
let l:nodeIndex += a:direction ? 1 : -1
endwhile
return {}
endfunction
"FUNCTION: TreeFileNode.GetRootForTab(){{{1
"get the root node for this tab
" FUNCTION: TreeFileNode.getNerdtree(){{{1
function! s:TreeFileNode.getNerdtree()
return self._nerdtree
endfunction
" FUNCTION: TreeFileNode.GetRootForTab(){{{1
" get the root node for this tab
function! s:TreeFileNode.GetRootForTab()
if g:NERDTree.ExistsForTab()
return getbufvar(t:NERDTreeBufName, 'NERDTreeRoot')
return getbufvar(t:NERDTreeBufName, 'NERDTree').root
end
return {}
endfunction
"FUNCTION: TreeFileNode.GetSelected() {{{1
"gets the treenode that the cursor is currently over
" FUNCTION: TreeFileNode.GetSelected() {{{1
" If the cursor is currently positioned on a tree node, return the node.
" Otherwise, return the empty dictionary.
function! s:TreeFileNode.GetSelected()
try
let path = b:NERDTree.ui.getPath(line("."))
if path ==# {}
let l:path = b:NERDTree.ui.getPath(line('.'))
if empty(l:path)
return {}
endif
return b:NERDTreeRoot.findNode(path)
catch /^NERDTree/
return b:NERDTree.root.findNode(l:path)
catch
return {}
endtry
endfunction
"FUNCTION: TreeFileNode.isVisible() {{{1
"returns 1 if this node should be visible according to the tree filters and
"hidden file filters (and their on/off status)
" FUNCTION: TreeFileNode.isVisible() {{{1
" returns 1 if this node should be visible according to the tree filters and
" hidden file filters (and their on/off status)
function! s:TreeFileNode.isVisible()
return !self.path.ignore()
return !self.path.ignore(self.getNerdtree())
endfunction
"FUNCTION: TreeFileNode.isRoot() {{{1
"returns 1 if this node is b:NERDTreeRoot
" FUNCTION: TreeFileNode.isRoot() {{{1
function! s:TreeFileNode.isRoot()
if !g:NERDTree.ExistsForBuf()
throw "NERDTree.NoTreeError: No tree exists for the current buffer"
throw 'NERDTree.NoTreeError: No tree exists for the current buffer'
endif
return self.equals(b:NERDTreeRoot)
return self.equals(self.getNerdtree().root)
endfunction
"FUNCTION: TreeFileNode.makeRoot() {{{1
"Make this node the root of the tree
function! s:TreeFileNode.makeRoot()
if self.path.isDirectory
let b:NERDTreeRoot = self
else
call self.cacheParent()
let b:NERDTreeRoot = self.parent
endif
call b:NERDTreeRoot.open()
"change dir to the dir of the new root if instructed to
if g:NERDTreeChDirMode ==# 2
exec "cd " . b:NERDTreeRoot.path.str({'format': 'Edit'})
endif
silent doautocmd User NERDTreeNewRoot
endfunction
"FUNCTION: TreeFileNode.New(path) {{{1
"Returns a new TreeNode object with the given path and parent
" FUNCTION: TreeFileNode.New(path, nerdtree) {{{1
" Returns a new TreeNode object with the given path and parent
"
"Args:
"path: a path object representing the full filesystem path to the file/dir that the node represents
function! s:TreeFileNode.New(path)
" Args:
" path: file/dir that the node represents
" nerdtree: the tree the node belongs to
function! s:TreeFileNode.New(path, nerdtree)
if a:path.isDirectory
return g:NERDTreeDirNode.New(a:path)
return g:NERDTreeDirNode.New(a:path, a:nerdtree)
else
let newTreeNode = copy(self)
let newTreeNode.path = a:path
let newTreeNode.parent = {}
let newTreeNode._nerdtree = a:nerdtree
return newTreeNode
endif
endfunction
"FUNCTION: TreeFileNode.open() {{{1
" FUNCTION: TreeFileNode.open() {{{1
function! s:TreeFileNode.open(...)
let opts = a:0 ? a:1 : {}
let opener = g:NERDTreeOpener.New(self.path, opts)
call opener.open(self)
endfunction
"FUNCTION: TreeFileNode.openSplit() {{{1
"Open this node in a new window
" FUNCTION: TreeFileNode.openSplit() {{{1
" Open this node in a new window
function! s:TreeFileNode.openSplit()
call nerdtree#deprecated('TreeFileNode.openSplit', 'is deprecated, use .open() instead.')
call self.open({'where': 'h'})
endfunction
"FUNCTION: TreeFileNode.openVSplit() {{{1
"Open this node in a new vertical window
" FUNCTION: TreeFileNode.openVSplit() {{{1
" Open this node in a new vertical window
function! s:TreeFileNode.openVSplit()
call nerdtree#deprecated('TreeFileNode.openVSplit', 'is deprecated, use .open() instead.')
call self.open({'where': 'v'})
endfunction
"FUNCTION: TreeFileNode.openInNewTab(options) {{{1
" FUNCTION: TreeFileNode.openInNewTab(options) {{{1
function! s:TreeFileNode.openInNewTab(options)
echomsg 'TreeFileNode.openInNewTab is deprecated'
call nerdtree#deprecated('TreeFileNode.openinNewTab', 'is deprecated, use .open() instead.')
call self.open(extend({'where': 't'}, a:options))
endfunction
"FUNCTION: TreeFileNode.putCursorHere(isJump, recurseUpward){{{1
"Places the cursor on the line number this node is rendered on
" FUNCTION: TreeFileNode.openExplorer()
function! s:TreeFileNode.openExplorer()
execute 'wincmd p'
execute 'edit '.self.path.getParent().str({'format':'Edit'})
endfunction
" FUNCTION: TreeFileNode.putCursorHere(isJump, recurseUpward){{{1
" Places the cursor on the line number this node is rendered on
"
"Args:
"isJump: 1 if this cursor movement should be counted as a jump by vim
"recurseUpward: try to put the cursor on the parent if the this node isnt
"visible
" Args:
" isJump: 1 if this cursor movement should be counted as a jump by vim
" recurseUpward: try to put the cursor on the parent if the this node isnt
" visible
function! s:TreeFileNode.putCursorHere(isJump, recurseUpward)
let ln = b:NERDTree.ui.getLineNum(self)
let ln = self.getNerdtree().ui.getLineNum(self)
if ln != -1
if a:isJump
mark '
endif
call cursor(ln, col("."))
call cursor(ln, col('.'))
else
if a:recurseUpward
let node = self
while node != {} && b:NERDTree.ui.getLineNum(node) ==# -1
while node != {} && self.getNerdtree().ui.getLineNum(node) ==# -1
let node = node.parent
call node.open()
endwhile
call b:NERDTree.render()
call self._nerdtree.render()
call node.putCursorHere(a:isJump, 0)
endif
endif
endfunction
"FUNCTION: TreeFileNode.refresh() {{{1
" FUNCTION: TreeFileNode.refresh() {{{1
function! s:TreeFileNode.refresh()
call self.path.refresh()
call self.path.refresh(self.getNerdtree())
endfunction
"FUNCTION: TreeFileNode.refreshFlags() {{{1
" FUNCTION: TreeFileNode.refreshFlags() {{{1
function! s:TreeFileNode.refreshFlags()
call self.path.refreshFlags()
call self.path.refreshFlags(self.getNerdtree())
endfunction
"FUNCTION: TreeFileNode.rename() {{{1
"Calls the rename method for this nodes path obj
" FUNCTION: TreeFileNode.rename() {{{1
" Calls the rename method for this nodes path obj
function! s:TreeFileNode.rename(newName)
let newName = substitute(a:newName, '\(\\\|\/\)$', '', '')
call self.path.rename(newName)
call self.parent.removeChild(self)
let parentPath = self.path.getParent()
let newParent = b:NERDTreeRoot.findNode(parentPath)
let newParent = self.getNerdtree().root.findNode(parentPath)
if newParent != {}
call newParent.createChild(self.path, 1)
@@ -334,94 +305,45 @@ function! s:TreeFileNode.rename(newName)
endif
endfunction
"FUNCTION: TreeFileNode.renderToString {{{1
"returns a string representation for this tree to be rendered in the view
" FUNCTION: TreeFileNode.renderToString {{{1
" returns a string representation for this tree to be rendered in the view
function! s:TreeFileNode.renderToString()
return self._renderToString(0, 0, [], self.getChildCount() ==# 1)
return self._renderToString(0, 0)
endfunction
"Args:
"depth: the current depth in the tree for this call
"drawText: 1 if we should actually draw the line for this node (if 0 then the
"child nodes are rendered only)
"vertMap: a binary array that indicates whether a vertical bar should be draw
"for each depth in the tree
"isLastChild:true if this curNode is the last child of its parent
function! s:TreeFileNode._renderToString(depth, drawText, vertMap, isLastChild)
let output = ""
" Args:
" depth: the current depth in the tree for this call
" drawText: 1 if we should actually draw the line for this node (if 0 then the
" child nodes are rendered only)
" for each depth in the tree
function! s:TreeFileNode._renderToString(depth, drawText)
let output = ''
if a:drawText ==# 1
let treeParts = ''
let treeParts = repeat(' ', a:depth - 1)
"get all the leading spaces and vertical tree parts for this line
if a:depth > 1
for j in a:vertMap[0:-2]
if g:NERDTreeDirArrows
let treeParts = treeParts . ' '
else
if j ==# 1
let treeParts = treeParts . '| '
else
let treeParts = treeParts . ' '
endif
endif
endfor
if !self.path.isDirectory
let treeParts = treeParts . ' '
endif
"get the last vertical tree part for this line which will be different
"if this node is the last child of its parent
if !g:NERDTreeDirArrows
if a:isLastChild
let treeParts = treeParts . '`'
else
let treeParts = treeParts . '|'
endif
endif
"smack the appropriate dir/file symbol on the line before the file/dir
"name itself
if self.path.isDirectory
if self.isOpen
if g:NERDTreeDirArrows
let treeParts = treeParts . g:NERDTreeDirArrowCollapsible . ' '
else
let treeParts = treeParts . '~'
endif
else
if g:NERDTreeDirArrows
let treeParts = treeParts . g:NERDTreeDirArrowExpandable . ' '
else
let treeParts = treeParts . '+'
endif
endif
else
if g:NERDTreeDirArrows
let treeParts = treeParts . ' '
else
let treeParts = treeParts . '-'
endif
endif
let line = treeParts . self.displayString()
let output = output . line . "\n"
endif
"if the node is an open dir, draw its children
" if the node is an open dir, draw its children
if self.path.isDirectory ==# 1 && self.isOpen ==# 1
let childNodesToDraw = self.getVisibleChildren()
if len(childNodesToDraw) > 0
"draw all the nodes children except the last
let lastIndx = len(childNodesToDraw)-1
if lastIndx > 0
for i in childNodesToDraw[0:lastIndx-1]
let output = output . i._renderToString(a:depth + 1, 1, add(copy(a:vertMap), 1), 0)
endfor
endif
if self.isCascadable() && a:depth > 0
"draw the last child, indicating that it IS the last
let output = output . childNodesToDraw[lastIndx]._renderToString(a:depth + 1, 1, add(copy(a:vertMap), 0), 1)
let output = output . childNodesToDraw[0]._renderToString(a:depth, 0)
elseif len(childNodesToDraw) > 0
for i in childNodesToDraw
let output = output . i._renderToString(a:depth + 1, 1)
endfor
endif
endif

View File

@@ -1,11 +1,14 @@
"CLASS: UI
"============================================================
" ============================================================================
" CLASS: UI
" ============================================================================
let s:UI = {}
let g:NERDTreeUI = s:UI
"FUNCTION: s:UI.centerView() {{{2
"centers the nerd tree window around the cursor (provided the nerd tree
"options permit)
" FUNCTION: s:UI.centerView() {{{1
" centers the nerd tree window around the cursor (provided the nerd tree
" options permit)
function! s:UI.centerView()
if g:NERDTreeAutoCenter
let current_line = winline()
@@ -17,173 +20,170 @@ function! s:UI.centerView()
endif
endfunction
"FUNCTION: s:UI._dumpHelp {{{1
"prints out the quick help
" FUNCTION: s:UI._dumpHelp {{{1
" prints out the quick help
function! s:UI._dumpHelp()
let old_h = @h
if b:treeShowHelp ==# 1
let @h= "\" NERD tree (" . nerdtree#version() . ") quickhelp~\n"
let @h=@h."\" ============================\n"
let @h=@h."\" File node mappings~\n"
let @h=@h."\" ". (g:NERDTreeMouseMode ==# 3 ? "single" : "double") ."-click,\n"
let @h=@h."\" <CR>,\n"
if b:NERDTreeType ==# "primary"
let @h=@h."\" ". g:NERDTreeMapActivateNode .": open in prev window\n"
if self.getShowHelp()
let help = "\" NERDTree (" . nerdtree#version() . ") quickhelp~\n"
let help .= "\" ============================\n"
let help .= "\" File node mappings~\n"
let help .= '" '. (g:NERDTreeMouseMode ==# 3 ? 'single' : 'double') ."-click,\n"
if self.nerdtree.isTabTree()
let help .= '" '. g:NERDTreeMapActivateNode .": open in prev window\n"
else
let @h=@h."\" ". g:NERDTreeMapActivateNode .": open in current window\n"
let help .= '" '. g:NERDTreeMapActivateNode .": open in current window\n"
endif
if b:NERDTreeType ==# "primary"
let @h=@h."\" ". g:NERDTreeMapPreview .": preview\n"
if self.nerdtree.isTabTree()
let help .= '" '. g:NERDTreeMapPreview .": preview\n"
endif
let @h=@h."\" ". g:NERDTreeMapOpenInTab.": open in new tab\n"
let @h=@h."\" ". g:NERDTreeMapOpenInTabSilent .": open in new tab silently\n"
let @h=@h."\" middle-click,\n"
let @h=@h."\" ". g:NERDTreeMapOpenSplit .": open split\n"
let @h=@h."\" ". g:NERDTreeMapPreviewSplit .": preview split\n"
let @h=@h."\" ". g:NERDTreeMapOpenVSplit .": open vsplit\n"
let @h=@h."\" ". g:NERDTreeMapPreviewVSplit .": preview vsplit\n"
let help .= '" '. g:NERDTreeMapOpenInTab.": open in new tab\n"
let help .= '" '. g:NERDTreeMapOpenInTabSilent .": open in new tab silently\n"
let help .= "\" middle-click,\n"
let help .= '" '. g:NERDTreeMapOpenSplit .": open split\n"
let help .= '" '. g:NERDTreeMapPreviewSplit .": preview split\n"
let help .= '" '. g:NERDTreeMapOpenVSplit .": open vsplit\n"
let help .= '" '. g:NERDTreeMapPreviewVSplit .": preview vsplit\n"
let help .= '" '. g:NERDTreeMapCustomOpen .": custom open\n"
let @h=@h."\"\n\" ----------------------------\n"
let @h=@h."\" Directory node mappings~\n"
let @h=@h."\" ". (g:NERDTreeMouseMode ==# 1 ? "double" : "single") ."-click,\n"
let @h=@h."\" ". g:NERDTreeMapActivateNode .": open & close node\n"
let @h=@h."\" ". g:NERDTreeMapOpenRecursively .": recursively open node\n"
let @h=@h."\" ". g:NERDTreeMapCloseDir .": close parent of node\n"
let @h=@h."\" ". g:NERDTreeMapCloseChildren .": close all child nodes of\n"
let @h=@h."\" current node recursively\n"
let @h=@h."\" middle-click,\n"
let @h=@h."\" ". g:NERDTreeMapOpenExpl.": explore selected dir\n"
let help .= "\"\n\" ----------------------------\n"
let help .= "\" Directory node mappings~\n"
let help .= '" '. (g:NERDTreeMouseMode ==# 1 ? 'double' : 'single') ."-click,\n"
let help .= '" '. g:NERDTreeMapActivateNode .": open & close node\n"
let help .= '" '. g:NERDTreeMapOpenRecursively .": recursively open node\n"
let help .= '" '. g:NERDTreeMapOpenInTab.": open in new tab\n"
let help .= '" '. g:NERDTreeMapOpenInTabSilent .": open in new tab silently\n"
let help .= '" '. g:NERDTreeMapCustomOpen .": custom open\n"
let help .= '" '. g:NERDTreeMapCloseDir .": close parent of node\n"
let help .= '" '. g:NERDTreeMapCloseChildren .": close all child nodes of\n"
let help .= "\" current node recursively\n"
let help .= "\" middle-click,\n"
let help .= '" '. g:NERDTreeMapOpenExpl.": explore selected dir\n"
let @h=@h."\"\n\" ----------------------------\n"
let @h=@h."\" Bookmark table mappings~\n"
let @h=@h."\" double-click,\n"
let @h=@h."\" ". g:NERDTreeMapActivateNode .": open bookmark\n"
let @h=@h."\" ". g:NERDTreeMapOpenInTab.": open in new tab\n"
let @h=@h."\" ". g:NERDTreeMapOpenInTabSilent .": open in new tab silently\n"
let @h=@h."\" ". g:NERDTreeMapDeleteBookmark .": delete bookmark\n"
let help .= "\"\n\" ----------------------------\n"
let help .= "\" Bookmark table mappings~\n"
let help .= "\" double-click,\n"
let help .= '" '. g:NERDTreeMapActivateNode .": open bookmark\n"
let help .= '" '. g:NERDTreeMapPreview .": preview file\n"
let help .= '" '. g:NERDTreeMapPreview .": find dir in tree\n"
let help .= '" '. g:NERDTreeMapOpenInTab.": open in new tab\n"
let help .= '" '. g:NERDTreeMapOpenInTabSilent .": open in new tab silently\n"
let help .= '" '. g:NERDTreeMapCustomOpen .": custom open\n"
let help .= '" '. g:NERDTreeMapDeleteBookmark .": delete bookmark\n"
let @h=@h."\"\n\" ----------------------------\n"
let @h=@h."\" Tree navigation mappings~\n"
let @h=@h."\" ". g:NERDTreeMapJumpRoot .": go to root\n"
let @h=@h."\" ". g:NERDTreeMapJumpParent .": go to parent\n"
let @h=@h."\" ". g:NERDTreeMapJumpFirstChild .": go to first child\n"
let @h=@h."\" ". g:NERDTreeMapJumpLastChild .": go to last child\n"
let @h=@h."\" ". g:NERDTreeMapJumpNextSibling .": go to next sibling\n"
let @h=@h."\" ". g:NERDTreeMapJumpPrevSibling .": go to prev sibling\n"
let help .= "\"\n\" ----------------------------\n"
let help .= "\" Tree navigation mappings~\n"
let help .= '" '. g:NERDTreeMapJumpRoot .": go to root\n"
let help .= '" '. g:NERDTreeMapJumpParent .": go to parent\n"
let help .= '" '. g:NERDTreeMapJumpFirstChild .": go to first child\n"
let help .= '" '. g:NERDTreeMapJumpLastChild .": go to last child\n"
let help .= '" '. g:NERDTreeMapJumpNextSibling .": go to next sibling\n"
let help .= '" '. g:NERDTreeMapJumpPrevSibling .": go to prev sibling\n"
let @h=@h."\"\n\" ----------------------------\n"
let @h=@h."\" Filesystem mappings~\n"
let @h=@h."\" ". g:NERDTreeMapChangeRoot .": change tree root to the\n"
let @h=@h."\" selected dir\n"
let @h=@h."\" ". g:NERDTreeMapUpdir .": move tree root up a dir\n"
let @h=@h."\" ". g:NERDTreeMapUpdirKeepOpen .": move tree root up a dir\n"
let @h=@h."\" but leave old root open\n"
let @h=@h."\" ". g:NERDTreeMapRefresh .": refresh cursor dir\n"
let @h=@h."\" ". g:NERDTreeMapRefreshRoot .": refresh current root\n"
let @h=@h."\" ". g:NERDTreeMapMenu .": Show menu\n"
let @h=@h."\" ". g:NERDTreeMapChdir .":change the CWD to the\n"
let @h=@h."\" selected dir\n"
let @h=@h."\" ". g:NERDTreeMapCWD .":change tree root to CWD\n"
let help .= "\"\n\" ----------------------------\n"
let help .= "\" Filesystem mappings~\n"
let help .= '" '. g:NERDTreeMapChangeRoot .": change tree root to the\n"
let help .= "\" selected dir\n"
let help .= '" '. g:NERDTreeMapUpdir .": move tree root up a dir\n"
let help .= '" '. g:NERDTreeMapUpdirKeepOpen .": move tree root up a dir\n"
let help .= "\" but leave old root open\n"
let help .= '" '. g:NERDTreeMapRefresh .": refresh cursor dir\n"
let help .= '" '. g:NERDTreeMapRefreshRoot .": refresh current root\n"
let help .= '" '. g:NERDTreeMapMenu .": Show menu\n"
let help .= '" '. g:NERDTreeMapChdir .":change the CWD to the\n"
let help .= "\" selected dir\n"
let help .= '" '. g:NERDTreeMapCWD .":change tree root to CWD\n"
let @h=@h."\"\n\" ----------------------------\n"
let @h=@h."\" Tree filtering mappings~\n"
let @h=@h."\" ". g:NERDTreeMapToggleHidden .": hidden files (" . (b:NERDTreeShowHidden ? "on" : "off") . ")\n"
let @h=@h."\" ". g:NERDTreeMapToggleFilters .": file filters (" . (b:NERDTreeIgnoreEnabled ? "on" : "off") . ")\n"
let @h=@h."\" ". g:NERDTreeMapToggleFiles .": files (" . (b:NERDTreeShowFiles ? "on" : "off") . ")\n"
let @h=@h."\" ". g:NERDTreeMapToggleBookmarks .": bookmarks (" . (b:NERDTreeShowBookmarks ? "on" : "off") . ")\n"
let help .= "\"\n\" ----------------------------\n"
let help .= "\" Tree filtering mappings~\n"
let help .= '" '. g:NERDTreeMapToggleHidden .': hidden files (' . (self.getShowHidden() ? 'on' : 'off') . ")\n"
let help .= '" '. g:NERDTreeMapToggleFilters .': file filters (' . (self.isIgnoreFilterEnabled() ? 'on' : 'off') . ")\n"
let help .= '" '. g:NERDTreeMapToggleFiles .': files (' . (self.getShowFiles() ? 'on' : 'off') . ")\n"
let help .= '" '. g:NERDTreeMapToggleBookmarks .': bookmarks (' . (self.getShowBookmarks() ? 'on' : 'off') . ")\n"
"add quickhelp entries for each custom key map
let @h=@h."\"\n\" ----------------------------\n"
let @h=@h."\" Custom mappings~\n"
" add quickhelp entries for each custom key map
let help .= "\"\n\" ----------------------------\n"
let help .= "\" Custom mappings~\n"
for i in g:NERDTreeKeyMap.All()
if !empty(i.quickhelpText)
let @h=@h."\" ". i.key .": ". i.quickhelpText ."\n"
let help .= '" '. i.key .': '. i.quickhelpText ."\n"
endif
endfor
let @h=@h."\"\n\" ----------------------------\n"
let @h=@h."\" Other mappings~\n"
let @h=@h."\" ". g:NERDTreeMapQuit .": Close the NERDTree window\n"
let @h=@h."\" ". g:NERDTreeMapToggleZoom .": Zoom (maximize-minimize)\n"
let @h=@h."\" the NERDTree window\n"
let @h=@h."\" ". g:NERDTreeMapHelp .": toggle help\n"
let @h=@h."\"\n\" ----------------------------\n"
let @h=@h."\" Bookmark commands~\n"
let @h=@h."\" :Bookmark [<name>]\n"
let @h=@h."\" :BookmarkToRoot <name>\n"
let @h=@h."\" :RevealBookmark <name>\n"
let @h=@h."\" :OpenBookmark <name>\n"
let @h=@h."\" :ClearBookmarks [<names>]\n"
let @h=@h."\" :ClearAllBookmarks\n"
silent! put h
elseif g:NERDTreeMinimalUI == 0
let @h="\" Press ". g:NERDTreeMapHelp ." for help\n"
silent! put h
let help .= "\"\n\" ----------------------------\n"
let help .= "\" Other mappings~\n"
let help .= '" '. g:NERDTreeMapQuit .": Close the NERDTree window\n"
let help .= '" '. g:NERDTreeMapToggleZoom .": Zoom (maximize-minimize)\n"
let help .= "\" the NERDTree window\n"
let help .= '" '. g:NERDTreeMapHelp .": toggle help\n"
let help .= "\"\n\" ----------------------------\n"
let help .= "\" Bookmark commands~\n"
let help .= "\" :Bookmark [<name>]\n"
let help .= "\" :BookmarkToRoot <name>\n"
let help .= "\" :RevealBookmark <name>\n"
let help .= "\" :OpenBookmark <name>\n"
let help .= "\" :ClearBookmarks [<names>]\n"
let help .= "\" :ClearAllBookmarks\n"
let help .= "\" :ReadBookmarks\n"
let help .= "\" :WriteBookmarks\n"
let help .= "\" :EditBookmarks\n"
silent! put =help
elseif !self.isMinimal()
let help ='" Press '. g:NERDTreeMapHelp ." for help\n"
silent! put =help
endif
let @h = old_h
endfunction
"FUNCTION: s:UI.new(nerdtree) {{{1
" FUNCTION: s:UI.new(nerdtree) {{{1
function! s:UI.New(nerdtree)
let newObj = copy(self)
let newObj.nerdtree = a:nerdtree
let newObj._showHelp = 0
let newObj._ignoreEnabled = 1
let newObj._showFiles = g:NERDTreeShowFiles
let newObj._showHidden = g:NERDTreeShowHidden
let newObj._showBookmarks = g:NERDTreeShowBookmarks
return newObj
endfunction
"FUNCTION: s:UI.getPath(ln) {{{1
"Gets the full path to the node that is rendered on the given line number
"
"Args:
"ln: the line number to get the path for
"
"Return:
"A path if a node was selected, {} if nothing is selected.
"If the 'up a dir' line was selected then the path to the parent of the
"current root is returned
" FUNCTION: s:UI.getPath(ln) {{{1
" Return the Path object for the node that is rendered on the given line
" number. If the 'up a dir' line is selected, return the Path object for
" the parent of the root. Return the empty dictionary if the given line
" does not reference a tree node.
function! s:UI.getPath(ln)
let line = getline(a:ln)
let rootLine = self.getRootLineNum()
"check to see if we have the root node
if a:ln == rootLine
return b:NERDTreeRoot.path
endif
if !g:NERDTreeDirArrows
" in case called from outside the tree
if line !~# '^ *[|`'.g:NERDTreeDirArrowExpandable.g:NERDTreeDirArrowCollapsible.' ]' || line =~# '^$'
return {}
endif
if a:ln ==# rootLine
return self.nerdtree.root.path
endif
if line ==# s:UI.UpDirLine()
return b:NERDTreeRoot.path.getParent()
return self.nerdtree.root.path.getParent()
endif
if a:ln < rootLine
return {}
endif
let indent = self._indentLevelFor(line)
"remove the tree parts and the leading space
let curFile = self._stripMarkup(line, 0)
" remove the tree parts and the leading space
let curFile = self._stripMarkup(line)
let wasdir = 0
if curFile =~# '/$'
let wasdir = 1
let curFile = substitute(curFile, '/\?$', '/', "")
endif
let dir = ""
let dir = ''
let lnum = a:ln
while lnum > 0
let lnum = lnum - 1
let curLine = getline(lnum)
let curLineStripped = self._stripMarkup(curLine, 1)
let curLineStripped = self._stripMarkup(curLine)
"have we reached the top of the tree?
if lnum == rootLine
let dir = b:NERDTreeRoot.path.str({'format': 'UI'}) . dir
" have we reached the top of the tree?
if lnum ==# rootLine
let dir = self.nerdtree.root.path.str({'format': 'UI'}) . dir
break
endif
if curLineStripped =~# '/$'
@@ -191,235 +191,239 @@ function! s:UI.getPath(ln)
if lpindent < indent
let indent = indent - 1
let dir = substitute (curLineStripped,'^\\', "", "") . dir
let dir = substitute (curLineStripped,'^\\', '', '') . dir
continue
endif
endif
endwhile
let curFile = b:NERDTreeRoot.path.drive . dir . curFile
let curFile = self.nerdtree.root.path.drive . dir . curFile
let toReturn = g:NERDTreePath.New(curFile)
return toReturn
endfunction
"FUNCTION: s:UI.getLineNum(file_node){{{1
"returns the line number this node is rendered on, or -1 if it isnt rendered
function! s:UI.getLineNum(file_node)
"if the node is the root then return the root line no.
if a:file_node.isRoot()
return b:NERDTree.ui.getRootLineNum()
" FUNCTION: s:UI.getLineNum(node) {{{1
" Return the line number where the given node is rendered. Return -1 if the
" given node is not visible.
function! s:UI.getLineNum(node)
if a:node.isRoot()
return self.getRootLineNum()
endif
let totalLines = line("$")
let l:pathComponents = [substitute(self.nerdtree.root.path.str({'format': 'UI'}), '/\s*$', '', '')]
let l:currentPathComponent = 1
"the path components we have matched so far
let pathcomponents = [substitute(b:NERDTreeRoot.path.str({'format': 'UI'}), '/ *$', '', '')]
"the index of the component we are searching for
let curPathComponent = 1
let l:fullPath = a:node.path.str({'format': 'UI'})
let fullpath = a:file_node.path.str({'format': 'UI'})
for l:lineNumber in range(self.getRootLineNum() + 1, line('$'))
let l:currentLine = getline(l:lineNumber)
let l:indentLevel = self._indentLevelFor(l:currentLine)
let lnum = b:NERDTree.ui.getRootLineNum()
while lnum > 0
let lnum = lnum + 1
"have we reached the bottom of the tree?
if lnum ==# totalLines+1
return -1
if l:indentLevel !=# l:currentPathComponent
continue
endif
let curLine = getline(lnum)
let l:currentLine = self._stripMarkup(l:currentLine)
let l:currentPath = join(l:pathComponents, '/') . '/' . l:currentLine
let indent = self._indentLevelFor(curLine)
if indent ==# curPathComponent
let curLine = self._stripMarkup(curLine, 1)
let curPath = join(pathcomponents, '/') . '/' . curLine
if stridx(fullpath, curPath, 0) ==# 0
if fullpath ==# curPath || strpart(fullpath, len(curPath)-1,1) ==# '/'
let curLine = substitute(curLine, '/ *$', '', '')
call add(pathcomponents, curLine)
let curPathComponent = curPathComponent + 1
if fullpath ==# curPath
return lnum
endif
endif
endif
" Directories: If the current path 'starts with' the full path, then
" either the paths are equal or the line is a cascade containing the
" full path.
if l:fullPath[-1:] ==# '/' && stridx(l:currentPath, l:fullPath) ==# 0
return l:lineNumber
endif
endwhile
" Files: The paths must exactly match.
if l:fullPath ==# l:currentPath
return l:lineNumber
endif
" Otherwise: If the full path starts with the current path and the
" current path is a directory, we add a new path component.
if stridx(l:fullPath, l:currentPath) ==# 0 && l:currentPath[-1:] ==# '/'
let l:currentLine = substitute(l:currentLine, '/\s*$', '', '')
call add(l:pathComponents, l:currentLine)
let l:currentPathComponent += 1
endif
endfor
return -1
endfunction
"FUNCTION: s:UI.getRootLineNum(){{{1
"gets the line number of the root node
" FUNCTION: s:UI.getRootLineNum(){{{1
" gets the line number of the root node
function! s:UI.getRootLineNum()
let rootLine = 1
while getline(rootLine) !~# '^\(/\|<\)'
while rootLine <= line('$') && getline(rootLine) !~# '^\(/\|<\)'
let rootLine = rootLine + 1
endwhile
return rootLine
endfunction
"FUNCTION: s:UI._indentLevelFor(line) {{{1
function! s:UI._indentLevelFor(line)
let level = match(a:line, '[^ \-+~'.g:NERDTreeDirArrowExpandable.g:NERDTreeDirArrowCollapsible.'`|]') / s:UI.IndentWid()
" check if line includes arrows
if match(a:line, '['.g:NERDTreeDirArrowExpandable.g:NERDTreeDirArrowCollapsible.']') > -1
" decrement level as arrow uses 3 ascii chars
let level = level - 1
endif
return level
" FUNCTION: s:UI.getShowBookmarks() {{{1
function! s:UI.getShowBookmarks()
return self._showBookmarks
endfunction
"FUNCTION: s:UI.IndentWid() {{{1
" FUNCTION: s:UI.getShowFiles() {{{1
function! s:UI.getShowFiles()
return self._showFiles
endfunction
" FUNCTION: s:UI.getShowHelp() {{{1
function! s:UI.getShowHelp()
return self._showHelp
endfunction
" FUNCTION: s:UI.getShowHidden() {{{1
function! s:UI.getShowHidden()
return self._showHidden
endfunction
" FUNCTION: s:UI._indentLevelFor(line) {{{1
function! s:UI._indentLevelFor(line)
" Replace multi-character DirArrows with a single space so the
" indentation calculation doesn't get messed up.
let l:line = substitute(substitute(a:line, '\V'.g:NERDTreeDirArrowExpandable, ' ', ''), '\V'.g:NERDTreeDirArrowCollapsible, ' ', '')
let leadChars = match(l:line, '\M\[^ ]')
return leadChars / s:UI.IndentWid()
endfunction
" FUNCTION: s:UI.IndentWid() {{{1
function! s:UI.IndentWid()
return 2
endfunction
"FUNCTION: s:UI.MarkupReg() {{{1
function! s:UI.MarkupReg()
if g:NERDTreeDirArrows
return '^\(['.g:NERDTreeDirArrowExpandable.g:NERDTreeDirArrowCollapsible.'] \| \+['.g:NERDTreeDirArrowExpandable.g:NERDTreeDirArrowCollapsible.'] \| \+\)'
endif
return '^[ `|]*[\-+~]'
" FUNCTION: s:UI.isIgnoreFilterEnabled() {{{1
function! s:UI.isIgnoreFilterEnabled()
return self._ignoreEnabled ==# 1
endfunction
"FUNCTION: s:UI._renderBookmarks {{{1
" FUNCTION: s:UI.isMinimal() {{{1
function! s:UI.isMinimal()
return g:NERDTreeMinimalUI
endfunction
" FUNCTION: s:UI.MarkupReg() {{{1
function! s:UI.MarkupReg()
return '^ *['.g:NERDTreeDirArrowExpandable.g:NERDTreeDirArrowCollapsible.']\? '
endfunction
" FUNCTION: s:UI._renderBookmarks {{{1
function! s:UI._renderBookmarks()
if g:NERDTreeMinimalUI == 0
call setline(line(".")+1, ">----------Bookmarks----------")
call cursor(line(".")+1, col("."))
if !self.isMinimal()
call setline(line('.')+1, '>----------Bookmarks----------')
call cursor(line('.')+1, col('.'))
endif
if g:NERDTreeBookmarksSort ==# 1 || g:NERDTreeBookmarksSort ==# 2
call g:NERDTreeBookmark.SortBookmarksList()
endif
for i in g:NERDTreeBookmark.Bookmarks()
call setline(line(".")+1, i.str())
call cursor(line(".")+1, col("."))
call setline(line('.')+1, i.str())
call cursor(line('.')+1, col('.'))
endfor
call setline(line(".")+1, '')
call cursor(line(".")+1, col("."))
call setline(line('.')+1, '')
call cursor(line('.')+1, col('.'))
endfunction
"FUNCTION: s:UI.restoreScreenState() {{{1
" FUNCTION: s:UI.restoreScreenState() {{{1
"
"Sets the screen state back to what it was when nerdtree#saveScreenState was last
"called.
" Sets the screen state back to what it was when nerdtree#saveScreenState was last
" called.
"
"Assumes the cursor is in the NERDTree window
" Assumes the cursor is in the NERDTree window
function! s:UI.restoreScreenState()
if !has_key(self, '_screenState')
return
endif
exec("silent vertical resize " . self._screenState['oldWindowSize'])
call nerdtree#exec('silent vertical resize ' . self._screenState['oldWindowSize'], 1)
let old_scrolloff=&scrolloff
let &scrolloff=0
call cursor(self._screenState['oldTopLine'], 0)
normal! zt
call setpos(".", self._screenState['oldPos'])
call setpos('.', self._screenState['oldPos'])
let &scrolloff=old_scrolloff
endfunction
"FUNCTION: s:UI.saveScreenState() {{{1
"Saves the current cursor position in the current buffer and the window
"scroll position
" FUNCTION: s:UI.saveScreenState() {{{1
" Saves the current cursor position in the current buffer and the window
" scroll position
function! s:UI.saveScreenState()
let win = winnr()
call g:NERDTree.CursorToTreeWin()
let self._screenState = {}
let self._screenState['oldPos'] = getpos(".")
let self._screenState['oldTopLine'] = line("w0")
let self._screenState['oldWindowSize']= winwidth("")
call nerdtree#exec(win . "wincmd w")
try
call g:NERDTree.CursorToTreeWin()
let self._screenState['oldPos'] = getpos('.')
let self._screenState['oldTopLine'] = line('w0')
let self._screenState['oldWindowSize']= winwidth('')
call nerdtree#exec(win . 'wincmd w', 1)
catch
endtry
endfunction
"FUNCTION: s:UI._stripMarkup(line, removeLeadingSpaces){{{1
"returns the given line with all the tree parts stripped off
" FUNCTION: s:UI.setShowHidden(val) {{{1
function! s:UI.setShowHidden(val)
let self._showHidden = a:val
endfunction
" FUNCTION: s:UI._stripMarkup(line){{{1
" find the filename in the given line, and return it.
"
"Args:
"line: the subject line
"removeLeadingSpaces: 1 if leading spaces are to be removed (leading spaces =
"any spaces before the actual text of the node)
function! s:UI._stripMarkup(line, removeLeadingSpaces)
let line = a:line
"remove the tree parts and the leading space
let line = substitute (line, g:NERDTreeUI.MarkupReg(),"","")
"strip off any read only flag
let line = substitute (line, ' \[RO\]', "","")
"strip off any bookmark flags
let line = substitute (line, ' {[^}]*}', "","")
"strip off any executable flags
let line = substitute (line, '*\ze\($\| \)', "","")
"strip off any generic flags
let line = substitute (line, '\[[^]]*\]', "","")
let wasdir = 0
if line =~# '/$'
let wasdir = 1
endif
let line = substitute (line,' -> .*',"","") " remove link to
if wasdir ==# 1
let line = substitute (line, '/\?$', '/', "")
endif
if a:removeLeadingSpaces
let line = substitute (line, '^ *', '', '')
endif
return line
" Args:
" line: the subject line
function! s:UI._stripMarkup(line)
let l:line = substitute(a:line, '^.\{-}' . g:NERDTreeNodeDelimiter, '', '')
return substitute(l:line, g:NERDTreeNodeDelimiter.'.*$', '', '')
endfunction
"FUNCTION: s:UI.render() {{{1
" FUNCTION: s:UI.render() {{{1
function! s:UI.render()
setlocal modifiable
setlocal noreadonly modifiable
"remember the top line of the buffer and the current line so we can
"restore the view exactly how it was
let curLine = line(".")
let curCol = col(".")
let topLine = line("w0")
" remember the top line of the buffer and the current line so we can
" restore the view exactly how it was
let curLine = line('.')
let curCol = col('.')
let topLine = line('w0')
"delete all lines in the buffer (being careful not to clobber a register)
" delete all lines in the buffer (being careful not to clobber a register)
silent 1,$delete _
call self._dumpHelp()
"delete the blank line before the help and add one after it
if g:NERDTreeMinimalUI == 0
call setline(line(".")+1, "")
call cursor(line(".")+1, col("."))
" delete the blank line before the help and add one after it
if !self.isMinimal()
call setline(line('.')+1, '')
call cursor(line('.')+1, col('.'))
endif
if b:NERDTreeShowBookmarks
if self.getShowBookmarks()
call self._renderBookmarks()
endif
"add the 'up a dir' line
if !g:NERDTreeMinimalUI
call setline(line(".")+1, s:UI.UpDirLine())
call cursor(line(".")+1, col("."))
" add the 'up a dir' line
if !self.isMinimal()
call setline(line('.')+1, s:UI.UpDirLine())
call cursor(line('.')+1, col('.'))
endif
"draw the header line
let header = b:NERDTreeRoot.path.str({'format': 'UI', 'truncateTo': winwidth(0)})
call setline(line(".")+1, header)
call cursor(line(".")+1, col("."))
" draw the header line
let header = self.nerdtree.root.path.str({'format': 'UI', 'truncateTo': winwidth(0)})
call setline(line('.')+1, header)
call cursor(line('.')+1, col('.'))
"draw the tree
let old_o = @o
let @o = b:NERDTreeRoot.renderToString()
silent put o
let @o = old_o
" draw the tree
silent put =self.nerdtree.root.renderToString()
"delete the blank line at the top of the buffer
" delete the blank line at the top of the buffer
silent 1,1delete _
"restore the view
" restore the view
let old_scrolloff=&scrolloff
let &scrolloff=0
call cursor(topLine, 1)
@@ -427,80 +431,95 @@ function! s:UI.render()
call cursor(curLine, curCol)
let &scrolloff = old_scrolloff
setlocal nomodifiable
setlocal readonly nomodifiable
endfunction
"FUNCTION: UI.renderViewSavingPosition {{{1
"Renders the tree and ensures the cursor stays on the current node or the
"current nodes parent if it is no longer available upon re-rendering
" FUNCTION: UI.renderViewSavingPosition {{{1
" Renders the tree and ensures the cursor stays on the current node or the
" current nodes parent if it is no longer available upon re-rendering
function! s:UI.renderViewSavingPosition()
let currentNode = g:NERDTreeFileNode.GetSelected()
"go up the tree till we find a node that will be visible or till we run
"out of nodes
while currentNode != {} && !currentNode.isVisible() && !currentNode.isRoot()
" go up the tree till we find a node that will be visible or till we run
" out of nodes
while currentNode !=# {} && !currentNode.isVisible() && !currentNode.isRoot()
let currentNode = currentNode.parent
endwhile
call b:NERDTree.render()
call self.render()
if currentNode != {}
if currentNode !=# {}
call currentNode.putCursorHere(0, 0)
endif
endfunction
" FUNCTION: s:UI.toggleHelp() {{{1
function! s:UI.toggleHelp()
let self._showHelp = !self._showHelp
endfunction
" FUNCTION: s:UI.toggleIgnoreFilter() {{{1
" toggles the use of the NERDTreeIgnore option
function! s:UI.toggleIgnoreFilter()
let b:NERDTreeIgnoreEnabled = !b:NERDTreeIgnoreEnabled
call b:NERDTree.ui.renderViewSavingPosition()
call b:NERDTree.ui.centerView()
let self._ignoreEnabled = !self._ignoreEnabled
call self.renderViewSavingPosition()
call self.centerView()
endfunction
" FUNCTION: s:UI.toggleShowBookmarks() {{{1
" toggles the display of bookmarks
" Toggle the visibility of the Bookmark table.
function! s:UI.toggleShowBookmarks()
let b:NERDTreeShowBookmarks = !b:NERDTreeShowBookmarks
if b:NERDTreeShowBookmarks
call b:NERDTree.render()
let self._showBookmarks = !self._showBookmarks
if self.getShowBookmarks()
call self.nerdtree.render()
call g:NERDTree.CursorToBookmarkTable()
else
call b:NERDTree.ui.renderViewSavingPosition()
if empty(g:NERDTreeFileNode.GetSelected())
call b:NERDTree.root.putCursorHere(0, 0)
normal! 0
endif
call self.renderViewSavingPosition()
endif
call b:NERDTree.ui.centerView()
call self.centerView()
endfunction
" FUNCTION: s:UI.toggleShowFiles() {{{1
" toggles the display of hidden files
function! s:UI.toggleShowFiles()
let b:NERDTreeShowFiles = !b:NERDTreeShowFiles
call b:NERDTree.ui.renderViewSavingPosition()
call b:NERDTree.ui.centerView()
let self._showFiles = !self._showFiles
call self.renderViewSavingPosition()
call self.centerView()
endfunction
" FUNCTION: s:UI.toggleShowHidden() {{{1
" toggles the display of hidden files
function! s:UI.toggleShowHidden()
let b:NERDTreeShowHidden = !b:NERDTreeShowHidden
call b:NERDTree.ui.renderViewSavingPosition()
let self._showHidden = !self._showHidden
call self.renderViewSavingPosition()
call self.centerView()
endfunction
" FUNCTION: s:UI.toggleZoom() {{{1
" zoom (maximize/minimize) the NERDTree window
function! s:UI.toggleZoom()
if exists("b:NERDTreeZoomed") && b:NERDTreeZoomed
let size = exists("b:NERDTreeOldWindowSize") ? b:NERDTreeOldWindowSize : g:NERDTreeWinSize
exec "silent vertical resize ". size
if exists('b:NERDTreeZoomed') && b:NERDTreeZoomed
let size = exists('b:NERDTreeOldWindowSize') ? b:NERDTreeOldWindowSize : g:NERDTreeWinSize
call nerdtree#exec('silent vertical resize '. size, 1)
let b:NERDTreeZoomed = 0
else
exec "vertical resize"
call nerdtree#exec('vertical resize '. get(g:, 'NERDTreeWinSizeMax', ''), 1)
let b:NERDTreeZoomed = 1
endif
endfunction
"FUNCTION: s:UI.UpDirLine() {{{1
" FUNCTION: s:UI.UpDirLine() {{{1
function! s:UI.UpDirLine()
return '.. (up a dir)'
endfunction
" vim: set sw=4 sts=4 et fdm=marker:

View File

@@ -9,7 +9,7 @@
" See http://sam.zoy.org/wtfpl/COPYING for more details.
"
" ============================================================================
if exists("g:loaded_nerdtree_exec_menuitem")
if exists('g:loaded_nerdtree_exec_menuitem')
finish
endif
let g:loaded_nerdtree_exec_menuitem = 1
@@ -32,9 +32,9 @@ function! NERDTreeExecFile()
let cmd = treenode.path.str({'escape': 1})
let cmd = input(':!', cmd . ' ')
if cmd != ''
if cmd !=# ''
exec ':!' . cmd
else
echo "Aborted"
echo 'Aborted'
endif
endfunction

View File

@@ -9,13 +9,13 @@
" See http://sam.zoy.org/wtfpl/COPYING for more details.
"
" ============================================================================
if exists("g:loaded_nerdtree_fs_menu")
if exists('g:loaded_nerdtree_fs_menu')
finish
endif
let g:loaded_nerdtree_fs_menu = 1
"Automatically delete the buffer after deleting or renaming a file
if !exists("g:NERDTreeAutoDeleteBuffer")
if !exists('g:NERDTreeAutoDeleteBuffer')
let g:NERDTreeAutoDeleteBuffer = 0
endif
@@ -23,22 +23,69 @@ call NERDTreeAddMenuItem({'text': '(a)dd a childnode', 'shortcut': 'a', 'callbac
call NERDTreeAddMenuItem({'text': '(m)ove the current node', 'shortcut': 'm', 'callback': 'NERDTreeMoveNode'})
call NERDTreeAddMenuItem({'text': '(d)elete the current node', 'shortcut': 'd', 'callback': 'NERDTreeDeleteNode'})
if has("gui_mac") || has("gui_macvim") || has("mac")
if has('gui_mac') || has('gui_macvim') || has('mac')
call NERDTreeAddMenuItem({'text': '(r)eveal in Finder the current node', 'shortcut': 'r', 'callback': 'NERDTreeRevealInFinder'})
call NERDTreeAddMenuItem({'text': '(o)pen the current node with system editor', 'shortcut': 'o', 'callback': 'NERDTreeExecuteFile'})
call NERDTreeAddMenuItem({'text': '(q)uicklook the current node', 'shortcut': 'q', 'callback': 'NERDTreeQuickLook'})
endif
if executable('xdg-open')
call NERDTreeAddMenuItem({'text': '(r)eveal the current node in file manager', 'shortcut': 'r', 'callback': 'NERDTreeRevealFileLinux'})
call NERDTreeAddMenuItem({'text': '(o)pen the current node with system editor', 'shortcut': 'o', 'callback': 'NERDTreeExecuteFileLinux'})
endif
if g:NERDTreePath.CopyingSupported()
call NERDTreeAddMenuItem({'text': '(c)opy the current node', 'shortcut': 'c', 'callback': 'NERDTreeCopyNode'})
endif
call NERDTreeAddMenuItem({'text': (has('clipboard')?'copy (p)ath to clipboard':'print (p)ath to screen'), 'shortcut': 'p', 'callback': 'NERDTreeCopyPath'})
if has("unix") || has("osx")
if has('unix') || has('osx')
call NERDTreeAddMenuItem({'text': '(l)ist the current node', 'shortcut': 'l', 'callback': 'NERDTreeListNode'})
else
call NERDTreeAddMenuItem({'text': '(l)ist the current node', 'shortcut': 'l', 'callback': 'NERDTreeListNodeWin32'})
endif
"FUNCTION: s:inputPrompt(action){{{1
"returns the string that should be prompted to the user for the given action
"
"Args:
"action: the action that is being performed, e.g. 'delete'
function! s:inputPrompt(action)
if a:action ==# 'add'
let title = 'Add a childnode'
let info = "Enter the dir/file name to be created. Dirs end with a '/'"
let minimal = 'Add node:'
elseif a:action ==# 'copy'
let title = 'Copy the current node'
let info = 'Enter the new path to copy the node to:'
let minimal = 'Copy to:'
elseif a:action ==# 'delete'
let title = 'Delete the current node'
let info = 'Are you sure you wish to delete the node:'
let minimal = 'Delete?'
elseif a:action ==# 'deleteNonEmpty'
let title = 'Delete the current node'
let info = "STOP! Directory is not empty! To delete, type 'yes'"
let minimal = 'Delete directory?'
elseif a:action ==# 'move'
let title = 'Rename the current node'
let info = 'Enter the new path for the node:'
let minimal = 'Move to:'
endif
if g:NERDTreeMenuController.isMinimal()
redraw! " Clear the menu
return minimal . ' '
else
let divider = '=========================================================='
return title . "\n" . divider . "\n" . info . "\n"
end
endfunction
"FUNCTION: s:promptToDelBuffer(bufnum, msg){{{1
"prints out the given msg and, if the user responds by pushing 'y' then the
"buffer with the given bufnum is deleted
@@ -55,127 +102,163 @@ function! s:promptToDelBuffer(bufnum, msg)
" Is not it better to close single tabs with this file only ?
let s:originalTabNumber = tabpagenr()
let s:originalWindowNumber = winnr()
exec "tabdo windo if winbufnr(0) == " . a:bufnum . " | exec ':enew! ' | endif"
exec "tabnext " . s:originalTabNumber
exec s:originalWindowNumber . "wincmd w"
" Go to the next buffer in buffer list if at least one extra buffer is listed
" Otherwise open a new empty buffer
if v:version >= 800
let l:listedBufferCount = len(getbufinfo({'buflisted':1}))
elseif v:version >= 702
let l:listedBufferCount = len(filter(range(1, bufnr('$')), 'buflisted(v:val)'))
else
" Ignore buffer count in this case to make sure we keep the old
" behavior
let l:listedBufferCount = 0
endif
if l:listedBufferCount > 1
call nerdtree#exec('tabdo windo if winbufnr(0) ==# ' . a:bufnum . " | exec ':bnext! ' | endif", 1)
else
call nerdtree#exec('tabdo windo if winbufnr(0) ==# ' . a:bufnum . " | exec ':enew! ' | endif", 1)
endif
call nerdtree#exec('tabnext ' . s:originalTabNumber, 1)
call nerdtree#exec(s:originalWindowNumber . 'wincmd w', 1)
" 3. We don't need a previous buffer anymore
exec "bwipeout! " . a:bufnum
call nerdtree#exec('bwipeout! ' . a:bufnum, 0)
endif
endfunction
"FUNCTION: s:promptToRenameBuffer(bufnum, msg){{{1
"prints out the given msg and, if the user responds by pushing 'y' then the
"buffer with the given bufnum is replaced with a new one
"FUNCTION: s:renameBuffer(bufNum, newNodeName, isDirectory){{{1
"The buffer with the given bufNum is replaced with a new one
"
"Args:
"bufnum: the buffer that may be deleted
"msg: a message that will be echoed to the user asking them if they wish to
" del the buffer
function! s:promptToRenameBuffer(bufnum, msg, newFileName)
echo a:msg
if g:NERDTreeAutoDeleteBuffer || nr2char(getchar()) ==# 'y'
let quotedFileName = "'" . a:newFileName . "'"
" 1. ensure that a new buffer is loaded
exec "badd " . quotedFileName
" 2. ensure that all windows which display the just deleted filename
" display a buffer for a new filename.
let s:originalTabNumber = tabpagenr()
let s:originalWindowNumber = winnr()
let editStr = g:NERDTreePath.New(a:newFileName).str({'format': 'Edit'})
exec "tabdo windo if winbufnr(0) == " . a:bufnum . " | exec ':e! " . editStr . "' | endif"
exec "tabnext " . s:originalTabNumber
exec s:originalWindowNumber . "wincmd w"
" 3. We don't need a previous buffer anymore
exec "bwipeout! " . a:bufnum
"bufNum: the buffer that may be deleted
"newNodeName: the name given to the renamed node
"isDirectory: determines how to do the create the new filenames
function! s:renameBuffer(bufNum, newNodeName, isDirectory)
if a:isDirectory
let quotedFileName = fnameescape(a:newNodeName . '/' . fnamemodify(bufname(a:bufNum),':t'))
let editStr = g:NERDTreePath.New(a:newNodeName . '/' . fnamemodify(bufname(a:bufNum),':t')).str({'format': 'Edit'})
else
let quotedFileName = fnameescape(a:newNodeName)
let editStr = g:NERDTreePath.New(a:newNodeName).str({'format': 'Edit'})
endif
" 1. ensure that a new buffer is loaded
call nerdtree#exec('badd ' . quotedFileName, 1)
" 2. ensure that all windows which display the just deleted filename
" display a buffer for a new filename.
let s:originalTabNumber = tabpagenr()
let s:originalWindowNumber = winnr()
call nerdtree#exec('tabdo windo if winbufnr(0) ==# ' . a:bufNum . " | exec ':e! " . editStr . "' | endif", 1)
call nerdtree#exec('tabnext ' . s:originalTabNumber, 1)
call nerdtree#exec(s:originalWindowNumber . 'wincmd w', 1)
" 3. We don't need a previous buffer anymore
try
call nerdtree#exec('confirm bwipeout ' . a:bufNum, 0)
catch
" This happens when answering Cancel if confirmation is needed. Do nothing.
endtry
endfunction
"FUNCTION: NERDTreeAddNode(){{{1
function! NERDTreeAddNode()
let curDirNode = g:NERDTreeDirNode.GetSelected()
let newNodeName = input("Add a childnode\n".
\ "==========================================================\n".
\ "Enter the dir/file name to be created. Dirs end with a '/'\n" .
\ "", curDirNode.path.str() . g:NERDTreePath.Slash(), "file")
let prompt = s:inputPrompt('add')
let newNodeName = input(prompt, curDirNode.path.str() . g:NERDTreePath.Slash(), 'file')
if newNodeName ==# ''
call nerdtree#echo("Node Creation Aborted.")
call nerdtree#echo('Node Creation Aborted.')
return
endif
try
let newPath = g:NERDTreePath.Create(newNodeName)
let parentNode = b:NERDTreeRoot.findNode(newPath.getParent())
let parentNode = b:NERDTree.root.findNode(newPath.getParent())
let newTreeNode = g:NERDTreeFileNode.New(newPath)
let newTreeNode = g:NERDTreeFileNode.New(newPath, b:NERDTree)
" Emptying g:NERDTreeOldSortOrder forces the sort to
" recalculate the cached sortKey so nodes sort correctly.
let g:NERDTreeOldSortOrder = []
if empty(parentNode)
call b:NERDTreeRoot.refresh()
call b:NERDTree.root.refresh()
call b:NERDTree.render()
elseif parentNode.isOpen || !empty(parentNode.children)
call parentNode.addChild(newTreeNode, 1)
call NERDTreeRender()
call newTreeNode.putCursorHere(1, 0)
endif
redraw!
catch /^NERDTree/
call nerdtree#echoWarning("Node Not Created.")
call nerdtree#echoWarning('Node Not Created.')
endtry
endfunction
"FUNCTION: NERDTreeMoveNode(){{{1
function! NERDTreeMoveNode()
let curNode = g:NERDTreeFileNode.GetSelected()
let newNodePath = input("Rename the current node\n" .
\ "==========================================================\n" .
\ "Enter the new path for the node: \n" .
\ "", curNode.path.str(), "file")
let prompt = s:inputPrompt('move')
let newNodePath = input(prompt, curNode.path.str(), 'file')
if newNodePath ==# ''
call nerdtree#echo("Node Renaming Aborted.")
call nerdtree#echo('Node Renaming Aborted.')
return
endif
try
let bufnum = bufnr("^".curNode.path.str()."$")
if curNode.path.isDirectory
let l:openBuffers = filter(range(1,bufnr('$')),'bufexists(v:val) && fnamemodify(bufname(v:val),":p") =~# curNode.path.str() . "/.*"')
else
let l:openBuffers = filter(range(1,bufnr('$')),'bufexists(v:val) && fnamemodify(bufname(v:val),":p") ==# curNode.path.str()')
endif
call curNode.rename(newNodePath)
" Emptying g:NERDTreeOldSortOrder forces the sort to
" recalculate the cached sortKey so nodes sort correctly.
let g:NERDTreeOldSortOrder = []
call b:NERDTree.root.refresh()
call NERDTreeRender()
"if the node is open in a buffer, ask the user if they want to
"close that buffer
if bufnum != -1
let prompt = "\nNode renamed.\n\nThe old file is open in buffer ". bufnum . (bufwinnr(bufnum) ==# -1 ? " (hidden)" : "") .". Replace this buffer with a new file? (yN)"
call s:promptToRenameBuffer(bufnum, prompt, newNodePath)
" If the file node is open, or files under the directory node are
" open, ask the user if they want to replace the file(s) with the
" renamed files.
if !empty(l:openBuffers)
if curNode.path.isDirectory
echo "\nDirectory renamed.\n\nFiles with the old directory name are open in buffers " . join(l:openBuffers, ', ') . '. Replace these buffers with the new files? (yN)'
else
echo "\nFile renamed.\n\nThe old file is open in buffer " . l:openBuffers[0] . '. Replace this buffer with the new file? (yN)'
endif
if g:NERDTreeAutoDeleteBuffer || nr2char(getchar()) ==# 'y'
for bufNum in l:openBuffers
call s:renameBuffer(bufNum, newNodePath, curNode.path.isDirectory)
endfor
endif
endif
call curNode.putCursorHere(1, 0)
redraw
redraw!
catch /^NERDTree/
call nerdtree#echoWarning("Node Not Renamed.")
call nerdtree#echoWarning('Node Not Renamed.')
endtry
endfunction
" FUNCTION: NERDTreeDeleteNode() {{{1
function! NERDTreeDeleteNode()
let l:shellslash = &shellslash
let &shellslash = 0
let currentNode = g:NERDTreeFileNode.GetSelected()
let confirmed = 0
if currentNode.path.isDirectory
let choice =input("Delete the current node\n" .
\ "==========================================================\n" .
\ "STOP! To delete this entire directory, type 'yes'\n" .
\ "" . currentNode.path.str() . ": ")
if currentNode.path.isDirectory && ((currentNode.isOpen && currentNode.getChildCount() > 0) ||
\ (len(currentNode._glob('*', 1)) > 0))
let prompt = s:inputPrompt('deleteNonEmpty') . currentNode.path.str() . ': '
let choice = input(prompt)
let confirmed = choice ==# 'yes'
else
echo "Delete the current node\n" .
\ "==========================================================\n".
\ "Are you sure you wish to delete the node:\n" .
\ "" . currentNode.path.str() . " (yN):"
let prompt = s:inputPrompt('delete') . currentNode.path.str() . ' (yN): '
echo prompt
let choice = nr2char(getchar())
let confirmed = choice ==# 'y'
endif
if confirmed
try
call currentNode.delete()
@@ -183,60 +266,77 @@ function! NERDTreeDeleteNode()
"if the node is open in a buffer, ask the user if they want to
"close that buffer
let bufnum = bufnr("^".currentNode.path.str()."$")
let bufnum = bufnr('^'.currentNode.path.str().'$')
if buflisted(bufnum)
let prompt = "\nNode deleted.\n\nThe file is open in buffer ". bufnum . (bufwinnr(bufnum) ==# -1 ? " (hidden)" : "") .". Delete this buffer? (yN)"
let prompt = "\nNode deleted.\n\nThe file is open in buffer ". bufnum . (bufwinnr(bufnum) ==# -1 ? ' (hidden)' : '') .'. Delete this buffer? (yN)'
call s:promptToDelBuffer(bufnum, prompt)
endif
redraw
redraw!
catch /^NERDTree/
call nerdtree#echoWarning("Could not remove node")
call nerdtree#echoWarning('Could not remove node')
endtry
else
call nerdtree#echo("delete aborted")
call nerdtree#echo('delete aborted')
endif
let &shellslash = l:shellslash
endfunction
" FUNCTION: NERDTreeListNode() {{{1
function! NERDTreeListNode()
let treenode = g:NERDTreeFileNode.GetSelected()
if treenode != {}
let metadata = split(system('ls -ld ' . shellescape(treenode.path.str())), '\n')
if !empty(treenode)
let s:uname = system('uname')
let stat_cmd = 'stat -c "%s" '
if s:uname =~? 'Darwin'
let stat_cmd = 'stat -f "%z" '
endif
let cmd = 'size=$(' . stat_cmd . shellescape(treenode.path.str()) . ') && ' .
\ 'size_with_commas=$(echo $size | sed -e :a -e "s/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/;ta") && ' .
\ 'ls -ld ' . shellescape(treenode.path.str()) . ' | sed -e "s/ $size / $size_with_commas /"'
let metadata = split(system(cmd),'\n')
call nerdtree#echo(metadata[0])
else
call nerdtree#echo("No information avaialable")
call nerdtree#echo('No information available')
endif
endfunction
" FUNCTION: NERDTreeListNodeWin32() {{{1
function! NERDTreeListNodeWin32()
let treenode = g:NERDTreeFileNode.GetSelected()
if treenode != {}
let metadata = split(system('DIR /Q ' . shellescape(treenode.path.str()) . ' | FINDSTR "^[012][0-9]/[0-3][0-9]/[12][0-9][0-9][0-9]"'), '\n')
call nerdtree#echo(metadata[0])
else
call nerdtree#echo("No information avaialable")
let l:node = g:NERDTreeFileNode.GetSelected()
if !empty(l:node)
let l:path = l:node.path.str()
call nerdtree#echo(printf('%s:%s MOD:%s BYTES:%d PERMISSIONS:%s',
\ toupper(getftype(l:path)),
\ fnamemodify(l:path, ':t'),
\ strftime('%c', getftime(l:path)),
\ getfsize(l:path),
\ getfperm(l:path)))
return
endif
call nerdtree#echo('node not recognized')
endfunction
" FUNCTION: NERDTreeCopyNode() {{{1
function! NERDTreeCopyNode()
let l:shellslash = &shellslash
let &shellslash = 0
let currentNode = g:NERDTreeFileNode.GetSelected()
let newNodePath = input("Copy the current node\n" .
\ "==========================================================\n" .
\ "Enter the new path to copy the node to: \n" .
\ "", currentNode.path.str(), "file")
let prompt = s:inputPrompt('copy')
let newNodePath = input(prompt, currentNode.path.str(), 'file')
if newNodePath != ""
if newNodePath !=# ''
"strip trailing slash
let newNodePath = substitute(newNodePath, '\/$', '', '')
let confirmed = 1
if currentNode.path.copyingWillOverwrite(newNodePath)
call nerdtree#echo("Warning: copying may overwrite files! Continue? (yN)")
call nerdtree#echo('Warning: copying may overwrite files! Continue? (yN)')
let choice = nr2char(getchar())
let confirmed = choice ==# 'y'
endif
@@ -244,27 +344,46 @@ function! NERDTreeCopyNode()
if confirmed
try
let newNode = currentNode.copy(newNodePath)
" Emptying g:NERDTreeOldSortOrder forces the sort to
" recalculate the cached sortKey so nodes sort correctly.
let g:NERDTreeOldSortOrder = []
if empty(newNode)
call b:NERDTreeRoot.refresh()
call b:NERDTree.root.refresh()
call b:NERDTree.render()
else
call NERDTreeRender()
call newNode.putCursorHere(0, 0)
endif
catch /^NERDTree/
call nerdtree#echoWarning("Could not copy node")
call nerdtree#echoWarning('Could not copy node')
endtry
endif
else
call nerdtree#echo("Copy aborted.")
call nerdtree#echo('Copy aborted.')
endif
let &shellslash = l:shellslash
redraw!
endfunction
" FUNCTION: NERDTreeCopyPath() {{{1
function! NERDTreeCopyPath()
let l:nodePath = g:NERDTreeFileNode.GetSelected().path.str()
if has('clipboard')
if &clipboard ==# 'unnamedplus'
let @+ = l:nodePath
else
let @* = l:nodePath
endif
call nerdtree#echo('The path [' . l:nodePath . '] was copied to your clipboard.')
else
call nerdtree#echo('The full path is: ' . l:nodePath)
endif
redraw
endfunction
" FUNCTION: NERDTreeQuickLook() {{{1
function! NERDTreeQuickLook()
let treenode = g:NERDTreeFileNode.GetSelected()
if treenode != {}
if treenode !=# {}
call system("qlmanage -p 2>/dev/null '" . treenode.path.str() . "'")
endif
endfunction
@@ -272,7 +391,7 @@ endfunction
" FUNCTION: NERDTreeRevealInFinder() {{{1
function! NERDTreeRevealInFinder()
let treenode = g:NERDTreeFileNode.GetSelected()
if treenode != {}
if treenode !=# {}
call system("open -R '" . treenode.path.str() . "'")
endif
endfunction
@@ -280,8 +399,27 @@ endfunction
" FUNCTION: NERDTreeExecuteFile() {{{1
function! NERDTreeExecuteFile()
let treenode = g:NERDTreeFileNode.GetSelected()
if treenode != {}
if treenode !=# {}
call system("open '" . treenode.path.str() . "'")
endif
endfunction
" FUNCTION: NERDTreeRevealFileLinux() {{{1
function! NERDTreeRevealFileLinux()
let treenode = g:NERDTreeFileNode.GetSelected()
let parentnode = treenode.parent
if parentnode !=# {}
call system("xdg-open '" . parentnode.path.str() . "' &")
endif
endfunction
" FUNCTION: NERDTreeExecuteFileLinux() {{{1
function! NERDTreeExecuteFileLinux()
let treenode = g:NERDTreeFileNode.GetSelected()
if treenode !=# {}
call system("xdg-open '" . treenode.path.str() . "' &")
endif
endfunction
" vim: set sw=4 sts=4 et fdm=marker:

47
nerdtree_plugin/vcs.vim Normal file
View File

@@ -0,0 +1,47 @@
" ============================================================================
" File: vcs.vim
" Description: NERDTree plugin that provides a command to open on the root of
" a version control system repository.
" Maintainer: Phil Runninger
" License: This program is free software. It comes without any warranty,
" to the extent permitted by applicable law. You can redistribute
" it and/or modify it under the terms of the Do What The Fuck You
" Want To Public License, Version 2, as published by Sam Hocevar.
" See http://sam.zoy.org/wtfpl/COPYING for more details.
"
" ============================================================================
command! -n=? -complete=dir -bar NERDTreeVCS :call <SID>CreateTabTreeVCS('<args>')
command! -n=? -complete=dir -bar NERDTreeToggleVCS :call <SID>ToggleTabTreeVCS('<args>')
" FUNCTION: s:CreateTabTreeVCS(a:name) {{{1
function! s:CreateTabTreeVCS(name)
let l:path = g:NERDTreeCreator._pathForString(a:name)
let l:path = s:FindParentVCSRoot(l:path)
call g:NERDTreeCreator.createTabTree(empty(l:path) ? '' : l:path._str())
endfunction
" FUNCTION: s:ToggleTabTreeVCS(a:name) {{{1
" Behaves the same as ToggleTabTree except roots directory at VCS root
function! s:ToggleTabTreeVCS(name)
let l:path = g:NERDTreeCreator._pathForString(a:name)
let l:path = s:FindParentVCSRoot(l:path)
call g:NERDTreeCreator.toggleTabTree(empty(l:path) ? '' : l:path._str())
endfunction
" FUNCTION: s:FindParentVCSRoot(a:path) {{{1
" Finds the root version control system folder of the given path. If a:path is
" not part of a repository, return the original path.
function! s:FindParentVCSRoot(path)
let l:path = a:path
while !empty(l:path) &&
\ l:path._str() !~# '^\(\a:\\\|\/\)$' &&
\ !isdirectory(l:path._str() . '/.git') &&
\ !isdirectory(l:path._str() . '/.svn') &&
\ !isdirectory(l:path._str() . '/.hg') &&
\ !isdirectory(l:path._str() . '/.bzr') &&
\ !isdirectory(l:path._str() . '/_darcs')
let l:path = l:path.getParent()
endwhile
return (empty(l:path) || l:path._str() =~# '^\(\a:\\\|\/\)$') ? a:path : l:path
endfunction

View File

@@ -11,18 +11,20 @@
"
" SECTION: Script init stuff {{{1
"============================================================
if exists("loaded_nerd_tree")
scriptencoding utf-8
if exists('loaded_nerd_tree')
finish
endif
if v:version < 700
echoerr "NERDTree: this plugin requires vim >= 7. DOWNLOAD IT! You'll thank me later!"
if v:version < 703
echoerr "NERDTree: this plugin requires vim >= 7.3. DOWNLOAD IT! You'll thank me later!"
finish
endif
let loaded_nerd_tree = 1
"for line continuation - i.e dont want C in &cpo
let s:old_cpo = &cpo
set cpo&vim
"for line continuation - i.e dont want C in &cpoptions
let s:old_cpo = &cpoptions
set cpoptions&vim
"Function: s:initVariable() function {{{2
"This function is used to initialise a given variable to a given value. The
@@ -36,106 +38,129 @@ set cpo&vim
"1 if the var is set, 0 otherwise
function! s:initVariable(var, value)
if !exists(a:var)
exec 'let ' . a:var . ' = ' . "'" . substitute(a:value, "'", "''", "g") . "'"
exec 'let ' . a:var . ' = ' . "'" . substitute(a:value, "'", "''", 'g') . "'"
return 1
endif
return 0
endfunction
"SECTION: Init variable calls and other random constants {{{2
call s:initVariable("g:NERDTreeAutoCenter", 1)
call s:initVariable("g:NERDTreeAutoCenterThreshold", 3)
call s:initVariable("g:NERDTreeCaseSensitiveSort", 0)
call s:initVariable("g:NERDTreeSortHiddenFirst", 1)
call s:initVariable("g:NERDTreeChDirMode", 0)
call s:initVariable("g:NERDTreeMinimalUI", 0)
if !exists("g:NERDTreeIgnore")
call s:initVariable('g:NERDTreeAutoCenter', 1)
call s:initVariable('g:NERDTreeAutoCenterThreshold', 3)
call s:initVariable('g:NERDTreeCaseSensitiveSort', 0)
call s:initVariable('g:NERDTreeNaturalSort', 0)
call s:initVariable('g:NERDTreeSortHiddenFirst', 1)
call s:initVariable('g:NERDTreeUseTCD', 0)
call s:initVariable('g:NERDTreeChDirMode', 0)
call s:initVariable('g:NERDTreeCreatePrefix', 'silent')
call s:initVariable('g:NERDTreeMinimalUI', 0)
call s:initVariable('g:NERDTreeMinimalMenu', 0)
if !exists('g:NERDTreeIgnore')
let g:NERDTreeIgnore = ['\~$']
endif
call s:initVariable("g:NERDTreeBookmarksFile", expand('$HOME') . '/.NERDTreeBookmarks')
call s:initVariable("g:NERDTreeBookmarksSort", 1)
call s:initVariable("g:NERDTreeHighlightCursorline", 1)
call s:initVariable("g:NERDTreeHijackNetrw", 1)
call s:initVariable("g:NERDTreeMouseMode", 1)
call s:initVariable("g:NERDTreeNotificationThreshold", 100)
call s:initVariable("g:NERDTreeQuitOnOpen", 0)
call s:initVariable("g:NERDTreeRespectWildIgnore", 0)
call s:initVariable("g:NERDTreeShowBookmarks", 0)
call s:initVariable("g:NERDTreeShowFiles", 1)
call s:initVariable("g:NERDTreeShowHidden", 0)
call s:initVariable("g:NERDTreeShowLineNumbers", 0)
call s:initVariable("g:NERDTreeSortDirs", 1)
call s:initVariable("g:NERDTreeDirArrows", !nerdtree#runningWindows())
call s:initVariable("g:NERDTreeDirArrowExpandable", "▸")
call s:initVariable("g:NERDTreeDirArrowCollapsible", "▾")
call s:initVariable("g:NERDTreeCascadeOpenSingleChildDir", 1)
call s:initVariable('g:NERDTreeBookmarksFile', expand('$HOME') . '/.NERDTreeBookmarks')
call s:initVariable('g:NERDTreeBookmarksSort', 1)
call s:initVariable('g:NERDTreeHighlightCursorline', 1)
call s:initVariable('g:NERDTreeHijackNetrw', 1)
call s:initVariable('g:NERDTreeMarkBookmarks', 1)
call s:initVariable('g:NERDTreeMouseMode', 1)
call s:initVariable('g:NERDTreeNotificationThreshold', 100)
call s:initVariable('g:NERDTreeQuitOnOpen', 0)
call s:initVariable('g:NERDTreeRespectWildIgnore', 0)
call s:initVariable('g:NERDTreeShowBookmarks', 0)
call s:initVariable('g:NERDTreeShowFiles', 1)
call s:initVariable('g:NERDTreeShowHidden', 0)
call s:initVariable('g:NERDTreeShowLineNumbers', 0)
call s:initVariable('g:NERDTreeSortDirs', 1)
if !exists("g:NERDTreeSortOrder")
let g:NERDTreeSortOrder = ['\/$', '*', '\.swp$', '\.bak$', '\~$']
if !nerdtree#runningWindows() && !nerdtree#runningCygwin()
call s:initVariable('g:NERDTreeDirArrowExpandable', '▸')
call s:initVariable('g:NERDTreeDirArrowCollapsible', '▾')
else
"if there isnt a * in the sort sequence then add one
if count(g:NERDTreeSortOrder, '*') < 1
call add(g:NERDTreeSortOrder, '*')
endif
call s:initVariable('g:NERDTreeDirArrowExpandable', '+')
call s:initVariable('g:NERDTreeDirArrowCollapsible', '~')
endif
call s:initVariable('g:NERDTreeCascadeOpenSingleChildDir', 1)
call s:initVariable('g:NERDTreeCascadeSingleChildDir', 1)
if !exists('g:NERDTreeSortOrder')
let g:NERDTreeSortOrder = ['\/$', '*', '\.swp$', '\.bak$', '\~$']
endif
let g:NERDTreeOldSortOrder = []
call s:initVariable('g:NERDTreeGlyphReadOnly', 'RO')
if has('conceal')
call s:initVariable('g:NERDTreeNodeDelimiter', "\x07")
elseif (g:NERDTreeDirArrowExpandable ==# "\u00a0" || g:NERDTreeDirArrowCollapsible ==# "\u00a0")
call s:initVariable('g:NERDTreeNodeDelimiter', "\u00b7")
else
call s:initVariable('g:NERDTreeNodeDelimiter', "\u00a0")
endif
if !exists('g:NERDTreeStatusline')
"the exists() crap here is a hack to stop vim spazzing out when
"loading a session that was created with an open nerd tree. It spazzes
"because it doesnt store b:NERDTreeRoot (its a b: var, and its a hash)
let g:NERDTreeStatusline = "%{exists('b:NERDTreeRoot')?b:NERDTreeRoot.path.str():''}"
"because it doesnt store b:NERDTree(its a b: var, and its a hash)
let g:NERDTreeStatusline = "%{exists('b:NERDTree')?b:NERDTree.root.path.str():''}"
endif
call s:initVariable("g:NERDTreeWinPos", "left")
call s:initVariable("g:NERDTreeWinSize", 31)
call s:initVariable('g:NERDTreeWinPos', 'left')
call s:initVariable('g:NERDTreeWinSize', 31)
"init the shell commands that will be used to copy nodes, and remove dir trees
"
"Note: the space after the command is important
if nerdtree#runningWindows()
call s:initVariable("g:NERDTreeRemoveDirCmd", 'rmdir /s /q ')
call s:initVariable('g:NERDTreeRemoveDirCmd', 'rmdir /s /q ')
call s:initVariable('g:NERDTreeCopyDirCmd', 'xcopy /s /e /i /y /q ')
call s:initVariable('g:NERDTreeCopyFileCmd', 'copy /y ')
else
call s:initVariable("g:NERDTreeRemoveDirCmd", 'rm -rf ')
call s:initVariable("g:NERDTreeCopyCmd", 'cp -r ')
call s:initVariable('g:NERDTreeRemoveDirCmd', 'rm -rf ')
call s:initVariable('g:NERDTreeCopyCmd', 'cp -r ')
endif
"SECTION: Init variable calls for key mappings {{{2
call s:initVariable("g:NERDTreeMapActivateNode", "o")
call s:initVariable("g:NERDTreeMapChangeRoot", "C")
call s:initVariable("g:NERDTreeMapChdir", "cd")
call s:initVariable("g:NERDTreeMapCloseChildren", "X")
call s:initVariable("g:NERDTreeMapCloseDir", "x")
call s:initVariable("g:NERDTreeMapDeleteBookmark", "D")
call s:initVariable("g:NERDTreeMapMenu", "m")
call s:initVariable("g:NERDTreeMapHelp", "?")
call s:initVariable("g:NERDTreeMapJumpFirstChild", "K")
call s:initVariable("g:NERDTreeMapJumpLastChild", "J")
call s:initVariable("g:NERDTreeMapJumpNextSibling", "<C-j>")
call s:initVariable("g:NERDTreeMapJumpParent", "p")
call s:initVariable("g:NERDTreeMapJumpPrevSibling", "<C-k>")
call s:initVariable("g:NERDTreeMapJumpRoot", "P")
call s:initVariable("g:NERDTreeMapOpenExpl", "e")
call s:initVariable("g:NERDTreeMapOpenInTab", "t")
call s:initVariable("g:NERDTreeMapOpenInTabSilent", "T")
call s:initVariable("g:NERDTreeMapOpenRecursively", "O")
call s:initVariable("g:NERDTreeMapOpenSplit", "i")
call s:initVariable("g:NERDTreeMapOpenVSplit", "s")
call s:initVariable("g:NERDTreeMapPreview", "g" . NERDTreeMapActivateNode)
call s:initVariable("g:NERDTreeMapPreviewSplit", "g" . NERDTreeMapOpenSplit)
call s:initVariable("g:NERDTreeMapPreviewVSplit", "g" . NERDTreeMapOpenVSplit)
call s:initVariable("g:NERDTreeMapQuit", "q")
call s:initVariable("g:NERDTreeMapRefresh", "r")
call s:initVariable("g:NERDTreeMapRefreshRoot", "R")
call s:initVariable("g:NERDTreeMapToggleBookmarks", "B")
call s:initVariable("g:NERDTreeMapToggleFiles", "F")
call s:initVariable("g:NERDTreeMapToggleFilters", "f")
call s:initVariable("g:NERDTreeMapToggleHidden", "I")
call s:initVariable("g:NERDTreeMapToggleZoom", "A")
call s:initVariable("g:NERDTreeMapUpdir", "u")
call s:initVariable("g:NERDTreeMapUpdirKeepOpen", "U")
call s:initVariable("g:NERDTreeMapCWD", "CD")
call s:initVariable('g:NERDTreeMapCustomOpen', '<CR>')
call s:initVariable('g:NERDTreeMapActivateNode', 'o')
call s:initVariable('g:NERDTreeMapChangeRoot', 'C')
call s:initVariable('g:NERDTreeMapChdir', 'cd')
call s:initVariable('g:NERDTreeMapCloseChildren', 'X')
call s:initVariable('g:NERDTreeMapCloseDir', 'x')
call s:initVariable('g:NERDTreeMapDeleteBookmark', 'D')
call s:initVariable('g:NERDTreeMapMenu', 'm')
call s:initVariable('g:NERDTreeMapHelp', '?')
call s:initVariable('g:NERDTreeMapJumpFirstChild', 'K')
call s:initVariable('g:NERDTreeMapJumpLastChild', 'J')
call s:initVariable('g:NERDTreeMapJumpNextSibling', '<C-j>')
call s:initVariable('g:NERDTreeMapJumpParent', 'p')
call s:initVariable('g:NERDTreeMapJumpPrevSibling', '<C-k>')
call s:initVariable('g:NERDTreeMapJumpRoot', 'P')
call s:initVariable('g:NERDTreeMapOpenExpl', 'e')
call s:initVariable('g:NERDTreeMapOpenInTab', 't')
call s:initVariable('g:NERDTreeMapOpenInTabSilent', 'T')
call s:initVariable('g:NERDTreeMapOpenRecursively', 'O')
call s:initVariable('g:NERDTreeMapOpenSplit', 'i')
call s:initVariable('g:NERDTreeMapOpenVSplit', 's')
call s:initVariable('g:NERDTreeMapPreview', 'g' . NERDTreeMapActivateNode)
call s:initVariable('g:NERDTreeMapPreviewSplit', 'g' . NERDTreeMapOpenSplit)
call s:initVariable('g:NERDTreeMapPreviewVSplit', 'g' . NERDTreeMapOpenVSplit)
call s:initVariable('g:NERDTreeMapQuit', 'q')
call s:initVariable('g:NERDTreeMapRefresh', 'r')
call s:initVariable('g:NERDTreeMapRefreshRoot', 'R')
call s:initVariable('g:NERDTreeMapToggleBookmarks', 'B')
call s:initVariable('g:NERDTreeMapToggleFiles', 'F')
call s:initVariable('g:NERDTreeMapToggleFilters', 'f')
call s:initVariable('g:NERDTreeMapToggleHidden', 'I')
call s:initVariable('g:NERDTreeMapToggleZoom', 'A')
call s:initVariable('g:NERDTreeMapUpdir', 'u')
call s:initVariable('g:NERDTreeMapUpdirKeepOpen', 'U')
call s:initVariable('g:NERDTreeMapCWD', 'CD')
call s:initVariable('g:NERDTreeMenuDown', 'j')
call s:initVariable('g:NERDTreeMenuUp', 'k')
"SECTION: Load class files{{{2
call nerdtree#loadClassFiles()
@@ -148,16 +173,22 @@ call nerdtree#ui_glue#setupCommands()
"============================================================
augroup NERDTree
"Save the cursor position whenever we close the nerd tree
exec "autocmd BufLeave ". g:NERDTreeCreator.BufNamePrefix() ."* if g:NERDTree.IsOpen() | call b:NERDTree.ui.saveScreenState() | endif"
exec 'autocmd BufLeave,WinLeave '. g:NERDTreeCreator.BufNamePrefix() .'* if g:NERDTree.IsOpen() | call b:NERDTree.ui.saveScreenState() | endif'
"disallow insert mode in the NERDTree
exec "autocmd BufEnter ". g:NERDTreeCreator.BufNamePrefix() ."* stopinsert"
exec 'autocmd BufEnter,WinEnter '. g:NERDTreeCreator.BufNamePrefix() .'* stopinsert'
augroup END
if g:NERDTreeHijackNetrw
augroup NERDTreeHijackNetrw
autocmd VimEnter * silent! autocmd! FileExplorer
au BufEnter,VimEnter * call nerdtree#checkForBrowse(expand("<amatch>"))
au BufEnter,VimEnter * call nerdtree#checkForBrowse(expand('<amatch>'))
augroup END
endif
if g:NERDTreeChDirMode ==# 3
augroup NERDTreeChDirOnTabSwitch
autocmd TabEnter * if g:NERDTree.ExistsForTab()|call g:NERDTree.ForCurrentTab().getRoot().path.changeToDir()|endif
augroup END
endif
@@ -188,13 +219,33 @@ function! NERDTreeFocus()
if g:NERDTree.IsOpen()
call g:NERDTree.CursorToTreeWin()
else
call g:NERDTreeCreator.TogglePrimary("")
call g:NERDTreeCreator.ToggleTabTree('')
endif
endfunction
function! NERDTreeCWD()
if empty(getcwd())
call nerdtree#echoWarning('current directory does not exist')
return
endif
try
let l:cwdPath = g:NERDTreePath.New(getcwd())
catch /^NERDTree.InvalidArgumentsError/
call nerdtree#echoWarning('current directory does not exist')
return
endtry
call NERDTreeFocus()
call nerdtree#ui_glue#chRootCwd()
if b:NERDTree.root.path.equals(l:cwdPath)
return
endif
let l:newRoot = g:NERDTreeFileNode.New(l:cwdPath, b:NERDTree)
call b:NERDTree.changeRoot(l:newRoot)
normal! ^
endfunction
function! NERDTreeAddPathFilter(callback)
@@ -204,7 +255,7 @@ endfunction
" SECTION: Post Source Actions {{{1
call nerdtree#postSourceActions()
"reset &cpo back to users setting
let &cpo = s:old_cpo
"reset &cpoptions back to users setting
let &cpoptions = s:old_cpo
" vim: set sw=4 sts=4 et fdm=marker:

BIN
screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

View File

@@ -1,14 +1,14 @@
let s:tree_up_dir_line = '.. (up a dir)'
syn match NERDTreeIgnore #\~#
syn match NERDTreeIgnore #\[RO\]#
exec 'syn match NERDTreeIgnore #\['.g:NERDTreeGlyphReadOnly.'\]#'
"highlighting for the .. (up dir) line at the top of the tree
execute "syn match NERDTreeUp #\\V". s:tree_up_dir_line ."#"
execute "syn match NERDTreeUp #\\V". s:tree_up_dir_line .'#'
"quickhelp syntax elements
syn match NERDTreeHelpKey #" \{1,2\}[^ ]*:#ms=s+2,me=e-1
syn match NERDTreeHelpKey #" \{1,2\}[^ ]*,#ms=s+2,me=e-1
syn match NERDTreeHelpTitle #" .*\~#ms=s+2,me=e-1
syn match NERDTreeHelpTitle #" .*\~$#ms=s+2,me=e-1
syn match NERDTreeToggleOn #(on)#ms=s+1,he=e-1
syn match NERDTreeToggleOff #(off)#ms=e-3,me=e-1
syn match NERDTreeHelpCommand #" :.\{-}\>#hs=s+3
@@ -22,42 +22,27 @@ syn match NERDTreeLinkDir #.*/ ->#me=e-3 containedin=NERDTreeDir
"highlighing for directory nodes and file nodes
syn match NERDTreeDirSlash #/# containedin=NERDTreeDir
if g:NERDTreeDirArrows
exec 'syn match NERDTreeClosable #'.escape(g:NERDTreeDirArrowCollapsible, '~').'# containedin=NERDTreeDir,NERDTreeFile'
exec 'syn match NERDTreeOpenable #'.escape(g:NERDTreeDirArrowExpandable, '~').'# containedin=NERDTreeDir,NERDTreeFile'
exec 'syn match NERDTreeClosable #' . escape(g:NERDTreeDirArrowCollapsible, '~') . '\ze .*/# containedin=NERDTreeDir,NERDTreeFile'
exec 'syn match NERDTreeOpenable #' . escape(g:NERDTreeDirArrowExpandable, '~') . '\ze .*/# containedin=NERDTreeDir,NERDTreeFile'
let s:dirArrows = escape(g:NERDTreeDirArrowCollapsible, '~').escape(g:NERDTreeDirArrowExpandable, '~')
exec 'syn match NERDTreeDir #[^'.s:dirArrows.' ].*/#'
syn match NERDTreeExecFile #^ .*\*\($\| \)# contains=NERDTreeRO,NERDTreeBookmark
exec 'syn match NERDTreeFile #^[^"\.'.s:dirArrows.'] *[^'.s:dirArrows.']*# contains=NERDTreeLink,NERDTreeRO,NERDTreeBookmark,NERDTreeExecFile'
let s:dirArrows = escape(g:NERDTreeDirArrowCollapsible, '~]\-').escape(g:NERDTreeDirArrowExpandable, '~]\-')
exec 'syn match NERDTreeDir #[^'.s:dirArrows.' ].*/#'
syn match NERDTreeExecFile '^ .*\*\($\| \)' contains=NERDTreeRO,NERDTreeBookmark
exec 'syn match NERDTreeFile #^[^"\.'.s:dirArrows.'] *[^'.s:dirArrows.']*# contains=NERDTreeLink,NERDTreeRO,NERDTreeBookmark,NERDTreeExecFile'
"highlighting for readonly files
syn match NERDTreeRO # *\zs.*\ze \[RO\]# contains=NERDTreeIgnore,NERDTreeBookmark,NERDTreeFile
"highlighting for readonly files
exec 'syn match NERDTreeRO # *\zs.*\ze \['.g:NERDTreeGlyphReadOnly.'\]# contains=NERDTreeIgnore,NERDTreeBookmark,NERDTreeFile'
syn match NERDTreeFlags #^ *\zs\[.\]# containedin=NERDTreeFile,NERDTreeExecFile
syn match NERDTreeFlags #\[.\]# containedin=NERDTreeDir
syn match NERDTreeFlags #^ *\zs\[[^\]]*\]# containedin=NERDTreeFile,NERDTreeExecFile
syn match NERDTreeFlags #\[[^\]]*\]# containedin=NERDTreeDir
"highlighing to conceal the delimiter around the file/dir name
if has('conceal')
exec 'syn match NERDTreeNodeDelimiters #\%d' . char2nr(g:NERDTreeNodeDelimiter) . '# conceal containedin=ALL'
setlocal conceallevel=3 concealcursor=nvic
else
"highlighting for the ~/+ symbols for the directory nodes
syn match NERDTreeClosable #\~\<#
syn match NERDTreeClosable #\~\.#
syn match NERDTreeOpenable #+\<#
syn match NERDTreeOpenable #+\.#he=e-1
"highlighting for the tree structural parts
syn match NERDTreePart #|#
syn match NERDTreePart #`#
syn match NERDTreePartFile #[|`]-#hs=s+1 contains=NERDTreePart
syn match NERDTreeDir #[^-| `].*/# contains=NERDTreeLink,NERDTreeOpenable,NERDTreeClosable
syn match NERDTreeExecFile #[|` ].*\*\($\| \)# contains=NERDTreeLink,NERDTreePart,NERDTreePartFile,NERDTreeBookmark
syn match NERDTreeFile #|-.*# contains=NERDTreeLink,NERDTreePart,NERDTreePartFile,NERDTreeBookmark,NERDTreeExecFile
syn match NERDTreeFile #`-.*# contains=NERDTreeLink,NERDTreePart,NERDTreePartFile,NERDTreeBookmark,NERDTreeExecFile
"highlighting for readonly files
syn match NERDTreeRO #|-.*\[RO\]#he=e-5 contains=NERDTreeIgnore,NERDTreeBookmark,NERDTreePart,NERDTreePartFile
syn match NERDTreeFlags #-\[.\]# containedin=NERDTreeFile,NERDTreePartFile
syn match NERDTreeFlags #[+~]\zs\[.\]# containedin=NERDTreeDir
exec 'syn match NERDTreeNodeDelimiters #\%d' . char2nr(g:NERDTreeNodeDelimiter) . '# containedin=ALL'
hi! link NERDTreeNodeDelimiters Ignore
endif
syn match NERDTreeCWD #^[</].*$#
@@ -96,8 +81,8 @@ hi def link NERDTreeDir Directory
hi def link NERDTreeUp Directory
hi def link NERDTreeFile Normal
hi def link NERDTreeCWD Statement
hi def link NERDTreeOpenable Title
hi def link NERDTreeClosable Title
hi def link NERDTreeOpenable Directory
hi def link NERDTreeClosable Directory
hi def link NERDTreeIgnore ignore
hi def link NERDTreeRO WarningMsg
hi def link NERDTreeBookmark Statement