mirror of
https://github.com/preservim/nerdtree.git
synced 2025-11-08 11:23:48 -05:00
Compare commits
388 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3b1a850b85 | ||
|
|
89a1a4355b | ||
|
|
62b78de367 | ||
|
|
aef6baf6e2 | ||
|
|
06c9d9c963 | ||
|
|
ca16df25fa | ||
|
|
cce6fb373f | ||
|
|
1c803b36f6 | ||
|
|
2cbc76bbfd | ||
|
|
347a58b0b0 | ||
|
|
33fe2fdf16 | ||
|
|
c46fbd21e3 | ||
|
|
b213fae779 | ||
|
|
b9a421b2d5 | ||
|
|
254f7678f3 | ||
|
|
318fb2d0de | ||
|
|
9bedadd062 | ||
|
|
12dea6ccb2 | ||
|
|
70dc34cb69 | ||
|
|
28eb47e267 | ||
|
|
67fa9b3116 | ||
|
|
a3f0e66793 | ||
|
|
3c06335782 | ||
|
|
9226eab2a8 | ||
|
|
e126b8745d | ||
|
|
7513f256aa | ||
|
|
839cddc750 | ||
|
|
e3e600608a | ||
|
|
0efbdfbc5a | ||
|
|
288669db1f | ||
|
|
e1916d6fe7 | ||
|
|
84737f2ebe | ||
|
|
b6cde142dd | ||
|
|
9eda9ce6a1 | ||
|
|
2e0b101d57 | ||
|
|
f4d2b301b7 | ||
|
|
4ef9967e29 | ||
|
|
842f5cabaa | ||
|
|
cce52fb9c5 | ||
|
|
c05615fd80 | ||
|
|
5e8aa9e721 | ||
|
|
74be22deb7 | ||
|
|
8cc154d4b0 | ||
|
|
72c3656799 | ||
|
|
a4dd4e1dce | ||
|
|
c1876da09c | ||
|
|
743b849dcf | ||
|
|
ffa8be8aa7 | ||
|
|
c905a5d7b8 | ||
|
|
370eb5bcb4 | ||
|
|
f406af39cf | ||
|
|
64c3a6aed3 | ||
|
|
6fe967b3b3 | ||
|
|
8d005db94f | ||
|
|
91e0f2253f | ||
|
|
c372911c4a | ||
|
|
388623e702 | ||
|
|
92a20c0736 | ||
|
|
52151fb307 | ||
|
|
f98078d3ae | ||
|
|
820955e773 | ||
|
|
5381197747 | ||
|
|
6b6cadf86c | ||
|
|
729e8014b9 | ||
|
|
bba4b0087b | ||
|
|
599238ad99 | ||
|
|
cd1f2c803e | ||
|
|
e9d3f72d9c | ||
|
|
b3804dcd71 | ||
|
|
15d06b676d | ||
|
|
2cd4331b78 | ||
|
|
5442d5e04a | ||
|
|
7e00a9971e | ||
|
|
7c8c811f00 | ||
|
|
c726ec7318 | ||
|
|
129a241b22 | ||
|
|
f78cf63627 | ||
|
|
808f5b225b | ||
|
|
b8cc044760 | ||
|
|
b10c61b063 | ||
|
|
18071f5999 | ||
|
|
39a89f5e50 | ||
|
|
026bfaf35e | ||
|
|
7d9a3f0e8b | ||
|
|
b6978ecd70 | ||
|
|
192b07ce1f | ||
|
|
e653a68270 | ||
|
|
9e9d16a38a | ||
|
|
43d569195c | ||
|
|
456367ab07 | ||
|
|
eee179f0bf | ||
|
|
e99a7a0313 | ||
|
|
1e2b7ef98d | ||
|
|
6ef3213cd0 | ||
|
|
a053925279 | ||
|
|
703e1ef4fe | ||
|
|
d6032c876c | ||
|
|
08db3a0eea | ||
|
|
a053179d6a | ||
|
|
c0d87db309 | ||
|
|
26abd33ad9 | ||
|
|
eb048a3070 | ||
|
|
bf4591c5d8 | ||
|
|
657be6b24d | ||
|
|
c6d757f198 | ||
|
|
9af083a6d1 | ||
|
|
57c825a169 | ||
|
|
0788027b55 | ||
|
|
80ee0897ff | ||
|
|
35953042fb | ||
|
|
c4f8a0f370 | ||
|
|
6188c5ea5f | ||
|
|
0bf429bac3 | ||
|
|
f9e83ad8bd | ||
|
|
2c38519733 | ||
|
|
68313ef0f5 | ||
|
|
2437b75479 | ||
|
|
925a96f58d | ||
|
|
abf200397f | ||
|
|
b45f2c27ea | ||
|
|
cc60495fe0 | ||
|
|
0972cda243 | ||
|
|
d3a7cd20ae | ||
|
|
ec3c3b0fa1 | ||
|
|
6aff1b6cd3 | ||
|
|
164131762f | ||
|
|
38d4d2288a | ||
|
|
1792b6a75b | ||
|
|
727770147a | ||
|
|
435861ee69 | ||
|
|
a0e49c9b11 | ||
|
|
b37495fa98 | ||
|
|
a172d7cfcb | ||
|
|
b702500f77 | ||
|
|
9afa6b3828 | ||
|
|
ed446e5cbe | ||
|
|
f6987b7ea6 | ||
|
|
d6fe203dec | ||
|
|
dc349a072a | ||
|
|
e47e588705 | ||
|
|
a0f3bf3ed6 | ||
|
|
68572ef461 | ||
|
|
183bb53485 | ||
|
|
6e26222a30 | ||
|
|
a019486dc8 | ||
|
|
1d14961285 | ||
|
|
8f052c5b47 | ||
|
|
1e93f6840a | ||
|
|
c6a68d4b96 | ||
|
|
d745e11b42 | ||
|
|
e6a116a9cd | ||
|
|
f4df038366 | ||
|
|
5fc48b0b13 | ||
|
|
af3ba1ef4e | ||
|
|
fa65ec60ea | ||
|
|
d90b2af474 | ||
|
|
0ff697eb40 | ||
|
|
57788abd6f | ||
|
|
f6dad4796e | ||
|
|
01b011d38e | ||
|
|
344119439e | ||
|
|
90d08dc626 | ||
|
|
5301dd24fb | ||
|
|
496d9a17d8 | ||
|
|
fc14b4f5df | ||
|
|
509122df20 | ||
|
|
9f985514f0 | ||
|
|
193fed598b | ||
|
|
b4b99c39fa | ||
|
|
461ea6d2d8 | ||
|
|
c20ac9c27f | ||
|
|
fc55d012ee | ||
|
|
2129740419 | ||
|
|
12960b966f | ||
|
|
8cbea5109e | ||
|
|
e48ae299f9 | ||
|
|
ea01a691a2 | ||
|
|
3485b2a939 | ||
|
|
b89de09810 | ||
|
|
ac94cd28c2 | ||
|
|
e0e36c5385 | ||
|
|
f526c4e652 | ||
|
|
70c8cb9bfa | ||
|
|
93356cd92b | ||
|
|
b6e3c0db30 | ||
|
|
e59d02575e | ||
|
|
21c470c316 | ||
|
|
4c409a1640 | ||
|
|
e27cd86a9b | ||
|
|
31dbf1c139 | ||
|
|
c9f7014034 | ||
|
|
ae1c95bcbc | ||
|
|
0a0374b826 | ||
|
|
870bedef21 | ||
|
|
d9074c2753 | ||
|
|
3cb90cb18d | ||
|
|
26168324fc | ||
|
|
f0a97209f1 | ||
|
|
97433edd43 | ||
|
|
a8c6245057 | ||
|
|
f554c20cb2 | ||
|
|
cb9f4db6ff | ||
|
|
8a6ae7c633 | ||
|
|
5782b228e4 | ||
|
|
876283b07c | ||
|
|
f4ff6dcf84 | ||
|
|
d7cf9a2a98 | ||
|
|
a32a55e8d9 | ||
|
|
7a2fc6b6b9 | ||
|
|
19b8dd7b60 | ||
|
|
72f9135d19 | ||
|
|
b5e54d255e | ||
|
|
1a121337dd | ||
|
|
a7d667b81b | ||
|
|
8cd17c1a47 | ||
|
|
d68c9abca8 | ||
|
|
5af263c2df | ||
|
|
35724ee206 | ||
|
|
719d6785d4 | ||
|
|
1269c070cd | ||
|
|
7027fd156e | ||
|
|
6efef8651e | ||
|
|
eae5d02fa9 | ||
|
|
e2a9929bbe | ||
|
|
5daec4c7b7 | ||
|
|
3a7694aa55 | ||
|
|
1f089a362b | ||
|
|
3245007f0e | ||
|
|
a3fdf1e3c1 | ||
|
|
49c165a103 | ||
|
|
ab0a3a7c24 | ||
|
|
c1b71dcfc5 | ||
|
|
ef35ee8918 | ||
|
|
7f4a7205dc | ||
|
|
ebc206e58d | ||
|
|
8660541333 | ||
|
|
18f04e0824 | ||
|
|
2e43ad074b | ||
|
|
2b2b35ceda | ||
|
|
7ed79c00c1 | ||
|
|
779e13374a | ||
|
|
2a97fb0fda | ||
|
|
b877fc65d8 | ||
|
|
b0c44c7be1 | ||
|
|
4a487474c4 | ||
|
|
626e80f6e4 | ||
|
|
54b423e0f8 | ||
|
|
c934b50c0d | ||
|
|
5ce9bda392 | ||
|
|
1d83e4c1ce | ||
|
|
5f3a44d066 | ||
|
|
2c3249de68 | ||
|
|
17713ee293 | ||
|
|
9bd34f9424 | ||
|
|
9b3487db64 | ||
|
|
471a03c9d9 | ||
|
|
3063dfb766 | ||
|
|
a03a639390 | ||
|
|
c0b90811b0 | ||
|
|
b0f60552ea | ||
|
|
81a42acb97 | ||
|
|
a9ab90198b | ||
|
|
84c681989d | ||
|
|
3a7293d450 | ||
|
|
c11affabb4 | ||
|
|
2a7a375729 | ||
|
|
0b65089122 | ||
|
|
5aec5ecfef | ||
|
|
519436ad20 | ||
|
|
66e00e61a2 | ||
|
|
d99967cadd | ||
|
|
0b84d458d6 | ||
|
|
fce10d1b10 | ||
|
|
925627536e | ||
|
|
23ba97d263 | ||
|
|
0c0bde3106 | ||
|
|
0caa466854 | ||
|
|
45f4d61f04 | ||
|
|
97d2d70f6c | ||
|
|
649d31384c | ||
|
|
bf193320f8 | ||
|
|
e671e403dd | ||
|
|
281701021c | ||
|
|
9c73a19f56 | ||
|
|
dee152d08f | ||
|
|
eee431dbd4 | ||
|
|
48df6bfd6e | ||
|
|
513bf64555 | ||
|
|
2027ae03db | ||
|
|
4477078170 | ||
|
|
84e7a77a7e | ||
|
|
334fb0e687 | ||
|
|
25ec8b47c6 | ||
|
|
32186f1660 | ||
|
|
b9b53d814b | ||
|
|
10ac799808 | ||
|
|
148e8570df | ||
|
|
a229d8bb61 | ||
|
|
b78fa83373 | ||
|
|
1c0d9efe6c | ||
|
|
4cb9762999 | ||
|
|
a9a5aec9c0 | ||
|
|
f26eaf8355 | ||
|
|
408f7a572c | ||
|
|
08773e1e74 | ||
|
|
682a7b64db | ||
|
|
af64474ebd | ||
|
|
26b40d162c | ||
|
|
f640646f2c | ||
|
|
1a6c502f19 | ||
|
|
5d7bc3b0b8 | ||
|
|
f173f62c9a | ||
|
|
1993700bef | ||
|
|
a536498601 | ||
|
|
fa57b8128d | ||
|
|
4ebd7de207 | ||
|
|
d34f3a257f | ||
|
|
b9ad20c0b1 | ||
|
|
9ff2096b04 | ||
|
|
9aae0be318 | ||
|
|
29cf96e45b | ||
|
|
d2f8bb8e8a | ||
|
|
ac2d3b077a | ||
|
|
4428aba2a2 | ||
|
|
0b73db9368 | ||
|
|
7730c8731a | ||
|
|
b5519197e9 | ||
|
|
40993e9010 | ||
|
|
916f6b8f8f | ||
|
|
0ef5b6be4f | ||
|
|
d2509d279e | ||
|
|
2e2b649232 | ||
|
|
2924ab2071 | ||
|
|
c99312442b | ||
|
|
d280b15ba9 | ||
|
|
1ac98de88a | ||
|
|
15445be5fb | ||
|
|
5294593b14 | ||
|
|
35b04fa3df | ||
|
|
5458680265 | ||
|
|
35c859179d | ||
|
|
0cb999c070 | ||
|
|
7954eac006 | ||
|
|
2ec9b3dd9d | ||
|
|
1a55a93788 | ||
|
|
0e4c270d19 | ||
|
|
b2bbed41fa | ||
|
|
88946e9832 | ||
|
|
7f6c608a35 | ||
|
|
dfb9111786 | ||
|
|
9843fd3686 | ||
|
|
68dce4f994 | ||
|
|
28560e2e1b | ||
|
|
e2bbedff09 | ||
|
|
6251ab1e63 | ||
|
|
afe99a46d8 | ||
|
|
4ebbb533c3 | ||
|
|
2f8a72144f | ||
|
|
bbb819d696 | ||
|
|
0544ff524c | ||
|
|
73ded483a0 | ||
|
|
fddac60afb | ||
|
|
c800aa27e2 | ||
|
|
a2b06bbac3 | ||
|
|
4f9e981a60 | ||
|
|
677a83b2b6 | ||
|
|
fb15cfbf45 | ||
|
|
af39458989 | ||
|
|
2cef8bb602 | ||
|
|
ee4d42cfed | ||
|
|
dd754c7bc6 | ||
|
|
9eb0004278 | ||
|
|
7c6795c5a2 | ||
|
|
a60bd34a33 | ||
|
|
c4f8681b77 | ||
|
|
665f326577 | ||
|
|
a0de028688 | ||
|
|
cedb40b4f5 | ||
|
|
71ee64fed7 | ||
|
|
bf217c75f9 | ||
|
|
d36b793656 | ||
|
|
0b966aa23a | ||
|
|
449f2c77ed | ||
|
|
b4fa33c39c | ||
|
|
83d108894e | ||
|
|
4d8a0c90cb | ||
|
|
5c20274761 | ||
|
|
848857d18b |
45
.github/ISSUE_TEMPLATE/bug.md
vendored
Normal file
45
.github/ISSUE_TEMPLATE/bug.md
vendored
Normal 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.
|
||||
|
||||
After reading, and before submitting your issue, please remove this introductory text.
|
||||
|
||||
──────────────────── ✄ ────────────────────
|
||||
|
||||
#### Self-Diagnosis
|
||||
- [ ] 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
|
||||
|
||||
8
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
8
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal 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
24
.github/ISSUE_TEMPLATE/question.md
vendored
Normal 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.
|
||||
|
||||
After reading, and before submitting your issue, please remove this introductory text.
|
||||
|
||||
──────────────────── ✄ ────────────────────
|
||||
|
||||
#### Self-Diagnosis
|
||||
- [ ] 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
|
||||
|
||||
20
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
20
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
### Description of Changes
|
||||
Closes # <!-- Issue number this PR addresses. If none, remove this line. -->
|
||||
|
||||
|
||||
---
|
||||
### New Version Info
|
||||
|
||||
- [ ] Derive a new 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 this format/example:
|
||||
```
|
||||
#### MAJOR.MINOR...
|
||||
- **.PATCH**: PR Title (Author) #PR Number
|
||||
|
||||
#### 5.1...
|
||||
- **.1**: Update Changelog and create PR Template (PhilRunninger) #1007
|
||||
- **.0**: Too many changes for one patch...
|
||||
```
|
||||
145
CHANGELOG
145
CHANGELOG
@@ -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
|
||||
216
CHANGELOG.md
Normal file
216
CHANGELOG.md
Normal file
@@ -0,0 +1,216 @@
|
||||
# Change Log
|
||||
|
||||
#### 5.2...
|
||||
- **.5**: Use `:mode` instead of `:redraw!` when updating menu. (PhilRunninger) #1016
|
||||
- **.4**: When searching for root line num, stop at end of file. (PhilRunninger) #1015
|
||||
- **.3**: Fix `<CR>` key map on the bookmark (lkebin) #1014
|
||||
- **.2**: Make Enter work on the `.. ( up a dir )` line (PhilRunninger) #1013
|
||||
- **.1**: Fix nerdtree#version() on Windows. (PhilRunninger) N/A
|
||||
- **.0**: Expand functionality of `<CR>` mapping. (PhilRunninger) #1011
|
||||
#### 5.1...
|
||||
- **.3**: Remove @mentions from PR template and change log. They weren't working. (PhilRunninger) #1009
|
||||
- **.2**: Fix NERDTree opening with the wrong size. (PhilRunninger) #1008
|
||||
- **.1**: Update Changelog and create PR Template (PhilRunninger) #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
|
||||
- Add a "copy path to clipboard" menu option (PhilRunninger) #1002
|
||||
- Enable root refresh on "vim ." a different way than #999. (PhilRunninger) #1001
|
||||
- Fix refreshroot (PhilRunninger) #999
|
||||
- Change version check to look for 703 not 730 (vhalis) #994
|
||||
- Change minimum vim (PhilRunninger) #991
|
||||
- Allow multi-character DirArrows (PhilRunninger) #985
|
||||
- Remove redraw! while still clearing last message empty string. (PhilRunninger) #979
|
||||
- fix _initChildren function value set to numChildrenCached error (terryding77) #969
|
||||
- On Windows, do a case-insensitive comparison of paths. (PhilRunninger) #967
|
||||
- Remove the "Please wait... DONE" messages. (PhilRunninger) #966
|
||||
- Smarter delimiter default (PhilRunninger) #963
|
||||
- Update directory .vimdc readme example (spencerdcarlson) #961
|
||||
- Preview bookmarks (PhilRunninger) #956
|
||||
- Add new value to NERDTreeQuitOnOpen to close bookmark table (PhilRunninger) #955
|
||||
- Add an :EditBookmarks command to edit the bookmarks file (PhilRunninger) #954
|
||||
- Before copying, turn off &shellslash. Restore after copy is finished. (PhilRunninger) #952
|
||||
- Set a maximum window size when zooming. (PhilRunninger) #950
|
||||
- Confirm the wipeout of a unsaved buffer whose file has been renamed. (PhilRunninger) #949
|
||||
- Escape a backslash so it can be used in a key mapping. (PhilRunninger) #948
|
||||
- Add a NERDTreeMinimalMenu feature (tuzz) #938
|
||||
- fixed root path error for windows (zcodes) #935
|
||||
- Restore getDirChildren for use in nerdtree-project-plugin. (PhilRunninger) #929
|
||||
- Document NERDTreeNodeDelimiter #912 (PhilRunninger) #926
|
||||
- Allow modification of menu keybindings (Leandros) #923
|
||||
- Add two more disqualifications for isCascadable(). (PhilRunninger) #914
|
||||
- Allow highlighting more than one flag. (kristijanhusak) #908
|
||||
- Support sorting files and directories by modification time. (PhilRunninger) #901
|
||||
- Parse . and .. from path string with trailing slash. (PhilRunninger) #899
|
||||
- Force sort to recalculate the cached sortKey. (PhilRunninger) #898
|
||||
- Add NERDTreeRefreshRoot command (wgfm) #897
|
||||
- Call Resolve on the file's path when calling :NERDTreeFind. (PhilRunninger) #896
|
||||
- Catch all errors, not just NERDTree errors. (PhilRunninger) #894
|
||||
- Fix typo in help file (lvoisin) #892
|
||||
- Make NERDTreeCreator set the `'nolist'` option (lifecrisis) #889
|
||||
- Refresh buffers after `m`, `m` operation on a folder (PhilRunninger) #888
|
||||
- Use a better arg for FINDSTR when using the m,l command in Windows. (PhilRunninger) #887
|
||||
- Fix the <C-J>/<C-K> motions, which currently fail with cascades (lifecrisis) #886
|
||||
- Function "s:UI.getLineNum()" doesn't always work on cascades. (lifecrisis) #882
|
||||
- NERDTreeCWD: reset CWD if changed by NERDTreeFocus (PhilRunninger) #878
|
||||
- Use <count>tabnext instead of <count>gt to allow users to remap gt. (PhilRunninger) #877
|
||||
- Do a case sensitive comparison of new/existing buffers. (PhilRunninger) #875
|
||||
- Fix opening sub-directories that have commas in their name. (PhilRunninger) #873
|
||||
- Add new command to open NERDTree in the root of a VCS repository. (PhilRunninger) #872
|
||||
- Make sure the path to the bookmarks file exists before writing it. (PhilRunninger) #871
|
||||
- Unzoom NERDTree when opening a file (PhilRunninger) #870
|
||||
- Support unusual characters in file and directory names (PhilRunninger) #868
|
||||
- Reword renamed-buffer prompt to be more clear (aflock) #867
|
||||
- Default to placing cursor on root when closing bookmark table (lifecrisis) #866
|
||||
- Fix issues with sorting of nodes (PhilRunninger) #856
|
||||
- Better OSX detection (bubba-h57) #853
|
||||
- Bugfix - ensure keymaps dictionary exists before using it (mnussbaum) #852
|
||||
- Decrease startup-time by avoiding linear-time iteration over key mappings (mnussbaum) #851
|
||||
- Add code to sort mappings in quickhelp (lifecrisis) #849
|
||||
- Use ":clearjumps" in new NERDTree windows (lifecrisis) #844
|
||||
- Like m-c did before, create parent directories if needed on m-m. (PhilRunninger) #840
|
||||
- BUGFIX: Repair a problem with the `'u'` mapping. (lifecrisis) #838
|
||||
- Make the NERDTree buffer writable when rendering it. (PhilRunninger) #837
|
||||
- Code cleanup: Remove unsupported bookmark table mappings (lifecrisis) #835
|
||||
- Replace strcharpart() with substitute() for backward compatibility (bravestarr) #834
|
||||
- Fixed error `unknown function strcharpart` for older versions of Vim (hav4ik) #833
|
||||
- Clear output when NERDTree menu is aborted (lifecrisis) #832
|
||||
- Display a path with multi-byte characters correctly when it is truncated (bravestarr) #830
|
||||
- Support revealing file and executing file with xdg-open for Linux (ngnmhieu) #824
|
||||
- If node isn't open, count children on disk before deleting. (PhilRunninger) #822
|
||||
- Add new variable g:NERDTreeRemoveFileCmd (kutsan) #816
|
||||
- Use a better check for existence of the NERDTree buffer. (PhilRunninger) #814
|
||||
- Fix focussing previous buffer when closing NERDTree (mrubli) #801
|
||||
- Update the docs for "NERDTreeStatusline" (lifecrisis) #796
|
||||
- BUGFIX: Unstable behavior in the "getPath()" method (lifecrisis) #795
|
||||
- Revert the bugfix from pull request #785 (lifecrisis) #794
|
||||
- BUGFIX: Allow ":NERDTreeFind" to discover hidden files (lifecrisis) #786
|
||||
- BUGFIX: Allow ":NERDTreeFind" to reveal new files (lifecrisis) #785
|
||||
- Add modelines (lifecrisis) #782
|
||||
- Change the type of completion used by NERDTreeFind (lifecrisis) #781
|
||||
- change NERDTreeFind with args (zhenyangze) #778
|
||||
- Style Choice: Using confirm() when deleting a bookmark (lifecrisis) #777
|
||||
- remove useless substitute when `file =~# "/$"` (skyblueee) #773
|
||||
- remove useless removeLeadingSpaces in _stripMarkup (skyblueee) #772
|
||||
- Make the "o" mapping consistent with "x" (lifecrisis) #769
|
||||
- Fix a problem with the "x" handler (lifecrisis) #768
|
||||
- Clean up the handler for the "x" mapping (lifecrisis) #767
|
||||
- Revert change to tab opening method (lifecrisis) #766
|
||||
- BUGFIX: Add back support for "b:NERDTreeRoot" (lifecrisis) #765
|
||||
- Fix broken "t" and "T" mappings, tabs now open at end (lifecrisis) #759
|
||||
- Update doc with already existing mapping variables (asnr) #699
|
||||
- Fix the broken g:NERDTreeBookmarksSort setting (lifecrisis) #696
|
||||
- Correct NERDTreeIgnore pattern in doc (cntoplolicon) #648
|
||||
- Remove empty segments when splitting path (sooth-sayer) #574
|
||||
- Suppress autocmds less agressively (wincent) #578 #691
|
||||
- Add an Issues template to ask for more info initially.
|
||||
- Fix markdown headers in readme (josephfrazier) #676
|
||||
- Don't touch @o and @h registers when rendering
|
||||
- Fix bug with files and directories with dollar signs (alegen) #649
|
||||
- Reuse/reopen existing window trees where possible #244
|
||||
- Remove NERDTree.previousBuf()
|
||||
- Change color of arrow (Leeiio) #630
|
||||
- Improved a tip in README.markdown (ggicci) #628
|
||||
- Shorten delete confimration of empty directory to `y` (mikeperri) #530
|
||||
- Fix API call to open directory tree in window (devm33) #533
|
||||
- Change default arrows on non-Windows platforms (gwilk) #546
|
||||
- Update to README - combine cd and git clone (zwhitchcox) #584
|
||||
- Update to README - Tip: start NERDTree when vim starts (therealplato) #593
|
||||
- Escape filename when moving an open buffer (zacharyvoase) #595
|
||||
- Fixed incorrect :helptags command in README (curran) #619
|
||||
- Fixed incomplete escaping of folder arrows (adityanatraj) #548
|
||||
- Added NERDTreeCascadeSingleChildDir option (juanibiapina) #558
|
||||
- Replace strchars() with backward compatible workaround.
|
||||
- Add support for copy command in Windows (SkylerLipthay) #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
|
||||
@@ -1,81 +1,41 @@
|
||||
The NERD Tree
|
||||
The NERDTree
|
||||
=============
|
||||
|
||||
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
|
||||

|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
####[pathogen.vim](https://github.com/tpope/vim-pathogen)
|
||||
#### [pathogen.vim](https://github.com/tpope/vim-pathogen)
|
||||
|
||||
cd ~/.vim/bundle
|
||||
git clone https://github.com/scrooloose/nerdtree.git
|
||||
git clone https://github.com/scrooloose/nerdtree.git ~/.vim/bundle/nerdtree
|
||||
|
||||
Then reload vim, run `:Helptags`, and check out `:help NERD_tree.txt`.
|
||||
Then reload Vim, run `:helptags ~/.vim/bundle/nerdtree/doc/` or `:Helptags`, and check out `:help NERDTree.txt`.
|
||||
|
||||
|
||||
####[apt-vim](https://github.com/egalpin/apt-vim)
|
||||
#### [apt-vim](https://github.com/egalpin/apt-vim)
|
||||
|
||||
apt-vim install -y https://github.com/scrooloose/nerdtree.git
|
||||
|
||||
|
||||
|
||||
Faq
|
||||
---
|
||||
F.A.Q.
|
||||
------
|
||||
|
||||
> 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?
|
||||
|
||||
@@ -85,37 +45,54 @@ 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?
|
||||
|
||||
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
|
||||
Stick this in your vimrc:
|
||||
|
||||
autocmd StdinReadPre * let s:std_in=1
|
||||
autocmd VimEnter * if argc() == 0 && !exists("s:std_in") | NERDTree | endif
|
||||
|
||||
Note: Now start vim with plain `vim`, not `vim .`
|
||||
|
||||
---
|
||||
> How can I open NERDTree automatically when vim starts up on opening a directory?
|
||||
|
||||
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
|
||||
|
||||
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):
|
||||
|
||||
map <C-n> :NERDTreeToggle<CR>
|
||||
|
||||
---
|
||||
> How can I close vim if the only window left open is a NERDTree?
|
||||
|
||||
Stick this in your vimrc:
|
||||
|
||||
autocmd bufenter * if (winnr("$") == 1 && exists("b:NERDTreeType") && b:NERDTreeType == "primary") | q | endif
|
||||
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/scrooloose/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 = '▾'
|
||||
|
||||
@@ -3,19 +3,95 @@ if exists("g:loaded_nerdtree_autoload")
|
||||
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(...)
|
||||
let l:changelog = readfile(join([s:rootNERDTreePath, "CHANGELOG.md"], nerdtree#slash()))
|
||||
let l:text = 'Unknown'
|
||||
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
|
||||
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()
|
||||
|
||||
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)
|
||||
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
|
||||
echomsg l:x . ", " . l:y . " => " l:result
|
||||
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)
|
||||
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
|
||||
@@ -24,11 +100,6 @@ function! nerdtree#completeBookmarks(A,L,P)
|
||||
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)
|
||||
return a:n1.path.compareTo(a:n2.path)
|
||||
@@ -36,9 +107,32 @@ endfunction
|
||||
|
||||
"FUNCTION: nerdtree#compareNodesBySortKey(n1, n2) {{{2
|
||||
function! nerdtree#compareNodesBySortKey(n1, n2)
|
||||
if a:n1.path.getSortKey() <# a:n2.path.getSortKey()
|
||||
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
|
||||
@@ -61,10 +155,12 @@ function! nerdtree#deprecated(func, ...)
|
||||
endfunction
|
||||
|
||||
" FUNCTION: nerdtree#exec(cmd) {{{2
|
||||
" same as :exec cmd but eventignore=all is set for the duration
|
||||
" Same as :exec cmd but with eventignore set for the duration
|
||||
" to disable the autocommands used by NERDTree (BufEnter,
|
||||
" BufLeave and VimEnter)
|
||||
function! nerdtree#exec(cmd)
|
||||
let old_ei = &ei
|
||||
set ei=all
|
||||
set ei=BufEnter,BufLeave,VimEnter
|
||||
exec a:cmd
|
||||
let &ei = old_ei
|
||||
endfunction
|
||||
@@ -94,7 +190,7 @@ endfunction
|
||||
|
||||
" FUNCTION: nerdtree#postSourceActions() {{{2
|
||||
function! nerdtree#postSourceActions()
|
||||
call g:NERDTreeBookmark.CacheBookmarks(0)
|
||||
call g:NERDTreeBookmark.CacheBookmarks(1)
|
||||
call nerdtree#ui_glue#createDefaultBindings()
|
||||
|
||||
"load all nerdtree plugins
|
||||
@@ -106,6 +202,11 @@ function! nerdtree#runningWindows()
|
||||
return has("win16") || has("win32") || has("win64")
|
||||
endfunction
|
||||
|
||||
"FUNCTION: nerdtree#runningCygwin(dir) {{{2
|
||||
function! nerdtree#runningCygwin()
|
||||
return has("win32unix")
|
||||
endfunction
|
||||
|
||||
" SECTION: View Functions {{{1
|
||||
"============================================================
|
||||
|
||||
@@ -116,7 +217,7 @@ endfunction
|
||||
"msg: the message to echo
|
||||
function! nerdtree#echo(msg)
|
||||
redraw
|
||||
echomsg "NERDTree: " . a:msg
|
||||
echomsg empty(a:msg) ? "" : ("NERDTree: " . a:msg)
|
||||
endfunction
|
||||
|
||||
"FUNCTION: nerdtree#echoError {{{2
|
||||
|
||||
@@ -7,38 +7,36 @@ let g:loaded_nerdtree_ui_glue_autoload = 1
|
||||
function! nerdtree#ui_glue#createDefaultBindings()
|
||||
let s = '<SNR>' . s:SID() . '_'
|
||||
|
||||
call NERDTreeAddKeyMap({ 'key': '<MiddleRelease>', 'scope': "all", 'callback': s."handleMiddleMouse" })
|
||||
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: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': "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': "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:NERDTreeMapOpenRecursively, 'scope': "DirNode", 'callback': s."openNodeRecursively" })
|
||||
|
||||
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: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:NERDTreeMapChdir, 'scope': "Node", 'callback': s."chCwd" })
|
||||
|
||||
@@ -68,10 +66,10 @@ function! nerdtree#ui_glue#createDefaultBindings()
|
||||
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpNextSibling, 'scope': "Node", 'callback': s."jumpToNextSibling" })
|
||||
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpPrevSibling, 'scope': "Node", 'callback': s."jumpToPrevSibling" })
|
||||
|
||||
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: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" })
|
||||
|
||||
@@ -82,6 +80,35 @@ endfunction
|
||||
"SECTION: Interface bindings {{{1
|
||||
"============================================================
|
||||
|
||||
"FUNCTION: s:customOpenFile() {{{1
|
||||
" Open file node with the "custom" key, initially <CR>.
|
||||
function! s:customOpenFile(node)
|
||||
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)
|
||||
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)
|
||||
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()
|
||||
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()
|
||||
@@ -90,10 +117,16 @@ function! s:activateAll()
|
||||
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, ...)
|
||||
|
||||
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
|
||||
@@ -102,10 +135,10 @@ function! s:activateFileNode(node)
|
||||
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'} : {})
|
||||
call a:bm.activate(b:NERDTree, !a:bm.path.isDirectory ? {'where': 'p'} : {})
|
||||
endfunction
|
||||
|
||||
" FUNCTION: nerdtree#ui_glue#bookmarkNode(name) {{{1
|
||||
@@ -140,24 +173,13 @@ 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)
|
||||
call b:NERDTree.changeRoot(a:node)
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:nerdtree#ui_glue#chRootCwd() {{{1
|
||||
" changes the current root to CWD
|
||||
" Change the NERDTree root to match the current working directory.
|
||||
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))
|
||||
NERDTreeCWD
|
||||
endfunction
|
||||
|
||||
" FUNCTION: nnerdtree#ui_glue#clearBookmarks(bookmarks) {{{1
|
||||
@@ -173,6 +195,7 @@ function! nerdtree#ui_glue#clearBookmarks(bookmarks)
|
||||
call bookmark.delete()
|
||||
endfor
|
||||
endif
|
||||
call b:NERDTree.root.refresh()
|
||||
call b:NERDTree.render()
|
||||
endfunction
|
||||
|
||||
@@ -185,31 +208,35 @@ function! s:closeChildren(node)
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:closeCurrentDir(node) {{{1
|
||||
" closes the parent dir of the current node
|
||||
" Close the parent directory 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)
|
||||
|
||||
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
|
||||
if b:NERDTree.isWinTree() && b:NERDTree.previousBuf() != -1
|
||||
exec "buffer " . b:NERDTree.previousBuf()
|
||||
else
|
||||
if winnr("$") > 1
|
||||
call g:NERDTree.Close()
|
||||
@@ -219,81 +246,85 @@ function! s:closeTreeWindow()
|
||||
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)
|
||||
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
|
||||
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)
|
||||
let l:pathStr = !empty(a:pathStr) ? a:pathStr : expand('%:p')
|
||||
|
||||
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
|
||||
@@ -334,48 +365,25 @@ 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" )
|
||||
|
||||
" 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
|
||||
@@ -383,33 +391,61 @@ function! nerdtree#ui_glue#invokeKeyMap(key)
|
||||
call g:NERDTreeKeyMap.Invoke(a:key)
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:jumpToFirstChild() {{{1
|
||||
" wrapper for the jump to child method
|
||||
" FUNCTION: s:jumpToFirstChild(node) {{{1
|
||||
function! s:jumpToFirstChild(node)
|
||||
call s:jumpToChild(a:node, 0)
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:jumpToLastChild() {{{1
|
||||
" wrapper for the jump to child method
|
||||
" FUNCTION: s:jumpToLastChild(node) {{{1
|
||||
function! s:jumpToLastChild(node)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
call b:NERDTree.root.putCursorHere(1, 0)
|
||||
call b:NERDTree.ui.centerView()
|
||||
endfunction
|
||||
|
||||
@@ -423,37 +459,38 @@ function! s:jumpToPrevSibling(node)
|
||||
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)
|
||||
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
|
||||
" Open the Bookmark that has the specified name. This function provides the
|
||||
" implementation for the ":OpenBookmark" command.
|
||||
function! nerdtree#ui_glue#openBookmark(name)
|
||||
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
|
||||
|
||||
@@ -474,12 +511,14 @@ endfunction
|
||||
|
||||
" FUNCTION: s:openInNewTab(target) {{{1
|
||||
function! s:openInNewTab(target)
|
||||
call a:target.activate({'where': 't'})
|
||||
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})
|
||||
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
|
||||
@@ -487,8 +526,16 @@ function! s:openNodeRecursively(node)
|
||||
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)
|
||||
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
|
||||
@@ -510,7 +557,7 @@ endfunction
|
||||
" put the cursor on the node associate with the given name
|
||||
function! nerdtree#ui_glue#revealBookmark(name)
|
||||
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")
|
||||
@@ -521,11 +568,18 @@ endfunction
|
||||
" Reloads the current root. All nodes below this will be lost and the root dir
|
||||
" will be reloaded.
|
||||
function! s:refreshRoot()
|
||||
if !g:NERDTree.IsOpen()
|
||||
return
|
||||
endif
|
||||
call nerdtree#echo("Refreshing the root node. This could take a while...")
|
||||
call b:NERDTreeRoot.refresh()
|
||||
|
||||
let l:curWin = winnr()
|
||||
call nerdtree#exec(g:NERDTree.GetWinNum() . "wincmd w")
|
||||
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")
|
||||
call nerdtree#echo("")
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:refreshCurrent(node) {{{1
|
||||
@@ -539,18 +593,18 @@ function! s:refreshCurrent(node)
|
||||
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>')
|
||||
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
|
||||
@@ -595,40 +649,33 @@ function! s:toggleZoom()
|
||||
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)
|
||||
|
||||
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
|
||||
|
||||
1496
doc/NERDTree.txt
Normal file
1496
doc/NERDTree.txt
Normal file
File diff suppressed because it is too large
Load Diff
1240
doc/NERD_tree.txt
1240
doc/NERD_tree.txt
File diff suppressed because it is too large
Load Diff
@@ -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,12 +27,9 @@ 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()
|
||||
@@ -34,7 +39,7 @@ function! s:Bookmark.Bookmarks()
|
||||
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 = []
|
||||
@@ -104,17 +114,31 @@ function! s:Bookmark.CacheBookmarks(silent)
|
||||
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,39 +152,45 @@ 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()
|
||||
execute "wincmd w"
|
||||
execute "edit ".g:NERDTreeBookmarksFile
|
||||
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
|
||||
@@ -178,7 +208,7 @@ 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()
|
||||
@@ -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)
|
||||
let pathStrMaxLen = winwidth(g:NERDTree.GetWinNum()) - 4 - strdisplaywidth(self.name)
|
||||
if &nu
|
||||
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.")
|
||||
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 = []
|
||||
@@ -314,7 +354,12 @@ function! s:Bookmark.Write()
|
||||
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:
|
||||
|
||||
@@ -1,93 +1,84 @@
|
||||
"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/
|
||||
@@ -100,14 +91,13 @@ function! s:Creator.createSecondary(dir)
|
||||
|
||||
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()
|
||||
@@ -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
|
||||
@@ -184,41 +175,56 @@ 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")
|
||||
@@ -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)
|
||||
@@ -259,18 +265,40 @@ 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
|
||||
else
|
||||
@@ -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
|
||||
@@ -322,20 +345,20 @@ function! s:Creator._tabpagevar(tabnr, var)
|
||||
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
|
||||
|
||||
|
||||
@@ -54,3 +54,5 @@ function! s:FlagSet.renderToString()
|
||||
|
||||
return '[' . flagstring . ']'
|
||||
endfunction
|
||||
|
||||
" vim: set sw=4 sts=4 et fdm=marker:
|
||||
|
||||
@@ -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,6 +51,7 @@ function! s:KeyMap.bind()
|
||||
else
|
||||
let keymapInvokeString = self.key
|
||||
endif
|
||||
let keymapInvokeString = escape(keymapInvokeString, '\')
|
||||
|
||||
let premap = self.key == "<LeftRelease>" ? " <LeftRelease>" : " "
|
||||
|
||||
@@ -49,12 +60,7 @@ 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
|
||||
@@ -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:
|
||||
|
||||
@@ -15,44 +15,66 @@ 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
|
||||
mode
|
||||
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()
|
||||
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 shortcuts = map(copy(self.menuItems), "v:val['shortcut']")
|
||||
let shortcuts[self.selection] = " " . split(selection)[0] . " "
|
||||
|
||||
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,9 +87,9 @@ 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
|
||||
let self.selection = -1
|
||||
@@ -123,7 +145,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
|
||||
|
||||
@@ -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
|
||||
" 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")
|
||||
let bufnr = bufnr("")
|
||||
let l:activeBufOrWin = l:useWinId ? win_getid() : bufnr("")
|
||||
call nerdtree#exec("wincmd p")
|
||||
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")
|
||||
if l:useWinId
|
||||
call nerdtree#exec("call win_gotoid(" . l:activeBufOrWin . ")")
|
||||
else
|
||||
call nerdtree#exec(bufwinnr(l:activeBufOrWin) . " wincmd w")
|
||||
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,7 +74,7 @@ endfunction
|
||||
"FUNCTION: s:NERDTree.CursorToBookmarkTable(){{{1
|
||||
"Places the cursor at the top of the bookmarks table
|
||||
function! s:NERDTree.CursorToBookmarkTable()
|
||||
if !b:NERDTreeShowBookmarks
|
||||
if !b:NERDTree.ui.getShowBookmarks()
|
||||
throw "NERDTree.IllegalOperationError: cant find bookmark table, bookmarks arent active"
|
||||
endif
|
||||
|
||||
@@ -73,13 +104,18 @@ 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,19 +126,44 @@ 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")
|
||||
return bufwinnr(t:NERDTreeBufName)
|
||||
else
|
||||
return -1
|
||||
endif
|
||||
|
||||
return -1
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:NERDTree.IsOpen() {{{1
|
||||
function! s:NERDTree.IsOpen()
|
||||
return s:NERDTree.GetWinNum() != -1
|
||||
return s:NERDTree.GetWinNum() != -1 || bufname('%') =~# '^' . g:NERDTreeCreator.BufNamePrefix() . '\d\+$'
|
||||
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
|
||||
@@ -113,11 +174,11 @@ function! s:NERDTree.MustBeOpen()
|
||||
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 +190,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:
|
||||
|
||||
@@ -11,8 +11,8 @@ 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)
|
||||
@@ -32,4 +32,3 @@ function! s:Notifier.GetListenersForEvent(name)
|
||||
endfunction
|
||||
|
||||
let g:NERDTreePathNotifier = deepcopy(s:Notifier)
|
||||
|
||||
|
||||
@@ -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,14 +31,15 @@ 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
|
||||
@@ -44,9 +50,8 @@ function! s:Opener._checkToCloseTree(newtab)
|
||||
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("$")
|
||||
@@ -62,9 +67,9 @@ function! s:Opener._firstUsableWindow()
|
||||
return -1
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Opener._gotoTargetWin() {{{1
|
||||
" FUNCTION: Opener._gotoTargetWin() {{{1
|
||||
function! s:Opener._gotoTargetWin()
|
||||
if b:NERDTreeType ==# "secondary"
|
||||
if b:NERDTree.isWinTree()
|
||||
if self._where == 'v'
|
||||
vsplit
|
||||
elseif self._where == 'h'
|
||||
@@ -89,12 +94,12 @@ 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
|
||||
@@ -120,42 +125,33 @@ 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
|
||||
@@ -215,66 +211,70 @@ function! s:Opener._newSplit()
|
||||
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('.')
|
||||
|
||||
if winnr('$') == 1
|
||||
let l:winwidth = g:NERDTreeWinSize
|
||||
endif
|
||||
|
||||
call nerdtree#exec("wincmd p")
|
||||
call nerdtree#exec('wincmd p')
|
||||
vnew
|
||||
|
||||
"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')
|
||||
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)
|
||||
call b:NERDTree.changeRoot(a:node)
|
||||
elseif self._where == 't'
|
||||
call g:NERDTreeCreator.CreatePrimary(a:node.path.str())
|
||||
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,7 +283,7 @@ 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
|
||||
call self._newSplit()
|
||||
@@ -303,16 +303,16 @@ function! s:Opener._previousWindow()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Opener._restoreCursorPos(){{{1
|
||||
" FUNCTION: Opener._restoreCursorPos() {{{1
|
||||
function! s:Opener._restoreCursorPos()
|
||||
call nerdtree#exec('normal ' . self._tabnr . 'gt')
|
||||
call nerdtree#exec(self._tabnr . 'tabnext')
|
||||
call nerdtree#exec(bufwinnr(self._bufnr) . 'wincmd w')
|
||||
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
|
||||
@@ -334,7 +334,7 @@ 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')
|
||||
let winnr = bufwinnr('^' . self._path.str() . '$')
|
||||
call nerdtree#exec(winnr . "wincmd w")
|
||||
return 1
|
||||
@@ -343,7 +343,7 @@ function! s:Opener._reuseWindow()
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Opener._saveCursorPos(){{{1
|
||||
" FUNCTION: Opener._saveCursorPos() {{{1
|
||||
function! s:Opener._saveCursorPos()
|
||||
let self._bufnr = bufnr("")
|
||||
let self._tabnr = tabpagenr()
|
||||
|
||||
@@ -1,36 +1,41 @@
|
||||
"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")
|
||||
call self.cacheDisplayString()
|
||||
@@ -38,14 +43,12 @@ function! s:Path.bookmarkNames()
|
||||
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
|
||||
@@ -82,16 +94,16 @@ function! s:Path.changeToDir()
|
||||
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 +138,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,12 +175,12 @@ 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"
|
||||
@@ -176,29 +188,33 @@ function! s:Path.copy(dest)
|
||||
|
||||
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
|
||||
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 +228,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,12 +242,11 @@ 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
|
||||
|
||||
@@ -242,7 +257,13 @@ function! s:Path.delete()
|
||||
throw "NERDTree.PathDeletionError: Could not delete directory: '" . self.str() . "'"
|
||||
endif
|
||||
else
|
||||
let success = delete(self.str())
|
||||
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
|
||||
@@ -255,10 +276,10 @@ 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 ==# ""
|
||||
call self.cacheDisplayString()
|
||||
@@ -267,14 +288,14 @@ function! s:Path.displayString()
|
||||
return self.cachedDisplayString
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.edit() {{{1
|
||||
" FUNCTION: Path.edit() {{{1
|
||||
function! s:Path.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 =~ '^\(\\\\\|\/\/\)'
|
||||
@@ -290,28 +311,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 +341,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 +357,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,8 +375,8 @@ 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)
|
||||
@@ -364,13 +385,39 @@ function! s:Path.getSortOrderIndex()
|
||||
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")
|
||||
let l:ascending = index(g:NERDTreeSortOrder,'[[timestamp]]')
|
||||
let l:descending = index(g:NERDTreeSortOrder,'[[-timestamp]]')
|
||||
if !exists("self._sortKey") || g:NERDTreeSortOrder !=# g:NERDTreeOldSortOrder || l:ascending >= 0 || l:descending >= 0
|
||||
let self._sortKey = [self.getSortOrderIndex()]
|
||||
|
||||
if l:descending >= 0
|
||||
call insert(self._sortKey, -getftime(self.str()), l:descending == 0 ? 0 : len(self._sortKey))
|
||||
elseif l:ascending >= 0
|
||||
call insert(self._sortKey, getftime(self.str()), l:ascending == 0 ? 0 : len(self._sortKey))
|
||||
endif
|
||||
|
||||
let path = self.getLastPathComponent(1)
|
||||
if !g:NERDTreeSortHiddenFirst
|
||||
let path = substitute(path, '^[._]', '', '')
|
||||
@@ -378,21 +425,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,11 +472,11 @@ 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
|
||||
@@ -418,26 +484,26 @@ function! s:Path.ignore()
|
||||
endfor
|
||||
|
||||
for callback in g:NERDTree.PathFilters()
|
||||
if {callback}({'path': self, 'nerdtree': b:NERDTree})
|
||||
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]]'
|
||||
@@ -455,10 +521,22 @@ 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
|
||||
" 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(that, this) == 0
|
||||
endfunction
|
||||
|
||||
" 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
|
||||
@@ -469,7 +547,7 @@ function! s:Path.isUnder(path)
|
||||
return stridx(this, that . s:Path.Slash()) == 0
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.JoinPathStrings(...) {{{1
|
||||
" FUNCTION: Path.JoinPathStrings(...) {{{1
|
||||
function! s:Path.JoinPathStrings(...)
|
||||
let components = []
|
||||
for i in a:000
|
||||
@@ -478,50 +556,64 @@ 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)
|
||||
|
||||
@@ -531,7 +623,7 @@ function! s:Path.readInfoFromDisk(fullpath)
|
||||
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)
|
||||
@@ -572,27 +664,29 @@ 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
|
||||
endif
|
||||
|
||||
call s:Path.createParentDirectories(a:newPath)
|
||||
|
||||
let success = rename(self.str(), a:newPath)
|
||||
if success != 0
|
||||
throw "NERDTree.PathRenameError: Could not rename: '" . self.str() . "'" . 'to:' . a:newPath
|
||||
@@ -606,28 +700,28 @@ 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 = ""
|
||||
@@ -649,8 +743,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,7 +758,7 @@ 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 != '/'
|
||||
@@ -671,37 +767,37 @@ function! s:Path._strForUI()
|
||||
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 +814,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 +842,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 +850,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
|
||||
|
||||
@@ -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
|
||||
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)
|
||||
@@ -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,12 +208,13 @@ 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)
|
||||
@@ -140,14 +223,14 @@ function! s:TreeDirNode.getChildByIndex(indx, visible)
|
||||
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,9 +254,90 @@ 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()
|
||||
@@ -185,56 +349,71 @@ 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
|
||||
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 ...")
|
||||
@@ -242,28 +421,18 @@ function! s:TreeDirNode._initChildren(silent)
|
||||
|
||||
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")
|
||||
@@ -271,13 +440,13 @@ function! s:TreeDirNode._initChildren(silent)
|
||||
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)
|
||||
" 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
|
||||
@@ -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
|
||||
@@ -336,101 +520,65 @@ 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'})
|
||||
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
|
||||
@@ -443,24 +591,27 @@ function! s:TreeDirNode.refresh()
|
||||
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()
|
||||
endif
|
||||
@@ -469,9 +620,15 @@ function! s:TreeDirNode.reveal(path)
|
||||
|
||||
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 +637,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)
|
||||
@@ -502,18 +657,19 @@ function! s:TreeDirNode.removeChild(treenode)
|
||||
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()
|
||||
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
|
||||
@@ -527,13 +683,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)
|
||||
|
||||
@@ -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"
|
||||
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,183 +116,145 @@ 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"
|
||||
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.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 '
|
||||
@@ -298,35 +263,35 @@ function! s:TreeFileNode.putCursorHere(isJump, recurseUpward)
|
||||
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 +299,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)
|
||||
" 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
|
||||
|
||||
|
||||
@@ -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
|
||||
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)
|
||||
|
||||
let wasdir = 0
|
||||
if curFile =~# '/$'
|
||||
let wasdir = 1
|
||||
let curFile = substitute(curFile, '/\?$', '/', "")
|
||||
endif
|
||||
" remove the tree parts and the leading space
|
||||
let curFile = self._stripMarkup(line)
|
||||
|
||||
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?
|
||||
" have we reached the top of the tree?
|
||||
if lnum == rootLine
|
||||
let dir = b:NERDTreeRoot.path.str({'format': 'UI'}) . dir
|
||||
let dir = self.nerdtree.root.path.str({'format': 'UI'}) . dir
|
||||
break
|
||||
endif
|
||||
if curLineStripped =~# '/$'
|
||||
@@ -196,102 +196,131 @@ function! s:UI.getPath(ln)
|
||||
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
|
||||
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("."))
|
||||
@@ -301,12 +330,12 @@ function! s:UI._renderBookmarks()
|
||||
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
|
||||
@@ -321,9 +350,9 @@ function! s:UI.restoreScreenState()
|
||||
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()
|
||||
@@ -334,92 +363,64 @@ function! s:UI.saveScreenState()
|
||||
call nerdtree#exec(win . "wincmd w")
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:UI._stripMarkup(line, removeLeadingSpaces){{{1
|
||||
"returns the given line with all the tree parts stripped off
|
||||
"
|
||||
"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
|
||||
" FUNCTION: s:UI.setShowHidden(val) {{{1
|
||||
function! s:UI.setShowHidden(val)
|
||||
let self._showHidden = a:val
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:UI.render() {{{1
|
||||
function! s:UI.render()
|
||||
setlocal modifiable
|
||||
" FUNCTION: s:UI._stripMarkup(line){{{1
|
||||
" find the filename in the given line, and return it.
|
||||
"
|
||||
" 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
|
||||
|
||||
"remember the top line of the buffer and the current line so we can
|
||||
"restore the view exactly how it was
|
||||
" FUNCTION: s:UI.render() {{{1
|
||||
function! s:UI.render()
|
||||
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")
|
||||
|
||||
"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
|
||||
" 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
|
||||
" 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)})
|
||||
" 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,63 +428,76 @@ 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
|
||||
" 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 != {}
|
||||
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
|
||||
|
||||
@@ -495,12 +509,14 @@ function! s:UI.toggleZoom()
|
||||
exec "silent vertical resize ". size
|
||||
let b:NERDTreeZoomed = 0
|
||||
else
|
||||
exec "vertical resize"
|
||||
exec "vertical resize ". get(g:, 'NERDTreeWinSizeMax', '')
|
||||
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:
|
||||
|
||||
@@ -29,9 +29,15 @@ if has("gui_mac") || has("gui_macvim") || has("mac")
|
||||
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")
|
||||
call NERDTreeAddMenuItem({'text': '(l)ist the current node', 'shortcut': 'l', 'callback': 'NERDTreeListNode'})
|
||||
@@ -39,6 +45,47 @@ 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,7 +102,22 @@ 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"
|
||||
" 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
|
||||
exec "tabdo windo if winbufnr(0) == " . a:bufnum . " | exec ':bnext! ' | endif"
|
||||
else
|
||||
exec "tabdo windo if winbufnr(0) == " . a:bufnum . " | exec ':enew! ' | endif"
|
||||
endif
|
||||
exec "tabnext " . s:originalTabNumber
|
||||
exec s:originalWindowNumber . "wincmd w"
|
||||
" 3. We don't need a previous buffer anymore
|
||||
@@ -63,40 +125,43 @@ function! s:promptToDelBuffer(bufnum, msg)
|
||||
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
|
||||
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()
|
||||
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
|
||||
try
|
||||
exec "confirm bwipeout " . a:bufNum
|
||||
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.")
|
||||
@@ -105,17 +170,22 @@ function! NERDTreeAddNode()
|
||||
|
||||
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.")
|
||||
endtry
|
||||
@@ -124,10 +194,8 @@ 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.")
|
||||
@@ -135,21 +203,38 @@ function! NERDTreeMoveNode()
|
||||
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.")
|
||||
endtry
|
||||
@@ -157,25 +242,23 @@ 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()
|
||||
@@ -189,46 +272,63 @@ function! NERDTreeDeleteNode()
|
||||
call s:promptToDelBuffer(bufnum, prompt)
|
||||
endif
|
||||
|
||||
redraw
|
||||
redraw!
|
||||
catch /^NERDTree/
|
||||
call nerdtree#echoWarning("Could not remove node")
|
||||
endtry
|
||||
else
|
||||
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 != ""
|
||||
"strip trailing slash
|
||||
@@ -244,8 +344,11 @@ 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()
|
||||
@@ -258,7 +361,19 @@ function! NERDTreeCopyNode()
|
||||
else
|
||||
call nerdtree#echo("Copy aborted.")
|
||||
endif
|
||||
redraw
|
||||
let &shellslash = l:shellslash
|
||||
redraw!
|
||||
endfunction
|
||||
|
||||
" FUNCTION: NERDTreeCopyPath() {{{1
|
||||
function! NERDTreeCopyPath()
|
||||
let l:nodePath = g:NERDTreeFileNode.GetSelected().path.str()
|
||||
if has("clipboard")
|
||||
let @* = l:nodePath
|
||||
call nerdtree#echo("The path [" . l:nodePath . "] was copied to your clipboard.")
|
||||
else
|
||||
call nerdtree#echo("The full path is: " . l:nodePath)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" FUNCTION: NERDTreeQuickLook() {{{1
|
||||
@@ -284,4 +399,23 @@ function! NERDTreeExecuteFile()
|
||||
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:
|
||||
|
||||
|
||||
38
nerdtree_plugin/vcs.vim
Normal file
38
nerdtree_plugin/vcs.vim
Normal file
@@ -0,0 +1,38 @@
|
||||
" ============================================================================
|
||||
" 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>')
|
||||
|
||||
" 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: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
|
||||
|
||||
@@ -14,8 +14,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
|
||||
@@ -46,9 +46,12 @@ endfunction
|
||||
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: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
|
||||
@@ -56,6 +59,7 @@ call s:initVariable("g:NERDTreeBookmarksFile", expand('$HOME') . '/.NERDTreeBook
|
||||
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)
|
||||
@@ -65,26 +69,39 @@ 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", "▾")
|
||||
|
||||
if !nerdtree#runningWindows() && !nerdtree#runningCygwin()
|
||||
call s:initVariable("g:NERDTreeDirArrowExpandable", "▸")
|
||||
call s:initVariable("g:NERDTreeDirArrowCollapsible", "▾")
|
||||
else
|
||||
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
|
||||
"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: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")
|
||||
@@ -95,6 +112,8 @@ call s:initVariable("g:NERDTreeWinSize", 31)
|
||||
"Note: the space after the command is important
|
||||
if nerdtree#runningWindows()
|
||||
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 ')
|
||||
@@ -102,6 +121,7 @@ endif
|
||||
|
||||
|
||||
"SECTION: Init variable calls for key mappings {{{2
|
||||
call s:initVariable("g:NERDTreeMapCustomOpen", "<CR>")
|
||||
call s:initVariable("g:NERDTreeMapActivateNode", "o")
|
||||
call s:initVariable("g:NERDTreeMapChangeRoot", "C")
|
||||
call s:initVariable("g:NERDTreeMapChdir", "cd")
|
||||
@@ -136,6 +156,8 @@ 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()
|
||||
@@ -188,13 +210,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)
|
||||
|
||||
BIN
screenshot.png
Normal file
BIN
screenshot.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 86 KiB |
@@ -1,6 +1,6 @@
|
||||
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 ."#"
|
||||
@@ -8,7 +8,7 @@ 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
|
||||
|
||||
Reference in New Issue
Block a user