mirror of
https://github.com/preservim/nerdtree.git
synced 2025-11-08 11:23:48 -05:00
Compare commits
668 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4dada8c04f | ||
|
|
be8f18914c | ||
|
|
f486403b68 | ||
|
|
024966c7a8 | ||
|
|
e4891632f5 | ||
|
|
0c13ebc126 | ||
|
|
e27ab9c5c7 | ||
|
|
5b7085d9ae | ||
|
|
adc11983bc | ||
|
|
b19995b14f | ||
|
|
3fb18e7399 | ||
|
|
f1af61ddf7 | ||
|
|
c60f401371 | ||
|
|
fb030bcb1c | ||
|
|
47c20c4b64 | ||
|
|
d384382091 | ||
|
|
af13d39651 | ||
|
|
caca3af211 | ||
|
|
3092ddf831 | ||
|
|
88104d26ac | ||
|
|
8996ea5bb5 | ||
|
|
34630f3926 | ||
|
|
0b44415a33 | ||
|
|
43012a6214 | ||
|
|
d66370a8e5 | ||
|
|
8c8c794104 | ||
|
|
8c7534bc9e | ||
|
|
dc29ec2db3 | ||
|
|
188bd92658 | ||
|
|
bcf3de4fdf | ||
|
|
f5fd121837 | ||
|
|
37f7a6cbe1 | ||
|
|
86e2e40af1 | ||
|
|
93c9726c6d | ||
|
|
96c07746b4 | ||
|
|
013c607ba4 | ||
|
|
af85499eda | ||
|
|
99fa465b5d | ||
|
|
008b62f71c | ||
|
|
6018af36bf | ||
|
|
2c1ebc37b2 | ||
|
|
dfe260d1d7 | ||
|
|
10261d60a0 | ||
|
|
80e184df56 | ||
|
|
3fb3fe3477 | ||
|
|
57d5bd7731 | ||
|
|
1f2531ec3a | ||
|
|
a87b1bf3c5 | ||
|
|
5c2060149f | ||
|
|
76dbc0c8ee | ||
|
|
da3874cf93 | ||
|
|
7270212214 | ||
|
|
64a9579c11 | ||
|
|
09e1dbec10 | ||
|
|
fc4bcb4806 | ||
|
|
8b189cb263 | ||
|
|
b0114d202b | ||
|
|
53d2de86eb | ||
|
|
0d88ce946f | ||
|
|
8270b6d717 | ||
|
|
973c9906f8 | ||
|
|
0e87d45e84 | ||
|
|
f8499462c5 | ||
|
|
186f817f5a | ||
|
|
5cec19365a | ||
|
|
b3281cc63e | ||
|
|
87b27802b5 | ||
|
|
1cbd52aa77 | ||
|
|
cd5f1685bc | ||
|
|
321de60366 | ||
|
|
f6cad7e957 | ||
|
|
6dfbcd660a | ||
|
|
3b98a7fcae | ||
|
|
ba26044746 | ||
|
|
f8fd2ecce2 | ||
|
|
a895a53f1f | ||
|
|
3d421b8ec5 | ||
|
|
3ce33f017e | ||
|
|
031ab5267c | ||
|
|
5d0626a003 | ||
|
|
1c08146224 | ||
|
|
cd8d87fa57 | ||
|
|
2fd0aa3ec7 | ||
|
|
6ccf83df24 | ||
|
|
5d19452284 | ||
|
|
8e06723c04 | ||
|
|
a283c0e03e | ||
|
|
4f1e6ecb05 | ||
|
|
c4086667ef | ||
|
|
a47c6caf80 | ||
|
|
8cd045d0e2 | ||
|
|
c2dd750860 | ||
|
|
fd14757c04 | ||
|
|
f9a933991d | ||
|
|
aa831e242b | ||
|
|
0c045d85ea | ||
|
|
2f552e116d | ||
|
|
579d96a0f3 | ||
|
|
9f351de594 | ||
|
|
1e0d1cbc8f | ||
|
|
98a5d1fca7 | ||
|
|
2f59cc2080 | ||
|
|
eaa66aaf63 | ||
|
|
8644622000 | ||
|
|
410081a60e | ||
|
|
1784de15dd | ||
|
|
7f36008e80 | ||
|
|
23dfc6d818 | ||
|
|
f982f61e8a | ||
|
|
86488b1aa0 | ||
|
|
04d9b27541 | ||
|
|
3941389f13 | ||
|
|
32cf3ee62d | ||
|
|
a7428eba38 | ||
|
|
3effeb5cb7 | ||
|
|
04ac39b4b9 | ||
|
|
d162c08fd7 | ||
|
|
2a769a7263 | ||
|
|
0ee888ee17 | ||
|
|
0b551a8abd | ||
|
|
82cd4f5a9f | ||
|
|
b64942a500 | ||
|
|
e954b2e6f8 | ||
|
|
e68e12a33b | ||
|
|
b33d6daf0b | ||
|
|
abb93879bb | ||
|
|
634c23eadb | ||
|
|
9d9edd03d4 | ||
|
|
9704a38a14 | ||
|
|
55a8954c48 | ||
|
|
0b1166ff78 | ||
|
|
b2d2cc1840 | ||
|
|
4b89264dfc | ||
|
|
1168f58987 | ||
|
|
0928b5b026 | ||
|
|
8189597c0b | ||
|
|
9e54c48086 | ||
|
|
3863e69733 | ||
|
|
8b48413155 | ||
|
|
186abb84c1 | ||
|
|
10ba84b1fc | ||
|
|
a45304832b | ||
|
|
dd8fe4bf69 | ||
|
|
e9427a9ca7 | ||
|
|
23d2d19846 | ||
|
|
1da2890856 | ||
|
|
47a3a84108 | ||
|
|
43842e0de5 | ||
|
|
fbab099fa9 | ||
|
|
e38d8a8340 | ||
|
|
603e6c74f2 | ||
|
|
13b4058f2f | ||
|
|
ad4ebaac93 | ||
|
|
a50c571929 | ||
|
|
4f48af0cb4 | ||
|
|
24561ad59c | ||
|
|
eacd5d72ec | ||
|
|
5b51f9d1ba | ||
|
|
2ebe28468b | ||
|
|
b0bb781fc7 | ||
|
|
21af5e0abd | ||
|
|
6697bb7bed | ||
|
|
448ad6f1bc | ||
|
|
2fa35fb494 | ||
|
|
6ef67a2d8e | ||
|
|
60683f1cce | ||
|
|
eaf19734e7 | ||
|
|
9a341ec18f | ||
|
|
f93d2c79e5 | ||
|
|
b8cab9bae2 | ||
|
|
40d05ace57 | ||
|
|
64cb6204cc | ||
|
|
c3b63d2fd9 | ||
|
|
7cbaee253a | ||
|
|
f5956dbbcf | ||
|
|
25b80b8a16 | ||
|
|
29d3db8ffe | ||
|
|
2eff928e7c | ||
|
|
a7d5b3dbc1 | ||
|
|
cc0777b792 | ||
|
|
8a984260e7 | ||
|
|
370f180ca0 | ||
|
|
fb4a5a116a | ||
|
|
1817ccdb57 | ||
|
|
154f7aae7b | ||
|
|
3a8310a60b | ||
|
|
bb1390c0c7 | ||
|
|
1dc3891f96 | ||
|
|
dff80ff7d0 | ||
|
|
30a770aab0 | ||
|
|
36cd8bfea7 | ||
|
|
072d46880a | ||
|
|
c59ac8fba1 | ||
|
|
ce6c347f85 | ||
|
|
22de74a45b | ||
|
|
16268c9c21 | ||
|
|
3e44d4ea5c | ||
|
|
d62180d0ff | ||
|
|
bf79e223ae | ||
|
|
92a31a6fb2 | ||
|
|
6b687977d9 | ||
|
|
0a16b24268 | ||
|
|
a1433c485e | ||
|
|
b64f4428c1 | ||
|
|
e7b663fe94 | ||
|
|
29e687978b | ||
|
|
dbeb1947ea | ||
|
|
cdb31d423c | ||
|
|
87208d210b | ||
|
|
121607b351 | ||
|
|
2cb0fc78fb | ||
|
|
94b2db2de6 | ||
|
|
678bb28168 | ||
|
|
aa1e7d642f | ||
|
|
7e7e761d7f | ||
|
|
0b3b8f7833 | ||
|
|
c8b54dc91a | ||
|
|
71465f79b1 | ||
|
|
ff0816979c | ||
|
|
2a0578227e | ||
|
|
30cc73d6ed | ||
|
|
7fbb77c067 | ||
|
|
185e087c40 | ||
|
|
f29d6a4f0f | ||
|
|
597cccce0f | ||
|
|
eced5f98a0 | ||
|
|
20f7ab8ade | ||
|
|
e5682d3948 | ||
|
|
b843635a50 | ||
|
|
ba74b99fd7 | ||
|
|
6d0183ea78 | ||
|
|
dfc0aea1e7 | ||
|
|
5c01c5acd8 | ||
|
|
6d83575490 | ||
|
|
e51a40c0d8 | ||
|
|
53bc77644c | ||
|
|
6782ec0104 | ||
|
|
588e71c1e9 | ||
|
|
6b7c9aa5c8 | ||
|
|
5e53df769d | ||
|
|
3b325f6812 | ||
|
|
4f1a205c83 | ||
|
|
3620029ae0 | ||
|
|
217d9f6651 | ||
|
|
ba3d43138a | ||
|
|
e027681803 | ||
|
|
57ccede250 | ||
|
|
04dbae2cb4 | ||
|
|
af13711fac | ||
|
|
92248f92ca | ||
|
|
9832d4a84a | ||
|
|
b7cdc191ca | ||
|
|
54fab2f2e5 | ||
|
|
4337022524 | ||
|
|
3be5f5ddd8 | ||
|
|
a55e9eca40 | ||
|
|
33a64260cd | ||
|
|
1848a2cf9d | ||
|
|
c431d38d97 | ||
|
|
ebb2835c45 | ||
|
|
98b2fa5104 | ||
|
|
a63c8a2ec8 | ||
|
|
aca917b4ca | ||
|
|
4425627683 | ||
|
|
b16a663618 | ||
|
|
62c94e272f | ||
|
|
0c12f6fe10 | ||
|
|
73e2d8ca7e | ||
|
|
b0e2ed1cc7 | ||
|
|
a1d528ae92 | ||
|
|
b5fd460560 | ||
|
|
205367ab3f | ||
|
|
4bd0def6fb | ||
|
|
4411344f7c | ||
|
|
7ff9def95b | ||
|
|
b3b394c329 | ||
|
|
4dd1bc9ef6 | ||
|
|
1b4dfc8745 | ||
|
|
0747198ee3 | ||
|
|
01f683c3c4 | ||
|
|
23d1746bbf | ||
|
|
aa28ae7863 | ||
|
|
02f1d828d9 | ||
|
|
b528910e7a | ||
|
|
dcccd0e532 | ||
|
|
af833e3006 | ||
|
|
82c93a6448 | ||
|
|
49b88757b0 | ||
|
|
30f6bcc30c | ||
|
|
796a40b5d7 | ||
|
|
1c568a4916 | ||
|
|
12f692f436 | ||
|
|
9b5851c36c | ||
|
|
077e330b64 | ||
|
|
86364c2150 | ||
|
|
2dd198c6c4 | ||
|
|
c08d7e9f19 | ||
|
|
5bd641834d | ||
|
|
bc745b6e99 | ||
|
|
0b0c76626b | ||
|
|
2fbd578a77 | ||
|
|
04aa45fcd8 | ||
|
|
71d6c1d3c6 | ||
|
|
063e4d0870 | ||
|
|
70ba0d60ec | ||
|
|
1cd50482d2 | ||
|
|
bf73470723 | ||
|
|
2e072fe0e2 | ||
|
|
7f5a8c3aac | ||
|
|
f621df68ae | ||
|
|
6a6ffe2ad6 | ||
|
|
1dd345c56d | ||
|
|
bc0c64ef82 | ||
|
|
702a88956b | ||
|
|
fad6f06ace | ||
|
|
e697444f29 | ||
|
|
d595605ff1 | ||
|
|
b9e970d934 | ||
|
|
999ba49857 | ||
|
|
21bd141866 | ||
|
|
e88f436302 | ||
|
|
2d17132f48 | ||
|
|
8accb0978e | ||
|
|
867de91643 | ||
|
|
1de3c22a44 | ||
|
|
eac32148a4 | ||
|
|
37bfae0d2f | ||
|
|
2504666a72 | ||
|
|
9e415dcc6d | ||
|
|
e4efdb3bd4 | ||
|
|
721ad3ecc2 | ||
|
|
8618929e9a | ||
|
|
b3df8fb1e6 | ||
|
|
492f491056 | ||
|
|
7650cdc662 | ||
|
|
a72cb80337 | ||
|
|
e1abd4d373 | ||
|
|
37859888b5 | ||
|
|
88aaba22b5 | ||
|
|
a997ab3341 | ||
|
|
153041ac93 | ||
|
|
68cb5fc2eb | ||
|
|
ee7aafb135 | ||
|
|
b047d7f312 | ||
|
|
1537d42706 | ||
|
|
4b566f153f | ||
|
|
f34986d30f | ||
|
|
a713a86f06 | ||
|
|
08bc9870bc | ||
|
|
94e085f1a2 | ||
|
|
241f2e9dfe | ||
|
|
c864c6e463 | ||
|
|
bc55f3dda8 | ||
|
|
39a3a78729 | ||
|
|
31f65b97b1 | ||
|
|
3837ea85e0 | ||
|
|
fedd5f1162 | ||
|
|
dc108f555e | ||
|
|
93a0a422b4 | ||
|
|
e899bed4d7 | ||
|
|
87fbc2e5e4 | ||
|
|
cf61ad3285 | ||
|
|
f772cfdefb | ||
|
|
a1e7bc0b01 | ||
|
|
e5c79fc5c1 | ||
|
|
a3b05e8e38 | ||
|
|
89cfedd39b | ||
|
|
1be18ed53c | ||
|
|
e2265ec3b3 | ||
|
|
5ba3b3a5a8 | ||
|
|
6a513e4340 | ||
|
|
1ea2a0c29b | ||
|
|
3a163fca64 | ||
|
|
36e4402550 | ||
|
|
effb5d4de0 | ||
|
|
a854feeb1e | ||
|
|
cbb0a8698f | ||
|
|
d21b00c767 | ||
|
|
5311777308 | ||
|
|
7a5685af57 | ||
|
|
38e2bcaf85 | ||
|
|
0dda0ce5d7 | ||
|
|
8fc72fd352 | ||
|
|
dc3f1b5edf | ||
|
|
dd38ab8f43 | ||
|
|
7051977808 | ||
|
|
d9f315d63e | ||
|
|
5e9635dfa4 | ||
|
|
f2a9e9a360 | ||
|
|
1080246af9 | ||
|
|
fcb4ec0303 | ||
|
|
8211554efa | ||
|
|
464699215c | ||
|
|
10bb62a728 | ||
|
|
46710bfb25 | ||
|
|
fcb54eee12 | ||
|
|
a686be5c31 | ||
|
|
bd5e5d71b5 | ||
|
|
711c8e3328 | ||
|
|
ec1f7e3e6e | ||
|
|
8535a906be | ||
|
|
eef8a7b280 | ||
|
|
891f0ed3a2 | ||
|
|
e93bf0632b | ||
|
|
31c0ec6d63 | ||
|
|
fc3cb76695 | ||
|
|
389f33ea81 | ||
|
|
abc0cc4c40 | ||
|
|
1654ef820b | ||
|
|
df3485ec64 | ||
|
|
59257d7a3a | ||
|
|
a052a0db65 | ||
|
|
65dd1137da | ||
|
|
236d20946c | ||
|
|
a796715ac1 | ||
|
|
abfd4fef76 | ||
|
|
95acf7dd25 | ||
|
|
02b3cec827 | ||
|
|
c3a2f88b63 | ||
|
|
bc2a628a10 | ||
|
|
6518d1eb4c | ||
|
|
a2ead3545e | ||
|
|
a163f327eb | ||
|
|
e9d6a7209c | ||
|
|
f0290b08dd | ||
|
|
51637ec6d4 | ||
|
|
4d77c3ae45 | ||
|
|
a7f9abe827 | ||
|
|
41029aef24 | ||
|
|
c75a022a23 | ||
|
|
1acf6321a5 | ||
|
|
e164980d84 | ||
|
|
71ebe27a8d | ||
|
|
e7ebee3084 | ||
|
|
1239f78baf | ||
|
|
5f4c005771 | ||
|
|
9e0a0b6a43 | ||
|
|
5c85d28285 | ||
|
|
f65bc62fac | ||
|
|
9b12953343 | ||
|
|
84f9793231 | ||
|
|
1f46ecf4b8 | ||
|
|
eef90bf320 | ||
|
|
3796a8799a | ||
|
|
c726655d23 | ||
|
|
bdfac3e25c | ||
|
|
faf1459ce5 | ||
|
|
02751f4d11 | ||
|
|
992c9f24eb | ||
|
|
8164fa09d3 | ||
|
|
5e50601788 | ||
|
|
23e79de2c2 | ||
|
|
4accc8a79c | ||
|
|
7522cbf4f0 | ||
|
|
3a25a594ca | ||
|
|
40374e5056 | ||
|
|
4e4fb179e7 | ||
|
|
0f2effb049 | ||
|
|
63ee15ca6e | ||
|
|
f8a105d972 | ||
|
|
f2707106bd | ||
|
|
1586cfdb03 | ||
|
|
ca8b1d2b34 | ||
|
|
100d8d2a47 | ||
|
|
efe03d6988 | ||
|
|
7b59186dfe | ||
|
|
e9f403ac44 | ||
|
|
2038f38026 | ||
|
|
6e9a5d4cea | ||
|
|
495e906169 | ||
|
|
2e6cedcad7 | ||
|
|
d76f936698 | ||
|
|
0e9feaede3 | ||
|
|
cd55e2d522 | ||
|
|
3d2bf2d9ac | ||
|
|
2f4d1b93e8 | ||
|
|
f06d99f7b5 | ||
|
|
1b13fb05ea | ||
|
|
f90da509e1 | ||
|
|
c8afb6d92d | ||
|
|
b0950d1593 | ||
|
|
9f569c61f9 | ||
|
|
7874b3c60e | ||
|
|
99afbe9ec8 | ||
|
|
78aa2fa1db | ||
|
|
111e309507 | ||
|
|
7a86663128 | ||
|
|
6f24013463 | ||
|
|
d508c231b5 | ||
|
|
8f7e2bb98a | ||
|
|
39fc42d1cf | ||
|
|
7f6603ea4a | ||
|
|
3b1289ba40 | ||
|
|
6464cff113 | ||
|
|
4f5599e275 | ||
|
|
f98a3f9eab | ||
|
|
c9c67b5b67 | ||
|
|
3803db5555 | ||
|
|
a33849ef9b | ||
|
|
b09e0fbfa4 | ||
|
|
402fea6902 | ||
|
|
589036f5c9 | ||
|
|
d3b2258acb | ||
|
|
6103a308af | ||
|
|
8d20ae913a | ||
|
|
9fc7fb8d51 | ||
|
|
6da7f317a3 | ||
|
|
d0d755ff87 | ||
|
|
56b5446eaf | ||
|
|
88020835d6 | ||
|
|
d4b78be306 | ||
|
|
5ff836ed26 | ||
|
|
6b4dca7361 | ||
|
|
7ac998fafc | ||
|
|
888934a3be | ||
|
|
fb5ee9fbc2 | ||
|
|
b2c56e94c9 | ||
|
|
3e5faf9c56 | ||
|
|
b0297c5c91 | ||
|
|
9aba1c17f6 | ||
|
|
0fc5d3f656 | ||
|
|
729abf8e9b | ||
|
|
96215c5da6 | ||
|
|
f4c455bc2f | ||
|
|
22904e41de | ||
|
|
d49c742daf | ||
|
|
a59a2f6177 | ||
|
|
2f399b9ba4 | ||
|
|
4b61723952 | ||
|
|
00ab690758 | ||
|
|
d4b4d69469 | ||
|
|
283559bd97 | ||
|
|
38442b06d4 | ||
|
|
ae0d744357 | ||
|
|
094074d8c6 | ||
|
|
9b192b4be4 | ||
|
|
5fcdd03f12 | ||
|
|
d89dbd354a | ||
|
|
ed273e108d | ||
|
|
03dec4cde4 | ||
|
|
171c3825fa | ||
|
|
be2e602efa | ||
|
|
2ca4573b01 | ||
|
|
cdc005f46a | ||
|
|
19d5aaa513 | ||
|
|
83966b7563 | ||
|
|
b2b2bdfccd | ||
|
|
cf8c54689b | ||
|
|
a8cd995624 | ||
|
|
82a6064803 | ||
|
|
f8b51d01b7 | ||
|
|
3cbb73a63c | ||
|
|
d24a421efd | ||
|
|
6cf4e9a763 | ||
|
|
2e26da9666 | ||
|
|
e102abe98f | ||
|
|
4c1362aff8 | ||
|
|
1a4cf45f03 | ||
|
|
374df70218 | ||
|
|
a57b867ee6 | ||
|
|
927aebfa8b | ||
|
|
4f0a39159a | ||
|
|
76d2ecbb17 | ||
|
|
73322e88d2 | ||
|
|
0620b91efa | ||
|
|
ea4d4ff80d | ||
|
|
45c33fe0f6 | ||
|
|
fe249e20b9 | ||
|
|
e819e13a5d | ||
|
|
5c95fbda65 | ||
|
|
3e217115bc | ||
|
|
5d564fdbcf | ||
|
|
8184b964bc | ||
|
|
0daeebc0eb | ||
|
|
5939fdb140 | ||
|
|
9dd850b672 | ||
|
|
21601d9c3d | ||
|
|
332a1baedd | ||
|
|
e8aadb77b8 | ||
|
|
31c1faea32 | ||
|
|
818a53003e | ||
|
|
78419f858c | ||
|
|
b1d10a12fa | ||
|
|
f404cdd54b | ||
|
|
c463234452 | ||
|
|
b1020ad9c8 | ||
|
|
0ad0d195e5 | ||
|
|
43bf05c42e | ||
|
|
236df49362 | ||
|
|
bccd73c8f5 | ||
|
|
fd487dfa5c | ||
|
|
3cb3227d56 | ||
|
|
f183d60b13 | ||
|
|
8c8cd29142 | ||
|
|
83e8c144ed | ||
|
|
06c7c53127 | ||
|
|
ec682b1f9b | ||
|
|
7a15d9879f | ||
|
|
dea37444bc | ||
|
|
f5a20e5379 | ||
|
|
a0573c51b1 | ||
|
|
d0cb14c7ce | ||
|
|
f2b2327c24 | ||
|
|
9d5a940be3 | ||
|
|
38d91b66b0 | ||
|
|
65ebd30334 | ||
|
|
1998cef2b4 | ||
|
|
030cff2eda | ||
|
|
02facac20a | ||
|
|
7789ccb90a | ||
|
|
d497c9ae9c | ||
|
|
cdf1e8d6e9 | ||
|
|
5f4a002787 | ||
|
|
c34968d282 | ||
|
|
f76f983182 | ||
|
|
312ce93bb4 | ||
|
|
06776557cf | ||
|
|
d831cbf17b | ||
|
|
aad2259522 | ||
|
|
e1bd98fc7c | ||
|
|
7ca9b07b68 | ||
|
|
1532bf1922 | ||
|
|
ac544460e4 | ||
|
|
d2989eb3e0 | ||
|
|
73be034d5e | ||
|
|
b5d6736f76 | ||
|
|
1c38ffd30b | ||
|
|
8e4b3565f8 | ||
|
|
31445645f7 | ||
|
|
fc053917d8 | ||
|
|
201df0a782 | ||
|
|
b59a7cd979 | ||
|
|
8f7aed712b | ||
|
|
3e946b1b4f | ||
|
|
2a16431b2d | ||
|
|
6815622d2c | ||
|
|
5c32c2a226 | ||
|
|
b363396a93 | ||
|
|
87382097df | ||
|
|
e6d2f12bf6 | ||
|
|
43ee096cee | ||
|
|
2b1eecebb2 | ||
|
|
c0d83f95a8 | ||
|
|
01ded5d150 | ||
|
|
5884cf3774 | ||
|
|
d15818bafa | ||
|
|
f74ec0661d | ||
|
|
d68dcd252e | ||
|
|
30bfb6e6b7 | ||
|
|
bfa5de8c55 | ||
|
|
6a665a588f | ||
|
|
55ff76171a | ||
|
|
a701bb71c4 | ||
|
|
6343639193 | ||
|
|
5ce5c62611 | ||
|
|
3ebff6ae54 | ||
|
|
d9a03f4600 | ||
|
|
59b132f0f7 | ||
|
|
d56bf992d2 | ||
|
|
efa7941c54 | ||
|
|
808850a464 | ||
|
|
24ad44b46f | ||
|
|
737ad58740 | ||
|
|
a856622f0c | ||
|
|
ce79c243a3 | ||
|
|
e1b369f34e | ||
|
|
0a73777381 | ||
|
|
176b551af0 |
145
CHANGELOG
Normal file
145
CHANGELOG
Normal file
@@ -0,0 +1,145 @@
|
||||
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
|
||||
13
LICENCE
Normal file
13
LICENCE
Normal file
@@ -0,0 +1,13 @@
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
Version 2, December 2004
|
||||
|
||||
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim or modified
|
||||
copies of this license document, and changing it is allowed as long
|
||||
as the name is changed.
|
||||
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||
121
README.markdown
Normal file
121
README.markdown
Normal file
@@ -0,0 +1,121 @@
|
||||
The NERD Tree
|
||||
=============
|
||||
|
||||
Intro
|
||||
-----
|
||||
|
||||
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 following features and functionality are provided by the NERD tree:
|
||||
|
||||
* 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)
|
||||
|
||||
cd ~/.vim/bundle
|
||||
git clone https://github.com/scrooloose/nerdtree.git
|
||||
|
||||
Then reload vim, run `:Helptags`, and check out `:help NERD_tree.txt`.
|
||||
|
||||
|
||||
####[apt-vim](https://github.com/egalpin/apt-vim)
|
||||
|
||||
apt-vim install -y https://github.com/scrooloose/nerdtree.git
|
||||
|
||||
|
||||
|
||||
Faq
|
||||
---
|
||||
|
||||
> 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?
|
||||
|
||||
Nope. If this is something you want then chances are you aren't using tabs and
|
||||
buffers as they were intended to be used. Read this
|
||||
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
|
||||
|
||||
autocmd StdinReadPre * let s:std_in=1
|
||||
autocmd VimEnter * if argc() == 0 && !exists("s:std_in") | NERDTree | endif
|
||||
|
||||
> How can I map a specific key or shortcut to open NERDTree?
|
||||
|
||||
Stick this in your vimrc to open NERDTree with `Ctrl+n` (you can set whatever key you want):
|
||||
|
||||
map <C-n> :NERDTreeToggle<CR>
|
||||
|
||||
> How can I close vim if the only window left open is a NERDTree?
|
||||
|
||||
Stick this in your vimrc:
|
||||
|
||||
autocmd bufenter * if (winnr("$") == 1 && exists("b:NERDTreeType") && b:NERDTreeType == "primary") | 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 = '▾'
|
||||
18
Rakefile
18
Rakefile
@@ -1,18 +0,0 @@
|
||||
desc "Copy the vim/doc files into ~/.vim"
|
||||
task :deploy_local do
|
||||
run "cp plugin/NERD_tree.vim ~/.vim/plugin"
|
||||
run "cp doc/NERD_tree.txt ~/.vim/doc"
|
||||
end
|
||||
|
||||
|
||||
desc "Create a zip archive for release to vim.org"
|
||||
task :zip do
|
||||
abort "NERD_tree.zip already exists, aborting" if File.exist?("NERD_tree.zip")
|
||||
run "zip NERD_tree.zip plugin/NERD_tree.vim doc/NERD_tree.txt"
|
||||
end
|
||||
|
||||
def run(cmd)
|
||||
puts "Executing: #{cmd}"
|
||||
system cmd
|
||||
end
|
||||
|
||||
147
autoload/nerdtree.vim
Normal file
147
autoload/nerdtree.vim
Normal file
@@ -0,0 +1,147 @@
|
||||
if exists("g:loaded_nerdtree_autoload")
|
||||
finish
|
||||
endif
|
||||
let g:loaded_nerdtree_autoload = 1
|
||||
|
||||
function! nerdtree#version()
|
||||
return '5.0.0'
|
||||
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)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" FUNCTION: nerdtree#completeBookmarks(A,L,P) {{{2
|
||||
" completion function for the bookmark commands
|
||||
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)
|
||||
endfunction
|
||||
|
||||
"FUNCTION: nerdtree#compareNodesBySortKey(n1, n2) {{{2
|
||||
function! nerdtree#compareNodesBySortKey(n1, n2)
|
||||
if a:n1.path.getSortKey() <# a:n2.path.getSortKey()
|
||||
return -1
|
||||
elseif a:n1.path.getSortKey() ># a:n2.path.getSortKey()
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" FUNCTION: nerdtree#deprecated(func, [msg]) {{{2
|
||||
" Issue a deprecation warning for a:func. If a second arg is given, use this
|
||||
" as the deprecation message
|
||||
function! nerdtree#deprecated(func, ...)
|
||||
let msg = a:0 ? a:func . ' ' . a:1 : a:func . ' is deprecated'
|
||||
|
||||
if !exists('s:deprecationWarnings')
|
||||
let s:deprecationWarnings = {}
|
||||
endif
|
||||
if !has_key(s:deprecationWarnings, a:func)
|
||||
let s:deprecationWarnings[a:func] = 1
|
||||
echomsg msg
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" FUNCTION: nerdtree#exec(cmd) {{{2
|
||||
" same as :exec cmd but eventignore=all is set for the duration
|
||||
function! nerdtree#exec(cmd)
|
||||
let old_ei = &ei
|
||||
set ei=all
|
||||
exec a:cmd
|
||||
let &ei = old_ei
|
||||
endfunction
|
||||
|
||||
" FUNCTION: nerdtree#has_opt(options, name) {{{2
|
||||
function! nerdtree#has_opt(options, name)
|
||||
return has_key(a:options, a:name) && a:options[a:name] == 1
|
||||
endfunction
|
||||
|
||||
" FUNCTION: nerdtree#loadClassFiles() {{{2
|
||||
function! nerdtree#loadClassFiles()
|
||||
runtime lib/nerdtree/path.vim
|
||||
runtime lib/nerdtree/menu_controller.vim
|
||||
runtime lib/nerdtree/menu_item.vim
|
||||
runtime lib/nerdtree/key_map.vim
|
||||
runtime lib/nerdtree/bookmark.vim
|
||||
runtime lib/nerdtree/tree_file_node.vim
|
||||
runtime lib/nerdtree/tree_dir_node.vim
|
||||
runtime lib/nerdtree/opener.vim
|
||||
runtime lib/nerdtree/creator.vim
|
||||
runtime lib/nerdtree/flag_set.vim
|
||||
runtime lib/nerdtree/nerdtree.vim
|
||||
runtime lib/nerdtree/ui.vim
|
||||
runtime lib/nerdtree/event.vim
|
||||
runtime lib/nerdtree/notifier.vim
|
||||
endfunction
|
||||
|
||||
" FUNCTION: nerdtree#postSourceActions() {{{2
|
||||
function! nerdtree#postSourceActions()
|
||||
call g:NERDTreeBookmark.CacheBookmarks(0)
|
||||
call nerdtree#ui_glue#createDefaultBindings()
|
||||
|
||||
"load all nerdtree plugins
|
||||
runtime! nerdtree_plugin/**/*.vim
|
||||
endfunction
|
||||
|
||||
"FUNCTION: nerdtree#runningWindows(dir) {{{2
|
||||
function! nerdtree#runningWindows()
|
||||
return has("win16") || has("win32") || has("win64")
|
||||
endfunction
|
||||
|
||||
" SECTION: View Functions {{{1
|
||||
"============================================================
|
||||
|
||||
"FUNCTION: nerdtree#echo {{{2
|
||||
"A wrapper for :echo. Appends 'NERDTree:' on the front of all messages
|
||||
"
|
||||
"Args:
|
||||
"msg: the message to echo
|
||||
function! nerdtree#echo(msg)
|
||||
redraw
|
||||
echomsg "NERDTree: " . a:msg
|
||||
endfunction
|
||||
|
||||
"FUNCTION: nerdtree#echoError {{{2
|
||||
"Wrapper for nerdtree#echo, sets the message type to errormsg for this message
|
||||
"Args:
|
||||
"msg: the message to echo
|
||||
function! nerdtree#echoError(msg)
|
||||
echohl errormsg
|
||||
call nerdtree#echo(a:msg)
|
||||
echohl normal
|
||||
endfunction
|
||||
|
||||
"FUNCTION: nerdtree#echoWarning {{{2
|
||||
"Wrapper for nerdtree#echo, sets the message type to warningmsg for this message
|
||||
"Args:
|
||||
"msg: the message to echo
|
||||
function! nerdtree#echoWarning(msg)
|
||||
echohl warningmsg
|
||||
call nerdtree#echo(a:msg)
|
||||
echohl normal
|
||||
endfunction
|
||||
|
||||
"FUNCTION: nerdtree#renderView {{{2
|
||||
function! nerdtree#renderView()
|
||||
call b:NERDTree.render()
|
||||
endfunction
|
||||
|
||||
" vim: set sw=4 sts=4 et fdm=marker:
|
||||
644
autoload/nerdtree/ui_glue.vim
Normal file
644
autoload/nerdtree/ui_glue.vim
Normal file
@@ -0,0 +1,644 @@
|
||||
if exists("g:loaded_nerdtree_ui_glue_autoload")
|
||||
finish
|
||||
endif
|
||||
let g:loaded_nerdtree_ui_glue_autoload = 1
|
||||
|
||||
" FUNCTION: nerdtree#ui_glue#createDefaultBindings() {{{1
|
||||
function! nerdtree#ui_glue#createDefaultBindings()
|
||||
let s = '<SNR>' . s:SID() . '_'
|
||||
|
||||
call NERDTreeAddKeyMap({ 'key': '<MiddleRelease>', 'scope': "all", 'callback': s."handleMiddleMouse" })
|
||||
call NERDTreeAddKeyMap({ 'key': '<LeftRelease>', 'scope': "all", 'callback': s."handleLeftClick" })
|
||||
call NERDTreeAddKeyMap({ 'key': '<2-LeftMouse>', 'scope': "DirNode", 'callback': s."activateDirNode" })
|
||||
call NERDTreeAddKeyMap({ 'key': '<2-LeftMouse>', 'scope': "FileNode", 'callback': s."activateFileNode" })
|
||||
call NERDTreeAddKeyMap({ 'key': '<2-LeftMouse>', 'scope': "Bookmark", 'callback': s."activateBookmark" })
|
||||
call NERDTreeAddKeyMap({ 'key': '<2-LeftMouse>', 'scope': "all", 'callback': s."activateAll" })
|
||||
|
||||
|
||||
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapActivateNode, 'scope': "DirNode", 'callback': s."activateDirNode" })
|
||||
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapActivateNode, 'scope': "FileNode", 'callback': s."activateFileNode" })
|
||||
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapActivateNode, 'scope': "Bookmark", 'callback': s."activateBookmark" })
|
||||
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapActivateNode, 'scope': "all", 'callback': s."activateAll" })
|
||||
|
||||
call NERDTreeAddKeyMap({ 'key': g: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:NERDTreeMapChdir, 'scope': "Node", 'callback': s."chCwd" })
|
||||
|
||||
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapQuit, 'scope': "all", 'callback': s."closeTreeWindow" })
|
||||
|
||||
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapCWD, 'scope': "all", 'callback': "nerdtree#ui_glue#chRootCwd" })
|
||||
|
||||
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapRefreshRoot, 'scope': "all", 'callback': s."refreshRoot" })
|
||||
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapRefresh, 'scope': "Node", 'callback': s."refreshCurrent" })
|
||||
|
||||
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapHelp, 'scope': "all", 'callback': s."displayHelp" })
|
||||
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapToggleZoom, 'scope': "all", 'callback': s."toggleZoom" })
|
||||
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapToggleHidden, 'scope': "all", 'callback': s."toggleShowHidden" })
|
||||
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapToggleFilters, 'scope': "all", 'callback': s."toggleIgnoreFilter" })
|
||||
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapToggleFiles, 'scope': "all", 'callback': s."toggleShowFiles" })
|
||||
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapToggleBookmarks, 'scope': "all", 'callback': s."toggleShowBookmarks" })
|
||||
|
||||
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapCloseDir, 'scope': "Node", 'callback': s."closeCurrentDir" })
|
||||
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapCloseChildren, 'scope': "DirNode", 'callback': s."closeChildren" })
|
||||
|
||||
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapMenu, 'scope': "Node", 'callback': s."showMenu" })
|
||||
|
||||
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpParent, 'scope': "Node", 'callback': s."jumpToParent" })
|
||||
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpFirstChild, 'scope': "Node", 'callback': s."jumpToFirstChild" })
|
||||
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpLastChild, 'scope': "Node", 'callback': s."jumpToLastChild" })
|
||||
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpRoot, 'scope': "all", 'callback': s."jumpToRoot" })
|
||||
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpNextSibling, 'scope': "Node", 'callback': s."jumpToNextSibling" })
|
||||
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpPrevSibling, 'scope': "Node", 'callback': s."jumpToPrevSibling" })
|
||||
|
||||
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenInTab, 'scope': "Node", 'callback': s."openInNewTab" })
|
||||
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenInTabSilent, 'scope': "Node", 'callback': s."openInNewTabSilent" })
|
||||
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenInTab, 'scope': "Bookmark", 'callback': s."openInNewTab" })
|
||||
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenInTabSilent, 'scope': "Bookmark", 'callback': s."openInNewTabSilent" })
|
||||
|
||||
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenExpl, 'scope': "DirNode", 'callback': s."openExplorer" })
|
||||
|
||||
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapDeleteBookmark, 'scope': "Bookmark", 'callback': s."deleteBookmark" })
|
||||
endfunction
|
||||
|
||||
|
||||
"SECTION: Interface bindings {{{1
|
||||
"============================================================
|
||||
|
||||
"FUNCTION: s:activateAll() {{{1
|
||||
"handle the user activating the updir line
|
||||
function! s:activateAll()
|
||||
if getline(".") ==# g:NERDTreeUI.UpDirLine()
|
||||
return nerdtree#ui_glue#upDir(0)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:activateDirNode() {{{1
|
||||
"handle the user activating a tree node
|
||||
function! s:activateDirNode(node)
|
||||
call a:node.activate()
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:activateFileNode() {{{1
|
||||
"handle the user activating a tree node
|
||||
function! s:activateFileNode(node)
|
||||
call a:node.activate({'reuse': 'all', 'where': 'p'})
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:activateBookmark() {{{1
|
||||
"handle the user activating a bookmark
|
||||
function! s:activateBookmark(bm)
|
||||
call a:bm.activate(!a:bm.path.isDirectory ? {'where': 'p'} : {})
|
||||
endfunction
|
||||
|
||||
" FUNCTION: nerdtree#ui_glue#bookmarkNode(name) {{{1
|
||||
" Associate the current node with the given name
|
||||
function! nerdtree#ui_glue#bookmarkNode(...)
|
||||
let currentNode = g:NERDTreeFileNode.GetSelected()
|
||||
if currentNode != {}
|
||||
let name = a:1
|
||||
if empty(name)
|
||||
let name = currentNode.path.getLastPathComponent(0)
|
||||
endif
|
||||
try
|
||||
call currentNode.bookmark(name)
|
||||
call b:NERDTree.render()
|
||||
catch /^NERDTree.IllegalBookmarkNameError/
|
||||
call nerdtree#echo("bookmark names must not contain spaces")
|
||||
endtry
|
||||
else
|
||||
call nerdtree#echo("select a node first")
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:chCwd(node) {{{1
|
||||
function! s:chCwd(node)
|
||||
try
|
||||
call a:node.path.changeToDir()
|
||||
catch /^NERDTree.PathChangeError/
|
||||
call nerdtree#echoWarning("could not change cwd")
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:chRoot(node) {{{1
|
||||
" changes the current root to the selected one
|
||||
function! s:chRoot(node)
|
||||
call a:node.makeRoot()
|
||||
call b:NERDTree.render()
|
||||
call b:NERDTreeRoot.putCursorHere(0, 0)
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:nerdtree#ui_glue#chRootCwd() {{{1
|
||||
" changes the current root to CWD
|
||||
function! nerdtree#ui_glue#chRootCwd()
|
||||
try
|
||||
let cwd = g:NERDTreePath.New(getcwd())
|
||||
catch /^NERDTree.InvalidArgumentsError/
|
||||
call nerdtree#echo("current directory does not exist.")
|
||||
return
|
||||
endtry
|
||||
if cwd.str() == g:NERDTreeFileNode.GetRootForTab().path.str()
|
||||
return
|
||||
endif
|
||||
call s:chRoot(g:NERDTreeDirNode.New(cwd))
|
||||
endfunction
|
||||
|
||||
" FUNCTION: nnerdtree#ui_glue#clearBookmarks(bookmarks) {{{1
|
||||
function! nerdtree#ui_glue#clearBookmarks(bookmarks)
|
||||
if a:bookmarks ==# ''
|
||||
let currentNode = g:NERDTreeFileNode.GetSelected()
|
||||
if currentNode != {}
|
||||
call currentNode.clearBookmarks()
|
||||
endif
|
||||
else
|
||||
for name in split(a:bookmarks, ' ')
|
||||
let bookmark = g:NERDTreeBookmark.BookmarkFor(name)
|
||||
call bookmark.delete()
|
||||
endfor
|
||||
endif
|
||||
call b:NERDTree.render()
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:closeChildren(node) {{{1
|
||||
" closes all childnodes of the current node
|
||||
function! s:closeChildren(node)
|
||||
call a:node.closeChildren()
|
||||
call b:NERDTree.render()
|
||||
call a:node.putCursorHere(0, 0)
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:closeCurrentDir(node) {{{1
|
||||
" closes the parent dir of the current node
|
||||
function! s:closeCurrentDir(node)
|
||||
let parent = a:node.parent
|
||||
if parent ==# {} || parent.isRoot()
|
||||
call nerdtree#echo("cannot close tree root")
|
||||
else
|
||||
while g:NERDTreeCascadeOpenSingleChildDir && !parent.parent.isRoot()
|
||||
if parent.parent.getVisibleChildCount() == 1
|
||||
call parent.close()
|
||||
let parent = parent.parent
|
||||
else
|
||||
break
|
||||
endif
|
||||
endwhile
|
||||
call parent.close()
|
||||
call b:NERDTree.render()
|
||||
call parent.putCursorHere(0, 0)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:closeTreeWindow() {{{1
|
||||
" close the tree window
|
||||
function! s:closeTreeWindow()
|
||||
if b:NERDTreeType ==# "secondary" && b:NERDTreePreviousBuf != -1
|
||||
exec "buffer " . b:NERDTreePreviousBuf
|
||||
else
|
||||
if winnr("$") > 1
|
||||
call g:NERDTree.Close()
|
||||
else
|
||||
call nerdtree#echo("Cannot close last window")
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:deleteBookmark(bm) {{{1
|
||||
" if the cursor is on a bookmark, prompt to delete
|
||||
function! s:deleteBookmark(bm)
|
||||
echo "Are you sure you wish to delete the bookmark:\n\"" . a:bm.name . "\" (yN):"
|
||||
|
||||
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" )
|
||||
endif
|
||||
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:displayHelp() {{{1
|
||||
" toggles the help display
|
||||
function! s:displayHelp()
|
||||
let b:treeShowHelp = b:treeShowHelp ? 0 : 1
|
||||
call b:NERDTree.render()
|
||||
call b:NERDTree.ui.centerView()
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:findAndRevealPath() {{{1
|
||||
function! s:findAndRevealPath()
|
||||
try
|
||||
let p = g:NERDTreePath.New(expand("%:p"))
|
||||
catch /^NERDTree.InvalidArgumentsError/
|
||||
call nerdtree#echo("no file for the current buffer")
|
||||
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())
|
||||
catch /^NERDTree.InvalidArgumentsError/
|
||||
call nerdtree#echo("current directory does not exist.")
|
||||
let cwd = p.getParent()
|
||||
endtry
|
||||
|
||||
if p.isUnder(cwd)
|
||||
call g:NERDTreeCreator.CreatePrimary(cwd.str())
|
||||
else
|
||||
call g:NERDTreeCreator.CreatePrimary(p.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
|
||||
endif
|
||||
endif
|
||||
call g:NERDTree.CursorToTreeWin()
|
||||
call b:NERDTreeRoot.reveal(p)
|
||||
|
||||
if p.isUnixHiddenFile()
|
||||
let g:NERDTreeShowHidden = showhidden
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:handleLeftClick() {{{1
|
||||
"Checks if the click should open the current node
|
||||
function! s:handleLeftClick()
|
||||
let currentNode = g:NERDTreeFileNode.GetSelected()
|
||||
if currentNode != {}
|
||||
|
||||
"the dir arrows are multibyte chars, and vim's string functions only
|
||||
"deal with single bytes - so split the line up with the hack below and
|
||||
"take the line substring manually
|
||||
let line = split(getline(line(".")), '\zs')
|
||||
let startToCur = ""
|
||||
for i in range(0,len(line)-1)
|
||||
let startToCur .= line[i]
|
||||
endfor
|
||||
|
||||
if currentNode.path.isDirectory
|
||||
if startToCur =~# g:NERDTreeUI.MarkupReg() && startToCur =~# '[+~'.g:NERDTreeDirArrowExpandable.g:NERDTreeDirArrowCollapsible.'] \?$'
|
||||
call currentNode.activate()
|
||||
return
|
||||
endif
|
||||
endif
|
||||
|
||||
if (g:NERDTreeMouseMode ==# 2 && currentNode.path.isDirectory) || g:NERDTreeMouseMode ==# 3
|
||||
let char = strpart(startToCur, strlen(startToCur)-1, 1)
|
||||
if char !~# g:NERDTreeUI.MarkupReg()
|
||||
if currentNode.path.isDirectory
|
||||
call currentNode.activate()
|
||||
else
|
||||
call currentNode.activate({'reuse': 'all', 'where': 'p'})
|
||||
endif
|
||||
return
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
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" )
|
||||
return
|
||||
endif
|
||||
|
||||
if curNode.path.isDirectory
|
||||
call nerdtree#openExplorer(curNode)
|
||||
else
|
||||
call curNode.open({'where': 'h'})
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:jumpToChild(direction) {{{2
|
||||
" Args:
|
||||
" direction: 0 if going to first child, 1 if going to last
|
||||
function! s:jumpToChild(currentNode, direction)
|
||||
if a:currentNode.isRoot()
|
||||
return nerdtree#echo("cannot jump to " . (a:direction ? "last" : "first") . " child")
|
||||
end
|
||||
let dirNode = a:currentNode.parent
|
||||
let childNodes = dirNode.getVisibleChildren()
|
||||
|
||||
let targetNode = childNodes[0]
|
||||
if a:direction
|
||||
let targetNode = childNodes[len(childNodes) - 1]
|
||||
endif
|
||||
|
||||
if targetNode.equals(a:currentNode)
|
||||
let siblingDir = a:currentNode.parent.findOpenDirSiblingWithVisibleChildren(a:direction)
|
||||
if siblingDir != {}
|
||||
let indx = a:direction ? siblingDir.getVisibleChildCount()-1 : 0
|
||||
let targetNode = siblingDir.getChildByIndex(indx, 1)
|
||||
endif
|
||||
endif
|
||||
|
||||
call targetNode.putCursorHere(1, 0)
|
||||
|
||||
call b:NERDTree.ui.centerView()
|
||||
endfunction
|
||||
|
||||
|
||||
" FUNCTION: nerdtree#ui_glue#invokeKeyMap(key) {{{1
|
||||
"this is needed since I cant figure out how to invoke dict functions from a
|
||||
"key map
|
||||
function! nerdtree#ui_glue#invokeKeyMap(key)
|
||||
call g:NERDTreeKeyMap.Invoke(a:key)
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:jumpToFirstChild() {{{1
|
||||
" wrapper for the jump to child method
|
||||
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)
|
||||
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")
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:jumpToRoot() {{{1
|
||||
" moves the cursor to the root node
|
||||
function! s:jumpToRoot()
|
||||
call b:NERDTreeRoot.putCursorHere(1, 0)
|
||||
call b:NERDTree.ui.centerView()
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:jumpToNextSibling(node) {{{1
|
||||
function! s:jumpToNextSibling(node)
|
||||
call s:jumpToSibling(a:node, 1)
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:jumpToPrevSibling(node) {{{1
|
||||
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
|
||||
"
|
||||
" 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)
|
||||
|
||||
if !empty(sibling)
|
||||
call sibling.putCursorHere(1, 0)
|
||||
call b:NERDTree.ui.centerView()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" FUNCTION: nerdtree#ui_glue#openBookmark(name) {{{1
|
||||
" put the cursor on the given bookmark and, if its a file, open it
|
||||
function! nerdtree#ui_glue#openBookmark(name)
|
||||
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)
|
||||
endtry
|
||||
if targetNode.path.isDirectory
|
||||
call targetNode.openExplorer()
|
||||
else
|
||||
call targetNode.open({'where': 'p'})
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:openHSplit(target) {{{1
|
||||
function! s:openHSplit(target)
|
||||
call a:target.activate({'where': 'h'})
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:openVSplit(target) {{{1
|
||||
function! s:openVSplit(target)
|
||||
call a:target.activate({'where': 'v'})
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:openExplorer(node) {{{1
|
||||
function! s:openExplorer(node)
|
||||
call a:node.openExplorer()
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:openInNewTab(target) {{{1
|
||||
function! s:openInNewTab(target)
|
||||
call a:target.activate({'where': 't'})
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:openInNewTabSilent(target) {{{1
|
||||
function! s:openInNewTabSilent(target)
|
||||
call a:target.activate({'where': 't', 'stay': 1})
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:openNodeRecursively(node) {{{1
|
||||
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")
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:previewNodeCurrent(node) {{{1
|
||||
function! s:previewNodeCurrent(node)
|
||||
call a:node.open({'stay': 1, 'where': 'p', 'keepopen': 1})
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:previewNodeHSplit(node) {{{1
|
||||
function! s:previewNodeHSplit(node)
|
||||
call a:node.open({'stay': 1, 'where': 'h', 'keepopen': 1})
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:previewNodeVSplit(node) {{{1
|
||||
function! s:previewNodeVSplit(node)
|
||||
call a:node.open({'stay': 1, 'where': 'v', 'keepopen': 1})
|
||||
endfunction
|
||||
|
||||
" FUNCTION: nerdtree#ui_glue#revealBookmark(name) {{{1
|
||||
" put the cursor on the node associate with the given name
|
||||
function! nerdtree#ui_glue#revealBookmark(name)
|
||||
try
|
||||
let targetNode = g:NERDTreeBookmark.GetNodeForName(a:name, 0)
|
||||
call targetNode.putCursorHere(0, 1)
|
||||
catch /^NERDTree.BookmarkNotFoundError/
|
||||
call nerdtree#echo("Bookmark isnt cached under the current root")
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:refreshRoot() {{{1
|
||||
" Reloads the current root. All nodes below this will be lost and the root dir
|
||||
" will be reloaded.
|
||||
function! s:refreshRoot()
|
||||
call nerdtree#echo("Refreshing the root node. This could take a while...")
|
||||
call b:NERDTreeRoot.refresh()
|
||||
call b:NERDTree.render()
|
||||
redraw
|
||||
call nerdtree#echo("Refreshing the root node. This could take a while... DONE")
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:refreshCurrent(node) {{{1
|
||||
" refreshes the root for the current node
|
||||
function! s:refreshCurrent(node)
|
||||
let node = a:node
|
||||
if !node.path.isDirectory
|
||||
let node = node.parent
|
||||
endif
|
||||
|
||||
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")
|
||||
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=0 -bar NERDTreeClose :call g:NERDTree.Close()
|
||||
command! -n=1 -complete=customlist,nerdtree#completeBookmarks -bar NERDTreeFromBookmark call g:NERDTreeCreator.CreatePrimary('<args>')
|
||||
command! -n=0 -bar NERDTreeMirror call g:NERDTreeCreator.CreateMirror()
|
||||
command! -n=0 -bar NERDTreeFind call s:findAndRevealPath()
|
||||
command! -n=0 -bar NERDTreeFocus call NERDTreeFocus()
|
||||
command! -n=0 -bar NERDTreeCWD call NERDTreeCWD()
|
||||
endfunction
|
||||
|
||||
" Function: s:SID() {{{1
|
||||
function s:SID()
|
||||
if !exists("s:sid")
|
||||
let s:sid = matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze_SID$')
|
||||
endif
|
||||
return s:sid
|
||||
endfun
|
||||
|
||||
" FUNCTION: s:showMenu(node) {{{1
|
||||
function! s:showMenu(node)
|
||||
let mc = g:NERDTreeMenuController.New(g:NERDTreeMenuItem.AllEnabled())
|
||||
call mc.showMenu()
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:toggleIgnoreFilter() {{{1
|
||||
function! s:toggleIgnoreFilter()
|
||||
call b:NERDTree.ui.toggleIgnoreFilter()
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:toggleShowBookmarks() {{{1
|
||||
function! s:toggleShowBookmarks()
|
||||
call b:NERDTree.ui.toggleShowBookmarks()
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:toggleShowFiles() {{{1
|
||||
function! s:toggleShowFiles()
|
||||
call b:NERDTree.ui.toggleShowFiles()
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:toggleShowHidden() {{{1
|
||||
" toggles the display of hidden files
|
||||
function! s:toggleShowHidden()
|
||||
call b:NERDTree.ui.toggleShowHidden()
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:toggleZoom() {{{1
|
||||
function! s:toggleZoom()
|
||||
call b:NERDTree.ui.toggleZoom()
|
||||
endfunction
|
||||
|
||||
"FUNCTION: nerdtree#ui_glue#upDir(keepState) {{{1
|
||||
"moves the tree up a 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
|
||||
|
||||
let oldRoot = b:NERDTreeRoot
|
||||
|
||||
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
|
||||
|
||||
if g:NERDTreeChDirMode ==# 2
|
||||
call b:NERDTreeRoot.path.changeToDir()
|
||||
endif
|
||||
|
||||
call b:NERDTree.render()
|
||||
call oldRoot.putCursorHere(0, 0)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:upDirCurrentRootOpen() {{{1
|
||||
function! s:upDirCurrentRootOpen()
|
||||
call nerdtree#ui_glue#upDir(1)
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:upDirCurrentRootClosed() {{{1
|
||||
function! s:upDirCurrentRootClosed()
|
||||
call nerdtree#ui_glue#upDir(0)
|
||||
endfunction
|
||||
|
||||
" vim: set sw=4 sts=4 et fdm=marker:
|
||||
1077
doc/NERD_tree.txt
1077
doc/NERD_tree.txt
File diff suppressed because it is too large
Load Diff
320
lib/nerdtree/bookmark.vim
Normal file
320
lib/nerdtree/bookmark.vim
Normal file
@@ -0,0 +1,320 @@
|
||||
"CLASS: Bookmark
|
||||
"============================================================
|
||||
let s:Bookmark = {}
|
||||
let g:NERDTreeBookmark = s:Bookmark
|
||||
|
||||
" FUNCTION: Bookmark.activate() {{{1
|
||||
function! s:Bookmark.activate(...)
|
||||
call self.open(a:0 ? a:1 : {})
|
||||
endfunction
|
||||
|
||||
" FUNCTION: Bookmark.AddBookmark(name, path) {{{1
|
||||
" Class method to add a new bookmark to the list, if a previous bookmark exists
|
||||
" with the same name, just update the path for that bookmark
|
||||
function! s:Bookmark.AddBookmark(name, path)
|
||||
for i in s:Bookmark.Bookmarks()
|
||||
if i.name ==# a:name
|
||||
let i.path = a:path
|
||||
return
|
||||
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
|
||||
" Class method to get all bookmarks. Lazily initializes the bookmarks global
|
||||
" variable
|
||||
function! s:Bookmark.Bookmarks()
|
||||
if !exists("g:NERDTreeBookmarks")
|
||||
let g:NERDTreeBookmarks = []
|
||||
endif
|
||||
return g:NERDTreeBookmarks
|
||||
endfunction
|
||||
|
||||
" 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)
|
||||
try
|
||||
call s:Bookmark.BookmarkFor(a:name)
|
||||
return 1
|
||||
catch /^NERDTree.BookmarkNotFoundError/
|
||||
return 0
|
||||
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! s:Bookmark.BookmarkFor(name)
|
||||
for i in s:Bookmark.Bookmarks()
|
||||
if i.name ==# a:name
|
||||
return i
|
||||
endif
|
||||
endfor
|
||||
throw "NERDTree.BookmarkNotFoundError: no bookmark found for name: \"". a:name .'"'
|
||||
endfunction
|
||||
|
||||
" FUNCTION: Bookmark.BookmarkNames() {{{1
|
||||
" Class method to return an array of all bookmark names
|
||||
function! s:Bookmark.BookmarkNames()
|
||||
let names = []
|
||||
for i in s:Bookmark.Bookmarks()
|
||||
call add(names, i.name)
|
||||
endfor
|
||||
return names
|
||||
endfunction
|
||||
|
||||
" FUNCTION: Bookmark.CacheBookmarks(silent) {{{1
|
||||
" Class method to read all bookmarks from the bookmarks file initialize
|
||||
" bookmark objects for each one.
|
||||
"
|
||||
" Args:
|
||||
" silent - dont echo an error msg if invalid bookmarks are found
|
||||
function! s:Bookmark.CacheBookmarks(silent)
|
||||
if filereadable(g:NERDTreeBookmarksFile)
|
||||
let g:NERDTreeBookmarks = []
|
||||
let g:NERDTreeInvalidBookmarks = []
|
||||
let bookmarkStrings = readfile(g:NERDTreeBookmarksFile)
|
||||
let invalidBookmarksFound = 0
|
||||
for i in bookmarkStrings
|
||||
|
||||
"ignore blank lines
|
||||
if i != ''
|
||||
|
||||
let name = substitute(i, '^\(.\{-}\) .*$', '\1', '')
|
||||
let path = substitute(i, '^.\{-} \(.*\)$', '\1', '')
|
||||
let path = fnamemodify(path, ':p')
|
||||
|
||||
try
|
||||
let bookmark = s:Bookmark.New(name, g:NERDTreePath.New(path))
|
||||
call add(g:NERDTreeBookmarks, bookmark)
|
||||
catch /^NERDTree.InvalidArgumentsError/
|
||||
call add(g:NERDTreeInvalidBookmarks, i)
|
||||
let invalidBookmarksFound += 1
|
||||
endtry
|
||||
endif
|
||||
endfor
|
||||
if invalidBookmarksFound
|
||||
call s:Bookmark.Write()
|
||||
if !a: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
|
||||
endfunction
|
||||
" FUNCTION: Bookmark.ClearAll() {{{1
|
||||
" Class method to delete all bookmarks.
|
||||
function! s:Bookmark.ClearAll()
|
||||
for i in s:Bookmark.Bookmarks()
|
||||
call i.delete()
|
||||
endfor
|
||||
call s:Bookmark.Write()
|
||||
endfunction
|
||||
|
||||
" FUNCTION: Bookmark.delete() {{{1
|
||||
" 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
|
||||
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)
|
||||
endfunction
|
||||
|
||||
" FUNCTION: Bookmark.GetSelected() {{{1
|
||||
" returns the Bookmark the cursor is over, or {}
|
||||
function! s:Bookmark.GetSelected()
|
||||
let line = getline(".")
|
||||
let name = substitute(line, '^>\(.\{-}\) .\+$', '\1', '')
|
||||
if name != line
|
||||
try
|
||||
return s:Bookmark.BookmarkFor(name)
|
||||
catch /^NERDTree.BookmarkNotFoundError/
|
||||
return {}
|
||||
endtry
|
||||
endif
|
||||
return {}
|
||||
endfunction
|
||||
|
||||
" FUNCTION: Bookmark.InvalidBookmarks() {{{1
|
||||
" Class method to get all invalid bookmark strings read from the bookmarks
|
||||
" file
|
||||
function! s:Bookmark.InvalidBookmarks()
|
||||
if !exists("g:NERDTreeInvalidBookmarks")
|
||||
let g:NERDTreeInvalidBookmarks = []
|
||||
endif
|
||||
return g:NERDTreeInvalidBookmarks
|
||||
endfunction
|
||||
|
||||
" FUNCTION: Bookmark.mustExist() {{{1
|
||||
function! s:Bookmark.mustExist()
|
||||
if !self.path.exists()
|
||||
call s:Bookmark.CacheBookmarks(1)
|
||||
throw "NERDTree.BookmarkPointsToInvalidLocationError: the bookmark \"".
|
||||
\ self.name ."\" points to a non existing location: \"". self.path.str()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" FUNCTION: Bookmark.New(name, path) {{{1
|
||||
" Create a new bookmark object with the given name and path object
|
||||
function! s:Bookmark.New(name, path)
|
||||
if a:name =~# ' '
|
||||
throw "NERDTree.IllegalBookmarkNameError: illegal name:" . a:name
|
||||
endif
|
||||
|
||||
let newBookmark = copy(self)
|
||||
let newBookmark.name = a:name
|
||||
let newBookmark.path = a:path
|
||||
return newBookmark
|
||||
endfunction
|
||||
|
||||
" FUNCTION: Bookmark.open([options]) {{{1
|
||||
"Args:
|
||||
"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'
|
||||
" (horizontal split), 't' (new tab) or 'p' (previous window).
|
||||
" 'reuse': if a window is displaying the file then jump the cursor there
|
||||
" 'keepopen': dont close the tree window
|
||||
" 'stay': open the file, but keep the cursor in the tree win
|
||||
"
|
||||
function! s:Bookmark.open(...)
|
||||
let opts = a:0 ? a:1 : {}
|
||||
|
||||
if self.path.isDirectory && !has_key(opts, 'where')
|
||||
call self.toRoot()
|
||||
else
|
||||
let opener = g:NERDTreeOpener.New(self.path, opts)
|
||||
call opener.open(self)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" FUNCTION: Bookmark.openInNewTab(options) {{{1
|
||||
" Create a new bookmark object with the given name and path object
|
||||
function! s:Bookmark.openInNewTab(options)
|
||||
call nerdtree#deprecated('Bookmark.openInNewTab', 'is deprecated, use open() instead')
|
||||
call self.open(a:options)
|
||||
endfunction
|
||||
|
||||
" 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)
|
||||
endfunction
|
||||
|
||||
" FUNCTION: Bookmark.str() {{{1
|
||||
" Get the string that should be rendered in the view for this bookmark
|
||||
function! s:Bookmark.str()
|
||||
let pathStrMaxLen = winwidth(g:NERDTree.GetWinNum()) - 4 - len(self.name)
|
||||
if &nu
|
||||
let pathStrMaxLen = pathStrMaxLen - &numberwidth
|
||||
endif
|
||||
|
||||
let pathStr = self.path.str({'format': 'UI'})
|
||||
if len(pathStr) > pathStrMaxLen
|
||||
let pathStr = '<' . strpart(pathStr, len(pathStr) - pathStrMaxLen)
|
||||
endif
|
||||
return '>' . self.name . ' ' . pathStr
|
||||
endfunction
|
||||
|
||||
" FUNCTION: Bookmark.toRoot() {{{1
|
||||
" Make the node for this bookmark the new tree root
|
||||
function! s:Bookmark.toRoot()
|
||||
if self.validate()
|
||||
try
|
||||
let targetNode = self.getNode(1)
|
||||
catch /^NERDTree.BookmarkedNodeNotFoundError/
|
||||
let targetNode = g:NERDTreeFileNode.New(s:Bookmark.BookmarkFor(self.name).path)
|
||||
endtry
|
||||
call targetNode.makeRoot()
|
||||
call b:NERDTree.render()
|
||||
call targetNode.putCursorHere(0, 0)
|
||||
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()
|
||||
endfunction
|
||||
|
||||
" FUNCTION: Bookmark.validate() {{{1
|
||||
function! s:Bookmark.validate()
|
||||
if self.path.exists()
|
||||
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
|
||||
" Class method to write all bookmarks to the bookmarks file
|
||||
function! s:Bookmark.Write()
|
||||
let bookmarkStrings = []
|
||||
for i in s:Bookmark.Bookmarks()
|
||||
call add(bookmarkStrings, i.name . ' ' . fnamemodify(i.path.str(), ':~'))
|
||||
endfor
|
||||
|
||||
"add a blank line before the invalid ones
|
||||
call add(bookmarkStrings, "")
|
||||
|
||||
for j in s:Bookmark.InvalidBookmarks()
|
||||
call add(bookmarkStrings, j)
|
||||
endfor
|
||||
call writefile(bookmarkStrings, g:NERDTreeBookmarksFile)
|
||||
endfunction
|
||||
|
||||
" vim: set sw=4 sts=4 et fdm=marker:
|
||||
366
lib/nerdtree/creator.vim
Normal file
366
lib/nerdtree/creator.vim
Normal file
@@ -0,0 +1,366 @@
|
||||
"CLASS: Creator
|
||||
"Creates primary/secondary/mirror nerdtree windows. Sets up all 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()
|
||||
"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=* ClearBookmarks call nerdtree#ui_glue#clearBookmarks('<args>')
|
||||
command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=+ BookmarkToRoot call g:NERDTreeBookmark.ToRoot('<args>')
|
||||
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()
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:Creator._broadcastInitEvent() {{{1
|
||||
function! s:Creator._broadcastInitEvent()
|
||||
silent doautocmd User NERDTreeInit
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:Creator.BufNamePrefix() {{{2
|
||||
function! s:Creator.BufNamePrefix()
|
||||
return 'NERD_tree_'
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:Creator.CreatePrimary(a:name) {{{1
|
||||
function! s:Creator.CreatePrimary(name)
|
||||
let creator = s:Creator.New()
|
||||
call creator.createPrimary(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)
|
||||
return
|
||||
endif
|
||||
|
||||
if path == {}
|
||||
return
|
||||
endif
|
||||
|
||||
"if instructed to, then change the vim CWD to the dir the NERDTree is
|
||||
"inited in
|
||||
if g:NERDTreeChDirMode != 0
|
||||
call path.changeToDir()
|
||||
endif
|
||||
|
||||
if g:NERDTree.ExistsForTab()
|
||||
if g:NERDTree.IsOpen()
|
||||
call g:NERDTree.Close()
|
||||
endif
|
||||
unlet t:NERDTreeBufName
|
||||
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 b:NERDTree.render()
|
||||
call b:NERDTreeRoot.putCursorHere(0, 0)
|
||||
|
||||
call self._broadcastInitEvent()
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:Creator.CreateSecondary(dir) {{{1
|
||||
function! s:Creator.CreateSecondary(dir)
|
||||
let creator = s:Creator.New()
|
||||
call creator.createSecondary(a:dir)
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:Creator.createSecondary(dir) {{{1
|
||||
function! s:Creator.createSecondary(dir)
|
||||
try
|
||||
let path = g:NERDTreePath.New(a:dir)
|
||||
catch /^NERDTree.InvalidArgumentsError/
|
||||
call nerdtree#echo("Invalid directory name:" . a:name)
|
||||
return
|
||||
endtry
|
||||
|
||||
"we want the directory buffer to disappear when we do the :edit below
|
||||
setlocal bufhidden=wipe
|
||||
|
||||
let previousBuf = expand("#")
|
||||
|
||||
"we need a unique name for each secondary tree buffer to ensure they are
|
||||
"all independent
|
||||
exec "silent edit " . self._nextBufferName()
|
||||
|
||||
let b:NERDTreePreviousBuf = bufnr(previousBuf)
|
||||
call self._createNERDTree(path)
|
||||
call self._setCommonBufOptions()
|
||||
let b:NERDTreeType = "secondary"
|
||||
|
||||
call b:NERDTree.render()
|
||||
|
||||
call self._broadcastInitEvent()
|
||||
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
|
||||
let b:NERDTreeRoot = b:NERDTree.root
|
||||
|
||||
call b:NERDTree.root.open()
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:Creator.CreateMirror() {{{1
|
||||
function! s:Creator.CreateMirror()
|
||||
let creator = s:Creator.New()
|
||||
call creator.createMirror()
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:Creator.createMirror() {{{1
|
||||
function! s:Creator.createMirror()
|
||||
"get the names off all the nerd tree buffers
|
||||
let treeBufNames = []
|
||||
for i in range(1, tabpagenr("$"))
|
||||
let nextName = self._tabpagevar(i, 'NERDTreeBufName')
|
||||
if nextName != -1 && (!exists("t:NERDTreeBufName") || nextName != t:NERDTreeBufName)
|
||||
call add(treeBufNames, nextName)
|
||||
endif
|
||||
endfor
|
||||
let treeBufNames = self._uniq(treeBufNames)
|
||||
|
||||
"map the option names (that the user will be prompted with) to the nerd
|
||||
"tree buffer names
|
||||
let options = {}
|
||||
let i = 0
|
||||
while i < len(treeBufNames)
|
||||
let bufName = treeBufNames[i]
|
||||
let treeRoot = getbufvar(bufName, "NERDTreeRoot")
|
||||
let options[i+1 . '. ' . treeRoot.path.str() . ' (buf name: ' . bufName . ')'] = bufName
|
||||
let i = i + 1
|
||||
endwhile
|
||||
|
||||
"work out which tree to mirror, if there is more than 1 then ask the user
|
||||
let bufferName = ''
|
||||
if len(keys(options)) > 1
|
||||
let choices = ["Choose a tree to mirror"]
|
||||
let choices = extend(choices, sort(keys(options)))
|
||||
let choice = inputlist(choices)
|
||||
if choice < 1 || choice > len(options) || choice ==# ''
|
||||
return
|
||||
endif
|
||||
|
||||
let bufferName = options[sort(keys(options))[choice-1]]
|
||||
elseif len(keys(options)) ==# 1
|
||||
let bufferName = values(options)[0]
|
||||
else
|
||||
call nerdtree#echo("No trees to mirror")
|
||||
return
|
||||
endif
|
||||
|
||||
if g:NERDTree.ExistsForTab() && g:NERDTree.IsOpen()
|
||||
call g:NERDTree.Close()
|
||||
endif
|
||||
|
||||
let t:NERDTreeBufName = bufferName
|
||||
call self._createTreeWin()
|
||||
exec 'buffer ' . bufferName
|
||||
if !&hidden
|
||||
call b:NERDTree.render()
|
||||
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()
|
||||
"create the nerd tree window
|
||||
let splitLocation = g:NERDTreeWinPos ==# "left" ? "topleft " : "botright "
|
||||
let splitSize = g:NERDTreeWinSize
|
||||
|
||||
if !exists('t:NERDTreeBufName')
|
||||
let t:NERDTreeBufName = self._nextBufferName()
|
||||
silent! exec splitLocation . 'vertical ' . splitSize . ' new'
|
||||
silent! exec "edit " . t:NERDTreeBufName
|
||||
else
|
||||
silent! exec splitLocation . 'vertical ' . splitSize . ' split'
|
||||
silent! exec "buffer " . t:NERDTreeBufName
|
||||
endif
|
||||
|
||||
setlocal winfixwidth
|
||||
call self._setCommonBufOptions()
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:Creator.New() {{{1
|
||||
function! s:Creator.New()
|
||||
let newCreator = copy(self)
|
||||
return newCreator
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:Creator._nextBufferName() {{{2
|
||||
" 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
|
||||
" 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")
|
||||
let s:Creator._NextBufNum = 1
|
||||
else
|
||||
let s:Creator._NextBufNum += 1
|
||||
endif
|
||||
|
||||
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)
|
||||
let path = {}
|
||||
if g:NERDTreeBookmark.BookmarkExistsFor(a:str)
|
||||
let path = g:NERDTreeBookmark.BookmarkFor(a:str).path
|
||||
else
|
||||
let dir = a:str ==# '' ? getcwd() : a:str
|
||||
|
||||
"hack to get an absolute path if a relative path is given
|
||||
if dir =~# '^\.'
|
||||
let dir = getcwd() . g:NERDTreePath.Slash() . dir
|
||||
endif
|
||||
let dir = g:NERDTreePath.Resolve(dir)
|
||||
|
||||
try
|
||||
let path = g:NERDTreePath.New(dir)
|
||||
catch /^NERDTree.InvalidArgumentsError/
|
||||
call nerdtree#echo("No bookmark or directory found for: " . a:str)
|
||||
return {}
|
||||
endtry
|
||||
endif
|
||||
if !path.isDirectory
|
||||
let path = path.getParent()
|
||||
endif
|
||||
|
||||
return path
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:Creator._setCommonBufOptions() {{{1
|
||||
function! s:Creator._setCommonBufOptions()
|
||||
"throwaway buffer options
|
||||
setlocal noswapfile
|
||||
setlocal buftype=nofile
|
||||
setlocal bufhidden=hide
|
||||
setlocal nowrap
|
||||
setlocal foldcolumn=0
|
||||
setlocal foldmethod=manual
|
||||
setlocal nofoldenable
|
||||
setlocal nobuflisted
|
||||
setlocal nospell
|
||||
if g:NERDTreeShowLineNumbers
|
||||
setlocal nu
|
||||
else
|
||||
setlocal nonu
|
||||
if v:version >= 703
|
||||
setlocal nornu
|
||||
endif
|
||||
endif
|
||||
|
||||
iabc <buffer>
|
||||
|
||||
if g:NERDTreeHighlightCursorline
|
||||
setlocal cursorline
|
||||
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()
|
||||
if g:NERDTreeStatusline != -1
|
||||
let &l:statusline = g:NERDTreeStatusline
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:Creator._tabpagevar(tabnr, var) {{{1
|
||||
function! s:Creator._tabpagevar(tabnr, var)
|
||||
let currentTab = tabpagenr()
|
||||
let old_ei = &ei
|
||||
set ei=all
|
||||
|
||||
exec "tabnext " . a:tabnr
|
||||
let v = -1
|
||||
if exists('t:' . a:var)
|
||||
exec 'let v = t:' . a:var
|
||||
endif
|
||||
exec "tabnext " . currentTab
|
||||
|
||||
let &ei = old_ei
|
||||
|
||||
return v
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:Creator.TogglePrimary(dir) {{{1
|
||||
function! s:Creator.TogglePrimary(dir)
|
||||
let creator = s:Creator.New()
|
||||
call creator.togglePrimary(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)
|
||||
"
|
||||
"Args:
|
||||
"dir: the full path for the root node (is only used if the NERD tree is being
|
||||
"initialized.
|
||||
function! s:Creator.togglePrimary(dir)
|
||||
if g:NERDTree.ExistsForTab()
|
||||
if !g:NERDTree.IsOpen()
|
||||
call self._createTreeWin()
|
||||
if !&hidden
|
||||
call b:NERDTree.render()
|
||||
endif
|
||||
call b:NERDTree.ui.restoreScreenState()
|
||||
else
|
||||
call g:NERDTree.Close()
|
||||
endif
|
||||
else
|
||||
call self.createPrimary(a:dir)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" Function: s:Creator._uniq(list) {{{1
|
||||
" returns a:list without duplicates
|
||||
function! s:Creator._uniq(list)
|
||||
let uniqlist = []
|
||||
for elem in a:list
|
||||
if index(uniqlist, elem) ==# -1
|
||||
let uniqlist += [elem]
|
||||
endif
|
||||
endfor
|
||||
return uniqlist
|
||||
endfunction
|
||||
|
||||
" vim: set sw=4 sts=4 et fdm=marker:
|
||||
13
lib/nerdtree/event.vim
Normal file
13
lib/nerdtree/event.vim
Normal file
@@ -0,0 +1,13 @@
|
||||
"CLASS: Event
|
||||
"============================================================
|
||||
let s:Event = {}
|
||||
let g:NERDTreeEvent = s:Event
|
||||
|
||||
function! s:Event.New(nerdtree, subject, action, params) abort
|
||||
let newObj = copy(self)
|
||||
let newObj.nerdtree = a:nerdtree
|
||||
let newObj.subject = a:subject
|
||||
let newObj.action = a:action
|
||||
let newObj.params = a:params
|
||||
return newObj
|
||||
endfunction
|
||||
56
lib/nerdtree/flag_set.vim
Normal file
56
lib/nerdtree/flag_set.vim
Normal file
@@ -0,0 +1,56 @@
|
||||
"CLASS: FlagSet
|
||||
"============================================================
|
||||
let s:FlagSet = {}
|
||||
let g:NERDTreeFlagSet = s:FlagSet
|
||||
|
||||
"FUNCTION: FlagSet.addFlag(scope, flag) {{{1
|
||||
function! s:FlagSet.addFlag(scope, flag)
|
||||
let flags = self._flagsForScope(a:scope)
|
||||
if index(flags, a:flag) == -1
|
||||
call add(flags, a:flag)
|
||||
end
|
||||
endfunction
|
||||
|
||||
"FUNCTION: FlagSet.clearFlags(scope) {{{1
|
||||
function! s:FlagSet.clearFlags(scope)
|
||||
let self._flags[a:scope] = []
|
||||
endfunction
|
||||
|
||||
"FUNCTION: FlagSet._flagsForScope(scope) {{{1
|
||||
function! s:FlagSet._flagsForScope(scope)
|
||||
if !has_key(self._flags, a:scope)
|
||||
let self._flags[a:scope] = []
|
||||
endif
|
||||
return self._flags[a:scope]
|
||||
endfunction
|
||||
|
||||
"FUNCTION: FlagSet.New() {{{1
|
||||
function! s:FlagSet.New()
|
||||
let newObj = copy(self)
|
||||
let newObj._flags = {}
|
||||
return newObj
|
||||
endfunction
|
||||
|
||||
"FUNCTION: FlagSet.removeFlag(scope, flag) {{{1
|
||||
function! s:FlagSet.removeFlag(scope, flag)
|
||||
let flags = self._flagsForScope(a:scope)
|
||||
|
||||
let i = index(flags, a:flag)
|
||||
if i >= 0
|
||||
call remove(flags, i)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: FlagSet.renderToString() {{{1
|
||||
function! s:FlagSet.renderToString()
|
||||
let flagstring = ""
|
||||
for i in values(self._flags)
|
||||
let flagstring .= join(i)
|
||||
endfor
|
||||
|
||||
if len(flagstring) == 0
|
||||
return ""
|
||||
endif
|
||||
|
||||
return '[' . flagstring . ']'
|
||||
endfunction
|
||||
159
lib/nerdtree/key_map.vim
Normal file
159
lib/nerdtree/key_map.vim
Normal file
@@ -0,0 +1,159 @@
|
||||
"CLASS: KeyMap
|
||||
"============================================================
|
||||
let s:KeyMap = {}
|
||||
let g:NERDTreeKeyMap = s:KeyMap
|
||||
|
||||
"FUNCTION: KeyMap.All() {{{1
|
||||
function! s:KeyMap.All()
|
||||
if !exists("s:keyMaps")
|
||||
let s:keyMaps = []
|
||||
endif
|
||||
return s:keyMaps
|
||||
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 {}
|
||||
endfunction
|
||||
|
||||
"FUNCTION: KeyMap.BindAll() {{{1
|
||||
function! s:KeyMap.BindAll()
|
||||
for i in s:KeyMap.All()
|
||||
call i.bind()
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
"FUNCTION: KeyMap.bind() {{{1
|
||||
function! s:KeyMap.bind()
|
||||
" If the key sequence we're trying to map contains any '<>' notation, we
|
||||
" must replace each of the '<' characters with '<lt>' to ensure the string
|
||||
" is not translated into its corresponding keycode during the later part
|
||||
" of the map command below
|
||||
" :he <>
|
||||
let specialNotationRegex = '\m<\([[:alnum:]_-]\+>\)'
|
||||
if self.key =~# specialNotationRegex
|
||||
let keymapInvokeString = substitute(self.key, specialNotationRegex, '<lt>\1', 'g')
|
||||
else
|
||||
let keymapInvokeString = self.key
|
||||
endif
|
||||
|
||||
let premap = self.key == "<LeftRelease>" ? " <LeftRelease>" : " "
|
||||
|
||||
exec 'nnoremap <buffer> <silent> '. self.key . premap . ':call nerdtree#ui_glue#invokeKeyMap("'. keymapInvokeString .'")<cr>'
|
||||
endfunction
|
||||
|
||||
"FUNCTION: KeyMap.Remove(key, scope) {{{1
|
||||
function! s:KeyMap.Remove(key, scope)
|
||||
let maps = s:KeyMap.All()
|
||||
for i in range(len(maps))
|
||||
if maps[i].key ==# a:key && maps[i].scope ==# a:scope
|
||||
return remove(maps, i)
|
||||
endif
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
"FUNCTION: KeyMap.invoke() {{{1
|
||||
"Call the KeyMaps callback function
|
||||
function! s:KeyMap.invoke(...)
|
||||
let Callback = function(self.callback)
|
||||
if a:0
|
||||
call Callback(a:1)
|
||||
else
|
||||
call Callback()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: KeyMap.Invoke() {{{1
|
||||
"Find a keymapping for a:key and the current scope invoke it.
|
||||
"
|
||||
"Scope is determined as follows:
|
||||
" * if the cursor is on a dir node then "DirNode"
|
||||
" * if the cursor is on a file node then "FileNode"
|
||||
" * if the cursor is on a bookmark then "Bookmark"
|
||||
"
|
||||
"If a keymap has the scope of "all" then it will be called if no other keymap
|
||||
"is found for a:key and the scope.
|
||||
function! s:KeyMap.Invoke(key)
|
||||
|
||||
"required because clicking the command window below another window still
|
||||
"invokes the <LeftRelease> mapping - but changes the window cursor
|
||||
"is in first
|
||||
"
|
||||
"TODO: remove this check when the vim bug is fixed
|
||||
if !g:NERDTree.ExistsForBuf()
|
||||
return {}
|
||||
endif
|
||||
|
||||
let node = g:NERDTreeFileNode.GetSelected()
|
||||
if !empty(node)
|
||||
|
||||
"try file node
|
||||
if !node.path.isDirectory
|
||||
let km = s:KeyMap.FindFor(a:key, "FileNode")
|
||||
if !empty(km)
|
||||
return km.invoke(node)
|
||||
endif
|
||||
endif
|
||||
|
||||
"try dir node
|
||||
if node.path.isDirectory
|
||||
let km = s:KeyMap.FindFor(a:key, "DirNode")
|
||||
if !empty(km)
|
||||
return km.invoke(node)
|
||||
endif
|
||||
endif
|
||||
|
||||
"try generic node
|
||||
let km = s:KeyMap.FindFor(a:key, "Node")
|
||||
if !empty(km)
|
||||
return km.invoke(node)
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
"try bookmark
|
||||
let bm = g:NERDTreeBookmark.GetSelected()
|
||||
if !empty(bm)
|
||||
let km = s:KeyMap.FindFor(a:key, "Bookmark")
|
||||
if !empty(km)
|
||||
return km.invoke(bm)
|
||||
endif
|
||||
endif
|
||||
|
||||
"try all
|
||||
let km = s:KeyMap.FindFor(a:key, "all")
|
||||
if !empty(km)
|
||||
return km.invoke()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: KeyMap.Create(options) {{{1
|
||||
function! s:KeyMap.Create(options)
|
||||
let opts = extend({'scope': 'all', 'quickhelpText': ''}, copy(a:options))
|
||||
|
||||
"dont override other mappings unless the 'override' option is given
|
||||
if get(opts, 'override', 0) == 0 && !empty(s:KeyMap.FindFor(opts['key'], opts['scope']))
|
||||
return
|
||||
end
|
||||
|
||||
let newKeyMap = copy(self)
|
||||
let newKeyMap.key = opts['key']
|
||||
let newKeyMap.quickhelpText = opts['quickhelpText']
|
||||
let newKeyMap.callback = opts['callback']
|
||||
let newKeyMap.scope = opts['scope']
|
||||
|
||||
call s:KeyMap.Add(newKeyMap)
|
||||
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)
|
||||
endfunction
|
||||
|
||||
" vim: set sw=4 sts=4 et fdm=marker:
|
||||
180
lib/nerdtree/menu_controller.vim
Normal file
180
lib/nerdtree/menu_controller.vim
Normal file
@@ -0,0 +1,180 @@
|
||||
"CLASS: MenuController
|
||||
"============================================================
|
||||
let s:MenuController = {}
|
||||
let g:NERDTreeMenuController = s:MenuController
|
||||
|
||||
"FUNCTION: MenuController.New(menuItems) {{{1
|
||||
"create a new menu controller that operates on the given menu items
|
||||
function! s:MenuController.New(menuItems)
|
||||
let newMenuController = copy(self)
|
||||
if a:menuItems[0].isSeparator()
|
||||
let newMenuController.menuItems = a:menuItems[1:-1]
|
||||
else
|
||||
let newMenuController.menuItems = a:menuItems
|
||||
endif
|
||||
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.showMenu()
|
||||
call self._saveOptions()
|
||||
|
||||
try
|
||||
let self.selection = 0
|
||||
|
||||
let done = 0
|
||||
while !done
|
||||
redraw!
|
||||
call self._echoPrompt()
|
||||
let key = nr2char(getchar())
|
||||
let done = self._handleKeypress(key)
|
||||
endwhile
|
||||
finally
|
||||
call self._restoreOptions()
|
||||
endtry
|
||||
|
||||
if self.selection != -1
|
||||
let m = self._current()
|
||||
call m.execute()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: MenuController._echoPrompt() {{{1
|
||||
function! s:MenuController._echoPrompt()
|
||||
echo "NERDTree Menu. Use j/k/enter and 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
|
||||
endfunction
|
||||
|
||||
"FUNCTION: MenuController._current(key) {{{1
|
||||
"get the MenuItem that is currently selected
|
||||
function! s:MenuController._current()
|
||||
return self.menuItems[self.selection]
|
||||
endfunction
|
||||
|
||||
"FUNCTION: MenuController._handleKeypress(key) {{{1
|
||||
"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'
|
||||
call self._cursorDown()
|
||||
elseif a:key == 'k'
|
||||
call self._cursorUp()
|
||||
elseif a:key == nr2char(27) "escape
|
||||
let self.selection = -1
|
||||
return 1
|
||||
elseif a:key == "\r" || a:key == "\n" "enter and ctrl-j
|
||||
return 1
|
||||
else
|
||||
let index = self._nextIndexFor(a:key)
|
||||
if index != -1
|
||||
let self.selection = index
|
||||
if len(self._allIndexesFor(a:key)) == 1
|
||||
return 1
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
"FUNCTION: MenuController._allIndexesFor(shortcut) {{{1
|
||||
"get indexes to all menu items with the given shortcut
|
||||
function! s:MenuController._allIndexesFor(shortcut)
|
||||
let toReturn = []
|
||||
|
||||
for i in range(0, len(self.menuItems)-1)
|
||||
if self.menuItems[i].shortcut == a:shortcut
|
||||
call add(toReturn, i)
|
||||
endif
|
||||
endfor
|
||||
|
||||
return toReturn
|
||||
endfunction
|
||||
|
||||
"FUNCTION: MenuController._nextIndexFor(shortcut) {{{1
|
||||
"get the index to the next menu item with the given shortcut, starts from the
|
||||
"current cursor location and wraps around to the top again if need be
|
||||
function! s:MenuController._nextIndexFor(shortcut)
|
||||
for i in range(self.selection+1, len(self.menuItems)-1)
|
||||
if self.menuItems[i].shortcut == a:shortcut
|
||||
return i
|
||||
endif
|
||||
endfor
|
||||
|
||||
for i in range(0, self.selection)
|
||||
if self.menuItems[i].shortcut == a:shortcut
|
||||
return i
|
||||
endif
|
||||
endfor
|
||||
|
||||
return -1
|
||||
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
|
||||
endfunction
|
||||
|
||||
"FUNCTION: MenuController._saveOptions() {{{1
|
||||
"set any vim options that are required to make the menu work (saving their old
|
||||
"values)
|
||||
function! s:MenuController._saveOptions()
|
||||
let self._oldLazyredraw = &lazyredraw
|
||||
let self._oldCmdheight = &cmdheight
|
||||
set nolazyredraw
|
||||
call self._setCmdheight()
|
||||
endfunction
|
||||
|
||||
"FUNCTION: MenuController._restoreOptions() {{{1
|
||||
"restore the options we saved in _saveOptions()
|
||||
function! s:MenuController._restoreOptions()
|
||||
let &cmdheight = self._oldCmdheight
|
||||
let &lazyredraw = self._oldLazyredraw
|
||||
endfunction
|
||||
|
||||
"FUNCTION: MenuController._cursorDown() {{{1
|
||||
"move the cursor to the next menu item, skipping separators
|
||||
function! s:MenuController._cursorDown()
|
||||
let done = 0
|
||||
while !done
|
||||
if self.selection < len(self.menuItems)-1
|
||||
let self.selection += 1
|
||||
else
|
||||
let self.selection = 0
|
||||
endif
|
||||
|
||||
if !self._current().isSeparator()
|
||||
let done = 1
|
||||
endif
|
||||
endwhile
|
||||
endfunction
|
||||
|
||||
"FUNCTION: MenuController._cursorUp() {{{1
|
||||
"move the cursor to the previous menu item, skipping separators
|
||||
function! s:MenuController._cursorUp()
|
||||
let done = 0
|
||||
while !done
|
||||
if self.selection > 0
|
||||
let self.selection -= 1
|
||||
else
|
||||
let self.selection = len(self.menuItems)-1
|
||||
endif
|
||||
|
||||
if !self._current().isSeparator()
|
||||
let done = 1
|
||||
endif
|
||||
endwhile
|
||||
endfunction
|
||||
|
||||
" vim: set sw=4 sts=4 et fdm=marker:
|
||||
114
lib/nerdtree/menu_item.vim
Normal file
114
lib/nerdtree/menu_item.vim
Normal file
@@ -0,0 +1,114 @@
|
||||
"CLASS: MenuItem
|
||||
"============================================================
|
||||
let s:MenuItem = {}
|
||||
let g:NERDTreeMenuItem = s:MenuItem
|
||||
|
||||
"FUNCTION: MenuItem.All() {{{1
|
||||
"get all top level menu items
|
||||
function! s:MenuItem.All()
|
||||
if !exists("s:menuItems")
|
||||
let s:menuItems = []
|
||||
endif
|
||||
return s:menuItems
|
||||
endfunction
|
||||
|
||||
"FUNCTION: MenuItem.AllEnabled() {{{1
|
||||
"get all top level menu items that are currently enabled
|
||||
function! s:MenuItem.AllEnabled()
|
||||
let toReturn = []
|
||||
for i in s:MenuItem.All()
|
||||
if i.enabled()
|
||||
call add(toReturn, i)
|
||||
endif
|
||||
endfor
|
||||
return toReturn
|
||||
endfunction
|
||||
|
||||
"FUNCTION: MenuItem.Create(options) {{{1
|
||||
"make a new menu item and add it to the global list
|
||||
function! s:MenuItem.Create(options)
|
||||
let newMenuItem = copy(self)
|
||||
|
||||
let newMenuItem.text = a:options['text']
|
||||
let newMenuItem.shortcut = a:options['shortcut']
|
||||
let newMenuItem.children = []
|
||||
|
||||
let newMenuItem.isActiveCallback = -1
|
||||
if has_key(a:options, 'isActiveCallback')
|
||||
let newMenuItem.isActiveCallback = a:options['isActiveCallback']
|
||||
endif
|
||||
|
||||
let newMenuItem.callback = -1
|
||||
if has_key(a:options, 'callback')
|
||||
let newMenuItem.callback = a:options['callback']
|
||||
endif
|
||||
|
||||
if has_key(a:options, 'parent')
|
||||
call add(a:options['parent'].children, newMenuItem)
|
||||
else
|
||||
call add(s:MenuItem.All(), newMenuItem)
|
||||
endif
|
||||
|
||||
return newMenuItem
|
||||
endfunction
|
||||
|
||||
"FUNCTION: MenuItem.CreateSeparator(options) {{{1
|
||||
"make a new separator menu item and add it to the global list
|
||||
function! s:MenuItem.CreateSeparator(options)
|
||||
let standard_options = { 'text': '--------------------',
|
||||
\ 'shortcut': -1,
|
||||
\ 'callback': -1 }
|
||||
let options = extend(a:options, standard_options, "force")
|
||||
|
||||
return s:MenuItem.Create(options)
|
||||
endfunction
|
||||
|
||||
"FUNCTION: MenuItem.CreateSubmenu(options) {{{1
|
||||
"make a new submenu and add it to global list
|
||||
function! s:MenuItem.CreateSubmenu(options)
|
||||
let standard_options = { 'callback': -1 }
|
||||
let options = extend(a:options, standard_options, "force")
|
||||
|
||||
return s:MenuItem.Create(options)
|
||||
endfunction
|
||||
|
||||
"FUNCTION: MenuItem.enabled() {{{1
|
||||
"return 1 if this menu item should be displayed
|
||||
"
|
||||
"delegates off to the isActiveCallback, and defaults to 1 if no callback was
|
||||
"specified
|
||||
function! s:MenuItem.enabled()
|
||||
if self.isActiveCallback != -1
|
||||
return {self.isActiveCallback}()
|
||||
endif
|
||||
return 1
|
||||
endfunction
|
||||
|
||||
"FUNCTION: MenuItem.execute() {{{1
|
||||
"perform the action behind this menu item, if this menuitem has children then
|
||||
"display a new menu for them, otherwise deletegate off to the menuitem's
|
||||
"callback
|
||||
function! s:MenuItem.execute()
|
||||
if len(self.children)
|
||||
let mc = g:NERDTreeMenuController.New(self.children)
|
||||
call mc.showMenu()
|
||||
else
|
||||
if self.callback != -1
|
||||
call {self.callback}()
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: MenuItem.isSeparator() {{{1
|
||||
"return 1 if this menuitem is a separator
|
||||
function! s:MenuItem.isSeparator()
|
||||
return self.callback == -1 && self.children == []
|
||||
endfunction
|
||||
|
||||
"FUNCTION: MenuItem.isSubmenu() {{{1
|
||||
"return 1 if this menuitem is a submenu
|
||||
function! s:MenuItem.isSubmenu()
|
||||
return self.callback == -1 && !empty(self.children)
|
||||
endfunction
|
||||
|
||||
" vim: set sw=4 sts=4 et fdm=marker:
|
||||
137
lib/nerdtree/nerdtree.vim
Normal file
137
lib/nerdtree/nerdtree.vim
Normal file
@@ -0,0 +1,137 @@
|
||||
"CLASS: NERDTree
|
||||
"============================================================
|
||||
let s:NERDTree = {}
|
||||
let g:NERDTree = s:NERDTree
|
||||
|
||||
"FUNCTION: s:NERDTree.AddPathFilter() {{{1
|
||||
function! s:NERDTree.AddPathFilter(callback)
|
||||
call add(s:NERDTree.PathFilters(), a:callback)
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:NERDTree.Close() {{{1
|
||||
"Closes the primary NERD tree window for this tab
|
||||
function! s:NERDTree.Close()
|
||||
if !s:NERDTree.IsOpen()
|
||||
return
|
||||
endif
|
||||
|
||||
if winnr("$") != 1
|
||||
if winnr() == s:NERDTree.GetWinNum()
|
||||
call nerdtree#exec("wincmd p")
|
||||
let bufnr = bufnr("")
|
||||
call nerdtree#exec("wincmd p")
|
||||
else
|
||||
let bufnr = bufnr("")
|
||||
endif
|
||||
|
||||
call nerdtree#exec(s:NERDTree.GetWinNum() . " wincmd w")
|
||||
close
|
||||
call nerdtree#exec(bufwinnr(bufnr) . " wincmd w")
|
||||
else
|
||||
close
|
||||
endif
|
||||
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()
|
||||
call s:NERDTree.Close()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:NERDTree.CursorToBookmarkTable(){{{1
|
||||
"Places the cursor at the top of the bookmarks table
|
||||
function! s:NERDTree.CursorToBookmarkTable()
|
||||
if !b:NERDTreeShowBookmarks
|
||||
throw "NERDTree.IllegalOperationError: cant find bookmark table, bookmarks arent active"
|
||||
endif
|
||||
|
||||
if g:NERDTreeMinimalUI
|
||||
return cursor(1, 2)
|
||||
endif
|
||||
|
||||
let rootNodeLine = b:NERDTree.ui.getRootLineNum()
|
||||
|
||||
let line = 1
|
||||
while getline(line) !~# '^>-\+Bookmarks-\+$'
|
||||
let line = line + 1
|
||||
if line >= rootNodeLine
|
||||
throw "NERDTree.BookmarkTableNotFoundError: didnt find the bookmarks table"
|
||||
endif
|
||||
endwhile
|
||||
call cursor(line, 2)
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:NERDTree.CursorToTreeWin(){{{1
|
||||
"Places the cursor in the nerd tree window
|
||||
function! s:NERDTree.CursorToTreeWin()
|
||||
call g:NERDTree.MustBeOpen()
|
||||
call nerdtree#exec(g:NERDTree.GetWinNum() . "wincmd w")
|
||||
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")
|
||||
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")
|
||||
endfunction
|
||||
|
||||
function! s:NERDTree.ForCurrentBuf()
|
||||
if s:NERDTree.ExistsForBuf()
|
||||
return b:NERDTree
|
||||
else
|
||||
return {}
|
||||
endif
|
||||
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
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:NERDTree.IsOpen() {{{1
|
||||
function! s:NERDTree.IsOpen()
|
||||
return s:NERDTree.GetWinNum() != -1
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:NERDTree.MustBeOpen() {{{1
|
||||
function! s:NERDTree.MustBeOpen()
|
||||
if !s:NERDTree.IsOpen()
|
||||
throw "NERDTree.TreeNotOpen"
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:NERDTree.New() {{{1
|
||||
function! s:NERDTree.New(path)
|
||||
let newObj = copy(self)
|
||||
let newObj.ui = g:NERDTreeUI.New(newObj)
|
||||
let newObj.root = g:NERDTreeDirNode.New(a:path)
|
||||
|
||||
return newObj
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:NERDTree.PathFilters() {{{1
|
||||
function! s:NERDTree.PathFilters()
|
||||
if !exists('s:NERDTree._PathFilters')
|
||||
let s:NERDTree._PathFilters = []
|
||||
endif
|
||||
return s:NERDTree._PathFilters
|
||||
endfunction
|
||||
|
||||
|
||||
"FUNCTION: s:NERDTree.render() {{{1
|
||||
"A convenience function - since this is called often
|
||||
function! s:NERDTree.render()
|
||||
call self.ui.render()
|
||||
endfunction
|
||||
35
lib/nerdtree/notifier.vim
Normal file
35
lib/nerdtree/notifier.vim
Normal file
@@ -0,0 +1,35 @@
|
||||
"CLASS: Notifier
|
||||
"============================================================
|
||||
let s:Notifier = {}
|
||||
|
||||
function! s:Notifier.AddListener(event, funcname)
|
||||
let listeners = s:Notifier.GetListenersForEvent(a:event)
|
||||
if listeners == []
|
||||
let listenersMap = s:Notifier.GetListenersMap()
|
||||
let listenersMap[a:event] = listeners
|
||||
endif
|
||||
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)
|
||||
|
||||
for listener in s:Notifier.GetListenersForEvent(a:event)
|
||||
call {listener}(event)
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
function! s:Notifier.GetListenersMap()
|
||||
if !exists("s:refreshListenersMap")
|
||||
let s:refreshListenersMap = {}
|
||||
endif
|
||||
return s:refreshListenersMap
|
||||
endfunction
|
||||
|
||||
function! s:Notifier.GetListenersForEvent(name)
|
||||
let listenersMap = s:Notifier.GetListenersMap()
|
||||
return get(listenersMap, a:name, [])
|
||||
endfunction
|
||||
|
||||
let g:NERDTreePathNotifier = deepcopy(s:Notifier)
|
||||
|
||||
352
lib/nerdtree/opener.vim
Normal file
352
lib/nerdtree/opener.vim
Normal file
@@ -0,0 +1,352 @@
|
||||
"CLASS: Opener
|
||||
"============================================================
|
||||
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!
|
||||
"
|
||||
"Args:
|
||||
"bnum: the subject buffers buffer number
|
||||
function! s:Opener._bufInWindows(bnum)
|
||||
let cnt = 0
|
||||
let winnum = 1
|
||||
while 1
|
||||
let bufnum = winbufnr(winnum)
|
||||
if bufnum < 0
|
||||
break
|
||||
endif
|
||||
if bufnum ==# a:bnum
|
||||
let cnt = cnt + 1
|
||||
endif
|
||||
let winnum = winnum + 1
|
||||
endwhile
|
||||
|
||||
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.
|
||||
"
|
||||
"Args:
|
||||
"a:newtab - boolean. If set, only close the tree now if we are opening the
|
||||
"target in a new tab. This is needed because we have to close tree before we
|
||||
"leave the tab
|
||||
function! s:Opener._checkToCloseTree(newtab)
|
||||
if self._keepopen
|
||||
return
|
||||
endif
|
||||
|
||||
if (a:newtab && self._where == 't') || !a:newtab
|
||||
call g:NERDTree.CloseIfQuitOnOpen()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
||||
"FUNCTION: s:Opener._firstUsableWindow(){{{1
|
||||
"find the window number of the first normal window
|
||||
function! s:Opener._firstUsableWindow()
|
||||
let i = 1
|
||||
while i <= winnr("$")
|
||||
let bnum = winbufnr(i)
|
||||
if bnum != -1 && getbufvar(bnum, '&buftype') ==# ''
|
||||
\ && !getwinvar(i, '&previewwindow')
|
||||
\ && (!getbufvar(bnum, '&modified') || &hidden)
|
||||
return i
|
||||
endif
|
||||
|
||||
let i += 1
|
||||
endwhile
|
||||
return -1
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Opener._gotoTargetWin() {{{1
|
||||
function! s:Opener._gotoTargetWin()
|
||||
if b:NERDTreeType ==# "secondary"
|
||||
if self._where == 'v'
|
||||
vsplit
|
||||
elseif self._where == 'h'
|
||||
split
|
||||
elseif self._where == 't'
|
||||
tabnew
|
||||
endif
|
||||
else
|
||||
call self._checkToCloseTree(1)
|
||||
|
||||
if self._where == 'v'
|
||||
call self._newVSplit()
|
||||
elseif self._where == 'h'
|
||||
call self._newSplit()
|
||||
elseif self._where == 't'
|
||||
tabnew
|
||||
elseif self._where == 'p'
|
||||
call self._previousWindow()
|
||||
endif
|
||||
|
||||
call self._checkToCloseTree(0)
|
||||
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
|
||||
"
|
||||
"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
|
||||
return 0
|
||||
endif
|
||||
|
||||
let oldwinnr = winnr()
|
||||
call nerdtree#exec(a:winnumber . "wincmd p")
|
||||
let specialWindow = getbufvar("%", '&buftype') != '' || getwinvar('%', '&previewwindow')
|
||||
let modified = &modified
|
||||
call nerdtree#exec(oldwinnr . "wincmd p")
|
||||
|
||||
"if its a special window e.g. quickfix or another explorer plugin then we
|
||||
"have to split
|
||||
if specialWindow
|
||||
return 0
|
||||
endif
|
||||
|
||||
if &hidden
|
||||
return 1
|
||||
endif
|
||||
|
||||
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! s:Opener.New(path, opts)
|
||||
let newObj = copy(self)
|
||||
|
||||
let newObj._path = a:path
|
||||
let newObj._stay = nerdtree#has_opt(a:opts, 'stay')
|
||||
|
||||
if has_key(a:opts, 'reuse')
|
||||
let newObj._reuse = a:opts['reuse']
|
||||
else
|
||||
let newObj._reuse = ''
|
||||
endif
|
||||
|
||||
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
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Opener._newSplit() {{{1
|
||||
function! s:Opener._newSplit()
|
||||
" Save the user's settings for splitbelow and splitright
|
||||
let savesplitbelow=&splitbelow
|
||||
let savesplitright=&splitright
|
||||
|
||||
" 'there' will be set to a command to move from the split window
|
||||
" back to the explorer window
|
||||
"
|
||||
" 'back' will be set to a command to move from the explorer window
|
||||
" back to the newly split window
|
||||
"
|
||||
" 'right' and 'below' will be set to the settings needed for
|
||||
" splitbelow and splitright IF the explorer is the only window.
|
||||
"
|
||||
let there= g:NERDTreeWinPos ==# "left" ? "wincmd h" : "wincmd l"
|
||||
let back = g:NERDTreeWinPos ==# "left" ? "wincmd l" : "wincmd h"
|
||||
let right= g:NERDTreeWinPos ==# "left"
|
||||
let below=0
|
||||
|
||||
" Attempt to go to adjacent window
|
||||
call nerdtree#exec(back)
|
||||
|
||||
let onlyOneWin = (winnr("$") ==# 1)
|
||||
|
||||
" If no adjacent window, set splitright and splitbelow appropriately
|
||||
if onlyOneWin
|
||||
let &splitright=right
|
||||
let &splitbelow=below
|
||||
else
|
||||
" found adjacent window - invert split direction
|
||||
let &splitright=!right
|
||||
let &splitbelow=!below
|
||||
endif
|
||||
|
||||
let splitMode = onlyOneWin ? "vertical" : ""
|
||||
|
||||
" Open the new window
|
||||
try
|
||||
exec(splitMode." sp ")
|
||||
catch /^Vim\%((\a\+)\)\=:E37/
|
||||
call g:NERDTree.CursorToTreeWin()
|
||||
throw "NERDTree.FileAlreadyOpenAndModifiedError: ". self._path.str() ." is already open and modified."
|
||||
catch /^Vim\%((\a\+)\)\=:/
|
||||
"do nothing
|
||||
endtry
|
||||
|
||||
"resize the tree window if no other window was open before
|
||||
if onlyOneWin
|
||||
let size = exists("b:NERDTreeOldWindowSize") ? b:NERDTreeOldWindowSize : g:NERDTreeWinSize
|
||||
call nerdtree#exec(there)
|
||||
exec("silent ". splitMode ." resize ". size)
|
||||
call nerdtree#exec('wincmd p')
|
||||
endif
|
||||
|
||||
" Restore splitmode settings
|
||||
let &splitbelow=savesplitbelow
|
||||
let &splitright=savesplitright
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Opener._newVSplit() {{{1
|
||||
function! s:Opener._newVSplit()
|
||||
let winwidth = winwidth(".")
|
||||
if winnr("$")==#1
|
||||
let winwidth = g:NERDTreeWinSize
|
||||
endif
|
||||
|
||||
call nerdtree#exec("wincmd p")
|
||||
vnew
|
||||
|
||||
"resize the nerd tree back to the original size
|
||||
call g:NERDTree.CursorToTreeWin()
|
||||
exec("silent vertical resize ". winwidth)
|
||||
call nerdtree#exec('wincmd p')
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Opener.open(target) {{{1
|
||||
function! s:Opener.open(target)
|
||||
if self._path.isDirectory
|
||||
call self._openDirectory(a:target)
|
||||
else
|
||||
call self._openFile()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Opener._openFile() {{{1
|
||||
function! s:Opener._openFile()
|
||||
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
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"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())
|
||||
else
|
||||
call self._gotoTargetWin()
|
||||
if empty(self._where)
|
||||
call a:node.makeRoot()
|
||||
call b:NERDTree.render()
|
||||
call a:node.putCursorHere(0, 0)
|
||||
elseif self._where == 't'
|
||||
call g:NERDTreeCreator.CreatePrimary(a:node.path.str())
|
||||
else
|
||||
call g:NERDTreeCreator.CreateSecondary(a:node.path.str())
|
||||
endif
|
||||
endif
|
||||
|
||||
if self._stay
|
||||
call self._restoreCursorPos()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Opener._previousWindow() {{{1
|
||||
function! s:Opener._previousWindow()
|
||||
if !self._isWindowUsable(winnr("#")) && self._firstUsableWindow() ==# -1
|
||||
call self._newSplit()
|
||||
else
|
||||
try
|
||||
if !self._isWindowUsable(winnr("#"))
|
||||
call nerdtree#exec(self._firstUsableWindow() . "wincmd w")
|
||||
else
|
||||
call nerdtree#exec('wincmd p')
|
||||
endif
|
||||
catch /^Vim\%((\a\+)\)\=:E37/
|
||||
call g:NERDTree.CursorToTreeWin()
|
||||
throw "NERDTree.FileAlreadyOpenAndModifiedError: ". self._path.str() ." is already open and modified."
|
||||
catch /^Vim\%((\a\+)\)\=:/
|
||||
echo v:exception
|
||||
endtry
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Opener._restoreCursorPos(){{{1
|
||||
function! s:Opener._restoreCursorPos()
|
||||
call nerdtree#exec('normal ' . self._tabnr . 'gt')
|
||||
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
|
||||
"
|
||||
"return 1 if we were successful
|
||||
function! s:Opener._reuseWindow()
|
||||
if empty(self._reuse)
|
||||
return 0
|
||||
endif
|
||||
|
||||
"check the current tab for the window
|
||||
let winnr = bufwinnr('^' . self._path.str() . '$')
|
||||
if winnr != -1
|
||||
call nerdtree#exec(winnr . "wincmd w")
|
||||
call self._checkToCloseTree(0)
|
||||
return 1
|
||||
endif
|
||||
|
||||
if self._reuse == 'currenttab'
|
||||
return 0
|
||||
endif
|
||||
|
||||
"check other tabs
|
||||
let tabnr = self._path.tabnr()
|
||||
if tabnr
|
||||
call self._checkToCloseTree(1)
|
||||
call nerdtree#exec('normal! ' . tabnr . 'gt')
|
||||
let winnr = bufwinnr('^' . self._path.str() . '$')
|
||||
call nerdtree#exec(winnr . "wincmd w")
|
||||
return 1
|
||||
endif
|
||||
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Opener._saveCursorPos(){{{1
|
||||
function! s:Opener._saveCursorPos()
|
||||
let self._bufnr = bufnr("")
|
||||
let self._tabnr = tabpagenr()
|
||||
endfunction
|
||||
|
||||
" vim: set sw=4 sts=4 et fdm=marker:
|
||||
785
lib/nerdtree/path.vim
Normal file
785
lib/nerdtree/path.vim
Normal file
@@ -0,0 +1,785 @@
|
||||
"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
|
||||
"============================================================
|
||||
let s:Path = {}
|
||||
let g:NERDTreePath = s:Path
|
||||
|
||||
"FUNCTION: Path.AbsolutePathFor(str) {{{1
|
||||
function! s:Path.AbsolutePathFor(str)
|
||||
let prependCWD = 0
|
||||
if nerdtree#runningWindows()
|
||||
let prependCWD = a:str !~# '^.:\(\\\|\/\)' && a:str !~# '^\(\\\\\|\/\/\)'
|
||||
else
|
||||
let prependCWD = a:str !~# '^/'
|
||||
endif
|
||||
|
||||
let toReturn = a:str
|
||||
if prependCWD
|
||||
let toReturn = getcwd() . s:Path.Slash() . a:str
|
||||
endif
|
||||
|
||||
return toReturn
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.bookmarkNames() {{{1
|
||||
function! s:Path.bookmarkNames()
|
||||
if !exists("self._bookmarkNames")
|
||||
call self.cacheDisplayString()
|
||||
endif
|
||||
return self._bookmarkNames
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.cacheDisplayString() {{{1
|
||||
function! s:Path.cacheDisplayString() abort
|
||||
let self.cachedDisplayString = self.flagSet.renderToString()
|
||||
|
||||
let self.cachedDisplayString .= self.getLastPathComponent(1)
|
||||
|
||||
if self.isExecutable
|
||||
let self.cachedDisplayString = self.cachedDisplayString . '*'
|
||||
endif
|
||||
|
||||
let self._bookmarkNames = []
|
||||
for i in g:NERDTreeBookmark.Bookmarks()
|
||||
if i.path.equals(self)
|
||||
call add(self._bookmarkNames, i.name)
|
||||
endif
|
||||
endfor
|
||||
if !empty(self._bookmarkNames)
|
||||
let self.cachedDisplayString .= ' {' . join(self._bookmarkNames) . '}'
|
||||
endif
|
||||
|
||||
if self.isSymLink
|
||||
let self.cachedDisplayString .= ' -> ' . self.symLinkDest
|
||||
endif
|
||||
|
||||
if self.isReadOnly
|
||||
let self.cachedDisplayString .= ' [RO]'
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.changeToDir() {{{1
|
||||
function! s:Path.changeToDir()
|
||||
let dir = self.str({'format': 'Cd'})
|
||||
if self.isDirectory ==# 0
|
||||
let dir = self.getParent().str({'format': 'Cd'})
|
||||
endif
|
||||
|
||||
try
|
||||
execute "cd " . dir
|
||||
call nerdtree#echo("CWD is now: " . getcwd())
|
||||
catch
|
||||
throw "NERDTree.PathChangeError: cannot change CWD to " . dir
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
"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".
|
||||
"
|
||||
"Args:
|
||||
"path: the path object to compare this to
|
||||
"
|
||||
"Return:
|
||||
"1, -1 or 0
|
||||
function! s:Path.compareTo(path)
|
||||
let thisPath = self.getLastPathComponent(1)
|
||||
let thatPath = a:path.getLastPathComponent(1)
|
||||
|
||||
"if the paths are the same then clearly we return 0
|
||||
if thisPath ==# thatPath
|
||||
return 0
|
||||
endif
|
||||
|
||||
let thisSS = self.getSortOrderIndex()
|
||||
let thatSS = a:path.getSortOrderIndex()
|
||||
|
||||
"compare the sort sequences, if they are different then the return
|
||||
"value is easy
|
||||
if thisSS < thatSS
|
||||
return -1
|
||||
elseif thisSS > thatSS
|
||||
return 1
|
||||
else
|
||||
if !g:NERDTreeSortHiddenFirst
|
||||
let thisPath = substitute(thisPath, '^[._]', '', '')
|
||||
let thatPath = substitute(thatPath, '^[._]', '', '')
|
||||
endif
|
||||
"if the sort sequences are the same then compare the paths
|
||||
"alphabetically
|
||||
let pathCompare = g:NERDTreeCaseSensitiveSort ? thisPath <# thatPath : thisPath <? thatPath
|
||||
if pathCompare
|
||||
return -1
|
||||
else
|
||||
return 1
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.Create(fullpath) {{{1
|
||||
"
|
||||
"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.
|
||||
"
|
||||
"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)
|
||||
throw "NERDTree.CreatePathError: Directory Exists: '" . a:fullpath . "'"
|
||||
endif
|
||||
|
||||
try
|
||||
|
||||
"if it ends with a slash, assume its a dir create it
|
||||
if a:fullpath =~# '\(\\\|\/\)$'
|
||||
"whack the trailing slash off the end if it exists
|
||||
let fullpath = substitute(a:fullpath, '\(\\\|\/\)$', '', '')
|
||||
|
||||
call mkdir(fullpath, 'p')
|
||||
|
||||
"assume its a file and create
|
||||
else
|
||||
call s:Path.createParentDirectories(a:fullpath)
|
||||
call writefile([], a:fullpath)
|
||||
endif
|
||||
catch
|
||||
throw "NERDTree.CreatePathError: Could not create path: '" . a:fullpath . "'"
|
||||
endtry
|
||||
|
||||
return s:Path.New(a:fullpath)
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.copy(dest) {{{1
|
||||
"
|
||||
"Copies the file/dir represented by this Path to the given location
|
||||
"
|
||||
"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"
|
||||
endif
|
||||
|
||||
call s:Path.createParentDirectories(a:dest)
|
||||
|
||||
let dest = s:Path.WinToUnixPath(a:dest)
|
||||
|
||||
let cmd = g:NERDTreeCopyCmd . " " . escape(self.str(), self._escChars()) . " " . escape(dest, self._escChars())
|
||||
let success = system(cmd)
|
||||
if success != 0
|
||||
throw "NERDTree.CopyError: Could not copy ''". self.str() ."'' to: '" . a:dest . "'"
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.CopyingSupported() {{{1
|
||||
"
|
||||
"returns 1 if copying is supported for this OS
|
||||
function! s:Path.CopyingSupported()
|
||||
return exists('g:NERDTreeCopyCmd')
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.copyingWillOverwrite(dest) {{{1
|
||||
"
|
||||
"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
|
||||
function! s:Path.copyingWillOverwrite(dest)
|
||||
if filereadable(a:dest)
|
||||
return 1
|
||||
endif
|
||||
|
||||
if isdirectory(a:dest)
|
||||
let path = s:Path.JoinPathStrings(a:dest, self.getLastPathComponent(0))
|
||||
if filereadable(path)
|
||||
return 1
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.createParentDirectories(path) {{{1
|
||||
"
|
||||
"create parent directories for this path if needed
|
||||
"without throwing any errors is those directories already exist
|
||||
"
|
||||
"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)
|
||||
call mkdir(dir_path, 'p')
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.delete() {{{1
|
||||
"
|
||||
"Deletes the file represented by this path.
|
||||
"Deletion of directories is not supported
|
||||
"
|
||||
"Throws NERDTree.Path.Deletion exceptions
|
||||
function! s:Path.delete()
|
||||
if self.isDirectory
|
||||
|
||||
let cmd = g:NERDTreeRemoveDirCmd . self.str({'escape': 1})
|
||||
let success = system(cmd)
|
||||
|
||||
if v:shell_error != 0
|
||||
throw "NERDTree.PathDeletionError: Could not delete directory: '" . self.str() . "'"
|
||||
endif
|
||||
else
|
||||
let success = delete(self.str())
|
||||
if success != 0
|
||||
throw "NERDTree.PathDeletionError: Could not delete file: '" . self.str() . "'"
|
||||
endif
|
||||
endif
|
||||
|
||||
"delete all bookmarks for this path
|
||||
for i in self.bookmarkNames()
|
||||
let bookmark = g:NERDTreeBookmark.BookmarkFor(i)
|
||||
call bookmark.delete()
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.displayString() {{{1
|
||||
"
|
||||
"Returns a string that specifies how the path should be represented as a
|
||||
"string
|
||||
function! s:Path.displayString()
|
||||
if self.cachedDisplayString ==# ""
|
||||
call self.cacheDisplayString()
|
||||
endif
|
||||
|
||||
return self.cachedDisplayString
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.edit() {{{1
|
||||
function! s:Path.edit()
|
||||
exec "edit " . self.str({'format': 'Edit'})
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.extractDriveLetter(fullpath) {{{1
|
||||
"
|
||||
"If running windows, cache the drive letter for this path
|
||||
function! s:Path.extractDriveLetter(fullpath)
|
||||
if nerdtree#runningWindows()
|
||||
if a:fullpath =~ '^\(\\\\\|\/\/\)'
|
||||
"For network shares, the 'drive' consists of the first two parts of the path, i.e. \\boxname\share
|
||||
let self.drive = substitute(a:fullpath, '^\(\(\\\\\|\/\/\)[^\\\/]*\(\\\|\/\)[^\\\/]*\).*', '\1', '')
|
||||
let self.drive = substitute(self.drive, '/', '\', "g")
|
||||
else
|
||||
let self.drive = substitute(a:fullpath, '\(^[a-zA-Z]:\).*', '\1', '')
|
||||
endif
|
||||
else
|
||||
let self.drive = ''
|
||||
endif
|
||||
|
||||
endfunction
|
||||
|
||||
"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! s:Path._escChars()
|
||||
if nerdtree#runningWindows()
|
||||
return " `\|\"#%&,?()\*^<>"
|
||||
endif
|
||||
|
||||
return " \\`\|\"#%&,?()\*^<>[]"
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.getDir() {{{1
|
||||
"
|
||||
"Returns this path if it is a directory, else this paths parent.
|
||||
"
|
||||
"Return:
|
||||
"a Path object
|
||||
function! s:Path.getDir()
|
||||
if self.isDirectory
|
||||
return self
|
||||
else
|
||||
return self.getParent()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.getParent() {{{1
|
||||
"
|
||||
"Returns a new path object for this paths parent
|
||||
"
|
||||
"Return:
|
||||
"a new Path object
|
||||
function! s:Path.getParent()
|
||||
if nerdtree#runningWindows()
|
||||
let path = self.drive . '\' . join(self.pathSegments[0:-2], '\')
|
||||
else
|
||||
let path = '/'. join(self.pathSegments[0:-2], '/')
|
||||
endif
|
||||
|
||||
return s:Path.New(path)
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.getLastPathComponent(dirSlash) {{{1
|
||||
"
|
||||
"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.
|
||||
function! s:Path.getLastPathComponent(dirSlash)
|
||||
if empty(self.pathSegments)
|
||||
return ''
|
||||
endif
|
||||
let toReturn = self.pathSegments[-1]
|
||||
if a:dirSlash && self.isDirectory
|
||||
let toReturn = toReturn . '/'
|
||||
endif
|
||||
return toReturn
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.getSortOrderIndex() {{{1
|
||||
"returns the index of the pattern in g:NERDTreeSortOrder that this path matches
|
||||
function! s:Path.getSortOrderIndex()
|
||||
let i = 0
|
||||
while i < len(g:NERDTreeSortOrder)
|
||||
if self.getLastPathComponent(1) =~# g:NERDTreeSortOrder[i]
|
||||
return i
|
||||
endif
|
||||
let i = i + 1
|
||||
endwhile
|
||||
return s:NERDTreeSortStarIndex
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.getSortKey() {{{1
|
||||
"returns a string used in compare function for sorting
|
||||
function! s:Path.getSortKey()
|
||||
if !exists("self._sortKey")
|
||||
let path = self.getLastPathComponent(1)
|
||||
if !g:NERDTreeSortHiddenFirst
|
||||
let path = substitute(path, '^[._]', '', '')
|
||||
endif
|
||||
if !g:NERDTreeCaseSensitiveSort
|
||||
let path = tolower(path)
|
||||
endif
|
||||
let self._sortKey = printf(s:sortKeyFormat, self.getSortOrderIndex()) . path
|
||||
endif
|
||||
|
||||
return self._sortKey
|
||||
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! s:Path.isUnixHiddenPath()
|
||||
if self.getLastPathComponent(0) =~# '^\.'
|
||||
return 1
|
||||
else
|
||||
for segment in self.pathSegments
|
||||
if segment =~# '^\.'
|
||||
return 1
|
||||
endif
|
||||
endfor
|
||||
return 0
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.ignore() {{{1
|
||||
"returns true if this path should be ignored
|
||||
function! s:Path.ignore()
|
||||
"filter out the user specified paths to ignore
|
||||
if b:NERDTreeIgnoreEnabled
|
||||
for i in g:NERDTreeIgnore
|
||||
if self._ignorePatternMatches(i)
|
||||
return 1
|
||||
endif
|
||||
endfor
|
||||
|
||||
for callback in g:NERDTree.PathFilters()
|
||||
if {callback}({'path': self, 'nerdtree': b:NERDTree})
|
||||
return 1
|
||||
endif
|
||||
endfor
|
||||
endif
|
||||
|
||||
"dont show hidden files unless instructed to
|
||||
if b:NERDTreeShowHidden ==# 0 && self.isUnixHiddenFile()
|
||||
return 1
|
||||
endif
|
||||
|
||||
if b:NERDTreeShowFiles ==# 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! s:Path._ignorePatternMatches(pattern)
|
||||
let pat = a:pattern
|
||||
if strpart(pat,len(pat)-7) == '[[dir]]'
|
||||
if !self.isDirectory
|
||||
return 0
|
||||
endif
|
||||
let pat = strpart(pat,0, len(pat)-7)
|
||||
elseif strpart(pat,len(pat)-8) == '[[file]]'
|
||||
if self.isDirectory
|
||||
return 0
|
||||
endif
|
||||
let pat = strpart(pat,0, len(pat)-8)
|
||||
endif
|
||||
|
||||
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.
|
||||
"
|
||||
"a:path should be a dir
|
||||
function! s:Path.isUnder(path)
|
||||
if a:path.isDirectory == 0
|
||||
return 0
|
||||
endif
|
||||
|
||||
let this = self.str()
|
||||
let that = a:path.str()
|
||||
return stridx(this, that . s:Path.Slash()) == 0
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.JoinPathStrings(...) {{{1
|
||||
function! s:Path.JoinPathStrings(...)
|
||||
let components = []
|
||||
for i in a:000
|
||||
let components = extend(components, split(i, '/'))
|
||||
endfor
|
||||
return '/' . join(components, '/')
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.equals() {{{1
|
||||
"
|
||||
"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
|
||||
function! s:Path.equals(path)
|
||||
return self.str() ==# a:path.str()
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.New() {{{1
|
||||
"The Constructor for the Path object
|
||||
function! s:Path.New(path)
|
||||
let newPath = copy(self)
|
||||
|
||||
call newPath.readInfoFromDisk(s:Path.AbsolutePathFor(a:path))
|
||||
|
||||
let newPath.cachedDisplayString = ""
|
||||
let newPath.flagSet = g:NERDTreeFlagSet.New()
|
||||
|
||||
return newPath
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.Slash() {{{1
|
||||
"return the slash to use for the current OS
|
||||
function! s:Path.Slash()
|
||||
return nerdtree#runningWindows() ? '\' : '/'
|
||||
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! s:Path.Resolve(path)
|
||||
let tmp = resolve(a:path)
|
||||
return tmp =~# '.\+/$' ? substitute(tmp, '/$', '', '') : tmp
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.readInfoFromDisk(fullpath) {{{1
|
||||
"
|
||||
"
|
||||
"Throws NERDTree.Path.InvalidArguments exception.
|
||||
function! s:Path.readInfoFromDisk(fullpath)
|
||||
call self.extractDriveLetter(a:fullpath)
|
||||
|
||||
let fullpath = s:Path.WinToUnixPath(a:fullpath)
|
||||
|
||||
if getftype(fullpath) ==# "fifo"
|
||||
throw "NERDTree.InvalidFiletypeError: Cant handle FIFO files: " . a:fullpath
|
||||
endif
|
||||
|
||||
let self.pathSegments = split(fullpath, '/')
|
||||
|
||||
let self.isReadOnly = 0
|
||||
if isdirectory(a:fullpath)
|
||||
let self.isDirectory = 1
|
||||
elseif filereadable(a:fullpath)
|
||||
let self.isDirectory = 0
|
||||
let self.isReadOnly = filewritable(a:fullpath) ==# 0
|
||||
else
|
||||
throw "NERDTree.InvalidArgumentsError: Invalid path = " . a:fullpath
|
||||
endif
|
||||
|
||||
let self.isExecutable = 0
|
||||
if !self.isDirectory
|
||||
let self.isExecutable = getfperm(a:fullpath) =~# 'x'
|
||||
endif
|
||||
|
||||
"grab the last part of the path (minus the trailing slash)
|
||||
let lastPathComponent = self.getLastPathComponent(0)
|
||||
|
||||
"get the path to the new node with the parent dir fully resolved
|
||||
let hardPath = s:Path.Resolve(self.strTrunk()) . '/' . lastPathComponent
|
||||
|
||||
"if the last part of the path is a symlink then flag it as such
|
||||
let self.isSymLink = (s:Path.Resolve(hardPath) != hardPath)
|
||||
if self.isSymLink
|
||||
let self.symLinkDest = s:Path.Resolve(fullpath)
|
||||
|
||||
"if the link is a dir then slap a / on the end of its dest
|
||||
if isdirectory(self.symLinkDest)
|
||||
|
||||
"we always wanna treat MS windows shortcuts as files for
|
||||
"simplicity
|
||||
if hardPath !~# '\.lnk$'
|
||||
|
||||
let self.symLinkDest = self.symLinkDest . '/'
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.refresh() {{{1
|
||||
function! s:Path.refresh()
|
||||
call self.readInfoFromDisk(self.str())
|
||||
call g:NERDTreePathNotifier.NotifyListeners('refresh', self, {})
|
||||
call self.cacheDisplayString()
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.refreshFlags() {{{1
|
||||
function! s:Path.refreshFlags()
|
||||
call g:NERDTreePathNotifier.NotifyListeners('refreshFlags', self, {})
|
||||
call self.cacheDisplayString()
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.rename() {{{1
|
||||
"
|
||||
"Renames this node on the filesystem
|
||||
function! s:Path.rename(newPath)
|
||||
if a:newPath ==# ''
|
||||
throw "NERDTree.InvalidArgumentsError: Invalid newPath for renaming = ". a:newPath
|
||||
endif
|
||||
|
||||
let success = rename(self.str(), a:newPath)
|
||||
if success != 0
|
||||
throw "NERDTree.PathRenameError: Could not rename: '" . self.str() . "'" . 'to:' . a:newPath
|
||||
endif
|
||||
call self.readInfoFromDisk(a:newPath)
|
||||
|
||||
for i in self.bookmarkNames()
|
||||
let b = g:NERDTreeBookmark.BookmarkFor(i)
|
||||
call b.setPath(copy(self))
|
||||
endfor
|
||||
call g:NERDTreeBookmark.Write()
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.str() {{{1
|
||||
"
|
||||
"Returns a string representation of this Path
|
||||
"
|
||||
"Takes an optional dictionary param to specify how the output should be
|
||||
"formatted.
|
||||
"
|
||||
"The dict 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 'escape' key, if specified will cause the output to be escaped with
|
||||
"shellescape()
|
||||
"
|
||||
"The 'truncateTo' key causes the resulting string to be truncated to the value
|
||||
"'truncateTo' maps to. A '<' char will be prepended.
|
||||
function! s:Path.str(...)
|
||||
let options = a:0 ? a:1 : {}
|
||||
let toReturn = ""
|
||||
|
||||
if has_key(options, 'format')
|
||||
let format = options['format']
|
||||
if has_key(self, '_strFor' . format)
|
||||
exec 'let toReturn = self._strFor' . format . '()'
|
||||
else
|
||||
throw 'NERDTree.UnknownFormatError: unknown format "'. format .'"'
|
||||
endif
|
||||
else
|
||||
let toReturn = self._str()
|
||||
endif
|
||||
|
||||
if nerdtree#has_opt(options, 'escape')
|
||||
let toReturn = shellescape(toReturn)
|
||||
endif
|
||||
|
||||
if has_key(options, 'truncateTo')
|
||||
let limit = options['truncateTo']
|
||||
if len(toReturn) > limit-1
|
||||
let toReturn = toReturn[(len(toReturn)-limit+1):]
|
||||
if len(split(toReturn, '/')) > 1
|
||||
let toReturn = '</' . join(split(toReturn, '/')[1:], '/') . '/'
|
||||
else
|
||||
let toReturn = '<' . toReturn
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
return toReturn
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path._strForUI() {{{1
|
||||
function! s:Path._strForUI()
|
||||
let toReturn = '/' . join(self.pathSegments, '/')
|
||||
if self.isDirectory && toReturn != '/'
|
||||
let toReturn = toReturn . '/'
|
||||
endif
|
||||
return toReturn
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path._strForCd() {{{1
|
||||
"
|
||||
" returns a string that can be used with :cd
|
||||
function! s:Path._strForCd()
|
||||
return escape(self.str(), self._escChars())
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path._strForEdit() {{{1
|
||||
"
|
||||
"Return: the string for this path that is suitable to be used with the :edit
|
||||
"command
|
||||
function! s:Path._strForEdit()
|
||||
let p = escape(self.str(), self._escChars())
|
||||
|
||||
"make it relative
|
||||
let p = fnamemodify(p, ':.')
|
||||
|
||||
"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
|
||||
endif
|
||||
|
||||
if p ==# ''
|
||||
let p = '.'
|
||||
endif
|
||||
|
||||
return p
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path._strForGlob() {{{1
|
||||
function! s:Path._strForGlob()
|
||||
let lead = s:Path.Slash()
|
||||
|
||||
"if we are running windows then slap a drive letter on the front
|
||||
if nerdtree#runningWindows()
|
||||
let lead = self.drive . '\'
|
||||
endif
|
||||
|
||||
let toReturn = lead . join(self.pathSegments, s:Path.Slash())
|
||||
|
||||
if !nerdtree#runningWindows()
|
||||
let toReturn = escape(toReturn, self._escChars())
|
||||
endif
|
||||
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! s:Path._str()
|
||||
let lead = s:Path.Slash()
|
||||
|
||||
"if we are running windows then slap a drive letter on the front
|
||||
if nerdtree#runningWindows()
|
||||
let lead = self.drive . '\'
|
||||
endif
|
||||
|
||||
return lead . join(self.pathSegments, s:Path.Slash())
|
||||
endfunction
|
||||
|
||||
"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
|
||||
|
||||
" FUNCTION: Path.tabnr() {{{1
|
||||
" return the number of the first tab that is displaying this file
|
||||
"
|
||||
" return 0 if no tab was found
|
||||
function! s:Path.tabnr()
|
||||
let str = self.str()
|
||||
for t in range(tabpagenr('$'))
|
||||
for b in tabpagebuflist(t+1)
|
||||
if str == expand('#' . b . ':p')
|
||||
return t+1
|
||||
endif
|
||||
endfor
|
||||
endfor
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.WinToUnixPath(pathstr){{{1
|
||||
"Takes in a windows path and returns the unix equiv
|
||||
"
|
||||
"A class level method
|
||||
"
|
||||
"Args:
|
||||
"pathstr: the windows path to convert
|
||||
function! s:Path.WinToUnixPath(pathstr)
|
||||
if !nerdtree#runningWindows()
|
||||
return a:pathstr
|
||||
endif
|
||||
|
||||
let toReturn = a:pathstr
|
||||
|
||||
"remove the x:\ of the front
|
||||
let toReturn = substitute(toReturn, '^.*:\(\\\|/\)\?', '/', "")
|
||||
|
||||
"remove the \\ network share from the front
|
||||
let toReturn = substitute(toReturn, '^\(\\\\\|\/\/\)[^\\\/]*\(\\\|\/\)[^\\\/]*\(\\\|\/\)\?', '/', "")
|
||||
|
||||
"convert all \ chars to /
|
||||
let toReturn = substitute(toReturn, '\', '/', "g")
|
||||
|
||||
return toReturn
|
||||
endfunction
|
||||
|
||||
" vim: set sw=4 sts=4 et fdm=marker:
|
||||
547
lib/nerdtree/tree_dir_node.vim
Normal file
547
lib/nerdtree/tree_dir_node.vim
Normal file
@@ -0,0 +1,547 @@
|
||||
"CLASS: TreeDirNode
|
||||
"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! s:TreeDirNode.AbsoluteTreeRoot()
|
||||
let currentNode = b:NERDTreeRoot
|
||||
while currentNode.parent != {}
|
||||
let currentNode = currentNode.parent
|
||||
endwhile
|
||||
return currentNode
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeDirNode.activate([options]) {{{1
|
||||
unlet s:TreeDirNode.activate
|
||||
function! s:TreeDirNode.activate(...)
|
||||
let opts = a:0 ? a:1 : {}
|
||||
call self.toggleOpen(opts)
|
||||
call b:NERDTree.render()
|
||||
call self.putCursorHere(0, 0)
|
||||
endfunction
|
||||
|
||||
"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
|
||||
function! s:TreeDirNode.addChild(treenode, inOrder)
|
||||
call add(self.children, a:treenode)
|
||||
let a:treenode.parent = self
|
||||
|
||||
if a:inOrder
|
||||
call self.sortChildren()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeDirNode.close() {{{1
|
||||
"Closes this directory
|
||||
function! s:TreeDirNode.close()
|
||||
let self.isOpen = 0
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeDirNode.closeChildren() {{{1
|
||||
"Closes all the child dir nodes of this node
|
||||
function! s:TreeDirNode.closeChildren()
|
||||
for i in self.children
|
||||
if i.path.isDirectory
|
||||
call i.close()
|
||||
call i.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.
|
||||
"
|
||||
"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
|
||||
function! s:TreeDirNode.createChild(path, inOrder)
|
||||
let newTreeNode = g:NERDTreeFileNode.New(a:path)
|
||||
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
|
||||
"
|
||||
"Args:
|
||||
"path: a path object
|
||||
unlet s:TreeDirNode.findNode
|
||||
function! s:TreeDirNode.findNode(path)
|
||||
if a:path.equals(self.path)
|
||||
return self
|
||||
endif
|
||||
if stridx(a:path.str(), self.path.str(), 0) ==# -1
|
||||
return {}
|
||||
endif
|
||||
|
||||
if self.path.isDirectory
|
||||
for i in self.children
|
||||
let retVal = i.findNode(a:path)
|
||||
if retVal != {}
|
||||
return retVal
|
||||
endif
|
||||
endfor
|
||||
endif
|
||||
return {}
|
||||
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.
|
||||
"
|
||||
"This function doesnt not recurse into child dir nodes
|
||||
"
|
||||
"Args:
|
||||
"path: a path object
|
||||
function! s:TreeDirNode.getChild(path)
|
||||
if stridx(a:path.str(), self.path.str(), 0) ==# -1
|
||||
return {}
|
||||
endif
|
||||
|
||||
let index = self.getChildIndex(a:path)
|
||||
if index ==# -1
|
||||
return {}
|
||||
else
|
||||
return self.children[index]
|
||||
endif
|
||||
|
||||
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! s:TreeDirNode.getChildByIndex(indx, visible)
|
||||
let array_to_search = a:visible? self.getVisibleChildren() : self.children
|
||||
if a:indx > len(array_to_search)
|
||||
throw "NERDTree.InvalidArgumentsError: Index is out of bounds."
|
||||
endif
|
||||
return array_to_search[a:indx]
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeDirNode.getChildIndex(path) {{{1
|
||||
"Returns the index of the child node of this node that has the given path or
|
||||
"-1 if no such node exists.
|
||||
"
|
||||
"This function doesnt not recurse into child dir nodes
|
||||
"
|
||||
"Args:
|
||||
"path: a path object
|
||||
function! s:TreeDirNode.getChildIndex(path)
|
||||
if stridx(a:path.str(), self.path.str(), 0) ==# -1
|
||||
return -1
|
||||
endif
|
||||
|
||||
"do a binary search for the child
|
||||
let a = 0
|
||||
let z = self.getChildCount()
|
||||
while a < z
|
||||
let mid = (a+z)/2
|
||||
let diff = a:path.compareTo(self.children[mid].path)
|
||||
|
||||
if diff ==# -1
|
||||
let z = mid
|
||||
elseif diff ==# 1
|
||||
let a = mid+1
|
||||
else
|
||||
return mid
|
||||
endif
|
||||
endwhile
|
||||
return -1
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeDirNode.GetSelected() {{{1
|
||||
"Returns the current node if it is a dir node, or else returns the current
|
||||
"nodes parent
|
||||
unlet s:TreeDirNode.GetSelected
|
||||
function! s:TreeDirNode.GetSelected()
|
||||
let currentDir = g:NERDTreeFileNode.GetSelected()
|
||||
if currentDir != {} && !currentDir.isRoot()
|
||||
if currentDir.path.isDirectory ==# 0
|
||||
let currentDir = currentDir.parent
|
||||
endif
|
||||
endif
|
||||
return currentDir
|
||||
endfunction
|
||||
|
||||
"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
|
||||
"
|
||||
"Return:
|
||||
"an array of treenodes
|
||||
function! s:TreeDirNode.getVisibleChildren()
|
||||
let toReturn = []
|
||||
for i in self.children
|
||||
if i.path.ignore() ==# 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! s:TreeDirNode.hasVisibleChildren()
|
||||
return self.getVisibleChildCount() != 0
|
||||
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
|
||||
"
|
||||
"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")
|
||||
|
||||
if !a:silent && len(files) > g:NERDTreeNotificationThreshold
|
||||
call nerdtree#echo("Please wait, caching a large dir ...")
|
||||
endif
|
||||
|
||||
let invalidFilesFound = 0
|
||||
for i in files
|
||||
|
||||
"filter out the .. and . directories
|
||||
"Note: we must match .. AND ../ since sometimes the globpath returns
|
||||
"../ for path with strange chars (eg $)
|
||||
if i[len(i)-3:2] != ".." && i[len(i)-2:2] != ".." &&
|
||||
\ i[len(i)-2:1] != "." && i[len(i)-1] != "."
|
||||
"put the next file in a new node and attach it
|
||||
try
|
||||
let path = g:NERDTreePath.New(i)
|
||||
call self.createChild(path, 0)
|
||||
call g:NERDTreePathNotifier.NotifyListeners('init', path, {})
|
||||
catch /^NERDTree.\(InvalidArguments\|InvalidFiletype\)Error/
|
||||
let invalidFilesFound += 1
|
||||
endtry
|
||||
endif
|
||||
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
|
||||
|
||||
if invalidFilesFound
|
||||
call nerdtree#echoWarning(invalidFilesFound . " file(s) could not be loaded into the NERD tree")
|
||||
endif
|
||||
return self.getChildCount()
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeDirNode.New(path) {{{1
|
||||
"Returns a new TreeNode object with the given path and parent
|
||||
"
|
||||
"Args:
|
||||
"path: a path object representing the full filesystem path to the file/dir that the node represents
|
||||
unlet s:TreeDirNode.New
|
||||
function! s:TreeDirNode.New(path)
|
||||
if a:path.isDirectory != 1
|
||||
throw "NERDTree.InvalidArgumentsError: A TreeDirNode object must be instantiated with a directory Path object."
|
||||
endif
|
||||
|
||||
let newTreeNode = copy(self)
|
||||
let newTreeNode.path = a:path
|
||||
|
||||
let newTreeNode.isOpen = 0
|
||||
let newTreeNode.children = []
|
||||
|
||||
let newTreeNode.parent = {}
|
||||
|
||||
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! s:TreeDirNode.open(...)
|
||||
let opts = 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
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeDirNode.openAlong([opts]) {{{1
|
||||
"recursive open the dir if it has only one directory child.
|
||||
"
|
||||
"return the level of opened directories.
|
||||
function! s:TreeDirNode.openAlong(...)
|
||||
let opts = a:0 ? a:1 : {}
|
||||
let level = 0
|
||||
|
||||
let node = self
|
||||
while node.path.isDirectory
|
||||
call node.open(opts)
|
||||
let level += 1
|
||||
if node.getVisibleChildCount() == 1
|
||||
let node = node.getChildByIndex(0, 1)
|
||||
else
|
||||
break
|
||||
endif
|
||||
endwhile
|
||||
return level
|
||||
endfunction
|
||||
|
||||
" FUNCTION: TreeDirNode.openExplorer() {{{1
|
||||
" opens an explorer window for this node in the previous window (could be a
|
||||
" nerd tree or a netrw)
|
||||
function! s:TreeDirNode.openExplorer()
|
||||
call self.open({'where': 'p'})
|
||||
endfunction
|
||||
|
||||
"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! s:TreeDirNode._openInNewTab()
|
||||
tabnew
|
||||
call g:NERDTreeCreator.CreatePrimary(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! s:TreeDirNode.openRecursively()
|
||||
call self._openRecursively2(1)
|
||||
endfunction
|
||||
|
||||
"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)
|
||||
endif
|
||||
|
||||
for i in self.children
|
||||
if i.path.isDirectory ==# 1
|
||||
call i._openRecursively2(0)
|
||||
endif
|
||||
endfor
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeDirNode.refresh() {{{1
|
||||
unlet s:TreeDirNode.refresh
|
||||
function! s:TreeDirNode.refresh()
|
||||
call self.path.refresh()
|
||||
|
||||
"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 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 !~# '\/\.\/\?$'
|
||||
|
||||
" 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
|
||||
endfor
|
||||
|
||||
"swap this nodes children out for the children we just read/refreshed
|
||||
let self.children = newChildNodes
|
||||
call self.sortChildren()
|
||||
|
||||
if invalidFilesFound
|
||||
call nerdtree#echoWarning("some files could not be loaded into the NERD tree")
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeDirNode.refreshFlags() {{{1
|
||||
unlet s:TreeDirNode.refreshFlags
|
||||
function! s:TreeDirNode.refreshFlags()
|
||||
call self.path.refreshFlags()
|
||||
for i in self.children
|
||||
call i.refreshFlags()
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeDirNode.refreshDirFlags() {{{1
|
||||
function! s:TreeDirNode.refreshDirFlags()
|
||||
call self.path.refreshFlags()
|
||||
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)
|
||||
if !a:path.isUnder(self.path)
|
||||
throw "NERDTree.InvalidArgumentsError: " . a:path.str() . " should be under " . self.path.str()
|
||||
endif
|
||||
|
||||
call self.open()
|
||||
|
||||
if self.path.equals(a:path.getParent())
|
||||
let n = self.findNode(a:path)
|
||||
call b:NERDTree.render()
|
||||
call n.putCursorHere(1,0)
|
||||
return
|
||||
endif
|
||||
|
||||
let p = a:path
|
||||
while !p.getParent().equals(self.path)
|
||||
let p = p.getParent()
|
||||
endwhile
|
||||
|
||||
let n = self.findNode(p)
|
||||
call n.reveal(a:path)
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeDirNode.removeChild(treenode) {{{1
|
||||
"
|
||||
"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
|
||||
function! s:TreeDirNode.removeChild(treenode)
|
||||
for i in range(0, self.getChildCount()-1)
|
||||
if self.children[i].equals(a:treenode)
|
||||
call remove(self.children, i)
|
||||
return
|
||||
endif
|
||||
endfor
|
||||
|
||||
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! s:TreeDirNode.sortChildren()
|
||||
let CompareFunc = function("nerdtree#compareNodesBySortKey")
|
||||
call sort(self.children, CompareFunc)
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeDirNode.toggleOpen([options]) {{{1
|
||||
"Opens this directory if it is closed and vice versa
|
||||
function! s:TreeDirNode.toggleOpen(...)
|
||||
let opts = a:0 ? a:1 : {}
|
||||
if self.isOpen ==# 1
|
||||
call self.close()
|
||||
else
|
||||
if g:NERDTreeCascadeOpenSingleChildDir == 0
|
||||
call self.open(opts)
|
||||
else
|
||||
call self.openAlong(opts)
|
||||
endif
|
||||
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
|
||||
"
|
||||
"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)
|
||||
let self.children[i] = a:newNode
|
||||
let a:newNode.parent = self
|
||||
break
|
||||
endif
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
" vim: set sw=4 sts=4 et fdm=marker:
|
||||
431
lib/nerdtree/tree_file_node.vim
Normal file
431
lib/nerdtree/tree_file_node.vim
Normal file
@@ -0,0 +1,431 @@
|
||||
"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.
|
||||
"============================================================
|
||||
let s:TreeFileNode = {}
|
||||
let g:NERDTreeFileNode = s:TreeFileNode
|
||||
|
||||
"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! 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
|
||||
let oldMarkedNode = {}
|
||||
try
|
||||
let oldMarkedNode = g:NERDTreeBookmark.GetNodeForName(a:name, 1)
|
||||
catch /^NERDTree.BookmarkNotFoundError/
|
||||
catch /^NERDTree.BookmarkedNodeNotFoundError/
|
||||
endtry
|
||||
|
||||
call g:NERDTreeBookmark.AddBookmark(a:name, self.path)
|
||||
call self.path.cacheDisplayString()
|
||||
call g:NERDTreeBookmark.Write()
|
||||
|
||||
if !empty(oldMarkedNode)
|
||||
call oldMarkedNode.path.cacheDisplayString()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"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)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeFileNode.clearBookmarks() {{{1
|
||||
function! s:TreeFileNode.clearBookmarks()
|
||||
for i in g:NERDTreeBookmark.Bookmarks()
|
||||
if i.path.equals(self.path)
|
||||
call i.delete()
|
||||
end
|
||||
endfor
|
||||
call self.path.cacheDisplayString()
|
||||
endfunction
|
||||
|
||||
"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())
|
||||
if !empty(parent)
|
||||
call parent.refresh()
|
||||
return parent.findNode(newPath)
|
||||
else
|
||||
return {}
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"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
|
||||
"
|
||||
"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
|
||||
function! s:TreeFileNode.displayString()
|
||||
return self.path.displayString()
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeFileNode.equals(treenode) {{{1
|
||||
"
|
||||
"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 ==
|
||||
"
|
||||
"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.
|
||||
"
|
||||
"Args:
|
||||
"path: the path object to compare against
|
||||
function! s:TreeFileNode.findNode(path)
|
||||
if a:path.equals(self.path)
|
||||
return self
|
||||
endif
|
||||
return {}
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeFileNode.findOpenDirSiblingWithVisibleChildren(direction) {{{1
|
||||
"
|
||||
"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 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
|
||||
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
|
||||
endif
|
||||
|
||||
return {}
|
||||
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')
|
||||
end
|
||||
return {}
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeFileNode.GetSelected() {{{1
|
||||
"gets the treenode that the cursor is currently over
|
||||
function! s:TreeFileNode.GetSelected()
|
||||
try
|
||||
let path = b:NERDTree.ui.getPath(line("."))
|
||||
if path ==# {}
|
||||
return {}
|
||||
endif
|
||||
return b:NERDTreeRoot.findNode(path)
|
||||
catch /^NERDTree/
|
||||
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! s:TreeFileNode.isVisible()
|
||||
return !self.path.ignore()
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeFileNode.isRoot() {{{1
|
||||
"returns 1 if this node is b:NERDTreeRoot
|
||||
function! s:TreeFileNode.isRoot()
|
||||
if !g:NERDTree.ExistsForBuf()
|
||||
throw "NERDTree.NoTreeError: No tree exists for the current buffer"
|
||||
endif
|
||||
|
||||
return self.equals(b:NERDTreeRoot)
|
||||
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
|
||||
"
|
||||
"Args:
|
||||
"path: a path object representing the full filesystem path to the file/dir that the node represents
|
||||
function! s:TreeFileNode.New(path)
|
||||
if a:path.isDirectory
|
||||
return g:NERDTreeDirNode.New(a:path)
|
||||
else
|
||||
let newTreeNode = copy(self)
|
||||
let newTreeNode.path = a:path
|
||||
let newTreeNode.parent = {}
|
||||
return newTreeNode
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"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! 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! 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! s:TreeFileNode.openInNewTab(options)
|
||||
echomsg 'TreeFileNode.openInNewTab is deprecated'
|
||||
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
|
||||
"
|
||||
"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)
|
||||
if ln != -1
|
||||
if a:isJump
|
||||
mark '
|
||||
endif
|
||||
call cursor(ln, col("."))
|
||||
else
|
||||
if a:recurseUpward
|
||||
let node = self
|
||||
while node != {} && b:NERDTree.ui.getLineNum(node) ==# -1
|
||||
let node = node.parent
|
||||
call node.open()
|
||||
endwhile
|
||||
call b:NERDTree.render()
|
||||
call node.putCursorHere(a:isJump, 0)
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeFileNode.refresh() {{{1
|
||||
function! s:TreeFileNode.refresh()
|
||||
call self.path.refresh()
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeFileNode.refreshFlags() {{{1
|
||||
function! s:TreeFileNode.refreshFlags()
|
||||
call self.path.refreshFlags()
|
||||
endfunction
|
||||
|
||||
"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)
|
||||
|
||||
if newParent != {}
|
||||
call newParent.createChild(self.path, 1)
|
||||
call newParent.refresh()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"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)
|
||||
endfunction
|
||||
|
||||
"Args:
|
||||
"depth: the current depth in the tree for this call
|
||||
"drawText: 1 if we should actually draw the line for this node (if 0 then the
|
||||
"child nodes are rendered only)
|
||||
"vertMap: a binary array that indicates whether a vertical bar should be draw
|
||||
"for each depth in the tree
|
||||
"isLastChild:true if this curNode is the last child of its parent
|
||||
function! s:TreeFileNode._renderToString(depth, drawText, vertMap, isLastChild)
|
||||
let output = ""
|
||||
if a:drawText ==# 1
|
||||
|
||||
let treeParts = ''
|
||||
|
||||
"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
|
||||
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 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
|
||||
|
||||
"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)
|
||||
endif
|
||||
endif
|
||||
|
||||
return output
|
||||
endfunction
|
||||
|
||||
" vim: set sw=4 sts=4 et fdm=marker:
|
||||
506
lib/nerdtree/ui.vim
Normal file
506
lib/nerdtree/ui.vim
Normal file
@@ -0,0 +1,506 @@
|
||||
"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()
|
||||
if g:NERDTreeAutoCenter
|
||||
let current_line = winline()
|
||||
let lines_to_top = current_line
|
||||
let lines_to_bottom = winheight(g:NERDTree.GetWinNum()) - current_line
|
||||
if lines_to_top < g:NERDTreeAutoCenterThreshold || lines_to_bottom < g:NERDTreeAutoCenterThreshold
|
||||
normal! zz
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"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"
|
||||
else
|
||||
let @h=@h."\" ". g:NERDTreeMapActivateNode .": open in current window\n"
|
||||
endif
|
||||
if b:NERDTreeType ==# "primary"
|
||||
let @h=@h."\" ". 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 @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 @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 @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 @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 @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"
|
||||
|
||||
"add quickhelp entries for each custom key map
|
||||
let @h=@h."\"\n\" ----------------------------\n"
|
||||
let @h=@h."\" Custom mappings~\n"
|
||||
for i in g:NERDTreeKeyMap.All()
|
||||
if !empty(i.quickhelpText)
|
||||
let @h=@h."\" ". 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
|
||||
endif
|
||||
|
||||
let @h = old_h
|
||||
endfunction
|
||||
|
||||
|
||||
"FUNCTION: s:UI.new(nerdtree) {{{1
|
||||
function! s:UI.New(nerdtree)
|
||||
let newObj = copy(self)
|
||||
let newObj.nerdtree = a:nerdtree
|
||||
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)
|
||||
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
|
||||
endif
|
||||
|
||||
if line ==# s:UI.UpDirLine()
|
||||
return b:NERDTreeRoot.path.getParent()
|
||||
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
|
||||
|
||||
let dir = ""
|
||||
let lnum = a:ln
|
||||
while lnum > 0
|
||||
let lnum = lnum - 1
|
||||
let curLine = getline(lnum)
|
||||
let curLineStripped = self._stripMarkup(curLine, 1)
|
||||
|
||||
"have we reached the top of the tree?
|
||||
if lnum == rootLine
|
||||
let dir = b:NERDTreeRoot.path.str({'format': 'UI'}) . dir
|
||||
break
|
||||
endif
|
||||
if curLineStripped =~# '/$'
|
||||
let lpindent = self._indentLevelFor(curLine)
|
||||
if lpindent < indent
|
||||
let indent = indent - 1
|
||||
|
||||
let dir = substitute (curLineStripped,'^\\', "", "") . dir
|
||||
continue
|
||||
endif
|
||||
endif
|
||||
endwhile
|
||||
let curFile = b:NERDTreeRoot.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()
|
||||
endif
|
||||
|
||||
let totalLines = line("$")
|
||||
|
||||
"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 fullpath = a:file_node.path.str({'format': 'UI'})
|
||||
|
||||
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
|
||||
endif
|
||||
|
||||
let curLine = getline(lnum)
|
||||
|
||||
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
|
||||
endif
|
||||
endwhile
|
||||
return -1
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:UI.getRootLineNum(){{{1
|
||||
"gets the line number of the root node
|
||||
function! s:UI.getRootLineNum()
|
||||
let rootLine = 1
|
||||
while 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
|
||||
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 '^[ `|]*[\-+~]'
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:UI._renderBookmarks {{{1
|
||||
function! s:UI._renderBookmarks()
|
||||
|
||||
if g:NERDTreeMinimalUI == 0
|
||||
call setline(line(".")+1, ">----------Bookmarks----------")
|
||||
call cursor(line(".")+1, col("."))
|
||||
endif
|
||||
|
||||
for i in g:NERDTreeBookmark.Bookmarks()
|
||||
call setline(line(".")+1, i.str())
|
||||
call cursor(line(".")+1, col("."))
|
||||
endfor
|
||||
|
||||
call setline(line(".")+1, '')
|
||||
call cursor(line(".")+1, col("."))
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:UI.restoreScreenState() {{{1
|
||||
"
|
||||
"Sets the screen state back to what it was when nerdtree#saveScreenState was last
|
||||
"called.
|
||||
"
|
||||
"Assumes the cursor is in the NERDTree window
|
||||
function! s:UI.restoreScreenState()
|
||||
if !has_key(self, '_screenState')
|
||||
return
|
||||
endif
|
||||
exec("silent vertical resize " . self._screenState['oldWindowSize'])
|
||||
|
||||
let old_scrolloff=&scrolloff
|
||||
let &scrolloff=0
|
||||
call cursor(self._screenState['oldTopLine'], 0)
|
||||
normal! zt
|
||||
call setpos(".", self._screenState['oldPos'])
|
||||
let &scrolloff=old_scrolloff
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:UI.saveScreenState() {{{1
|
||||
"Saves the current cursor position in the current buffer and the window
|
||||
"scroll position
|
||||
function! s:UI.saveScreenState()
|
||||
let win = winnr()
|
||||
call g:NERDTree.CursorToTreeWin()
|
||||
let self._screenState = {}
|
||||
let self._screenState['oldPos'] = getpos(".")
|
||||
let self._screenState['oldTopLine'] = line("w0")
|
||||
let self._screenState['oldWindowSize']= winwidth("")
|
||||
call nerdtree#exec(win . "wincmd w")
|
||||
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
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:UI.render() {{{1
|
||||
function! s:UI.render()
|
||||
setlocal 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)
|
||||
silent 1,$delete _
|
||||
|
||||
call self._dumpHelp()
|
||||
|
||||
"delete the blank line before the help and add one after it
|
||||
if g:NERDTreeMinimalUI == 0
|
||||
call setline(line(".")+1, "")
|
||||
call cursor(line(".")+1, col("."))
|
||||
endif
|
||||
|
||||
if b:NERDTreeShowBookmarks
|
||||
call self._renderBookmarks()
|
||||
endif
|
||||
|
||||
"add the 'up a dir' line
|
||||
if !g:NERDTreeMinimalUI
|
||||
call setline(line(".")+1, s:UI.UpDirLine())
|
||||
call cursor(line(".")+1, col("."))
|
||||
endif
|
||||
|
||||
"draw the header line
|
||||
let header = b:NERDTreeRoot.path.str({'format': 'UI', 'truncateTo': winwidth(0)})
|
||||
call setline(line(".")+1, header)
|
||||
call cursor(line(".")+1, col("."))
|
||||
|
||||
"draw the tree
|
||||
let old_o = @o
|
||||
let @o = b:NERDTreeRoot.renderToString()
|
||||
silent put o
|
||||
let @o = old_o
|
||||
|
||||
"delete the blank line at the top of the buffer
|
||||
silent 1,1delete _
|
||||
|
||||
"restore the view
|
||||
let old_scrolloff=&scrolloff
|
||||
let &scrolloff=0
|
||||
call cursor(topLine, 1)
|
||||
normal! zt
|
||||
call cursor(curLine, curCol)
|
||||
let &scrolloff = old_scrolloff
|
||||
|
||||
setlocal 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! s:UI.renderViewSavingPosition()
|
||||
let currentNode = g:NERDTreeFileNode.GetSelected()
|
||||
|
||||
"go up the tree till we find a node that will be visible or till we run
|
||||
"out of nodes
|
||||
while currentNode != {} && !currentNode.isVisible() && !currentNode.isRoot()
|
||||
let currentNode = currentNode.parent
|
||||
endwhile
|
||||
|
||||
call b:NERDTree.render()
|
||||
|
||||
if currentNode != {}
|
||||
call currentNode.putCursorHere(0, 0)
|
||||
endif
|
||||
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()
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:UI.toggleShowBookmarks() {{{1
|
||||
" toggles the display of bookmarks
|
||||
function! s:UI.toggleShowBookmarks()
|
||||
let b:NERDTreeShowBookmarks = !b:NERDTreeShowBookmarks
|
||||
if b:NERDTreeShowBookmarks
|
||||
call b:NERDTree.render()
|
||||
call g:NERDTree.CursorToBookmarkTable()
|
||||
else
|
||||
call b:NERDTree.ui.renderViewSavingPosition()
|
||||
endif
|
||||
call b:NERDTree.ui.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()
|
||||
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()
|
||||
call self.centerView()
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:UI.toggleZoom() {{{1
|
||||
" zoom (maximize/minimize) the NERDTree window
|
||||
function! s:UI.toggleZoom()
|
||||
if exists("b:NERDTreeZoomed") && b:NERDTreeZoomed
|
||||
let size = exists("b:NERDTreeOldWindowSize") ? b:NERDTreeOldWindowSize : g:NERDTreeWinSize
|
||||
exec "silent vertical resize ". size
|
||||
let b:NERDTreeZoomed = 0
|
||||
else
|
||||
exec "vertical resize"
|
||||
let b:NERDTreeZoomed = 1
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:UI.UpDirLine() {{{1
|
||||
function! s:UI.UpDirLine()
|
||||
return '.. (up a dir)'
|
||||
endfunction
|
||||
40
nerdtree_plugin/exec_menuitem.vim
Normal file
40
nerdtree_plugin/exec_menuitem.vim
Normal file
@@ -0,0 +1,40 @@
|
||||
" ============================================================================
|
||||
" File: exec_menuitem.vim
|
||||
" Description: plugin for NERD Tree that provides an execute file menu item
|
||||
" Maintainer: Martin Grenfell <martin.grenfell at gmail dot com>
|
||||
" 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.
|
||||
"
|
||||
" ============================================================================
|
||||
if exists("g:loaded_nerdtree_exec_menuitem")
|
||||
finish
|
||||
endif
|
||||
let g:loaded_nerdtree_exec_menuitem = 1
|
||||
|
||||
call NERDTreeAddMenuItem({
|
||||
\ 'text': '(!)Execute file',
|
||||
\ 'shortcut': '!',
|
||||
\ 'callback': 'NERDTreeExecFile',
|
||||
\ 'isActiveCallback': 'NERDTreeExecFileActive' })
|
||||
|
||||
function! NERDTreeExecFileActive()
|
||||
let node = g:NERDTreeFileNode.GetSelected()
|
||||
return !node.path.isDirectory && node.path.isExecutable
|
||||
endfunction
|
||||
|
||||
function! NERDTreeExecFile()
|
||||
let treenode = g:NERDTreeFileNode.GetSelected()
|
||||
echo "==========================================================\n"
|
||||
echo "Complete the command to execute (add arguments etc):\n"
|
||||
let cmd = treenode.path.str({'escape': 1})
|
||||
let cmd = input(':!', cmd . ' ')
|
||||
|
||||
if cmd != ''
|
||||
exec ':!' . cmd
|
||||
else
|
||||
echo "Aborted"
|
||||
endif
|
||||
endfunction
|
||||
287
nerdtree_plugin/fs_menu.vim
Normal file
287
nerdtree_plugin/fs_menu.vim
Normal file
@@ -0,0 +1,287 @@
|
||||
" ============================================================================
|
||||
" File: fs_menu.vim
|
||||
" Description: plugin for the NERD Tree that provides a file system menu
|
||||
" Maintainer: Martin Grenfell <martin.grenfell at gmail dot com>
|
||||
" 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.
|
||||
"
|
||||
" ============================================================================
|
||||
if exists("g:loaded_nerdtree_fs_menu")
|
||||
finish
|
||||
endif
|
||||
let g:loaded_nerdtree_fs_menu = 1
|
||||
|
||||
"Automatically delete the buffer after deleting or renaming a file
|
||||
if !exists("g:NERDTreeAutoDeleteBuffer")
|
||||
let g:NERDTreeAutoDeleteBuffer = 0
|
||||
endif
|
||||
|
||||
call NERDTreeAddMenuItem({'text': '(a)dd a childnode', 'shortcut': 'a', 'callback': 'NERDTreeAddNode'})
|
||||
call NERDTreeAddMenuItem({'text': '(m)ove the current node', 'shortcut': 'm', 'callback': 'NERDTreeMoveNode'})
|
||||
call NERDTreeAddMenuItem({'text': '(d)elete the current node', 'shortcut': 'd', 'callback': 'NERDTreeDeleteNode'})
|
||||
|
||||
if has("gui_mac") || has("gui_macvim") || has("mac")
|
||||
call NERDTreeAddMenuItem({'text': '(r)eveal in Finder the current node', 'shortcut': 'r', 'callback': 'NERDTreeRevealInFinder'})
|
||||
call NERDTreeAddMenuItem({'text': '(o)pen the current node with system editor', 'shortcut': 'o', 'callback': 'NERDTreeExecuteFile'})
|
||||
call NERDTreeAddMenuItem({'text': '(q)uicklook the current node', 'shortcut': 'q', 'callback': 'NERDTreeQuickLook'})
|
||||
endif
|
||||
|
||||
if g:NERDTreePath.CopyingSupported()
|
||||
call NERDTreeAddMenuItem({'text': '(c)opy the current node', 'shortcut': 'c', 'callback': 'NERDTreeCopyNode'})
|
||||
endif
|
||||
|
||||
if has("unix") || has("osx")
|
||||
call NERDTreeAddMenuItem({'text': '(l)ist the current node', 'shortcut': 'l', 'callback': 'NERDTreeListNode'})
|
||||
else
|
||||
call NERDTreeAddMenuItem({'text': '(l)ist the current node', 'shortcut': 'l', 'callback': 'NERDTreeListNodeWin32'})
|
||||
endif
|
||||
|
||||
"FUNCTION: s: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
|
||||
"
|
||||
"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:promptToDelBuffer(bufnum, msg)
|
||||
echo a:msg
|
||||
if g:NERDTreeAutoDeleteBuffer || nr2char(getchar()) ==# 'y'
|
||||
" 1. ensure that all windows which display the just deleted filename
|
||||
" now display an empty buffer (so a layout is preserved).
|
||||
" Is not it better to close single tabs with this file only ?
|
||||
let s:originalTabNumber = tabpagenr()
|
||||
let s:originalWindowNumber = winnr()
|
||||
exec "tabdo windo if winbufnr(0) == " . a:bufnum . " | exec ':enew! ' | endif"
|
||||
exec "tabnext " . s:originalTabNumber
|
||||
exec s:originalWindowNumber . "wincmd w"
|
||||
" 3. We don't need a previous buffer anymore
|
||||
exec "bwipeout! " . a:bufnum
|
||||
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
|
||||
"
|
||||
"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
|
||||
endif
|
||||
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")
|
||||
|
||||
if newNodeName ==# ''
|
||||
call nerdtree#echo("Node Creation Aborted.")
|
||||
return
|
||||
endif
|
||||
|
||||
try
|
||||
let newPath = g:NERDTreePath.Create(newNodeName)
|
||||
let parentNode = b:NERDTreeRoot.findNode(newPath.getParent())
|
||||
|
||||
let newTreeNode = g:NERDTreeFileNode.New(newPath)
|
||||
if empty(parentNode)
|
||||
call b:NERDTreeRoot.refresh()
|
||||
call b:NERDTree.render()
|
||||
elseif parentNode.isOpen || !empty(parentNode.children)
|
||||
call parentNode.addChild(newTreeNode, 1)
|
||||
call NERDTreeRender()
|
||||
call newTreeNode.putCursorHere(1, 0)
|
||||
endif
|
||||
catch /^NERDTree/
|
||||
call nerdtree#echoWarning("Node Not Created.")
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
"FUNCTION: NERDTreeMoveNode(){{{1
|
||||
function! NERDTreeMoveNode()
|
||||
let curNode = g:NERDTreeFileNode.GetSelected()
|
||||
let newNodePath = input("Rename the current node\n" .
|
||||
\ "==========================================================\n" .
|
||||
\ "Enter the new path for the node: \n" .
|
||||
\ "", curNode.path.str(), "file")
|
||||
|
||||
if newNodePath ==# ''
|
||||
call nerdtree#echo("Node Renaming Aborted.")
|
||||
return
|
||||
endif
|
||||
|
||||
try
|
||||
let bufnum = bufnr("^".curNode.path.str()."$")
|
||||
|
||||
call curNode.rename(newNodePath)
|
||||
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)
|
||||
endif
|
||||
|
||||
call curNode.putCursorHere(1, 0)
|
||||
|
||||
redraw
|
||||
catch /^NERDTree/
|
||||
call nerdtree#echoWarning("Node Not Renamed.")
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
" FUNCTION: NERDTreeDeleteNode() {{{1
|
||||
function! NERDTreeDeleteNode()
|
||||
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() . ": ")
|
||||
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 choice = nr2char(getchar())
|
||||
let confirmed = choice ==# 'y'
|
||||
endif
|
||||
|
||||
|
||||
if confirmed
|
||||
try
|
||||
call currentNode.delete()
|
||||
call NERDTreeRender()
|
||||
|
||||
"if the node is open in a buffer, ask the user if they want to
|
||||
"close that buffer
|
||||
let bufnum = bufnr("^".currentNode.path.str()."$")
|
||||
if buflisted(bufnum)
|
||||
let prompt = "\nNode deleted.\n\nThe file is open in buffer ". bufnum . (bufwinnr(bufnum) ==# -1 ? " (hidden)" : "") .". Delete this buffer? (yN)"
|
||||
call s:promptToDelBuffer(bufnum, prompt)
|
||||
endif
|
||||
|
||||
redraw
|
||||
catch /^NERDTree/
|
||||
call nerdtree#echoWarning("Could not remove node")
|
||||
endtry
|
||||
else
|
||||
call nerdtree#echo("delete aborted")
|
||||
endif
|
||||
|
||||
endfunction
|
||||
|
||||
" FUNCTION: NERDTreeListNode() {{{1
|
||||
function! NERDTreeListNode()
|
||||
let treenode = g:NERDTreeFileNode.GetSelected()
|
||||
if treenode != {}
|
||||
let metadata = split(system('ls -ld ' . shellescape(treenode.path.str())), '\n')
|
||||
call nerdtree#echo(metadata[0])
|
||||
else
|
||||
call nerdtree#echo("No information avaialable")
|
||||
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")
|
||||
endif
|
||||
|
||||
endfunction
|
||||
|
||||
" FUNCTION: NERDTreeCopyNode() {{{1
|
||||
function! NERDTreeCopyNode()
|
||||
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")
|
||||
|
||||
if newNodePath != ""
|
||||
"strip trailing slash
|
||||
let newNodePath = substitute(newNodePath, '\/$', '', '')
|
||||
|
||||
let confirmed = 1
|
||||
if currentNode.path.copyingWillOverwrite(newNodePath)
|
||||
call nerdtree#echo("Warning: copying may overwrite files! Continue? (yN)")
|
||||
let choice = nr2char(getchar())
|
||||
let confirmed = choice ==# 'y'
|
||||
endif
|
||||
|
||||
if confirmed
|
||||
try
|
||||
let newNode = currentNode.copy(newNodePath)
|
||||
if empty(newNode)
|
||||
call b:NERDTreeRoot.refresh()
|
||||
call b:NERDTree.render()
|
||||
else
|
||||
call NERDTreeRender()
|
||||
call newNode.putCursorHere(0, 0)
|
||||
endif
|
||||
catch /^NERDTree/
|
||||
call nerdtree#echoWarning("Could not copy node")
|
||||
endtry
|
||||
endif
|
||||
else
|
||||
call nerdtree#echo("Copy aborted.")
|
||||
endif
|
||||
redraw
|
||||
endfunction
|
||||
|
||||
" FUNCTION: NERDTreeQuickLook() {{{1
|
||||
function! NERDTreeQuickLook()
|
||||
let treenode = g:NERDTreeFileNode.GetSelected()
|
||||
if treenode != {}
|
||||
call system("qlmanage -p 2>/dev/null '" . treenode.path.str() . "'")
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" FUNCTION: NERDTreeRevealInFinder() {{{1
|
||||
function! NERDTreeRevealInFinder()
|
||||
let treenode = g:NERDTreeFileNode.GetSelected()
|
||||
if treenode != {}
|
||||
call system("open -R '" . treenode.path.str() . "'")
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" FUNCTION: NERDTreeExecuteFile() {{{1
|
||||
function! NERDTreeExecuteFile()
|
||||
let treenode = g:NERDTreeFileNode.GetSelected()
|
||||
if treenode != {}
|
||||
call system("open '" . treenode.path.str() . "'")
|
||||
endif
|
||||
endfunction
|
||||
" vim: set sw=4 sts=4 et fdm=marker:
|
||||
3288
plugin/NERD_tree.vim
3288
plugin/NERD_tree.vim
File diff suppressed because it is too large
Load Diff
106
syntax/nerdtree.vim
Normal file
106
syntax/nerdtree.vim
Normal file
@@ -0,0 +1,106 @@
|
||||
let s:tree_up_dir_line = '.. (up a dir)'
|
||||
syn match NERDTreeIgnore #\~#
|
||||
syn match NERDTreeIgnore #\[RO\]#
|
||||
|
||||
"highlighting for the .. (up dir) line at the top of the tree
|
||||
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 NERDTreeToggleOn #(on)#ms=s+1,he=e-1
|
||||
syn match NERDTreeToggleOff #(off)#ms=e-3,me=e-1
|
||||
syn match NERDTreeHelpCommand #" :.\{-}\>#hs=s+3
|
||||
syn match NERDTreeHelp #^".*# contains=NERDTreeHelpKey,NERDTreeHelpTitle,NERDTreeIgnore,NERDTreeToggleOff,NERDTreeToggleOn,NERDTreeHelpCommand
|
||||
|
||||
"highlighting for sym links
|
||||
syn match NERDTreeLinkTarget #->.*# containedin=NERDTreeDir,NERDTreeFile
|
||||
syn match NERDTreeLinkFile #.* ->#me=e-3 containedin=NERDTreeFile
|
||||
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'
|
||||
|
||||
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
|
||||
|
||||
syn match NERDTreeFlags #^ *\zs\[.\]# containedin=NERDTreeFile,NERDTreeExecFile
|
||||
syn match NERDTreeFlags #\[.\]# containedin=NERDTreeDir
|
||||
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
|
||||
endif
|
||||
|
||||
syn match NERDTreeCWD #^[</].*$#
|
||||
|
||||
"highlighting for bookmarks
|
||||
syn match NERDTreeBookmark # {.*}#hs=s+1
|
||||
|
||||
"highlighting for the bookmarks table
|
||||
syn match NERDTreeBookmarksLeader #^>#
|
||||
syn match NERDTreeBookmarksHeader #^>-\+Bookmarks-\+$# contains=NERDTreeBookmarksLeader
|
||||
syn match NERDTreeBookmarkName #^>.\{-} #he=e-1 contains=NERDTreeBookmarksLeader
|
||||
syn match NERDTreeBookmark #^>.*$# contains=NERDTreeBookmarksLeader,NERDTreeBookmarkName,NERDTreeBookmarksHeader
|
||||
|
||||
hi def link NERDTreePart Special
|
||||
hi def link NERDTreePartFile Type
|
||||
hi def link NERDTreeExecFile Title
|
||||
hi def link NERDTreeDirSlash Identifier
|
||||
|
||||
hi def link NERDTreeBookmarksHeader statement
|
||||
hi def link NERDTreeBookmarksLeader ignore
|
||||
hi def link NERDTreeBookmarkName Identifier
|
||||
hi def link NERDTreeBookmark normal
|
||||
|
||||
hi def link NERDTreeHelp String
|
||||
hi def link NERDTreeHelpKey Identifier
|
||||
hi def link NERDTreeHelpCommand Identifier
|
||||
hi def link NERDTreeHelpTitle Macro
|
||||
hi def link NERDTreeToggleOn Question
|
||||
hi def link NERDTreeToggleOff WarningMsg
|
||||
|
||||
hi def link NERDTreeLinkTarget Type
|
||||
hi def link NERDTreeLinkFile Macro
|
||||
hi def link NERDTreeLinkDir Macro
|
||||
|
||||
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 NERDTreeIgnore ignore
|
||||
hi def link NERDTreeRO WarningMsg
|
||||
hi def link NERDTreeBookmark Statement
|
||||
hi def link NERDTreeFlags Number
|
||||
|
||||
hi def link NERDTreeCurrentNode Search
|
||||
Reference in New Issue
Block a user