Compare commits
1161 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eab243fc7a | ||
|
|
ba1982d4a9 | ||
|
|
62b439ef8e | ||
|
|
1c20b8b2ee | ||
|
|
04ffa283ac | ||
|
|
10edaa088b | ||
|
|
a45575fee6 | ||
|
|
e4900bb037 | ||
|
|
793646955f | ||
|
|
7a1a979632 | ||
|
|
05dcd84216 | ||
|
|
5ccc80d8b8 | ||
|
|
1ae8604964 | ||
|
|
1b0d912814 | ||
|
|
5d5fa05d8e | ||
|
|
19f61aba7f | ||
|
|
607dc29dbb | ||
|
|
a1ddc1443c | ||
|
|
f1d16950c5 | ||
|
|
142b5e070d | ||
|
|
a79e8106ea | ||
|
|
5e143e7fe5 | ||
|
|
b7c5f0f2f2 | ||
|
|
364a56f4dc | ||
|
|
e317355a5e | ||
|
|
2934ac6408 | ||
|
|
c1670137ae | ||
|
|
20636913e5 | ||
|
|
f6a19a57e9 | ||
|
|
524a922880 | ||
|
|
802e4ddc48 | ||
|
|
29c9d1529a | ||
|
|
b54e86d361 | ||
|
|
7e0104ef42 | ||
|
|
d7933adfb0 | ||
|
|
a8b1764ec6 | ||
|
|
216aaf1f48 | ||
|
|
0547509481 | ||
|
|
45b180174f | ||
|
|
64072411bb | ||
|
|
9b5673edf7 | ||
|
|
3df75398a0 | ||
|
|
210c33d076 | ||
|
|
72586faef9 | ||
|
|
41a354c571 | ||
|
|
e6a5b0cac9 | ||
|
|
ecf08f4ba7 | ||
|
|
54430504d1 | ||
|
|
730dd59b39 | ||
|
|
90c441a329 | ||
|
|
b068a8d036 | ||
|
|
0d86165122 | ||
|
|
8007aa8ee7 | ||
|
|
a9fb228f23 | ||
|
|
7351c8a716 | ||
|
|
86fb0582cc | ||
|
|
ee31799e7f | ||
|
|
2b26fe9952 | ||
|
|
aa23f346d9 | ||
|
|
89afe613ad | ||
|
|
5cb517e3f8 | ||
|
|
17f7d7bf31 | ||
|
|
fb2cc6a205 | ||
|
|
8b81eb7299 | ||
|
|
af2a42423b | ||
|
|
b4fb673943 | ||
|
|
ce59050ded | ||
|
|
53f3d002b0 | ||
|
|
be8ad38e6c | ||
|
|
bdb3f098ca | ||
|
|
29f70f11f9 | ||
|
|
103ce24787 | ||
|
|
b0d0063b1c | ||
|
|
33db6f4a31 | ||
|
|
3ff6c4e5fb | ||
|
|
fe1f470995 | ||
|
|
22469380e2 | ||
|
|
ad3a5ae7f9 | ||
|
|
dc95fc6e3c | ||
|
|
eeb9038d1e | ||
|
|
f8fd4253f2 | ||
|
|
debbc864e4 | ||
|
|
1628e7d629 | ||
|
|
6e409f2789 | ||
|
|
0f655de980 | ||
|
|
852d780990 | ||
|
|
141c5a6eab | ||
|
|
78b858742b | ||
|
|
18f3dfcc99 | ||
|
|
956836a9ed | ||
|
|
a42f512c44 | ||
|
|
901595077f | ||
|
|
b46003799d | ||
|
|
fa080e6546 | ||
|
|
58a6b6c242 | ||
|
|
ffb611e383 | ||
|
|
82d4355517 | ||
|
|
e506412f93 | ||
|
|
797dcc2369 | ||
|
|
da59a32ac5 | ||
|
|
e35811ae97 | ||
|
|
5e31eb1370 | ||
|
|
989157dcce | ||
|
|
f026de2e52 | ||
|
|
bb83be4b47 | ||
|
|
600cb85909 | ||
|
|
672efc5a3f | ||
|
|
d64e5f04ff | ||
|
|
797feb6ab1 | ||
|
|
2072968e03 | ||
|
|
0cf4934ac1 | ||
|
|
ef0a6af11a | ||
|
|
5c51bfe412 | ||
|
|
96b917efe1 | ||
|
|
f0556b500b | ||
|
|
1e57352eee | ||
|
|
c488c08501 | ||
|
|
44017d988b | ||
|
|
a04c944069 | ||
|
|
f7c1ba52a3 | ||
|
|
881fb50681 | ||
|
|
6d163377ff | ||
|
|
211fcd3b4c | ||
|
|
415b35e7ee | ||
|
|
940bf564a4 | ||
|
|
9cdba8979a | ||
|
|
c766a2dc5c | ||
|
|
abf7ab2409 | ||
|
|
be6d556e94 | ||
|
|
fcafb31a83 | ||
|
|
1d05e3d265 | ||
|
|
d2a2847506 | ||
|
|
cd1599e833 | ||
|
|
2b21fcd164 | ||
|
|
72ddc05fd1 | ||
|
|
67b6674558 | ||
|
|
b9005e6bfe | ||
|
|
97d72926a5 | ||
|
|
6f2c2105a2 | ||
|
|
4fa34aa538 | ||
|
|
89debe2577 | ||
|
|
2a8f232d18 | ||
|
|
281a8a2e8b | ||
|
|
ea8c671251 | ||
|
|
78fad856b6 | ||
|
|
81082488f9 | ||
|
|
b53835c147 | ||
|
|
89f54e3be4 | ||
|
|
ffb657ba1b | ||
|
|
abdd0a8c89 | ||
|
|
aa9a85be9d | ||
|
|
2b1203bb3a | ||
|
|
de02802bf0 | ||
|
|
ff39185773 | ||
|
|
e638d21dc3 | ||
|
|
baf6d2858a | ||
|
|
cc7c9cbe03 | ||
|
|
3f7d24ebba | ||
|
|
f8ac8a540c | ||
|
|
1aebe9e395 | ||
|
|
7197a4e16d | ||
|
|
ab8e309268 | ||
|
|
77bd73b4c8 | ||
|
|
90367cd891 | ||
|
|
2f3f10d3b1 | ||
|
|
9a249914dd | ||
|
|
0966af8b35 | ||
|
|
f4a2c53bb5 | ||
|
|
de213ceec0 | ||
|
|
c473cc527f | ||
|
|
dfedd81d46 | ||
|
|
60c54590a1 | ||
|
|
64e1a730dc | ||
|
|
9b613d58f7 | ||
|
|
b61cda656f | ||
|
|
2842f3f6ce | ||
|
|
305aa063d4 | ||
|
|
9f1552c687 | ||
|
|
36d94d41a6 | ||
|
|
3dd3f22820 | ||
|
|
ebdd1940fe | ||
|
|
4759fcfa31 | ||
|
|
f3f4233a7a | ||
|
|
8228142060 | ||
|
|
983b5a745a | ||
|
|
b962994201 | ||
|
|
c7252ea86f | ||
|
|
f0b7204af0 | ||
|
|
3690aae695 | ||
|
|
9e0df1a6ae | ||
|
|
d36b90ce40 | ||
|
|
da1ff18493 | ||
|
|
173f62c519 | ||
|
|
e214141ccb | ||
|
|
f89e6661f3 | ||
|
|
b21e535391 | ||
|
|
583fa4f6f7 | ||
|
|
8d11075b89 | ||
|
|
5eddd2aed2 | ||
|
|
a4d56fb819 | ||
|
|
99f9d622e6 | ||
|
|
ce7cab13ba | ||
|
|
a7d6f6e591 | ||
|
|
9260848868 | ||
|
|
e6c763a73c | ||
|
|
d68aa5cf41 | ||
|
|
1044a88e58 | ||
|
|
3205dd289d | ||
|
|
245b3f44b1 | ||
|
|
c435b03bdc | ||
|
|
de4aa27d70 | ||
|
|
b5341b8b81 | ||
|
|
0ea19cacad | ||
|
|
f26ae44d84 | ||
|
|
69b3d144c4 | ||
|
|
b8a170592f | ||
|
|
ba4108445a | ||
|
|
092b240ef6 | ||
|
|
b6c512925f | ||
|
|
0b5b04c739 | ||
|
|
0506f5fea2 | ||
|
|
e2faf2300e | ||
|
|
b0daa72a72 | ||
|
|
d2586089c8 | ||
|
|
0b6fceec23 | ||
|
|
f5f2b71562 | ||
|
|
3e8083d5a1 | ||
|
|
8eb57e919e | ||
|
|
797d8de45f | ||
|
|
23567a75ab | ||
|
|
4ce0df57da | ||
|
|
4ff2c992d5 | ||
|
|
d1bfdd5a31 | ||
|
|
bcf9b630bb | ||
|
|
b7cf7d08f6 | ||
|
|
023e6be4e5 | ||
|
|
a5bfa4397a | ||
|
|
5468509778 | ||
|
|
36c726006f | ||
|
|
b05f3cc185 | ||
|
|
b241e1a4df | ||
|
|
46e9c52030 | ||
|
|
09fe097d3f | ||
|
|
f8946a22f3 | ||
|
|
53066c8f4c | ||
|
|
cb9ffee1e3 | ||
|
|
582831e5bc | ||
|
|
a42631cbc7 | ||
|
|
f37a619cc6 | ||
|
|
3f8ed04898 | ||
|
|
56aae2e861 | ||
|
|
33d2f52dcf | ||
|
|
56421ccc7b | ||
|
|
0ea8c77dd8 | ||
|
|
051e90070c | ||
|
|
b753a8c492 | ||
|
|
da368f58d9 | ||
|
|
86dd7e169a | ||
|
|
34fd68b620 | ||
|
|
e19730578c | ||
|
|
2eb57cc725 | ||
|
|
9a2b6dfd81 | ||
|
|
94ba30cbfd | ||
|
|
fe4a807042 | ||
|
|
e21a470853 | ||
|
|
c5257275ea | ||
|
|
620c17c7dc | ||
|
|
c73fee2f7d | ||
|
|
dafe95d900 | ||
|
|
ccca1092e7 | ||
|
|
758eef133c | ||
|
|
edf22cd6cd | ||
|
|
3d8dfd0db4 | ||
|
|
963cfbb9f8 | ||
|
|
945e2a57fb | ||
|
|
ab4ce7ee30 | ||
|
|
cbed0b449a | ||
|
|
f2d809d57b | ||
|
|
0461a35219 | ||
|
|
5f993a19d9 | ||
|
|
38cc1a3ea3 | ||
|
|
096869d82e | ||
|
|
bcb248b768 | ||
|
|
fdf181b8e0 | ||
|
|
2e5da439b0 | ||
|
|
3ba251cc2f | ||
|
|
01b2d0b265 | ||
|
|
861b5ef431 | ||
|
|
0847faa7e8 | ||
|
|
43c39b525f | ||
|
|
5f1d320112 | ||
|
|
429afdc541 | ||
|
|
9a75c29281 | ||
|
|
7c49f67247 | ||
|
|
e70edff5ce | ||
|
|
009b4bbee9 | ||
|
|
e11e0044ef | ||
|
|
cb977ca08f | ||
|
|
c8bc743202 | ||
|
|
25a10675e9 | ||
|
|
8194294ac7 | ||
|
|
8b886e7539 | ||
|
|
e9be309ce4 | ||
|
|
057dd91085 | ||
|
|
44a9c4f7ec | ||
|
|
a0daecc8bb | ||
|
|
884b9bcb33 | ||
|
|
1810f2f914 | ||
|
|
acd33d7bbe | ||
|
|
034728e900 | ||
|
|
a55e7620a0 | ||
|
|
868bcbff76 | ||
|
|
564592891c | ||
|
|
2c00450029 | ||
|
|
2666a008bf | ||
|
|
6c195dd8a0 | ||
|
|
e3359a6877 | ||
|
|
d479bc6153 | ||
|
|
72dcf7b18f | ||
|
|
02f5287b56 | ||
|
|
3ff31cf0c1 | ||
|
|
1ad3c0dcb2 | ||
|
|
82928702d3 | ||
|
|
d49881f96b | ||
|
|
72530932e3 | ||
|
|
cd81e96db6 | ||
|
|
32d734d568 | ||
|
|
347ef0c010 | ||
|
|
7b31f45468 | ||
|
|
5dacfbad97 | ||
|
|
46a76abbdd | ||
|
|
489aa2dbe3 | ||
|
|
0acae98979 | ||
|
|
d520c94c3b | ||
|
|
dfb87e2037 | ||
|
|
62cec50eb0 | ||
|
|
d12c51fc7b | ||
|
|
b043571fbe | ||
|
|
1c76d4fb55 | ||
|
|
e714c4f930 | ||
|
|
73d158cf02 | ||
|
|
70c03a7f0b | ||
|
|
5216720f26 | ||
|
|
d42ce98154 | ||
|
|
62b1003a05 | ||
|
|
cb363c575b | ||
|
|
c5e5ed86f6 | ||
|
|
29ca94e719 | ||
|
|
4ca28d0860 | ||
|
|
85be64273f | ||
|
|
ea4e142757 | ||
|
|
1b1775a4c2 | ||
|
|
3f73e08dd7 | ||
|
|
307b757e1f | ||
|
|
ecf9e38f55 | ||
|
|
3d424076bd | ||
|
|
e6e080f84c | ||
|
|
c8d3454fe0 | ||
|
|
0704214dea | ||
|
|
530e9d77b1 | ||
|
|
01601036c3 | ||
|
|
d7982dcd47 | ||
|
|
46b493d02e | ||
|
|
eebbcdd702 | ||
|
|
95364dd229 | ||
|
|
78e663a734 | ||
|
|
6d487b3873 | ||
|
|
b950e34459 | ||
|
|
8eaf7bab37 | ||
|
|
49e4ec976b | ||
|
|
5958b55bd0 | ||
|
|
a0d610e174 | ||
|
|
5f3d7f10b0 | ||
|
|
8a62f5e633 | ||
|
|
67bdab7e4f | ||
|
|
df21507d50 | ||
|
|
1c048e6061 | ||
|
|
9105c80eb7 | ||
|
|
f6b5b8811a | ||
|
|
15d09e7ce1 | ||
|
|
85f8d4f4b7 | ||
|
|
d13774814d | ||
|
|
bb4a8c82aa | ||
|
|
7afb791950 | ||
|
|
861ec57327 | ||
|
|
08bb19e17f | ||
|
|
2a4a38a4f1 | ||
|
|
2c6b34a86b | ||
|
|
5aeeed7683 | ||
|
|
bcd65ad420 | ||
|
|
f34cf1bdfe | ||
|
|
c8007331b0 | ||
|
|
144dcce30a | ||
|
|
9eb2005e36 | ||
|
|
6b3610450c | ||
|
|
cf3eb09f9f | ||
|
|
b9a94f63ce | ||
|
|
2640838f33 | ||
|
|
36fed3c12b | ||
|
|
897f8a2eca | ||
|
|
b34c90ee2b | ||
|
|
8901c29bd5 | ||
|
|
afb5a0c7eb | ||
|
|
903886f083 | ||
|
|
4419794991 | ||
|
|
51c3d88a69 | ||
|
|
7a3525be77 | ||
|
|
064a4e9086 | ||
|
|
a266a869b7 | ||
|
|
6154859110 | ||
|
|
b067845242 | ||
|
|
8793be5562 | ||
|
|
cbc94254b4 | ||
|
|
bc94be742e | ||
|
|
91bc189ba3 | ||
|
|
c7a6ce60f8 | ||
|
|
92f167eee8 | ||
|
|
6dc7f688b6 | ||
|
|
5e466c139e | ||
|
|
bed28181f3 | ||
|
|
236ec0f6b7 | ||
|
|
8d9024ca4e | ||
|
|
9070e7f78f | ||
|
|
c3257e29dc | ||
|
|
2b425eec4f | ||
|
|
67a77f4e83 | ||
|
|
f4cbac1e1f | ||
|
|
9f6888fc9e | ||
|
|
685d7feb09 | ||
|
|
cbcc7e6124 | ||
|
|
63685f559a | ||
|
|
18e14e47b1 | ||
|
|
43903ca8b2 | ||
|
|
d70b3f8dca | ||
|
|
13890ec409 | ||
|
|
5dc3af1937 | ||
|
|
d3e566b9c1 | ||
|
|
3dcc0b3d1b | ||
|
|
0e2b626556 | ||
|
|
236f5fba00 | ||
|
|
3778c37f40 | ||
|
|
02fd115fb0 | ||
|
|
ad546d9af9 | ||
|
|
aaa9905fac | ||
|
|
21e5f436fd | ||
|
|
190e75884d | ||
|
|
b42308c7cc | ||
|
|
520dc08100 | ||
|
|
02ca94a8d9 | ||
|
|
77695f994a | ||
|
|
586a586e60 | ||
|
|
5d72fb1938 | ||
|
|
a335257505 | ||
|
|
03cdfbb39c | ||
|
|
cb00aeb413 | ||
|
|
a29fdf1c74 | ||
|
|
66f6d958d7 | ||
|
|
c0e36f137d | ||
|
|
41cb97d664 | ||
|
|
33fec26984 | ||
|
|
29a78697bb | ||
|
|
982e075a90 | ||
|
|
267e77a089 | ||
|
|
00a0f800f9 | ||
|
|
d69ed5c294 | ||
|
|
1729244db3 | ||
|
|
a4e6856901 | ||
|
|
9e234c3901 | ||
|
|
cce38f9f21 | ||
|
|
4c1e020b42 | ||
|
|
c8a9222749 | ||
|
|
dd0f1cbb70 | ||
|
|
49f1843955 | ||
|
|
f88d74997a | ||
|
|
594b0bd340 | ||
|
|
c6287668ee | ||
|
|
1f2098707c | ||
|
|
1cf69f74d9 | ||
|
|
e8fe076681 | ||
|
|
64d65c444a | ||
|
|
974350d652 | ||
|
|
0290d7f15f | ||
|
|
d70fa6d4a2 | ||
|
|
89b2dfc373 | ||
|
|
1d67e23993 | ||
|
|
5a4ddda37d | ||
|
|
c365c937e2 | ||
|
|
6ee469fdcb | ||
|
|
690cf9d3f4 | ||
|
|
562b9fe502 | ||
|
|
a2afbe54bc | ||
|
|
c243415049 | ||
|
|
e9b3bdac34 | ||
|
|
1d900c928d | ||
|
|
8efba79453 | ||
|
|
b6853fbd88 | ||
|
|
10b8cc2fe1 | ||
|
|
ac6b54c181 | ||
|
|
f13f1242b2 | ||
|
|
87a3d2f288 | ||
|
|
fae4acceef | ||
|
|
fc227ed503 | ||
|
|
db435b179d | ||
|
|
23c35a54d4 | ||
|
|
8247501924 | ||
|
|
9589eb81d6 | ||
|
|
32a783b282 | ||
|
|
8047c9da4a | ||
|
|
ffbadfc988 | ||
|
|
37f2313979 | ||
|
|
3cdcc7a64b | ||
|
|
f055496161 | ||
|
|
a980a295bf | ||
|
|
955f509581 | ||
|
|
610e00ee21 | ||
|
|
1795cd93d6 | ||
|
|
a9153aeef5 | ||
|
|
96a19b8523 | ||
|
|
27060d59af | ||
|
|
127ae12c1b | ||
|
|
df73eb5e3e | ||
|
|
bb61e5c144 | ||
|
|
d136c46ecc | ||
|
|
0386f8b5d6 | ||
|
|
547812928e | ||
|
|
0881128a4f | ||
|
|
02176938c9 | ||
|
|
d8eff3fa55 | ||
|
|
efe4e475a6 | ||
|
|
5bdfc18daf | ||
|
|
879a072353 | ||
|
|
4050376761 | ||
|
|
1872f1406d | ||
|
|
436c81204f | ||
|
|
0cafb89831 | ||
|
|
6b91546e15 | ||
|
|
f445dd8765 | ||
|
|
5300702e34 | ||
|
|
20dce38741 | ||
|
|
0b4d70a207 | ||
|
|
6eb28b6b4f | ||
|
|
dafad57d0d | ||
|
|
101058517b | ||
|
|
8bff88848b | ||
|
|
0abbfda862 | ||
|
|
e53ec4caa8 | ||
|
|
98b931be7f | ||
|
|
23bba3f41e | ||
|
|
e03eb16e6b | ||
|
|
73c50e41a8 | ||
|
|
b544eb796e | ||
|
|
4cf8be871d | ||
|
|
5b249d3fec | ||
|
|
d065230e70 | ||
|
|
e8571684a7 | ||
|
|
832f47d2c5 | ||
|
|
47ead5ea93 | ||
|
|
b945d5c734 | ||
|
|
458e4dfdea | ||
|
|
a1ea57eaf0 | ||
|
|
a2651e22ba | ||
|
|
e265779369 | ||
|
|
6f91361197 | ||
|
|
ba3f0e0815 | ||
|
|
38ad885dd7 | ||
|
|
31e9e9c0c6 | ||
|
|
5dc840844c | ||
|
|
09ec03058e | ||
|
|
8f6381ddf5 | ||
|
|
bd92e3bf4f | ||
|
|
12d6318d39 | ||
|
|
1568e1f341 | ||
|
|
083a4901bd | ||
|
|
db10ca1bc4 | ||
|
|
2aabb8ddff | ||
|
|
4fcfdbaff3 | ||
|
|
41994632cf | ||
|
|
d498c0b7a1 | ||
|
|
11ba4dad59 | ||
|
|
7df11051e6 | ||
|
|
9a70b404af | ||
|
|
b19af4deb7 | ||
|
|
eb4090e257 | ||
|
|
bfd4e4e611 | ||
|
|
bef9c09598 | ||
|
|
4bc910bd5b | ||
|
|
737c88d7e5 | ||
|
|
c0f85b2567 | ||
|
|
6694b35ee4 | ||
|
|
44256dcf70 | ||
|
|
867dc086a0 | ||
|
|
fe08f9e819 | ||
|
|
9a9611636a | ||
|
|
8ccc3dbc49 | ||
|
|
434bddcfc7 | ||
|
|
1a4506195c | ||
|
|
7bfd309e1a | ||
|
|
9814f832fb | ||
|
|
7965ee581c | ||
|
|
d624fe0c45 | ||
|
|
1bdba0dad0 | ||
|
|
dc6f6ade41 | ||
|
|
16ff30a788 | ||
|
|
075ca1049a | ||
|
|
304bd8e63e | ||
|
|
6777957ff2 | ||
|
|
e3324d2216 | ||
|
|
8384a185a6 | ||
|
|
1236f23f9e | ||
|
|
9673eaf517 | ||
|
|
f2ec07fd1c | ||
|
|
03e4d0d52b | ||
|
|
eae9fb5fbd | ||
|
|
c218df7350 | ||
|
|
445d9f4065 | ||
|
|
491731f1d7 | ||
|
|
c0b3115fb3 | ||
|
|
0228b28cc4 | ||
|
|
6a959074a4 | ||
|
|
4cebb15918 | ||
|
|
3766ffaa38 | ||
|
|
6fd0527c07 | ||
|
|
5930dab630 | ||
|
|
2c337bb572 | ||
|
|
401b1a61cd | ||
|
|
2b33e34d3a | ||
|
|
66933f63b6 | ||
|
|
6ed2451e36 | ||
|
|
045f8d6dc1 | ||
|
|
5b38ebfefd | ||
|
|
8610fa3d5f | ||
|
|
e4de476c7f | ||
|
|
e3baaa9236 | ||
|
|
636bb45965 | ||
|
|
c73a6c47b9 | ||
|
|
d49ffa7aa4 | ||
|
|
42291fad3b | ||
|
|
6b7e632c90 | ||
|
|
63d2a36ac8 | ||
|
|
6a393f5a32 | ||
|
|
647b8e1fef | ||
|
|
25b70f8f8f | ||
|
|
781794ef92 | ||
|
|
1451077f12 | ||
|
|
c8116f6569 | ||
|
|
3e12897b31 | ||
|
|
70864552db | ||
|
|
31e3a0329e | ||
|
|
495f90db3d | ||
|
|
c5d2c45f19 | ||
|
|
4d0ed49bac | ||
|
|
ac54a9d944 | ||
|
|
353794224c | ||
|
|
b5026af628 | ||
|
|
a14650860d | ||
|
|
97b6d6faee | ||
|
|
a1c91ccb99 | ||
|
|
4b1365bccc | ||
|
|
1625046d9c | ||
|
|
f8c2ebef1d | ||
|
|
e563155b0e | ||
|
|
9cb55b3711 | ||
|
|
00ee15a32f | ||
|
|
fdfdac63a8 | ||
|
|
38f234aa91 | ||
|
|
b280a3c320 | ||
|
|
0eaff0bb07 | ||
|
|
18d97ce0d7 | ||
|
|
65fd7d2529 | ||
|
|
34e451bbfa | ||
|
|
2953a469da | ||
|
|
8460e1c8a0 | ||
|
|
214ad84a66 | ||
|
|
070cbd9001 | ||
|
|
d42adf7e32 | ||
|
|
6f9ae457e4 | ||
|
|
185a05d759 | ||
|
|
4b6cf96030 | ||
|
|
ffd98d0f8e | ||
|
|
7b3557262f | ||
|
|
980e65bd2c | ||
|
|
a30d3ecbe8 | ||
|
|
66dc2118e7 | ||
|
|
fc92dca39c | ||
|
|
2ba6dcc2b8 | ||
|
|
7f23ade08b | ||
|
|
8c558dbf3f | ||
|
|
599b186614 | ||
|
|
94bdb41dd1 | ||
|
|
45f8f0e5bb | ||
|
|
16bbb5ea24 | ||
|
|
6cb640c0e5 | ||
|
|
abd89d3aee | ||
|
|
4ad7d90c9d | ||
|
|
c05beb3059 | ||
|
|
8ebbbbac65 | ||
|
|
dadf185a87 | ||
|
|
c746cd7197 | ||
|
|
17c4cb1e2a | ||
|
|
b5c7aed3ad | ||
|
|
5317e14c98 | ||
|
|
981de641ae | ||
|
|
a1616aec0a | ||
|
|
b7fa80cc2e | ||
|
|
7a8a0d2591 | ||
|
|
8efe06e8f4 | ||
|
|
52a9f5d182 | ||
|
|
c4a7f05025 | ||
|
|
598be3bb88 | ||
|
|
d3c34f6f89 | ||
|
|
b2666ffecb | ||
|
|
0e047b8e51 | ||
|
|
f3df07a237 | ||
|
|
51771dc19a | ||
|
|
2e58aed1ea | ||
|
|
78a3726f2f | ||
|
|
ac88ceaebe | ||
|
|
33214ee924 | ||
|
|
b7e7a8264b | ||
|
|
81267dbd2a | ||
|
|
af27e80447 | ||
|
|
82322ac017 | ||
|
|
1f17a48af3 | ||
|
|
31c0d2a550 | ||
|
|
9328c0e401 | ||
|
|
3b5196910c | ||
|
|
24ceab93f9 | ||
|
|
631f42bd74 | ||
|
|
1a4c0cd761 | ||
|
|
36415f76b6 | ||
|
|
d2226c3295 | ||
|
|
a3e2983b4b | ||
|
|
6a03ad42ff | ||
|
|
2dfedf5e47 | ||
|
|
9b77e3df63 | ||
|
|
9a1411338c | ||
|
|
0bc25d9989 | ||
|
|
3bcbd9b39f | ||
|
|
084f28fcff | ||
|
|
927c40d2f3 | ||
|
|
f8fbb2a0c8 | ||
|
|
f236898f73 | ||
|
|
9cc1f53d9a | ||
|
|
88da43bfaf | ||
|
|
a82ad19110 | ||
|
|
38473b6bfa | ||
|
|
d9ca7112bc | ||
|
|
80ae319225 | ||
|
|
8f989eeadd | ||
|
|
69f5993735 | ||
|
|
2dc3146d1f | ||
|
|
ee71a1ac61 | ||
|
|
d63762fbe8 | ||
|
|
efbae0c203 | ||
|
|
8ea1fe4dab | ||
|
|
ea857ea550 | ||
|
|
19dd8a47d0 | ||
|
|
25133923e3 | ||
|
|
11d7a98303 | ||
|
|
633b76cec5 | ||
|
|
c1f17e866c | ||
|
|
6fde3e3a38 | ||
|
|
1c9d25780a | ||
|
|
5e2f1061d1 | ||
|
|
1b5155cfae | ||
|
|
0372788f2d | ||
|
|
2f7967031e | ||
|
|
31030113cf | ||
|
|
65829a2234 | ||
|
|
b6bee303a9 | ||
|
|
9aaabacf68 | ||
|
|
da49a89b28 | ||
|
|
76cc6d37e7 | ||
|
|
f56d7386c6 | ||
|
|
36c5351fde | ||
|
|
6bfb47632e | ||
|
|
b8f1241bca | ||
|
|
73939984b4 | ||
|
|
add8aaa664 | ||
|
|
11c6e7269f | ||
|
|
77885514aa | ||
|
|
8c4d70d1e1 | ||
|
|
8f936d00b7 | ||
|
|
5e2ca90f04 | ||
|
|
fe9406aba1 | ||
|
|
e771fc9fc9 | ||
|
|
346e39b723 | ||
|
|
00e680d413 | ||
|
|
de79656b04 | ||
|
|
62ebd04231 | ||
|
|
a98bef4c90 | ||
|
|
7af4dbaf1c | ||
|
|
e33838804b | ||
|
|
0f4b60314b | ||
|
|
df317bb472 | ||
|
|
3ae01237be | ||
|
|
b8e0fafaeb | ||
|
|
f03f51267b | ||
|
|
48c2bae2a0 | ||
|
|
4333952081 | ||
|
|
61653e3f19 | ||
|
|
6141b383f1 | ||
|
|
3c42a91fc5 | ||
|
|
42351724d3 | ||
|
|
fa2206bb0a | ||
|
|
90c9484d8b | ||
|
|
b46d1161c5 | ||
|
|
7b7330ec5a | ||
|
|
5c114b8b69 | ||
|
|
ab449a12e3 | ||
|
|
54445e3f3c | ||
|
|
1838f2d720 | ||
|
|
e9f7d933bd | ||
|
|
8e81ef015b | ||
|
|
1ae6a19b35 | ||
|
|
e13f0ce5d4 | ||
|
|
29cd1a376f | ||
|
|
6f8ab54a4f | ||
|
|
566b800a04 | ||
|
|
8776ec2c2d | ||
|
|
70953689e2 | ||
|
|
c805b80209 | ||
|
|
7981f8d749 | ||
|
|
cac1924b14 | ||
|
|
1561bdef7d | ||
|
|
c8c0d1f269 | ||
|
|
c61d4e6b80 | ||
|
|
fbf08e1288 | ||
|
|
8a32e87cd9 | ||
|
|
52042e8abc | ||
|
|
2923c38dc4 | ||
|
|
aa9bd9da6a | ||
|
|
9ed9764b74 | ||
|
|
7074d0da91 | ||
|
|
445e278af0 | ||
|
|
7e238a470e | ||
|
|
db365a2228 | ||
|
|
0aafeb2530 | ||
|
|
28bd6ba3e4 | ||
|
|
c5d47187cf | ||
|
|
edc216fa37 | ||
|
|
b266f389e9 | ||
|
|
9881369aa1 | ||
|
|
733b3ac8f7 | ||
|
|
caf04598d2 | ||
|
|
3332e9d34e | ||
|
|
87dc701b46 | ||
|
|
12e7eab68d | ||
|
|
bc99d7fc37 | ||
|
|
97b442d3ec | ||
|
|
211491409b | ||
|
|
51413c346e | ||
|
|
158572ae38 | ||
|
|
4683b1d542 | ||
|
|
aa951c640f | ||
|
|
4541fc5c50 | ||
|
|
caa21ee356 | ||
|
|
c9c01e0805 | ||
|
|
5ebfb4835f | ||
|
|
fd5bd89d56 | ||
|
|
95848bafa3 | ||
|
|
6a44fd9a35 | ||
|
|
990fb0d796 | ||
|
|
04b0adac56 | ||
|
|
9db97cd61c | ||
|
|
3e6a89099e | ||
|
|
0c6695d236 | ||
|
|
965af859b0 | ||
|
|
2105eb3d5b | ||
|
|
155eac8677 | ||
|
|
d0f99be764 | ||
|
|
5753d7b6ab | ||
|
|
d5f3874105 | ||
|
|
363bc44caa | ||
|
|
342ed23b66 | ||
|
|
ccf3794be2 | ||
|
|
8aa718c280 | ||
|
|
b5be1f318d | ||
|
|
3c0582c304 | ||
|
|
fe39c786a6 | ||
|
|
2b15290021 | ||
|
|
0950c7e62e | ||
|
|
95c527ff73 | ||
|
|
dba2d39f80 | ||
|
|
9fd97f0b03 | ||
|
|
8015a8fd1c | ||
|
|
932fe2b8f6 | ||
|
|
a801b47e28 | ||
|
|
7414922a76 | ||
|
|
28d6b096ab | ||
|
|
5dcb8f3200 | ||
|
|
ac1658ffd0 | ||
|
|
97c582164b | ||
|
|
87a5188de9 | ||
|
|
b92c0b7758 | ||
|
|
933b5442bd | ||
|
|
42399b17ab | ||
|
|
3ef2048289 | ||
|
|
ead26b4a66 | ||
|
|
5a96c3611d | ||
|
|
cc863af2cf | ||
|
|
d452b72dd8 | ||
|
|
2356d30394 | ||
|
|
3eb382e8f1 | ||
|
|
150a7c2439 | ||
|
|
2c43b2ccec | ||
|
|
31a0a0a2e6 | ||
|
|
0db80e844b | ||
|
|
9b363b47de | ||
|
|
e7e8216611 | ||
|
|
06400d089f | ||
|
|
6355b1259f | ||
|
|
05216eadbb | ||
|
|
6ec3534fcd | ||
|
|
1a62484509 | ||
|
|
a39092df49 | ||
|
|
1d562debc9 | ||
|
|
44904082ad | ||
|
|
888ba0d1a4 | ||
|
|
7908b34f2e | ||
|
|
5d5c522577 | ||
|
|
6663c6c3f0 | ||
|
|
a1e9ec5a55 | ||
|
|
edc5535682 | ||
|
|
c265194182 | ||
|
|
77593efd05 | ||
|
|
07334af6fc | ||
|
|
e094f843db | ||
|
|
5265275d0d | ||
|
|
38c9f1f177 | ||
|
|
8a39e9aaf4 | ||
|
|
dc623ee0d1 | ||
|
|
5ef468c192 | ||
|
|
4f0f9e53d7 | ||
|
|
f431e98c03 | ||
|
|
5b8a16df23 | ||
|
|
d4ce9322cd | ||
|
|
ef9178f7d0 | ||
|
|
787c7c6945 | ||
|
|
3d52833fa3 | ||
|
|
f59f7dc0e0 | ||
|
|
188561c9ca | ||
|
|
44b290b86c | ||
|
|
dc2bfda057 | ||
|
|
f0b107978b | ||
|
|
2c632522e7 | ||
|
|
5247b41d8b | ||
|
|
8cf00fe1b7 | ||
|
|
59b13fae82 | ||
|
|
4f199c26aa | ||
|
|
b0b949b301 | ||
|
|
b597bdd1c1 | ||
|
|
268fbfef6a | ||
|
|
9eaf45acab | ||
|
|
6669d199ef | ||
|
|
05a8c9897b | ||
|
|
aca4fd9833 | ||
|
|
c70ec71e07 | ||
|
|
34b7520c44 | ||
|
|
1c6681e99d | ||
|
|
fccb1627a6 | ||
|
|
831425d5af | ||
|
|
54bde3badd | ||
|
|
1765d44a69 | ||
|
|
d9a0b49bce | ||
|
|
bca271fbe6 | ||
|
|
607013b22b | ||
|
|
461af61a59 | ||
|
|
761e2a2aaf | ||
|
|
9963df5343 | ||
|
|
843736d5b1 | ||
|
|
796a3f0ddd | ||
|
|
db001078b2 | ||
|
|
9eaac2045b | ||
|
|
0eb04e4e6e | ||
|
|
b4566dc48b | ||
|
|
6357b4dfff | ||
|
|
94426dfd79 | ||
|
|
02c57a34ce | ||
|
|
495060e074 | ||
|
|
3bdbca77a9 | ||
|
|
6bf8afb357 | ||
|
|
39b7ae7546 | ||
|
|
a7f2823df2 | ||
|
|
8f4e23130e | ||
|
|
f463aa7b52 | ||
|
|
e3571d1281 | ||
|
|
c9d09547ac | ||
|
|
07351bdcb0 | ||
|
|
ee739c6e7a | ||
|
|
c260bb9a02 | ||
|
|
a19d9baf48 | ||
|
|
b04f8d04b2 | ||
|
|
87aef67274 | ||
|
|
b29dddc547 | ||
|
|
41c4560a6f | ||
|
|
812aa7fa42 | ||
|
|
2cbbe786fb | ||
|
|
48658c4cf9 | ||
|
|
8cca60beac | ||
|
|
8f0025c650 | ||
|
|
3eee2599b7 | ||
|
|
7fb6b2cc3b | ||
|
|
0477f38a2d | ||
|
|
5902e224e5 | ||
|
|
cbda45ae11 | ||
|
|
b7f18f6f61 | ||
|
|
2cf1e5ee44 | ||
|
|
5d67e189a8 | ||
|
|
ac10c408e3 | ||
|
|
d0473749c9 | ||
|
|
ed2b9ae4d0 | ||
|
|
1d37b2b6e2 | ||
|
|
dbacb6f8ed | ||
|
|
5ec1f2808c | ||
|
|
45dec1039c | ||
|
|
4b61da17c9 | ||
|
|
210d956214 | ||
|
|
493004b521 | ||
|
|
4fe0e98704 | ||
|
|
7e85f82426 | ||
|
|
58b2bf8f74 | ||
|
|
0b77cb0d27 | ||
|
|
4c52543f98 | ||
|
|
342f56a822 | ||
|
|
a1c82b1aa7 | ||
|
|
110059704d | ||
|
|
9ee2cbb5ed | ||
|
|
00b5a5b6f7 | ||
|
|
b664a21cdd | ||
|
|
2c41e0b862 | ||
|
|
ca1bf91c52 | ||
|
|
42815f72fa | ||
|
|
e2621f4025 | ||
|
|
78c2803523 | ||
|
|
134ebe28c0 | ||
|
|
14c3e82d16 | ||
|
|
962a7bdcc6 | ||
|
|
87ffe00a06 | ||
|
|
0adfd54133 | ||
|
|
1d00832772 | ||
|
|
83053e7fe4 | ||
|
|
464451859a | ||
|
|
7f0ab93e0d | ||
|
|
176df61343 | ||
|
|
c7f68baec6 | ||
|
|
0e7e6f853b | ||
|
|
f7a569c628 | ||
|
|
51bc7c388c | ||
|
|
f460c99015 | ||
|
|
36971ed715 | ||
|
|
a3bf0984ca | ||
|
|
36df8ef3ca | ||
|
|
4ed0bda9ff | ||
|
|
6acb18fba4 | ||
|
|
76fa728a89 | ||
|
|
629995a669 | ||
|
|
086414a5c5 | ||
|
|
f2c4c01d9e | ||
|
|
fbd85c660b | ||
|
|
d5208b758f | ||
|
|
df0aeb5005 | ||
|
|
fe004fff34 | ||
|
|
3897e49ef8 | ||
|
|
8f09c278f1 | ||
|
|
1f979b35ac | ||
|
|
f1fe73e974 | ||
|
|
8a3f29fddb | ||
|
|
983dfa943e | ||
|
|
f7e8cde45e | ||
|
|
ea85c1778f | ||
|
|
44ca13c291 | ||
|
|
618ba14369 | ||
|
|
ce69995f1d | ||
|
|
1684a267dc | ||
|
|
af1ad01b99 | ||
|
|
36fa2fc1db | ||
|
|
49a8f59091 | ||
|
|
b71203be18 | ||
|
|
ea4542027b | ||
|
|
68911aa357 | ||
|
|
55ba68195e | ||
|
|
edf2dfa5dc | ||
|
|
7f99d7a8e1 | ||
|
|
13a4f59ef6 | ||
|
|
7a7bc00777 | ||
|
|
a549b6e56f | ||
|
|
bf60ca69e7 | ||
|
|
d89f9845ab | ||
|
|
1bd2a71946 | ||
|
|
8d92eb49c6 | ||
|
|
eefc2842a6 | ||
|
|
c4de02651e | ||
|
|
8b479fb169 | ||
|
|
38d3a6445a | ||
|
|
58d2c383e8 | ||
|
|
c9dc4f2d98 | ||
|
|
5f9df53708 | ||
|
|
9b8983d355 | ||
|
|
06d6734622 | ||
|
|
1d2c2f182b | ||
|
|
b41ac01700 | ||
|
|
318bc09cf2 | ||
|
|
5d9c3cccda | ||
|
|
5075fa6efb | ||
|
|
f80fb93419 | ||
|
|
59de26fcbe | ||
|
|
6913cb9363 | ||
|
|
60edb202a3 | ||
|
|
6c6b4f8f66 | ||
|
|
587443f9e3 | ||
|
|
4000eb0412 | ||
|
|
f8569144ea | ||
|
|
4703d45fef | ||
|
|
bc20f65f85 | ||
|
|
857a83a3fb | ||
|
|
f83e3304d1 | ||
|
|
fb752f1783 | ||
|
|
fe0e82f046 | ||
|
|
26440e76e1 | ||
|
|
07cb619214 | ||
|
|
f26d4dd93a | ||
|
|
6dad574249 | ||
|
|
c477f71dd2 | ||
|
|
a784ca6a2b | ||
|
|
d04c335aa9 | ||
|
|
17891e74c7 | ||
|
|
f17634dfa7 | ||
|
|
1988c22cab | ||
|
|
badfaf95aa | ||
|
|
6c6c652638 | ||
|
|
c1d9868b49 | ||
|
|
270a5af7e8 | ||
|
|
40d89449f6 | ||
|
|
2984a58930 | ||
|
|
29720f05d1 | ||
|
|
ef991d5a26 | ||
|
|
d35e49afb0 | ||
|
|
1d26b0a6c1 | ||
|
|
80b330a2be | ||
|
|
fe2d881a08 | ||
|
|
59cc5d73c3 | ||
|
|
214c10e547 | ||
|
|
c083164e33 | ||
|
|
14df28fb35 | ||
|
|
f5fdf2a9c0 | ||
|
|
3e8cea6a23 | ||
|
|
7b067f2e65 | ||
|
|
48d7d73116 | ||
|
|
9020f645af | ||
|
|
1428b7137b | ||
|
|
04f4145524 | ||
|
|
f03d84bb7b | ||
|
|
0b62eabfce | ||
|
|
61b9a58368 | ||
|
|
a7e93400b6 | ||
|
|
ab02708306 | ||
|
|
e8a20fdb77 | ||
|
|
37de84e93c | ||
|
|
034a26c478 | ||
|
|
34ecaac3d3 |
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
node_modules/
|
||||
15
.jscsrc
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"preset": "airbnb",
|
||||
|
||||
"esnext": false,
|
||||
"requireTrailingComma": null,
|
||||
"requireCommaBeforeLineBreak": null,
|
||||
"requireCamelCaseOrUpperCaseIdentifiers": null,
|
||||
"requirePaddingNewLinesBeforeLineComments": null,
|
||||
"requirePaddingNewLinesAfterBlocks": null,
|
||||
"safeContextKeyword": "self",
|
||||
|
||||
"maximumLineLength": 110,
|
||||
"maxErrors": 1000,
|
||||
"requireSpaceAfterLineComment": true
|
||||
}
|
||||
41
.jshintrc
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"bitwise": false,
|
||||
"curly": false,
|
||||
"eqeqeq": true,
|
||||
"freeze": true,
|
||||
"latedef": "nofunc",
|
||||
"maxparams": 7,
|
||||
"noarg": true,
|
||||
"shadow": "inner",
|
||||
"undef": true,
|
||||
"unused": true,
|
||||
|
||||
"boss": true,
|
||||
"expr": true,
|
||||
"eqnull": true,
|
||||
"evil": true,
|
||||
"loopfunc": true,
|
||||
"proto": true,
|
||||
"supernew": true,
|
||||
|
||||
"-W018": true,
|
||||
"-W064": true,
|
||||
"-W086": true,
|
||||
"+W032": true,
|
||||
|
||||
"browser": false,
|
||||
"browserify": false,
|
||||
"node": true,
|
||||
"nonstandard": true,
|
||||
"typed": true,
|
||||
"worker": false,
|
||||
|
||||
"camelcase": false,
|
||||
"indent": 2,
|
||||
"maxlen": 110,
|
||||
"newcap": true,
|
||||
"quotmark": "single",
|
||||
|
||||
"laxbreak": true,
|
||||
"laxcomma": true
|
||||
}
|
||||
6
.npmignore
Normal file
@ -0,0 +1,6 @@
|
||||
.git*
|
||||
test/
|
||||
img/
|
||||
node_modules/
|
||||
.jshintrc
|
||||
.jscsrc
|
||||
83
CHANGELOG.md
Normal file
@ -0,0 +1,83 @@
|
||||
# Blessed v0.1.0 - new terminal goodies for node.js
|
||||
|
||||

|
||||
|
||||
The features demonstrated in the above gif __element transparency/shadow__ and
|
||||
__border docking__.
|
||||
|
||||
## New useful options for your typewriter application:
|
||||
|
||||
- __`transparent` option__ - Lower element opacity to 50%. This will display
|
||||
dimmed elements and content behind the foreground element using a naive color
|
||||
blending function (good enough for a terminal's limited amount of colors).
|
||||
works best with 256color terminals. (see widget-shadow.js)
|
||||
|
||||
- __`shadow` option__ - Give the element a translucent shadow. Automatically
|
||||
darkens the background behind it. (see widget-shadow.js)
|
||||
|
||||
- __`dockBorders` option__ - Element borders will automatically "dock" to each
|
||||
other. Instead of overlapping the borders end up connecting. (see
|
||||
widget-dock.js)
|
||||
|
||||
- __`autoPadding` default__ - Auto padding is now enabled by default, meaning
|
||||
blessed will automatically position elements inside their parent's border.
|
||||
|
||||
- __`rleft` property__ - Relative offsets are now default element properties
|
||||
(`left` instead of `rleft`).
|
||||
|
||||
- __`draggable` property__ - Make any element draggable with the mouse. (see
|
||||
widget-shadow.js or widget-dock.js)
|
||||
|
||||
- __`Table` and `ListTable` elements__ - Tables with a high quality rendering.
|
||||
(see widget-table.js and widget-listtable.js)
|
||||
|
||||
- __`Log` element__ - A top to bottom logger box with scrollback and other
|
||||
features. (see widget-log.js)
|
||||
|
||||
- __Obscurable borders__ - In addition to docking borders, it's possible to
|
||||
obscure borders by sliding them off the screen with negative offsets. (see
|
||||
widget-dock.js)
|
||||
|
||||
- __Percentage expressions__ - Like CSS, arithmetic can now be performed on
|
||||
percentages. e.g. `width: '50%-1'`. This is useful for overlapping borders on
|
||||
elements with a percentage width. (see widget-dock.js)
|
||||
|
||||
## Other features that weren't mentioned before:
|
||||
|
||||
- __`setHover` option__ - Set a hover text box to follow cursor on mouseover,
|
||||
similar to how a web browser handles the "title" attribute. (see widget.js)
|
||||
|
||||
- __`Terminal` element__ - Spin up a pseudo terminal as a blessed element.
|
||||
useful for writing a terminal multiplexer. (requires term.js and pty.js as
|
||||
optional dependencies). (see example/multiplex.js)
|
||||
|
||||
- __`Image` element__ - Uses `w3mimgdisplay` to draw real images your terminal.
|
||||
this is much easier than calling w3mimgdisplay by hand. Image elements behave
|
||||
like any other element, although it is wise to use `width: 'shrink', height:
|
||||
'shrink'`. (see widget-image.js)
|
||||
|
||||
---
|
||||
|
||||
The major things that justified the 0.1.0 release were fixes and stabilization
|
||||
of api (`autoPadding`/`rleft`/`left`). Scrolling boxes were almost completely
|
||||
revamped to work a bit smarter.
|
||||
|
||||
---
|
||||
|
||||
## Things yet to come:
|
||||
|
||||
- __@secrettriangle's [improvements](https://github.com/slap-editor/slap) for
|
||||
textareas__ - This allows for real text navigation.
|
||||
|
||||
- __Gravity and margin layouts__
|
||||
|
||||
This is something that's been in the idea bin for a while. Every element could
|
||||
potentially have properties like:
|
||||
|
||||
```
|
||||
gravity: 'bottomleft',
|
||||
margin: 5,
|
||||
``
|
||||
|
||||
In other words, just a more complex `float` system than what the CSSOM is used
|
||||
to.
|
||||
3
LICENSE
@ -1,4 +1,5 @@
|
||||
Copyright (c) 2013, Christopher Jeffrey (https://github.com/chjj/)
|
||||
Copyright (c) 2013-2015, Christopher Jeffrey and contributors
|
||||
https://github.com/chjj/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
16
bin/tput.js
Executable file
@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
var blessed = require('../')
|
||||
, argv = process.argv.slice(2)
|
||||
, cmd = argv.shift()
|
||||
, tput;
|
||||
|
||||
tput = blessed.tput({
|
||||
terminal: process.env.TERM,
|
||||
termcap: !!process.env.USE_TERMCAP,
|
||||
extended: true
|
||||
});
|
||||
|
||||
if (tput[cmd]) {
|
||||
process.stdout.write(tput[cmd].apply(tput, argv));
|
||||
}
|
||||
7
browser/Makefile
Normal file
@ -0,0 +1,7 @@
|
||||
all:
|
||||
@cd .. && browserify -e index.js -o browser/blessed.js
|
||||
|
||||
clean:
|
||||
@rm -f blessed.js
|
||||
|
||||
.PHONY: clean all
|
||||
105
browser/transform.js
Normal file
@ -0,0 +1,105 @@
|
||||
/**
|
||||
* transform.js - browserify workaround for blessed
|
||||
* Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
var Transform = require('stream').Transform
|
||||
, path = require('path')
|
||||
, fs = require('fs');
|
||||
|
||||
/**
|
||||
* Transformer
|
||||
*/
|
||||
|
||||
function transformer(code) {
|
||||
var stream = new Transform;
|
||||
stream._transform = function(chunk, encoding, callback) {
|
||||
return callback(null, chunk);
|
||||
};
|
||||
stream._flush = function(callback) {
|
||||
if (code) {
|
||||
stream.push(code);
|
||||
}
|
||||
return callback();
|
||||
};
|
||||
return stream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Explicitly require all widgets in widget.js
|
||||
*/
|
||||
|
||||
var widgets = fs.readdirSync(__dirname + '/../lib/widgets');
|
||||
|
||||
var requireWidgets = widgets.reduce(function(out, name) {
|
||||
name = path.basename(name, '.js');
|
||||
out += '\nrequire(\'./widgets/' + name + '\');';
|
||||
return out;
|
||||
}, '');
|
||||
|
||||
/**
|
||||
* Do not make filesystem calls in tput.js for
|
||||
* terminfo or termcap, just use xterm terminfo/cap.
|
||||
*/
|
||||
|
||||
var infoPath = path.resolve(__dirname, '..', 'usr', 'xterm-256color')
|
||||
, capPath = path.resolve(__dirname, '..', 'usr', 'xterm.termcap');
|
||||
|
||||
var infoPathFake = path.resolve(
|
||||
path.sep, 'usr', 'share', 'terminfo',
|
||||
path.basename(infoPath)[0],
|
||||
path.basename(infoPath)
|
||||
);
|
||||
|
||||
function readMethods() {
|
||||
Tput._infoBuffer = new Buffer(TERMINFO, 'base64');
|
||||
|
||||
Tput.prototype.readTerminfo = function() {
|
||||
this.terminal = TERMINFO_NAME;
|
||||
return this.parseTerminfo(Tput._infoBuffer, TERMINFO_PATH);
|
||||
};
|
||||
|
||||
Tput.cpaths = [];
|
||||
Tput.termcap = TERMCAP;
|
||||
|
||||
Tput.prototype._readTermcap = Tput.prototype.readTermcap;
|
||||
Tput.prototype.readTermcap = function() {
|
||||
this.terminal = TERMCAP_NAME;
|
||||
return this._readTermcap(this.terminal);
|
||||
};
|
||||
|
||||
Tput.prototype.detectUnicode = function() {
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
readMethods = readMethods.toString().slice(24, -2)
|
||||
.replace(/^ /gm, '')
|
||||
.replace('TERMINFO', JSON.stringify(fs.readFileSync(infoPath, 'base64')))
|
||||
.replace('TERMINFO_NAME', JSON.stringify(path.basename(infoPath)))
|
||||
.replace('TERMINFO_PATH', JSON.stringify(infoPathFake))
|
||||
.replace('TERMCAP', JSON.stringify(fs.readFileSync(capPath, 'utf8')))
|
||||
.replace('TERMCAP_NAME', JSON.stringify(path.basename(capPath, '.termcap')));
|
||||
|
||||
/**
|
||||
* Helpers
|
||||
*/
|
||||
|
||||
function end(file, offset) {
|
||||
return file.split(path.sep).slice(-offset).join('/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = function(file) {
|
||||
if (end(file, 2) === 'lib/widget.js') {
|
||||
return transformer(requireWidgets);
|
||||
}
|
||||
if (end(file, 2) === 'lib/tput.js') {
|
||||
return transformer(readMethods);
|
||||
}
|
||||
return transformer();
|
||||
};
|
||||
20
example/ansi-viewer/LICENSE
Normal file
@ -0,0 +1,20 @@
|
||||
Copyright (c) 2015, Christopher Jeffrey
|
||||
https://github.com/chjj/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
17
example/ansi-viewer/README.md
Normal file
@ -0,0 +1,17 @@
|
||||
# ansi-viewer
|
||||
|
||||
A terminal app to view ANSI art from http://artscene.textfiles.com/ansi/.
|
||||
|
||||

|
||||
|
||||
## Contribution and License Agreement
|
||||
|
||||
If you contribute code to this project, you are implicitly allowing your code
|
||||
to be distributed under the MIT license. You are also implicitly verifying that
|
||||
all code is your original work. `</legalese>`
|
||||
|
||||
## License
|
||||
|
||||
Copyright (c) 2015, Christopher Jeffrey. (MIT License)
|
||||
|
||||
See LICENSE for more info.
|
||||
2717
example/ansi-viewer/ansi-art.list
Normal file
292
example/ansi-viewer/index.js
Normal file
@ -0,0 +1,292 @@
|
||||
/**
|
||||
* ansi-viewer
|
||||
* ANSI art viewer for node.
|
||||
* Copyright (c) 2015, Christopher Jeffrey and contributors (MIT License).
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
var blessed = require('blessed')
|
||||
, request = require('request')
|
||||
, singlebyte = require('./singlebyte')
|
||||
, fs = require('fs');
|
||||
|
||||
// $ wget -r -o log --tries=10 'http://artscene.textfiles.com/ansi/'
|
||||
// $ grep 'http.*\.ans$' log | awk '{ print $3 }' > ansi-art.list
|
||||
|
||||
var urls = fs.readFileSync(__dirname + '/ansi-art.list', 'utf8').trim().split('\n');
|
||||
|
||||
var map = urls.reduce(function(map, url) {
|
||||
map[/([^.\/]+\/[^.\/]+)\.ans$/.exec(url)[1]] = url;
|
||||
return map;
|
||||
}, {});
|
||||
|
||||
var max = Object.keys(map).reduce(function(out, text) {
|
||||
return Math.max(out, text.length);
|
||||
}, 0) + 6;
|
||||
|
||||
var screen = blessed.screen({
|
||||
smartCSR: true,
|
||||
dockBorders: true
|
||||
});
|
||||
|
||||
var art = blessed.terminal({
|
||||
parent: screen,
|
||||
left: 0,
|
||||
top: 0,
|
||||
height: 60,
|
||||
// some are 78/80, some are 80/82
|
||||
width: 82,
|
||||
border: 'line',
|
||||
tags: true,
|
||||
label: ' {bold}{cyan-fg}ANSI Art{/cyan-fg}{/bold} (Drag Me) ',
|
||||
handler: function() {},
|
||||
draggable: true
|
||||
});
|
||||
|
||||
var list = blessed.list({
|
||||
parent: screen,
|
||||
label: ' {bold}{cyan-fg}Art List{/cyan-fg}{/bold} (Drag Me) ',
|
||||
tags: true,
|
||||
draggable: true,
|
||||
top: 0,
|
||||
right: 0,
|
||||
width: max,
|
||||
height: '50%',
|
||||
keys: true,
|
||||
vi: true,
|
||||
mouse: true,
|
||||
border: 'line',
|
||||
scrollbar: {
|
||||
ch: ' ',
|
||||
track: {
|
||||
bg: 'cyan'
|
||||
},
|
||||
style: {
|
||||
inverse: true
|
||||
}
|
||||
},
|
||||
style: {
|
||||
item: {
|
||||
hover: {
|
||||
bg: 'blue'
|
||||
}
|
||||
},
|
||||
selected: {
|
||||
bg: 'blue',
|
||||
bold: true
|
||||
}
|
||||
},
|
||||
search: function(callback) {
|
||||
prompt.input('Search:', '', function(err, value) {
|
||||
if (err) return;
|
||||
return callback(null, value);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
var status = blessed.box({
|
||||
parent: screen,
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
height: 1,
|
||||
width: 'shrink',
|
||||
style: {
|
||||
bg: 'blue'
|
||||
},
|
||||
content: 'Select your piece of ANSI art (`/` to search).'
|
||||
});
|
||||
|
||||
var loader = blessed.loading({
|
||||
parent: screen,
|
||||
top: 'center',
|
||||
left: 'center',
|
||||
height: 5,
|
||||
align: 'center',
|
||||
width: '50%',
|
||||
tags: true,
|
||||
hidden: true,
|
||||
border: 'line'
|
||||
});
|
||||
|
||||
var msg = blessed.message({
|
||||
parent: screen,
|
||||
top: 'center',
|
||||
left: 'center',
|
||||
height: 'shrink',
|
||||
width: '50%',
|
||||
align: 'center',
|
||||
tags: true,
|
||||
hidden: true,
|
||||
border: 'line'
|
||||
});
|
||||
|
||||
var prompt = blessed.prompt({
|
||||
parent: screen,
|
||||
top: 'center',
|
||||
left: 'center',
|
||||
height: 'shrink',
|
||||
width: 'shrink',
|
||||
keys: true,
|
||||
vi: true,
|
||||
mouse: true,
|
||||
tags: true,
|
||||
border: 'line',
|
||||
hidden: true
|
||||
});
|
||||
|
||||
list.setItems(Object.keys(map));
|
||||
|
||||
list.on('select', function(el, selected) {
|
||||
if (list._.rendering) return;
|
||||
|
||||
var name = el.getText();
|
||||
var url = map[name];
|
||||
|
||||
status.setContent(url);
|
||||
|
||||
list._.rendering = true;
|
||||
loader.load('Loading...');
|
||||
|
||||
request({
|
||||
uri: url,
|
||||
encoding: null
|
||||
}, function(err, res, body) {
|
||||
list._.rendering = false;
|
||||
loader.stop();
|
||||
|
||||
if (err) {
|
||||
return msg.error(err.message);
|
||||
}
|
||||
|
||||
if (!body) {
|
||||
return msg.error('No body.');
|
||||
}
|
||||
|
||||
return cp437ToUtf8(body, function(err, body) {
|
||||
if (err) {
|
||||
return msg.error(err.message);
|
||||
}
|
||||
|
||||
if (process.argv[2] === '--debug') {
|
||||
var filename = name.replace(/\//g, '.') + '.ans';
|
||||
fs.writeFileSync(__dirname + '/' + filename, body);
|
||||
}
|
||||
|
||||
// Remove text:
|
||||
body = body.replace('Downloaded From P-80 International Information Systems 304-744-2253', '');
|
||||
|
||||
// Remove MCI codes:
|
||||
body = body.replace(/%[A-Z0-9]{2}/g, '');
|
||||
|
||||
// ^A (SOH) seems to need to produce CRLF in some cases??
|
||||
// body = body.replace(/\x01/g, '\r\n');
|
||||
|
||||
// Reset and write the art:
|
||||
art.term.reset();
|
||||
art.term.write(body);
|
||||
art.term.cursorHidden = true;
|
||||
|
||||
screen.render();
|
||||
|
||||
if (process.argv[2] === '--debug' || process.argv[2] === '--save') {
|
||||
takeScreenshot(name);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
list.items.forEach(function(item, i) {
|
||||
var text = item.getText();
|
||||
item.setHover(map[text]);
|
||||
});
|
||||
|
||||
list.focus();
|
||||
list.enterSelected(0);
|
||||
|
||||
screen.key('h', function() {
|
||||
list.toggle();
|
||||
if (list.visible) list.focus();
|
||||
});
|
||||
|
||||
screen.key('r', function() {
|
||||
shuffle();
|
||||
});
|
||||
|
||||
screen.key('S-s', function() {
|
||||
takeScreenshot(list.ritems[list.selected]);
|
||||
});
|
||||
|
||||
screen.key('s', function() {
|
||||
slideshow();
|
||||
});
|
||||
|
||||
screen.key('q', function() {
|
||||
return process.exit(0);
|
||||
});
|
||||
|
||||
screen.render();
|
||||
|
||||
/**
|
||||
* Helpers
|
||||
*/
|
||||
|
||||
// https://github.com/chjj/blessed/issues/127
|
||||
// https://github.com/Mithgol/node-singlebyte
|
||||
|
||||
function cp437ToUtf8(buf, callback) {
|
||||
try {
|
||||
return callback(null, singlebyte.bufToStr(buf, 'cp437'));
|
||||
} catch (e) {
|
||||
return callback(e);
|
||||
}
|
||||
}
|
||||
|
||||
// Animating ANSI art doesn't work for screenshots.
|
||||
var ANIMATING = [
|
||||
'bbs/void3',
|
||||
'holiday/xmasfwks',
|
||||
'unsorted/diver',
|
||||
'unsorted/mash-chp',
|
||||
'unsorted/ryans47',
|
||||
'unsorted/xmasfwks'
|
||||
];
|
||||
|
||||
function takeScreenshot(name) {
|
||||
var filename = name.replace(/\//g, '.') + '.ans.sgr';
|
||||
var image;
|
||||
// Animating art hangs terminal during screenshot as of right now.
|
||||
if (~ANIMATING.indexOf(name)) {
|
||||
image = blessed.element.prototype.screenshot.call(art,
|
||||
0 - art.ileft, art.width - art.iright,
|
||||
0 - art.itop, art.height - art.ibottom);
|
||||
} else {
|
||||
image = art.screenshot();
|
||||
}
|
||||
fs.writeFileSync(__dirname + '/' + filename, image);
|
||||
msg.display('Screenshot taken.');
|
||||
}
|
||||
|
||||
function slideshow() {
|
||||
if (!screen._.slideshow) {
|
||||
screen._.slideshow = setInterval(function slide() {
|
||||
if (screen.lockKeys) return;
|
||||
var i = (list.items.length - 1) * Math.random() | 0;
|
||||
list.enterSelected(i);
|
||||
return slide;
|
||||
}(), 3000);
|
||||
msg.display('Slideshow started.');
|
||||
} else {
|
||||
clearInterval(screen._.slideshow);
|
||||
delete screen._.slideshow;
|
||||
msg.display('Slideshow stopped.');
|
||||
}
|
||||
}
|
||||
|
||||
function shuffle() {
|
||||
var items = Object.keys(map).sort(function(key) {
|
||||
return Math.random() > 0.5 ? 1 : -1;
|
||||
});
|
||||
list.setItems(items);
|
||||
screen.render();
|
||||
msg.display('Shuffled items.');
|
||||
}
|
||||
19
example/ansi-viewer/package.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "ansi-viewer",
|
||||
"description": "ANSI art viewer for node",
|
||||
"author": "Christopher Jeffrey",
|
||||
"version": "0.0.1",
|
||||
"main": "./index.js",
|
||||
"bin": "./index.js",
|
||||
"preferGlobal": false,
|
||||
"repository": "git://github.com/chjj/blessed.git",
|
||||
"homepage": "https://github.com/chjj/blessed",
|
||||
"bugs": { "url": "http://github.com/chjj/blessed/issues" },
|
||||
"keywords": ["ansi", "art"],
|
||||
"tags": ["ansi", "art"],
|
||||
"dependencies": {
|
||||
"blessed": ">=0.1.5",
|
||||
"term.js": "0.0.4",
|
||||
"request": "2.55.0"
|
||||
}
|
||||
}
|
||||
406
example/ansi-viewer/singlebyte.js
Normal file
@ -0,0 +1,406 @@
|
||||
/**
|
||||
* node-singlebyte
|
||||
*/
|
||||
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2013, Sergey Sokoloff (aka Mithgol the Webmaster).
|
||||
// https://github.com/Mithgol/node-singlebyte
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var extend = function(target) {
|
||||
target = target || {};
|
||||
Array.prototype.slice.call(arguments, 1).forEach(function(obj) {
|
||||
Object.keys(obj || {}).forEach(function(key) {
|
||||
target[key] = obj[key];
|
||||
});
|
||||
});
|
||||
return target;
|
||||
};
|
||||
|
||||
var singlebyte = function(){
|
||||
/* jshint indent: false */
|
||||
if(!( this instanceof singlebyte )){
|
||||
return new singlebyte();
|
||||
}
|
||||
|
||||
this.encodings = [];
|
||||
|
||||
// CP437
|
||||
this.learnEncoding('cp437', this.extendASCII([
|
||||
0xC7, 0xFC, 0xE9, 0xE2, 0xE4, 0xE0, 0xE5, 0xE7,
|
||||
0xEA, 0xEB, 0xE8, 0xEF, 0xEE, 0xEC, 0xC4, 0xC5,
|
||||
0xC9, 0xE6, 0xC6, 0xF4, 0xF6, 0xF2, 0xFB, 0xF9,
|
||||
0xFF, 0xD6, 0xDC, 0xA2, 0xA3, 0xA5, 0x20A7, 0x192,
|
||||
0xE1, 0xED, 0xF3, 0xFA, 0xF1, 0xD1, 0xAA, 0xBA,
|
||||
0xBF, 0x2310, 0xAC, 0xBD, 0xBC, 0xA1, 0xAB, 0xBB,
|
||||
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
|
||||
0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
|
||||
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F,
|
||||
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
|
||||
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B,
|
||||
0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
|
||||
0x3B1, 0x3B2, 0x393, 0x3C0, 0x3A3, 0x3C3, 0x3BC, 0x3C4,
|
||||
0x3A6, 0x398, 0x3A9, 0x3B4, 0x221E, 0x3C6, 0x3B5, 0x2229,
|
||||
0x2261, 0xB1, 0x2265, 0x2264, 0x2320, 0x2321, 0xF7, 0x2248,
|
||||
0xB0, 0x2219, 0xB7, 0x221A, 0x207F, 0xB2, 0x25A0, 0xA0
|
||||
]));
|
||||
|
||||
// CP850
|
||||
this.learnEncoding('cp850', this.extendASCII([
|
||||
0xC7, 0xFC, 0xE9, 0xE2, 0xE4, 0xE0, 0xE5, 0xE7,
|
||||
0xEA, 0xEB, 0xE8, 0xEF, 0xEE, 0xEC, 0xC4, 0xC5,
|
||||
0xC9, 0xE6, 0xC6, 0xF4, 0xF6, 0xF2, 0xFB, 0xF9,
|
||||
0xFF, 0xD6, 0xDC, 0xF8, 0xA3, 0xD8, 0xD7, 0x192,
|
||||
0xE1, 0xED, 0xF3, 0xFA, 0xF1, 0xD1, 0xAA, 0xBA,
|
||||
0xBF, 0xAE, 0xAC, 0xBD, 0xBC, 0xA1, 0xAB, 0xBB,
|
||||
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0xC1, 0xC2, 0xC0,
|
||||
0xA9, 0x2563, 0x2551, 0x2557, 0x255D, 0xA2, 0xA5, 0x2510,
|
||||
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0xE3, 0xC3,
|
||||
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0xA4,
|
||||
0xF0, 0xD0, 0xCA, 0xCB, 0xC8, 0x131, 0xCD, 0xCE,
|
||||
0xCF, 0x2518, 0x250C, 0x2588, 0x2584, 0xA6, 0xCC, 0x2580,
|
||||
0xD3, 0xDF, 0xD4, 0xD2, 0xF5, 0xD5, 0xB5, 0xFE,
|
||||
0xDE, 0xDA, 0xDB, 0xD9, 0xFD, 0xDD, 0xAF, 0xB4,
|
||||
0xAD, 0xB1, 0x2017, 0xBE, 0xB6, 0xA7, 0xF7, 0xB8,
|
||||
0xB0, 0xA8, 0xB7, 0xB9, 0xB3, 0xB2, 0x25A0, 0xA0
|
||||
]));
|
||||
|
||||
// CP858
|
||||
this.learnEncoding('cp858', this.extendASCII([
|
||||
0xC7, 0xFC, 0xE9, 0xE2, 0xE4, 0xE0, 0xE5, 0xE7,
|
||||
0xEA, 0xEB, 0xE8, 0xEF, 0xEE, 0xEC, 0xC4, 0xC5,
|
||||
0xC9, 0xE6, 0xC6, 0xF4, 0xF6, 0xF2, 0xFB, 0xF9,
|
||||
0xFF, 0xD6, 0xDC, 0xF8, 0xA3, 0xD8, 0xD7, 0x192,
|
||||
0xE1, 0xED, 0xF3, 0xFA, 0xF1, 0xD1, 0xAA, 0xBA,
|
||||
0xBF, 0xAE, 0xAC, 0xBD, 0xBC, 0xA1, 0xAB, 0xBB,
|
||||
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0xC1, 0xC2, 0xC0,
|
||||
0xA9, 0x2563, 0x2551, 0x2557, 0x255D, 0xA2, 0xA5, 0x2510,
|
||||
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0xE3, 0xC3,
|
||||
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0xA4,
|
||||
0xF0, 0xD0, 0xCA, 0xCB, 0xC8, 0x20AC, 0xCD, 0xCE,
|
||||
0xCF, 0x2518, 0x250C, 0x2588, 0x2584, 0xA6, 0xCC, 0x2580,
|
||||
0xD3, 0xDF, 0xD4, 0xD2, 0xF5, 0xD5, 0xB5, 0xFE,
|
||||
0xDE, 0xDA, 0xDB, 0xD9, 0xFD, 0xDD, 0xAF, 0xB4,
|
||||
0xAD, 0xB1, 0x2017, 0xBE, 0xB6, 0xA7, 0xF7, 0xB8,
|
||||
0xB0, 0xA8, 0xB7, 0xB9, 0xB3, 0xB2, 0x25A0, 0xA0
|
||||
]));
|
||||
|
||||
// CP808
|
||||
this.learnEncoding('cp808', this.extendASCII([
|
||||
0x410, 0x411, 0x412, 0x413, 0x414, 0x415, 0x416, 0x417,
|
||||
0x418, 0x419, 0x41A, 0x41B, 0x41C, 0x41D, 0x41E, 0x41F,
|
||||
0x420, 0x421, 0x422, 0x423, 0x424, 0x425, 0x426, 0x427,
|
||||
0x428, 0x429, 0x42A, 0x42B, 0x42C, 0x42D, 0x42E, 0x42F,
|
||||
0x430, 0x431, 0x432, 0x433, 0x434, 0x435, 0x436, 0x437,
|
||||
0x438, 0x439, 0x43A, 0x43B, 0x43C, 0x43D, 0x43E, 0x43F,
|
||||
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
|
||||
0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
|
||||
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F,
|
||||
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
|
||||
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B,
|
||||
0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
|
||||
0x440, 0x441, 0x442, 0x443, 0x444, 0x445, 0x446, 0x447,
|
||||
0x448, 0x449, 0x44A, 0x44B, 0x44C, 0x44D, 0x44E, 0x44F,
|
||||
0x401, 0x451, 0x404, 0x454, 0x407, 0x457, 0x40E, 0x45E,
|
||||
0xB0, 0x2219, 0xB7, 0x221A, 0x2116, 0x20AC, 0x25A0, 0xA0
|
||||
]));
|
||||
|
||||
// CP866
|
||||
this.learnEncoding('cp866', this.extendASCII([
|
||||
0x410, 0x411, 0x412, 0x413, 0x414, 0x415, 0x416, 0x417,
|
||||
0x418, 0x419, 0x41A, 0x41B, 0x41C, 0x41D, 0x41E, 0x41F,
|
||||
0x420, 0x421, 0x422, 0x423, 0x424, 0x425, 0x426, 0x427,
|
||||
0x428, 0x429, 0x42A, 0x42B, 0x42C, 0x42D, 0x42E, 0x42F,
|
||||
0x430, 0x431, 0x432, 0x433, 0x434, 0x435, 0x436, 0x437,
|
||||
0x438, 0x439, 0x43A, 0x43B, 0x43C, 0x43D, 0x43E, 0x43F,
|
||||
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
|
||||
0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
|
||||
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F,
|
||||
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
|
||||
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B,
|
||||
0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
|
||||
0x440, 0x441, 0x442, 0x443, 0x444, 0x445, 0x446, 0x447,
|
||||
0x448, 0x449, 0x44A, 0x44B, 0x44C, 0x44D, 0x44E, 0x44F,
|
||||
0x401, 0x451, 0x404, 0x454, 0x407, 0x457, 0x40E, 0x45E,
|
||||
0xB0, 0x2219, 0xB7, 0x221A, 0x2116, 0xA4, 0x25A0, 0xA0
|
||||
]));
|
||||
|
||||
// CP1125
|
||||
this.learnEncoding('cp1125', this.extendASCII([
|
||||
0x410, 0x411, 0x412, 0x413, 0x414, 0x415, 0x416, 0x417,
|
||||
0x418, 0x419, 0x41A, 0x41B, 0x41C, 0x41D, 0x41E, 0x41F,
|
||||
0x420, 0x421, 0x422, 0x423, 0x424, 0x425, 0x426, 0x427,
|
||||
0x428, 0x429, 0x42A, 0x42B, 0x42C, 0x42D, 0x42E, 0x42F,
|
||||
0x430, 0x431, 0x432, 0x433, 0x434, 0x435, 0x436, 0x437,
|
||||
0x438, 0x439, 0x43A, 0x43B, 0x43C, 0x43D, 0x43E, 0x43F,
|
||||
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
|
||||
0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
|
||||
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F,
|
||||
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
|
||||
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B,
|
||||
0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
|
||||
0x440, 0x441, 0x442, 0x443, 0x444, 0x445, 0x446, 0x447,
|
||||
0x448, 0x449, 0x44A, 0x44B, 0x44C, 0x44D, 0x44E, 0x44F,
|
||||
0x401, 0x451, 0x490, 0x491, 0x404, 0x454, 0x406, 0x456,
|
||||
0x407, 0x457, 0xB7, 0x221A, 0x2116, 0xA4, 0x25A0, 0xA0
|
||||
]));
|
||||
|
||||
// KOI8-R
|
||||
this.learnEncoding('koi8-r', this.extendASCII([
|
||||
0x2500, 0x2502, 0x250C, 0x2510, 0x2514, 0x2518, 0x251C, 0x2524,
|
||||
0x252C, 0x2534, 0x253C, 0x2580, 0x2584, 0x2588, 0x258C, 0x2590,
|
||||
0x2591, 0x2592, 0x2593, 0x2320, 0x25A0, 0x2219, 0x221A, 0x2248,
|
||||
0x2264, 0x2265, 0xA0, 0x2321, 0xB0, 0xB2, 0xB7, 0xF7,
|
||||
0x2550, 0x2551, 0x2552, 0x451, 0x2553, 0x2554, 0x2555, 0x2556,
|
||||
0x2557, 0x2558, 0x2559, 0x255A, 0x255B, 0x255C, 0x255D, 0x255E,
|
||||
0x255F, 0x2560, 0x2561, 0x401, 0x2562, 0x2563, 0x2564, 0x2565,
|
||||
0x2566, 0x2567, 0x2568, 0x2569, 0x256A, 0x256B, 0x256C, 0xA9,
|
||||
0x44E, 0x430, 0x431, 0x446, 0x434, 0x435, 0x444, 0x433,
|
||||
0x445, 0x438, 0x439, 0x43A, 0x43B, 0x43C, 0x43D, 0x043E,
|
||||
0x43F, 0x44F, 0x440, 0x441, 0x442, 0x443, 0x436, 0x432,
|
||||
0x44C, 0x44B, 0x437, 0x448, 0x44D, 0x449, 0x447, 0x44A,
|
||||
0x42E, 0x410, 0x411, 0x426, 0x414, 0x415, 0x424, 0x413,
|
||||
0x425, 0x418, 0x419, 0x41A, 0x41B, 0x41C, 0x41D, 0x41E,
|
||||
0x41F, 0x42F, 0x420, 0x421, 0x422, 0x423, 0x416, 0x412,
|
||||
0x42C, 0x42B, 0x417, 0x428, 0x42D, 0x429, 0x427, 0x42A
|
||||
]));
|
||||
|
||||
// KOI8-U
|
||||
this.learnEncoding('koi8-u', this.extendASCII([
|
||||
0x2500, 0x2502, 0x250C, 0x2510, 0x2514, 0x2518, 0x251C, 0x2524,
|
||||
0x252C, 0x2534, 0x253C, 0x2580, 0x2584, 0x2588, 0x258C, 0x2590,
|
||||
0x2591, 0x2592, 0x2593, 0x2320, 0x25A0, 0x2219, 0x221A, 0x2248,
|
||||
0x2264, 0x2265, 0xA0, 0x2321, 0xB0, 0xB2, 0xB7, 0xF7,
|
||||
0x2550, 0x2551, 0x2552, 0x451, 0x454, 0x2554, 0x456, 0x457,
|
||||
0x2557, 0x2558, 0x2559, 0x255A, 0x255B, 0x491, 0x255D, 0x255E,
|
||||
0x255F, 0x2560, 0x2561, 0x401, 0x404, 0x2563, 0x406, 0x407,
|
||||
0x2566, 0x2567, 0x2568, 0x2569, 0x256A, 0x490, 0x256C, 0xA9,
|
||||
0x44E, 0x430, 0x431, 0x446, 0x434, 0x435, 0x444, 0x433,
|
||||
0x445, 0x438, 0x439, 0x43A, 0x43B, 0x43C, 0x43D, 0x043E,
|
||||
0x43F, 0x44F, 0x440, 0x441, 0x442, 0x443, 0x436, 0x432,
|
||||
0x44C, 0x44B, 0x437, 0x448, 0x44D, 0x449, 0x447, 0x44A,
|
||||
0x42E, 0x410, 0x411, 0x426, 0x414, 0x415, 0x424, 0x413,
|
||||
0x425, 0x418, 0x419, 0x41A, 0x41B, 0x41C, 0x41D, 0x41E,
|
||||
0x41F, 0x42F, 0x420, 0x421, 0x422, 0x423, 0x416, 0x412,
|
||||
0x42C, 0x42B, 0x417, 0x428, 0x42D, 0x429, 0x427, 0x42A
|
||||
]));
|
||||
|
||||
// KOI8-RU
|
||||
this.learnEncoding('koi8-ru', this.extendASCII([
|
||||
0x2500, 0x2502, 0x250C, 0x2510, 0x2514, 0x2518, 0x251C, 0x2524,
|
||||
0x252C, 0x2534, 0x253C, 0x2580, 0x2584, 0x2588, 0x258C, 0x2590,
|
||||
0x2591, 0x2592, 0x2593, 0x2320, 0x25A0, 0x2219, 0x221A, 0x2248,
|
||||
0x2264, 0x2265, 0xA0, 0x2321, 0xB0, 0xB2, 0xB7, 0xF7,
|
||||
0x2550, 0x2551, 0x2552, 0x451, 0x454, 0x2554, 0x456, 0x457,
|
||||
0x2557, 0x2558, 0x2559, 0x255A, 0x255B, 0x491, 0x45E, 0x255E,
|
||||
0x255F, 0x2560, 0x2561, 0x401, 0x404, 0x2563, 0x406, 0x407,
|
||||
0x2566, 0x2567, 0x2568, 0x2569, 0x256A, 0x490, 0x40E, 0xA9,
|
||||
0x44E, 0x430, 0x431, 0x446, 0x434, 0x435, 0x444, 0x433,
|
||||
0x445, 0x438, 0x439, 0x43A, 0x43B, 0x43C, 0x43D, 0x043E,
|
||||
0x43F, 0x44F, 0x440, 0x441, 0x442, 0x443, 0x436, 0x432,
|
||||
0x44C, 0x44B, 0x437, 0x448, 0x44D, 0x449, 0x447, 0x44A,
|
||||
0x42E, 0x410, 0x411, 0x426, 0x414, 0x415, 0x424, 0x413,
|
||||
0x425, 0x418, 0x419, 0x41A, 0x41B, 0x41C, 0x41D, 0x41E,
|
||||
0x41F, 0x42F, 0x420, 0x421, 0x422, 0x423, 0x416, 0x412,
|
||||
0x42C, 0x42B, 0x417, 0x428, 0x42D, 0x429, 0x427, 0x42A
|
||||
]));
|
||||
|
||||
// LATIN-1 aka ISO 8859-1 (Western European)
|
||||
this.learnEncoding('latin-1', this.extendASCII([
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
|
||||
0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
|
||||
0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
|
||||
0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
|
||||
0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
|
||||
0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7,
|
||||
0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
|
||||
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
|
||||
0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
|
||||
0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7,
|
||||
0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
|
||||
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
|
||||
0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
|
||||
0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
|
||||
]));
|
||||
|
||||
// Windows-1252
|
||||
this.learnEncoding('cp1252', this.extendASCII([
|
||||
0x20AC, 0x81, 0x201A, 0x192, 0x201E, 0x2026, 0x2020, 0x2021,
|
||||
0x2C6, 0x2030, 0x160, 0x2039, 0x152, 0x8D, 0x017D, 0x8F,
|
||||
0x90, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
|
||||
0x02DC, 0x2122, 0x161, 0x203A, 0x0153, 0x9D, 0x17E, 0x178,
|
||||
0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
|
||||
0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
|
||||
0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7,
|
||||
0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
|
||||
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
|
||||
0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
|
||||
0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7,
|
||||
0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
|
||||
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
|
||||
0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
|
||||
0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
|
||||
]));
|
||||
};
|
||||
|
||||
singlebyte.prototype.isEncoding = function(encodingName){
|
||||
if( Buffer.isEncoding(encodingName) ) return true;
|
||||
for( var i = 0; i < this.encodings.length; i++ ){
|
||||
if( this.encodings[i].name === encodingName ) return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
singlebyte.prototype.learnEncoding = function(encodingName, encodingTable){
|
||||
/*jshint bitwise: false */
|
||||
if( Buffer.isEncoding(encodingName) ){
|
||||
throw new Error(this.errors.BUFFER_ENCODING);
|
||||
}
|
||||
|
||||
if( encodingTable.length !== 256 ){
|
||||
throw new Error(this.errors.INVALID_TABLE_LENGTH);
|
||||
}
|
||||
|
||||
var _this = this;
|
||||
encodingTable = encodingTable.map(function(item){
|
||||
var nextCode = item |0;
|
||||
if( 0 > nextCode || nextCode > 0x10FFFF ){
|
||||
throw new Error(_this.errors.OUT_OF_UNICODE);
|
||||
}
|
||||
return item;
|
||||
});
|
||||
|
||||
if( this.isEncoding(encodingName) ){
|
||||
for( var i = 0; i < this.encodings.length; i++ ){
|
||||
if( this.encodings[i].name === encodingName ){
|
||||
this.encodings[i].table = encodingTable;
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.encodings.push({
|
||||
name: encodingName,
|
||||
table: encodingTable
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
singlebyte.prototype.getEncodingTable = function(encodingName){
|
||||
for( var i = 0; i < this.encodings.length; i++ ){
|
||||
if( this.encodings[i].name === encodingName ){
|
||||
return this.encodings[i].table;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
singlebyte.prototype.extendASCII = function(extensionTable){
|
||||
if( extensionTable.length !== 128 ){
|
||||
throw new Error(this.errors.INVALID_EXTENSION);
|
||||
}
|
||||
|
||||
var output = [];
|
||||
for( var i = 0; i < 128; i++ ) output.push(i);
|
||||
return output.concat(extensionTable);
|
||||
};
|
||||
|
||||
singlebyte.prototype.bufToStr = function(buf, encoding, start, end){
|
||||
/* jshint bitwise: false */
|
||||
if(!( Buffer.isBuffer(buf) )){
|
||||
throw new Error(this.errors.NOT_A_BUFFER);
|
||||
}
|
||||
if( Buffer.isEncoding(encoding) ){
|
||||
return buf.toString(encoding, start, end);
|
||||
}
|
||||
var table = this.getEncodingTable(encoding);
|
||||
if( table === null ) throw new Error(this.errors.UNKNOWN_ENCODING);
|
||||
|
||||
if( typeof end === 'undefined' ) end = buf.length;
|
||||
if( typeof start === 'undefined' ) start = 0;
|
||||
|
||||
var output = '';
|
||||
var sourceValue;
|
||||
for( var i = start; i < end; i++ ){
|
||||
sourceValue = table[ buf[i] ];
|
||||
if( sourceValue <= 0xFFFF ){
|
||||
output += String.fromCharCode(sourceValue);
|
||||
} else if( 0x10000 <= sourceValue && sourceValue <= 0x10FFFF ){
|
||||
sourceValue -= 0x10000;
|
||||
output += String.fromCharCode( 0xD800 + (sourceValue >> 10) );
|
||||
output += String.fromCharCode( 0xDC00 + (sourceValue & 0x3FF) );
|
||||
} else throw new Error(this.errors.OUT_OF_UNICODE);
|
||||
}
|
||||
return output;
|
||||
};
|
||||
|
||||
var strToBufDefaults = {
|
||||
defaultCode: 0x3F // '?'
|
||||
};
|
||||
|
||||
singlebyte.prototype.strToBuf = function(str, encoding, encodingOptions){
|
||||
if( Buffer.isEncoding(encoding) ){
|
||||
return new Buffer(str, encoding);
|
||||
}
|
||||
str = '' + str;
|
||||
var options = extend({}, strToBufDefaults, encodingOptions);
|
||||
var table = this.getEncodingTable(encoding);
|
||||
if( table === null ) throw new Error(this.errors.UNKNOWN_ENCODING);
|
||||
var output = [];
|
||||
for( var i = 0; i < str.length; i++ ){
|
||||
var charUnicode;
|
||||
var thisCharCode = str.charCodeAt(i);
|
||||
if( 0xD800 <= thisCharCode && thisCharCode <= 0xDBFF &&
|
||||
i+1 < str.length
|
||||
){
|
||||
var nextCharCode = str.charCodeAt(i+1);
|
||||
if( 0xDC00 <= nextCharCode && nextCharCode <= 0xDFFF ){
|
||||
charUnicode = 0x10000 + (thisCharCode - 0xD800)*0x400 +
|
||||
(nextCharCode - 0xDC00);
|
||||
i++;
|
||||
} else {
|
||||
charUnicode = thisCharCode;
|
||||
}
|
||||
} else {
|
||||
charUnicode = thisCharCode;
|
||||
}
|
||||
|
||||
var codeFoundIndex = table.indexOf(charUnicode);
|
||||
if( codeFoundIndex < 0 ){
|
||||
output.push(options.defaultCode);
|
||||
} else {
|
||||
output.push(codeFoundIndex);
|
||||
}
|
||||
}
|
||||
return new Buffer(output);
|
||||
};
|
||||
|
||||
singlebyte.prototype.errors = {
|
||||
NOT_A_BUFFER : 'The given source is not a buffer!',
|
||||
UNKNOWN_ENCODING : 'The given encoding is not defined!',
|
||||
INVALID_TABLE_LENGTH : 'The encoding table must have 256 elements!',
|
||||
INVALID_EXTENSION : 'The ASCII extension table must have 128 elements!',
|
||||
BUFFER_ENCODING : "Cannot redefine a Node's encoding!",
|
||||
OUT_OF_UNICODE : "An encoding table's element is greater than 0x10FFFF!"
|
||||
};
|
||||
|
||||
module.exports = singlebyte();
|
||||
99
example/blessed-telnet.js
Executable file
@ -0,0 +1,99 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* blessed-telnet.js
|
||||
* https://github.com/chjj/blessed
|
||||
* Copyright (c) 2013-2015, Christopher Jeffrey (MIT License)
|
||||
* A blessed telnet server.
|
||||
* See: https://github.com/TooTallNate/node-telnet
|
||||
*/
|
||||
|
||||
process.title = 'blessed-telnet';
|
||||
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var blessed = require('blessed');
|
||||
var telnet = require('telnet2');
|
||||
|
||||
var server = telnet({ tty: true }, function(client) {
|
||||
client.on('debug', function(msg) {
|
||||
console.error(msg);
|
||||
});
|
||||
|
||||
client.on('term', function(terminal) {
|
||||
screen.terminal = terminal;
|
||||
screen.render();
|
||||
});
|
||||
|
||||
client.on('size', function(width, height) {
|
||||
client.columns = width;
|
||||
client.rows = height;
|
||||
client.emit('resize');
|
||||
});
|
||||
|
||||
var screen = blessed.screen({
|
||||
smartCSR: true,
|
||||
input: client,
|
||||
output: client,
|
||||
terminal: 'xterm-256color',
|
||||
fullUnicode: true
|
||||
});
|
||||
|
||||
client.on('close', function() {
|
||||
if (!screen.destroyed) {
|
||||
screen.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
screen.on('destroy', function() {
|
||||
if (client.writable) {
|
||||
client.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
if (test === 'widget-simple') {
|
||||
return simpleTest(screen);
|
||||
}
|
||||
|
||||
loadTest(screen, test);
|
||||
});
|
||||
|
||||
function simpleTest(screen) {
|
||||
screen.data.main = blessed.box({
|
||||
parent: screen,
|
||||
width: '80%',
|
||||
height: '90%',
|
||||
border: 'line',
|
||||
content: 'Welcome to my server. Here is your own private session.',
|
||||
style: {
|
||||
bg: 'red'
|
||||
}
|
||||
});
|
||||
|
||||
screen.key('i', function() {
|
||||
screen.data.main.style.bg = 'blue';
|
||||
screen.render();
|
||||
});
|
||||
|
||||
screen.key(['C-c', 'q'], function(ch, key) {
|
||||
screen.destroy();
|
||||
});
|
||||
|
||||
screen.render();
|
||||
}
|
||||
|
||||
var test = process.argv[2] || path.resolve(__dirname, '../test/widget-shadow.js');
|
||||
if (~test.indexOf('widget-png.js')) process.argv.length = 2;
|
||||
test = path.resolve(process.cwd(), test);
|
||||
|
||||
function loadTest(screen, name) {
|
||||
var Screen = blessed.screen;
|
||||
blessed.screen = function() { return screen; };
|
||||
var path = require.resolve(name);
|
||||
delete require.cache[path];
|
||||
require(name);
|
||||
blessed.screen = Screen;
|
||||
}
|
||||
|
||||
server.listen(2300);
|
||||
console.log('Listening on 2300...');
|
||||
77
example/index.js
Normal file
@ -0,0 +1,77 @@
|
||||
/**
|
||||
* Example Program for Blessed
|
||||
* Copyright (c) 2013, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
var blessed = require('../')
|
||||
, program = blessed.program();
|
||||
|
||||
process.title = 'blessed';
|
||||
|
||||
program.on('keypress', function(ch, key) {
|
||||
if (key.name === 'q') {
|
||||
program.clear();
|
||||
program.disableMouse();
|
||||
program.showCursor();
|
||||
program.normalBuffer();
|
||||
process.exit(0);
|
||||
}
|
||||
});
|
||||
|
||||
program.on('mouse', function(data) {
|
||||
if (data.action === 'mouseup') return;
|
||||
program.move(1, program.rows);
|
||||
program.eraseInLine('right');
|
||||
if (data.action === 'wheelup') {
|
||||
program.write('Mouse wheel up at: ' + data.x + ', ' + data.y);
|
||||
} else if (data.action === 'wheeldown') {
|
||||
program.write('Mouse wheel down at: ' + data.x + ', ' + data.y);
|
||||
} else if (data.action === 'mousedown' && data.button === 'left') {
|
||||
program.write('Left button down at: ' + data.x + ', ' + data.y);
|
||||
} else if (data.action === 'mousedown' && data.button === 'right') {
|
||||
program.write('Right button down at: ' + data.x + ', ' + data.y);
|
||||
} else {
|
||||
program.write('Mouse at: ' + data.x + ', ' + data.y);
|
||||
}
|
||||
program.move(data.x, data.y);
|
||||
program.bg('red');
|
||||
program.write(' ');
|
||||
program.bg('!red');
|
||||
});
|
||||
|
||||
program.on('focus', function() {
|
||||
program.move(1, program.rows);
|
||||
program.write('Gained focus.');
|
||||
});
|
||||
|
||||
program.on('blur', function() {
|
||||
program.move(1, program.rows);
|
||||
program.write('Lost focus.');
|
||||
});
|
||||
|
||||
program.alternateBuffer();
|
||||
program.enableMouse();
|
||||
program.hideCursor();
|
||||
program.clear();
|
||||
|
||||
program.move(1, 1);
|
||||
program.bg('black');
|
||||
program.write('Hello world', 'blue fg');
|
||||
program.setx((program.cols / 2 | 0) - 4);
|
||||
program.down(5);
|
||||
program.write('Hi again!');
|
||||
program.bg('!black');
|
||||
program.feed();
|
||||
|
||||
program.getCursor(function(err, data) {
|
||||
if (!err) {
|
||||
program.write('Cursor is at: ' + data.x + ', ' + data.y + '.');
|
||||
program.feed();
|
||||
}
|
||||
|
||||
program.charset('SCLD');
|
||||
program.write('abcdefghijklmnopqrstuvwxyz0123456789');
|
||||
program.charset('US');
|
||||
program.setx(1);
|
||||
});
|
||||
142
example/multiplex.js
Executable file
@ -0,0 +1,142 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* multiplex.js
|
||||
* https://github.com/chjj/blessed
|
||||
* Copyright (c) 2013-2015, Christopher Jeffrey (MIT License)
|
||||
* A terminal multiplexer created by blessed.
|
||||
*/
|
||||
|
||||
process.title = 'multiplex.js';
|
||||
|
||||
var blessed = require('blessed')
|
||||
, screen;
|
||||
|
||||
screen = blessed.screen({
|
||||
smartCSR: true,
|
||||
log: process.env.HOME + '/blessed-terminal.log',
|
||||
fullUnicode: true,
|
||||
dockBorders: true,
|
||||
ignoreDockContrast: true
|
||||
});
|
||||
|
||||
var topleft = blessed.terminal({
|
||||
parent: screen,
|
||||
cursor: 'line',
|
||||
cursorBlink: true,
|
||||
screenKeys: false,
|
||||
label: ' multiplex.js ',
|
||||
left: 0,
|
||||
top: 0,
|
||||
width: '50%',
|
||||
height: '50%',
|
||||
border: 'line',
|
||||
style: {
|
||||
fg: 'default',
|
||||
bg: 'default',
|
||||
focus: {
|
||||
border: {
|
||||
fg: 'green'
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
topleft.pty.on('data', function(data) {
|
||||
screen.log(JSON.stringify(data));
|
||||
});
|
||||
|
||||
var topright = blessed.terminal({
|
||||
parent: screen,
|
||||
cursor: 'block',
|
||||
cursorBlink: true,
|
||||
screenKeys: false,
|
||||
label: ' multiplex.js ',
|
||||
left: '50%-1',
|
||||
top: 0,
|
||||
width: '50%+1',
|
||||
height: '50%',
|
||||
border: 'line',
|
||||
style: {
|
||||
fg: 'red',
|
||||
bg: 'black',
|
||||
focus: {
|
||||
border: {
|
||||
fg: 'green'
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var bottomleft = blessed.terminal({
|
||||
parent: screen,
|
||||
cursor: 'block',
|
||||
cursorBlink: true,
|
||||
screenKeys: false,
|
||||
label: ' multiplex.js ',
|
||||
left: 0,
|
||||
top: '50%-1',
|
||||
width: '50%',
|
||||
height: '50%+1',
|
||||
border: 'line',
|
||||
style: {
|
||||
fg: 'default',
|
||||
bg: 'default',
|
||||
focus: {
|
||||
border: {
|
||||
fg: 'green'
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var bottomright = blessed.terminal({
|
||||
parent: screen,
|
||||
cursor: 'block',
|
||||
cursorBlink: true,
|
||||
screenKeys: false,
|
||||
label: ' multiplex.js ',
|
||||
left: '50%-1',
|
||||
top: '50%-1',
|
||||
width: '50%+1',
|
||||
height: '50%+1',
|
||||
border: 'line',
|
||||
style: {
|
||||
fg: 'default',
|
||||
bg: 'default',
|
||||
focus: {
|
||||
border: {
|
||||
fg: 'green'
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
[topleft, topright, bottomleft, bottomright].forEach(function(term) {
|
||||
term.enableDrag(function(mouse) {
|
||||
return !!mouse.ctrl;
|
||||
});
|
||||
term.on('title', function(title) {
|
||||
screen.title = title;
|
||||
term.setLabel(' ' + title + ' ');
|
||||
screen.render();
|
||||
});
|
||||
term.on('click', term.focus.bind(term));
|
||||
});
|
||||
|
||||
topleft.focus();
|
||||
|
||||
screen.key('C-q', function() {
|
||||
topleft.kill();
|
||||
topright.kill();
|
||||
bottomleft.kill();
|
||||
bottomright.kill();
|
||||
return screen.destroy();
|
||||
});
|
||||
|
||||
screen.program.key('S-tab', function() {
|
||||
screen.focusNext();
|
||||
screen.render();
|
||||
});
|
||||
|
||||
screen.render();
|
||||
448
example/ping
Executable file
@ -0,0 +1,448 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* ping
|
||||
* https://github.com/chjj/blessed
|
||||
* Copyright (c) 2013, Christopher Jeffrey (MIT License)
|
||||
* Online (ping)pong in your terminal.
|
||||
*/
|
||||
|
||||
// Example Usage:
|
||||
// Server: $ ./example/ping 3000
|
||||
// Client: $ ./example/ping 127.0.0.1 3000
|
||||
// Demo: $ ./example/ping
|
||||
|
||||
process.title = 'ping';
|
||||
|
||||
if (/^(-h|--help|-\?)$/.test(process.argv[2])) {
|
||||
console.log('node-ping');
|
||||
console.log('Example Usage:');
|
||||
console.log('Server: $ node-ping 3000');
|
||||
console.log('Client: $ node-ping 127.0.0.1 3000');
|
||||
console.log('Demo: $ node-ping');
|
||||
return process.exit(0);
|
||||
}
|
||||
|
||||
var blessed = require('blessed')
|
||||
, nssocket;
|
||||
|
||||
try {
|
||||
nssocket = require('nssocket');
|
||||
} catch (e) {
|
||||
;
|
||||
}
|
||||
|
||||
var server
|
||||
, socket;
|
||||
|
||||
/**
|
||||
* Screen Layout
|
||||
*/
|
||||
|
||||
var screen = blessed.screen();
|
||||
|
||||
var table = blessed.box({
|
||||
left: 0,
|
||||
top: 0,
|
||||
width: screen.width,
|
||||
height: screen.height
|
||||
});
|
||||
|
||||
var ball = blessed.box({
|
||||
width: 1,
|
||||
height: 1,
|
||||
bg: 'white',
|
||||
top: 0,
|
||||
left: 0
|
||||
});
|
||||
|
||||
var lpaddle = blessed.box({
|
||||
width: 1,
|
||||
height: 3,
|
||||
bg: 'yellow',
|
||||
top: 0,
|
||||
left: 0
|
||||
});
|
||||
|
||||
var rpaddle = blessed.box({
|
||||
width: 1,
|
||||
height: 3,
|
||||
bg: 'yellow',
|
||||
top: 0,
|
||||
right: 0
|
||||
});
|
||||
|
||||
var score = blessed.box({
|
||||
top: 0,
|
||||
left: 4,
|
||||
height: 3,
|
||||
width: 'shrink',
|
||||
border: {
|
||||
type: 'line'
|
||||
},
|
||||
//align: 'center',
|
||||
style: {
|
||||
bold: true
|
||||
},
|
||||
tags: true
|
||||
});
|
||||
|
||||
score.lwins = 0;
|
||||
score.rwins = 0;
|
||||
|
||||
var net = blessed.box({
|
||||
width: 1,
|
||||
height: '100%',
|
||||
bg: 'yellow',
|
||||
top: 0,
|
||||
left: 'center'
|
||||
});
|
||||
|
||||
var message = blessed.box({
|
||||
width: '50%',
|
||||
height: 3,
|
||||
border: {
|
||||
type: 'line'
|
||||
},
|
||||
top: 'center',
|
||||
left: 'center'
|
||||
});
|
||||
|
||||
var text = blessed.box({
|
||||
top: 'center',
|
||||
left: 1,
|
||||
right: 1,
|
||||
height: 1,
|
||||
align: 'center',
|
||||
content: 'Waiting for players to connect...'
|
||||
});
|
||||
|
||||
message.append(text);
|
||||
|
||||
screen.append(table);
|
||||
|
||||
table.append(score);
|
||||
table.append(lpaddle);
|
||||
table.append(rpaddle);
|
||||
table.append(net);
|
||||
table.append(ball);
|
||||
table.append(message);
|
||||
|
||||
screen.on('resize', function() {
|
||||
table.width = screen.width;
|
||||
table.height = screen.height;
|
||||
[ball, lpaddle, rpaddle].forEach(function(el) {
|
||||
if (el.rbottom < 0) el.rtop = table.height - 1 - el.height;
|
||||
if (el.rright < 0) el.rleft = table.width - 1;
|
||||
});
|
||||
screen.render();
|
||||
sync();
|
||||
});
|
||||
|
||||
/**
|
||||
* Options
|
||||
*/
|
||||
|
||||
ball.speed = 2;
|
||||
ball.unpredictable = true;
|
||||
lpaddle.speed = 2;
|
||||
rpaddle.speed = 2;
|
||||
|
||||
/**
|
||||
* Game
|
||||
*/
|
||||
|
||||
function sync() {
|
||||
if (!socket) return;
|
||||
socket.send(['update'], {
|
||||
table: { width: table.width, height: table.height },
|
||||
lpaddle: { rleft: lpaddle.rleft, rtop: lpaddle.rtop, speed: lpaddle.speed },
|
||||
rpaddle: { rleft: rpaddle.rleft, rtop: rpaddle.rtop, speed: rpaddle.speed },
|
||||
score: { lwins: score.lwins, rwins: score.rwins }
|
||||
});
|
||||
}
|
||||
|
||||
function reset() {
|
||||
text.setContent('Waiting for players to connect...');
|
||||
message.hide();
|
||||
ball.moving = true;
|
||||
ball.direction = 'right';
|
||||
ball.angle = 'down';
|
||||
ball.rtop = 1;
|
||||
ball.rleft = 1;
|
||||
if ((score.lwins + score.rwins) % 2 !== 0) {
|
||||
ball.direction = 'left';
|
||||
ball.rleft = table.width - 1;
|
||||
}
|
||||
lpaddle.rtop = 0;
|
||||
rpaddle.rtop = 0;
|
||||
|
||||
score.setContent('{green-fg}Score:{/} ' + score.lwins + ' | ' + score.rwins);
|
||||
|
||||
rpaddle.movable = true;
|
||||
|
||||
screen.render();
|
||||
if (server && socket) {
|
||||
socket.send(['reset']);
|
||||
}
|
||||
}
|
||||
|
||||
function rand(min, max) {
|
||||
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||
}
|
||||
|
||||
function startGame() {
|
||||
reset();
|
||||
|
||||
if (startGame._bound) return;
|
||||
startGame._bound = true;
|
||||
|
||||
screen.on('keypress', function(ch, key) {
|
||||
if (!ball.moving) return;
|
||||
if (key.name === 'up' || key.name === 'k') {
|
||||
if (socket) socket.send(['up']);
|
||||
if (lpaddle.rtop > 0) lpaddle.rtop -= lpaddle.speed;
|
||||
if (!socket) if (rpaddle.rtop > 0) rpaddle.rtop -= rpaddle.speed;
|
||||
if (lpaddle.rtop < 0) lpaddle.rtop = 0;
|
||||
if (rpaddle.rtop < 0) rpaddle.rtop = 0;
|
||||
screen.render();
|
||||
} else if (key.name === 'down' || key.name === 'j') {
|
||||
if (socket) socket.send(['down']);
|
||||
if (lpaddle.rbottom > 0) lpaddle.rtop += lpaddle.speed;
|
||||
if (!socket) if (rpaddle.rbottom > 0) rpaddle.rtop += rpaddle.speed;
|
||||
if (lpaddle.rbottom < 0) lpaddle.rtop = table.height - lpaddle.height - 1;
|
||||
if (rpaddle.rbottom < 0) rpaddle.rtop = table.height - rpaddle.height - 1;
|
||||
screen.render();
|
||||
}
|
||||
});
|
||||
|
||||
setInterval(function() {
|
||||
if (!ball.moving) return;
|
||||
if (ball.direction === 'right') {
|
||||
if (ball.rright > 1) {
|
||||
ball.rleft += ball.speed;
|
||||
} else {
|
||||
if (ball.rtop >= rpaddle.rtop && ball.rtop <= rpaddle.rtop + rpaddle.height) {
|
||||
ball.direction = 'left';
|
||||
ball.rleft -= ball.speed;
|
||||
|
||||
ball.rleft -= rand(0, 3);
|
||||
if (ball.angle === 'down') ball.rtop += rand(0, 3);
|
||||
else if (ball.angle === 'up') ball.rtop -= rand(0, 3);
|
||||
} else {
|
||||
// Right loses
|
||||
score.lwins++;
|
||||
ball.rleft = table.width - 1;
|
||||
if (socket) socket.send(['lose']);
|
||||
ball.moving = false;
|
||||
text.setContent('Right player loses!');
|
||||
message.show();
|
||||
setTimeout(reset, 3000);
|
||||
screen.render();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (ball.rright < 1) ball.rleft = table.width - 2;
|
||||
} else if (ball.direction === 'left') {
|
||||
if (ball.rleft > 1) {
|
||||
ball.rleft -= ball.speed;
|
||||
} else {
|
||||
if (ball.rtop >= lpaddle.rtop && ball.rtop <= lpaddle.rtop + lpaddle.height) {
|
||||
ball.direction = 'right';
|
||||
ball.rleft += ball.speed;
|
||||
|
||||
ball.rleft += rand(0, 3);
|
||||
if (ball.angle === 'down') ball.rtop += rand(0, 3);
|
||||
else if (ball.angle === 'up') ball.rtop -= rand(0, 3);
|
||||
} else {
|
||||
// Left loses
|
||||
score.rwins++;
|
||||
ball.rleft = 0;
|
||||
if (socket) socket.send(['win']);
|
||||
ball.moving = false;
|
||||
text.setContent('Left player loses!');
|
||||
message.show();
|
||||
setTimeout(reset, 3000);
|
||||
screen.render();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (ball.rleft < 1) ball.rleft = 1;
|
||||
}
|
||||
if (ball.angle === 'down') {
|
||||
if (ball.rbottom > 0) {
|
||||
ball.rtop++;
|
||||
if (ball.unpredictable) ball.rtop += rand(0, 3);
|
||||
} else {
|
||||
ball.angle = 'up';
|
||||
ball.rtop--;
|
||||
}
|
||||
} else if (ball.angle === 'up') {
|
||||
if (ball.rtop > 0) {
|
||||
ball.rtop--;
|
||||
if (ball.unpredictable) ball.rtop -= rand(0, 3);
|
||||
} else {
|
||||
ball.angle = 'down';
|
||||
ball.rtop++;
|
||||
}
|
||||
}
|
||||
if (ball.rtop < 0) ball.rtop = 0;
|
||||
if (ball.rbottom < 0) ball.rtop = table.height - 1;
|
||||
if (socket) socket.send(['ball'], { rleft: ball.rleft, rtop: ball.rtop });
|
||||
screen.render();
|
||||
}, 100);
|
||||
}
|
||||
|
||||
function startServer() {
|
||||
server = nssocket.createServer({}, function(socket_) {
|
||||
socket = socket_;
|
||||
|
||||
sync();
|
||||
|
||||
socket.data(['up'], function() {
|
||||
if (!ball.moving) return;
|
||||
if (rpaddle.rtop > 0) rpaddle.rtop -= rpaddle.speed;
|
||||
screen.render();
|
||||
});
|
||||
|
||||
socket.data(['down'], function() {
|
||||
if (!ball.moving) return;
|
||||
if (rpaddle.rtop < table.height - 1) rpaddle.rtop += rpaddle.speed;
|
||||
screen.render();
|
||||
});
|
||||
|
||||
socket.on('error', function() {
|
||||
socket = null;
|
||||
reset();
|
||||
ball.moving = false;
|
||||
message.show();
|
||||
screen.render();
|
||||
});
|
||||
|
||||
startGame();
|
||||
});
|
||||
|
||||
server.listen(+process.argv[2]);
|
||||
}
|
||||
|
||||
function startClient() {
|
||||
var socket = new nssocket.NsSocket({
|
||||
reconnect: true,
|
||||
maxRetries: Infinity,
|
||||
retryInterval: 5000
|
||||
});
|
||||
|
||||
socket.connect(+process.argv[3], process.argv[2]);
|
||||
|
||||
screen.on('keypress', function(ch, key) {
|
||||
if (!rpaddle.movable) return;
|
||||
if (key.name === 'up' || key.name === 'k') {
|
||||
socket.send(['up']);
|
||||
if (rpaddle.rtop > 0) rpaddle.rtop -= rpaddle.speed;
|
||||
if (rpaddle.rtop < 0) rpaddle.rtop = 0;
|
||||
screen.render();
|
||||
} else if (key.name === 'down' || key.name === 'j') {
|
||||
socket.send(['down']);
|
||||
if (rpaddle.rbottom > 0) rpaddle.rtop += rpaddle.speed;
|
||||
if (rpaddle.rbottom < 0) rpaddle.rtop = table.height - rpaddle.height - 1;
|
||||
screen.render();
|
||||
}
|
||||
});
|
||||
|
||||
socket.data(['up'], function() {
|
||||
if (lpaddle.rtop > 0) lpaddle.rtop -= lpaddle.speed;
|
||||
screen.render();
|
||||
});
|
||||
|
||||
socket.data(['down'], function() {
|
||||
if (lpaddle.rtop < table.height - 1) lpaddle.rtop += lpaddle.speed;
|
||||
screen.render();
|
||||
});
|
||||
|
||||
socket.data(['ball'], function(data) {
|
||||
ball.rleft = data.rleft;
|
||||
ball.rtop = data.rtop;
|
||||
screen.render();
|
||||
});
|
||||
|
||||
socket.data(['update'], function(data) {
|
||||
if (data.lpaddle) {
|
||||
lpaddle.rleft = data.lpaddle.rleft;
|
||||
lpaddle.rtop = data.lpaddle.rtop;
|
||||
lpaddle.speed = data.lpaddle.speed;
|
||||
}
|
||||
|
||||
if (data.rpaddle) {
|
||||
rpaddle.rleft = data.rpaddle.rleft;
|
||||
rpaddle.rtop = data.rpaddle.rtop;
|
||||
rpaddle.speed = data.rpaddle.speed;
|
||||
}
|
||||
|
||||
if (data.ball) {
|
||||
ball.moving = data.ball.moving;
|
||||
ball.rleft = data.ball.rleft;
|
||||
ball.rtop = data.ball.rtop;
|
||||
}
|
||||
|
||||
if (data.table) {
|
||||
table.height = data.table.height;
|
||||
table.width = data.table.width;
|
||||
}
|
||||
|
||||
if (data.score) {
|
||||
score.lwins = data.score.lwins;
|
||||
score.rwins = data.score.rwins;
|
||||
}
|
||||
|
||||
screen.render();
|
||||
});
|
||||
|
||||
socket.data(['win'], function() {
|
||||
rpaddle.movable = false;
|
||||
score.rwins++;
|
||||
text.setContent('Left player loses!');
|
||||
message.show();
|
||||
screen.render();
|
||||
});
|
||||
|
||||
socket.data(['lose'], function() {
|
||||
rpaddle.movable = false;
|
||||
score.lwins++;
|
||||
text.setContent('Right player loses!');
|
||||
message.show();
|
||||
screen.render();
|
||||
});
|
||||
|
||||
socket.data(['reset'], reset);
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Main
|
||||
*/
|
||||
|
||||
function main() {
|
||||
screen.on('keypress', function(ch, key) {
|
||||
if (key.name === 'q' || key.name === 'escape') {
|
||||
return process.exit(0);
|
||||
}
|
||||
});
|
||||
|
||||
screen.render();
|
||||
|
||||
// Demo Mode / Single Player
|
||||
if (!nssocket || !process.argv[2]) return startGame();
|
||||
|
||||
// Server Mode
|
||||
if (!process.argv[3]) return startServer();
|
||||
|
||||
// Client Mode
|
||||
if (process.argv[2] && process.argv[3]) return startClient();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute
|
||||
*/
|
||||
|
||||
main();
|
||||
87
example/simple-form.js
Normal file
@ -0,0 +1,87 @@
|
||||
var blessed = require('blessed')
|
||||
, screen = blessed.screen();
|
||||
|
||||
var form = blessed.form({
|
||||
parent: screen,
|
||||
keys: true,
|
||||
left: 0,
|
||||
top: 0,
|
||||
width: 30,
|
||||
height: 4,
|
||||
bg: 'green',
|
||||
content: 'Submit or cancel?'
|
||||
});
|
||||
|
||||
var submit = blessed.button({
|
||||
parent: form,
|
||||
mouse: true,
|
||||
keys: true,
|
||||
shrink: true,
|
||||
padding: {
|
||||
left: 1,
|
||||
right: 1
|
||||
},
|
||||
left: 10,
|
||||
top: 2,
|
||||
shrink: true,
|
||||
name: 'submit',
|
||||
content: 'submit',
|
||||
style: {
|
||||
bg: 'blue',
|
||||
focus: {
|
||||
bg: 'red'
|
||||
},
|
||||
hover: {
|
||||
bg: 'red'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var cancel = blessed.button({
|
||||
parent: form,
|
||||
mouse: true,
|
||||
keys: true,
|
||||
shrink: true,
|
||||
padding: {
|
||||
left: 1,
|
||||
right: 1
|
||||
},
|
||||
left: 20,
|
||||
top: 2,
|
||||
shrink: true,
|
||||
name: 'cancel',
|
||||
content: 'cancel',
|
||||
style: {
|
||||
bg: 'blue',
|
||||
focus: {
|
||||
bg: 'red'
|
||||
},
|
||||
hover: {
|
||||
bg: 'red'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
submit.on('press', function() {
|
||||
form.submit();
|
||||
});
|
||||
|
||||
cancel.on('press', function() {
|
||||
form.reset();
|
||||
});
|
||||
|
||||
form.on('submit', function(data) {
|
||||
form.setContent('Submitted.');
|
||||
screen.render();
|
||||
});
|
||||
|
||||
form.on('reset', function(data) {
|
||||
form.setContent('Canceled.');
|
||||
screen.render();
|
||||
});
|
||||
|
||||
screen.key('q', function() {
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
screen.render();
|
||||
1052
example/time.js
Executable file
55
example/widget.js
Normal file
@ -0,0 +1,55 @@
|
||||
var blessed = require('../');
|
||||
|
||||
// Create a screen object.
|
||||
var screen = blessed.screen();
|
||||
|
||||
// Create a box perfectly centered horizontally and vertically.
|
||||
var box = blessed.box({
|
||||
top: 'center',
|
||||
left: 'center',
|
||||
width: '50%',
|
||||
height: '50%',
|
||||
content: 'Hello {bold}world{/bold}!',
|
||||
tags: true,
|
||||
border: {
|
||||
type: 'line'
|
||||
},
|
||||
style: {
|
||||
fg: 'white',
|
||||
bg: 'magenta',
|
||||
border: {
|
||||
fg: '#ffffff'
|
||||
},
|
||||
hover: {
|
||||
bg: 'green'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Append our box to the screen.
|
||||
screen.append(box);
|
||||
|
||||
// If our box is clicked, change the content.
|
||||
box.on('click', function(data) {
|
||||
box.setContent('{center}Some different {red-fg}content{/red-fg}.{/center}');
|
||||
screen.render();
|
||||
});
|
||||
|
||||
// If box is focused, handle `enter` and give us some more content.
|
||||
box.key('enter', function() {
|
||||
box.setContent('{right}Even different {black-fg}content{/black-fg}.{/right}\n');
|
||||
box.setLine(1, 'bar');
|
||||
box.insertLine(1, 'foo');
|
||||
screen.render();
|
||||
});
|
||||
|
||||
// Quit on Escape, q, or Control-C.
|
||||
screen.key(['escape', 'q', 'C-c'], function(ch, key) {
|
||||
return process.exit(0);
|
||||
});
|
||||
|
||||
// Focus our element.
|
||||
box.focus();
|
||||
|
||||
// Render the screen.
|
||||
screen.render();
|
||||
BIN
img/ansi-viewer.png
Normal file
|
After Width: | Height: | Size: 6.9 KiB |
BIN
img/screenshot.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
img/v0.1.0-1.gif
Normal file
|
After Width: | Height: | Size: 4.0 MiB |
BIN
img/v0.1.0-2.gif
Normal file
|
After Width: | Height: | Size: 2.1 MiB |
BIN
img/v0.1.0-3.gif
Normal file
|
After Width: | Height: | Size: 2.3 MiB |
BIN
img/v0.1.0-4.gif
Normal file
|
After Width: | Height: | Size: 2.8 MiB |
BIN
img/v0.1.0.gif
Normal file
|
After Width: | Height: | Size: 4.0 MiB |
2
index.js
@ -1 +1 @@
|
||||
module.exports = require('./lib/program');
|
||||
module.exports = require('./lib/blessed');
|
||||
|
||||
526
lib/alias.js
Normal file
@ -0,0 +1,526 @@
|
||||
/**
|
||||
* alias.js - terminfo/cap aliases for blessed.
|
||||
* https://github.com/chjj/blessed
|
||||
* Taken from terminfo(5) man page.
|
||||
*/
|
||||
|
||||
/* jshint maxlen: 300 */
|
||||
// jscs:disable maximumLineLength
|
||||
// jscs:disable
|
||||
|
||||
var alias = exports;
|
||||
|
||||
// These are the boolean capabilities:
|
||||
alias.bools = {
|
||||
// Variable Cap- TCap Description
|
||||
// Booleans name Code
|
||||
'auto_left_margin': ['bw', 'bw'], // cub1 wraps from col‐ umn 0 to last column
|
||||
'auto_right_margin': ['am', 'am'], // terminal has auto‐ matic margins
|
||||
'back_color_erase': ['bce', 'ut'], // screen erased with background color
|
||||
'can_change': ['ccc', 'cc'], // terminal can re- define existing col‐ ors
|
||||
'ceol_standout_glitch': ['xhp', 'xs'], // standout not erased by overwriting (hp)
|
||||
'col_addr_glitch': ['xhpa', 'YA'], // only positive motion for hpa/mhpa caps
|
||||
'cpi_changes_res': ['cpix', 'YF'], // changing character pitch changes reso‐ lution
|
||||
'cr_cancels_micro_mode': ['crxm', 'YB'], // using cr turns off micro mode
|
||||
'dest_tabs_magic_smso': ['xt', 'xt'], // tabs destructive, magic so char (t1061)
|
||||
'eat_newline_glitch': ['xenl', 'xn'], // newline ignored after 80 cols (con‐ cept)
|
||||
'erase_overstrike': ['eo', 'eo'], // can erase over‐ strikes with a blank
|
||||
'generic_type': ['gn', 'gn'], // generic line type
|
||||
'hard_copy': ['hc', 'hc'], // hardcopy terminal
|
||||
'hard_cursor': ['chts', 'HC'], // cursor is hard to see
|
||||
'has_meta_key': ['km', 'km'], // Has a meta key (i.e., sets 8th-bit)
|
||||
'has_print_wheel': ['daisy', 'YC'], // printer needs opera‐ tor to change char‐ acter set
|
||||
'has_status_line': ['hs', 'hs'], // has extra status line
|
||||
'hue_lightness_saturation': ['hls', 'hl'], // terminal uses only HLS color notation (Tektronix)
|
||||
'insert_null_glitch': ['in', 'in'], // insert mode distin‐ guishes nulls
|
||||
'lpi_changes_res': ['lpix', 'YG'], // changing line pitch changes resolution
|
||||
'memory_above': ['da', 'da'], // display may be retained above the screen
|
||||
'memory_below': ['db', 'db'], // display may be retained below the screen
|
||||
'move_insert_mode': ['mir', 'mi'], // safe to move while in insert mode
|
||||
'move_standout_mode': ['msgr', 'ms'], // safe to move while in standout mode
|
||||
'needs_xon_xoff': ['nxon', 'nx'], // padding will not work, xon/xoff required
|
||||
'no_esc_ctlc': ['xsb', 'xb'], // beehive (f1=escape, f2=ctrl C)
|
||||
'no_pad_char': ['npc', 'NP'], // pad character does not exist
|
||||
'non_dest_scroll_region': ['ndscr', 'ND'], // scrolling region is non-destructive
|
||||
'non_rev_rmcup': ['nrrmc', 'NR'], // smcup does not reverse rmcup
|
||||
'over_strike': ['os', 'os'], // terminal can over‐ strike
|
||||
'prtr_silent': ['mc5i', '5i'], // printer will not echo on screen
|
||||
'row_addr_glitch': ['xvpa', 'YD'], // only positive motion for vpa/mvpa caps
|
||||
'semi_auto_right_margin': ['sam', 'YE'], // printing in last column causes cr
|
||||
'status_line_esc_ok': ['eslok', 'es'], // escape can be used on the status line
|
||||
'tilde_glitch': ['hz', 'hz'], // cannot print ~'s (hazeltine)
|
||||
'transparent_underline': ['ul', 'ul'], // underline character overstrikes
|
||||
'xon_xoff': ['xon', 'xo'] // terminal uses xon/xoff handshaking
|
||||
};
|
||||
|
||||
// These are the numeric capabilities:
|
||||
alias.numbers = {
|
||||
// Variable Cap- TCap Description
|
||||
// Numeric name Code
|
||||
'columns': ['cols', 'co'], // number of columns in a line
|
||||
'init_tabs': ['it', 'it'], // tabs initially every # spaces
|
||||
'label_height': ['lh', 'lh'], // rows in each label
|
||||
'label_width': ['lw', 'lw'], // columns in each label
|
||||
'lines': ['lines', 'li'], // number of lines on screen or page
|
||||
'lines_of_memory': ['lm', 'lm'], // lines of memory if > line. 0 means varies
|
||||
'magic_cookie_glitch': ['xmc', 'sg'], // number of blank characters left by smso or rmso
|
||||
'max_attributes': ['ma', 'ma'], // maximum combined attributes terminal can handle
|
||||
'max_colors': ['colors', 'Co'], // maximum number of colors on screen
|
||||
'max_pairs': ['pairs', 'pa'], // maximum number of color-pairs on the screen
|
||||
'maximum_windows': ['wnum', 'MW'], // maximum number of defineable windows
|
||||
'no_color_video': ['ncv', 'NC'], // video attributes that cannot be used with colors
|
||||
'num_labels': ['nlab', 'Nl'], // number of labels on screen
|
||||
'padding_baud_rate': ['pb', 'pb'], // lowest baud rate where padding needed
|
||||
'virtual_terminal': ['vt', 'vt'], // virtual terminal number (CB/unix)
|
||||
'width_status_line': ['wsl', 'ws'], // number of columns in status line
|
||||
|
||||
// The following numeric capabilities are present in the SVr4.0 term structure, but are not yet documented in the man page. They came in with
|
||||
// SVr4's printer support.
|
||||
|
||||
|
||||
// Variable Cap- TCap Description
|
||||
// Numeric name Code
|
||||
'bit_image_entwining': ['bitwin', 'Yo'], // number of passes for each bit-image row
|
||||
'bit_image_type': ['bitype', 'Yp'], // type of bit-image device
|
||||
'buffer_capacity': ['bufsz', 'Ya'], // numbers of bytes buffered before printing
|
||||
'buttons': ['btns', 'BT'], // number of buttons on mouse
|
||||
'dot_horz_spacing': ['spinh', 'Yc'], // spacing of dots hor‐ izontally in dots per inch
|
||||
'dot_vert_spacing': ['spinv', 'Yb'], // spacing of pins ver‐ tically in pins per inch
|
||||
'max_micro_address': ['maddr', 'Yd'], // maximum value in micro_..._address
|
||||
'max_micro_jump': ['mjump', 'Ye'], // maximum value in parm_..._micro
|
||||
'micro_col_size': ['mcs', 'Yf'], // character step size when in micro mode
|
||||
'micro_line_size': ['mls', 'Yg'], // line step size when in micro mode
|
||||
'number_of_pins': ['npins', 'Yh'], // numbers of pins in print-head
|
||||
'output_res_char': ['orc', 'Yi'], // horizontal resolu‐ tion in units per line
|
||||
'output_res_horz_inch': ['orhi', 'Yk'], // horizontal resolu‐ tion in units per inch
|
||||
'output_res_line': ['orl', 'Yj'], // vertical resolution in units per line
|
||||
'output_res_vert_inch': ['orvi', 'Yl'], // vertical resolution in units per inch
|
||||
'print_rate': ['cps', 'Ym'], // print rate in char‐ acters per second
|
||||
'wide_char_size': ['widcs', 'Yn'] // character step size when in double wide mode
|
||||
};
|
||||
|
||||
// These are the string capabilities:
|
||||
alias.strings = {
|
||||
// Variable Cap- TCap Description
|
||||
// String name Code
|
||||
'acs_chars': ['acsc', 'ac'], // graphics charset pairs, based on vt100
|
||||
'back_tab': ['cbt', 'bt'], // back tab (P)
|
||||
'bell': ['bel', 'bl'], // audible signal (bell) (P)
|
||||
'carriage_return': ['cr', 'cr'], // carriage return (P*) (P*)
|
||||
'change_char_pitch': ['cpi', 'ZA'], // Change number of characters per inch to #1
|
||||
'change_line_pitch': ['lpi', 'ZB'], // Change number of lines per inch to #1
|
||||
'change_res_horz': ['chr', 'ZC'], // Change horizontal resolution to #1
|
||||
'change_res_vert': ['cvr', 'ZD'], // Change vertical res‐ olution to #1
|
||||
'change_scroll_region': ['csr', 'cs'], // change region to line #1 to line #2 (P)
|
||||
'char_padding': ['rmp', 'rP'], // like ip but when in insert mode
|
||||
'clear_all_tabs': ['tbc', 'ct'], // clear all tab stops (P)
|
||||
'clear_margins': ['mgc', 'MC'], // clear right and left soft margins
|
||||
'clear_screen': ['clear', 'cl'], // clear screen and home cursor (P*)
|
||||
'clr_bol': ['el1', 'cb'], // Clear to beginning of line
|
||||
'clr_eol': ['el', 'ce'], // clear to end of line (P)
|
||||
'clr_eos': ['ed', 'cd'], // clear to end of screen (P*)
|
||||
'column_address': ['hpa', 'ch'], // horizontal position #1, absolute (P)
|
||||
'command_character': ['cmdch', 'CC'], // terminal settable cmd character in prototype !?
|
||||
'create_window': ['cwin', 'CW'], // define a window #1 from #2,#3 to #4,#5
|
||||
'cursor_address': ['cup', 'cm'], // move to row #1 col‐ umns #2
|
||||
'cursor_down': ['cud1', 'do'], // down one line
|
||||
'cursor_home': ['home', 'ho'], // home cursor (if no cup)
|
||||
'cursor_invisible': ['civis', 'vi'], // make cursor invisi‐ ble
|
||||
'cursor_left': ['cub1', 'le'], // move left one space
|
||||
'cursor_mem_address': ['mrcup', 'CM'], // memory relative cur‐ sor addressing, move to row #1 columns #2
|
||||
'cursor_normal': ['cnorm', 've'], // make cursor appear normal (undo civis/cvvis)
|
||||
'cursor_right': ['cuf1', 'nd'], // non-destructive space (move right one space)
|
||||
'cursor_to_ll': ['ll', 'll'], // last line, first column (if no cup)
|
||||
'cursor_up': ['cuu1', 'up'], // up one line
|
||||
'cursor_visible': ['cvvis', 'vs'], // make cursor very visible
|
||||
'define_char': ['defc', 'ZE'], // Define a character #1, #2 dots wide, descender #3
|
||||
'delete_character': ['dch1', 'dc'], // delete character (P*)
|
||||
'delete_line': ['dl1', 'dl'], // delete line (P*)
|
||||
'dial_phone': ['dial', 'DI'], // dial number #1
|
||||
'dis_status_line': ['dsl', 'ds'], // disable status line
|
||||
'display_clock': ['dclk', 'DK'], // display clock
|
||||
'down_half_line': ['hd', 'hd'], // half a line down
|
||||
'ena_acs': ['enacs', 'eA'], // enable alternate char set
|
||||
'enter_alt_charset_mode': ['smacs', 'as'], // start alternate character set (P)
|
||||
'enter_am_mode': ['smam', 'SA'], // turn on automatic margins
|
||||
'enter_blink_mode': ['blink', 'mb'], // turn on blinking
|
||||
'enter_bold_mode': ['bold', 'md'], // turn on bold (extra bright) mode
|
||||
'enter_ca_mode': ['smcup', 'ti'], // string to start pro‐ grams using cup
|
||||
'enter_delete_mode': ['smdc', 'dm'], // enter delete mode
|
||||
'enter_dim_mode': ['dim', 'mh'], // turn on half-bright mode
|
||||
'enter_doublewide_mode': ['swidm', 'ZF'], // Enter double-wide mode
|
||||
'enter_draft_quality': ['sdrfq', 'ZG'], // Enter draft-quality mode
|
||||
'enter_insert_mode': ['smir', 'im'], // enter insert mode
|
||||
'enter_italics_mode': ['sitm', 'ZH'], // Enter italic mode
|
||||
'enter_leftward_mode': ['slm', 'ZI'], // Start leftward car‐ riage motion
|
||||
'enter_micro_mode': ['smicm', 'ZJ'], // Start micro-motion mode
|
||||
'enter_near_letter_quality': ['snlq', 'ZK'], // Enter NLQ mode
|
||||
'enter_normal_quality': ['snrmq', 'ZL'], // Enter normal-quality mode
|
||||
'enter_protected_mode': ['prot', 'mp'], // turn on protected mode
|
||||
'enter_reverse_mode': ['rev', 'mr'], // turn on reverse video mode
|
||||
'enter_secure_mode': ['invis', 'mk'], // turn on blank mode (characters invisi‐ ble)
|
||||
'enter_shadow_mode': ['sshm', 'ZM'], // Enter shadow-print mode
|
||||
'enter_standout_mode': ['smso', 'so'], // begin standout mode
|
||||
'enter_subscript_mode': ['ssubm', 'ZN'], // Enter subscript mode
|
||||
'enter_superscript_mode': ['ssupm', 'ZO'], // Enter superscript mode
|
||||
'enter_underline_mode': ['smul', 'us'], // begin underline mode
|
||||
'enter_upward_mode': ['sum', 'ZP'], // Start upward car‐ riage motion
|
||||
'enter_xon_mode': ['smxon', 'SX'], // turn on xon/xoff handshaking
|
||||
'erase_chars': ['ech', 'ec'], // erase #1 characters (P)
|
||||
'exit_alt_charset_mode': ['rmacs', 'ae'], // end alternate char‐ acter set (P)
|
||||
'exit_am_mode': ['rmam', 'RA'], // turn off automatic margins
|
||||
'exit_attribute_mode': ['sgr0', 'me'], // turn off all attributes
|
||||
'exit_ca_mode': ['rmcup', 'te'], // strings to end pro‐ grams using cup
|
||||
'exit_delete_mode': ['rmdc', 'ed'], // end delete mode
|
||||
'exit_doublewide_mode': ['rwidm', 'ZQ'], // End double-wide mode
|
||||
'exit_insert_mode': ['rmir', 'ei'], // exit insert mode
|
||||
'exit_italics_mode': ['ritm', 'ZR'], // End italic mode
|
||||
'exit_leftward_mode': ['rlm', 'ZS'], // End left-motion mode
|
||||
|
||||
|
||||
'exit_micro_mode': ['rmicm', 'ZT'], // End micro-motion mode
|
||||
'exit_shadow_mode': ['rshm', 'ZU'], // End shadow-print mode
|
||||
'exit_standout_mode': ['rmso', 'se'], // exit standout mode
|
||||
'exit_subscript_mode': ['rsubm', 'ZV'], // End subscript mode
|
||||
'exit_superscript_mode': ['rsupm', 'ZW'], // End superscript mode
|
||||
'exit_underline_mode': ['rmul', 'ue'], // exit underline mode
|
||||
'exit_upward_mode': ['rum', 'ZX'], // End reverse charac‐ ter motion
|
||||
'exit_xon_mode': ['rmxon', 'RX'], // turn off xon/xoff handshaking
|
||||
'fixed_pause': ['pause', 'PA'], // pause for 2-3 sec‐ onds
|
||||
'flash_hook': ['hook', 'fh'], // flash switch hook
|
||||
'flash_screen': ['flash', 'vb'], // visible bell (may not move cursor)
|
||||
'form_feed': ['ff', 'ff'], // hardcopy terminal page eject (P*)
|
||||
'from_status_line': ['fsl', 'fs'], // return from status line
|
||||
'goto_window': ['wingo', 'WG'], // go to window #1
|
||||
'hangup': ['hup', 'HU'], // hang-up phone
|
||||
'init_1string': ['is1', 'i1'], // initialization string
|
||||
'init_2string': ['is2', 'is'], // initialization string
|
||||
'init_3string': ['is3', 'i3'], // initialization string
|
||||
'init_file': ['if', 'if'], // name of initializa‐ tion file
|
||||
'init_prog': ['iprog', 'iP'], // path name of program for initialization
|
||||
'initialize_color': ['initc', 'Ic'], // initialize color #1 to (#2,#3,#4)
|
||||
'initialize_pair': ['initp', 'Ip'], // Initialize color pair #1 to fg=(#2,#3,#4), bg=(#5,#6,#7)
|
||||
'insert_character': ['ich1', 'ic'], // insert character (P)
|
||||
'insert_line': ['il1', 'al'], // insert line (P*)
|
||||
'insert_padding': ['ip', 'ip'], // insert padding after inserted character
|
||||
'key_a1': ['ka1', 'K1'], // upper left of keypad
|
||||
'key_a3': ['ka3', 'K3'], // upper right of key‐ pad
|
||||
'key_b2': ['kb2', 'K2'], // center of keypad
|
||||
'key_backspace': ['kbs', 'kb'], // backspace key
|
||||
'key_beg': ['kbeg', '@1'], // begin key
|
||||
'key_btab': ['kcbt', 'kB'], // back-tab key
|
||||
'key_c1': ['kc1', 'K4'], // lower left of keypad
|
||||
'key_c3': ['kc3', 'K5'], // lower right of key‐ pad
|
||||
'key_cancel': ['kcan', '@2'], // cancel key
|
||||
'key_catab': ['ktbc', 'ka'], // clear-all-tabs key
|
||||
'key_clear': ['kclr', 'kC'], // clear-screen or erase key
|
||||
'key_close': ['kclo', '@3'], // close key
|
||||
'key_command': ['kcmd', '@4'], // command key
|
||||
'key_copy': ['kcpy', '@5'], // copy key
|
||||
'key_create': ['kcrt', '@6'], // create key
|
||||
'key_ctab': ['kctab', 'kt'], // clear-tab key
|
||||
'key_dc': ['kdch1', 'kD'], // delete-character key
|
||||
'key_dl': ['kdl1', 'kL'], // delete-line key
|
||||
'key_down': ['kcud1', 'kd'], // down-arrow key
|
||||
|
||||
'key_eic': ['krmir', 'kM'], // sent by rmir or smir in insert mode
|
||||
'key_end': ['kend', '@7'], // end key
|
||||
'key_enter': ['kent', '@8'], // enter/send key
|
||||
'key_eol': ['kel', 'kE'], // clear-to-end-of-line key
|
||||
'key_eos': ['ked', 'kS'], // clear-to-end-of- screen key
|
||||
'key_exit': ['kext', '@9'], // exit key
|
||||
'key_f0': ['kf0', 'k0'], // F0 function key
|
||||
'key_f1': ['kf1', 'k1'], // F1 function key
|
||||
'key_f10': ['kf10', 'k;'], // F10 function key
|
||||
'key_f11': ['kf11', 'F1'], // F11 function key
|
||||
'key_f12': ['kf12', 'F2'], // F12 function key
|
||||
'key_f13': ['kf13', 'F3'], // F13 function key
|
||||
'key_f14': ['kf14', 'F4'], // F14 function key
|
||||
'key_f15': ['kf15', 'F5'], // F15 function key
|
||||
'key_f16': ['kf16', 'F6'], // F16 function key
|
||||
'key_f17': ['kf17', 'F7'], // F17 function key
|
||||
'key_f18': ['kf18', 'F8'], // F18 function key
|
||||
'key_f19': ['kf19', 'F9'], // F19 function key
|
||||
'key_f2': ['kf2', 'k2'], // F2 function key
|
||||
'key_f20': ['kf20', 'FA'], // F20 function key
|
||||
'key_f21': ['kf21', 'FB'], // F21 function key
|
||||
'key_f22': ['kf22', 'FC'], // F22 function key
|
||||
'key_f23': ['kf23', 'FD'], // F23 function key
|
||||
'key_f24': ['kf24', 'FE'], // F24 function key
|
||||
'key_f25': ['kf25', 'FF'], // F25 function key
|
||||
'key_f26': ['kf26', 'FG'], // F26 function key
|
||||
'key_f27': ['kf27', 'FH'], // F27 function key
|
||||
'key_f28': ['kf28', 'FI'], // F28 function key
|
||||
'key_f29': ['kf29', 'FJ'], // F29 function key
|
||||
'key_f3': ['kf3', 'k3'], // F3 function key
|
||||
'key_f30': ['kf30', 'FK'], // F30 function key
|
||||
'key_f31': ['kf31', 'FL'], // F31 function key
|
||||
'key_f32': ['kf32', 'FM'], // F32 function key
|
||||
'key_f33': ['kf33', 'FN'], // F33 function key
|
||||
'key_f34': ['kf34', 'FO'], // F34 function key
|
||||
'key_f35': ['kf35', 'FP'], // F35 function key
|
||||
'key_f36': ['kf36', 'FQ'], // F36 function key
|
||||
'key_f37': ['kf37', 'FR'], // F37 function key
|
||||
'key_f38': ['kf38', 'FS'], // F38 function key
|
||||
'key_f39': ['kf39', 'FT'], // F39 function key
|
||||
'key_f4': ['kf4', 'k4'], // F4 function key
|
||||
'key_f40': ['kf40', 'FU'], // F40 function key
|
||||
'key_f41': ['kf41', 'FV'], // F41 function key
|
||||
'key_f42': ['kf42', 'FW'], // F42 function key
|
||||
'key_f43': ['kf43', 'FX'], // F43 function key
|
||||
'key_f44': ['kf44', 'FY'], // F44 function key
|
||||
'key_f45': ['kf45', 'FZ'], // F45 function key
|
||||
'key_f46': ['kf46', 'Fa'], // F46 function key
|
||||
'key_f47': ['kf47', 'Fb'], // F47 function key
|
||||
'key_f48': ['kf48', 'Fc'], // F48 function key
|
||||
'key_f49': ['kf49', 'Fd'], // F49 function key
|
||||
'key_f5': ['kf5', 'k5'], // F5 function key
|
||||
'key_f50': ['kf50', 'Fe'], // F50 function key
|
||||
'key_f51': ['kf51', 'Ff'], // F51 function key
|
||||
'key_f52': ['kf52', 'Fg'], // F52 function key
|
||||
'key_f53': ['kf53', 'Fh'], // F53 function key
|
||||
'key_f54': ['kf54', 'Fi'], // F54 function key
|
||||
'key_f55': ['kf55', 'Fj'], // F55 function key
|
||||
'key_f56': ['kf56', 'Fk'], // F56 function key
|
||||
'key_f57': ['kf57', 'Fl'], // F57 function key
|
||||
'key_f58': ['kf58', 'Fm'], // F58 function key
|
||||
'key_f59': ['kf59', 'Fn'], // F59 function key
|
||||
|
||||
'key_f6': ['kf6', 'k6'], // F6 function key
|
||||
'key_f60': ['kf60', 'Fo'], // F60 function key
|
||||
'key_f61': ['kf61', 'Fp'], // F61 function key
|
||||
'key_f62': ['kf62', 'Fq'], // F62 function key
|
||||
'key_f63': ['kf63', 'Fr'], // F63 function key
|
||||
'key_f7': ['kf7', 'k7'], // F7 function key
|
||||
'key_f8': ['kf8', 'k8'], // F8 function key
|
||||
'key_f9': ['kf9', 'k9'], // F9 function key
|
||||
'key_find': ['kfnd', '@0'], // find key
|
||||
'key_help': ['khlp', '%1'], // help key
|
||||
'key_home': ['khome', 'kh'], // home key
|
||||
'key_ic': ['kich1', 'kI'], // insert-character key
|
||||
'key_il': ['kil1', 'kA'], // insert-line key
|
||||
'key_left': ['kcub1', 'kl'], // left-arrow key
|
||||
'key_ll': ['kll', 'kH'], // lower-left key (home down)
|
||||
'key_mark': ['kmrk', '%2'], // mark key
|
||||
'key_message': ['kmsg', '%3'], // message key
|
||||
'key_move': ['kmov', '%4'], // move key
|
||||
'key_next': ['knxt', '%5'], // next key
|
||||
'key_npage': ['knp', 'kN'], // next-page key
|
||||
'key_open': ['kopn', '%6'], // open key
|
||||
'key_options': ['kopt', '%7'], // options key
|
||||
'key_ppage': ['kpp', 'kP'], // previous-page key
|
||||
'key_previous': ['kprv', '%8'], // previous key
|
||||
'key_print': ['kprt', '%9'], // print key
|
||||
'key_redo': ['krdo', '%0'], // redo key
|
||||
'key_reference': ['kref', '&1'], // reference key
|
||||
'key_refresh': ['krfr', '&2'], // refresh key
|
||||
'key_replace': ['krpl', '&3'], // replace key
|
||||
'key_restart': ['krst', '&4'], // restart key
|
||||
'key_resume': ['kres', '&5'], // resume key
|
||||
'key_right': ['kcuf1', 'kr'], // right-arrow key
|
||||
'key_save': ['ksav', '&6'], // save key
|
||||
'key_sbeg': ['kBEG', '&9'], // shifted begin key
|
||||
'key_scancel': ['kCAN', '&0'], // shifted cancel key
|
||||
'key_scommand': ['kCMD', '*1'], // shifted command key
|
||||
'key_scopy': ['kCPY', '*2'], // shifted copy key
|
||||
'key_screate': ['kCRT', '*3'], // shifted create key
|
||||
'key_sdc': ['kDC', '*4'], // shifted delete-char‐ acter key
|
||||
'key_sdl': ['kDL', '*5'], // shifted delete-line key
|
||||
'key_select': ['kslt', '*6'], // select key
|
||||
'key_send': ['kEND', '*7'], // shifted end key
|
||||
'key_seol': ['kEOL', '*8'], // shifted clear-to- end-of-line key
|
||||
'key_sexit': ['kEXT', '*9'], // shifted exit key
|
||||
'key_sf': ['kind', 'kF'], // scroll-forward key
|
||||
'key_sfind': ['kFND', '*0'], // shifted find key
|
||||
'key_shelp': ['kHLP', '#1'], // shifted help key
|
||||
'key_shome': ['kHOM', '#2'], // shifted home key
|
||||
'key_sic': ['kIC', '#3'], // shifted insert-char‐ acter key
|
||||
'key_sleft': ['kLFT', '#4'], // shifted left-arrow key
|
||||
'key_smessage': ['kMSG', '%a'], // shifted message key
|
||||
'key_smove': ['kMOV', '%b'], // shifted move key
|
||||
'key_snext': ['kNXT', '%c'], // shifted next key
|
||||
'key_soptions': ['kOPT', '%d'], // shifted options key
|
||||
'key_sprevious': ['kPRV', '%e'], // shifted previous key
|
||||
'key_sprint': ['kPRT', '%f'], // shifted print key
|
||||
'key_sr': ['kri', 'kR'], // scroll-backward key
|
||||
'key_sredo': ['kRDO', '%g'], // shifted redo key
|
||||
'key_sreplace': ['kRPL', '%h'], // shifted replace key
|
||||
|
||||
'key_sright': ['kRIT', '%i'], // shifted right-arrow key
|
||||
'key_srsume': ['kRES', '%j'], // shifted resume key
|
||||
'key_ssave': ['kSAV', '!1'], // shifted save key
|
||||
'key_ssuspend': ['kSPD', '!2'], // shifted suspend key
|
||||
'key_stab': ['khts', 'kT'], // set-tab key
|
||||
'key_sundo': ['kUND', '!3'], // shifted undo key
|
||||
'key_suspend': ['kspd', '&7'], // suspend key
|
||||
'key_undo': ['kund', '&8'], // undo key
|
||||
'key_up': ['kcuu1', 'ku'], // up-arrow key
|
||||
'keypad_local': ['rmkx', 'ke'], // leave 'key‐ board_transmit' mode
|
||||
'keypad_xmit': ['smkx', 'ks'], // enter 'key‐ board_transmit' mode
|
||||
'lab_f0': ['lf0', 'l0'], // label on function key f0 if not f0
|
||||
'lab_f1': ['lf1', 'l1'], // label on function key f1 if not f1
|
||||
'lab_f10': ['lf10', 'la'], // label on function key f10 if not f10
|
||||
'lab_f2': ['lf2', 'l2'], // label on function key f2 if not f2
|
||||
'lab_f3': ['lf3', 'l3'], // label on function key f3 if not f3
|
||||
'lab_f4': ['lf4', 'l4'], // label on function key f4 if not f4
|
||||
'lab_f5': ['lf5', 'l5'], // label on function key f5 if not f5
|
||||
'lab_f6': ['lf6', 'l6'], // label on function key f6 if not f6
|
||||
'lab_f7': ['lf7', 'l7'], // label on function key f7 if not f7
|
||||
'lab_f8': ['lf8', 'l8'], // label on function key f8 if not f8
|
||||
'lab_f9': ['lf9', 'l9'], // label on function key f9 if not f9
|
||||
'label_format': ['fln', 'Lf'], // label format
|
||||
'label_off': ['rmln', 'LF'], // turn off soft labels
|
||||
'label_on': ['smln', 'LO'], // turn on soft labels
|
||||
'meta_off': ['rmm', 'mo'], // turn off meta mode
|
||||
'meta_on': ['smm', 'mm'], // turn on meta mode (8th-bit on)
|
||||
'micro_column_address': ['mhpa', 'ZY'], // Like column_address in micro mode
|
||||
'micro_down': ['mcud1', 'ZZ'], // Like cursor_down in micro mode
|
||||
'micro_left': ['mcub1', 'Za'], // Like cursor_left in micro mode
|
||||
'micro_right': ['mcuf1', 'Zb'], // Like cursor_right in micro mode
|
||||
'micro_row_address': ['mvpa', 'Zc'], // Like row_address #1 in micro mode
|
||||
'micro_up': ['mcuu1', 'Zd'], // Like cursor_up in micro mode
|
||||
'newline': ['nel', 'nw'], // newline (behave like cr followed by lf)
|
||||
'order_of_pins': ['porder', 'Ze'], // Match software bits to print-head pins
|
||||
'orig_colors': ['oc', 'oc'], // Set all color pairs to the original ones
|
||||
'orig_pair': ['op', 'op'], // Set default pair to its original value
|
||||
'pad_char': ['pad', 'pc'], // padding char (instead of null)
|
||||
|
||||
|
||||
'parm_dch': ['dch', 'DC'], // delete #1 characters (P*)
|
||||
'parm_delete_line': ['dl', 'DL'], // delete #1 lines (P*)
|
||||
'parm_down_cursor': ['cud', 'DO'], // down #1 lines (P*)
|
||||
'parm_down_micro': ['mcud', 'Zf'], // Like parm_down_cur‐ sor in micro mode
|
||||
'parm_ich': ['ich', 'IC'], // insert #1 characters (P*)
|
||||
'parm_index': ['indn', 'SF'], // scroll forward #1 lines (P)
|
||||
'parm_insert_line': ['il', 'AL'], // insert #1 lines (P*)
|
||||
'parm_left_cursor': ['cub', 'LE'], // move #1 characters to the left (P)
|
||||
'parm_left_micro': ['mcub', 'Zg'], // Like parm_left_cur‐ sor in micro mode
|
||||
'parm_right_cursor': ['cuf', 'RI'], // move #1 characters to the right (P*)
|
||||
'parm_right_micro': ['mcuf', 'Zh'], // Like parm_right_cur‐ sor in micro mode
|
||||
'parm_rindex': ['rin', 'SR'], // scroll back #1 lines (P)
|
||||
'parm_up_cursor': ['cuu', 'UP'], // up #1 lines (P*)
|
||||
'parm_up_micro': ['mcuu', 'Zi'], // Like parm_up_cursor in micro mode
|
||||
'pkey_key': ['pfkey', 'pk'], // program function key #1 to type string #2
|
||||
'pkey_local': ['pfloc', 'pl'], // program function key #1 to execute string #2
|
||||
'pkey_xmit': ['pfx', 'px'], // program function key #1 to transmit string #2
|
||||
'plab_norm': ['pln', 'pn'], // program label #1 to show string #2
|
||||
'print_screen': ['mc0', 'ps'], // print contents of screen
|
||||
'prtr_non': ['mc5p', 'pO'], // turn on printer for #1 bytes
|
||||
'prtr_off': ['mc4', 'pf'], // turn off printer
|
||||
'prtr_on': ['mc5', 'po'], // turn on printer
|
||||
'pulse': ['pulse', 'PU'], // select pulse dialing
|
||||
'quick_dial': ['qdial', 'QD'], // dial number #1 with‐ out checking
|
||||
'remove_clock': ['rmclk', 'RC'], // remove clock
|
||||
'repeat_char': ['rep', 'rp'], // repeat char #1 #2 times (P*)
|
||||
'req_for_input': ['rfi', 'RF'], // send next input char (for ptys)
|
||||
'reset_1string': ['rs1', 'r1'], // reset string
|
||||
'reset_2string': ['rs2', 'r2'], // reset string
|
||||
'reset_3string': ['rs3', 'r3'], // reset string
|
||||
'reset_file': ['rf', 'rf'], // name of reset file
|
||||
'restore_cursor': ['rc', 'rc'], // restore cursor to position of last save_cursor
|
||||
'row_address': ['vpa', 'cv'], // vertical position #1 absolute (P)
|
||||
'save_cursor': ['sc', 'sc'], // save current cursor position (P)
|
||||
'scroll_forward': ['ind', 'sf'], // scroll text up (P)
|
||||
'scroll_reverse': ['ri', 'sr'], // scroll text down (P)
|
||||
'select_char_set': ['scs', 'Zj'], // Select character set, #1
|
||||
|
||||
|
||||
|
||||
'set_attributes': ['sgr', 'sa'], // define video attributes #1-#9 (PG9)
|
||||
'set_background': ['setb', 'Sb'], // Set background color #1
|
||||
'set_bottom_margin': ['smgb', 'Zk'], // Set bottom margin at current line
|
||||
'set_bottom_margin_parm': ['smgbp', 'Zl'], // Set bottom margin at line #1 or (if smgtp is not given) #2 lines from bottom
|
||||
'set_clock': ['sclk', 'SC'], // set clock, #1 hrs #2 mins #3 secs
|
||||
'set_color_pair': ['scp', 'sp'], // Set current color pair to #1
|
||||
'set_foreground': ['setf', 'Sf'], // Set foreground color #1
|
||||
'set_left_margin': ['smgl', 'ML'], // set left soft margin at current col‐ umn. See smgl. (ML is not in BSD termcap).
|
||||
'set_left_margin_parm': ['smglp', 'Zm'], // Set left (right) margin at column #1
|
||||
'set_right_margin': ['smgr', 'MR'], // set right soft margin at current column
|
||||
'set_right_margin_parm': ['smgrp', 'Zn'], // Set right margin at column #1
|
||||
'set_tab': ['hts', 'st'], // set a tab in every row, current columns
|
||||
'set_top_margin': ['smgt', 'Zo'], // Set top margin at current line
|
||||
'set_top_margin_parm': ['smgtp', 'Zp'], // Set top (bottom) margin at row #1
|
||||
'set_window': ['wind', 'wi'], // current window is lines #1-#2 cols #3-#4
|
||||
'start_bit_image': ['sbim', 'Zq'], // Start printing bit image graphics
|
||||
'start_char_set_def': ['scsd', 'Zr'], // Start character set defi‐ nition #1, with #2 charac‐ ters in the set
|
||||
'stop_bit_image': ['rbim', 'Zs'], // Stop printing bit image graphics
|
||||
'stop_char_set_def': ['rcsd', 'Zt'], // End definition of charac‐ ter set #1
|
||||
'subscript_characters': ['subcs', 'Zu'], // List of subscriptable characters
|
||||
'superscript_characters': ['supcs', 'Zv'], // List of superscriptable characters
|
||||
'tab': ['ht', 'ta'], // tab to next 8-space hard‐ ware tab stop
|
||||
'these_cause_cr': ['docr', 'Zw'], // Printing any of these characters causes CR
|
||||
'to_status_line': ['tsl', 'ts'], // move to status line, col‐ umn #1
|
||||
'tone': ['tone', 'TO'], // select touch tone dialing
|
||||
'underline_char': ['uc', 'uc'], // underline char and move past it
|
||||
'up_half_line': ['hu', 'hu'], // half a line up
|
||||
'user0': ['u0', 'u0'], // User string #0
|
||||
'user1': ['u1', 'u1'], // User string #1
|
||||
'user2': ['u2', 'u2'], // User string #2
|
||||
'user3': ['u3', 'u3'], // User string #3
|
||||
'user4': ['u4', 'u4'], // User string #4
|
||||
'user5': ['u5', 'u5'], // User string #5
|
||||
|
||||
'user6': ['u6', 'u6'], // User string #6
|
||||
'user7': ['u7', 'u7'], // User string #7
|
||||
'user8': ['u8', 'u8'], // User string #8
|
||||
'user9': ['u9', 'u9'], // User string #9
|
||||
'wait_tone': ['wait', 'WA'], // wait for dial-tone
|
||||
'xoff_character': ['xoffc', 'XF'], // XOFF character
|
||||
'xon_character': ['xonc', 'XN'], // XON character
|
||||
'zero_motion': ['zerom', 'Zx'], // No motion for subsequent character
|
||||
|
||||
// The following string capabilities are present in the SVr4.0 term structure, but were originally not documented in the man page.
|
||||
|
||||
|
||||
// Variable Cap- TCap Description
|
||||
// String name Code
|
||||
'alt_scancode_esc': ['scesa', 'S8'], // Alternate escape for scancode emu‐ lation
|
||||
'bit_image_carriage_return': ['bicr', 'Yv'], // Move to beginning of same row
|
||||
'bit_image_newline': ['binel', 'Zz'], // Move to next row of the bit image
|
||||
'bit_image_repeat': ['birep', 'Xy'], // Repeat bit image cell #1 #2 times
|
||||
'char_set_names': ['csnm', 'Zy'], // Produce #1'th item from list of char‐ acter set names
|
||||
'code_set_init': ['csin', 'ci'], // Init sequence for multiple codesets
|
||||
'color_names': ['colornm', 'Yw'], // Give name for color #1
|
||||
'define_bit_image_region': ['defbi', 'Yx'], // Define rectan‐ gualar bit image region
|
||||
'device_type': ['devt', 'dv'], // Indicate lan‐ guage/codeset sup‐ port
|
||||
'display_pc_char': ['dispc', 'S1'], // Display PC charac‐ ter #1
|
||||
'end_bit_image_region': ['endbi', 'Yy'], // End a bit-image region
|
||||
'enter_pc_charset_mode': ['smpch', 'S2'], // Enter PC character display mode
|
||||
'enter_scancode_mode': ['smsc', 'S4'], // Enter PC scancode mode
|
||||
'exit_pc_charset_mode': ['rmpch', 'S3'], // Exit PC character display mode
|
||||
'exit_scancode_mode': ['rmsc', 'S5'], // Exit PC scancode mode
|
||||
'get_mouse': ['getm', 'Gm'], // Curses should get button events, parameter #1 not documented.
|
||||
'key_mouse': ['kmous', 'Km'], // Mouse event has occurred
|
||||
'mouse_info': ['minfo', 'Mi'], // Mouse status information
|
||||
'pc_term_options': ['pctrm', 'S6'], // PC terminal options
|
||||
'pkey_plab': ['pfxl', 'xl'], // Program function key #1 to type string #2 and show string #3
|
||||
'req_mouse_pos': ['reqmp', 'RQ'], // Request mouse position
|
||||
|
||||
'scancode_escape': ['scesc', 'S7'], // Escape for scan‐ code emulation
|
||||
'set0_des_seq': ['s0ds', 's0'], // Shift to codeset 0 (EUC set 0, ASCII)
|
||||
'set1_des_seq': ['s1ds', 's1'], // Shift to codeset 1
|
||||
'set2_des_seq': ['s2ds', 's2'], // Shift to codeset 2
|
||||
'set3_des_seq': ['s3ds', 's3'], // Shift to codeset 3
|
||||
'set_a_background': ['setab', 'AB'], // Set background color to #1, using ANSI escape
|
||||
'set_a_foreground': ['setaf', 'AF'], // Set foreground color to #1, using ANSI escape
|
||||
'set_color_band': ['setcolor', 'Yz'], // Change to ribbon color #1
|
||||
'set_lr_margin': ['smglr', 'ML'], // Set both left and right margins to #1, #2. (ML is not in BSD term‐ cap).
|
||||
'set_page_length': ['slines', 'YZ'], // Set page length to #1 lines
|
||||
'set_tb_margin': ['smgtb', 'MT'], // Sets both top and bottom margins to #1, #2
|
||||
|
||||
// The XSI Curses standard added these. They are some post-4.1 versions of System V curses, e.g., Solaris 2.5 and IRIX 6.x. The ncurses termcap
|
||||
// names for them are invented; according to the XSI Curses standard, they have no termcap names. If your compiled terminfo entries use these,
|
||||
// they may not be binary-compatible with System V terminfo entries after SVr4.1; beware!
|
||||
|
||||
|
||||
// Variable Cap- TCap Description
|
||||
// String name Code
|
||||
'enter_horizontal_hl_mode': ['ehhlm', 'Xh'], // Enter horizontal highlight mode
|
||||
'enter_left_hl_mode': ['elhlm', 'Xl'], // Enter left highlight mode
|
||||
'enter_low_hl_mode': ['elohlm', 'Xo'], // Enter low highlight mode
|
||||
'enter_right_hl_mode': ['erhlm', 'Xr'], // Enter right high‐ light mode
|
||||
'enter_top_hl_mode': ['ethlm', 'Xt'], // Enter top highlight mode
|
||||
'enter_vertical_hl_mode': ['evhlm', 'Xv'], // Enter vertical high‐ light mode
|
||||
'set_a_attributes': ['sgr1', 'sA'], // Define second set of video attributes #1-#6
|
||||
'set_pglen_inch': ['slength', 'sL'] // YI Set page length to #1 hundredth of an inch
|
||||
};
|
||||
32
lib/blessed.js
Normal file
@ -0,0 +1,32 @@
|
||||
/**
|
||||
* blessed - a high-level terminal interface library for node.js
|
||||
* Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Blessed
|
||||
*/
|
||||
|
||||
function blessed() {
|
||||
return blessed.program.apply(null, arguments);
|
||||
}
|
||||
|
||||
blessed.program = blessed.Program = require('./program');
|
||||
blessed.tput = blessed.Tput = require('./tput');
|
||||
blessed.widget = require('./widget');
|
||||
blessed.colors = require('./colors');
|
||||
blessed.unicode = require('./unicode');
|
||||
blessed.helpers = require('./helpers');
|
||||
|
||||
blessed.helpers.sprintf = blessed.tput.sprintf;
|
||||
blessed.helpers.tryRead = blessed.tput.tryRead;
|
||||
blessed.helpers.merge(blessed, blessed.helpers);
|
||||
|
||||
blessed.helpers.merge(blessed, blessed.widget);
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = blessed;
|
||||
530
lib/colors.js
Normal file
@ -0,0 +1,530 @@
|
||||
/**
|
||||
* colors.js - color-related functions for blessed.
|
||||
* Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
exports.match = function(r1, g1, b1) {
|
||||
if (typeof r1 === 'string') {
|
||||
var hex = r1;
|
||||
if (hex[0] !== '#') {
|
||||
return -1;
|
||||
}
|
||||
hex = exports.hexToRGB(hex);
|
||||
r1 = hex[0], g1 = hex[1], b1 = hex[2];
|
||||
} else if (Array.isArray(r1)) {
|
||||
b1 = r1[2], g1 = r1[1], r1 = r1[0];
|
||||
}
|
||||
|
||||
var hash = (r1 << 16) | (g1 << 8) | b1;
|
||||
|
||||
if (exports._cache[hash] != null) {
|
||||
return exports._cache[hash];
|
||||
}
|
||||
|
||||
var ldiff = Infinity
|
||||
, li = -1
|
||||
, i = 0
|
||||
, c
|
||||
, r2
|
||||
, g2
|
||||
, b2
|
||||
, diff;
|
||||
|
||||
for (; i < exports.vcolors.length; i++) {
|
||||
c = exports.vcolors[i];
|
||||
r2 = c[0];
|
||||
g2 = c[1];
|
||||
b2 = c[2];
|
||||
|
||||
diff = colorDistance(r1, g1, b1, r2, g2, b2);
|
||||
|
||||
if (diff === 0) {
|
||||
li = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (diff < ldiff) {
|
||||
ldiff = diff;
|
||||
li = i;
|
||||
}
|
||||
}
|
||||
|
||||
return exports._cache[hash] = li;
|
||||
};
|
||||
|
||||
exports.RGBToHex = function(r, g, b) {
|
||||
if (Array.isArray(r)) {
|
||||
b = r[2], g = r[1], r = r[0];
|
||||
}
|
||||
|
||||
function hex(n) {
|
||||
n = n.toString(16);
|
||||
if (n.length < 2) n = '0' + n;
|
||||
return n;
|
||||
}
|
||||
|
||||
return '#' + hex(r) + hex(g) + hex(b);
|
||||
};
|
||||
|
||||
exports.hexToRGB = function(hex) {
|
||||
if (hex.length === 4) {
|
||||
hex = hex[0]
|
||||
+ hex[1] + hex[1]
|
||||
+ hex[2] + hex[2]
|
||||
+ hex[3] + hex[3];
|
||||
}
|
||||
|
||||
var col = parseInt(hex.substring(1), 16)
|
||||
, r = (col >> 16) & 0xff
|
||||
, g = (col >> 8) & 0xff
|
||||
, b = col & 0xff;
|
||||
|
||||
return [r, g, b];
|
||||
};
|
||||
|
||||
// As it happens, comparing how similar two colors are is really hard. Here is
|
||||
// one of the simplest solutions, which doesn't require conversion to another
|
||||
// color space, posted on stackoverflow[1]. Maybe someone better at math can
|
||||
// propose a superior solution.
|
||||
// [1] http://stackoverflow.com/questions/1633828
|
||||
|
||||
function colorDistance(r1, g1, b1, r2, g2, b2) {
|
||||
return Math.pow(30 * (r1 - r2), 2)
|
||||
+ Math.pow(59 * (g1 - g2), 2)
|
||||
+ Math.pow(11 * (b1 - b2), 2);
|
||||
}
|
||||
|
||||
// This might work well enough for a terminal's colors: treat RGB as XYZ in a
|
||||
// 3-dimensional space and go midway between the two points.
|
||||
exports.mixColors = function(c1, c2, alpha) {
|
||||
// if (c1 === 0x1ff) return c1;
|
||||
// if (c2 === 0x1ff) return c1;
|
||||
if (c1 === 0x1ff) c1 = 0;
|
||||
if (c2 === 0x1ff) c2 = 0;
|
||||
if (alpha == null) alpha = 0.5;
|
||||
|
||||
c1 = exports.vcolors[c1];
|
||||
var r1 = c1[0];
|
||||
var g1 = c1[1];
|
||||
var b1 = c1[2];
|
||||
|
||||
c2 = exports.vcolors[c2];
|
||||
var r2 = c2[0];
|
||||
var g2 = c2[1];
|
||||
var b2 = c2[2];
|
||||
|
||||
r1 += (r2 - r1) * alpha | 0;
|
||||
g1 += (g2 - g1) * alpha | 0;
|
||||
b1 += (b2 - b1) * alpha | 0;
|
||||
|
||||
return exports.match([r1, g1, b1]);
|
||||
};
|
||||
|
||||
exports.blend = function blend(attr, attr2, alpha) {
|
||||
var name, i, c, nc;
|
||||
|
||||
var bg = attr & 0x1ff;
|
||||
if (attr2 != null) {
|
||||
var bg2 = attr2 & 0x1ff;
|
||||
if (bg === 0x1ff) bg = 0;
|
||||
if (bg2 === 0x1ff) bg2 = 0;
|
||||
bg = exports.mixColors(bg, bg2, alpha);
|
||||
} else {
|
||||
if (blend._cache[bg] != null) {
|
||||
bg = blend._cache[bg];
|
||||
// } else if (bg < 8) {
|
||||
// bg += 8;
|
||||
} else if (bg >= 8 && bg <= 15) {
|
||||
bg -= 8;
|
||||
} else {
|
||||
name = exports.ncolors[bg];
|
||||
if (name) {
|
||||
for (i = 0; i < exports.ncolors.length; i++) {
|
||||
if (name === exports.ncolors[i] && i !== bg) {
|
||||
c = exports.vcolors[bg];
|
||||
nc = exports.vcolors[i];
|
||||
if (nc[0] + nc[1] + nc[2] < c[0] + c[1] + c[2]) {
|
||||
blend._cache[bg] = i;
|
||||
bg = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
attr &= ~0x1ff;
|
||||
attr |= bg;
|
||||
|
||||
var fg = (attr >> 9) & 0x1ff;
|
||||
if (attr2 != null) {
|
||||
var fg2 = (attr2 >> 9) & 0x1ff;
|
||||
// 0, 7, 188, 231, 251
|
||||
if (fg === 0x1ff) {
|
||||
// XXX workaround
|
||||
fg = 248;
|
||||
} else {
|
||||
if (fg === 0x1ff) fg = 7;
|
||||
if (fg2 === 0x1ff) fg2 = 7;
|
||||
fg = exports.mixColors(fg, fg2, alpha);
|
||||
}
|
||||
} else {
|
||||
if (blend._cache[fg] != null) {
|
||||
fg = blend._cache[fg];
|
||||
// } else if (fg < 8) {
|
||||
// fg += 8;
|
||||
} else if (fg >= 8 && fg <= 15) {
|
||||
fg -= 8;
|
||||
} else {
|
||||
name = exports.ncolors[fg];
|
||||
if (name) {
|
||||
for (i = 0; i < exports.ncolors.length; i++) {
|
||||
if (name === exports.ncolors[i] && i !== fg) {
|
||||
c = exports.vcolors[fg];
|
||||
nc = exports.vcolors[i];
|
||||
if (nc[0] + nc[1] + nc[2] < c[0] + c[1] + c[2]) {
|
||||
blend._cache[fg] = i;
|
||||
fg = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
attr &= ~(0x1ff << 9);
|
||||
attr |= fg << 9;
|
||||
|
||||
return attr;
|
||||
};
|
||||
|
||||
exports.blend._cache = {};
|
||||
|
||||
exports._cache = {};
|
||||
|
||||
exports.reduce = function(color, total) {
|
||||
if (color >= 16 && total <= 16) {
|
||||
color = exports.ccolors[color];
|
||||
} else if (color >= 8 && total <= 8) {
|
||||
color -= 8;
|
||||
} else if (color >= 2 && total <= 2) {
|
||||
color %= 2;
|
||||
}
|
||||
return color;
|
||||
};
|
||||
|
||||
// XTerm Colors
|
||||
// These were actually tough to track down. The xterm source only uses color
|
||||
// keywords. The X11 source needed to be examined to find the actual values.
|
||||
// They then had to be mapped to rgb values and then converted to hex values.
|
||||
exports.xterm = [
|
||||
'#000000', // black
|
||||
'#cd0000', // red3
|
||||
'#00cd00', // green3
|
||||
'#cdcd00', // yellow3
|
||||
'#0000ee', // blue2
|
||||
'#cd00cd', // magenta3
|
||||
'#00cdcd', // cyan3
|
||||
'#e5e5e5', // gray90
|
||||
'#7f7f7f', // gray50
|
||||
'#ff0000', // red
|
||||
'#00ff00', // green
|
||||
'#ffff00', // yellow
|
||||
'#5c5cff', // rgb:5c/5c/ff
|
||||
'#ff00ff', // magenta
|
||||
'#00ffff', // cyan
|
||||
'#ffffff' // white
|
||||
];
|
||||
|
||||
// Seed all 256 colors. Assume xterm defaults.
|
||||
// Ported from the xterm color generation script.
|
||||
exports.colors = (function() {
|
||||
var cols = exports.colors = []
|
||||
, _cols = exports.vcolors = []
|
||||
, r
|
||||
, g
|
||||
, b
|
||||
, i
|
||||
, l;
|
||||
|
||||
function hex(n) {
|
||||
n = n.toString(16);
|
||||
if (n.length < 2) n = '0' + n;
|
||||
return n;
|
||||
}
|
||||
|
||||
function push(i, r, g, b) {
|
||||
cols[i] = '#' + hex(r) + hex(g) + hex(b);
|
||||
_cols[i] = [r, g, b];
|
||||
}
|
||||
|
||||
// 0 - 15
|
||||
exports.xterm.forEach(function(c, i) {
|
||||
c = parseInt(c.substring(1), 16);
|
||||
push(i, (c >> 16) & 0xff, (c >> 8) & 0xff, c & 0xff);
|
||||
});
|
||||
|
||||
// 16 - 231
|
||||
for (r = 0; r < 6; r++) {
|
||||
for (g = 0; g < 6; g++) {
|
||||
for (b = 0; b < 6; b++) {
|
||||
i = 16 + (r * 36) + (g * 6) + b;
|
||||
push(i,
|
||||
r ? (r * 40 + 55) : 0,
|
||||
g ? (g * 40 + 55) : 0,
|
||||
b ? (b * 40 + 55) : 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 232 - 255 are grey.
|
||||
for (g = 0; g < 24; g++) {
|
||||
l = (g * 10) + 8;
|
||||
i = 232 + g;
|
||||
push(i, l, l, l);
|
||||
}
|
||||
|
||||
return cols;
|
||||
})();
|
||||
|
||||
// Map higher colors to the first 8 colors.
|
||||
// This allows translation of high colors to low colors on 8-color terminals.
|
||||
exports.ccolors = (function() {
|
||||
var _cols = exports.vcolors.slice()
|
||||
, cols = exports.colors.slice()
|
||||
, out;
|
||||
|
||||
exports.vcolors = exports.vcolors.slice(0, 8);
|
||||
exports.colors = exports.colors.slice(0, 8);
|
||||
|
||||
out = cols.map(exports.match);
|
||||
|
||||
exports.colors = cols;
|
||||
exports.vcolors = _cols;
|
||||
exports.ccolors = out;
|
||||
|
||||
return out;
|
||||
})();
|
||||
|
||||
var colorNames = exports.colorNames = {
|
||||
// special
|
||||
default: -1,
|
||||
normal: -1,
|
||||
bg: -1,
|
||||
fg: -1,
|
||||
// normal
|
||||
black: 0,
|
||||
red: 1,
|
||||
green: 2,
|
||||
yellow: 3,
|
||||
blue: 4,
|
||||
magenta: 5,
|
||||
cyan: 6,
|
||||
white: 7,
|
||||
// light
|
||||
lightblack: 8,
|
||||
lightred: 9,
|
||||
lightgreen: 10,
|
||||
lightyellow: 11,
|
||||
lightblue: 12,
|
||||
lightmagenta: 13,
|
||||
lightcyan: 14,
|
||||
lightwhite: 15,
|
||||
// bright
|
||||
brightblack: 8,
|
||||
brightred: 9,
|
||||
brightgreen: 10,
|
||||
brightyellow: 11,
|
||||
brightblue: 12,
|
||||
brightmagenta: 13,
|
||||
brightcyan: 14,
|
||||
brightwhite: 15,
|
||||
// alternate spellings
|
||||
grey: 8,
|
||||
gray: 8,
|
||||
lightgrey: 7,
|
||||
lightgray: 7,
|
||||
brightgrey: 7,
|
||||
brightgray: 7
|
||||
};
|
||||
|
||||
exports.convert = function(color) {
|
||||
if (typeof color === 'number') {
|
||||
;
|
||||
} else if (typeof color === 'string') {
|
||||
color = color.replace(/[\- ]/g, '');
|
||||
if (colorNames[color] != null) {
|
||||
color = colorNames[color];
|
||||
} else {
|
||||
color = exports.match(color);
|
||||
}
|
||||
} else if (Array.isArray(color)) {
|
||||
color = exports.match(color);
|
||||
} else {
|
||||
color = -1;
|
||||
}
|
||||
return color !== -1 ? color : 0x1ff;
|
||||
};
|
||||
|
||||
// Map higher colors to the first 8 colors.
|
||||
// This allows translation of high colors to low colors on 8-color terminals.
|
||||
// Why the hell did I do this by hand?
|
||||
exports.ccolors = {
|
||||
blue: [
|
||||
4,
|
||||
12,
|
||||
[17, 21],
|
||||
[24, 27],
|
||||
[31, 33],
|
||||
[38, 39],
|
||||
45,
|
||||
[54, 57],
|
||||
[60, 63],
|
||||
[67, 69],
|
||||
[74, 75],
|
||||
81,
|
||||
[91, 93],
|
||||
[97, 99],
|
||||
[103, 105],
|
||||
[110, 111],
|
||||
117,
|
||||
[128, 129],
|
||||
[134, 135],
|
||||
[140, 141],
|
||||
[146, 147],
|
||||
153,
|
||||
165,
|
||||
171,
|
||||
177,
|
||||
183,
|
||||
189
|
||||
],
|
||||
|
||||
green: [
|
||||
2,
|
||||
10,
|
||||
22,
|
||||
[28, 29],
|
||||
[34, 36],
|
||||
[40, 43],
|
||||
[46, 50],
|
||||
[64, 65],
|
||||
[70, 72],
|
||||
[76, 79],
|
||||
[82, 86],
|
||||
[106, 108],
|
||||
[112, 115],
|
||||
[118, 122],
|
||||
[148, 151],
|
||||
[154, 158],
|
||||
[190, 194]
|
||||
],
|
||||
|
||||
cyan: [
|
||||
6,
|
||||
14,
|
||||
23,
|
||||
30,
|
||||
37,
|
||||
44,
|
||||
51,
|
||||
66,
|
||||
73,
|
||||
80,
|
||||
87,
|
||||
109,
|
||||
116,
|
||||
123,
|
||||
152,
|
||||
159,
|
||||
195
|
||||
],
|
||||
|
||||
red: [
|
||||
1,
|
||||
9,
|
||||
52,
|
||||
[88, 89],
|
||||
[94, 95],
|
||||
[124, 126],
|
||||
[130, 132],
|
||||
[136, 138],
|
||||
[160, 163],
|
||||
[166, 169],
|
||||
[172, 175],
|
||||
[178, 181],
|
||||
[196, 200],
|
||||
[202, 206],
|
||||
[208, 212],
|
||||
[214, 218],
|
||||
[220, 224]
|
||||
],
|
||||
|
||||
magenta: [
|
||||
5,
|
||||
13,
|
||||
53,
|
||||
90,
|
||||
96,
|
||||
127,
|
||||
133,
|
||||
139,
|
||||
164,
|
||||
170,
|
||||
176,
|
||||
182,
|
||||
201,
|
||||
207,
|
||||
213,
|
||||
219,
|
||||
225
|
||||
],
|
||||
|
||||
yellow: [
|
||||
3,
|
||||
11,
|
||||
58,
|
||||
[100, 101],
|
||||
[142, 144],
|
||||
[184, 187],
|
||||
[226, 230]
|
||||
],
|
||||
|
||||
black: [
|
||||
0,
|
||||
8,
|
||||
16,
|
||||
59,
|
||||
102,
|
||||
[232, 243]
|
||||
],
|
||||
|
||||
white: [
|
||||
7,
|
||||
15,
|
||||
145,
|
||||
188,
|
||||
231,
|
||||
[244, 255]
|
||||
]
|
||||
};
|
||||
|
||||
exports.ncolors = [];
|
||||
|
||||
Object.keys(exports.ccolors).forEach(function(name) {
|
||||
exports.ccolors[name].forEach(function(offset) {
|
||||
if (typeof offset === 'number') {
|
||||
exports.ncolors[offset] = name;
|
||||
exports.ccolors[offset] = exports.colorNames[name];
|
||||
return;
|
||||
}
|
||||
for (var i = offset[0], l = offset[1]; i <= l; i++) {
|
||||
exports.ncolors[i] = name;
|
||||
exports.ccolors[i] = exports.colorNames[name];
|
||||
}
|
||||
});
|
||||
delete exports.ccolors[name];
|
||||
});
|
||||
189
lib/events.js
Normal file
@ -0,0 +1,189 @@
|
||||
/**
|
||||
* events.js - event emitter for blessed
|
||||
* Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
var slice = Array.prototype.slice;
|
||||
|
||||
/**
|
||||
* EventEmitter
|
||||
*/
|
||||
|
||||
function EventEmitter() {
|
||||
if (!this._events) this._events = {};
|
||||
}
|
||||
|
||||
EventEmitter.prototype.setMaxListeners = function(n) {
|
||||
this._maxListeners = n;
|
||||
};
|
||||
|
||||
EventEmitter.prototype.addListener = function(type, listener) {
|
||||
if (!this._events[type]) {
|
||||
this._events[type] = listener;
|
||||
} else if (typeof this._events[type] === 'function') {
|
||||
this._events[type] = [this._events[type], listener];
|
||||
} else {
|
||||
this._events[type].push(listener);
|
||||
}
|
||||
this._emit('newListener', [type, listener]);
|
||||
};
|
||||
|
||||
EventEmitter.prototype.on = EventEmitter.prototype.addListener;
|
||||
|
||||
EventEmitter.prototype.removeListener = function(type, listener) {
|
||||
var handler = this._events[type];
|
||||
if (!handler) return;
|
||||
|
||||
if (typeof handler === 'function' || handler.length === 1) {
|
||||
delete this._events[type];
|
||||
this._emit('removeListener', [type, listener]);
|
||||
return;
|
||||
}
|
||||
|
||||
for (var i = 0; i < handler.length; i++) {
|
||||
if (handler[i] === listener || handler[i].listener === listener) {
|
||||
handler.splice(i, 1);
|
||||
this._emit('removeListener', [type, listener]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
|
||||
|
||||
EventEmitter.prototype.removeAllListeners = function(type) {
|
||||
if (type) {
|
||||
delete this._events[type];
|
||||
} else {
|
||||
this._events = {};
|
||||
}
|
||||
};
|
||||
|
||||
EventEmitter.prototype.once = function(type, listener) {
|
||||
function on() {
|
||||
this.removeListener(type, on);
|
||||
return listener.apply(this, arguments);
|
||||
}
|
||||
on.listener = listener;
|
||||
return this.on(type, on);
|
||||
};
|
||||
|
||||
EventEmitter.prototype.listeners = function(type) {
|
||||
return typeof this._events[type] === 'function'
|
||||
? [this._events[type]]
|
||||
: this._events[type] || [];
|
||||
};
|
||||
|
||||
EventEmitter.prototype._emit = function(type, args) {
|
||||
var handler = this._events[type]
|
||||
, ret;
|
||||
|
||||
// if (type !== 'event') {
|
||||
// this._emit('event', [type.replace(/^element /, '')].concat(args));
|
||||
// }
|
||||
|
||||
if (!handler) {
|
||||
if (type === 'error') {
|
||||
throw new args[0];
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof handler === 'function') {
|
||||
return handler.apply(this, args);
|
||||
}
|
||||
|
||||
for (var i = 0; i < handler.length; i++) {
|
||||
if (handler[i].apply(this, args) === false) {
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
|
||||
return ret !== false;
|
||||
};
|
||||
|
||||
EventEmitter.prototype.emit = function(type) {
|
||||
var args = slice.call(arguments, 1)
|
||||
, params = slice.call(arguments)
|
||||
, el = this;
|
||||
|
||||
this._emit('event', params);
|
||||
|
||||
if (this.type === 'screen') {
|
||||
return this._emit(type, args);
|
||||
}
|
||||
|
||||
if (this._emit(type, args) === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
type = 'element ' + type;
|
||||
args.unshift(this);
|
||||
// `element` prefix
|
||||
// params = [type].concat(args);
|
||||
// no `element` prefix
|
||||
// params.splice(1, 0, this);
|
||||
|
||||
do {
|
||||
// el._emit('event', params);
|
||||
if (!el._events[type]) continue;
|
||||
if (el._emit(type, args) === false) {
|
||||
return false;
|
||||
}
|
||||
} while (el = el.parent);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
// For hooking into the main EventEmitter if we want to.
|
||||
// Might be better to do things this way being that it
|
||||
// will always be compatible with node, not to mention
|
||||
// it gives us domain support as well.
|
||||
// Node.prototype._emit = Node.prototype.emit;
|
||||
// Node.prototype.emit = function(type) {
|
||||
// var args, el;
|
||||
//
|
||||
// if (this.type === 'screen') {
|
||||
// return this._emit.apply(this, arguments);
|
||||
// }
|
||||
//
|
||||
// this._emit.apply(this, arguments);
|
||||
// if (this._bubbleStopped) return false;
|
||||
//
|
||||
// args = slice.call(arguments, 1);
|
||||
// el = this;
|
||||
//
|
||||
// args.unshift('element ' + type, this);
|
||||
// this._bubbleStopped = false;
|
||||
// //args.push(stopBubble);
|
||||
//
|
||||
// do {
|
||||
// if (!el._events || !el._events[type]) continue;
|
||||
// el._emit.apply(el, args);
|
||||
// if (this._bubbleStopped) return false;
|
||||
// } while (el = el.parent);
|
||||
//
|
||||
// return true;
|
||||
// };
|
||||
//
|
||||
// Node.prototype._addListener = Node.prototype.addListener;
|
||||
// Node.prototype.on =
|
||||
// Node.prototype.addListener = function(type, listener) {
|
||||
// function on() {
|
||||
// if (listener.apply(this, arguments) === false) {
|
||||
// this._bubbleStopped = true;
|
||||
// }
|
||||
// }
|
||||
// on.listener = listener;
|
||||
// return this._addListener(type, on);
|
||||
// };
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
exports = EventEmitter;
|
||||
exports.EventEmitter = EventEmitter;
|
||||
|
||||
module.exports = exports;
|
||||
221
lib/gpmclient.js
Normal file
@ -0,0 +1,221 @@
|
||||
/**
|
||||
* gpmclient.js - support the gpm mouse protocol
|
||||
* Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
var net = require('net');
|
||||
var fs = require('fs');
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
|
||||
var GPM_USE_MAGIC = false;
|
||||
|
||||
var GPM_MOVE = 1
|
||||
, GPM_DRAG = 2
|
||||
, GPM_DOWN = 4
|
||||
, GPM_UP = 8;
|
||||
|
||||
var GPM_DOUBLE = 32
|
||||
, GPM_MFLAG = 128;
|
||||
|
||||
var GPM_REQ_NOPASTE = 3
|
||||
, GPM_HARD = 256;
|
||||
|
||||
var GPM_MAGIC = 0x47706D4C;
|
||||
var GPM_SOCKET = '/dev/gpmctl';
|
||||
|
||||
// typedef struct Gpm_Connect {
|
||||
// unsigned short eventMask, defaultMask;
|
||||
// unsigned short minMod, maxMod;
|
||||
// int pid;
|
||||
// int vc;
|
||||
// } Gpm_Connect;
|
||||
|
||||
function send_config(socket, Gpm_Connect, callback) {
|
||||
var buffer;
|
||||
if (GPM_USE_MAGIC) {
|
||||
buffer = new Buffer(20);
|
||||
buffer.writeUInt32LE(GPM_MAGIC, 0);
|
||||
buffer.writeUInt16LE(Gpm_Connect.eventMask, 4);
|
||||
buffer.writeUInt16LE(Gpm_Connect.defaultMask, 6);
|
||||
buffer.writeUInt16LE(Gpm_Connect.minMod, 8);
|
||||
buffer.writeUInt16LE(Gpm_Connect.maxMod, 10);
|
||||
buffer.writeInt16LE(process.pid, 12);
|
||||
buffer.writeInt16LE(Gpm_Connect.vc, 16);
|
||||
} else {
|
||||
buffer = new Buffer(16);
|
||||
buffer.writeUInt16LE(Gpm_Connect.eventMask, 0);
|
||||
buffer.writeUInt16LE(Gpm_Connect.defaultMask, 2);
|
||||
buffer.writeUInt16LE(Gpm_Connect.minMod, 4);
|
||||
buffer.writeUInt16LE(Gpm_Connect.maxMod, 6);
|
||||
buffer.writeInt16LE(Gpm_Connect.pid, 8);
|
||||
buffer.writeInt16LE(Gpm_Connect.vc, 12);
|
||||
}
|
||||
socket.write(buffer, function() {
|
||||
if (callback) callback();
|
||||
});
|
||||
}
|
||||
|
||||
// typedef struct Gpm_Event {
|
||||
// unsigned char buttons, modifiers; // try to be a multiple of 4
|
||||
// unsigned short vc;
|
||||
// short dx, dy, x, y; // displacement x,y for this event, and absolute x,y
|
||||
// enum Gpm_Etype type;
|
||||
// // clicks e.g. double click are determined by time-based processing
|
||||
// int clicks;
|
||||
// enum Gpm_Margin margin;
|
||||
// // wdx/y: displacement of wheels in this event. Absolute values are not
|
||||
// // required, because wheel movement is typically used for scrolling
|
||||
// // or selecting fields, not for cursor positioning. The application
|
||||
// // can determine when the end of file or form is reached, and not
|
||||
// // go any further.
|
||||
// // A single mouse will use wdy, "vertical scroll" wheel.
|
||||
// short wdx, wdy;
|
||||
// } Gpm_Event;
|
||||
|
||||
function parseEvent(raw) {
|
||||
var evnt = {};
|
||||
evnt.buttons = raw[0];
|
||||
evnt.modifiers = raw[1];
|
||||
evnt.vc = raw.readUInt16LE(2);
|
||||
evnt.dx = raw.readInt16LE(4);
|
||||
evnt.dy = raw.readInt16LE(6);
|
||||
evnt.x = raw.readInt16LE(8);
|
||||
evnt.y = raw.readInt16LE(10);
|
||||
evnt.type = raw.readInt16LE(12);
|
||||
evnt.clicks = raw.readInt32LE(16);
|
||||
evnt.margin = raw.readInt32LE(20);
|
||||
evnt.wdx = raw.readInt16LE(24);
|
||||
evnt.wdy = raw.readInt16LE(26);
|
||||
return evnt;
|
||||
}
|
||||
|
||||
function GpmClient(options) {
|
||||
if (!(this instanceof GpmClient)) {
|
||||
return new GpmClient(options);
|
||||
}
|
||||
|
||||
EventEmitter.call(this);
|
||||
|
||||
var pid = process.pid;
|
||||
|
||||
// check tty for /dev/tty[n]
|
||||
var path;
|
||||
try {
|
||||
path = fs.readlinkSync('/proc/' + pid + '/fd/0');
|
||||
} catch (e) {
|
||||
;
|
||||
}
|
||||
var tty = /tty[0-9]+$/.exec(path);
|
||||
if (tty === null) {
|
||||
// TODO: should also check for /dev/input/..
|
||||
}
|
||||
|
||||
var vc;
|
||||
if (tty) {
|
||||
tty = tty[0];
|
||||
vc = +/[0-9]+$/.exec(tty)[0];
|
||||
}
|
||||
|
||||
var self = this;
|
||||
|
||||
if (tty) {
|
||||
fs.stat(GPM_SOCKET, function(err, stat) {
|
||||
if (err || !stat.isSocket()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var conf = {
|
||||
eventMask: 0xffff,
|
||||
defaultMask: GPM_MOVE | GPM_HARD,
|
||||
minMod: 0,
|
||||
maxMod: 0xffff,
|
||||
pid: pid,
|
||||
vc: vc
|
||||
};
|
||||
|
||||
var gpm = net.createConnection(GPM_SOCKET);
|
||||
this.gpm = gpm;
|
||||
|
||||
gpm.on('connect', function() {
|
||||
send_config(gpm, conf, function() {
|
||||
conf.pid = 0;
|
||||
conf.vc = GPM_REQ_NOPASTE;
|
||||
//send_config(gpm, conf);
|
||||
});
|
||||
});
|
||||
|
||||
gpm.on('data', function(packet) {
|
||||
var evnt = parseEvent(packet);
|
||||
switch (evnt.type & 15) {
|
||||
case GPM_MOVE:
|
||||
if (evnt.dx || evnt.dy) {
|
||||
self.emit('move', evnt.buttons, evnt.modifiers, evnt.x, evnt.y);
|
||||
}
|
||||
if (evnt.wdx || evnt.wdy) {
|
||||
self.emit('mousewheel',
|
||||
evnt.buttons, evnt.modifiers,
|
||||
evnt.x, evnt.y, evnt.wdx, evnt.wdy);
|
||||
}
|
||||
break;
|
||||
case GPM_DRAG:
|
||||
if (evnt.dx || evnt.dy) {
|
||||
self.emit('drag', evnt.buttons, evnt.modifiers, evnt.x, evnt.y);
|
||||
}
|
||||
if (evnt.wdx || evnt.wdy) {
|
||||
self.emit('mousewheel',
|
||||
evnt.buttons, evnt.modifiers,
|
||||
evnt.x, evnt.y, evnt.wdx, evnt.wdy);
|
||||
}
|
||||
break;
|
||||
case GPM_DOWN:
|
||||
self.emit('btndown', evnt.buttons, evnt.modifiers, evnt.x, evnt.y);
|
||||
if (evnt.type & GPM_DOUBLE) {
|
||||
self.emit('dblclick', evnt.buttons, evnt.modifiers, evnt.x, evnt.y);
|
||||
}
|
||||
break;
|
||||
case GPM_UP:
|
||||
self.emit('btnup', evnt.buttons, evnt.modifiers, evnt.x, evnt.y);
|
||||
if (!(evnt.type & GPM_MFLAG)) {
|
||||
self.emit('click', evnt.buttons, evnt.modifiers, evnt.x, evnt.y);
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
gpm.on('error', function() {
|
||||
self.stop();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
GpmClient.prototype.__proto__ = EventEmitter.prototype;
|
||||
|
||||
GpmClient.prototype.stop = function() {
|
||||
if (this.gpm) {
|
||||
this.gpm.end();
|
||||
}
|
||||
delete this.gpm;
|
||||
};
|
||||
|
||||
GpmClient.prototype.ButtonName = function(btn) {
|
||||
if (btn & 4) return 'left';
|
||||
if (btn & 2) return 'middle';
|
||||
if (btn & 1) return 'right';
|
||||
return '';
|
||||
};
|
||||
|
||||
GpmClient.prototype.hasShiftKey = function(mod) {
|
||||
return (mod & 1) ? true : false;
|
||||
};
|
||||
|
||||
GpmClient.prototype.hasCtrlKey = function(mod) {
|
||||
return (mod & 4) ? true : false;
|
||||
};
|
||||
|
||||
GpmClient.prototype.hasMetaKey = function(mod) {
|
||||
return (mod & 8) ? true : false;
|
||||
};
|
||||
|
||||
module.exports = GpmClient;
|
||||
165
lib/helpers.js
Normal file
@ -0,0 +1,165 @@
|
||||
/**
|
||||
* helpers.js - helpers for blessed
|
||||
* Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Modules
|
||||
*/
|
||||
|
||||
var fs = require('fs');
|
||||
|
||||
var unicode = require('./unicode');
|
||||
|
||||
/**
|
||||
* Helpers
|
||||
*/
|
||||
|
||||
var helpers = exports;
|
||||
|
||||
helpers.merge = function(a, b) {
|
||||
Object.keys(b).forEach(function(key) {
|
||||
a[key] = b[key];
|
||||
});
|
||||
return a;
|
||||
};
|
||||
|
||||
helpers.asort = function(obj) {
|
||||
return obj.sort(function(a, b) {
|
||||
a = a.name.toLowerCase();
|
||||
b = b.name.toLowerCase();
|
||||
|
||||
if (a[0] === '.' && b[0] === '.') {
|
||||
a = a[1];
|
||||
b = b[1];
|
||||
} else {
|
||||
a = a[0];
|
||||
b = b[0];
|
||||
}
|
||||
|
||||
return a > b ? 1 : (a < b ? -1 : 0);
|
||||
});
|
||||
};
|
||||
|
||||
helpers.hsort = function(obj) {
|
||||
return obj.sort(function(a, b) {
|
||||
return b.index - a.index;
|
||||
});
|
||||
};
|
||||
|
||||
helpers.findFile = function(start, target) {
|
||||
return (function read(dir) {
|
||||
var files, file, stat, out;
|
||||
|
||||
if (dir === '/dev' || dir === '/sys'
|
||||
|| dir === '/proc' || dir === '/net') {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
files = fs.readdirSync(dir);
|
||||
} catch (e) {
|
||||
files = [];
|
||||
}
|
||||
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
file = files[i];
|
||||
|
||||
if (file === target) {
|
||||
return (dir === '/' ? '' : dir) + '/' + file;
|
||||
}
|
||||
|
||||
try {
|
||||
stat = fs.lstatSync((dir === '/' ? '' : dir) + '/' + file);
|
||||
} catch (e) {
|
||||
stat = null;
|
||||
}
|
||||
|
||||
if (stat && stat.isDirectory() && !stat.isSymbolicLink()) {
|
||||
out = read((dir === '/' ? '' : dir) + '/' + file);
|
||||
if (out) return out;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
})(start);
|
||||
};
|
||||
|
||||
// Escape text for tag-enabled elements.
|
||||
helpers.escape = function(text) {
|
||||
return text.replace(/[{}]/g, function(ch) {
|
||||
return ch === '{' ? '{open}' : '{close}';
|
||||
});
|
||||
};
|
||||
|
||||
helpers.parseTags = function(text, screen) {
|
||||
return helpers.Element.prototype._parseTags.call(
|
||||
{ parseTags: true, screen: screen || helpers.Screen.global }, text);
|
||||
};
|
||||
|
||||
helpers.generateTags = function(style, text) {
|
||||
var open = ''
|
||||
, close = '';
|
||||
|
||||
Object.keys(style || {}).forEach(function(key) {
|
||||
var val = style[key];
|
||||
if (typeof val === 'string') {
|
||||
val = val.replace(/^light(?!-)/, 'light-');
|
||||
val = val.replace(/^bright(?!-)/, 'bright-');
|
||||
open = '{' + val + '-' + key + '}' + open;
|
||||
close += '{/' + val + '-' + key + '}';
|
||||
} else {
|
||||
if (val === true) {
|
||||
open = '{' + key + '}' + open;
|
||||
close += '{/' + key + '}';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (text != null) {
|
||||
return open + text + close;
|
||||
}
|
||||
|
||||
return {
|
||||
open: open,
|
||||
close: close
|
||||
};
|
||||
};
|
||||
|
||||
helpers.attrToBinary = function(style, element) {
|
||||
return helpers.Element.prototype.sattr.call(element || {}, style);
|
||||
};
|
||||
|
||||
helpers.stripTags = function(text) {
|
||||
if (!text) return '';
|
||||
return text
|
||||
.replace(/{(\/?)([\w\-,;!#]*)}/g, '')
|
||||
.replace(/\x1b\[[\d;]*m/g, '');
|
||||
};
|
||||
|
||||
helpers.cleanTags = function(text) {
|
||||
return helpers.stripTags(text).trim();
|
||||
};
|
||||
|
||||
helpers.dropUnicode = function(text) {
|
||||
if (!text) return '';
|
||||
return text
|
||||
.replace(unicode.chars.all, '??')
|
||||
.replace(unicode.chars.combining, '')
|
||||
.replace(unicode.chars.surrogate, '?');
|
||||
};
|
||||
|
||||
helpers.__defineGetter__('Screen', function() {
|
||||
if (!helpers._screen) {
|
||||
helpers._screen = require('./widgets/screen');
|
||||
}
|
||||
return helpers._screen;
|
||||
});
|
||||
|
||||
helpers.__defineGetter__('Element', function() {
|
||||
if (!helpers._element) {
|
||||
helpers._element = require('./widgets/element');
|
||||
}
|
||||
return helpers._element;
|
||||
});
|
||||
339
lib/keys.js
Normal file
@ -0,0 +1,339 @@
|
||||
/**
|
||||
* keys.js - emit key presses
|
||||
* Copyright (c) 2010-2015, Joyent, Inc. and other contributors (MIT License)
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
// Originally taken from the node.js tree:
|
||||
//
|
||||
// Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
|
||||
// NOTE: node <=v0.8.x has no EventEmitter.listenerCount
|
||||
function listenerCount(stream, event) {
|
||||
return EventEmitter.listenerCount
|
||||
? EventEmitter.listenerCount(stream, event)
|
||||
: stream.listeners(event).length;
|
||||
}
|
||||
|
||||
/**
|
||||
* accepts a readable Stream instance and makes it emit "keypress" events
|
||||
*/
|
||||
|
||||
function emitKeypressEvents(stream) {
|
||||
if (stream._keypressDecoder) return;
|
||||
var StringDecoder = require('string_decoder').StringDecoder; // lazy load
|
||||
stream._keypressDecoder = new StringDecoder('utf8');
|
||||
|
||||
function onData(b) {
|
||||
if (listenerCount(stream, 'keypress') > 0) {
|
||||
var r = stream._keypressDecoder.write(b);
|
||||
if (r) emitKeys(stream, r);
|
||||
} else {
|
||||
// Nobody's watching anyway
|
||||
stream.removeListener('data', onData);
|
||||
stream.on('newListener', onNewListener);
|
||||
}
|
||||
}
|
||||
|
||||
function onNewListener(event) {
|
||||
if (event === 'keypress') {
|
||||
stream.on('data', onData);
|
||||
stream.removeListener('newListener', onNewListener);
|
||||
}
|
||||
}
|
||||
|
||||
if (listenerCount(stream, 'keypress') > 0) {
|
||||
stream.on('data', onData);
|
||||
} else {
|
||||
stream.on('newListener', onNewListener);
|
||||
}
|
||||
}
|
||||
exports.emitKeypressEvents = emitKeypressEvents;
|
||||
|
||||
/*
|
||||
Some patterns seen in terminal key escape codes, derived from combos seen
|
||||
at http://www.midnight-commander.org/browser/lib/tty/key.c
|
||||
|
||||
ESC letter
|
||||
ESC [ letter
|
||||
ESC [ modifier letter
|
||||
ESC [ 1 ; modifier letter
|
||||
ESC [ num char
|
||||
ESC [ num ; modifier char
|
||||
ESC O letter
|
||||
ESC O modifier letter
|
||||
ESC O 1 ; modifier letter
|
||||
ESC N letter
|
||||
ESC [ [ num ; modifier char
|
||||
ESC [ [ 1 ; modifier letter
|
||||
ESC ESC [ num char
|
||||
ESC ESC O letter
|
||||
|
||||
- char is usually ~ but $ and ^ also happen with rxvt
|
||||
- modifier is 1 +
|
||||
(shift * 1) +
|
||||
(left_alt * 2) +
|
||||
(ctrl * 4) +
|
||||
(right_alt * 8)
|
||||
- two leading ESCs apparently mean the same as one leading ESC
|
||||
*/
|
||||
|
||||
// Regexes used for ansi escape code splitting
|
||||
var metaKeyCodeReAnywhere = /(?:\x1b)([a-zA-Z0-9])/;
|
||||
var metaKeyCodeRe = new RegExp('^' + metaKeyCodeReAnywhere.source + '$');
|
||||
var functionKeyCodeReAnywhere = new RegExp('(?:\x1b+)(O|N|\\[|\\[\\[)(?:' + [
|
||||
'(\\d+)(?:;(\\d+))?([~^$])',
|
||||
'(?:M([@ #!a`])(.)(.))', // mouse
|
||||
'(?:1;)?(\\d+)?([a-zA-Z])'
|
||||
].join('|') + ')');
|
||||
var functionKeyCodeRe = new RegExp('^' + functionKeyCodeReAnywhere.source);
|
||||
var escapeCodeReAnywhere = new RegExp([
|
||||
functionKeyCodeReAnywhere.source, metaKeyCodeReAnywhere.source, /\x1b./.source
|
||||
].join('|'));
|
||||
|
||||
function emitKeys(stream, s) {
|
||||
if (Buffer.isBuffer(s)) {
|
||||
if (s[0] > 127 && s[1] === undefined) {
|
||||
s[0] -= 128;
|
||||
s = '\x1b' + s.toString(stream.encoding || 'utf-8');
|
||||
} else {
|
||||
s = s.toString(stream.encoding || 'utf-8');
|
||||
}
|
||||
}
|
||||
|
||||
if (isMouse(s)) return;
|
||||
|
||||
var buffer = [];
|
||||
var match;
|
||||
while (match = escapeCodeReAnywhere.exec(s)) {
|
||||
buffer = buffer.concat(s.slice(0, match.index).split(''));
|
||||
buffer.push(match[0]);
|
||||
s = s.slice(match.index + match[0].length);
|
||||
}
|
||||
buffer = buffer.concat(s.split(''));
|
||||
|
||||
buffer.forEach(function(s) {
|
||||
var ch,
|
||||
key = {
|
||||
sequence: s,
|
||||
name: undefined,
|
||||
ctrl: false,
|
||||
meta: false,
|
||||
shift: false
|
||||
},
|
||||
parts;
|
||||
|
||||
if (s === '\r') {
|
||||
// carriage return
|
||||
key.name = 'return';
|
||||
|
||||
} else if (s === '\n') {
|
||||
// enter, should have been called linefeed
|
||||
key.name = 'enter';
|
||||
// linefeed
|
||||
// key.name = 'linefeed';
|
||||
|
||||
} else if (s === '\t') {
|
||||
// tab
|
||||
key.name = 'tab';
|
||||
|
||||
} else if (s === '\b' || s === '\x7f' ||
|
||||
s === '\x1b\x7f' || s === '\x1b\b') {
|
||||
// backspace or ctrl+h
|
||||
key.name = 'backspace';
|
||||
key.meta = (s.charAt(0) === '\x1b');
|
||||
|
||||
} else if (s === '\x1b' || s === '\x1b\x1b') {
|
||||
// escape key
|
||||
key.name = 'escape';
|
||||
key.meta = (s.length === 2);
|
||||
|
||||
} else if (s === ' ' || s === '\x1b ') {
|
||||
key.name = 'space';
|
||||
key.meta = (s.length === 2);
|
||||
|
||||
} else if (s.length === 1 && s <= '\x1a') {
|
||||
// ctrl+letter
|
||||
key.name = String.fromCharCode(s.charCodeAt(0) + 'a'.charCodeAt(0) - 1);
|
||||
key.ctrl = true;
|
||||
|
||||
} else if (s.length === 1 && s >= 'a' && s <= 'z') {
|
||||
// lowercase letter
|
||||
key.name = s;
|
||||
|
||||
} else if (s.length === 1 && s >= 'A' && s <= 'Z') {
|
||||
// shift+letter
|
||||
key.name = s.toLowerCase();
|
||||
key.shift = true;
|
||||
|
||||
} else if (parts = metaKeyCodeRe.exec(s)) {
|
||||
// meta+character key
|
||||
key.name = parts[1].toLowerCase();
|
||||
key.meta = true;
|
||||
key.shift = /^[A-Z]$/.test(parts[1]);
|
||||
|
||||
} else if (parts = functionKeyCodeRe.exec(s)) {
|
||||
// ansi escape sequence
|
||||
|
||||
// reassemble the key code leaving out leading \x1b's,
|
||||
// the modifier key bitflag and any meaningless "1;" sequence
|
||||
var code = (parts[1] || '') + (parts[2] || '') +
|
||||
(parts[4] || '') + (parts[9] || ''),
|
||||
modifier = (parts[3] || parts[8] || 1) - 1;
|
||||
|
||||
// Parse the key modifier
|
||||
key.ctrl = !!(modifier & 4);
|
||||
key.meta = !!(modifier & 10);
|
||||
key.shift = !!(modifier & 1);
|
||||
key.code = code;
|
||||
|
||||
// Parse the key itself
|
||||
switch (code) {
|
||||
/* xterm/gnome ESC O letter */
|
||||
case 'OP': key.name = 'f1'; break;
|
||||
case 'OQ': key.name = 'f2'; break;
|
||||
case 'OR': key.name = 'f3'; break;
|
||||
case 'OS': key.name = 'f4'; break;
|
||||
|
||||
/* xterm/rxvt ESC [ number ~ */
|
||||
case '[11~': key.name = 'f1'; break;
|
||||
case '[12~': key.name = 'f2'; break;
|
||||
case '[13~': key.name = 'f3'; break;
|
||||
case '[14~': key.name = 'f4'; break;
|
||||
|
||||
/* from Cygwin and used in libuv */
|
||||
case '[[A': key.name = 'f1'; break;
|
||||
case '[[B': key.name = 'f2'; break;
|
||||
case '[[C': key.name = 'f3'; break;
|
||||
case '[[D': key.name = 'f4'; break;
|
||||
case '[[E': key.name = 'f5'; break;
|
||||
|
||||
/* common */
|
||||
case '[15~': key.name = 'f5'; break;
|
||||
case '[17~': key.name = 'f6'; break;
|
||||
case '[18~': key.name = 'f7'; break;
|
||||
case '[19~': key.name = 'f8'; break;
|
||||
case '[20~': key.name = 'f9'; break;
|
||||
case '[21~': key.name = 'f10'; break;
|
||||
case '[23~': key.name = 'f11'; break;
|
||||
case '[24~': key.name = 'f12'; break;
|
||||
|
||||
/* xterm ESC [ letter */
|
||||
case '[A': key.name = 'up'; break;
|
||||
case '[B': key.name = 'down'; break;
|
||||
case '[C': key.name = 'right'; break;
|
||||
case '[D': key.name = 'left'; break;
|
||||
case '[E': key.name = 'clear'; break;
|
||||
case '[F': key.name = 'end'; break;
|
||||
case '[H': key.name = 'home'; break;
|
||||
|
||||
/* xterm/gnome ESC O letter */
|
||||
case 'OA': key.name = 'up'; break;
|
||||
case 'OB': key.name = 'down'; break;
|
||||
case 'OC': key.name = 'right'; break;
|
||||
case 'OD': key.name = 'left'; break;
|
||||
case 'OE': key.name = 'clear'; break;
|
||||
case 'OF': key.name = 'end'; break;
|
||||
case 'OH': key.name = 'home'; break;
|
||||
|
||||
/* xterm/rxvt ESC [ number ~ */
|
||||
case '[1~': key.name = 'home'; break;
|
||||
case '[2~': key.name = 'insert'; break;
|
||||
case '[3~': key.name = 'delete'; break;
|
||||
case '[4~': key.name = 'end'; break;
|
||||
case '[5~': key.name = 'pageup'; break;
|
||||
case '[6~': key.name = 'pagedown'; break;
|
||||
|
||||
/* putty */
|
||||
case '[[5~': key.name = 'pageup'; break;
|
||||
case '[[6~': key.name = 'pagedown'; break;
|
||||
|
||||
/* rxvt */
|
||||
case '[7~': key.name = 'home'; break;
|
||||
case '[8~': key.name = 'end'; break;
|
||||
|
||||
/* rxvt keys with modifiers */
|
||||
case '[a': key.name = 'up'; key.shift = true; break;
|
||||
case '[b': key.name = 'down'; key.shift = true; break;
|
||||
case '[c': key.name = 'right'; key.shift = true; break;
|
||||
case '[d': key.name = 'left'; key.shift = true; break;
|
||||
case '[e': key.name = 'clear'; key.shift = true; break;
|
||||
|
||||
case '[2$': key.name = 'insert'; key.shift = true; break;
|
||||
case '[3$': key.name = 'delete'; key.shift = true; break;
|
||||
case '[5$': key.name = 'pageup'; key.shift = true; break;
|
||||
case '[6$': key.name = 'pagedown'; key.shift = true; break;
|
||||
case '[7$': key.name = 'home'; key.shift = true; break;
|
||||
case '[8$': key.name = 'end'; key.shift = true; break;
|
||||
|
||||
case 'Oa': key.name = 'up'; key.ctrl = true; break;
|
||||
case 'Ob': key.name = 'down'; key.ctrl = true; break;
|
||||
case 'Oc': key.name = 'right'; key.ctrl = true; break;
|
||||
case 'Od': key.name = 'left'; key.ctrl = true; break;
|
||||
case 'Oe': key.name = 'clear'; key.ctrl = true; break;
|
||||
|
||||
case '[2^': key.name = 'insert'; key.ctrl = true; break;
|
||||
case '[3^': key.name = 'delete'; key.ctrl = true; break;
|
||||
case '[5^': key.name = 'pageup'; key.ctrl = true; break;
|
||||
case '[6^': key.name = 'pagedown'; key.ctrl = true; break;
|
||||
case '[7^': key.name = 'home'; key.ctrl = true; break;
|
||||
case '[8^': key.name = 'end'; key.ctrl = true; break;
|
||||
|
||||
/* misc. */
|
||||
case '[Z': key.name = 'tab'; key.shift = true; break;
|
||||
default: key.name = 'undefined'; break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Don't emit a key if no name was found
|
||||
if (key.name === undefined) {
|
||||
key = undefined;
|
||||
}
|
||||
|
||||
if (s.length === 1) {
|
||||
ch = s;
|
||||
}
|
||||
|
||||
if (key || ch) {
|
||||
stream.emit('keypress', ch, key);
|
||||
// if (key && key.name === 'return') {
|
||||
// var nkey = {};
|
||||
// Object.keys(key).forEach(function(k) {
|
||||
// nkey[k] = key[k];
|
||||
// });
|
||||
// nkey.name = 'enter';
|
||||
// stream.emit('keypress', ch, nkey);
|
||||
// }
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function isMouse(s) {
|
||||
return /\x1b\[M/.test(s)
|
||||
|| /\x1b\[M([\x00\u0020-\uffff]{3})/.test(s)
|
||||
|| /\x1b\[(\d+;\d+;\d+)M/.test(s)
|
||||
|| /\x1b\[<(\d+;\d+;\d+)([mM])/.test(s)
|
||||
|| /\x1b\[<(\d+;\d+;\d+;\d+)&w/.test(s)
|
||||
|| /\x1b\[24([0135])~\[(\d+),(\d+)\]\r/.test(s)
|
||||
|| /\x1b\[(O|I)/.test(s);
|
||||
}
|
||||
3289
lib/program.js
3022
lib/tput.js
Normal file
790
lib/unicode.js
Normal file
@ -0,0 +1,790 @@
|
||||
/**
|
||||
* unicode.js - east asian width and surrogate pairs
|
||||
* Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
|
||||
* https://github.com/chjj/blessed
|
||||
* Borrowed from vangie/east-asian-width, komagata/eastasianwidth,
|
||||
* and mathiasbynens/String.prototype.codePointAt. Licenses below.
|
||||
*/
|
||||
|
||||
// east-asian-width
|
||||
//
|
||||
// Copyright (c) 2015 Vangie Du
|
||||
// https://github.com/vangie/east-asian-width
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
// eastasianwidth
|
||||
//
|
||||
// Copyright (c) 2013, Masaki Komagata
|
||||
// https://github.com/komagata/eastasianwidth
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
// String.prototype.codePointAt
|
||||
//
|
||||
// Copyright Mathias Bynens <https://mathiasbynens.be/>
|
||||
// https://github.com/mathiasbynens/String.prototype.codePointAt
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
// String.fromCodePoint
|
||||
//
|
||||
// Copyright Mathias Bynens <https://mathiasbynens.be/>
|
||||
// https://github.com/mathiasbynens/String.fromCodePoint
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var stringFromCharCode = String.fromCharCode;
|
||||
var floor = Math.floor;
|
||||
|
||||
/**
|
||||
* Wide, Surrogates, and Combining
|
||||
*/
|
||||
|
||||
exports.charWidth = function(str, i) {
|
||||
var point = typeof str !== 'number'
|
||||
? exports.codePointAt(str, i || 0)
|
||||
: str;
|
||||
|
||||
// nul
|
||||
if (point === 0) return 0;
|
||||
|
||||
// tab
|
||||
if (point === 0x09) {
|
||||
if (!exports.blessed) {
|
||||
exports.blessed = require('../');
|
||||
}
|
||||
return exports.blessed.screen.global
|
||||
? exports.blessed.screen.global.tabc.length
|
||||
: 8;
|
||||
}
|
||||
|
||||
// 8-bit control characters (2-width according to unicode??)
|
||||
if (point < 32 || (point >= 0x7f && point < 0xa0)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// search table of non-spacing characters
|
||||
// is ucs combining or C0/C1 control character
|
||||
if (exports.combining[point]) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// check for double-wide
|
||||
// if (point >= 0x1100
|
||||
// && (point <= 0x115f // Hangul Jamo init. consonants
|
||||
// || point === 0x2329 || point === 0x232a
|
||||
// || (point >= 0x2e80 && point <= 0xa4cf
|
||||
// && point !== 0x303f) // CJK ... Yi
|
||||
// || (point >= 0xac00 && point <= 0xd7a3) // Hangul Syllables
|
||||
// || (point >= 0xf900 && point <= 0xfaff) // CJK Compatibility Ideographs
|
||||
// || (point >= 0xfe10 && point <= 0xfe19) // Vertical forms
|
||||
// || (point >= 0xfe30 && point <= 0xfe6f) // CJK Compatibility Forms
|
||||
// || (point >= 0xff00 && point <= 0xff60) // Fullwidth Forms
|
||||
// || (point >= 0xffe0 && point <= 0xffe6)
|
||||
// || (point >= 0x20000 && point <= 0x2fffd)
|
||||
// || (point >= 0x30000 && point <= 0x3fffd))) {
|
||||
// return 2;
|
||||
// }
|
||||
|
||||
// check for double-wide
|
||||
if ((0x3000 === point)
|
||||
|| (0xFF01 <= point && point <= 0xFF60)
|
||||
|| (0xFFE0 <= point && point <= 0xFFE6)) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
if ((0x1100 <= point && point <= 0x115F)
|
||||
|| (0x11A3 <= point && point <= 0x11A7)
|
||||
|| (0x11FA <= point && point <= 0x11FF)
|
||||
|| (0x2329 <= point && point <= 0x232A)
|
||||
|| (0x2E80 <= point && point <= 0x2E99)
|
||||
|| (0x2E9B <= point && point <= 0x2EF3)
|
||||
|| (0x2F00 <= point && point <= 0x2FD5)
|
||||
|| (0x2FF0 <= point && point <= 0x2FFB)
|
||||
|| (0x3001 <= point && point <= 0x303E)
|
||||
|| (0x3041 <= point && point <= 0x3096)
|
||||
|| (0x3099 <= point && point <= 0x30FF)
|
||||
|| (0x3105 <= point && point <= 0x312D)
|
||||
|| (0x3131 <= point && point <= 0x318E)
|
||||
|| (0x3190 <= point && point <= 0x31BA)
|
||||
|| (0x31C0 <= point && point <= 0x31E3)
|
||||
|| (0x31F0 <= point && point <= 0x321E)
|
||||
|| (0x3220 <= point && point <= 0x3247)
|
||||
|| (0x3250 <= point && point <= 0x32FE)
|
||||
|| (0x3300 <= point && point <= 0x4DBF)
|
||||
|| (0x4E00 <= point && point <= 0xA48C)
|
||||
|| (0xA490 <= point && point <= 0xA4C6)
|
||||
|| (0xA960 <= point && point <= 0xA97C)
|
||||
|| (0xAC00 <= point && point <= 0xD7A3)
|
||||
|| (0xD7B0 <= point && point <= 0xD7C6)
|
||||
|| (0xD7CB <= point && point <= 0xD7FB)
|
||||
|| (0xF900 <= point && point <= 0xFAFF)
|
||||
|| (0xFE10 <= point && point <= 0xFE19)
|
||||
|| (0xFE30 <= point && point <= 0xFE52)
|
||||
|| (0xFE54 <= point && point <= 0xFE66)
|
||||
|| (0xFE68 <= point && point <= 0xFE6B)
|
||||
|| (0x1B000 <= point && point <= 0x1B001)
|
||||
|| (0x1F200 <= point && point <= 0x1F202)
|
||||
|| (0x1F210 <= point && point <= 0x1F23A)
|
||||
|| (0x1F240 <= point && point <= 0x1F248)
|
||||
|| (0x1F250 <= point && point <= 0x1F251)
|
||||
|| (0x20000 <= point && point <= 0x2F73F)
|
||||
|| (0x2B740 <= point && point <= 0x2FFFD)
|
||||
|| (0x30000 <= point && point <= 0x3FFFD)) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
// CJK Ambiguous
|
||||
// http://www.unicode.org/reports/tr11/
|
||||
// http://www.unicode.org/reports/tr11/#Ambiguous
|
||||
if (process.env.NCURSES_CJK_WIDTH) {
|
||||
if ((0x00A1 === point)
|
||||
|| (0x00A4 === point)
|
||||
|| (0x00A7 <= point && point <= 0x00A8)
|
||||
|| (0x00AA === point)
|
||||
|| (0x00AD <= point && point <= 0x00AE)
|
||||
|| (0x00B0 <= point && point <= 0x00B4)
|
||||
|| (0x00B6 <= point && point <= 0x00BA)
|
||||
|| (0x00BC <= point && point <= 0x00BF)
|
||||
|| (0x00C6 === point)
|
||||
|| (0x00D0 === point)
|
||||
|| (0x00D7 <= point && point <= 0x00D8)
|
||||
|| (0x00DE <= point && point <= 0x00E1)
|
||||
|| (0x00E6 === point)
|
||||
|| (0x00E8 <= point && point <= 0x00EA)
|
||||
|| (0x00EC <= point && point <= 0x00ED)
|
||||
|| (0x00F0 === point)
|
||||
|| (0x00F2 <= point && point <= 0x00F3)
|
||||
|| (0x00F7 <= point && point <= 0x00FA)
|
||||
|| (0x00FC === point)
|
||||
|| (0x00FE === point)
|
||||
|| (0x0101 === point)
|
||||
|| (0x0111 === point)
|
||||
|| (0x0113 === point)
|
||||
|| (0x011B === point)
|
||||
|| (0x0126 <= point && point <= 0x0127)
|
||||
|| (0x012B === point)
|
||||
|| (0x0131 <= point && point <= 0x0133)
|
||||
|| (0x0138 === point)
|
||||
|| (0x013F <= point && point <= 0x0142)
|
||||
|| (0x0144 === point)
|
||||
|| (0x0148 <= point && point <= 0x014B)
|
||||
|| (0x014D === point)
|
||||
|| (0x0152 <= point && point <= 0x0153)
|
||||
|| (0x0166 <= point && point <= 0x0167)
|
||||
|| (0x016B === point)
|
||||
|| (0x01CE === point)
|
||||
|| (0x01D0 === point)
|
||||
|| (0x01D2 === point)
|
||||
|| (0x01D4 === point)
|
||||
|| (0x01D6 === point)
|
||||
|| (0x01D8 === point)
|
||||
|| (0x01DA === point)
|
||||
|| (0x01DC === point)
|
||||
|| (0x0251 === point)
|
||||
|| (0x0261 === point)
|
||||
|| (0x02C4 === point)
|
||||
|| (0x02C7 === point)
|
||||
|| (0x02C9 <= point && point <= 0x02CB)
|
||||
|| (0x02CD === point)
|
||||
|| (0x02D0 === point)
|
||||
|| (0x02D8 <= point && point <= 0x02DB)
|
||||
|| (0x02DD === point)
|
||||
|| (0x02DF === point)
|
||||
|| (0x0300 <= point && point <= 0x036F)
|
||||
|| (0x0391 <= point && point <= 0x03A1)
|
||||
|| (0x03A3 <= point && point <= 0x03A9)
|
||||
|| (0x03B1 <= point && point <= 0x03C1)
|
||||
|| (0x03C3 <= point && point <= 0x03C9)
|
||||
|| (0x0401 === point)
|
||||
|| (0x0410 <= point && point <= 0x044F)
|
||||
|| (0x0451 === point)
|
||||
|| (0x2010 === point)
|
||||
|| (0x2013 <= point && point <= 0x2016)
|
||||
|| (0x2018 <= point && point <= 0x2019)
|
||||
|| (0x201C <= point && point <= 0x201D)
|
||||
|| (0x2020 <= point && point <= 0x2022)
|
||||
|| (0x2024 <= point && point <= 0x2027)
|
||||
|| (0x2030 === point)
|
||||
|| (0x2032 <= point && point <= 0x2033)
|
||||
|| (0x2035 === point)
|
||||
|| (0x203B === point)
|
||||
|| (0x203E === point)
|
||||
|| (0x2074 === point)
|
||||
|| (0x207F === point)
|
||||
|| (0x2081 <= point && point <= 0x2084)
|
||||
|| (0x20AC === point)
|
||||
|| (0x2103 === point)
|
||||
|| (0x2105 === point)
|
||||
|| (0x2109 === point)
|
||||
|| (0x2113 === point)
|
||||
|| (0x2116 === point)
|
||||
|| (0x2121 <= point && point <= 0x2122)
|
||||
|| (0x2126 === point)
|
||||
|| (0x212B === point)
|
||||
|| (0x2153 <= point && point <= 0x2154)
|
||||
|| (0x215B <= point && point <= 0x215E)
|
||||
|| (0x2160 <= point && point <= 0x216B)
|
||||
|| (0x2170 <= point && point <= 0x2179)
|
||||
|| (0x2189 === point)
|
||||
|| (0x2190 <= point && point <= 0x2199)
|
||||
|| (0x21B8 <= point && point <= 0x21B9)
|
||||
|| (0x21D2 === point)
|
||||
|| (0x21D4 === point)
|
||||
|| (0x21E7 === point)
|
||||
|| (0x2200 === point)
|
||||
|| (0x2202 <= point && point <= 0x2203)
|
||||
|| (0x2207 <= point && point <= 0x2208)
|
||||
|| (0x220B === point)
|
||||
|| (0x220F === point)
|
||||
|| (0x2211 === point)
|
||||
|| (0x2215 === point)
|
||||
|| (0x221A === point)
|
||||
|| (0x221D <= point && point <= 0x2220)
|
||||
|| (0x2223 === point)
|
||||
|| (0x2225 === point)
|
||||
|| (0x2227 <= point && point <= 0x222C)
|
||||
|| (0x222E === point)
|
||||
|| (0x2234 <= point && point <= 0x2237)
|
||||
|| (0x223C <= point && point <= 0x223D)
|
||||
|| (0x2248 === point)
|
||||
|| (0x224C === point)
|
||||
|| (0x2252 === point)
|
||||
|| (0x2260 <= point && point <= 0x2261)
|
||||
|| (0x2264 <= point && point <= 0x2267)
|
||||
|| (0x226A <= point && point <= 0x226B)
|
||||
|| (0x226E <= point && point <= 0x226F)
|
||||
|| (0x2282 <= point && point <= 0x2283)
|
||||
|| (0x2286 <= point && point <= 0x2287)
|
||||
|| (0x2295 === point)
|
||||
|| (0x2299 === point)
|
||||
|| (0x22A5 === point)
|
||||
|| (0x22BF === point)
|
||||
|| (0x2312 === point)
|
||||
|| (0x2460 <= point && point <= 0x24E9)
|
||||
|| (0x24EB <= point && point <= 0x254B)
|
||||
|| (0x2550 <= point && point <= 0x2573)
|
||||
|| (0x2580 <= point && point <= 0x258F)
|
||||
|| (0x2592 <= point && point <= 0x2595)
|
||||
|| (0x25A0 <= point && point <= 0x25A1)
|
||||
|| (0x25A3 <= point && point <= 0x25A9)
|
||||
|| (0x25B2 <= point && point <= 0x25B3)
|
||||
|| (0x25B6 <= point && point <= 0x25B7)
|
||||
|| (0x25BC <= point && point <= 0x25BD)
|
||||
|| (0x25C0 <= point && point <= 0x25C1)
|
||||
|| (0x25C6 <= point && point <= 0x25C8)
|
||||
|| (0x25CB === point)
|
||||
|| (0x25CE <= point && point <= 0x25D1)
|
||||
|| (0x25E2 <= point && point <= 0x25E5)
|
||||
|| (0x25EF === point)
|
||||
|| (0x2605 <= point && point <= 0x2606)
|
||||
|| (0x2609 === point)
|
||||
|| (0x260E <= point && point <= 0x260F)
|
||||
|| (0x2614 <= point && point <= 0x2615)
|
||||
|| (0x261C === point)
|
||||
|| (0x261E === point)
|
||||
|| (0x2640 === point)
|
||||
|| (0x2642 === point)
|
||||
|| (0x2660 <= point && point <= 0x2661)
|
||||
|| (0x2663 <= point && point <= 0x2665)
|
||||
|| (0x2667 <= point && point <= 0x266A)
|
||||
|| (0x266C <= point && point <= 0x266D)
|
||||
|| (0x266F === point)
|
||||
|| (0x269E <= point && point <= 0x269F)
|
||||
|| (0x26BE <= point && point <= 0x26BF)
|
||||
|| (0x26C4 <= point && point <= 0x26CD)
|
||||
|| (0x26CF <= point && point <= 0x26E1)
|
||||
|| (0x26E3 === point)
|
||||
|| (0x26E8 <= point && point <= 0x26FF)
|
||||
|| (0x273D === point)
|
||||
|| (0x2757 === point)
|
||||
|| (0x2776 <= point && point <= 0x277F)
|
||||
|| (0x2B55 <= point && point <= 0x2B59)
|
||||
|| (0x3248 <= point && point <= 0x324F)
|
||||
|| (0xE000 <= point && point <= 0xF8FF)
|
||||
|| (0xFE00 <= point && point <= 0xFE0F)
|
||||
|| (0xFFFD === point)
|
||||
|| (0x1F100 <= point && point <= 0x1F10A)
|
||||
|| (0x1F110 <= point && point <= 0x1F12D)
|
||||
|| (0x1F130 <= point && point <= 0x1F169)
|
||||
|| (0x1F170 <= point && point <= 0x1F19A)
|
||||
|| (0xE0100 <= point && point <= 0xE01EF)
|
||||
|| (0xF0000 <= point && point <= 0xFFFFD)
|
||||
|| (0x100000 <= point && point <= 0x10FFFD)) {
|
||||
return +process.env.NCURSES_CJK_WIDTH || 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
};
|
||||
|
||||
exports.strWidth = function(str) {
|
||||
var width = 0;
|
||||
for (var i = 0; i < str.length; i++) {
|
||||
width += exports.charWidth(str, i);
|
||||
if (exports.isSurrogate(str, i)) i++;
|
||||
}
|
||||
return width;
|
||||
};
|
||||
|
||||
exports.isSurrogate = function(str, i) {
|
||||
var point = typeof str !== 'number'
|
||||
? exports.codePointAt(str, i || 0)
|
||||
: str;
|
||||
return point > 0x00ffff;
|
||||
};
|
||||
|
||||
exports.combiningTable = [
|
||||
[0x0300, 0x036F], [0x0483, 0x0486], [0x0488, 0x0489],
|
||||
[0x0591, 0x05BD], [0x05BF, 0x05BF], [0x05C1, 0x05C2],
|
||||
[0x05C4, 0x05C5], [0x05C7, 0x05C7], [0x0600, 0x0603],
|
||||
[0x0610, 0x0615], [0x064B, 0x065E], [0x0670, 0x0670],
|
||||
[0x06D6, 0x06E4], [0x06E7, 0x06E8], [0x06EA, 0x06ED],
|
||||
[0x070F, 0x070F], [0x0711, 0x0711], [0x0730, 0x074A],
|
||||
[0x07A6, 0x07B0], [0x07EB, 0x07F3], [0x0901, 0x0902],
|
||||
[0x093C, 0x093C], [0x0941, 0x0948], [0x094D, 0x094D],
|
||||
[0x0951, 0x0954], [0x0962, 0x0963], [0x0981, 0x0981],
|
||||
[0x09BC, 0x09BC], [0x09C1, 0x09C4], [0x09CD, 0x09CD],
|
||||
[0x09E2, 0x09E3], [0x0A01, 0x0A02], [0x0A3C, 0x0A3C],
|
||||
[0x0A41, 0x0A42], [0x0A47, 0x0A48], [0x0A4B, 0x0A4D],
|
||||
[0x0A70, 0x0A71], [0x0A81, 0x0A82], [0x0ABC, 0x0ABC],
|
||||
[0x0AC1, 0x0AC5], [0x0AC7, 0x0AC8], [0x0ACD, 0x0ACD],
|
||||
[0x0AE2, 0x0AE3], [0x0B01, 0x0B01], [0x0B3C, 0x0B3C],
|
||||
[0x0B3F, 0x0B3F], [0x0B41, 0x0B43], [0x0B4D, 0x0B4D],
|
||||
[0x0B56, 0x0B56], [0x0B82, 0x0B82], [0x0BC0, 0x0BC0],
|
||||
[0x0BCD, 0x0BCD], [0x0C3E, 0x0C40], [0x0C46, 0x0C48],
|
||||
[0x0C4A, 0x0C4D], [0x0C55, 0x0C56], [0x0CBC, 0x0CBC],
|
||||
[0x0CBF, 0x0CBF], [0x0CC6, 0x0CC6], [0x0CCC, 0x0CCD],
|
||||
[0x0CE2, 0x0CE3], [0x0D41, 0x0D43], [0x0D4D, 0x0D4D],
|
||||
[0x0DCA, 0x0DCA], [0x0DD2, 0x0DD4], [0x0DD6, 0x0DD6],
|
||||
[0x0E31, 0x0E31], [0x0E34, 0x0E3A], [0x0E47, 0x0E4E],
|
||||
[0x0EB1, 0x0EB1], [0x0EB4, 0x0EB9], [0x0EBB, 0x0EBC],
|
||||
[0x0EC8, 0x0ECD], [0x0F18, 0x0F19], [0x0F35, 0x0F35],
|
||||
[0x0F37, 0x0F37], [0x0F39, 0x0F39], [0x0F71, 0x0F7E],
|
||||
[0x0F80, 0x0F84], [0x0F86, 0x0F87], [0x0F90, 0x0F97],
|
||||
[0x0F99, 0x0FBC], [0x0FC6, 0x0FC6], [0x102D, 0x1030],
|
||||
[0x1032, 0x1032], [0x1036, 0x1037], [0x1039, 0x1039],
|
||||
[0x1058, 0x1059], [0x1160, 0x11FF], [0x135F, 0x135F],
|
||||
[0x1712, 0x1714], [0x1732, 0x1734], [0x1752, 0x1753],
|
||||
[0x1772, 0x1773], [0x17B4, 0x17B5], [0x17B7, 0x17BD],
|
||||
[0x17C6, 0x17C6], [0x17C9, 0x17D3], [0x17DD, 0x17DD],
|
||||
[0x180B, 0x180D], [0x18A9, 0x18A9], [0x1920, 0x1922],
|
||||
[0x1927, 0x1928], [0x1932, 0x1932], [0x1939, 0x193B],
|
||||
[0x1A17, 0x1A18], [0x1B00, 0x1B03], [0x1B34, 0x1B34],
|
||||
[0x1B36, 0x1B3A], [0x1B3C, 0x1B3C], [0x1B42, 0x1B42],
|
||||
[0x1B6B, 0x1B73], [0x1DC0, 0x1DCA], [0x1DFE, 0x1DFF],
|
||||
[0x200B, 0x200F], [0x202A, 0x202E], [0x2060, 0x2063],
|
||||
[0x206A, 0x206F], [0x20D0, 0x20EF], [0x302A, 0x302F],
|
||||
[0x3099, 0x309A], [0xA806, 0xA806], [0xA80B, 0xA80B],
|
||||
[0xA825, 0xA826], [0xFB1E, 0xFB1E], [0xFE00, 0xFE0F],
|
||||
[0xFE20, 0xFE23], [0xFEFF, 0xFEFF], [0xFFF9, 0xFFFB],
|
||||
[0x10A01, 0x10A03], [0x10A05, 0x10A06], [0x10A0C, 0x10A0F],
|
||||
[0x10A38, 0x10A3A], [0x10A3F, 0x10A3F], [0x1D167, 0x1D169],
|
||||
[0x1D173, 0x1D182], [0x1D185, 0x1D18B], [0x1D1AA, 0x1D1AD],
|
||||
[0x1D242, 0x1D244], [0xE0001, 0xE0001], [0xE0020, 0xE007F],
|
||||
[0xE0100, 0xE01EF]
|
||||
];
|
||||
|
||||
exports.combining = exports.combiningTable.reduce(function(out, row) {
|
||||
for (var i = row[0]; i <= row[1]; i++) {
|
||||
out[i] = true;
|
||||
}
|
||||
return out;
|
||||
}, {});
|
||||
|
||||
exports.isCombining = function(str, i) {
|
||||
var point = typeof str !== 'number'
|
||||
? exports.codePointAt(str, i || 0)
|
||||
: str;
|
||||
return exports.combining[point] === true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Code Point Helpers
|
||||
*/
|
||||
|
||||
exports.codePointAt = function(str, position) {
|
||||
if (str == null) {
|
||||
throw TypeError();
|
||||
}
|
||||
var string = String(str);
|
||||
if (string.codePointAt) {
|
||||
return string.codePointAt(position);
|
||||
}
|
||||
var size = string.length;
|
||||
// `ToInteger`
|
||||
var index = position ? Number(position) : 0;
|
||||
if (index !== index) { // better `isNaN`
|
||||
index = 0;
|
||||
}
|
||||
// Account for out-of-bounds indices:
|
||||
if (index < 0 || index >= size) {
|
||||
return undefined;
|
||||
}
|
||||
// Get the first code unit
|
||||
var first = string.charCodeAt(index);
|
||||
var second;
|
||||
if ( // check if it’s the start of a surrogate pair
|
||||
first >= 0xD800 && first <= 0xDBFF && // high surrogate
|
||||
size > index + 1 // there is a next code unit
|
||||
) {
|
||||
second = string.charCodeAt(index + 1);
|
||||
if (second >= 0xDC00 && second <= 0xDFFF) { // low surrogate
|
||||
// http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
|
||||
return (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000;
|
||||
}
|
||||
}
|
||||
return first;
|
||||
};
|
||||
|
||||
// exports.codePointAt = function(str, position) {
|
||||
// position = +position || 0;
|
||||
// var x = str.charCodeAt(position);
|
||||
// var y = str.length > 1 ? str.charCodeAt(position + 1) : 0;
|
||||
// var point = x;
|
||||
// if ((0xD800 <= x && x <= 0xDBFF) && (0xDC00 <= y && y <= 0xDFFF)) {
|
||||
// x &= 0x3FF;
|
||||
// y &= 0x3FF;
|
||||
// point = (x << 10) | y;
|
||||
// point += 0x10000;
|
||||
// }
|
||||
// return point;
|
||||
// };
|
||||
|
||||
exports.fromCodePoint = function() {
|
||||
if (String.fromCodePoint) {
|
||||
return String.fromCodePoint.apply(String, arguments);
|
||||
}
|
||||
var MAX_SIZE = 0x4000;
|
||||
var codeUnits = [];
|
||||
var highSurrogate;
|
||||
var lowSurrogate;
|
||||
var index = -1;
|
||||
var length = arguments.length;
|
||||
if (!length) {
|
||||
return '';
|
||||
}
|
||||
var result = '';
|
||||
while (++index < length) {
|
||||
var codePoint = Number(arguments[index]);
|
||||
if (
|
||||
!isFinite(codePoint) || // `NaN`, `+Infinity`, or `-Infinity`
|
||||
codePoint < 0 || // not a valid Unicode code point
|
||||
codePoint > 0x10FFFF || // not a valid Unicode code point
|
||||
floor(codePoint) !== codePoint // not an integer
|
||||
) {
|
||||
throw RangeError('Invalid code point: ' + codePoint);
|
||||
}
|
||||
if (codePoint <= 0xFFFF) { // BMP code point
|
||||
codeUnits.push(codePoint);
|
||||
} else { // Astral code point; split in surrogate halves
|
||||
// http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
|
||||
codePoint -= 0x10000;
|
||||
highSurrogate = (codePoint >> 10) + 0xD800;
|
||||
lowSurrogate = (codePoint % 0x400) + 0xDC00;
|
||||
codeUnits.push(highSurrogate, lowSurrogate);
|
||||
}
|
||||
if (index + 1 === length || codeUnits.length > MAX_SIZE) {
|
||||
result += stringFromCharCode.apply(null, codeUnits);
|
||||
codeUnits.length = 0;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* Regexes
|
||||
*/
|
||||
|
||||
exports.chars = {};
|
||||
|
||||
// Double width characters that are _not_ surrogate pairs.
|
||||
// NOTE: 0x20000 - 0x2fffd and 0x30000 - 0x3fffd are not necessary for this
|
||||
// regex anyway. This regex is used to put a blank char after wide chars to
|
||||
// be eaten, however, if this is a surrogate pair, parseContent already adds
|
||||
// the extra one char because its length equals 2 instead of 1.
|
||||
exports.chars.wide = new RegExp('(['
|
||||
+ '\\u1100-\\u115f' // Hangul Jamo init. consonants
|
||||
+ '\\u2329\\u232a'
|
||||
+ '\\u2e80-\\u303e\\u3040-\\ua4cf' // CJK ... Yi
|
||||
+ '\\uac00-\\ud7a3' // Hangul Syllables
|
||||
+ '\\uf900-\\ufaff' // CJK Compatibility Ideographs
|
||||
+ '\\ufe10-\\ufe19' // Vertical forms
|
||||
+ '\\ufe30-\\ufe6f' // CJK Compatibility Forms
|
||||
+ '\\uff00-\\uff60' // Fullwidth Forms
|
||||
+ '\\uffe0-\\uffe6'
|
||||
+ '])', 'g');
|
||||
|
||||
// All surrogate pair wide chars.
|
||||
exports.chars.swide = new RegExp('('
|
||||
// 0x20000 - 0x2fffd:
|
||||
+ '[\\ud840-\\ud87f][\\udc00-\\udffd]'
|
||||
+ '|'
|
||||
// 0x30000 - 0x3fffd:
|
||||
+ '[\\ud880-\\ud8bf][\\udc00-\\udffd]'
|
||||
+ ')', 'g');
|
||||
|
||||
// All wide chars including surrogate pairs.
|
||||
exports.chars.all = new RegExp('('
|
||||
+ exports.chars.swide.source.slice(1, -1)
|
||||
+ '|'
|
||||
+ exports.chars.wide.source.slice(1, -1)
|
||||
+ ')', 'g');
|
||||
|
||||
// Regex to detect a surrogate pair.
|
||||
exports.chars.surrogate = /[\ud800-\udbff][\udc00-\udfff]/g;
|
||||
|
||||
// Regex to find combining characters.
|
||||
exports.chars.combining = exports.combiningTable.reduce(function(out, row) {
|
||||
var low, high, range;
|
||||
if (row[0] > 0x00ffff) {
|
||||
low = exports.fromCodePoint(row[0]);
|
||||
low = [
|
||||
hexify(low.charCodeAt(0)),
|
||||
hexify(low.charCodeAt(1))
|
||||
];
|
||||
high = exports.fromCodePoint(row[1]);
|
||||
high = [
|
||||
hexify(high.charCodeAt(0)),
|
||||
hexify(high.charCodeAt(1))
|
||||
];
|
||||
range = '[\\u' + low[0] + '-' + '\\u' + high[0] + ']'
|
||||
+ '[\\u' + low[1] + '-' + '\\u' + high[1] + ']';
|
||||
if (!~out.indexOf('|')) out += ']';
|
||||
out += '|' + range;
|
||||
} else {
|
||||
low = hexify(row[0]);
|
||||
high = hexify(row[1]);
|
||||
low = '\\u' + low;
|
||||
high = '\\u' + high;
|
||||
out += low + '-' + high;
|
||||
}
|
||||
return out;
|
||||
}, '[');
|
||||
|
||||
exports.chars.combining = new RegExp(exports.chars.combining, 'g');
|
||||
|
||||
function hexify(n) {
|
||||
n = n.toString(16);
|
||||
while (n.length < 4) n = '0' + n;
|
||||
return n;
|
||||
}
|
||||
|
||||
/*
|
||||
exports.chars.combining = new RegExp(
|
||||
'['
|
||||
+ '\\u0300-\\u036f'
|
||||
+ '\\u0483-\\u0486'
|
||||
+ '\\u0488-\\u0489'
|
||||
+ '\\u0591-\\u05bd'
|
||||
+ '\\u05bf-\\u05bf'
|
||||
+ '\\u05c1-\\u05c2'
|
||||
+ '\\u05c4-\\u05c5'
|
||||
+ '\\u05c7-\\u05c7'
|
||||
+ '\\u0600-\\u0603'
|
||||
+ '\\u0610-\\u0615'
|
||||
+ '\\u064b-\\u065e'
|
||||
+ '\\u0670-\\u0670'
|
||||
+ '\\u06d6-\\u06e4'
|
||||
+ '\\u06e7-\\u06e8'
|
||||
+ '\\u06ea-\\u06ed'
|
||||
+ '\\u070f-\\u070f'
|
||||
+ '\\u0711-\\u0711'
|
||||
+ '\\u0730-\\u074a'
|
||||
+ '\\u07a6-\\u07b0'
|
||||
+ '\\u07eb-\\u07f3'
|
||||
+ '\\u0901-\\u0902'
|
||||
+ '\\u093c-\\u093c'
|
||||
+ '\\u0941-\\u0948'
|
||||
+ '\\u094d-\\u094d'
|
||||
+ '\\u0951-\\u0954'
|
||||
+ '\\u0962-\\u0963'
|
||||
+ '\\u0981-\\u0981'
|
||||
+ '\\u09bc-\\u09bc'
|
||||
+ '\\u09c1-\\u09c4'
|
||||
+ '\\u09cd-\\u09cd'
|
||||
+ '\\u09e2-\\u09e3'
|
||||
+ '\\u0a01-\\u0a02'
|
||||
+ '\\u0a3c-\\u0a3c'
|
||||
+ '\\u0a41-\\u0a42'
|
||||
+ '\\u0a47-\\u0a48'
|
||||
+ '\\u0a4b-\\u0a4d'
|
||||
+ '\\u0a70-\\u0a71'
|
||||
+ '\\u0a81-\\u0a82'
|
||||
+ '\\u0abc-\\u0abc'
|
||||
+ '\\u0ac1-\\u0ac5'
|
||||
+ '\\u0ac7-\\u0ac8'
|
||||
+ '\\u0acd-\\u0acd'
|
||||
+ '\\u0ae2-\\u0ae3'
|
||||
+ '\\u0b01-\\u0b01'
|
||||
+ '\\u0b3c-\\u0b3c'
|
||||
+ '\\u0b3f-\\u0b3f'
|
||||
+ '\\u0b41-\\u0b43'
|
||||
+ '\\u0b4d-\\u0b4d'
|
||||
+ '\\u0b56-\\u0b56'
|
||||
+ '\\u0b82-\\u0b82'
|
||||
+ '\\u0bc0-\\u0bc0'
|
||||
+ '\\u0bcd-\\u0bcd'
|
||||
+ '\\u0c3e-\\u0c40'
|
||||
+ '\\u0c46-\\u0c48'
|
||||
+ '\\u0c4a-\\u0c4d'
|
||||
+ '\\u0c55-\\u0c56'
|
||||
+ '\\u0cbc-\\u0cbc'
|
||||
+ '\\u0cbf-\\u0cbf'
|
||||
+ '\\u0cc6-\\u0cc6'
|
||||
+ '\\u0ccc-\\u0ccd'
|
||||
+ '\\u0ce2-\\u0ce3'
|
||||
+ '\\u0d41-\\u0d43'
|
||||
+ '\\u0d4d-\\u0d4d'
|
||||
+ '\\u0dca-\\u0dca'
|
||||
+ '\\u0dd2-\\u0dd4'
|
||||
+ '\\u0dd6-\\u0dd6'
|
||||
+ '\\u0e31-\\u0e31'
|
||||
+ '\\u0e34-\\u0e3a'
|
||||
+ '\\u0e47-\\u0e4e'
|
||||
+ '\\u0eb1-\\u0eb1'
|
||||
+ '\\u0eb4-\\u0eb9'
|
||||
+ '\\u0ebb-\\u0ebc'
|
||||
+ '\\u0ec8-\\u0ecd'
|
||||
+ '\\u0f18-\\u0f19'
|
||||
+ '\\u0f35-\\u0f35'
|
||||
+ '\\u0f37-\\u0f37'
|
||||
+ '\\u0f39-\\u0f39'
|
||||
+ '\\u0f71-\\u0f7e'
|
||||
+ '\\u0f80-\\u0f84'
|
||||
+ '\\u0f86-\\u0f87'
|
||||
+ '\\u0f90-\\u0f97'
|
||||
+ '\\u0f99-\\u0fbc'
|
||||
+ '\\u0fc6-\\u0fc6'
|
||||
+ '\\u102d-\\u1030'
|
||||
+ '\\u1032-\\u1032'
|
||||
+ '\\u1036-\\u1037'
|
||||
+ '\\u1039-\\u1039'
|
||||
+ '\\u1058-\\u1059'
|
||||
+ '\\u1160-\\u11ff'
|
||||
+ '\\u135f-\\u135f'
|
||||
+ '\\u1712-\\u1714'
|
||||
+ '\\u1732-\\u1734'
|
||||
+ '\\u1752-\\u1753'
|
||||
+ '\\u1772-\\u1773'
|
||||
+ '\\u17b4-\\u17b5'
|
||||
+ '\\u17b7-\\u17bd'
|
||||
+ '\\u17c6-\\u17c6'
|
||||
+ '\\u17c9-\\u17d3'
|
||||
+ '\\u17dd-\\u17dd'
|
||||
+ '\\u180b-\\u180d'
|
||||
+ '\\u18a9-\\u18a9'
|
||||
+ '\\u1920-\\u1922'
|
||||
+ '\\u1927-\\u1928'
|
||||
+ '\\u1932-\\u1932'
|
||||
+ '\\u1939-\\u193b'
|
||||
+ '\\u1a17-\\u1a18'
|
||||
+ '\\u1b00-\\u1b03'
|
||||
+ '\\u1b34-\\u1b34'
|
||||
+ '\\u1b36-\\u1b3a'
|
||||
+ '\\u1b3c-\\u1b3c'
|
||||
+ '\\u1b42-\\u1b42'
|
||||
+ '\\u1b6b-\\u1b73'
|
||||
+ '\\u1dc0-\\u1dca'
|
||||
+ '\\u1dfe-\\u1dff'
|
||||
+ '\\u200b-\\u200f'
|
||||
+ '\\u202a-\\u202e'
|
||||
+ '\\u2060-\\u2063'
|
||||
+ '\\u206a-\\u206f'
|
||||
+ '\\u20d0-\\u20ef'
|
||||
+ '\\u302a-\\u302f'
|
||||
+ '\\u3099-\\u309a'
|
||||
+ '\\ua806-\\ua806'
|
||||
+ '\\ua80b-\\ua80b'
|
||||
+ '\\ua825-\\ua826'
|
||||
+ '\\ufb1e-\\ufb1e'
|
||||
+ '\\ufe00-\\ufe0f'
|
||||
+ '\\ufe20-\\ufe23'
|
||||
+ '\\ufeff-\\ufeff'
|
||||
+ '\\ufff9-\\ufffb'
|
||||
+ ']'
|
||||
+ '|[\\ud802-\\ud802][\\ude01-\\ude03]'
|
||||
+ '|[\\ud802-\\ud802][\\ude05-\\ude06]'
|
||||
+ '|[\\ud802-\\ud802][\\ude0c-\\ude0f]'
|
||||
+ '|[\\ud802-\\ud802][\\ude38-\\ude3a]'
|
||||
+ '|[\\ud802-\\ud802][\\ude3f-\\ude3f]'
|
||||
+ '|[\\ud834-\\ud834][\\udd67-\\udd69]'
|
||||
+ '|[\\ud834-\\ud834][\\udd73-\\udd82]'
|
||||
+ '|[\\ud834-\\ud834][\\udd85-\\udd8b]'
|
||||
+ '|[\\ud834-\\ud834][\\uddaa-\\uddad]'
|
||||
+ '|[\\ud834-\\ud834][\\ude42-\\ude44]'
|
||||
+ '|[\\udb40-\\udb40][\\udc01-\\udc01]'
|
||||
+ '|[\\udb40-\\udb40][\\udc20-\\udc7f]'
|
||||
+ '|[\\udb40-\\udb40][\\udd00-\\uddef]'
|
||||
, 'g');
|
||||
*/
|
||||
60
lib/widget.js
Normal file
@ -0,0 +1,60 @@
|
||||
/**
|
||||
* widget.js - high-level interface for blessed
|
||||
* Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
var widget = exports;
|
||||
|
||||
widget.classes = [
|
||||
'Node',
|
||||
'Screen',
|
||||
'Element',
|
||||
'Box',
|
||||
'Text',
|
||||
'Line',
|
||||
'ScrollableBox',
|
||||
'ScrollableText',
|
||||
'BigText',
|
||||
'List',
|
||||
'Form',
|
||||
'Input',
|
||||
'Textarea',
|
||||
'Textbox',
|
||||
'Button',
|
||||
'ProgressBar',
|
||||
'FileManager',
|
||||
'Checkbox',
|
||||
'RadioSet',
|
||||
'RadioButton',
|
||||
'Prompt',
|
||||
'Question',
|
||||
'Message',
|
||||
'Loading',
|
||||
'Listbar',
|
||||
'Log',
|
||||
'Table',
|
||||
'ListTable',
|
||||
'Terminal',
|
||||
'Image',
|
||||
'ANSIImage',
|
||||
'OverlayImage',
|
||||
'Video',
|
||||
'Layout'
|
||||
];
|
||||
|
||||
widget.classes.forEach(function(name) {
|
||||
var file = name.toLowerCase();
|
||||
widget[name] = widget[file] = require('./widgets/' + file);
|
||||
});
|
||||
|
||||
widget.aliases = {
|
||||
'ListBar': 'Listbar',
|
||||
'PNG': 'ANSIImage'
|
||||
};
|
||||
|
||||
Object.keys(widget.aliases).forEach(function(key) {
|
||||
var name = widget.aliases[key];
|
||||
widget[key] = widget[name];
|
||||
widget[key.toLowerCase()] = widget[name];
|
||||
});
|
||||
167
lib/widgets/ansiimage.js
Normal file
@ -0,0 +1,167 @@
|
||||
/**
|
||||
* ansiimage.js - render PNGS/GIFS as ANSI
|
||||
* Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Modules
|
||||
*/
|
||||
|
||||
var cp = require('child_process');
|
||||
|
||||
var colors = require('../colors');
|
||||
|
||||
var Node = require('./node');
|
||||
var Box = require('./box');
|
||||
|
||||
var tng = require('../../vendor/tng');
|
||||
|
||||
/**
|
||||
* ANSIImage
|
||||
*/
|
||||
|
||||
function ANSIImage(options) {
|
||||
var self = this;
|
||||
|
||||
if (!(this instanceof Node)) {
|
||||
return new ANSIImage(options);
|
||||
}
|
||||
|
||||
options = options || {};
|
||||
options.shrink = true;
|
||||
|
||||
Box.call(this, options);
|
||||
|
||||
this.scale = this.options.scale || 1.0;
|
||||
this.options.animate = this.options.animate !== false;
|
||||
this._noFill = true;
|
||||
|
||||
if (this.options.file) {
|
||||
this.setImage(this.options.file);
|
||||
}
|
||||
|
||||
this.screen.on('prerender', function() {
|
||||
var lpos = self.lpos;
|
||||
if (!lpos) return;
|
||||
// prevent image from blending with itself if there are alpha channels
|
||||
self.screen.clearRegion(lpos.xi, lpos.xl, lpos.yi, lpos.yl);
|
||||
});
|
||||
|
||||
this.on('destroy', function() {
|
||||
self.stop();
|
||||
});
|
||||
}
|
||||
|
||||
ANSIImage.prototype.__proto__ = Box.prototype;
|
||||
|
||||
ANSIImage.prototype.type = 'ansiimage';
|
||||
|
||||
ANSIImage.curl = function(url) {
|
||||
try {
|
||||
return cp.execFileSync('curl',
|
||||
['-s', '-A', '', url],
|
||||
{ stdio: ['ignore', 'pipe', 'ignore'] });
|
||||
} catch (e) {
|
||||
;
|
||||
}
|
||||
try {
|
||||
return cp.execFileSync('wget',
|
||||
['-U', '', '-O', '-', url],
|
||||
{ stdio: ['ignore', 'pipe', 'ignore'] });
|
||||
} catch (e) {
|
||||
;
|
||||
}
|
||||
throw new Error('curl or wget failed.');
|
||||
};
|
||||
|
||||
ANSIImage.prototype.setImage = function(file) {
|
||||
this.file = typeof file === 'string' ? file : null;
|
||||
|
||||
if (/^https?:/.test(file)) {
|
||||
file = ANSIImage.curl(file);
|
||||
}
|
||||
|
||||
var width = this.position.width;
|
||||
var height = this.position.height;
|
||||
|
||||
if (width != null) {
|
||||
width = this.width;
|
||||
}
|
||||
|
||||
if (height != null) {
|
||||
height = this.height;
|
||||
}
|
||||
|
||||
try {
|
||||
this.setContent('');
|
||||
|
||||
this.img = tng(file, {
|
||||
colors: colors,
|
||||
width: width,
|
||||
height: height,
|
||||
scale: this.scale,
|
||||
ascii: this.options.ascii,
|
||||
speed: this.options.speed,
|
||||
filename: this.file
|
||||
});
|
||||
|
||||
if (width == null || height == null) {
|
||||
this.width = this.img.cellmap[0].length;
|
||||
this.height = this.img.cellmap.length;
|
||||
}
|
||||
|
||||
if (this.img.frames && this.options.animate) {
|
||||
this.play();
|
||||
} else {
|
||||
this.cellmap = this.img.cellmap;
|
||||
}
|
||||
} catch (e) {
|
||||
this.setContent('Image Error: ' + e.message);
|
||||
this.img = null;
|
||||
this.cellmap = null;
|
||||
}
|
||||
};
|
||||
|
||||
ANSIImage.prototype.play = function() {
|
||||
var self = this;
|
||||
if (!this.img) return;
|
||||
return this.img.play(function(bmp, cellmap) {
|
||||
self.cellmap = cellmap;
|
||||
self.screen.render();
|
||||
});
|
||||
};
|
||||
|
||||
ANSIImage.prototype.pause = function() {
|
||||
if (!this.img) return;
|
||||
return this.img.pause();
|
||||
};
|
||||
|
||||
ANSIImage.prototype.stop = function() {
|
||||
if (!this.img) return;
|
||||
return this.img.stop();
|
||||
};
|
||||
|
||||
ANSIImage.prototype.clearImage = function() {
|
||||
this.stop();
|
||||
this.setContent('');
|
||||
this.img = null;
|
||||
this.cellmap = null;
|
||||
};
|
||||
|
||||
ANSIImage.prototype.render = function() {
|
||||
var coords = this._render();
|
||||
if (!coords) return;
|
||||
|
||||
if (this.img && this.cellmap) {
|
||||
this.img.renderElement(this.cellmap, this);
|
||||
}
|
||||
|
||||
return coords;
|
||||
};
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = ANSIImage;
|
||||
159
lib/widgets/bigtext.js
Normal file
@ -0,0 +1,159 @@
|
||||
/**
|
||||
* bigtext.js - bigtext element for blessed
|
||||
* Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Modules
|
||||
*/
|
||||
|
||||
var fs = require('fs');
|
||||
|
||||
var Node = require('./node');
|
||||
var Box = require('./box');
|
||||
|
||||
/**
|
||||
* BigText
|
||||
*/
|
||||
|
||||
function BigText(options) {
|
||||
if (!(this instanceof Node)) {
|
||||
return new BigText(options);
|
||||
}
|
||||
options = options || {};
|
||||
options.font = options.font
|
||||
|| __dirname + '/../../usr/fonts/ter-u14n.json';
|
||||
options.fontBold = options.font
|
||||
|| __dirname + '/../../usr/fonts/ter-u14b.json';
|
||||
this.fch = options.fch;
|
||||
this.ratio = {};
|
||||
this.font = this.loadFont(options.font);
|
||||
this.fontBold = this.loadFont(options.font);
|
||||
Box.call(this, options);
|
||||
if (this.style.bold) {
|
||||
this.font = this.fontBold;
|
||||
}
|
||||
}
|
||||
|
||||
BigText.prototype.__proto__ = Box.prototype;
|
||||
|
||||
BigText.prototype.type = 'bigtext';
|
||||
|
||||
BigText.prototype.loadFont = function(filename) {
|
||||
var self = this
|
||||
, data
|
||||
, font;
|
||||
|
||||
data = JSON.parse(fs.readFileSync(filename, 'utf8'));
|
||||
|
||||
this.ratio.width = data.width;
|
||||
this.ratio.height = data.height;
|
||||
|
||||
function convertLetter(ch, lines) {
|
||||
var line, i;
|
||||
|
||||
while (lines.length > self.ratio.height) {
|
||||
lines.shift();
|
||||
lines.pop();
|
||||
}
|
||||
|
||||
lines = lines.map(function(line) {
|
||||
var chs = line.split('');
|
||||
chs = chs.map(function(ch) {
|
||||
return ch === ' ' ? 0 : 1;
|
||||
});
|
||||
while (chs.length < self.ratio.width) {
|
||||
chs.push(0);
|
||||
}
|
||||
return chs;
|
||||
});
|
||||
|
||||
while (lines.length < self.ratio.height) {
|
||||
line = [];
|
||||
for (i = 0; i < self.ratio.width; i++) {
|
||||
line.push(0);
|
||||
}
|
||||
lines.push(line);
|
||||
}
|
||||
|
||||
return lines;
|
||||
}
|
||||
|
||||
font = Object.keys(data.glyphs).reduce(function(out, ch) {
|
||||
var lines = data.glyphs[ch].map;
|
||||
out[ch] = convertLetter(ch, lines);
|
||||
return out;
|
||||
}, {});
|
||||
|
||||
delete font[' '];
|
||||
|
||||
return font;
|
||||
};
|
||||
|
||||
BigText.prototype.setContent = function(content) {
|
||||
this.content = '';
|
||||
this.text = content || '';
|
||||
};
|
||||
|
||||
BigText.prototype.render = function() {
|
||||
if (this.position.width == null || this._shrinkWidth) {
|
||||
// if (this.width - this.iwidth < this.ratio.width * this.text.length + 1) {
|
||||
this.position.width = this.ratio.width * this.text.length + 1;
|
||||
this._shrinkWidth = true;
|
||||
// }
|
||||
}
|
||||
if (this.position.height == null || this._shrinkHeight) {
|
||||
// if (this.height - this.iheight < this.ratio.height + 0) {
|
||||
this.position.height = this.ratio.height + 0;
|
||||
this._shrinkHeight = true;
|
||||
// }
|
||||
}
|
||||
|
||||
var coords = this._render();
|
||||
if (!coords) return;
|
||||
|
||||
var lines = this.screen.lines
|
||||
, left = coords.xi + this.ileft
|
||||
, top = coords.yi + this.itop
|
||||
, right = coords.xl - this.iright
|
||||
, bottom = coords.yl - this.ibottom;
|
||||
|
||||
var dattr = this.sattr(this.style)
|
||||
, bg = dattr & 0x1ff
|
||||
, fg = (dattr >> 9) & 0x1ff
|
||||
, flags = (dattr >> 18) & 0x1ff
|
||||
, attr = (flags << 18) | (bg << 9) | fg;
|
||||
|
||||
for (var x = left, i = 0; x < right; x += this.ratio.width, i++) {
|
||||
var ch = this.text[i];
|
||||
if (!ch) break;
|
||||
var map = this.font[ch];
|
||||
if (!map) continue;
|
||||
for (var y = top; y < Math.min(bottom, top + this.ratio.height); y++) {
|
||||
if (!lines[y]) continue;
|
||||
var mline = map[y - top];
|
||||
if (!mline) continue;
|
||||
for (var mx = 0; mx < this.ratio.width; mx++) {
|
||||
var mcell = mline[mx];
|
||||
if (mcell == null) break;
|
||||
if (this.fch && this.fch !== ' ') {
|
||||
lines[y][x + mx][0] = dattr;
|
||||
lines[y][x + mx][1] = mcell === 1 ? this.fch : this.ch;
|
||||
} else {
|
||||
lines[y][x + mx][0] = mcell === 1 ? attr : dattr;
|
||||
lines[y][x + mx][1] = mcell === 1 ? ' ' : this.ch;
|
||||
}
|
||||
}
|
||||
lines[y].dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
return coords;
|
||||
};
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = BigText;
|
||||
34
lib/widgets/box.js
Normal file
@ -0,0 +1,34 @@
|
||||
/**
|
||||
* box.js - box element for blessed
|
||||
* Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Modules
|
||||
*/
|
||||
|
||||
var Node = require('./node');
|
||||
var Element = require('./element');
|
||||
|
||||
/**
|
||||
* Box
|
||||
*/
|
||||
|
||||
function Box(options) {
|
||||
if (!(this instanceof Node)) {
|
||||
return new Box(options);
|
||||
}
|
||||
options = options || {};
|
||||
Element.call(this, options);
|
||||
}
|
||||
|
||||
Box.prototype.__proto__ = Element.prototype;
|
||||
|
||||
Box.prototype.type = 'box';
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = Box;
|
||||
62
lib/widgets/button.js
Normal file
@ -0,0 +1,62 @@
|
||||
/**
|
||||
* button.js - button element for blessed
|
||||
* Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Modules
|
||||
*/
|
||||
|
||||
var Node = require('./node');
|
||||
var Input = require('./input');
|
||||
|
||||
/**
|
||||
* Button
|
||||
*/
|
||||
|
||||
function Button(options) {
|
||||
var self = this;
|
||||
|
||||
if (!(this instanceof Node)) {
|
||||
return new Button(options);
|
||||
}
|
||||
|
||||
options = options || {};
|
||||
|
||||
if (options.autoFocus == null) {
|
||||
options.autoFocus = false;
|
||||
}
|
||||
|
||||
Input.call(this, options);
|
||||
|
||||
this.on('keypress', function(ch, key) {
|
||||
if (key.name === 'enter' || key.name === 'space') {
|
||||
return self.press();
|
||||
}
|
||||
});
|
||||
|
||||
if (this.options.mouse) {
|
||||
this.on('click', function() {
|
||||
return self.press();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Button.prototype.__proto__ = Input.prototype;
|
||||
|
||||
Button.prototype.type = 'button';
|
||||
|
||||
Button.prototype.press = function() {
|
||||
this.focus();
|
||||
this.value = true;
|
||||
var result = this.emit('press');
|
||||
delete this.value;
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = Button;
|
||||
91
lib/widgets/checkbox.js
Normal file
@ -0,0 +1,91 @@
|
||||
/**
|
||||
* checkbox.js - checkbox element for blessed
|
||||
* Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Modules
|
||||
*/
|
||||
|
||||
var Node = require('./node');
|
||||
var Input = require('./input');
|
||||
|
||||
/**
|
||||
* Checkbox
|
||||
*/
|
||||
|
||||
function Checkbox(options) {
|
||||
var self = this;
|
||||
|
||||
if (!(this instanceof Node)) {
|
||||
return new Checkbox(options);
|
||||
}
|
||||
|
||||
options = options || {};
|
||||
|
||||
Input.call(this, options);
|
||||
|
||||
this.text = options.content || options.text || '';
|
||||
this.checked = this.value = options.checked || false;
|
||||
|
||||
this.on('keypress', function(ch, key) {
|
||||
if (key.name === 'enter' || key.name === 'space') {
|
||||
self.toggle();
|
||||
self.screen.render();
|
||||
}
|
||||
});
|
||||
|
||||
if (options.mouse) {
|
||||
this.on('click', function() {
|
||||
self.toggle();
|
||||
self.screen.render();
|
||||
});
|
||||
}
|
||||
|
||||
this.on('focus', function() {
|
||||
var lpos = self.lpos;
|
||||
if (!lpos) return;
|
||||
self.screen.program.lsaveCursor('checkbox');
|
||||
self.screen.program.cup(lpos.yi, lpos.xi + 1);
|
||||
self.screen.program.showCursor();
|
||||
});
|
||||
|
||||
this.on('blur', function() {
|
||||
self.screen.program.lrestoreCursor('checkbox', true);
|
||||
});
|
||||
}
|
||||
|
||||
Checkbox.prototype.__proto__ = Input.prototype;
|
||||
|
||||
Checkbox.prototype.type = 'checkbox';
|
||||
|
||||
Checkbox.prototype.render = function() {
|
||||
this.clearPos(true);
|
||||
this.setContent('[' + (this.checked ? 'x' : ' ') + '] ' + this.text, true);
|
||||
return this._render();
|
||||
};
|
||||
|
||||
Checkbox.prototype.check = function() {
|
||||
if (this.checked) return;
|
||||
this.checked = this.value = true;
|
||||
this.emit('check');
|
||||
};
|
||||
|
||||
Checkbox.prototype.uncheck = function() {
|
||||
if (!this.checked) return;
|
||||
this.checked = this.value = false;
|
||||
this.emit('uncheck');
|
||||
};
|
||||
|
||||
Checkbox.prototype.toggle = function() {
|
||||
return this.checked
|
||||
? this.uncheck()
|
||||
: this.check();
|
||||
};
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = Checkbox;
|
||||
2570
lib/widgets/element.js
Normal file
212
lib/widgets/filemanager.js
Normal file
@ -0,0 +1,212 @@
|
||||
/**
|
||||
* filemanager.js - file manager element for blessed
|
||||
* Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Modules
|
||||
*/
|
||||
|
||||
var path = require('path')
|
||||
, fs = require('fs');
|
||||
|
||||
var helpers = require('../helpers');
|
||||
|
||||
var Node = require('./node');
|
||||
var List = require('./list');
|
||||
|
||||
/**
|
||||
* FileManager
|
||||
*/
|
||||
|
||||
function FileManager(options) {
|
||||
var self = this;
|
||||
|
||||
if (!(this instanceof Node)) {
|
||||
return new FileManager(options);
|
||||
}
|
||||
|
||||
options = options || {};
|
||||
options.parseTags = true;
|
||||
// options.label = ' {blue-fg}%path{/blue-fg} ';
|
||||
|
||||
List.call(this, options);
|
||||
|
||||
this.cwd = options.cwd || process.cwd();
|
||||
this.file = this.cwd;
|
||||
this.value = this.cwd;
|
||||
|
||||
if (options.label && ~options.label.indexOf('%path')) {
|
||||
this._label.setContent(options.label.replace('%path', this.cwd));
|
||||
}
|
||||
|
||||
this.on('select', function(item) {
|
||||
var value = item.content.replace(/\{[^{}]+\}/g, '').replace(/@$/, '')
|
||||
, file = path.resolve(self.cwd, value);
|
||||
|
||||
return fs.stat(file, function(err, stat) {
|
||||
if (err) {
|
||||
return self.emit('error', err, file);
|
||||
}
|
||||
self.file = file;
|
||||
self.value = file;
|
||||
if (stat.isDirectory()) {
|
||||
self.emit('cd', file, self.cwd);
|
||||
self.cwd = file;
|
||||
if (options.label && ~options.label.indexOf('%path')) {
|
||||
self._label.setContent(options.label.replace('%path', file));
|
||||
}
|
||||
self.refresh();
|
||||
} else {
|
||||
self.emit('file', file);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
FileManager.prototype.__proto__ = List.prototype;
|
||||
|
||||
FileManager.prototype.type = 'file-manager';
|
||||
|
||||
FileManager.prototype.refresh = function(cwd, callback) {
|
||||
if (!callback) {
|
||||
callback = cwd;
|
||||
cwd = null;
|
||||
}
|
||||
|
||||
var self = this;
|
||||
|
||||
if (cwd) this.cwd = cwd;
|
||||
else cwd = this.cwd;
|
||||
|
||||
return fs.readdir(cwd, function(err, list) {
|
||||
if (err && err.code === 'ENOENT') {
|
||||
self.cwd = cwd !== process.env.HOME
|
||||
? process.env.HOME
|
||||
: '/';
|
||||
return self.refresh(callback);
|
||||
}
|
||||
|
||||
if (err) {
|
||||
if (callback) return callback(err);
|
||||
return self.emit('error', err, cwd);
|
||||
}
|
||||
|
||||
var dirs = []
|
||||
, files = [];
|
||||
|
||||
list.unshift('..');
|
||||
|
||||
list.forEach(function(name) {
|
||||
var f = path.resolve(cwd, name)
|
||||
, stat;
|
||||
|
||||
try {
|
||||
stat = fs.lstatSync(f);
|
||||
} catch (e) {
|
||||
;
|
||||
}
|
||||
|
||||
if ((stat && stat.isDirectory()) || name === '..') {
|
||||
dirs.push({
|
||||
name: name,
|
||||
text: '{light-blue-fg}' + name + '{/light-blue-fg}/',
|
||||
dir: true
|
||||
});
|
||||
} else if (stat && stat.isSymbolicLink()) {
|
||||
files.push({
|
||||
name: name,
|
||||
text: '{light-cyan-fg}' + name + '{/light-cyan-fg}@',
|
||||
dir: false
|
||||
});
|
||||
} else {
|
||||
files.push({
|
||||
name: name,
|
||||
text: name,
|
||||
dir: false
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
dirs = helpers.asort(dirs);
|
||||
files = helpers.asort(files);
|
||||
|
||||
list = dirs.concat(files).map(function(data) {
|
||||
return data.text;
|
||||
});
|
||||
|
||||
self.setItems(list);
|
||||
self.select(0);
|
||||
self.screen.render();
|
||||
|
||||
self.emit('refresh');
|
||||
|
||||
if (callback) callback();
|
||||
});
|
||||
};
|
||||
|
||||
FileManager.prototype.pick = function(cwd, callback) {
|
||||
if (!callback) {
|
||||
callback = cwd;
|
||||
cwd = null;
|
||||
}
|
||||
|
||||
var self = this
|
||||
, focused = this.screen.focused === this
|
||||
, hidden = this.hidden
|
||||
, onfile
|
||||
, oncancel;
|
||||
|
||||
function resume() {
|
||||
self.removeListener('file', onfile);
|
||||
self.removeListener('cancel', oncancel);
|
||||
if (hidden) {
|
||||
self.hide();
|
||||
}
|
||||
if (!focused) {
|
||||
self.screen.restoreFocus();
|
||||
}
|
||||
self.screen.render();
|
||||
}
|
||||
|
||||
this.on('file', onfile = function(file) {
|
||||
resume();
|
||||
return callback(null, file);
|
||||
});
|
||||
|
||||
this.on('cancel', oncancel = function() {
|
||||
resume();
|
||||
return callback();
|
||||
});
|
||||
|
||||
this.refresh(cwd, function(err) {
|
||||
if (err) return callback(err);
|
||||
|
||||
if (hidden) {
|
||||
self.show();
|
||||
}
|
||||
|
||||
if (!focused) {
|
||||
self.screen.saveFocus();
|
||||
self.focus();
|
||||
}
|
||||
|
||||
self.screen.render();
|
||||
});
|
||||
};
|
||||
|
||||
FileManager.prototype.reset = function(cwd, callback) {
|
||||
if (!callback) {
|
||||
callback = cwd;
|
||||
cwd = null;
|
||||
}
|
||||
this.cwd = cwd || this.options.cwd;
|
||||
this.refresh(callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = FileManager;
|
||||
267
lib/widgets/form.js
Normal file
@ -0,0 +1,267 @@
|
||||
/**
|
||||
* form.js - form element for blessed
|
||||
* Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Modules
|
||||
*/
|
||||
|
||||
var Node = require('./node');
|
||||
var Box = require('./box');
|
||||
|
||||
/**
|
||||
* Form
|
||||
*/
|
||||
|
||||
function Form(options) {
|
||||
var self = this;
|
||||
|
||||
if (!(this instanceof Node)) {
|
||||
return new Form(options);
|
||||
}
|
||||
|
||||
options = options || {};
|
||||
|
||||
options.ignoreKeys = true;
|
||||
Box.call(this, options);
|
||||
|
||||
if (options.keys) {
|
||||
this.screen._listenKeys(this);
|
||||
this.on('element keypress', function(el, ch, key) {
|
||||
if ((key.name === 'tab' && !key.shift)
|
||||
|| (el.type === 'textbox' && options.autoNext && key.name === 'enter')
|
||||
|| key.name === 'down'
|
||||
|| (options.vi && key.name === 'j')) {
|
||||
if (el.type === 'textbox' || el.type === 'textarea') {
|
||||
if (key.name === 'j') return;
|
||||
if (key.name === 'tab') {
|
||||
// Workaround, since we can't stop the tab from being added.
|
||||
el.emit('keypress', null, { name: 'backspace' });
|
||||
}
|
||||
el.emit('keypress', '\x1b', { name: 'escape' });
|
||||
}
|
||||
self.focusNext();
|
||||
return;
|
||||
}
|
||||
|
||||
if ((key.name === 'tab' && key.shift)
|
||||
|| key.name === 'up'
|
||||
|| (options.vi && key.name === 'k')) {
|
||||
if (el.type === 'textbox' || el.type === 'textarea') {
|
||||
if (key.name === 'k') return;
|
||||
el.emit('keypress', '\x1b', { name: 'escape' });
|
||||
}
|
||||
self.focusPrevious();
|
||||
return;
|
||||
}
|
||||
|
||||
if (key.name === 'escape') {
|
||||
self.focus();
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Form.prototype.__proto__ = Box.prototype;
|
||||
|
||||
Form.prototype.type = 'form';
|
||||
|
||||
Form.prototype._refresh = function() {
|
||||
// XXX Possibly remove this if statement and refresh on every focus.
|
||||
// Also potentially only include *visible* focusable elements.
|
||||
// This would remove the need to check for _selected.visible in previous()
|
||||
// and next().
|
||||
if (!this._children) {
|
||||
var out = [];
|
||||
|
||||
this.children.forEach(function fn(el) {
|
||||
if (el.keyable) out.push(el);
|
||||
el.children.forEach(fn);
|
||||
});
|
||||
|
||||
this._children = out;
|
||||
}
|
||||
};
|
||||
|
||||
Form.prototype._visible = function() {
|
||||
return !!this._children.filter(function(el) {
|
||||
return el.visible;
|
||||
}).length;
|
||||
};
|
||||
|
||||
Form.prototype.next = function() {
|
||||
this._refresh();
|
||||
|
||||
if (!this._visible()) return;
|
||||
|
||||
if (!this._selected) {
|
||||
this._selected = this._children[0];
|
||||
if (!this._selected.visible) return this.next();
|
||||
if (this.screen.focused !== this._selected) return this._selected;
|
||||
}
|
||||
|
||||
var i = this._children.indexOf(this._selected);
|
||||
if (!~i || !this._children[i + 1]) {
|
||||
this._selected = this._children[0];
|
||||
if (!this._selected.visible) return this.next();
|
||||
return this._selected;
|
||||
}
|
||||
|
||||
this._selected = this._children[i + 1];
|
||||
if (!this._selected.visible) return this.next();
|
||||
return this._selected;
|
||||
};
|
||||
|
||||
Form.prototype.previous = function() {
|
||||
this._refresh();
|
||||
|
||||
if (!this._visible()) return;
|
||||
|
||||
if (!this._selected) {
|
||||
this._selected = this._children[this._children.length - 1];
|
||||
if (!this._selected.visible) return this.previous();
|
||||
if (this.screen.focused !== this._selected) return this._selected;
|
||||
}
|
||||
|
||||
var i = this._children.indexOf(this._selected);
|
||||
if (!~i || !this._children[i - 1]) {
|
||||
this._selected = this._children[this._children.length - 1];
|
||||
if (!this._selected.visible) return this.previous();
|
||||
return this._selected;
|
||||
}
|
||||
|
||||
this._selected = this._children[i - 1];
|
||||
if (!this._selected.visible) return this.previous();
|
||||
return this._selected;
|
||||
};
|
||||
|
||||
Form.prototype.focusNext = function() {
|
||||
var next = this.next();
|
||||
if (next) next.focus();
|
||||
};
|
||||
|
||||
Form.prototype.focusPrevious = function() {
|
||||
var previous = this.previous();
|
||||
if (previous) previous.focus();
|
||||
};
|
||||
|
||||
Form.prototype.resetSelected = function() {
|
||||
this._selected = null;
|
||||
};
|
||||
|
||||
Form.prototype.focusFirst = function() {
|
||||
this.resetSelected();
|
||||
this.focusNext();
|
||||
};
|
||||
|
||||
Form.prototype.focusLast = function() {
|
||||
this.resetSelected();
|
||||
this.focusPrevious();
|
||||
};
|
||||
|
||||
Form.prototype.submit = function() {
|
||||
var out = {};
|
||||
|
||||
this.children.forEach(function fn(el) {
|
||||
if (el.value != null) {
|
||||
var name = el.name || el.type;
|
||||
if (Array.isArray(out[name])) {
|
||||
out[name].push(el.value);
|
||||
} else if (out[name]) {
|
||||
out[name] = [out[name], el.value];
|
||||
} else {
|
||||
out[name] = el.value;
|
||||
}
|
||||
}
|
||||
el.children.forEach(fn);
|
||||
});
|
||||
|
||||
this.emit('submit', out);
|
||||
|
||||
return this.submission = out;
|
||||
};
|
||||
|
||||
Form.prototype.cancel = function() {
|
||||
this.emit('cancel');
|
||||
};
|
||||
|
||||
Form.prototype.reset = function() {
|
||||
this.children.forEach(function fn(el) {
|
||||
switch (el.type) {
|
||||
case 'screen':
|
||||
break;
|
||||
case 'box':
|
||||
break;
|
||||
case 'text':
|
||||
break;
|
||||
case 'line':
|
||||
break;
|
||||
case 'scrollable-box':
|
||||
break;
|
||||
case 'list':
|
||||
el.select(0);
|
||||
return;
|
||||
case 'form':
|
||||
break;
|
||||
case 'input':
|
||||
break;
|
||||
case 'textbox':
|
||||
el.clearInput();
|
||||
return;
|
||||
case 'textarea':
|
||||
el.clearInput();
|
||||
return;
|
||||
case 'button':
|
||||
delete el.value;
|
||||
break;
|
||||
case 'progress-bar':
|
||||
el.setProgress(0);
|
||||
break;
|
||||
case 'file-manager':
|
||||
el.refresh(el.options.cwd);
|
||||
return;
|
||||
case 'checkbox':
|
||||
el.uncheck();
|
||||
return;
|
||||
case 'radio-set':
|
||||
break;
|
||||
case 'radio-button':
|
||||
el.uncheck();
|
||||
return;
|
||||
case 'prompt':
|
||||
break;
|
||||
case 'question':
|
||||
break;
|
||||
case 'message':
|
||||
break;
|
||||
case 'info':
|
||||
break;
|
||||
case 'loading':
|
||||
break;
|
||||
case 'list-bar':
|
||||
//el.select(0);
|
||||
break;
|
||||
case 'dir-manager':
|
||||
el.refresh(el.options.cwd);
|
||||
return;
|
||||
case 'terminal':
|
||||
el.write('');
|
||||
return;
|
||||
case 'image':
|
||||
//el.clearImage();
|
||||
return;
|
||||
}
|
||||
el.children.forEach(fn);
|
||||
});
|
||||
|
||||
this.emit('reset');
|
||||
};
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = Form;
|
||||
61
lib/widgets/image.js
Normal file
@ -0,0 +1,61 @@
|
||||
/**
|
||||
* image.js - image element for blessed
|
||||
* Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Modules
|
||||
*/
|
||||
|
||||
var Node = require('./node');
|
||||
var Box = require('./box');
|
||||
|
||||
/**
|
||||
* Image
|
||||
*/
|
||||
|
||||
function Image(options) {
|
||||
if (!(this instanceof Node)) {
|
||||
return new Image(options);
|
||||
}
|
||||
|
||||
options = options || {};
|
||||
options.type = options.itype || options.type || 'ansi';
|
||||
|
||||
Box.call(this, options);
|
||||
|
||||
if (options.type === 'ansi' && this.type !== 'ansiimage') {
|
||||
var ANSIImage = require('./ansiimage');
|
||||
Object.getOwnPropertyNames(ANSIImage.prototype).forEach(function(key) {
|
||||
if (key === 'type') return;
|
||||
Object.defineProperty(this, key,
|
||||
Object.getOwnPropertyDescriptor(ANSIImage.prototype, key));
|
||||
}, this);
|
||||
ANSIImage.call(this, options);
|
||||
return this;
|
||||
}
|
||||
|
||||
if (options.type === 'overlay' && this.type !== 'overlayimage') {
|
||||
var OverlayImage = require('./overlayimage');
|
||||
Object.getOwnPropertyNames(OverlayImage.prototype).forEach(function(key) {
|
||||
if (key === 'type') return;
|
||||
Object.defineProperty(this, key,
|
||||
Object.getOwnPropertyDescriptor(OverlayImage.prototype, key));
|
||||
}, this);
|
||||
OverlayImage.call(this, options);
|
||||
return this;
|
||||
}
|
||||
|
||||
throw new Error('`type` must either be `ansi` or `overlay`.');
|
||||
}
|
||||
|
||||
Image.prototype.__proto__ = Box.prototype;
|
||||
|
||||
Image.prototype.type = 'image';
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = Image;
|
||||
34
lib/widgets/input.js
Normal file
@ -0,0 +1,34 @@
|
||||
/**
|
||||
* input.js - abstract input element for blessed
|
||||
* Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Modules
|
||||
*/
|
||||
|
||||
var Node = require('./node');
|
||||
var Box = require('./box');
|
||||
|
||||
/**
|
||||
* Input
|
||||
*/
|
||||
|
||||
function Input(options) {
|
||||
if (!(this instanceof Node)) {
|
||||
return new Input(options);
|
||||
}
|
||||
options = options || {};
|
||||
Box.call(this, options);
|
||||
}
|
||||
|
||||
Input.prototype.__proto__ = Box.prototype;
|
||||
|
||||
Input.prototype.type = 'input';
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = Input;
|
||||
233
lib/widgets/layout.js
Normal file
@ -0,0 +1,233 @@
|
||||
/**
|
||||
* layout.js - layout element for blessed
|
||||
* Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Modules
|
||||
*/
|
||||
|
||||
var Node = require('./node');
|
||||
var Element = require('./element');
|
||||
|
||||
/**
|
||||
* Layout
|
||||
*/
|
||||
|
||||
function Layout(options) {
|
||||
if (!(this instanceof Node)) {
|
||||
return new Layout(options);
|
||||
}
|
||||
|
||||
options = options || {};
|
||||
|
||||
if ((options.width == null
|
||||
&& (options.left == null && options.right == null))
|
||||
|| (options.height == null
|
||||
&& (options.top == null && options.bottom == null))) {
|
||||
throw new Error('`Layout` must have a width and height!');
|
||||
}
|
||||
|
||||
options.layout = options.layout || 'inline';
|
||||
|
||||
Element.call(this, options);
|
||||
|
||||
if (options.renderer) {
|
||||
this.renderer = options.renderer;
|
||||
}
|
||||
}
|
||||
|
||||
Layout.prototype.__proto__ = Element.prototype;
|
||||
|
||||
Layout.prototype.type = 'layout';
|
||||
|
||||
Layout.prototype.isRendered = function(el) {
|
||||
if (!el.lpos) return false;
|
||||
return (el.lpos.xl - el.lpos.xi) > 0
|
||||
&& (el.lpos.yl - el.lpos.yi) > 0;
|
||||
};
|
||||
|
||||
Layout.prototype.getLast = function(i) {
|
||||
while (this.children[--i]) {
|
||||
var el = this.children[i];
|
||||
if (this.isRendered(el)) return el;
|
||||
}
|
||||
};
|
||||
|
||||
Layout.prototype.getLastCoords = function(i) {
|
||||
var last = this.getLast(i);
|
||||
if (last) return last.lpos;
|
||||
};
|
||||
|
||||
Layout.prototype._renderCoords = function() {
|
||||
var coords = this._getCoords(true);
|
||||
var children = this.children;
|
||||
this.children = [];
|
||||
this._render();
|
||||
this.children = children;
|
||||
return coords;
|
||||
};
|
||||
|
||||
Layout.prototype.renderer = function(coords) {
|
||||
var self = this;
|
||||
|
||||
// The coordinates of the layout element
|
||||
var width = coords.xl - coords.xi
|
||||
, height = coords.yl - coords.yi
|
||||
, xi = coords.xi
|
||||
, yi = coords.yi;
|
||||
|
||||
// The current row offset in cells (which row are we on?)
|
||||
var rowOffset = 0;
|
||||
|
||||
// The index of the first child in the row
|
||||
var rowIndex = 0;
|
||||
var lastRowIndex = 0;
|
||||
|
||||
// Figure out the highest width child
|
||||
if (this.options.layout === 'grid') {
|
||||
var highWidth = this.children.reduce(function(out, el) {
|
||||
out = Math.max(out, el.width);
|
||||
return out;
|
||||
}, 0);
|
||||
}
|
||||
|
||||
return function iterator(el, i) {
|
||||
// Make our children shrinkable. If they don't have a height, for
|
||||
// example, calculate it for them.
|
||||
el.shrink = true;
|
||||
|
||||
// Find the previous rendered child's coordinates
|
||||
var last = self.getLast(i);
|
||||
|
||||
// If there is no previously rendered element, we are on the first child.
|
||||
if (!last) {
|
||||
el.position.left = 0;
|
||||
el.position.top = 0;
|
||||
} else {
|
||||
// Otherwise, figure out where to place this child. We'll start by
|
||||
// setting it's `left`/`x` coordinate to right after the previous
|
||||
// rendered element. This child will end up directly to the right of it.
|
||||
el.position.left = last.lpos.xl - xi;
|
||||
|
||||
// Make sure the position matches the highest width element
|
||||
if (self.options.layout === 'grid') {
|
||||
// Compensate with width:
|
||||
// el.position.width = el.width + (highWidth - el.width);
|
||||
// Compensate with position:
|
||||
el.position.left += highWidth - (last.lpos.xl - last.lpos.xi);
|
||||
}
|
||||
|
||||
// If our child does not overlap the right side of the Layout, set it's
|
||||
// `top`/`y` to the current `rowOffset` (the coordinate for the current
|
||||
// row).
|
||||
if (el.position.left + el.width <= width) {
|
||||
el.position.top = rowOffset;
|
||||
} else {
|
||||
// Otherwise we need to start a new row and calculate a new
|
||||
// `rowOffset` and `rowIndex` (the index of the child on the current
|
||||
// row).
|
||||
rowOffset += self.children.slice(rowIndex, i).reduce(function(out, el) {
|
||||
if (!self.isRendered(el)) return out;
|
||||
out = Math.max(out, el.lpos.yl - el.lpos.yi);
|
||||
return out;
|
||||
}, 0);
|
||||
lastRowIndex = rowIndex;
|
||||
rowIndex = i;
|
||||
el.position.left = 0;
|
||||
el.position.top = rowOffset;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the elements on lower rows graviatate up as much as possible
|
||||
if (self.options.layout === 'inline') {
|
||||
var above = null;
|
||||
var abovea = Infinity;
|
||||
for (var j = lastRowIndex; j < rowIndex; j++) {
|
||||
var l = self.children[j];
|
||||
if (!self.isRendered(l)) continue;
|
||||
var abs = Math.abs(el.position.left - (l.lpos.xi - xi));
|
||||
// if (abs < abovea && (l.lpos.xl - l.lpos.xi) <= el.width) {
|
||||
if (abs < abovea) {
|
||||
above = l;
|
||||
abovea = abs;
|
||||
}
|
||||
}
|
||||
if (above) {
|
||||
el.position.top = above.lpos.yl - yi;
|
||||
}
|
||||
}
|
||||
|
||||
// If our child overflows the Layout, do not render it!
|
||||
// Disable this feature for now.
|
||||
if (el.position.top + el.height > height) {
|
||||
// Returning false tells blessed to ignore this child.
|
||||
// return false;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
Layout.prototype.render = function() {
|
||||
this._emit('prerender');
|
||||
|
||||
var coords = this._renderCoords();
|
||||
if (!coords) {
|
||||
delete this.lpos;
|
||||
return;
|
||||
}
|
||||
|
||||
if (coords.xl - coords.xi <= 0) {
|
||||
coords.xl = Math.max(coords.xl, coords.xi);
|
||||
return;
|
||||
}
|
||||
|
||||
if (coords.yl - coords.yi <= 0) {
|
||||
coords.yl = Math.max(coords.yl, coords.yi);
|
||||
return;
|
||||
}
|
||||
|
||||
this.lpos = coords;
|
||||
|
||||
if (this.border) coords.xi++, coords.xl--, coords.yi++, coords.yl--;
|
||||
if (this.tpadding) {
|
||||
coords.xi += this.padding.left, coords.xl -= this.padding.right;
|
||||
coords.yi += this.padding.top, coords.yl -= this.padding.bottom;
|
||||
}
|
||||
|
||||
var iterator = this.renderer(coords);
|
||||
|
||||
if (this.border) coords.xi--, coords.xl++, coords.yi--, coords.yl++;
|
||||
if (this.tpadding) {
|
||||
coords.xi -= this.padding.left, coords.xl += this.padding.right;
|
||||
coords.yi -= this.padding.top, coords.yl += this.padding.bottom;
|
||||
}
|
||||
|
||||
this.children.forEach(function(el, i) {
|
||||
if (el.screen._ci !== -1) {
|
||||
el.index = el.screen._ci++;
|
||||
}
|
||||
var rendered = iterator(el, i);
|
||||
if (rendered === false) {
|
||||
delete el.lpos;
|
||||
return;
|
||||
}
|
||||
// if (el.screen._rendering) {
|
||||
// el._rendering = true;
|
||||
// }
|
||||
el.render();
|
||||
// if (el.screen._rendering) {
|
||||
// el._rendering = false;
|
||||
// }
|
||||
});
|
||||
|
||||
this._emit('render', [coords]);
|
||||
|
||||
return coords;
|
||||
};
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = Layout;
|
||||
56
lib/widgets/line.js
Normal file
@ -0,0 +1,56 @@
|
||||
/**
|
||||
* line.js - line element for blessed
|
||||
* Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Modules
|
||||
*/
|
||||
|
||||
var Node = require('./node');
|
||||
var Box = require('./box');
|
||||
|
||||
/**
|
||||
* Line
|
||||
*/
|
||||
|
||||
function Line(options) {
|
||||
if (!(this instanceof Node)) {
|
||||
return new Line(options);
|
||||
}
|
||||
|
||||
options = options || {};
|
||||
|
||||
var orientation = options.orientation || 'vertical';
|
||||
delete options.orientation;
|
||||
|
||||
if (orientation === 'vertical') {
|
||||
options.width = 1;
|
||||
} else {
|
||||
options.height = 1;
|
||||
}
|
||||
|
||||
Box.call(this, options);
|
||||
|
||||
this.ch = !options.type || options.type === 'line'
|
||||
? orientation === 'horizontal' ? '─' : '│'
|
||||
: options.ch || ' ';
|
||||
|
||||
this.border = {
|
||||
type: 'bg',
|
||||
__proto__: this
|
||||
};
|
||||
|
||||
this.style.border = this.style;
|
||||
}
|
||||
|
||||
Line.prototype.__proto__ = Box.prototype;
|
||||
|
||||
Line.prototype.type = 'line';
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = Line;
|
||||
599
lib/widgets/list.js
Normal file
@ -0,0 +1,599 @@
|
||||
/**
|
||||
* list.js - list element for blessed
|
||||
* Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Modules
|
||||
*/
|
||||
|
||||
var helpers = require('../helpers');
|
||||
|
||||
var Node = require('./node');
|
||||
var Box = require('./box');
|
||||
|
||||
/**
|
||||
* List
|
||||
*/
|
||||
|
||||
function List(options) {
|
||||
var self = this;
|
||||
|
||||
if (!(this instanceof Node)) {
|
||||
return new List(options);
|
||||
}
|
||||
|
||||
options = options || {};
|
||||
|
||||
options.ignoreKeys = true;
|
||||
// Possibly put this here: this.items = [];
|
||||
options.scrollable = true;
|
||||
Box.call(this, options);
|
||||
|
||||
this.value = '';
|
||||
this.items = [];
|
||||
this.ritems = [];
|
||||
this.selected = 0;
|
||||
this._isList = true;
|
||||
|
||||
if (!this.style.selected) {
|
||||
this.style.selected = {};
|
||||
this.style.selected.bg = options.selectedBg;
|
||||
this.style.selected.fg = options.selectedFg;
|
||||
this.style.selected.bold = options.selectedBold;
|
||||
this.style.selected.underline = options.selectedUnderline;
|
||||
this.style.selected.blink = options.selectedBlink;
|
||||
this.style.selected.inverse = options.selectedInverse;
|
||||
this.style.selected.invisible = options.selectedInvisible;
|
||||
}
|
||||
|
||||
if (!this.style.item) {
|
||||
this.style.item = {};
|
||||
this.style.item.bg = options.itemBg;
|
||||
this.style.item.fg = options.itemFg;
|
||||
this.style.item.bold = options.itemBold;
|
||||
this.style.item.underline = options.itemUnderline;
|
||||
this.style.item.blink = options.itemBlink;
|
||||
this.style.item.inverse = options.itemInverse;
|
||||
this.style.item.invisible = options.itemInvisible;
|
||||
}
|
||||
|
||||
// Legacy: for apps written before the addition of item attributes.
|
||||
['bg', 'fg', 'bold', 'underline',
|
||||
'blink', 'inverse', 'invisible'].forEach(function(name) {
|
||||
if (self.style[name] != null && self.style.item[name] == null) {
|
||||
self.style.item[name] = self.style[name];
|
||||
}
|
||||
});
|
||||
|
||||
if (this.options.itemHoverBg) {
|
||||
this.options.itemHoverEffects = { bg: this.options.itemHoverBg };
|
||||
}
|
||||
|
||||
if (this.options.itemHoverEffects) {
|
||||
this.style.item.hover = this.options.itemHoverEffects;
|
||||
}
|
||||
|
||||
if (this.options.itemFocusEffects) {
|
||||
this.style.item.focus = this.options.itemFocusEffects;
|
||||
}
|
||||
|
||||
this.interactive = options.interactive !== false;
|
||||
|
||||
this.mouse = options.mouse || false;
|
||||
|
||||
if (options.items) {
|
||||
this.ritems = options.items;
|
||||
options.items.forEach(this.add.bind(this));
|
||||
}
|
||||
|
||||
this.select(0);
|
||||
|
||||
if (options.mouse) {
|
||||
this.screen._listenMouse(this);
|
||||
this.on('element wheeldown', function() {
|
||||
self.select(self.selected + 2);
|
||||
self.screen.render();
|
||||
});
|
||||
this.on('element wheelup', function() {
|
||||
self.select(self.selected - 2);
|
||||
self.screen.render();
|
||||
});
|
||||
}
|
||||
|
||||
if (options.keys) {
|
||||
this.on('keypress', function(ch, key) {
|
||||
if (key.name === 'up' || (options.vi && key.name === 'k')) {
|
||||
self.up();
|
||||
self.screen.render();
|
||||
return;
|
||||
}
|
||||
if (key.name === 'down' || (options.vi && key.name === 'j')) {
|
||||
self.down();
|
||||
self.screen.render();
|
||||
return;
|
||||
}
|
||||
if (key.name === 'enter'
|
||||
|| (options.vi && key.name === 'l' && !key.shift)) {
|
||||
self.enterSelected();
|
||||
return;
|
||||
}
|
||||
if (key.name === 'escape' || (options.vi && key.name === 'q')) {
|
||||
self.cancelSelected();
|
||||
return;
|
||||
}
|
||||
if (options.vi && key.name === 'u' && key.ctrl) {
|
||||
self.move(-((self.height - self.iheight) / 2) | 0);
|
||||
self.screen.render();
|
||||
return;
|
||||
}
|
||||
if (options.vi && key.name === 'd' && key.ctrl) {
|
||||
self.move((self.height - self.iheight) / 2 | 0);
|
||||
self.screen.render();
|
||||
return;
|
||||
}
|
||||
if (options.vi && key.name === 'b' && key.ctrl) {
|
||||
self.move(-(self.height - self.iheight));
|
||||
self.screen.render();
|
||||
return;
|
||||
}
|
||||
if (options.vi && key.name === 'f' && key.ctrl) {
|
||||
self.move(self.height - self.iheight);
|
||||
self.screen.render();
|
||||
return;
|
||||
}
|
||||
if (options.vi && key.name === 'h' && key.shift) {
|
||||
self.move(self.childBase - self.selected);
|
||||
self.screen.render();
|
||||
return;
|
||||
}
|
||||
if (options.vi && key.name === 'm' && key.shift) {
|
||||
// TODO: Maybe use Math.min(this.items.length,
|
||||
// ... for calculating visible items elsewhere.
|
||||
var visible = Math.min(
|
||||
self.height - self.iheight,
|
||||
self.items.length) / 2 | 0;
|
||||
self.move(self.childBase + visible - self.selected);
|
||||
self.screen.render();
|
||||
return;
|
||||
}
|
||||
if (options.vi && key.name === 'l' && key.shift) {
|
||||
// XXX This goes one too far on lists with an odd number of items.
|
||||
self.down(self.childBase
|
||||
+ Math.min(self.height - self.iheight, self.items.length)
|
||||
- self.selected);
|
||||
self.screen.render();
|
||||
return;
|
||||
}
|
||||
if (options.vi && key.name === 'g' && !key.shift) {
|
||||
self.select(0);
|
||||
self.screen.render();
|
||||
return;
|
||||
}
|
||||
if (options.vi && key.name === 'g' && key.shift) {
|
||||
self.select(self.items.length - 1);
|
||||
self.screen.render();
|
||||
return;
|
||||
}
|
||||
|
||||
if (options.vi && (key.ch === '/' || key.ch === '?')) {
|
||||
if (typeof self.options.search !== 'function') {
|
||||
return;
|
||||
}
|
||||
return self.options.search(function(err, value) {
|
||||
if (typeof err === 'string' || typeof err === 'function'
|
||||
|| typeof err === 'number' || (err && err.test)) {
|
||||
value = err;
|
||||
err = null;
|
||||
}
|
||||
if (err || !value) return self.screen.render();
|
||||
self.select(self.fuzzyFind(value, key.ch === '?'));
|
||||
self.screen.render();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.on('resize', function() {
|
||||
var visible = self.height - self.iheight;
|
||||
// if (self.selected < visible - 1) {
|
||||
if (visible >= self.selected + 1) {
|
||||
self.childBase = 0;
|
||||
self.childOffset = self.selected;
|
||||
} else {
|
||||
// Is this supposed to be: self.childBase = visible - self.selected + 1; ?
|
||||
self.childBase = self.selected - visible + 1;
|
||||
self.childOffset = visible - 1;
|
||||
}
|
||||
});
|
||||
|
||||
this.on('adopt', function(el) {
|
||||
if (!~self.items.indexOf(el)) {
|
||||
el.fixed = true;
|
||||
}
|
||||
});
|
||||
|
||||
// Ensure children are removed from the
|
||||
// item list if they are items.
|
||||
this.on('remove', function(el) {
|
||||
self.removeItem(el);
|
||||
});
|
||||
}
|
||||
|
||||
List.prototype.__proto__ = Box.prototype;
|
||||
|
||||
List.prototype.type = 'list';
|
||||
|
||||
List.prototype.createItem = function(content) {
|
||||
var self = this;
|
||||
|
||||
// Note: Could potentially use Button here.
|
||||
var options = {
|
||||
screen: this.screen,
|
||||
content: content,
|
||||
align: this.align || 'left',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: (this.scrollbar ? 1 : 0),
|
||||
tags: this.parseTags,
|
||||
height: 1,
|
||||
hoverEffects: this.mouse ? this.style.item.hover : null,
|
||||
focusEffects: this.mouse ? this.style.item.focus : null,
|
||||
autoFocus: false
|
||||
};
|
||||
|
||||
if (!this.screen.autoPadding) {
|
||||
options.top = 1;
|
||||
options.left = this.ileft;
|
||||
options.right = this.iright + (this.scrollbar ? 1 : 0);
|
||||
}
|
||||
|
||||
// if (this.shrink) {
|
||||
// XXX NOTE: Maybe just do this on all shrinkage once autoPadding is default?
|
||||
if (this.shrink && this.options.normalShrink) {
|
||||
delete options.right;
|
||||
options.width = 'shrink';
|
||||
}
|
||||
|
||||
['bg', 'fg', 'bold', 'underline',
|
||||
'blink', 'inverse', 'invisible'].forEach(function(name) {
|
||||
options[name] = function() {
|
||||
var attr = self.items[self.selected] === item && self.interactive
|
||||
? self.style.selected[name]
|
||||
: self.style.item[name];
|
||||
if (typeof attr === 'function') attr = attr(item);
|
||||
return attr;
|
||||
};
|
||||
});
|
||||
|
||||
if (this.style.transparent) {
|
||||
options.transparent = true;
|
||||
}
|
||||
|
||||
var item = new Box(options);
|
||||
|
||||
if (this.mouse) {
|
||||
item.on('click', function() {
|
||||
self.focus();
|
||||
if (self.items[self.selected] === item) {
|
||||
self.emit('action', item, self.selected);
|
||||
self.emit('select', item, self.selected);
|
||||
return;
|
||||
}
|
||||
self.select(item);
|
||||
self.screen.render();
|
||||
});
|
||||
}
|
||||
|
||||
this.emit('create item');
|
||||
|
||||
return item;
|
||||
};
|
||||
|
||||
List.prototype.add =
|
||||
List.prototype.addItem =
|
||||
List.prototype.appendItem = function(content) {
|
||||
content = typeof content === 'string' ? content : content.getContent();
|
||||
|
||||
var item = this.createItem(content);
|
||||
item.position.top = this.items.length;
|
||||
if (!this.screen.autoPadding) {
|
||||
item.position.top = this.itop + this.items.length;
|
||||
}
|
||||
|
||||
this.ritems.push(content);
|
||||
this.items.push(item);
|
||||
this.append(item);
|
||||
|
||||
if (this.items.length === 1) {
|
||||
this.select(0);
|
||||
}
|
||||
|
||||
this.emit('add item');
|
||||
|
||||
return item;
|
||||
};
|
||||
|
||||
List.prototype.removeItem = function(child) {
|
||||
var i = this.getItemIndex(child);
|
||||
if (~i && this.items[i]) {
|
||||
child = this.items.splice(i, 1)[0];
|
||||
this.ritems.splice(i, 1);
|
||||
this.remove(child);
|
||||
for (var j = i; j < this.items.length; j++) {
|
||||
this.items[j].position.top--;
|
||||
}
|
||||
if (i === this.selected) {
|
||||
this.select(i - 1);
|
||||
}
|
||||
}
|
||||
this.emit('remove item');
|
||||
return child;
|
||||
};
|
||||
|
||||
List.prototype.insertItem = function(child, content) {
|
||||
content = typeof content === 'string' ? content : content.getContent();
|
||||
var i = this.getItemIndex(child);
|
||||
if (!~i) return;
|
||||
if (i >= this.items.length) return this.appendItem(content);
|
||||
var item = this.createItem(content);
|
||||
for (var j = i; j < this.items.length; j++) {
|
||||
this.items[j].position.top++;
|
||||
}
|
||||
item.position.top = i + (!this.screen.autoPadding ? 1 : 0);
|
||||
this.ritems.splice(i, 0, content);
|
||||
this.items.splice(i, 0, item);
|
||||
this.append(item);
|
||||
if (i === this.selected) {
|
||||
this.select(i + 1);
|
||||
}
|
||||
this.emit('insert item');
|
||||
};
|
||||
|
||||
List.prototype.getItem = function(child) {
|
||||
return this.items[this.getItemIndex(child)];
|
||||
};
|
||||
|
||||
List.prototype.setItem = function(child, content) {
|
||||
content = typeof content === 'string' ? content : content.getContent();
|
||||
var i = this.getItemIndex(child);
|
||||
if (!~i) return;
|
||||
this.items[i].setContent(content);
|
||||
this.ritems[i] = content;
|
||||
};
|
||||
|
||||
List.prototype.clearItems = function() {
|
||||
return this.setItems([]);
|
||||
};
|
||||
|
||||
List.prototype.setItems = function(items) {
|
||||
var original = this.items.slice()
|
||||
, selected = this.selected
|
||||
, sel = this.ritems[this.selected]
|
||||
, i = 0;
|
||||
|
||||
items = items.slice();
|
||||
|
||||
this.select(0);
|
||||
|
||||
for (; i < items.length; i++) {
|
||||
if (this.items[i]) {
|
||||
this.items[i].setContent(items[i]);
|
||||
} else {
|
||||
this.add(items[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for (; i < original.length; i++) {
|
||||
this.remove(original[i]);
|
||||
}
|
||||
|
||||
this.ritems = items;
|
||||
|
||||
// Try to find our old item if it still exists.
|
||||
sel = items.indexOf(sel);
|
||||
if (~sel) {
|
||||
this.select(sel);
|
||||
} else if (items.length === original.length) {
|
||||
this.select(selected);
|
||||
} else {
|
||||
this.select(Math.min(selected, items.length - 1));
|
||||
}
|
||||
|
||||
this.emit('set items');
|
||||
};
|
||||
|
||||
List.prototype.pushItem = function(content) {
|
||||
this.appendItem(content);
|
||||
return this.items.length;
|
||||
};
|
||||
|
||||
List.prototype.popItem = function() {
|
||||
return this.removeItem(this.items.length - 1);
|
||||
};
|
||||
|
||||
List.prototype.unshiftItem = function(content) {
|
||||
this.insertItem(0, content);
|
||||
return this.items.length;
|
||||
};
|
||||
|
||||
List.prototype.shiftItem = function() {
|
||||
return this.removeItem(0);
|
||||
};
|
||||
|
||||
List.prototype.spliceItem = function(child, n) {
|
||||
var self = this;
|
||||
var i = this.getItemIndex(child);
|
||||
if (!~i) return;
|
||||
var items = Array.prototype.slice.call(arguments, 2);
|
||||
var removed = [];
|
||||
while (n--) {
|
||||
removed.push(this.removeItem(i));
|
||||
}
|
||||
items.forEach(function(item) {
|
||||
self.insertItem(i++, item);
|
||||
});
|
||||
return removed;
|
||||
};
|
||||
|
||||
List.prototype.find =
|
||||
List.prototype.fuzzyFind = function(search, back) {
|
||||
var start = this.selected + (back ? -1 : 1)
|
||||
, i;
|
||||
|
||||
if (typeof search === 'number') search += '';
|
||||
|
||||
if (search && search[0] === '/' && search[search.length - 1] === '/') {
|
||||
try {
|
||||
search = new RegExp(search.slice(1, -1));
|
||||
} catch (e) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
var test = typeof search === 'string'
|
||||
? function(item) { return !!~item.indexOf(search); }
|
||||
: (search.test ? search.test.bind(search) : search);
|
||||
|
||||
if (typeof test !== 'function') {
|
||||
if (this.screen.options.debug) {
|
||||
throw new Error('fuzzyFind(): `test` is not a function.');
|
||||
}
|
||||
return this.selected;
|
||||
}
|
||||
|
||||
if (!back) {
|
||||
for (i = start; i < this.ritems.length; i++) {
|
||||
if (test(helpers.cleanTags(this.ritems[i]))) return i;
|
||||
}
|
||||
for (i = 0; i < start; i++) {
|
||||
if (test(helpers.cleanTags(this.ritems[i]))) return i;
|
||||
}
|
||||
} else {
|
||||
for (i = start; i >= 0; i--) {
|
||||
if (test(helpers.cleanTags(this.ritems[i]))) return i;
|
||||
}
|
||||
for (i = this.ritems.length - 1; i > start; i--) {
|
||||
if (test(helpers.cleanTags(this.ritems[i]))) return i;
|
||||
}
|
||||
}
|
||||
|
||||
return this.selected;
|
||||
};
|
||||
|
||||
List.prototype.getItemIndex = function(child) {
|
||||
if (typeof child === 'number') {
|
||||
return child;
|
||||
} else if (typeof child === 'string') {
|
||||
var i = this.ritems.indexOf(child);
|
||||
if (~i) return i;
|
||||
for (i = 0; i < this.ritems.length; i++) {
|
||||
if (helpers.cleanTags(this.ritems[i]) === child) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
} else {
|
||||
return this.items.indexOf(child);
|
||||
}
|
||||
};
|
||||
|
||||
List.prototype.select = function(index) {
|
||||
if (!this.interactive) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.items.length) {
|
||||
this.selected = 0;
|
||||
this.value = '';
|
||||
this.scrollTo(0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof index === 'object') {
|
||||
index = this.items.indexOf(index);
|
||||
}
|
||||
|
||||
if (index < 0) {
|
||||
index = 0;
|
||||
} else if (index >= this.items.length) {
|
||||
index = this.items.length - 1;
|
||||
}
|
||||
|
||||
if (this.selected === index && this._listInitialized) return;
|
||||
this._listInitialized = true;
|
||||
|
||||
this.selected = index;
|
||||
this.value = helpers.cleanTags(this.ritems[this.selected]);
|
||||
if (!this.parent) return;
|
||||
this.scrollTo(this.selected);
|
||||
|
||||
// XXX Move `action` and `select` events here.
|
||||
this.emit('select item', this.items[this.selected], this.selected);
|
||||
};
|
||||
|
||||
List.prototype.move = function(offset) {
|
||||
this.select(this.selected + offset);
|
||||
};
|
||||
|
||||
List.prototype.up = function(offset) {
|
||||
this.move(-(offset || 1));
|
||||
};
|
||||
|
||||
List.prototype.down = function(offset) {
|
||||
this.move(offset || 1);
|
||||
};
|
||||
|
||||
List.prototype.pick = function(label, callback) {
|
||||
if (!callback) {
|
||||
callback = label;
|
||||
label = null;
|
||||
}
|
||||
|
||||
if (!this.interactive) {
|
||||
return callback();
|
||||
}
|
||||
|
||||
var self = this;
|
||||
var focused = this.screen.focused;
|
||||
if (focused && focused._done) focused._done('stop');
|
||||
this.screen.saveFocus();
|
||||
|
||||
// XXX Keep above:
|
||||
// var parent = this.parent;
|
||||
// this.detach();
|
||||
// parent.append(this);
|
||||
|
||||
this.focus();
|
||||
this.show();
|
||||
this.select(0);
|
||||
if (label) this.setLabel(label);
|
||||
this.screen.render();
|
||||
this.once('action', function(el, selected) {
|
||||
if (label) self.removeLabel();
|
||||
self.screen.restoreFocus();
|
||||
self.hide();
|
||||
self.screen.render();
|
||||
if (!el) return callback();
|
||||
return callback(null, helpers.cleanTags(self.ritems[selected]));
|
||||
});
|
||||
};
|
||||
|
||||
List.prototype.enterSelected = function(i) {
|
||||
if (i != null) this.select(i);
|
||||
this.emit('action', this.items[this.selected], this.selected);
|
||||
this.emit('select', this.items[this.selected], this.selected);
|
||||
};
|
||||
|
||||
List.prototype.cancelSelected = function(i) {
|
||||
if (i != null) this.select(i);
|
||||
this.emit('action');
|
||||
this.emit('cancel');
|
||||
};
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = List;
|
||||
411
lib/widgets/listbar.js
Normal file
@ -0,0 +1,411 @@
|
||||
/**
|
||||
* listbar.js - listbar element for blessed
|
||||
* Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Modules
|
||||
*/
|
||||
|
||||
var helpers = require('../helpers');
|
||||
|
||||
var Node = require('./node');
|
||||
var Box = require('./box');
|
||||
|
||||
/**
|
||||
* Listbar / HorizontalList
|
||||
*/
|
||||
|
||||
function Listbar(options) {
|
||||
var self = this;
|
||||
|
||||
if (!(this instanceof Node)) {
|
||||
return new Listbar(options);
|
||||
}
|
||||
|
||||
options = options || {};
|
||||
|
||||
this.items = [];
|
||||
this.ritems = [];
|
||||
this.commands = [];
|
||||
|
||||
this.leftBase = 0;
|
||||
this.leftOffset = 0;
|
||||
|
||||
this.mouse = options.mouse || false;
|
||||
|
||||
Box.call(this, options);
|
||||
|
||||
if (!this.style.selected) {
|
||||
this.style.selected = {};
|
||||
}
|
||||
|
||||
if (!this.style.item) {
|
||||
this.style.item = {};
|
||||
}
|
||||
|
||||
if (options.commands || options.items) {
|
||||
this.setItems(options.commands || options.items);
|
||||
}
|
||||
|
||||
if (options.keys) {
|
||||
this.on('keypress', function(ch, key) {
|
||||
if (key.name === 'left'
|
||||
|| (options.vi && key.name === 'h')
|
||||
|| (key.shift && key.name === 'tab')) {
|
||||
self.moveLeft();
|
||||
self.screen.render();
|
||||
// Stop propagation if we're in a form.
|
||||
if (key.name === 'tab') return false;
|
||||
return;
|
||||
}
|
||||
if (key.name === 'right'
|
||||
|| (options.vi && key.name === 'l')
|
||||
|| key.name === 'tab') {
|
||||
self.moveRight();
|
||||
self.screen.render();
|
||||
// Stop propagation if we're in a form.
|
||||
if (key.name === 'tab') return false;
|
||||
return;
|
||||
}
|
||||
if (key.name === 'enter'
|
||||
|| (options.vi && key.name === 'k' && !key.shift)) {
|
||||
self.emit('action', self.items[self.selected], self.selected);
|
||||
self.emit('select', self.items[self.selected], self.selected);
|
||||
var item = self.items[self.selected];
|
||||
if (item._.cmd.callback) {
|
||||
item._.cmd.callback();
|
||||
}
|
||||
self.screen.render();
|
||||
return;
|
||||
}
|
||||
if (key.name === 'escape' || (options.vi && key.name === 'q')) {
|
||||
self.emit('action');
|
||||
self.emit('cancel');
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (options.autoCommandKeys) {
|
||||
this.onScreenEvent('keypress', function(ch) {
|
||||
if (/^[0-9]$/.test(ch)) {
|
||||
var i = +ch - 1;
|
||||
if (!~i) i = 9;
|
||||
return self.selectTab(i);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.on('focus', function() {
|
||||
self.select(self.selected);
|
||||
});
|
||||
}
|
||||
|
||||
Listbar.prototype.__proto__ = Box.prototype;
|
||||
|
||||
Listbar.prototype.type = 'listbar';
|
||||
|
||||
Listbar.prototype.__defineGetter__('selected', function() {
|
||||
return this.leftBase + this.leftOffset;
|
||||
});
|
||||
|
||||
Listbar.prototype.setItems = function(commands) {
|
||||
var self = this;
|
||||
|
||||
if (!Array.isArray(commands)) {
|
||||
commands = Object.keys(commands).reduce(function(obj, key, i) {
|
||||
var cmd = commands[key]
|
||||
, cb;
|
||||
|
||||
if (typeof cmd === 'function') {
|
||||
cb = cmd;
|
||||
cmd = { callback: cb };
|
||||
}
|
||||
|
||||
if (cmd.text == null) cmd.text = key;
|
||||
if (cmd.prefix == null) cmd.prefix = ++i + '';
|
||||
|
||||
if (cmd.text == null && cmd.callback) {
|
||||
cmd.text = cmd.callback.name;
|
||||
}
|
||||
|
||||
obj.push(cmd);
|
||||
|
||||
return obj;
|
||||
}, []);
|
||||
}
|
||||
|
||||
this.items.forEach(function(el) {
|
||||
el.detach();
|
||||
});
|
||||
|
||||
this.items = [];
|
||||
this.ritems = [];
|
||||
this.commands = [];
|
||||
|
||||
commands.forEach(function(cmd) {
|
||||
self.add(cmd);
|
||||
});
|
||||
|
||||
this.emit('set items');
|
||||
};
|
||||
|
||||
Listbar.prototype.add =
|
||||
Listbar.prototype.addItem =
|
||||
Listbar.prototype.appendItem = function(item, callback) {
|
||||
var self = this
|
||||
, prev = this.items[this.items.length - 1]
|
||||
, drawn
|
||||
, cmd
|
||||
, title
|
||||
, len;
|
||||
|
||||
if (!this.parent) {
|
||||
drawn = 0;
|
||||
} else {
|
||||
drawn = prev ? prev.aleft + prev.width : 0;
|
||||
if (!this.screen.autoPadding) {
|
||||
drawn += this.ileft;
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof item === 'object') {
|
||||
cmd = item;
|
||||
if (cmd.prefix == null) cmd.prefix = (this.items.length + 1) + '';
|
||||
}
|
||||
|
||||
if (typeof item === 'string') {
|
||||
cmd = {
|
||||
prefix: (this.items.length + 1) + '',
|
||||
text: item,
|
||||
callback: callback
|
||||
};
|
||||
}
|
||||
|
||||
if (typeof item === 'function') {
|
||||
cmd = {
|
||||
prefix: (this.items.length + 1) + '',
|
||||
text: item.name,
|
||||
callback: item
|
||||
};
|
||||
}
|
||||
|
||||
if (cmd.keys && cmd.keys[0]) {
|
||||
cmd.prefix = cmd.keys[0];
|
||||
}
|
||||
|
||||
var t = helpers.generateTags(this.style.prefix || { fg: 'lightblack' });
|
||||
|
||||
title = (cmd.prefix != null ? t.open + cmd.prefix + t.close + ':' : '') + cmd.text;
|
||||
|
||||
len = ((cmd.prefix != null ? cmd.prefix + ':' : '') + cmd.text).length;
|
||||
|
||||
var options = {
|
||||
screen: this.screen,
|
||||
top: 0,
|
||||
left: drawn + 1,
|
||||
height: 1,
|
||||
content: title,
|
||||
width: len + 2,
|
||||
align: 'center',
|
||||
autoFocus: false,
|
||||
tags: true,
|
||||
mouse: true,
|
||||
style: helpers.merge({}, this.style.item),
|
||||
noOverflow: true
|
||||
};
|
||||
|
||||
if (!this.screen.autoPadding) {
|
||||
options.top += this.itop;
|
||||
options.left += this.ileft;
|
||||
}
|
||||
|
||||
['bg', 'fg', 'bold', 'underline',
|
||||
'blink', 'inverse', 'invisible'].forEach(function(name) {
|
||||
options.style[name] = function() {
|
||||
var attr = self.items[self.selected] === el
|
||||
? self.style.selected[name]
|
||||
: self.style.item[name];
|
||||
if (typeof attr === 'function') attr = attr(el);
|
||||
return attr;
|
||||
};
|
||||
});
|
||||
|
||||
var el = new Box(options);
|
||||
|
||||
this._[cmd.text] = el;
|
||||
cmd.element = el;
|
||||
el._.cmd = cmd;
|
||||
|
||||
this.ritems.push(cmd.text);
|
||||
this.items.push(el);
|
||||
this.commands.push(cmd);
|
||||
this.append(el);
|
||||
|
||||
if (cmd.callback) {
|
||||
if (cmd.keys) {
|
||||
this.screen.key(cmd.keys, function() {
|
||||
self.emit('action', el, self.selected);
|
||||
self.emit('select', el, self.selected);
|
||||
if (el._.cmd.callback) {
|
||||
el._.cmd.callback();
|
||||
}
|
||||
self.select(el);
|
||||
self.screen.render();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (this.items.length === 1) {
|
||||
this.select(0);
|
||||
}
|
||||
|
||||
// XXX May be affected by new element.options.mouse option.
|
||||
if (this.mouse) {
|
||||
el.on('click', function() {
|
||||
self.emit('action', el, self.selected);
|
||||
self.emit('select', el, self.selected);
|
||||
if (el._.cmd.callback) {
|
||||
el._.cmd.callback();
|
||||
}
|
||||
self.select(el);
|
||||
self.screen.render();
|
||||
});
|
||||
}
|
||||
|
||||
this.emit('add item');
|
||||
};
|
||||
|
||||
Listbar.prototype.render = function() {
|
||||
var self = this
|
||||
, drawn = 0;
|
||||
|
||||
if (!this.screen.autoPadding) {
|
||||
drawn += this.ileft;
|
||||
}
|
||||
|
||||
this.items.forEach(function(el, i) {
|
||||
if (i < self.leftBase) {
|
||||
el.hide();
|
||||
} else {
|
||||
el.rleft = drawn + 1;
|
||||
drawn += el.width + 2;
|
||||
el.show();
|
||||
}
|
||||
});
|
||||
|
||||
return this._render();
|
||||
};
|
||||
|
||||
Listbar.prototype.select = function(offset) {
|
||||
if (typeof offset !== 'number') {
|
||||
offset = this.items.indexOf(offset);
|
||||
}
|
||||
|
||||
if (offset < 0) {
|
||||
offset = 0;
|
||||
} else if (offset >= this.items.length) {
|
||||
offset = this.items.length - 1;
|
||||
}
|
||||
|
||||
if (!this.parent) {
|
||||
this.emit('select item', this.items[offset], offset);
|
||||
return;
|
||||
}
|
||||
|
||||
var lpos = this._getCoords();
|
||||
if (!lpos) return;
|
||||
|
||||
var self = this
|
||||
, width = (lpos.xl - lpos.xi) - this.iwidth
|
||||
, drawn = 0
|
||||
, visible = 0
|
||||
, el;
|
||||
|
||||
el = this.items[offset];
|
||||
if (!el) return;
|
||||
|
||||
this.items.forEach(function(el, i) {
|
||||
if (i < self.leftBase) return;
|
||||
|
||||
var lpos = el._getCoords();
|
||||
if (!lpos) return;
|
||||
|
||||
if (lpos.xl - lpos.xi <= 0) return;
|
||||
|
||||
drawn += (lpos.xl - lpos.xi) + 2;
|
||||
|
||||
if (drawn <= width) visible++;
|
||||
});
|
||||
|
||||
var diff = offset - (this.leftBase + this.leftOffset);
|
||||
if (offset > this.leftBase + this.leftOffset) {
|
||||
if (offset > this.leftBase + visible - 1) {
|
||||
this.leftOffset = 0;
|
||||
this.leftBase = offset;
|
||||
} else {
|
||||
this.leftOffset += diff;
|
||||
}
|
||||
} else if (offset < this.leftBase + this.leftOffset) {
|
||||
diff = -diff;
|
||||
if (offset < this.leftBase) {
|
||||
this.leftOffset = 0;
|
||||
this.leftBase = offset;
|
||||
} else {
|
||||
this.leftOffset -= diff;
|
||||
}
|
||||
}
|
||||
|
||||
// XXX Move `action` and `select` events here.
|
||||
this.emit('select item', el, offset);
|
||||
};
|
||||
|
||||
Listbar.prototype.removeItem = function(child) {
|
||||
var i = typeof child !== 'number'
|
||||
? this.items.indexOf(child)
|
||||
: child;
|
||||
|
||||
if (~i && this.items[i]) {
|
||||
child = this.items.splice(i, 1)[0];
|
||||
this.ritems.splice(i, 1);
|
||||
this.commands.splice(i, 1);
|
||||
this.remove(child);
|
||||
if (i === this.selected) {
|
||||
this.select(i - 1);
|
||||
}
|
||||
}
|
||||
|
||||
this.emit('remove item');
|
||||
};
|
||||
|
||||
Listbar.prototype.move = function(offset) {
|
||||
this.select(this.selected + offset);
|
||||
};
|
||||
|
||||
Listbar.prototype.moveLeft = function(offset) {
|
||||
this.move(-(offset || 1));
|
||||
};
|
||||
|
||||
Listbar.prototype.moveRight = function(offset) {
|
||||
this.move(offset || 1);
|
||||
};
|
||||
|
||||
Listbar.prototype.selectTab = function(index) {
|
||||
var item = this.items[index];
|
||||
if (item) {
|
||||
if (item._.cmd.callback) {
|
||||
item._.cmd.callback();
|
||||
}
|
||||
this.select(index);
|
||||
this.screen.render();
|
||||
}
|
||||
this.emit('select tab', item, index);
|
||||
};
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = Listbar;
|
||||
280
lib/widgets/listtable.js
Normal file
@ -0,0 +1,280 @@
|
||||
/**
|
||||
* listtable.js - list table element for blessed
|
||||
* Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Modules
|
||||
*/
|
||||
|
||||
var Node = require('./node');
|
||||
var Box = require('./box');
|
||||
var List = require('./list');
|
||||
var Table = require('./table');
|
||||
|
||||
/**
|
||||
* ListTable
|
||||
*/
|
||||
|
||||
function ListTable(options) {
|
||||
var self = this;
|
||||
|
||||
if (!(this instanceof Node)) {
|
||||
return new ListTable(options);
|
||||
}
|
||||
|
||||
options = options || {};
|
||||
|
||||
// options.shrink = true;
|
||||
options.normalShrink = true;
|
||||
options.style = options.style || {};
|
||||
options.style.border = options.style.border || {};
|
||||
options.style.header = options.style.header || {};
|
||||
options.style.cell = options.style.cell || {};
|
||||
this.__align = options.align || 'center';
|
||||
delete options.align;
|
||||
|
||||
options.style.selected = options.style.cell.selected;
|
||||
options.style.item = options.style.cell;
|
||||
|
||||
var border = options.border;
|
||||
if (border
|
||||
&& border.top === false
|
||||
&& border.bottom === false
|
||||
&& border.left === false
|
||||
&& border.right === false) {
|
||||
delete options.border;
|
||||
}
|
||||
|
||||
List.call(this, options);
|
||||
|
||||
options.border = border;
|
||||
|
||||
this._header = new Box({
|
||||
parent: this,
|
||||
left: this.screen.autoPadding ? 0 : this.ileft,
|
||||
top: 0,
|
||||
width: 'shrink',
|
||||
height: 1,
|
||||
style: options.style.header,
|
||||
tags: options.parseTags || options.tags
|
||||
});
|
||||
|
||||
this.on('scroll', function() {
|
||||
self._header.setFront();
|
||||
self._header.rtop = self.childBase;
|
||||
if (!self.screen.autoPadding) {
|
||||
self._header.rtop = self.childBase + (self.border ? 1 : 0);
|
||||
}
|
||||
});
|
||||
|
||||
this.pad = options.pad != null
|
||||
? options.pad
|
||||
: 2;
|
||||
|
||||
this.setData(options.rows || options.data);
|
||||
|
||||
this.on('attach', function() {
|
||||
self.setData(self.rows);
|
||||
});
|
||||
|
||||
this.on('resize', function() {
|
||||
var selected = self.selected;
|
||||
self.setData(self.rows);
|
||||
self.select(selected);
|
||||
self.screen.render();
|
||||
});
|
||||
}
|
||||
|
||||
ListTable.prototype.__proto__ = List.prototype;
|
||||
|
||||
ListTable.prototype.type = 'list-table';
|
||||
|
||||
ListTable.prototype._calculateMaxes = Table.prototype._calculateMaxes;
|
||||
|
||||
ListTable.prototype.setRows =
|
||||
ListTable.prototype.setData = function(rows) {
|
||||
var self = this
|
||||
, align = this.__align
|
||||
, selected = this.selected
|
||||
, original = this.items.slice()
|
||||
, sel = this.ritems[this.selected];
|
||||
|
||||
if (this.visible && this.lpos) {
|
||||
this.clearPos();
|
||||
}
|
||||
|
||||
this.clearItems();
|
||||
|
||||
this.rows = rows || [];
|
||||
|
||||
this._calculateMaxes();
|
||||
|
||||
if (!this._maxes) return;
|
||||
|
||||
this.addItem('');
|
||||
|
||||
this.rows.forEach(function(row, i) {
|
||||
var isHeader = i === 0;
|
||||
var text = '';
|
||||
row.forEach(function(cell, i) {
|
||||
var width = self._maxes[i];
|
||||
var clen = self.strWidth(cell);
|
||||
|
||||
if (i !== 0) {
|
||||
text += ' ';
|
||||
}
|
||||
|
||||
while (clen < width) {
|
||||
if (align === 'center') {
|
||||
cell = ' ' + cell + ' ';
|
||||
clen += 2;
|
||||
} else if (align === 'left') {
|
||||
cell = cell + ' ';
|
||||
clen += 1;
|
||||
} else if (align === 'right') {
|
||||
cell = ' ' + cell;
|
||||
clen += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (clen > width) {
|
||||
if (align === 'center') {
|
||||
cell = cell.substring(1);
|
||||
clen--;
|
||||
} else if (align === 'left') {
|
||||
cell = cell.slice(0, -1);
|
||||
clen--;
|
||||
} else if (align === 'right') {
|
||||
cell = cell.substring(1);
|
||||
clen--;
|
||||
}
|
||||
}
|
||||
|
||||
text += cell;
|
||||
});
|
||||
if (isHeader) {
|
||||
self._header.setContent(text);
|
||||
} else {
|
||||
self.addItem(text);
|
||||
}
|
||||
});
|
||||
|
||||
this._header.setFront();
|
||||
|
||||
// Try to find our old item if it still exists.
|
||||
sel = this.ritems.indexOf(sel);
|
||||
if (~sel) {
|
||||
this.select(sel);
|
||||
} else if (this.items.length === original.length) {
|
||||
this.select(selected);
|
||||
} else {
|
||||
this.select(Math.min(selected, this.items.length - 1));
|
||||
}
|
||||
};
|
||||
|
||||
ListTable.prototype._select = ListTable.prototype.select;
|
||||
ListTable.prototype.select = function(i) {
|
||||
if (i === 0) {
|
||||
i = 1;
|
||||
}
|
||||
if (i <= this.childBase) {
|
||||
this.setScroll(this.childBase - 1);
|
||||
}
|
||||
return this._select(i);
|
||||
};
|
||||
|
||||
ListTable.prototype.render = function() {
|
||||
var self = this;
|
||||
|
||||
var coords = this._render();
|
||||
if (!coords) return;
|
||||
|
||||
this._calculateMaxes();
|
||||
|
||||
if (!this._maxes) return coords;
|
||||
|
||||
var lines = this.screen.lines
|
||||
, xi = coords.xi
|
||||
, yi = coords.yi
|
||||
, rx
|
||||
, ry
|
||||
, i;
|
||||
|
||||
var battr = this.sattr(this.style.border);
|
||||
|
||||
var height = coords.yl - coords.yi - this.ibottom;
|
||||
|
||||
var border = this.border;
|
||||
if (!this.border && this.options.border) {
|
||||
border = this.options.border;
|
||||
}
|
||||
|
||||
if (!border || this.options.noCellBorders) return coords;
|
||||
|
||||
// Draw border with correct angles.
|
||||
ry = 0;
|
||||
for (i = 0; i < height + 1; i++) {
|
||||
if (!lines[yi + ry]) break;
|
||||
rx = 0;
|
||||
self._maxes.slice(0, -1).forEach(function(max) {
|
||||
rx += max;
|
||||
if (!lines[yi + ry][xi + rx + 1]) return;
|
||||
// center
|
||||
if (ry === 0) {
|
||||
// top
|
||||
rx++;
|
||||
lines[yi + ry][xi + rx][0] = battr;
|
||||
lines[yi + ry][xi + rx][1] = '\u252c'; // '┬'
|
||||
// XXX If we alter iheight and itop for no borders - nothing should be written here
|
||||
if (!border.top) {
|
||||
lines[yi + ry][xi + rx][1] = '\u2502'; // '│'
|
||||
}
|
||||
lines[yi + ry].dirty = true;
|
||||
} else if (ry === height) {
|
||||
// bottom
|
||||
rx++;
|
||||
lines[yi + ry][xi + rx][0] = battr;
|
||||
lines[yi + ry][xi + rx][1] = '\u2534'; // '┴'
|
||||
// XXX If we alter iheight and ibottom for no borders - nothing should be written here
|
||||
if (!border.bottom) {
|
||||
lines[yi + ry][xi + rx][1] = '\u2502'; // '│'
|
||||
}
|
||||
lines[yi + ry].dirty = true;
|
||||
} else {
|
||||
// middle
|
||||
rx++;
|
||||
}
|
||||
});
|
||||
ry += 1;
|
||||
}
|
||||
|
||||
// Draw internal borders.
|
||||
for (ry = 1; ry < height; ry++) {
|
||||
if (!lines[yi + ry]) break;
|
||||
rx = 0;
|
||||
self._maxes.slice(0, -1).forEach(function(max) {
|
||||
rx += max;
|
||||
if (!lines[yi + ry][xi + rx + 1]) return;
|
||||
if (self.options.fillCellBorders !== false) {
|
||||
var lbg = lines[yi + ry][xi + rx][0] & 0x1ff;
|
||||
rx++;
|
||||
lines[yi + ry][xi + rx][0] = (battr & ~0x1ff) | lbg;
|
||||
} else {
|
||||
rx++;
|
||||
lines[yi + ry][xi + rx][0] = battr;
|
||||
}
|
||||
lines[yi + ry][xi + rx][1] = '\u2502'; // '│'
|
||||
lines[yi + ry].dirty = true;
|
||||
});
|
||||
}
|
||||
|
||||
return coords;
|
||||
};
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = ListTable;
|
||||
88
lib/widgets/loading.js
Normal file
@ -0,0 +1,88 @@
|
||||
/**
|
||||
* loading.js - loading element for blessed
|
||||
* Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Modules
|
||||
*/
|
||||
|
||||
var Node = require('./node');
|
||||
var Box = require('./box');
|
||||
var Text = require('./text');
|
||||
|
||||
/**
|
||||
* Loading
|
||||
*/
|
||||
|
||||
function Loading(options) {
|
||||
if (!(this instanceof Node)) {
|
||||
return new Loading(options);
|
||||
}
|
||||
|
||||
options = options || {};
|
||||
|
||||
Box.call(this, options);
|
||||
|
||||
this._.icon = new Text({
|
||||
parent: this,
|
||||
align: 'center',
|
||||
top: 2,
|
||||
left: 1,
|
||||
right: 1,
|
||||
height: 1,
|
||||
content: '|'
|
||||
});
|
||||
}
|
||||
|
||||
Loading.prototype.__proto__ = Box.prototype;
|
||||
|
||||
Loading.prototype.type = 'loading';
|
||||
|
||||
Loading.prototype.load = function(text) {
|
||||
var self = this;
|
||||
|
||||
// XXX Keep above:
|
||||
// var parent = this.parent;
|
||||
// this.detach();
|
||||
// parent.append(this);
|
||||
|
||||
this.show();
|
||||
this.setContent(text);
|
||||
|
||||
if (this._.timer) {
|
||||
this.stop();
|
||||
}
|
||||
|
||||
this.screen.lockKeys = true;
|
||||
|
||||
this._.timer = setInterval(function() {
|
||||
if (self._.icon.content === '|') {
|
||||
self._.icon.setContent('/');
|
||||
} else if (self._.icon.content === '/') {
|
||||
self._.icon.setContent('-');
|
||||
} else if (self._.icon.content === '-') {
|
||||
self._.icon.setContent('\\');
|
||||
} else if (self._.icon.content === '\\') {
|
||||
self._.icon.setContent('|');
|
||||
}
|
||||
self.screen.render();
|
||||
}, 200);
|
||||
};
|
||||
|
||||
Loading.prototype.stop = function() {
|
||||
this.screen.lockKeys = false;
|
||||
this.hide();
|
||||
if (this._.timer) {
|
||||
clearInterval(this._.timer);
|
||||
delete this._.timer;
|
||||
}
|
||||
this.screen.render();
|
||||
};
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = Loading;
|
||||
83
lib/widgets/log.js
Normal file
@ -0,0 +1,83 @@
|
||||
/**
|
||||
* log.js - log element for blessed
|
||||
* Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Modules
|
||||
*/
|
||||
|
||||
var util = require('util');
|
||||
|
||||
var nextTick = global.setImmediate || process.nextTick.bind(process);
|
||||
|
||||
var Node = require('./node');
|
||||
var ScrollableText = require('./scrollabletext');
|
||||
|
||||
/**
|
||||
* Log
|
||||
*/
|
||||
|
||||
function Log(options) {
|
||||
var self = this;
|
||||
|
||||
if (!(this instanceof Node)) {
|
||||
return new Log(options);
|
||||
}
|
||||
|
||||
options = options || {};
|
||||
|
||||
ScrollableText.call(this, options);
|
||||
|
||||
this.scrollback = options.scrollback != null
|
||||
? options.scrollback
|
||||
: Infinity;
|
||||
this.scrollOnInput = options.scrollOnInput;
|
||||
|
||||
this.on('set content', function() {
|
||||
if (!self._userScrolled || self.scrollOnInput) {
|
||||
nextTick(function() {
|
||||
self.setScrollPerc(100);
|
||||
self._userScrolled = false;
|
||||
self.screen.render();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Log.prototype.__proto__ = ScrollableText.prototype;
|
||||
|
||||
Log.prototype.type = 'log';
|
||||
|
||||
Log.prototype.log =
|
||||
Log.prototype.add = function() {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
if (typeof args[0] === 'object') {
|
||||
args[0] = util.inspect(args[0], true, 20, true);
|
||||
}
|
||||
var text = util.format.apply(util, args);
|
||||
this.emit('log', text);
|
||||
var ret = this.pushLine(text);
|
||||
if (this._clines.fake.length > this.scrollback) {
|
||||
this.shiftLine(0, (this.scrollback / 3) | 0);
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
Log.prototype._scroll = Log.prototype.scroll;
|
||||
Log.prototype.scroll = function(offset, always) {
|
||||
if (offset === 0) return this._scroll(offset, always);
|
||||
this._userScrolled = true;
|
||||
var ret = this._scroll(offset, always);
|
||||
if (this.getScrollPerc() === 100) {
|
||||
this._userScrolled = false;
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = Log;
|
||||
123
lib/widgets/message.js
Normal file
@ -0,0 +1,123 @@
|
||||
/**
|
||||
* message.js - message element for blessed
|
||||
* Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Modules
|
||||
*/
|
||||
|
||||
var Node = require('./node');
|
||||
var Box = require('./box');
|
||||
|
||||
/**
|
||||
* Message / Error
|
||||
*/
|
||||
|
||||
function Message(options) {
|
||||
if (!(this instanceof Node)) {
|
||||
return new Message(options);
|
||||
}
|
||||
|
||||
options = options || {};
|
||||
options.tags = true;
|
||||
|
||||
Box.call(this, options);
|
||||
}
|
||||
|
||||
Message.prototype.__proto__ = Box.prototype;
|
||||
|
||||
Message.prototype.type = 'message';
|
||||
|
||||
Message.prototype.log =
|
||||
Message.prototype.display = function(text, time, callback) {
|
||||
var self = this;
|
||||
|
||||
if (typeof time === 'function') {
|
||||
callback = time;
|
||||
time = null;
|
||||
}
|
||||
|
||||
if (time == null) time = 3;
|
||||
|
||||
// Keep above:
|
||||
// var parent = this.parent;
|
||||
// this.detach();
|
||||
// parent.append(this);
|
||||
|
||||
if (this.scrollable) {
|
||||
this.screen.saveFocus();
|
||||
this.focus();
|
||||
this.scrollTo(0);
|
||||
}
|
||||
|
||||
this.show();
|
||||
this.setContent(text);
|
||||
this.screen.render();
|
||||
|
||||
if (time === Infinity || time === -1 || time === 0) {
|
||||
var end = function() {
|
||||
if (end.done) return;
|
||||
end.done = true;
|
||||
if (self.scrollable) {
|
||||
try {
|
||||
self.screen.restoreFocus();
|
||||
} catch (e) {
|
||||
;
|
||||
}
|
||||
}
|
||||
self.hide();
|
||||
self.screen.render();
|
||||
if (callback) callback();
|
||||
};
|
||||
|
||||
setTimeout(function() {
|
||||
self.onScreenEvent('keypress', function fn(ch, key) {
|
||||
if (key.name === 'mouse') return;
|
||||
if (self.scrollable) {
|
||||
if ((key.name === 'up' || (self.options.vi && key.name === 'k'))
|
||||
|| (key.name === 'down' || (self.options.vi && key.name === 'j'))
|
||||
|| (self.options.vi && key.name === 'u' && key.ctrl)
|
||||
|| (self.options.vi && key.name === 'd' && key.ctrl)
|
||||
|| (self.options.vi && key.name === 'b' && key.ctrl)
|
||||
|| (self.options.vi && key.name === 'f' && key.ctrl)
|
||||
|| (self.options.vi && key.name === 'g' && !key.shift)
|
||||
|| (self.options.vi && key.name === 'g' && key.shift)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (self.options.ignoreKeys && ~self.options.ignoreKeys.indexOf(key.name)) {
|
||||
return;
|
||||
}
|
||||
self.removeScreenEvent('keypress', fn);
|
||||
end();
|
||||
});
|
||||
// XXX May be affected by new element.options.mouse option.
|
||||
if (!self.options.mouse) return;
|
||||
self.onScreenEvent('mouse', function fn(data) {
|
||||
if (data.action === 'mousemove') return;
|
||||
self.removeScreenEvent('mouse', fn);
|
||||
end();
|
||||
});
|
||||
}, 10);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
setTimeout(function() {
|
||||
self.hide();
|
||||
self.screen.render();
|
||||
if (callback) callback();
|
||||
}, time * 1000);
|
||||
};
|
||||
|
||||
Message.prototype.error = function(text, time, callback) {
|
||||
return this.display('{red-fg}Error: ' + text + '{/red-fg}', time, callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = Message;
|
||||
282
lib/widgets/node.js
Normal file
@ -0,0 +1,282 @@
|
||||
/**
|
||||
* node.js - base abstract node for blessed
|
||||
* Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Modules
|
||||
*/
|
||||
|
||||
var EventEmitter = require('../events').EventEmitter;
|
||||
|
||||
/**
|
||||
* Node
|
||||
*/
|
||||
|
||||
function Node(options) {
|
||||
var self = this;
|
||||
var Screen = require('./screen');
|
||||
|
||||
if (!(this instanceof Node)) {
|
||||
return new Node(options);
|
||||
}
|
||||
|
||||
EventEmitter.call(this);
|
||||
|
||||
options = options || {};
|
||||
this.options = options;
|
||||
|
||||
this.screen = this.screen || options.screen;
|
||||
|
||||
if (!this.screen) {
|
||||
if (this.type === 'screen') {
|
||||
this.screen = this;
|
||||
} else if (Screen.total === 1) {
|
||||
this.screen = Screen.global;
|
||||
} else if (options.parent) {
|
||||
this.screen = options.parent;
|
||||
while (this.screen && this.screen.type !== 'screen') {
|
||||
this.screen = this.screen.parent;
|
||||
}
|
||||
} else if (Screen.total) {
|
||||
// This _should_ work in most cases as long as the element is appended
|
||||
// synchronously after the screen's creation. Throw error if not.
|
||||
this.screen = Screen.instances[Screen.instances.length - 1];
|
||||
process.nextTick(function() {
|
||||
if (!self.parent) {
|
||||
throw new Error('Element (' + self.type + ')'
|
||||
+ ' was not appended synchronously after the'
|
||||
+ ' screen\'s creation. Please set a `parent`'
|
||||
+ ' or `screen` option in the element\'s constructor'
|
||||
+ ' if you are going to use multiple screens and'
|
||||
+ ' append the element later.');
|
||||
}
|
||||
});
|
||||
} else {
|
||||
throw new Error('No active screen.');
|
||||
}
|
||||
}
|
||||
|
||||
this.parent = options.parent || null;
|
||||
this.children = [];
|
||||
this.$ = this._ = this.data = {};
|
||||
this.uid = Node.uid++;
|
||||
this.index = this.index != null ? this.index : -1;
|
||||
|
||||
if (this.type !== 'screen') {
|
||||
this.detached = true;
|
||||
}
|
||||
|
||||
if (this.parent) {
|
||||
this.parent.append(this);
|
||||
}
|
||||
|
||||
(options.children || []).forEach(this.append.bind(this));
|
||||
}
|
||||
|
||||
Node.uid = 0;
|
||||
|
||||
Node.prototype.__proto__ = EventEmitter.prototype;
|
||||
|
||||
Node.prototype.type = 'node';
|
||||
|
||||
Node.prototype.insert = function(element, i) {
|
||||
var self = this;
|
||||
|
||||
if (element.screen && element.screen !== this.screen) {
|
||||
throw new Error('Cannot switch a node\'s screen.');
|
||||
}
|
||||
|
||||
element.detach();
|
||||
element.parent = this;
|
||||
element.screen = this.screen;
|
||||
|
||||
if (i === 0) {
|
||||
this.children.unshift(element);
|
||||
} else if (i === this.children.length) {
|
||||
this.children.push(element);
|
||||
} else {
|
||||
this.children.splice(i, 0, element);
|
||||
}
|
||||
|
||||
element.emit('reparent', this);
|
||||
this.emit('adopt', element);
|
||||
|
||||
(function emit(el) {
|
||||
var n = el.detached !== self.detached;
|
||||
el.detached = self.detached;
|
||||
if (n) el.emit('attach');
|
||||
el.children.forEach(emit);
|
||||
})(element);
|
||||
|
||||
if (!this.screen.focused) {
|
||||
this.screen.focused = element;
|
||||
}
|
||||
};
|
||||
|
||||
Node.prototype.prepend = function(element) {
|
||||
this.insert(element, 0);
|
||||
};
|
||||
|
||||
Node.prototype.append = function(element) {
|
||||
this.insert(element, this.children.length);
|
||||
};
|
||||
|
||||
Node.prototype.insertBefore = function(element, other) {
|
||||
var i = this.children.indexOf(other);
|
||||
if (~i) this.insert(element, i);
|
||||
};
|
||||
|
||||
Node.prototype.insertAfter = function(element, other) {
|
||||
var i = this.children.indexOf(other);
|
||||
if (~i) this.insert(element, i + 1);
|
||||
};
|
||||
|
||||
Node.prototype.remove = function(element) {
|
||||
if (element.parent !== this) return;
|
||||
|
||||
var i = this.children.indexOf(element);
|
||||
if (!~i) return;
|
||||
|
||||
element.clearPos();
|
||||
|
||||
element.parent = null;
|
||||
|
||||
this.children.splice(i, 1);
|
||||
|
||||
i = this.screen.clickable.indexOf(element);
|
||||
if (~i) this.screen.clickable.splice(i, 1);
|
||||
i = this.screen.keyable.indexOf(element);
|
||||
if (~i) this.screen.keyable.splice(i, 1);
|
||||
|
||||
element.emit('reparent', null);
|
||||
this.emit('remove', element);
|
||||
|
||||
(function emit(el) {
|
||||
var n = el.detached !== true;
|
||||
el.detached = true;
|
||||
if (n) el.emit('detach');
|
||||
el.children.forEach(emit);
|
||||
})(element);
|
||||
|
||||
if (this.screen.focused === element) {
|
||||
this.screen.rewindFocus();
|
||||
}
|
||||
};
|
||||
|
||||
Node.prototype.detach = function() {
|
||||
if (this.parent) this.parent.remove(this);
|
||||
};
|
||||
|
||||
Node.prototype.free = function() {
|
||||
return;
|
||||
};
|
||||
|
||||
Node.prototype.destroy = function() {
|
||||
this.detach();
|
||||
this.forDescendants(function(el) {
|
||||
el.free();
|
||||
el.destroyed = true;
|
||||
el.emit('destroy');
|
||||
}, this);
|
||||
};
|
||||
|
||||
Node.prototype.forDescendants = function(iter, s) {
|
||||
if (s) iter(this);
|
||||
this.children.forEach(function emit(el) {
|
||||
iter(el);
|
||||
el.children.forEach(emit);
|
||||
});
|
||||
};
|
||||
|
||||
Node.prototype.forAncestors = function(iter, s) {
|
||||
var el = this;
|
||||
if (s) iter(this);
|
||||
while (el = el.parent) {
|
||||
iter(el);
|
||||
}
|
||||
};
|
||||
|
||||
Node.prototype.collectDescendants = function(s) {
|
||||
var out = [];
|
||||
this.forDescendants(function(el) {
|
||||
out.push(el);
|
||||
}, s);
|
||||
return out;
|
||||
};
|
||||
|
||||
Node.prototype.collectAncestors = function(s) {
|
||||
var out = [];
|
||||
this.forAncestors(function(el) {
|
||||
out.push(el);
|
||||
}, s);
|
||||
return out;
|
||||
};
|
||||
|
||||
Node.prototype.emitDescendants = function() {
|
||||
var args = Array.prototype.slice(arguments)
|
||||
, iter;
|
||||
|
||||
if (typeof args[args.length - 1] === 'function') {
|
||||
iter = args.pop();
|
||||
}
|
||||
|
||||
return this.forDescendants(function(el) {
|
||||
if (iter) iter(el);
|
||||
el.emit.apply(el, args);
|
||||
}, true);
|
||||
};
|
||||
|
||||
Node.prototype.emitAncestors = function() {
|
||||
var args = Array.prototype.slice(arguments)
|
||||
, iter;
|
||||
|
||||
if (typeof args[args.length - 1] === 'function') {
|
||||
iter = args.pop();
|
||||
}
|
||||
|
||||
return this.forAncestors(function(el) {
|
||||
if (iter) iter(el);
|
||||
el.emit.apply(el, args);
|
||||
}, true);
|
||||
};
|
||||
|
||||
Node.prototype.hasDescendant = function(target) {
|
||||
return (function find(el) {
|
||||
for (var i = 0; i < el.children.length; i++) {
|
||||
if (el.children[i] === target) {
|
||||
return true;
|
||||
}
|
||||
if (find(el.children[i]) === true) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
})(this);
|
||||
};
|
||||
|
||||
Node.prototype.hasAncestor = function(target) {
|
||||
var el = this;
|
||||
while (el = el.parent) {
|
||||
if (el === target) return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
Node.prototype.get = function(name, value) {
|
||||
if (this.data.hasOwnProperty(name)) {
|
||||
return this.data[name];
|
||||
}
|
||||
return value;
|
||||
};
|
||||
|
||||
Node.prototype.set = function(name, value) {
|
||||
return this.data[name] = value;
|
||||
};
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = Node;
|
||||
717
lib/widgets/overlayimage.js
Normal file
@ -0,0 +1,717 @@
|
||||
/**
|
||||
* overlayimage.js - w3m image element for blessed
|
||||
* Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Modules
|
||||
*/
|
||||
|
||||
var fs = require('fs')
|
||||
, cp = require('child_process');
|
||||
|
||||
var helpers = require('../helpers');
|
||||
|
||||
var Node = require('./node');
|
||||
var Box = require('./box');
|
||||
|
||||
/**
|
||||
* OverlayImage
|
||||
* Good example of w3mimgdisplay commands:
|
||||
* https://github.com/hut/ranger/blob/master/ranger/ext/img_display.py
|
||||
*/
|
||||
|
||||
function OverlayImage(options) {
|
||||
var self = this;
|
||||
|
||||
if (!(this instanceof Node)) {
|
||||
return new OverlayImage(options);
|
||||
}
|
||||
|
||||
options = options || {};
|
||||
|
||||
Box.call(this, options);
|
||||
|
||||
if (options.w3m) {
|
||||
OverlayImage.w3mdisplay = options.w3m;
|
||||
}
|
||||
|
||||
if (OverlayImage.hasW3MDisplay == null) {
|
||||
if (fs.existsSync(OverlayImage.w3mdisplay)) {
|
||||
OverlayImage.hasW3MDisplay = true;
|
||||
} else if (options.search !== false) {
|
||||
var file = helpers.findFile('/usr', 'w3mimgdisplay')
|
||||
|| helpers.findFile('/lib', 'w3mimgdisplay')
|
||||
|| helpers.findFile('/bin', 'w3mimgdisplay');
|
||||
if (file) {
|
||||
OverlayImage.hasW3MDisplay = true;
|
||||
OverlayImage.w3mdisplay = file;
|
||||
} else {
|
||||
OverlayImage.hasW3MDisplay = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.on('hide', function() {
|
||||
self._lastFile = self.file;
|
||||
self.clearImage();
|
||||
});
|
||||
|
||||
this.on('show', function() {
|
||||
if (!self._lastFile) return;
|
||||
self.setImage(self._lastFile);
|
||||
});
|
||||
|
||||
this.on('detach', function() {
|
||||
self._lastFile = self.file;
|
||||
self.clearImage();
|
||||
});
|
||||
|
||||
this.on('attach', function() {
|
||||
if (!self._lastFile) return;
|
||||
self.setImage(self._lastFile);
|
||||
});
|
||||
|
||||
this.onScreenEvent('resize', function() {
|
||||
self._needsRatio = true;
|
||||
});
|
||||
|
||||
// Get images to overlap properly. Maybe not worth it:
|
||||
// this.onScreenEvent('render', function() {
|
||||
// self.screen.program.flush();
|
||||
// if (!self._noImage) return;
|
||||
// function display(el, next) {
|
||||
// if (el.type === 'w3mimage' && el.file) {
|
||||
// el.setImage(el.file, next);
|
||||
// } else {
|
||||
// next();
|
||||
// }
|
||||
// }
|
||||
// function done(el) {
|
||||
// el.children.forEach(recurse);
|
||||
// }
|
||||
// function recurse(el) {
|
||||
// display(el, function() {
|
||||
// var pending = el.children.length;
|
||||
// el.children.forEach(function(el) {
|
||||
// display(el, function() {
|
||||
// if (!--pending) done(el);
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
// }
|
||||
// recurse(self.screen);
|
||||
// });
|
||||
|
||||
this.onScreenEvent('render', function() {
|
||||
self.screen.program.flush();
|
||||
if (!self._noImage) {
|
||||
self.setImage(self.file);
|
||||
}
|
||||
});
|
||||
|
||||
if (this.options.file || this.options.img) {
|
||||
this.setImage(this.options.file || this.options.img);
|
||||
}
|
||||
}
|
||||
|
||||
OverlayImage.prototype.__proto__ = Box.prototype;
|
||||
|
||||
OverlayImage.prototype.type = 'overlayimage';
|
||||
|
||||
OverlayImage.w3mdisplay = '/usr/lib/w3m/w3mimgdisplay';
|
||||
|
||||
OverlayImage.prototype.spawn = function(file, args, opt, callback) {
|
||||
var spawn = require('child_process').spawn
|
||||
, ps;
|
||||
|
||||
opt = opt || {};
|
||||
ps = spawn(file, args, opt);
|
||||
|
||||
ps.on('error', function(err) {
|
||||
if (!callback) return;
|
||||
return callback(err);
|
||||
});
|
||||
|
||||
ps.on('exit', function(code) {
|
||||
if (!callback) return;
|
||||
if (code !== 0) return callback(new Error('Exit Code: ' + code));
|
||||
return callback(null, code === 0);
|
||||
});
|
||||
|
||||
return ps;
|
||||
};
|
||||
|
||||
OverlayImage.prototype.setImage = function(img, callback) {
|
||||
var self = this;
|
||||
|
||||
if (this._settingImage) {
|
||||
this._queue = this._queue || [];
|
||||
this._queue.push([img, callback]);
|
||||
return;
|
||||
}
|
||||
this._settingImage = true;
|
||||
|
||||
var reset = function() {
|
||||
self._settingImage = false;
|
||||
self._queue = self._queue || [];
|
||||
var item = self._queue.shift();
|
||||
if (item) {
|
||||
self.setImage(item[0], item[1]);
|
||||
}
|
||||
};
|
||||
|
||||
if (OverlayImage.hasW3MDisplay === false) {
|
||||
reset();
|
||||
if (!callback) return;
|
||||
return callback(new Error('W3M Image Display not available.'));
|
||||
}
|
||||
|
||||
if (!img) {
|
||||
reset();
|
||||
if (!callback) return;
|
||||
return callback(new Error('No image.'));
|
||||
}
|
||||
|
||||
this.file = img;
|
||||
|
||||
return this.getPixelRatio(function(err, ratio) {
|
||||
if (err) {
|
||||
reset();
|
||||
if (!callback) return;
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
return self.renderImage(img, ratio, function(err, success) {
|
||||
if (err) {
|
||||
reset();
|
||||
if (!callback) return;
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
if (self.shrink || self.options.autofit) {
|
||||
delete self.shrink;
|
||||
delete self.options.shrink;
|
||||
self.options.autofit = true;
|
||||
return self.imageSize(function(err, size) {
|
||||
if (err) {
|
||||
reset();
|
||||
if (!callback) return;
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
if (self._lastSize
|
||||
&& ratio.tw === self._lastSize.tw
|
||||
&& ratio.th === self._lastSize.th
|
||||
&& size.width === self._lastSize.width
|
||||
&& size.height === self._lastSize.height
|
||||
&& self.aleft === self._lastSize.aleft
|
||||
&& self.atop === self._lastSize.atop) {
|
||||
reset();
|
||||
if (!callback) return;
|
||||
return callback(null, success);
|
||||
}
|
||||
|
||||
self._lastSize = {
|
||||
tw: ratio.tw,
|
||||
th: ratio.th,
|
||||
width: size.width,
|
||||
height: size.height,
|
||||
aleft: self.aleft,
|
||||
atop: self.atop
|
||||
};
|
||||
|
||||
self.position.width = size.width / ratio.tw | 0;
|
||||
self.position.height = size.height / ratio.th | 0;
|
||||
|
||||
self._noImage = true;
|
||||
self.screen.render();
|
||||
self._noImage = false;
|
||||
|
||||
reset();
|
||||
return self.renderImage(img, ratio, callback);
|
||||
});
|
||||
}
|
||||
|
||||
reset();
|
||||
if (!callback) return;
|
||||
return callback(null, success);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
OverlayImage.prototype.renderImage = function(img, ratio, callback) {
|
||||
var self = this;
|
||||
|
||||
if (cp.execSync) {
|
||||
callback = callback || function(err, result) { return result; };
|
||||
try {
|
||||
return callback(null, this.renderImageSync(img, ratio));
|
||||
} catch (e) {
|
||||
return callback(e);
|
||||
}
|
||||
}
|
||||
|
||||
if (OverlayImage.hasW3MDisplay === false) {
|
||||
if (!callback) return;
|
||||
return callback(new Error('W3M Image Display not available.'));
|
||||
}
|
||||
|
||||
if (!ratio) {
|
||||
if (!callback) return;
|
||||
return callback(new Error('No ratio.'));
|
||||
}
|
||||
|
||||
// clearImage unsets these:
|
||||
var _file = self.file;
|
||||
var _lastSize = self._lastSize;
|
||||
return self.clearImage(function(err) {
|
||||
if (err) return callback(err);
|
||||
|
||||
self.file = _file;
|
||||
self._lastSize = _lastSize;
|
||||
|
||||
var opt = {
|
||||
stdio: 'pipe',
|
||||
env: process.env,
|
||||
cwd: process.env.HOME
|
||||
};
|
||||
|
||||
var ps = self.spawn(OverlayImage.w3mdisplay, [], opt, function(err, success) {
|
||||
if (!callback) return;
|
||||
return err
|
||||
? callback(err)
|
||||
: callback(null, success);
|
||||
});
|
||||
|
||||
var width = self.width * ratio.tw | 0
|
||||
, height = self.height * ratio.th | 0
|
||||
, aleft = self.aleft * ratio.tw | 0
|
||||
, atop = self.atop * ratio.th | 0;
|
||||
|
||||
var input = '0;1;'
|
||||
+ aleft + ';'
|
||||
+ atop + ';'
|
||||
+ width + ';'
|
||||
+ height + ';;;;;'
|
||||
+ img
|
||||
+ '\n4;\n3;\n';
|
||||
|
||||
self._props = {
|
||||
aleft: aleft,
|
||||
atop: atop,
|
||||
width: width,
|
||||
height: height
|
||||
};
|
||||
|
||||
ps.stdin.write(input);
|
||||
ps.stdin.end();
|
||||
});
|
||||
};
|
||||
|
||||
OverlayImage.prototype.clearImage = function(callback) {
|
||||
if (cp.execSync) {
|
||||
callback = callback || function(err, result) { return result; };
|
||||
try {
|
||||
return callback(null, this.clearImageSync());
|
||||
} catch (e) {
|
||||
return callback(e);
|
||||
}
|
||||
}
|
||||
|
||||
if (OverlayImage.hasW3MDisplay === false) {
|
||||
if (!callback) return;
|
||||
return callback(new Error('W3M Image Display not available.'));
|
||||
}
|
||||
|
||||
if (!this._props) {
|
||||
if (!callback) return;
|
||||
return callback(null);
|
||||
}
|
||||
|
||||
var opt = {
|
||||
stdio: 'pipe',
|
||||
env: process.env,
|
||||
cwd: process.env.HOME
|
||||
};
|
||||
|
||||
var ps = this.spawn(OverlayImage.w3mdisplay, [], opt, function(err, success) {
|
||||
if (!callback) return;
|
||||
return err
|
||||
? callback(err)
|
||||
: callback(null, success);
|
||||
});
|
||||
|
||||
var width = this._props.width + 2
|
||||
, height = this._props.height + 2
|
||||
, aleft = this._props.aleft
|
||||
, atop = this._props.atop;
|
||||
|
||||
if (this._drag) {
|
||||
aleft -= 10;
|
||||
atop -= 10;
|
||||
width += 10;
|
||||
height += 10;
|
||||
}
|
||||
|
||||
var input = '6;'
|
||||
+ aleft + ';'
|
||||
+ atop + ';'
|
||||
+ width + ';'
|
||||
+ height
|
||||
+ '\n4;\n3;\n';
|
||||
|
||||
delete this.file;
|
||||
delete this._props;
|
||||
delete this._lastSize;
|
||||
|
||||
ps.stdin.write(input);
|
||||
ps.stdin.end();
|
||||
};
|
||||
|
||||
OverlayImage.prototype.imageSize = function(callback) {
|
||||
var img = this.file;
|
||||
|
||||
if (cp.execSync) {
|
||||
callback = callback || function(err, result) { return result; };
|
||||
try {
|
||||
return callback(null, this.imageSizeSync());
|
||||
} catch (e) {
|
||||
return callback(e);
|
||||
}
|
||||
}
|
||||
|
||||
if (OverlayImage.hasW3MDisplay === false) {
|
||||
if (!callback) return;
|
||||
return callback(new Error('W3M Image Display not available.'));
|
||||
}
|
||||
|
||||
if (!img) {
|
||||
if (!callback) return;
|
||||
return callback(new Error('No image.'));
|
||||
}
|
||||
|
||||
var opt = {
|
||||
stdio: 'pipe',
|
||||
env: process.env,
|
||||
cwd: process.env.HOME
|
||||
};
|
||||
|
||||
var ps = this.spawn(OverlayImage.w3mdisplay, [], opt);
|
||||
|
||||
var buf = '';
|
||||
|
||||
ps.stdout.setEncoding('utf8');
|
||||
|
||||
ps.stdout.on('data', function(data) {
|
||||
buf += data;
|
||||
});
|
||||
|
||||
ps.on('error', function(err) {
|
||||
if (!callback) return;
|
||||
return callback(err);
|
||||
});
|
||||
|
||||
ps.on('exit', function() {
|
||||
if (!callback) return;
|
||||
var size = buf.trim().split(/\s+/);
|
||||
return callback(null, {
|
||||
raw: buf.trim(),
|
||||
width: +size[0],
|
||||
height: +size[1]
|
||||
});
|
||||
});
|
||||
|
||||
var input = '5;' + img + '\n';
|
||||
|
||||
ps.stdin.write(input);
|
||||
ps.stdin.end();
|
||||
};
|
||||
|
||||
OverlayImage.prototype.termSize = function(callback) {
|
||||
var self = this;
|
||||
|
||||
if (cp.execSync) {
|
||||
callback = callback || function(err, result) { return result; };
|
||||
try {
|
||||
return callback(null, this.termSizeSync());
|
||||
} catch (e) {
|
||||
return callback(e);
|
||||
}
|
||||
}
|
||||
|
||||
if (OverlayImage.hasW3MDisplay === false) {
|
||||
if (!callback) return;
|
||||
return callback(new Error('W3M Image Display not available.'));
|
||||
}
|
||||
|
||||
var opt = {
|
||||
stdio: 'pipe',
|
||||
env: process.env,
|
||||
cwd: process.env.HOME
|
||||
};
|
||||
|
||||
var ps = this.spawn(OverlayImage.w3mdisplay, ['-test'], opt);
|
||||
|
||||
var buf = '';
|
||||
|
||||
ps.stdout.setEncoding('utf8');
|
||||
|
||||
ps.stdout.on('data', function(data) {
|
||||
buf += data;
|
||||
});
|
||||
|
||||
ps.on('error', function(err) {
|
||||
if (!callback) return;
|
||||
return callback(err);
|
||||
});
|
||||
|
||||
ps.on('exit', function() {
|
||||
if (!callback) return;
|
||||
|
||||
if (!buf.trim()) {
|
||||
// Bug: w3mimgdisplay will sometimes
|
||||
// output nothing. Try again:
|
||||
return self.termSize(callback);
|
||||
}
|
||||
|
||||
var size = buf.trim().split(/\s+/);
|
||||
|
||||
return callback(null, {
|
||||
raw: buf.trim(),
|
||||
width: +size[0],
|
||||
height: +size[1]
|
||||
});
|
||||
});
|
||||
|
||||
ps.stdin.end();
|
||||
};
|
||||
|
||||
OverlayImage.prototype.getPixelRatio = function(callback) {
|
||||
var self = this;
|
||||
|
||||
if (cp.execSync) {
|
||||
callback = callback || function(err, result) { return result; };
|
||||
try {
|
||||
return callback(null, this.getPixelRatioSync());
|
||||
} catch (e) {
|
||||
return callback(e);
|
||||
}
|
||||
}
|
||||
|
||||
// XXX We could cache this, but sometimes it's better
|
||||
// to recalculate to be pixel perfect.
|
||||
if (this._ratio && !this._needsRatio) {
|
||||
return callback(null, this._ratio);
|
||||
}
|
||||
|
||||
return this.termSize(function(err, dimensions) {
|
||||
if (err) return callback(err);
|
||||
|
||||
self._ratio = {
|
||||
tw: dimensions.width / self.screen.width,
|
||||
th: dimensions.height / self.screen.height
|
||||
};
|
||||
|
||||
self._needsRatio = false;
|
||||
|
||||
return callback(null, self._ratio);
|
||||
});
|
||||
};
|
||||
|
||||
OverlayImage.prototype.renderImageSync = function(img, ratio) {
|
||||
if (OverlayImage.hasW3MDisplay === false) {
|
||||
throw new Error('W3M Image Display not available.');
|
||||
}
|
||||
|
||||
if (!ratio) {
|
||||
throw new Error('No ratio.');
|
||||
}
|
||||
|
||||
// clearImage unsets these:
|
||||
var _file = this.file;
|
||||
var _lastSize = this._lastSize;
|
||||
|
||||
this.clearImageSync();
|
||||
|
||||
this.file = _file;
|
||||
this._lastSize = _lastSize;
|
||||
|
||||
var width = this.width * ratio.tw | 0
|
||||
, height = this.height * ratio.th | 0
|
||||
, aleft = this.aleft * ratio.tw | 0
|
||||
, atop = this.atop * ratio.th | 0;
|
||||
|
||||
var input = '0;1;'
|
||||
+ aleft + ';'
|
||||
+ atop + ';'
|
||||
+ width + ';'
|
||||
+ height + ';;;;;'
|
||||
+ img
|
||||
+ '\n4;\n3;\n';
|
||||
|
||||
this._props = {
|
||||
aleft: aleft,
|
||||
atop: atop,
|
||||
width: width,
|
||||
height: height
|
||||
};
|
||||
|
||||
try {
|
||||
cp.execFileSync(OverlayImage.w3mdisplay, [], {
|
||||
env: process.env,
|
||||
encoding: 'utf8',
|
||||
input: input,
|
||||
timeout: 1000
|
||||
});
|
||||
} catch (e) {
|
||||
;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
OverlayImage.prototype.clearImageSync = function() {
|
||||
if (OverlayImage.hasW3MDisplay === false) {
|
||||
throw new Error('W3M Image Display not available.');
|
||||
}
|
||||
|
||||
if (!this._props) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var width = this._props.width + 2
|
||||
, height = this._props.height + 2
|
||||
, aleft = this._props.aleft
|
||||
, atop = this._props.atop;
|
||||
|
||||
if (this._drag) {
|
||||
aleft -= 10;
|
||||
atop -= 10;
|
||||
width += 10;
|
||||
height += 10;
|
||||
}
|
||||
|
||||
var input = '6;'
|
||||
+ aleft + ';'
|
||||
+ atop + ';'
|
||||
+ width + ';'
|
||||
+ height
|
||||
+ '\n4;\n3;\n';
|
||||
|
||||
delete this.file;
|
||||
delete this._props;
|
||||
delete this._lastSize;
|
||||
|
||||
try {
|
||||
cp.execFileSync(OverlayImage.w3mdisplay, [], {
|
||||
env: process.env,
|
||||
encoding: 'utf8',
|
||||
input: input,
|
||||
timeout: 1000
|
||||
});
|
||||
} catch (e) {
|
||||
;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
OverlayImage.prototype.imageSizeSync = function() {
|
||||
var img = this.file;
|
||||
|
||||
if (OverlayImage.hasW3MDisplay === false) {
|
||||
throw new Error('W3M Image Display not available.');
|
||||
}
|
||||
|
||||
if (!img) {
|
||||
throw new Error('No image.');
|
||||
}
|
||||
|
||||
var buf = '';
|
||||
var input = '5;' + img + '\n';
|
||||
|
||||
try {
|
||||
buf = cp.execFileSync(OverlayImage.w3mdisplay, [], {
|
||||
env: process.env,
|
||||
encoding: 'utf8',
|
||||
input: input,
|
||||
timeout: 1000
|
||||
});
|
||||
} catch (e) {
|
||||
;
|
||||
}
|
||||
|
||||
var size = buf.trim().split(/\s+/);
|
||||
|
||||
return {
|
||||
raw: buf.trim(),
|
||||
width: +size[0],
|
||||
height: +size[1]
|
||||
};
|
||||
};
|
||||
|
||||
OverlayImage.prototype.termSizeSync = function(_, recurse) {
|
||||
if (OverlayImage.hasW3MDisplay === false) {
|
||||
throw new Error('W3M Image Display not available.');
|
||||
}
|
||||
|
||||
var buf = '';
|
||||
|
||||
try {
|
||||
buf = cp.execFileSync(OverlayImage.w3mdisplay, ['-test'], {
|
||||
env: process.env,
|
||||
encoding: 'utf8',
|
||||
timeout: 1000
|
||||
});
|
||||
} catch (e) {
|
||||
;
|
||||
}
|
||||
|
||||
if (!buf.trim()) {
|
||||
// Bug: w3mimgdisplay will sometimes
|
||||
// output nothing. Try again:
|
||||
recurse = recurse || 0;
|
||||
if (++recurse === 5) {
|
||||
throw new Error('Term size not determined.');
|
||||
}
|
||||
return this.termSizeSync(_, recurse);
|
||||
}
|
||||
|
||||
var size = buf.trim().split(/\s+/);
|
||||
|
||||
return {
|
||||
raw: buf.trim(),
|
||||
width: +size[0],
|
||||
height: +size[1]
|
||||
};
|
||||
};
|
||||
|
||||
OverlayImage.prototype.getPixelRatioSync = function() {
|
||||
// XXX We could cache this, but sometimes it's better
|
||||
// to recalculate to be pixel perfect.
|
||||
if (this._ratio && !this._needsRatio) {
|
||||
return this._ratio;
|
||||
}
|
||||
this._needsRatio = false;
|
||||
|
||||
var dimensions = this.termSizeSync();
|
||||
|
||||
this._ratio = {
|
||||
tw: dimensions.width / this.screen.width,
|
||||
th: dimensions.height / this.screen.height
|
||||
};
|
||||
|
||||
return this._ratio;
|
||||
};
|
||||
|
||||
OverlayImage.prototype.displayImage = function(callback) {
|
||||
return this.screen.displayImage(this.file, callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = OverlayImage;
|
||||
157
lib/widgets/progressbar.js
Normal file
@ -0,0 +1,157 @@
|
||||
/**
|
||||
* progressbar.js - progress bar element for blessed
|
||||
* Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Modules
|
||||
*/
|
||||
|
||||
var Node = require('./node');
|
||||
var Input = require('./input');
|
||||
|
||||
/**
|
||||
* ProgressBar
|
||||
*/
|
||||
|
||||
function ProgressBar(options) {
|
||||
var self = this;
|
||||
|
||||
if (!(this instanceof Node)) {
|
||||
return new ProgressBar(options);
|
||||
}
|
||||
|
||||
options = options || {};
|
||||
|
||||
Input.call(this, options);
|
||||
|
||||
this.filled = options.filled || 0;
|
||||
if (typeof this.filled === 'string') {
|
||||
this.filled = +this.filled.slice(0, -1);
|
||||
}
|
||||
this.value = this.filled;
|
||||
|
||||
this.pch = options.pch || ' ';
|
||||
|
||||
// XXX Workaround that predates the usage of `el.ch`.
|
||||
if (options.ch) {
|
||||
this.pch = options.ch;
|
||||
this.ch = ' ';
|
||||
}
|
||||
if (options.bch) {
|
||||
this.ch = options.bch;
|
||||
}
|
||||
|
||||
if (!this.style.bar) {
|
||||
this.style.bar = {};
|
||||
this.style.bar.fg = options.barFg;
|
||||
this.style.bar.bg = options.barBg;
|
||||
}
|
||||
|
||||
this.orientation = options.orientation || 'horizontal';
|
||||
|
||||
if (options.keys) {
|
||||
this.on('keypress', function(ch, key) {
|
||||
var back, forward;
|
||||
if (self.orientation === 'horizontal') {
|
||||
back = ['left', 'h'];
|
||||
forward = ['right', 'l'];
|
||||
} else if (self.orientation === 'vertical') {
|
||||
back = ['down', 'j'];
|
||||
forward = ['up', 'k'];
|
||||
}
|
||||
if (key.name === back[0] || (options.vi && key.name === back[1])) {
|
||||
self.progress(-5);
|
||||
self.screen.render();
|
||||
return;
|
||||
}
|
||||
if (key.name === forward[0] || (options.vi && key.name === forward[1])) {
|
||||
self.progress(5);
|
||||
self.screen.render();
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (options.mouse) {
|
||||
this.on('click', function(data) {
|
||||
var x, y, m, p;
|
||||
if (!self.lpos) return;
|
||||
if (self.orientation === 'horizontal') {
|
||||
x = data.x - self.lpos.xi;
|
||||
m = (self.lpos.xl - self.lpos.xi) - self.iwidth;
|
||||
p = x / m * 100 | 0;
|
||||
} else if (self.orientation === 'vertical') {
|
||||
y = data.y - self.lpos.yi;
|
||||
m = (self.lpos.yl - self.lpos.yi) - self.iheight;
|
||||
p = y / m * 100 | 0;
|
||||
}
|
||||
self.setProgress(p);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ProgressBar.prototype.__proto__ = Input.prototype;
|
||||
|
||||
ProgressBar.prototype.type = 'progress-bar';
|
||||
|
||||
ProgressBar.prototype.render = function() {
|
||||
var ret = this._render();
|
||||
if (!ret) return;
|
||||
|
||||
var xi = ret.xi
|
||||
, xl = ret.xl
|
||||
, yi = ret.yi
|
||||
, yl = ret.yl
|
||||
, dattr;
|
||||
|
||||
if (this.border) xi++, yi++, xl--, yl--;
|
||||
|
||||
if (this.orientation === 'horizontal') {
|
||||
xl = xi + ((xl - xi) * (this.filled / 100)) | 0;
|
||||
} else if (this.orientation === 'vertical') {
|
||||
yi = yi + ((yl - yi) - (((yl - yi) * (this.filled / 100)) | 0));
|
||||
}
|
||||
|
||||
dattr = this.sattr(this.style.bar);
|
||||
|
||||
this.screen.fillRegion(dattr, this.pch, xi, xl, yi, yl);
|
||||
|
||||
if (this.content) {
|
||||
var line = this.screen.lines[yi];
|
||||
for (var i = 0; i < this.content.length; i++) {
|
||||
line[xi + i][1] = this.content[i];
|
||||
}
|
||||
line.dirty = true;
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
ProgressBar.prototype.progress = function(filled) {
|
||||
this.filled += filled;
|
||||
if (this.filled < 0) this.filled = 0;
|
||||
else if (this.filled > 100) this.filled = 100;
|
||||
if (this.filled === 100) {
|
||||
this.emit('complete');
|
||||
}
|
||||
this.value = this.filled;
|
||||
};
|
||||
|
||||
ProgressBar.prototype.setProgress = function(filled) {
|
||||
this.filled = 0;
|
||||
this.progress(filled);
|
||||
};
|
||||
|
||||
ProgressBar.prototype.reset = function() {
|
||||
this.emit('reset');
|
||||
this.filled = 0;
|
||||
this.value = this.filled;
|
||||
};
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = ProgressBar;
|
||||
120
lib/widgets/prompt.js
Normal file
@ -0,0 +1,120 @@
|
||||
/**
|
||||
* prompt.js - prompt element for blessed
|
||||
* Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Modules
|
||||
*/
|
||||
|
||||
var Node = require('./node');
|
||||
var Box = require('./box');
|
||||
var Button = require('./button');
|
||||
var Textbox = require('./textbox');
|
||||
|
||||
/**
|
||||
* Prompt
|
||||
*/
|
||||
|
||||
function Prompt(options) {
|
||||
if (!(this instanceof Node)) {
|
||||
return new Prompt(options);
|
||||
}
|
||||
|
||||
options = options || {};
|
||||
|
||||
options.hidden = true;
|
||||
|
||||
Box.call(this, options);
|
||||
|
||||
this._.input = new Textbox({
|
||||
parent: this,
|
||||
top: 3,
|
||||
height: 1,
|
||||
left: 2,
|
||||
right: 2,
|
||||
bg: 'black'
|
||||
});
|
||||
|
||||
this._.okay = new Button({
|
||||
parent: this,
|
||||
top: 5,
|
||||
height: 1,
|
||||
left: 2,
|
||||
width: 6,
|
||||
content: 'Okay',
|
||||
align: 'center',
|
||||
bg: 'black',
|
||||
hoverBg: 'blue',
|
||||
autoFocus: false,
|
||||
mouse: true
|
||||
});
|
||||
|
||||
this._.cancel = new Button({
|
||||
parent: this,
|
||||
top: 5,
|
||||
height: 1,
|
||||
shrink: true,
|
||||
left: 10,
|
||||
width: 8,
|
||||
content: 'Cancel',
|
||||
align: 'center',
|
||||
bg: 'black',
|
||||
hoverBg: 'blue',
|
||||
autoFocus: false,
|
||||
mouse: true
|
||||
});
|
||||
}
|
||||
|
||||
Prompt.prototype.__proto__ = Box.prototype;
|
||||
|
||||
Prompt.prototype.type = 'prompt';
|
||||
|
||||
Prompt.prototype.input =
|
||||
Prompt.prototype.setInput =
|
||||
Prompt.prototype.readInput = function(text, value, callback) {
|
||||
var self = this;
|
||||
var okay, cancel;
|
||||
|
||||
if (!callback) {
|
||||
callback = value;
|
||||
value = '';
|
||||
}
|
||||
|
||||
// Keep above:
|
||||
// var parent = this.parent;
|
||||
// this.detach();
|
||||
// parent.append(this);
|
||||
|
||||
this.show();
|
||||
this.setContent(' ' + text);
|
||||
|
||||
this._.input.value = value;
|
||||
|
||||
this.screen.saveFocus();
|
||||
|
||||
this._.okay.on('press', okay = function() {
|
||||
self._.input.submit();
|
||||
});
|
||||
|
||||
this._.cancel.on('press', cancel = function() {
|
||||
self._.input.cancel();
|
||||
});
|
||||
|
||||
this._.input.readInput(function(err, data) {
|
||||
self.hide();
|
||||
self.screen.restoreFocus();
|
||||
self._.okay.removeListener('press', okay);
|
||||
self._.cancel.removeListener('press', cancel);
|
||||
return callback(err, data);
|
||||
});
|
||||
|
||||
this.screen.render();
|
||||
};
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = Prompt;
|
||||
116
lib/widgets/question.js
Normal file
@ -0,0 +1,116 @@
|
||||
/**
|
||||
* question.js - question element for blessed
|
||||
* Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Modules
|
||||
*/
|
||||
|
||||
var Node = require('./node');
|
||||
var Box = require('./box');
|
||||
var Button = require('./button');
|
||||
|
||||
/**
|
||||
* Question
|
||||
*/
|
||||
|
||||
function Question(options) {
|
||||
if (!(this instanceof Node)) {
|
||||
return new Question(options);
|
||||
}
|
||||
|
||||
options = options || {};
|
||||
options.hidden = true;
|
||||
|
||||
Box.call(this, options);
|
||||
|
||||
this._.okay = new Button({
|
||||
screen: this.screen,
|
||||
parent: this,
|
||||
top: 2,
|
||||
height: 1,
|
||||
left: 2,
|
||||
width: 6,
|
||||
content: 'Okay',
|
||||
align: 'center',
|
||||
bg: 'black',
|
||||
hoverBg: 'blue',
|
||||
autoFocus: false,
|
||||
mouse: true
|
||||
});
|
||||
|
||||
this._.cancel = new Button({
|
||||
screen: this.screen,
|
||||
parent: this,
|
||||
top: 2,
|
||||
height: 1,
|
||||
shrink: true,
|
||||
left: 10,
|
||||
width: 8,
|
||||
content: 'Cancel',
|
||||
align: 'center',
|
||||
bg: 'black',
|
||||
hoverBg: 'blue',
|
||||
autoFocus: false,
|
||||
mouse: true
|
||||
});
|
||||
}
|
||||
|
||||
Question.prototype.__proto__ = Box.prototype;
|
||||
|
||||
Question.prototype.type = 'question';
|
||||
|
||||
Question.prototype.ask = function(text, callback) {
|
||||
var self = this;
|
||||
var press, okay, cancel;
|
||||
|
||||
// Keep above:
|
||||
// var parent = this.parent;
|
||||
// this.detach();
|
||||
// parent.append(this);
|
||||
|
||||
this.show();
|
||||
this.setContent(' ' + text);
|
||||
|
||||
this.onScreenEvent('keypress', press = function(ch, key) {
|
||||
if (key.name === 'mouse') return;
|
||||
if (key.name !== 'enter'
|
||||
&& key.name !== 'escape'
|
||||
&& key.name !== 'q'
|
||||
&& key.name !== 'y'
|
||||
&& key.name !== 'n') {
|
||||
return;
|
||||
}
|
||||
done(null, key.name === 'enter' || key.name === 'y');
|
||||
});
|
||||
|
||||
this._.okay.on('press', okay = function() {
|
||||
done(null, true);
|
||||
});
|
||||
|
||||
this._.cancel.on('press', cancel = function() {
|
||||
done(null, false);
|
||||
});
|
||||
|
||||
this.screen.saveFocus();
|
||||
this.focus();
|
||||
|
||||
function done(err, data) {
|
||||
self.hide();
|
||||
self.screen.restoreFocus();
|
||||
self.removeScreenEvent('keypress', press);
|
||||
self._.okay.removeListener('press', okay);
|
||||
self._.cancel.removeListener('press', cancel);
|
||||
return callback(err, data);
|
||||
}
|
||||
|
||||
this.screen.render();
|
||||
};
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = Question;
|
||||
61
lib/widgets/radiobutton.js
Normal file
@ -0,0 +1,61 @@
|
||||
/**
|
||||
* radiobutton.js - radio button element for blessed
|
||||
* Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Modules
|
||||
*/
|
||||
|
||||
var Node = require('./node');
|
||||
var Checkbox = require('./checkbox');
|
||||
|
||||
/**
|
||||
* RadioButton
|
||||
*/
|
||||
|
||||
function RadioButton(options) {
|
||||
var self = this;
|
||||
|
||||
if (!(this instanceof Node)) {
|
||||
return new RadioButton(options);
|
||||
}
|
||||
|
||||
options = options || {};
|
||||
|
||||
Checkbox.call(this, options);
|
||||
|
||||
this.on('check', function() {
|
||||
var el = self;
|
||||
while (el = el.parent) {
|
||||
if (el.type === 'radio-set'
|
||||
|| el.type === 'form') break;
|
||||
}
|
||||
el = el || self.parent;
|
||||
el.forDescendants(function(el) {
|
||||
if (el.type !== 'radio-button' || el === self) {
|
||||
return;
|
||||
}
|
||||
el.uncheck();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
RadioButton.prototype.__proto__ = Checkbox.prototype;
|
||||
|
||||
RadioButton.prototype.type = 'radio-button';
|
||||
|
||||
RadioButton.prototype.render = function() {
|
||||
this.clearPos(true);
|
||||
this.setContent('(' + (this.checked ? '*' : ' ') + ') ' + this.text, true);
|
||||
return this._render();
|
||||
};
|
||||
|
||||
RadioButton.prototype.toggle = RadioButton.prototype.check;
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = RadioButton;
|
||||
36
lib/widgets/radioset.js
Normal file
@ -0,0 +1,36 @@
|
||||
/**
|
||||
* radioset.js - radio set element for blessed
|
||||
* Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Modules
|
||||
*/
|
||||
|
||||
var Node = require('./node');
|
||||
var Box = require('./box');
|
||||
|
||||
/**
|
||||
* RadioSet
|
||||
*/
|
||||
|
||||
function RadioSet(options) {
|
||||
if (!(this instanceof Node)) {
|
||||
return new RadioSet(options);
|
||||
}
|
||||
options = options || {};
|
||||
// Possibly inherit parent's style.
|
||||
// options.style = this.parent.style;
|
||||
Box.call(this, options);
|
||||
}
|
||||
|
||||
RadioSet.prototype.__proto__ = Box.prototype;
|
||||
|
||||
RadioSet.prototype.type = 'radio-set';
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = RadioSet;
|
||||
2298
lib/widgets/screen.js
Normal file
389
lib/widgets/scrollablebox.js
Normal file
@ -0,0 +1,389 @@
|
||||
/**
|
||||
* scrollablebox.js - scrollable box element for blessed
|
||||
* Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Modules
|
||||
*/
|
||||
|
||||
var Node = require('./node');
|
||||
var Box = require('./box');
|
||||
|
||||
/**
|
||||
* ScrollableBox
|
||||
*/
|
||||
|
||||
function ScrollableBox(options) {
|
||||
var self = this;
|
||||
|
||||
if (!(this instanceof Node)) {
|
||||
return new ScrollableBox(options);
|
||||
}
|
||||
|
||||
options = options || {};
|
||||
|
||||
Box.call(this, options);
|
||||
|
||||
if (options.scrollable === false) {
|
||||
return this;
|
||||
}
|
||||
|
||||
this.scrollable = true;
|
||||
this.childOffset = 0;
|
||||
this.childBase = 0;
|
||||
this.baseLimit = options.baseLimit || Infinity;
|
||||
this.alwaysScroll = options.alwaysScroll;
|
||||
|
||||
this.scrollbar = options.scrollbar;
|
||||
if (this.scrollbar) {
|
||||
this.scrollbar.ch = this.scrollbar.ch || ' ';
|
||||
this.style.scrollbar = this.style.scrollbar || this.scrollbar.style;
|
||||
if (!this.style.scrollbar) {
|
||||
this.style.scrollbar = {};
|
||||
this.style.scrollbar.fg = this.scrollbar.fg;
|
||||
this.style.scrollbar.bg = this.scrollbar.bg;
|
||||
this.style.scrollbar.bold = this.scrollbar.bold;
|
||||
this.style.scrollbar.underline = this.scrollbar.underline;
|
||||
this.style.scrollbar.inverse = this.scrollbar.inverse;
|
||||
this.style.scrollbar.invisible = this.scrollbar.invisible;
|
||||
}
|
||||
//this.scrollbar.style = this.style.scrollbar;
|
||||
if (this.track || this.scrollbar.track) {
|
||||
this.track = this.scrollbar.track || this.track;
|
||||
this.style.track = this.style.scrollbar.track || this.style.track;
|
||||
this.track.ch = this.track.ch || ' ';
|
||||
this.style.track = this.style.track || this.track.style;
|
||||
if (!this.style.track) {
|
||||
this.style.track = {};
|
||||
this.style.track.fg = this.track.fg;
|
||||
this.style.track.bg = this.track.bg;
|
||||
this.style.track.bold = this.track.bold;
|
||||
this.style.track.underline = this.track.underline;
|
||||
this.style.track.inverse = this.track.inverse;
|
||||
this.style.track.invisible = this.track.invisible;
|
||||
}
|
||||
this.track.style = this.style.track;
|
||||
}
|
||||
// Allow controlling of the scrollbar via the mouse:
|
||||
if (options.mouse) {
|
||||
this.on('mousedown', function(data) {
|
||||
if (self._scrollingBar) {
|
||||
// Do not allow dragging on the scrollbar:
|
||||
delete self.screen._dragging;
|
||||
delete self._drag;
|
||||
return;
|
||||
}
|
||||
var x = data.x - self.aleft;
|
||||
var y = data.y - self.atop;
|
||||
if (x === self.width - self.iright - 1) {
|
||||
// Do not allow dragging on the scrollbar:
|
||||
delete self.screen._dragging;
|
||||
delete self._drag;
|
||||
var perc = (y - self.itop) / (self.height - self.iheight);
|
||||
self.setScrollPerc(perc * 100 | 0);
|
||||
self.screen.render();
|
||||
var smd, smu;
|
||||
self._scrollingBar = true;
|
||||
self.onScreenEvent('mousedown', smd = function(data) {
|
||||
var y = data.y - self.atop;
|
||||
var perc = y / self.height;
|
||||
self.setScrollPerc(perc * 100 | 0);
|
||||
self.screen.render();
|
||||
});
|
||||
// If mouseup occurs out of the window, no mouseup event fires, and
|
||||
// scrollbar will drag again on mousedown until another mouseup
|
||||
// occurs.
|
||||
self.onScreenEvent('mouseup', smu = function() {
|
||||
self._scrollingBar = false;
|
||||
self.removeScreenEvent('mousedown', smd);
|
||||
self.removeScreenEvent('mouseup', smu);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (options.mouse) {
|
||||
this.on('wheeldown', function() {
|
||||
self.scroll(self.height / 2 | 0 || 1);
|
||||
self.screen.render();
|
||||
});
|
||||
this.on('wheelup', function() {
|
||||
self.scroll(-(self.height / 2 | 0) || -1);
|
||||
self.screen.render();
|
||||
});
|
||||
}
|
||||
|
||||
if (options.keys && !options.ignoreKeys) {
|
||||
this.on('keypress', function(ch, key) {
|
||||
if (key.name === 'up' || (options.vi && key.name === 'k')) {
|
||||
self.scroll(-1);
|
||||
self.screen.render();
|
||||
return;
|
||||
}
|
||||
if (key.name === 'down' || (options.vi && key.name === 'j')) {
|
||||
self.scroll(1);
|
||||
self.screen.render();
|
||||
return;
|
||||
}
|
||||
if (options.vi && key.name === 'u' && key.ctrl) {
|
||||
self.scroll(-(self.height / 2 | 0) || -1);
|
||||
self.screen.render();
|
||||
return;
|
||||
}
|
||||
if (options.vi && key.name === 'd' && key.ctrl) {
|
||||
self.scroll(self.height / 2 | 0 || 1);
|
||||
self.screen.render();
|
||||
return;
|
||||
}
|
||||
if (options.vi && key.name === 'b' && key.ctrl) {
|
||||
self.scroll(-self.height || -1);
|
||||
self.screen.render();
|
||||
return;
|
||||
}
|
||||
if (options.vi && key.name === 'f' && key.ctrl) {
|
||||
self.scroll(self.height || 1);
|
||||
self.screen.render();
|
||||
return;
|
||||
}
|
||||
if (options.vi && key.name === 'g' && !key.shift) {
|
||||
self.scrollTo(0);
|
||||
self.screen.render();
|
||||
return;
|
||||
}
|
||||
if (options.vi && key.name === 'g' && key.shift) {
|
||||
self.scrollTo(self.getScrollHeight());
|
||||
self.screen.render();
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.on('parsed content', function() {
|
||||
self._recalculateIndex();
|
||||
});
|
||||
|
||||
self._recalculateIndex();
|
||||
}
|
||||
|
||||
ScrollableBox.prototype.__proto__ = Box.prototype;
|
||||
|
||||
ScrollableBox.prototype.type = 'scrollable-box';
|
||||
|
||||
// XXX Potentially use this in place of scrollable checks elsewhere.
|
||||
ScrollableBox.prototype.__defineGetter__('reallyScrollable', function() {
|
||||
if (this.shrink) return this.scrollable;
|
||||
return this.getScrollHeight() > this.height;
|
||||
});
|
||||
|
||||
ScrollableBox.prototype._scrollBottom = function() {
|
||||
if (!this.scrollable) return 0;
|
||||
|
||||
// We could just calculate the children, but we can
|
||||
// optimize for lists by just returning the items.length.
|
||||
if (this._isList) {
|
||||
return this.items ? this.items.length : 0;
|
||||
}
|
||||
|
||||
if (this.lpos && this.lpos._scrollBottom) {
|
||||
return this.lpos._scrollBottom;
|
||||
}
|
||||
|
||||
var bottom = this.children.reduce(function(current, el) {
|
||||
// el.height alone does not calculate the shrunken height, we need to use
|
||||
// getCoords. A shrunken box inside a scrollable element will not grow any
|
||||
// larger than the scrollable element's context regardless of how much
|
||||
// content is in the shrunken box, unless we do this (call getCoords
|
||||
// without the scrollable calculation):
|
||||
// See: $ node test/widget-shrink-fail-2.js
|
||||
if (!el.detached) {
|
||||
var lpos = el._getCoords(false, true);
|
||||
if (lpos) {
|
||||
return Math.max(current, el.rtop + (lpos.yl - lpos.yi));
|
||||
}
|
||||
}
|
||||
return Math.max(current, el.rtop + el.height);
|
||||
}, 0);
|
||||
|
||||
// XXX Use this? Makes .getScrollHeight() useless!
|
||||
// if (bottom < this._clines.length) bottom = this._clines.length;
|
||||
|
||||
if (this.lpos) this.lpos._scrollBottom = bottom;
|
||||
|
||||
return bottom;
|
||||
};
|
||||
|
||||
ScrollableBox.prototype.setScroll =
|
||||
ScrollableBox.prototype.scrollTo = function(offset, always) {
|
||||
// XXX
|
||||
// At first, this appeared to account for the first new calculation of childBase:
|
||||
this.scroll(0);
|
||||
return this.scroll(offset - (this.childBase + this.childOffset), always);
|
||||
};
|
||||
|
||||
ScrollableBox.prototype.getScroll = function() {
|
||||
return this.childBase + this.childOffset;
|
||||
};
|
||||
|
||||
ScrollableBox.prototype.scroll = function(offset, always) {
|
||||
if (!this.scrollable) return;
|
||||
|
||||
if (this.detached) return;
|
||||
|
||||
// Handle scrolling.
|
||||
var visible = this.height - this.iheight
|
||||
, base = this.childBase
|
||||
, d
|
||||
, p
|
||||
, t
|
||||
, b
|
||||
, max
|
||||
, emax;
|
||||
|
||||
if (this.alwaysScroll || always) {
|
||||
// Semi-workaround
|
||||
this.childOffset = offset > 0
|
||||
? visible - 1 + offset
|
||||
: offset;
|
||||
} else {
|
||||
this.childOffset += offset;
|
||||
}
|
||||
|
||||
if (this.childOffset > visible - 1) {
|
||||
d = this.childOffset - (visible - 1);
|
||||
this.childOffset -= d;
|
||||
this.childBase += d;
|
||||
} else if (this.childOffset < 0) {
|
||||
d = this.childOffset;
|
||||
this.childOffset += -d;
|
||||
this.childBase += d;
|
||||
}
|
||||
|
||||
if (this.childBase < 0) {
|
||||
this.childBase = 0;
|
||||
} else if (this.childBase > this.baseLimit) {
|
||||
this.childBase = this.baseLimit;
|
||||
}
|
||||
|
||||
// Find max "bottom" value for
|
||||
// content and descendant elements.
|
||||
// Scroll the content if necessary.
|
||||
if (this.childBase === base) {
|
||||
return this.emit('scroll');
|
||||
}
|
||||
|
||||
// When scrolling text, we want to be able to handle SGR codes as well as line
|
||||
// feeds. This allows us to take preformatted text output from other programs
|
||||
// and put it in a scrollable text box.
|
||||
this.parseContent();
|
||||
|
||||
// XXX
|
||||
// max = this.getScrollHeight() - (this.height - this.iheight);
|
||||
|
||||
max = this._clines.length - (this.height - this.iheight);
|
||||
if (max < 0) max = 0;
|
||||
emax = this._scrollBottom() - (this.height - this.iheight);
|
||||
if (emax < 0) emax = 0;
|
||||
|
||||
this.childBase = Math.min(this.childBase, Math.max(emax, max));
|
||||
|
||||
if (this.childBase < 0) {
|
||||
this.childBase = 0;
|
||||
} else if (this.childBase > this.baseLimit) {
|
||||
this.childBase = this.baseLimit;
|
||||
}
|
||||
|
||||
// Optimize scrolling with CSR + IL/DL.
|
||||
p = this.lpos;
|
||||
// Only really need _getCoords() if we want
|
||||
// to allow nestable scrolling elements...
|
||||
// or if we **really** want shrinkable
|
||||
// scrolling elements.
|
||||
// p = this._getCoords();
|
||||
if (p && this.childBase !== base && this.screen.cleanSides(this)) {
|
||||
t = p.yi + this.itop;
|
||||
b = p.yl - this.ibottom - 1;
|
||||
d = this.childBase - base;
|
||||
|
||||
if (d > 0 && d < visible) {
|
||||
// scrolled down
|
||||
this.screen.deleteLine(d, t, t, b);
|
||||
} else if (d < 0 && -d < visible) {
|
||||
// scrolled up
|
||||
d = -d;
|
||||
this.screen.insertLine(d, t, t, b);
|
||||
}
|
||||
}
|
||||
|
||||
return this.emit('scroll');
|
||||
};
|
||||
|
||||
ScrollableBox.prototype._recalculateIndex = function() {
|
||||
var max, emax;
|
||||
|
||||
if (this.detached || !this.scrollable) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// XXX
|
||||
// max = this.getScrollHeight() - (this.height - this.iheight);
|
||||
|
||||
max = this._clines.length - (this.height - this.iheight);
|
||||
if (max < 0) max = 0;
|
||||
emax = this._scrollBottom() - (this.height - this.iheight);
|
||||
if (emax < 0) emax = 0;
|
||||
|
||||
this.childBase = Math.min(this.childBase, Math.max(emax, max));
|
||||
|
||||
if (this.childBase < 0) {
|
||||
this.childBase = 0;
|
||||
} else if (this.childBase > this.baseLimit) {
|
||||
this.childBase = this.baseLimit;
|
||||
}
|
||||
};
|
||||
|
||||
ScrollableBox.prototype.resetScroll = function() {
|
||||
if (!this.scrollable) return;
|
||||
this.childOffset = 0;
|
||||
this.childBase = 0;
|
||||
return this.emit('scroll');
|
||||
};
|
||||
|
||||
ScrollableBox.prototype.getScrollHeight = function() {
|
||||
return Math.max(this._clines.length, this._scrollBottom());
|
||||
};
|
||||
|
||||
ScrollableBox.prototype.getScrollPerc = function(s) {
|
||||
var pos = this.lpos || this._getCoords();
|
||||
if (!pos) return s ? -1 : 0;
|
||||
|
||||
var height = (pos.yl - pos.yi) - this.iheight
|
||||
, i = this.getScrollHeight()
|
||||
, p;
|
||||
|
||||
if (height < i) {
|
||||
if (this.alwaysScroll) {
|
||||
p = this.childBase / (i - height);
|
||||
} else {
|
||||
p = (this.childBase + this.childOffset) / (i - 1);
|
||||
}
|
||||
return p * 100;
|
||||
}
|
||||
|
||||
return s ? -1 : 0;
|
||||
};
|
||||
|
||||
ScrollableBox.prototype.setScrollPerc = function(i) {
|
||||
// XXX
|
||||
// var m = this.getScrollHeight();
|
||||
var m = Math.max(this._clines.length, this._scrollBottom());
|
||||
return this.scrollTo((i / 100) * m | 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = ScrollableBox;
|
||||
35
lib/widgets/scrollabletext.js
Normal file
@ -0,0 +1,35 @@
|
||||
/**
|
||||
* scrollabletext.js - scrollable text element for blessed
|
||||
* Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Modules
|
||||
*/
|
||||
|
||||
var Node = require('./node');
|
||||
var ScrollableBox = require('./scrollablebox');
|
||||
|
||||
/**
|
||||
* ScrollableText
|
||||
*/
|
||||
|
||||
function ScrollableText(options) {
|
||||
if (!(this instanceof Node)) {
|
||||
return new ScrollableText(options);
|
||||
}
|
||||
options = options || {};
|
||||
options.alwaysScroll = true;
|
||||
ScrollableBox.call(this, options);
|
||||
}
|
||||
|
||||
ScrollableText.prototype.__proto__ = ScrollableBox.prototype;
|
||||
|
||||
ScrollableText.prototype.type = 'scrollable-text';
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = ScrollableText;
|
||||
354
lib/widgets/table.js
Normal file
@ -0,0 +1,354 @@
|
||||
/**
|
||||
* table.js - table element for blessed
|
||||
* Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Modules
|
||||
*/
|
||||
|
||||
var Node = require('./node');
|
||||
var Box = require('./box');
|
||||
|
||||
/**
|
||||
* Table
|
||||
*/
|
||||
|
||||
function Table(options) {
|
||||
var self = this;
|
||||
|
||||
if (!(this instanceof Node)) {
|
||||
return new Table(options);
|
||||
}
|
||||
|
||||
options = options || {};
|
||||
options.shrink = true;
|
||||
options.style = options.style || {};
|
||||
options.style.border = options.style.border || {};
|
||||
options.style.header = options.style.header || {};
|
||||
options.style.cell = options.style.cell || {};
|
||||
options.align = options.align || 'center';
|
||||
|
||||
// Regular tables do not get custom height (this would
|
||||
// require extra padding). Maybe add in the future.
|
||||
delete options.height;
|
||||
|
||||
Box.call(this, options);
|
||||
|
||||
this.pad = options.pad != null
|
||||
? options.pad
|
||||
: 2;
|
||||
|
||||
this.setData(options.rows || options.data);
|
||||
|
||||
this.on('attach', function() {
|
||||
self.setContent('');
|
||||
self.setData(self.rows);
|
||||
});
|
||||
|
||||
this.on('resize', function() {
|
||||
self.setContent('');
|
||||
self.setData(self.rows);
|
||||
self.screen.render();
|
||||
});
|
||||
}
|
||||
|
||||
Table.prototype.__proto__ = Box.prototype;
|
||||
|
||||
Table.prototype.type = 'table';
|
||||
|
||||
Table.prototype._calculateMaxes = function() {
|
||||
var self = this;
|
||||
var maxes = [];
|
||||
|
||||
if (this.detached) return;
|
||||
|
||||
this.rows = this.rows || [];
|
||||
|
||||
this.rows.forEach(function(row) {
|
||||
row.forEach(function(cell, i) {
|
||||
var clen = self.strWidth(cell);
|
||||
if (!maxes[i] || maxes[i] < clen) {
|
||||
maxes[i] = clen;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var total = maxes.reduce(function(total, max) {
|
||||
return total + max;
|
||||
}, 0);
|
||||
total += maxes.length + 1;
|
||||
|
||||
// XXX There might be an issue with resizing where on the first resize event
|
||||
// width appears to be less than total if it's a percentage or left/right
|
||||
// combination.
|
||||
if (this.width < total) {
|
||||
delete this.position.width;
|
||||
}
|
||||
|
||||
if (this.position.width != null) {
|
||||
var missing = this.width - total;
|
||||
var w = missing / maxes.length | 0;
|
||||
var wr = missing % maxes.length;
|
||||
maxes = maxes.map(function(max, i) {
|
||||
if (i === maxes.length - 1) {
|
||||
return max + w + wr;
|
||||
}
|
||||
return max + w;
|
||||
});
|
||||
} else {
|
||||
maxes = maxes.map(function(max) {
|
||||
return max + self.pad;
|
||||
});
|
||||
}
|
||||
|
||||
return this._maxes = maxes;
|
||||
};
|
||||
|
||||
Table.prototype.setRows =
|
||||
Table.prototype.setData = function(rows) {
|
||||
var self = this
|
||||
, text = ''
|
||||
, align = this.align;
|
||||
|
||||
this.rows = rows || [];
|
||||
|
||||
this._calculateMaxes();
|
||||
|
||||
if (!this._maxes) return;
|
||||
|
||||
this.rows.forEach(function(row, i) {
|
||||
var isFooter = i === self.rows.length - 1;
|
||||
row.forEach(function(cell, i) {
|
||||
var width = self._maxes[i];
|
||||
var clen = self.strWidth(cell);
|
||||
|
||||
if (i !== 0) {
|
||||
text += ' ';
|
||||
}
|
||||
|
||||
while (clen < width) {
|
||||
if (align === 'center') {
|
||||
cell = ' ' + cell + ' ';
|
||||
clen += 2;
|
||||
} else if (align === 'left') {
|
||||
cell = cell + ' ';
|
||||
clen += 1;
|
||||
} else if (align === 'right') {
|
||||
cell = ' ' + cell;
|
||||
clen += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (clen > width) {
|
||||
if (align === 'center') {
|
||||
cell = cell.substring(1);
|
||||
clen--;
|
||||
} else if (align === 'left') {
|
||||
cell = cell.slice(0, -1);
|
||||
clen--;
|
||||
} else if (align === 'right') {
|
||||
cell = cell.substring(1);
|
||||
clen--;
|
||||
}
|
||||
}
|
||||
|
||||
text += cell;
|
||||
});
|
||||
if (!isFooter) {
|
||||
text += '\n\n';
|
||||
}
|
||||
});
|
||||
|
||||
delete this.align;
|
||||
this.setContent(text);
|
||||
this.align = align;
|
||||
};
|
||||
|
||||
Table.prototype.render = function() {
|
||||
var self = this;
|
||||
|
||||
var coords = this._render();
|
||||
if (!coords) return;
|
||||
|
||||
this._calculateMaxes();
|
||||
|
||||
if (!this._maxes) return coords;
|
||||
|
||||
var lines = this.screen.lines
|
||||
, xi = coords.xi
|
||||
, yi = coords.yi
|
||||
, rx
|
||||
, ry
|
||||
, i;
|
||||
|
||||
var dattr = this.sattr(this.style)
|
||||
, hattr = this.sattr(this.style.header)
|
||||
, cattr = this.sattr(this.style.cell)
|
||||
, battr = this.sattr(this.style.border);
|
||||
|
||||
var width = coords.xl - coords.xi - this.iright
|
||||
, height = coords.yl - coords.yi - this.ibottom;
|
||||
|
||||
// Apply attributes to header cells and cells.
|
||||
for (var y = this.itop; y < height; y++) {
|
||||
if (!lines[yi + y]) break;
|
||||
for (var x = this.ileft; x < width; x++) {
|
||||
if (!lines[yi + y][xi + x]) break;
|
||||
// Check to see if it's not the default attr. Allows for tags:
|
||||
if (lines[yi + y][xi + x][0] !== dattr) continue;
|
||||
if (y === this.itop) {
|
||||
lines[yi + y][xi + x][0] = hattr;
|
||||
} else {
|
||||
lines[yi + y][xi + x][0] = cattr;
|
||||
}
|
||||
lines[yi + y].dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.border || this.options.noCellBorders) return coords;
|
||||
|
||||
// Draw border with correct angles.
|
||||
ry = 0;
|
||||
for (i = 0; i < self.rows.length + 1; i++) {
|
||||
if (!lines[yi + ry]) break;
|
||||
rx = 0;
|
||||
self._maxes.forEach(function(max, i) {
|
||||
rx += max;
|
||||
if (i === 0) {
|
||||
if (!lines[yi + ry][xi + 0]) return;
|
||||
// left side
|
||||
if (ry === 0) {
|
||||
// top
|
||||
lines[yi + ry][xi + 0][0] = battr;
|
||||
// lines[yi + ry][xi + 0][1] = '\u250c'; // '┌'
|
||||
} else if (ry / 2 === self.rows.length) {
|
||||
// bottom
|
||||
lines[yi + ry][xi + 0][0] = battr;
|
||||
// lines[yi + ry][xi + 0][1] = '\u2514'; // '└'
|
||||
} else {
|
||||
// middle
|
||||
lines[yi + ry][xi + 0][0] = battr;
|
||||
lines[yi + ry][xi + 0][1] = '\u251c'; // '├'
|
||||
// XXX If we alter iwidth and ileft for no borders - nothing should be written here
|
||||
if (!self.border.left) {
|
||||
lines[yi + ry][xi + 0][1] = '\u2500'; // '─'
|
||||
}
|
||||
}
|
||||
lines[yi + ry].dirty = true;
|
||||
} else if (i === self._maxes.length - 1) {
|
||||
if (!lines[yi + ry][xi + rx + 1]) return;
|
||||
// right side
|
||||
if (ry === 0) {
|
||||
// top
|
||||
rx++;
|
||||
lines[yi + ry][xi + rx][0] = battr;
|
||||
// lines[yi + ry][xi + rx][1] = '\u2510'; // '┐'
|
||||
} else if (ry / 2 === self.rows.length) {
|
||||
// bottom
|
||||
rx++;
|
||||
lines[yi + ry][xi + rx][0] = battr;
|
||||
// lines[yi + ry][xi + rx][1] = '\u2518'; // '┘'
|
||||
} else {
|
||||
// middle
|
||||
rx++;
|
||||
lines[yi + ry][xi + rx][0] = battr;
|
||||
lines[yi + ry][xi + rx][1] = '\u2524'; // '┤'
|
||||
// XXX If we alter iwidth and iright for no borders - nothing should be written here
|
||||
if (!self.border.right) {
|
||||
lines[yi + ry][xi + rx][1] = '\u2500'; // '─'
|
||||
}
|
||||
}
|
||||
lines[yi + ry].dirty = true;
|
||||
return;
|
||||
}
|
||||
if (!lines[yi + ry][xi + rx + 1]) return;
|
||||
// center
|
||||
if (ry === 0) {
|
||||
// top
|
||||
rx++;
|
||||
lines[yi + ry][xi + rx][0] = battr;
|
||||
lines[yi + ry][xi + rx][1] = '\u252c'; // '┬'
|
||||
// XXX If we alter iheight and itop for no borders - nothing should be written here
|
||||
if (!self.border.top) {
|
||||
lines[yi + ry][xi + rx][1] = '\u2502'; // '│'
|
||||
}
|
||||
} else if (ry / 2 === self.rows.length) {
|
||||
// bottom
|
||||
rx++;
|
||||
lines[yi + ry][xi + rx][0] = battr;
|
||||
lines[yi + ry][xi + rx][1] = '\u2534'; // '┴'
|
||||
// XXX If we alter iheight and ibottom for no borders - nothing should be written here
|
||||
if (!self.border.bottom) {
|
||||
lines[yi + ry][xi + rx][1] = '\u2502'; // '│'
|
||||
}
|
||||
} else {
|
||||
// middle
|
||||
if (self.options.fillCellBorders) {
|
||||
var lbg = (ry <= 2 ? hattr : cattr) & 0x1ff;
|
||||
rx++;
|
||||
lines[yi + ry][xi + rx][0] = (battr & ~0x1ff) | lbg;
|
||||
} else {
|
||||
rx++;
|
||||
lines[yi + ry][xi + rx][0] = battr;
|
||||
}
|
||||
lines[yi + ry][xi + rx][1] = '\u253c'; // '┼'
|
||||
// rx++;
|
||||
}
|
||||
lines[yi + ry].dirty = true;
|
||||
});
|
||||
ry += 2;
|
||||
}
|
||||
|
||||
// Draw internal borders.
|
||||
for (ry = 1; ry < self.rows.length * 2; ry++) {
|
||||
if (!lines[yi + ry]) break;
|
||||
rx = 0;
|
||||
self._maxes.slice(0, -1).forEach(function(max) {
|
||||
rx += max;
|
||||
if (!lines[yi + ry][xi + rx + 1]) return;
|
||||
if (ry % 2 !== 0) {
|
||||
if (self.options.fillCellBorders) {
|
||||
var lbg = (ry <= 2 ? hattr : cattr) & 0x1ff;
|
||||
rx++;
|
||||
lines[yi + ry][xi + rx][0] = (battr & ~0x1ff) | lbg;
|
||||
} else {
|
||||
rx++;
|
||||
lines[yi + ry][xi + rx][0] = battr;
|
||||
}
|
||||
lines[yi + ry][xi + rx][1] = '\u2502'; // '│'
|
||||
lines[yi + ry].dirty = true;
|
||||
} else {
|
||||
rx++;
|
||||
}
|
||||
});
|
||||
rx = 1;
|
||||
self._maxes.forEach(function(max) {
|
||||
while (max--) {
|
||||
if (ry % 2 === 0) {
|
||||
if (!lines[yi + ry]) break;
|
||||
if (!lines[yi + ry][xi + rx + 1]) break;
|
||||
if (self.options.fillCellBorders) {
|
||||
var lbg = (ry <= 2 ? hattr : cattr) & 0x1ff;
|
||||
lines[yi + ry][xi + rx][0] = (battr & ~0x1ff) | lbg;
|
||||
} else {
|
||||
lines[yi + ry][xi + rx][0] = battr;
|
||||
}
|
||||
lines[yi + ry][xi + rx][1] = '\u2500'; // '─'
|
||||
lines[yi + ry].dirty = true;
|
||||
}
|
||||
rx++;
|
||||
}
|
||||
rx++;
|
||||
});
|
||||
}
|
||||
|
||||
return coords;
|
||||
};
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = Table;
|
||||
412
lib/widgets/terminal.js
Normal file
@ -0,0 +1,412 @@
|
||||
/**
|
||||
* terminal.js - term.js terminal element for blessed
|
||||
* Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Modules
|
||||
*/
|
||||
|
||||
var nextTick = global.setImmediate || process.nextTick.bind(process);
|
||||
|
||||
var Node = require('./node');
|
||||
var Box = require('./box');
|
||||
|
||||
/**
|
||||
* Terminal
|
||||
*/
|
||||
|
||||
function Terminal(options) {
|
||||
if (!(this instanceof Node)) {
|
||||
return new Terminal(options);
|
||||
}
|
||||
|
||||
options = options || {};
|
||||
options.scrollable = false;
|
||||
|
||||
Box.call(this, options);
|
||||
|
||||
// XXX Workaround for all motion
|
||||
if (this.screen.program.tmux && this.screen.program.tmuxVersion >= 2) {
|
||||
this.screen.program.enableMouse();
|
||||
}
|
||||
|
||||
this.handler = options.handler;
|
||||
this.shell = options.shell || process.env.SHELL || 'sh';
|
||||
this.args = options.args || [];
|
||||
|
||||
this.cursor = this.options.cursor;
|
||||
this.cursorBlink = this.options.cursorBlink;
|
||||
this.screenKeys = this.options.screenKeys;
|
||||
|
||||
this.style = this.style || {};
|
||||
this.style.bg = this.style.bg || 'default';
|
||||
this.style.fg = this.style.fg || 'default';
|
||||
|
||||
this.termName = options.terminal
|
||||
|| options.term
|
||||
|| process.env.TERM
|
||||
|| 'xterm';
|
||||
|
||||
this.bootstrap();
|
||||
}
|
||||
|
||||
Terminal.prototype.__proto__ = Box.prototype;
|
||||
|
||||
Terminal.prototype.type = 'terminal';
|
||||
|
||||
Terminal.prototype.bootstrap = function() {
|
||||
var self = this;
|
||||
|
||||
var element = {
|
||||
// window
|
||||
get document() { return element; },
|
||||
navigator: { userAgent: 'node.js' },
|
||||
|
||||
// document
|
||||
get defaultView() { return element; },
|
||||
get documentElement() { return element; },
|
||||
createElement: function() { return element; },
|
||||
|
||||
// element
|
||||
get ownerDocument() { return element; },
|
||||
addEventListener: function() {},
|
||||
removeEventListener: function() {},
|
||||
getElementsByTagName: function() { return [element]; },
|
||||
getElementById: function() { return element; },
|
||||
parentNode: null,
|
||||
offsetParent: null,
|
||||
appendChild: function() {},
|
||||
removeChild: function() {},
|
||||
setAttribute: function() {},
|
||||
getAttribute: function() {},
|
||||
style: {},
|
||||
focus: function() {},
|
||||
blur: function() {},
|
||||
console: console
|
||||
};
|
||||
|
||||
element.parentNode = element;
|
||||
element.offsetParent = element;
|
||||
|
||||
this.term = require('term.js')({
|
||||
termName: this.termName,
|
||||
cols: this.width - this.iwidth,
|
||||
rows: this.height - this.iheight,
|
||||
context: element,
|
||||
document: element,
|
||||
body: element,
|
||||
parent: element,
|
||||
cursorBlink: this.cursorBlink,
|
||||
screenKeys: this.screenKeys
|
||||
});
|
||||
|
||||
this.term.refresh = function() {
|
||||
self.screen.render();
|
||||
};
|
||||
|
||||
this.term.keyDown = function() {};
|
||||
this.term.keyPress = function() {};
|
||||
|
||||
this.term.open(element);
|
||||
|
||||
// Emits key sequences in html-land.
|
||||
// Technically not necessary here.
|
||||
// In reality if we wanted to be neat, we would overwrite the keyDown and
|
||||
// keyPress methods with our own node.js-keys->terminal-keys methods, but
|
||||
// since all the keys are already coming in as escape sequences, we can just
|
||||
// send the input directly to the handler/socket (see below).
|
||||
// this.term.on('data', function(data) {
|
||||
// self.handler(data);
|
||||
// });
|
||||
|
||||
// Incoming keys and mouse inputs.
|
||||
// NOTE: Cannot pass mouse events - coordinates will be off!
|
||||
this.screen.program.input.on('data', this._onData = function(data) {
|
||||
if (self.screen.focused === self && !self._isMouse(data)) {
|
||||
self.handler(data);
|
||||
}
|
||||
});
|
||||
|
||||
this.onScreenEvent('mouse', function(data) {
|
||||
if (self.screen.focused !== self) return;
|
||||
|
||||
if (data.x < self.aleft + self.ileft) return;
|
||||
if (data.y < self.atop + self.itop) return;
|
||||
if (data.x > self.aleft - self.ileft + self.width) return;
|
||||
if (data.y > self.atop - self.itop + self.height) return;
|
||||
|
||||
if (self.term.x10Mouse
|
||||
|| self.term.vt200Mouse
|
||||
|| self.term.normalMouse
|
||||
|| self.term.mouseEvents
|
||||
|| self.term.utfMouse
|
||||
|| self.term.sgrMouse
|
||||
|| self.term.urxvtMouse) {
|
||||
;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
var b = data.raw[0]
|
||||
, x = data.x - self.aleft
|
||||
, y = data.y - self.atop
|
||||
, s;
|
||||
|
||||
if (self.term.urxvtMouse) {
|
||||
if (self.screen.program.sgrMouse) {
|
||||
b += 32;
|
||||
}
|
||||
s = '\x1b[' + b + ';' + (x + 32) + ';' + (y + 32) + 'M';
|
||||
} else if (self.term.sgrMouse) {
|
||||
if (!self.screen.program.sgrMouse) {
|
||||
b -= 32;
|
||||
}
|
||||
s = '\x1b[<' + b + ';' + x + ';' + y
|
||||
+ (data.action === 'mousedown' ? 'M' : 'm');
|
||||
} else {
|
||||
if (self.screen.program.sgrMouse) {
|
||||
b += 32;
|
||||
}
|
||||
s = '\x1b[M'
|
||||
+ String.fromCharCode(b)
|
||||
+ String.fromCharCode(x + 32)
|
||||
+ String.fromCharCode(y + 32);
|
||||
}
|
||||
|
||||
self.handler(s);
|
||||
});
|
||||
|
||||
this.on('focus', function() {
|
||||
self.term.focus();
|
||||
});
|
||||
|
||||
this.on('blur', function() {
|
||||
self.term.blur();
|
||||
});
|
||||
|
||||
this.term.on('title', function(title) {
|
||||
self.title = title;
|
||||
self.emit('title', title);
|
||||
});
|
||||
|
||||
this.term.on('passthrough', function(data) {
|
||||
self.screen.program.flush();
|
||||
self.screen.program._owrite(data);
|
||||
});
|
||||
|
||||
this.on('resize', function() {
|
||||
nextTick(function() {
|
||||
self.term.resize(self.width - self.iwidth, self.height - self.iheight);
|
||||
});
|
||||
});
|
||||
|
||||
this.once('render', function() {
|
||||
self.term.resize(self.width - self.iwidth, self.height - self.iheight);
|
||||
});
|
||||
|
||||
this.on('destroy', function() {
|
||||
self.kill();
|
||||
self.screen.program.input.removeListener('data', self._onData);
|
||||
});
|
||||
|
||||
if (this.handler) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.pty = require('pty.js').fork(this.shell, this.args, {
|
||||
name: this.termName,
|
||||
cols: this.width - this.iwidth,
|
||||
rows: this.height - this.iheight,
|
||||
cwd: process.env.HOME,
|
||||
env: this.options.env || process.env
|
||||
});
|
||||
|
||||
this.on('resize', function() {
|
||||
nextTick(function() {
|
||||
try {
|
||||
self.pty.resize(self.width - self.iwidth, self.height - self.iheight);
|
||||
} catch (e) {
|
||||
;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
this.handler = function(data) {
|
||||
self.pty.write(data);
|
||||
self.screen.render();
|
||||
};
|
||||
|
||||
this.pty.on('data', function(data) {
|
||||
self.write(data);
|
||||
self.screen.render();
|
||||
});
|
||||
|
||||
this.pty.on('exit', function(code) {
|
||||
self.emit('exit', code || null);
|
||||
});
|
||||
|
||||
this.onScreenEvent('keypress', function() {
|
||||
self.screen.render();
|
||||
});
|
||||
|
||||
this.screen._listenKeys(this);
|
||||
};
|
||||
|
||||
Terminal.prototype.write = function(data) {
|
||||
return this.term.write(data);
|
||||
};
|
||||
|
||||
Terminal.prototype.render = function() {
|
||||
var ret = this._render();
|
||||
if (!ret) return;
|
||||
|
||||
this.dattr = this.sattr(this.style);
|
||||
|
||||
var xi = ret.xi + this.ileft
|
||||
, xl = ret.xl - this.iright
|
||||
, yi = ret.yi + this.itop
|
||||
, yl = ret.yl - this.ibottom
|
||||
, cursor;
|
||||
|
||||
var scrollback = this.term.lines.length - (yl - yi);
|
||||
|
||||
for (var y = Math.max(yi, 0); y < yl; y++) {
|
||||
var line = this.screen.lines[y];
|
||||
if (!line || !this.term.lines[scrollback + y - yi]) break;
|
||||
|
||||
if (y === yi + this.term.y
|
||||
&& this.term.cursorState
|
||||
&& this.screen.focused === this
|
||||
&& (this.term.ydisp === this.term.ybase || this.term.selectMode)
|
||||
&& !this.term.cursorHidden) {
|
||||
cursor = xi + this.term.x;
|
||||
} else {
|
||||
cursor = -1;
|
||||
}
|
||||
|
||||
for (var x = Math.max(xi, 0); x < xl; x++) {
|
||||
if (!line[x] || !this.term.lines[scrollback + y - yi][x - xi]) break;
|
||||
|
||||
line[x][0] = this.term.lines[scrollback + y - yi][x - xi][0];
|
||||
|
||||
if (x === cursor) {
|
||||
if (this.cursor === 'line') {
|
||||
line[x][0] = this.dattr;
|
||||
line[x][1] = '\u2502';
|
||||
continue;
|
||||
} else if (this.cursor === 'underline') {
|
||||
line[x][0] = this.dattr | (2 << 18);
|
||||
} else if (this.cursor === 'block' || !this.cursor) {
|
||||
line[x][0] = this.dattr | (8 << 18);
|
||||
}
|
||||
}
|
||||
|
||||
line[x][1] = this.term.lines[scrollback + y - yi][x - xi][1];
|
||||
|
||||
// default foreground = 257
|
||||
if (((line[x][0] >> 9) & 0x1ff) === 257) {
|
||||
line[x][0] &= ~(0x1ff << 9);
|
||||
line[x][0] |= ((this.dattr >> 9) & 0x1ff) << 9;
|
||||
}
|
||||
|
||||
// default background = 256
|
||||
if ((line[x][0] & 0x1ff) === 256) {
|
||||
line[x][0] &= ~0x1ff;
|
||||
line[x][0] |= this.dattr & 0x1ff;
|
||||
}
|
||||
}
|
||||
|
||||
line.dirty = true;
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
Terminal.prototype._isMouse = function(buf) {
|
||||
var s = buf;
|
||||
if (Buffer.isBuffer(s)) {
|
||||
if (s[0] > 127 && s[1] === undefined) {
|
||||
s[0] -= 128;
|
||||
s = '\x1b' + s.toString('utf-8');
|
||||
} else {
|
||||
s = s.toString('utf-8');
|
||||
}
|
||||
}
|
||||
return (buf[0] === 0x1b && buf[1] === 0x5b && buf[2] === 0x4d)
|
||||
|| /^\x1b\[M([\x00\u0020-\uffff]{3})/.test(s)
|
||||
|| /^\x1b\[(\d+;\d+;\d+)M/.test(s)
|
||||
|| /^\x1b\[<(\d+;\d+;\d+)([mM])/.test(s)
|
||||
|| /^\x1b\[<(\d+;\d+;\d+;\d+)&w/.test(s)
|
||||
|| /^\x1b\[24([0135])~\[(\d+),(\d+)\]\r/.test(s)
|
||||
|| /^\x1b\[(O|I)/.test(s);
|
||||
};
|
||||
|
||||
Terminal.prototype.setScroll =
|
||||
Terminal.prototype.scrollTo = function(offset) {
|
||||
this.term.ydisp = offset;
|
||||
return this.emit('scroll');
|
||||
};
|
||||
|
||||
Terminal.prototype.getScroll = function() {
|
||||
return this.term.ydisp;
|
||||
};
|
||||
|
||||
Terminal.prototype.scroll = function(offset) {
|
||||
this.term.scrollDisp(offset);
|
||||
return this.emit('scroll');
|
||||
};
|
||||
|
||||
Terminal.prototype.resetScroll = function() {
|
||||
this.term.ydisp = 0;
|
||||
this.term.ybase = 0;
|
||||
return this.emit('scroll');
|
||||
};
|
||||
|
||||
Terminal.prototype.getScrollHeight = function() {
|
||||
return this.term.rows - 1;
|
||||
};
|
||||
|
||||
Terminal.prototype.getScrollPerc = function() {
|
||||
return (this.term.ydisp / this.term.ybase) * 100;
|
||||
};
|
||||
|
||||
Terminal.prototype.setScrollPerc = function(i) {
|
||||
return this.setScroll((i / 100) * this.term.ybase | 0);
|
||||
};
|
||||
|
||||
Terminal.prototype.screenshot = function(xi, xl, yi, yl) {
|
||||
xi = 0 + (xi || 0);
|
||||
if (xl != null) {
|
||||
xl = 0 + (xl || 0);
|
||||
} else {
|
||||
xl = this.term.lines[0].length;
|
||||
}
|
||||
yi = 0 + (yi || 0);
|
||||
if (yl != null) {
|
||||
yl = 0 + (yl || 0);
|
||||
} else {
|
||||
yl = this.term.lines.length;
|
||||
}
|
||||
return this.screen.screenshot(xi, xl, yi, yl, this.term);
|
||||
};
|
||||
|
||||
Terminal.prototype.kill = function() {
|
||||
if (this.pty) {
|
||||
this.pty.destroy();
|
||||
this.pty.kill();
|
||||
}
|
||||
this.term.refresh = function() {};
|
||||
this.term.write('\x1b[H\x1b[J');
|
||||
if (this.term._blink) {
|
||||
clearInterval(this.term._blink);
|
||||
}
|
||||
this.term.destroy();
|
||||
};
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = Terminal;
|
||||
35
lib/widgets/text.js
Normal file
@ -0,0 +1,35 @@
|
||||
/**
|
||||
* text.js - text element for blessed
|
||||
* Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Modules
|
||||
*/
|
||||
|
||||
var Node = require('./node');
|
||||
var Element = require('./element');
|
||||
|
||||
/**
|
||||
* Text
|
||||
*/
|
||||
|
||||
function Text(options) {
|
||||
if (!(this instanceof Node)) {
|
||||
return new Text(options);
|
||||
}
|
||||
options = options || {};
|
||||
options.shrink = true;
|
||||
Element.call(this, options);
|
||||
}
|
||||
|
||||
Text.prototype.__proto__ = Element.prototype;
|
||||
|
||||
Text.prototype.type = 'text';
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = Text;
|
||||
342
lib/widgets/textarea.js
Normal file
@ -0,0 +1,342 @@
|
||||
/**
|
||||
* textarea.js - textarea element for blessed
|
||||
* Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Modules
|
||||
*/
|
||||
|
||||
var unicode = require('../unicode');
|
||||
|
||||
var nextTick = global.setImmediate || process.nextTick.bind(process);
|
||||
|
||||
var Node = require('./node');
|
||||
var Input = require('./input');
|
||||
|
||||
/**
|
||||
* Textarea
|
||||
*/
|
||||
|
||||
function Textarea(options) {
|
||||
var self = this;
|
||||
|
||||
if (!(this instanceof Node)) {
|
||||
return new Textarea(options);
|
||||
}
|
||||
|
||||
options = options || {};
|
||||
|
||||
options.scrollable = options.scrollable !== false;
|
||||
|
||||
Input.call(this, options);
|
||||
|
||||
this.screen._listenKeys(this);
|
||||
|
||||
this.value = options.value || '';
|
||||
|
||||
this.__updateCursor = this._updateCursor.bind(this);
|
||||
this.on('resize', this.__updateCursor);
|
||||
this.on('move', this.__updateCursor);
|
||||
|
||||
if (options.inputOnFocus) {
|
||||
this.on('focus', this.readInput.bind(this, null));
|
||||
}
|
||||
|
||||
if (!options.inputOnFocus && options.keys) {
|
||||
this.on('keypress', function(ch, key) {
|
||||
if (self._reading) return;
|
||||
if (key.name === 'enter' || (options.vi && key.name === 'i')) {
|
||||
return self.readInput();
|
||||
}
|
||||
if (key.name === 'e') {
|
||||
return self.readEditor();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (options.mouse) {
|
||||
this.on('click', function(data) {
|
||||
if (self._reading) return;
|
||||
if (data.button !== 'right') return;
|
||||
self.readEditor();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Textarea.prototype.__proto__ = Input.prototype;
|
||||
|
||||
Textarea.prototype.type = 'textarea';
|
||||
|
||||
Textarea.prototype._updateCursor = function(get) {
|
||||
if (this.screen.focused !== this) {
|
||||
return;
|
||||
}
|
||||
|
||||
var lpos = get ? this.lpos : this._getCoords();
|
||||
if (!lpos) return;
|
||||
|
||||
var last = this._clines[this._clines.length - 1]
|
||||
, program = this.screen.program
|
||||
, line
|
||||
, cx
|
||||
, cy;
|
||||
|
||||
// Stop a situation where the textarea begins scrolling
|
||||
// and the last cline appears to always be empty from the
|
||||
// _typeScroll `+ '\n'` thing.
|
||||
// Maybe not necessary anymore?
|
||||
if (last === '' && this.value[this.value.length - 1] !== '\n') {
|
||||
last = this._clines[this._clines.length - 2] || '';
|
||||
}
|
||||
|
||||
line = Math.min(
|
||||
this._clines.length - 1 - (this.childBase || 0),
|
||||
(lpos.yl - lpos.yi) - this.iheight - 1);
|
||||
|
||||
// When calling clearValue() on a full textarea with a border, the first
|
||||
// argument in the above Math.min call ends up being -2. Make sure we stay
|
||||
// positive.
|
||||
line = Math.max(0, line);
|
||||
|
||||
cy = lpos.yi + this.itop + line;
|
||||
cx = lpos.xi + this.ileft + this.strWidth(last);
|
||||
|
||||
// XXX Not sure, but this may still sometimes
|
||||
// cause problems when leaving editor.
|
||||
if (cy === program.y && cx === program.x) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (cy === program.y) {
|
||||
if (cx > program.x) {
|
||||
program.cuf(cx - program.x);
|
||||
} else if (cx < program.x) {
|
||||
program.cub(program.x - cx);
|
||||
}
|
||||
} else if (cx === program.x) {
|
||||
if (cy > program.y) {
|
||||
program.cud(cy - program.y);
|
||||
} else if (cy < program.y) {
|
||||
program.cuu(program.y - cy);
|
||||
}
|
||||
} else {
|
||||
program.cup(cy, cx);
|
||||
}
|
||||
};
|
||||
|
||||
Textarea.prototype.input =
|
||||
Textarea.prototype.setInput =
|
||||
Textarea.prototype.readInput = function(callback) {
|
||||
var self = this
|
||||
, focused = this.screen.focused === this;
|
||||
|
||||
if (this._reading) return;
|
||||
this._reading = true;
|
||||
|
||||
this._callback = callback;
|
||||
|
||||
if (!focused) {
|
||||
this.screen.saveFocus();
|
||||
this.focus();
|
||||
}
|
||||
|
||||
this.screen.grabKeys = true;
|
||||
|
||||
this._updateCursor();
|
||||
this.screen.program.showCursor();
|
||||
//this.screen.program.sgr('normal');
|
||||
|
||||
this._done = function fn(err, value) {
|
||||
if (!self._reading) return;
|
||||
|
||||
if (fn.done) return;
|
||||
fn.done = true;
|
||||
|
||||
self._reading = false;
|
||||
|
||||
delete self._callback;
|
||||
delete self._done;
|
||||
|
||||
self.removeListener('keypress', self.__listener);
|
||||
delete self.__listener;
|
||||
|
||||
self.removeListener('blur', self.__done);
|
||||
delete self.__done;
|
||||
|
||||
self.screen.program.hideCursor();
|
||||
self.screen.grabKeys = false;
|
||||
|
||||
if (!focused) {
|
||||
self.screen.restoreFocus();
|
||||
}
|
||||
|
||||
if (self.options.inputOnFocus) {
|
||||
self.screen.rewindFocus();
|
||||
}
|
||||
|
||||
// Ugly
|
||||
if (err === 'stop') return;
|
||||
|
||||
if (err) {
|
||||
self.emit('error', err);
|
||||
} else if (value != null) {
|
||||
self.emit('submit', value);
|
||||
} else {
|
||||
self.emit('cancel', value);
|
||||
}
|
||||
self.emit('action', value);
|
||||
|
||||
if (!callback) return;
|
||||
|
||||
return err
|
||||
? callback(err)
|
||||
: callback(null, value);
|
||||
};
|
||||
|
||||
// Put this in a nextTick so the current
|
||||
// key event doesn't trigger any keys input.
|
||||
nextTick(function() {
|
||||
self.__listener = self._listener.bind(self);
|
||||
self.on('keypress', self.__listener);
|
||||
});
|
||||
|
||||
this.__done = this._done.bind(this, null, null);
|
||||
this.on('blur', this.__done);
|
||||
};
|
||||
|
||||
Textarea.prototype._listener = function(ch, key) {
|
||||
var done = this._done
|
||||
, value = this.value;
|
||||
|
||||
if (key.name === 'return') return;
|
||||
if (key.name === 'enter') {
|
||||
ch = '\n';
|
||||
}
|
||||
|
||||
// TODO: Handle directional keys.
|
||||
if (key.name === 'left' || key.name === 'right'
|
||||
|| key.name === 'up' || key.name === 'down') {
|
||||
;
|
||||
}
|
||||
|
||||
if (this.options.keys && key.ctrl && key.name === 'e') {
|
||||
return this.readEditor();
|
||||
}
|
||||
|
||||
// TODO: Optimize typing by writing directly
|
||||
// to the screen and screen buffer here.
|
||||
if (key.name === 'escape') {
|
||||
done(null, null);
|
||||
} else if (key.name === 'backspace') {
|
||||
if (this.value.length) {
|
||||
if (this.screen.fullUnicode) {
|
||||
if (unicode.isSurrogate(this.value, this.value.length - 2)) {
|
||||
// || unicode.isCombining(this.value, this.value.length - 1)) {
|
||||
this.value = this.value.slice(0, -2);
|
||||
} else {
|
||||
this.value = this.value.slice(0, -1);
|
||||
}
|
||||
} else {
|
||||
this.value = this.value.slice(0, -1);
|
||||
}
|
||||
}
|
||||
} else if (ch) {
|
||||
if (!/^[\x00-\x08\x0b-\x0c\x0e-\x1f\x7f]$/.test(ch)) {
|
||||
this.value += ch;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.value !== value) {
|
||||
this.screen.render();
|
||||
}
|
||||
};
|
||||
|
||||
Textarea.prototype._typeScroll = function() {
|
||||
// XXX Workaround
|
||||
var height = this.height - this.iheight;
|
||||
if (this._clines.length - this.childBase > height) {
|
||||
this.scroll(this._clines.length);
|
||||
}
|
||||
};
|
||||
|
||||
Textarea.prototype.getValue = function() {
|
||||
return this.value;
|
||||
};
|
||||
|
||||
Textarea.prototype.setValue = function(value) {
|
||||
if (value == null) {
|
||||
value = this.value;
|
||||
}
|
||||
if (this._value !== value) {
|
||||
this.value = value;
|
||||
this._value = value;
|
||||
this.setContent(this.value);
|
||||
this._typeScroll();
|
||||
this._updateCursor();
|
||||
}
|
||||
};
|
||||
|
||||
Textarea.prototype.clearInput =
|
||||
Textarea.prototype.clearValue = function() {
|
||||
return this.setValue('');
|
||||
};
|
||||
|
||||
Textarea.prototype.submit = function() {
|
||||
if (!this.__listener) return;
|
||||
return this.__listener('\x1b', { name: 'escape' });
|
||||
};
|
||||
|
||||
Textarea.prototype.cancel = function() {
|
||||
if (!this.__listener) return;
|
||||
return this.__listener('\x1b', { name: 'escape' });
|
||||
};
|
||||
|
||||
Textarea.prototype.render = function() {
|
||||
this.setValue();
|
||||
return this._render();
|
||||
};
|
||||
|
||||
Textarea.prototype.editor =
|
||||
Textarea.prototype.setEditor =
|
||||
Textarea.prototype.readEditor = function(callback) {
|
||||
var self = this;
|
||||
|
||||
if (this._reading) {
|
||||
var _cb = this._callback
|
||||
, cb = callback;
|
||||
|
||||
this._done('stop');
|
||||
|
||||
callback = function(err, value) {
|
||||
if (_cb) _cb(err, value);
|
||||
if (cb) cb(err, value);
|
||||
};
|
||||
}
|
||||
|
||||
if (!callback) {
|
||||
callback = function() {};
|
||||
}
|
||||
|
||||
return this.screen.readEditor({ value: this.value }, function(err, value) {
|
||||
if (err) {
|
||||
if (err.message === 'Unsuccessful.') {
|
||||
self.screen.render();
|
||||
return self.readInput(callback);
|
||||
}
|
||||
self.screen.render();
|
||||
self.readInput(callback);
|
||||
return callback(err);
|
||||
}
|
||||
self.setValue(value);
|
||||
self.screen.render();
|
||||
return self.readInput(callback);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = Textarea;
|
||||
77
lib/widgets/textbox.js
Normal file
@ -0,0 +1,77 @@
|
||||
/**
|
||||
* textbox.js - textbox element for blessed
|
||||
* Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Modules
|
||||
*/
|
||||
|
||||
var Node = require('./node');
|
||||
var Textarea = require('./textarea');
|
||||
|
||||
/**
|
||||
* Textbox
|
||||
*/
|
||||
|
||||
function Textbox(options) {
|
||||
if (!(this instanceof Node)) {
|
||||
return new Textbox(options);
|
||||
}
|
||||
|
||||
options = options || {};
|
||||
|
||||
options.scrollable = false;
|
||||
|
||||
Textarea.call(this, options);
|
||||
|
||||
this.secret = options.secret;
|
||||
this.censor = options.censor;
|
||||
}
|
||||
|
||||
Textbox.prototype.__proto__ = Textarea.prototype;
|
||||
|
||||
Textbox.prototype.type = 'textbox';
|
||||
|
||||
Textbox.prototype.__olistener = Textbox.prototype._listener;
|
||||
Textbox.prototype._listener = function(ch, key) {
|
||||
if (key.name === 'enter') {
|
||||
this._done(null, this.value);
|
||||
return;
|
||||
}
|
||||
return this.__olistener(ch, key);
|
||||
};
|
||||
|
||||
Textbox.prototype.setValue = function(value) {
|
||||
var visible, val;
|
||||
if (value == null) {
|
||||
value = this.value;
|
||||
}
|
||||
if (this._value !== value) {
|
||||
value = value.replace(/\n/g, '');
|
||||
this.value = value;
|
||||
this._value = value;
|
||||
if (this.secret) {
|
||||
this.setContent('');
|
||||
} else if (this.censor) {
|
||||
this.setContent(Array(this.value.length + 1).join('*'));
|
||||
} else {
|
||||
visible = -(this.width - this.iwidth - 1);
|
||||
val = this.value.replace(/\t/g, this.screen.tabc);
|
||||
this.setContent(val.slice(visible));
|
||||
}
|
||||
this._updateCursor();
|
||||
}
|
||||
};
|
||||
|
||||
Textbox.prototype.submit = function() {
|
||||
if (!this.__listener) return;
|
||||
return this.__listener('\r', { name: 'enter' });
|
||||
};
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = Textbox;
|
||||
126
lib/widgets/video.js
Normal file
@ -0,0 +1,126 @@
|
||||
/**
|
||||
* video.js - video element for blessed
|
||||
* Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Modules
|
||||
*/
|
||||
|
||||
var cp = require('child_process');
|
||||
|
||||
var Node = require('./node');
|
||||
var Box = require('./box');
|
||||
var Terminal = require('./terminal');
|
||||
|
||||
/**
|
||||
* Video
|
||||
*/
|
||||
|
||||
function Video(options) {
|
||||
var self = this
|
||||
, shell
|
||||
, args;
|
||||
|
||||
if (!(this instanceof Node)) {
|
||||
return new Video(options);
|
||||
}
|
||||
|
||||
options = options || {};
|
||||
|
||||
Box.call(this, options);
|
||||
|
||||
if (this.exists('mplayer')) {
|
||||
shell = 'mplayer';
|
||||
args = ['-vo', 'caca', '-quiet', options.file];
|
||||
} else if (this.exists('mpv')) {
|
||||
shell = 'mpv';
|
||||
args = ['--vo', 'caca', '--really-quiet', options.file];
|
||||
} else {
|
||||
this.parseTags = true;
|
||||
this.setContent('{red-fg}{bold}Error:{/bold}'
|
||||
+ ' mplayer or mpv not installed.{/red-fg}');
|
||||
return this;
|
||||
}
|
||||
|
||||
var opts = {
|
||||
parent: this,
|
||||
left: 0,
|
||||
top: 0,
|
||||
width: this.width - this.iwidth,
|
||||
height: this.height - this.iheight,
|
||||
shell: shell,
|
||||
args: args.slice()
|
||||
};
|
||||
|
||||
this.now = Date.now() / 1000 | 0;
|
||||
this.start = opts.start || 0;
|
||||
if (this.start) {
|
||||
if (shell === 'mplayer') {
|
||||
opts.args.unshift('-ss', this.start + '');
|
||||
} else if (shell === 'mpv') {
|
||||
opts.args.unshift('--start', this.start + '');
|
||||
}
|
||||
}
|
||||
|
||||
var DISPLAY = process.env.DISPLAY;
|
||||
delete process.env.DISPLAY;
|
||||
this.tty = new Terminal(opts);
|
||||
process.env.DISPLAY = DISPLAY;
|
||||
|
||||
this.on('click', function() {
|
||||
self.tty.pty.write('p');
|
||||
});
|
||||
|
||||
// mplayer/mpv cannot resize itself in the terminal, so we have
|
||||
// to restart it at the correct start time.
|
||||
this.on('resize', function() {
|
||||
self.tty.destroy();
|
||||
|
||||
var opts = {
|
||||
parent: self,
|
||||
left: 0,
|
||||
top: 0,
|
||||
width: self.width - self.iwidth,
|
||||
height: self.height - self.iheight,
|
||||
shell: shell,
|
||||
args: args.slice()
|
||||
};
|
||||
|
||||
var watched = (Date.now() / 1000 | 0) - self.now;
|
||||
self.now = Date.now() / 1000 | 0;
|
||||
self.start += watched;
|
||||
if (shell === 'mplayer') {
|
||||
opts.args.unshift('-ss', self.start + '');
|
||||
} else if (shell === 'mpv') {
|
||||
opts.args.unshift('--start', self.start + '');
|
||||
}
|
||||
|
||||
var DISPLAY = process.env.DISPLAY;
|
||||
delete process.env.DISPLAY;
|
||||
self.tty = new Terminal(opts);
|
||||
process.env.DISPLAY = DISPLAY;
|
||||
self.screen.render();
|
||||
});
|
||||
}
|
||||
|
||||
Video.prototype.__proto__ = Box.prototype;
|
||||
|
||||
Video.prototype.type = 'video';
|
||||
|
||||
Video.prototype.exists = function(program) {
|
||||
try {
|
||||
return !!+cp.execSync('type '
|
||||
+ program + ' > /dev/null 2> /dev/null'
|
||||
+ ' && echo 1', { encoding: 'utf8' }).trim();
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = Video;
|
||||
20
package.json
@ -1,13 +1,21 @@
|
||||
{
|
||||
"name": "blessed",
|
||||
"description": "A curses-like library for node.js.",
|
||||
"description": "A high-level terminal interface library for node.js.",
|
||||
"author": "Christopher Jeffrey",
|
||||
"version": "0.0.1",
|
||||
"main": "./lib/program.js",
|
||||
"version": "0.1.81",
|
||||
"license": "MIT",
|
||||
"main": "./lib/blessed.js",
|
||||
"bin": "./bin/tput.js",
|
||||
"preferGlobal": false,
|
||||
"repository": "git://github.com/chjj/blessed.git",
|
||||
"homepage": "https://github.com/chjj/blessed",
|
||||
"bugs": { "url": "http://github.com/chjj/blessed/issues" },
|
||||
"keywords": ["curses", "tui"],
|
||||
"tags": ["curses", "tui"],
|
||||
"scripts": { "test": "node test", "bench": "node test --bench" }
|
||||
"keywords": ["curses", "tui", "tput", "terminfo", "termcap"],
|
||||
"tags": ["curses", "tui", "tput", "terminfo", "termcap"],
|
||||
"engines": {
|
||||
"node": ">= 0.8.0"
|
||||
},
|
||||
"browserify": {
|
||||
"transform": ["./browser/transform.js"]
|
||||
}
|
||||
}
|
||||
|
||||
143
test/git.diff
Normal file
@ -0,0 +1,143 @@
|
||||
[1mdiff --git a/lib/widget.js b/lib/widget.js[m
|
||||
[1mindex 8785046..4bfefd3 100644[m
|
||||
[1m--- a/lib/widget.js[m
|
||||
[1m+++ b/lib/widget.js[m
|
||||
[36m@@ -511,6 +511,9 @@[m [mElement.prototype.__defineGetter__('left', function() {[m
|
||||
});[m
|
||||
[m
|
||||
Element.prototype.__defineGetter__('right', function() {[m
|
||||
[32m+[m[32m //if (this.options.right == null && this.options.left != null) {[m
|
||||
[32m+[m[32m // return this.screen.cols - (this.left + this.width);[m
|
||||
[32m+[m[32m //}[m
|
||||
return (this.parent.right || 0) + this.position.right;[m
|
||||
});[m
|
||||
[m
|
||||
[36m@@ -532,6 +535,9 @@[m [mElement.prototype.__defineGetter__('top', function() {[m
|
||||
});[m
|
||||
[m
|
||||
Element.prototype.__defineGetter__('bottom', function() {[m
|
||||
[32m+[m[32m //if (this.options.bottom == null && this.options.top != null) {[m
|
||||
[32m+[m[32m // return this.screen.rows - (this.top + this.height);[m
|
||||
[32m+[m[32m //}[m
|
||||
return (this.parent.bottom || 0) + this.position.bottom;[m
|
||||
});[m
|
||||
[m
|
||||
[36m@@ -671,7 +677,20 @@[m [mBox.prototype.render = function(stop) {[m
|
||||
var cb = this.childBase[m
|
||||
, xxl = xl - (this.border ? 1 : 0)[m
|
||||
, xxi;[m
|
||||
[31m- while (cb--) for (xxi = xi + (this.border ? 1 : 0); xxi < xxl; xxi++) ci++;[m
|
||||
[32m+[m[32m while (cb--) {[m
|
||||
[32m+[m[32m for (xxi = xi + (this.border ? 1 : 0); xxi < xxl; xxi++) {[m
|
||||
[32m+[m[32m if (this.content[ci] === '\n' || this.content[ci] === '\r') {[m
|
||||
[32m+[m[32m ci++;[m
|
||||
[32m+[m[32m if (!cb) break;[m
|
||||
[32m+[m[32m cb--;[m
|
||||
[32m+[m[32m } else if (this.content[ci] === '\x1b') {[m
|
||||
[32m+[m[32m for (; ci < this.content.length; ci++) {[m
|
||||
[32m+[m[32m if (this.content[ci] === 'm') break;[m
|
||||
[32m+[m[32m }[m
|
||||
[32m+[m[32m }[m
|
||||
[32m+[m[32m ci++;[m
|
||||
[32m+[m[32m }[m
|
||||
[32m+[m[32m }[m
|
||||
}[m
|
||||
[m
|
||||
var ret = {[m
|
||||
[36m@@ -683,6 +702,8 @@[m [mBox.prototype.render = function(stop) {[m
|
||||
[m
|
||||
if (stop) return ret;[m
|
||||
[m
|
||||
[32m+[m[32m var lastEscape, hasEscapes, c;[m
|
||||
[32m+[m
|
||||
for (; yi < yl; yi++) {[m
|
||||
if (!lines[yi]) break;[m
|
||||
for (xi = this.left; xi < xl; xi++) {[m
|
||||
[36m@@ -708,22 +729,52 @@[m [mBox.prototype.render = function(stop) {[m
|
||||
} else {[m
|
||||
attr = ((this.bold << 18) + (this.underline << 18)) | (this.fg << 9) | this.bg;[m
|
||||
ch = this.content[ci++] || ' ';[m
|
||||
[32m+[m
|
||||
[32m+[m[32m // Handle escape codes.[m
|
||||
[32m+[m[32m // NOTE: We could also change around `attr`, that might be cleaner.[m
|
||||
[32m+[m[32m // NOTE: Currently, this will not work with newline handling.[m
|
||||
[32m+[m[32m if (lastEscape) {[m
|
||||
[32m+[m[32m ch = lastEscape + ch;[m
|
||||
[32m+[m[32m lastEscape = '';[m
|
||||
[32m+[m[32m }[m
|
||||
[32m+[m[32m if (ch === '\x1b') {[m
|
||||
[32m+[m[32m hasEscapes = true;[m
|
||||
[32m+[m[32m if (c = /^\x1b\[\d+(?:;\d+)*m/.exec(this.content.substring(ci - 1))) {[m
|
||||
[32m+[m[32m ci += c[0].length - 1;[m
|
||||
[32m+[m[32m if (!this.content[c[0].length]) {[m
|
||||
[32m+[m[32m // Problem: No character to put here[m
|
||||
[32m+[m[32m // needs to wrap around below.[m
|
||||
[32m+[m[32m lastEscape = c[0];[m
|
||||
[32m+[m[32m ch = ' ';[m
|
||||
[32m+[m[32m } else {[m
|
||||
[32m+[m[32m ch = c[0] + this.content[ci];[m
|
||||
[32m+[m[32m }[m
|
||||
[32m+[m[32m ci++;[m
|
||||
[32m+[m[32m }[m
|
||||
[32m+[m[32m }[m
|
||||
[32m+[m[32m if (hasEscapes && xi === xl - 1) {[m
|
||||
[32m+[m[32m ch += '\x1b[m';[m
|
||||
[32m+[m[32m }[m
|
||||
}[m
|
||||
[m
|
||||
[31m- // TODO: Allow newlines.[m
|
||||
[31m- //if (ch === '\n' || ch === '\r') {[m
|
||||
[31m- // ch = ' ';[m
|
||||
[31m- // xl = xl - 1 - (this.border ? 1 : 0);[m
|
||||
[31m- // for (; xi < xl; xi++) {[m
|
||||
[31m- // cell = lines[yi][xi];[m
|
||||
[31m- // if (!cell) break;[m
|
||||
[31m- // if (attr !== cell[0] || ch !== cell[1]) {[m
|
||||
[31m- // lines[yi][xi][0] = attr;[m
|
||||
[31m- // lines[yi][xi][1] = ch;[m
|
||||
[31m- // lines[yi].dirty = true;[m
|
||||
[31m- // }[m
|
||||
[31m- // }[m
|
||||
[31m- //}[m
|
||||
[32m+[m[32m // Handle newlines.[m
|
||||
[32m+[m[32m if (ch === '\n' || ch === '\r') {[m
|
||||
[32m+[m[32m ch = ' ';[m
|
||||
[32m+[m[32m if (hasEscapes) ch += '\x1b[m';[m
|
||||
[32m+[m[32m var xxl = xl - (this.border ? 1 : 0);[m
|
||||
[32m+[m[32m for (; xi < xxl; xi++) {[m
|
||||
[32m+[m[32m attr = ((this.bold << 18) + (this.underline << 18)) | (this.fg << 9) | this.bg;[m
|
||||
[32m+[m[32m cell = lines[yi][xi];[m
|
||||
[32m+[m[32m if (!cell) break;[m
|
||||
[32m+[m[32m if (attr !== cell[0] || ch !== cell[1]) {[m
|
||||
[32m+[m[32m lines[yi][xi][0] = attr;[m
|
||||
[32m+[m[32m lines[yi][xi][1] = ch;[m
|
||||
[32m+[m[32m lines[yi].dirty = true;[m
|
||||
[32m+[m[32m }[m
|
||||
[32m+[m[32m }[m
|
||||
[32m+[m[32m if (this.border) xi--;[m
|
||||
[32m+[m[32m continue;[m
|
||||
[32m+[m[32m }[m
|
||||
[m
|
||||
if (attr !== cell[0] || ch !== cell[1]) {[m
|
||||
lines[yi][xi][0] = attr;[m
|
||||
[36m@@ -958,6 +1009,7 @@[m [mList.prototype.__proto__ = ScrollableBox.prototype;[m
|
||||
List.prototype.add = function(item) {[m
|
||||
var self = this;[m
|
||||
[m
|
||||
[32m+[m[32m // TODO: Use box here and get rid of text.[m
|
||||
var item = new Text({[m
|
||||
screen: this.screen,[m
|
||||
parent: this,[m
|
||||
[1mdiff --git a/test/widget.js b/test/widget.js[m
|
||||
[1mindex a392a0e..1e62e8c 100644[m
|
||||
[1m--- a/test/widget.js[m
|
||||
[1m+++ b/test/widget.js[m
|
||||
[36m@@ -136,7 +136,7 @@[m [mvar progress = new blessed.ProgressBar({[m
|
||||
[m
|
||||
screen.append(progress);[m
|
||||
[m
|
||||
[31m-var lorem = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.';[m
|
||||
[32m+[m[32mvar lorem = 'Lorem ipsum \x1b[41mdolor sit amet, \nconsectetur adipisicing elit, \x1b[43msed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.';[m
|
||||
[m
|
||||
var stext = new blessed.ScrollableText({[m
|
||||
screen: screen,[m
|
||||
5
test/helpers.js
Normal file
@ -0,0 +1,5 @@
|
||||
var blessed = require('../'),
|
||||
screen = blessed.screen();
|
||||
|
||||
console.log(blessed.helpers.parseTags('{red-fg}This should be red.{/red-fg}'));
|
||||
console.log(blessed.helpers.parseTags('{green-bg}This should have a green background.{/green-bg}'));
|
||||
1
test/logs/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
*
|
||||
1
test/lorem.txt
Normal file
@ -0,0 +1 @@
|
||||
Non eram nescius Brute cum quae summis ingeniis exquisitaque doctrina philosophi Graeco sermone tractavissent ea Latinis litteris mandaremus fore ut hic noster labor in varias reprehensiones incurreret nam quibusdam et iis quidem non admodum indoctis totum hoc displicet philosophari quidam autem non tam id reprehendunt si remissius agatur sed tantum studium tamque multam operam ponendam in eo non arbitrantur erunt etiam et ii quidem eruditi Graecis litteris contemnentes Latinas qui se dicant in Graecis legendis operam malle consumere postremo aliquos futuros suspicor qui me ad alias litteras vocent genus hoc scribendi etsi sit elegans personae tamen et dignitatis esse negent Contra quos omnis dicendum breviter existimo Quamquam philosophiae quidem vituperatoribus satis responsum est eo libro quo a nobis philosophia defensa et collaudata est cum esset accusata et vituperata ab Hortensio qui liber cum et tibi probatus videretur et iis quos ego posse iudicare arbitrarer plura suscepi veritus ne movere hominum studia viderer retinere non posse Qui autem si maxime hoc placeat moderatius tamen id volunt fieri difficilem quandam temperantiam postulant in eo quod semel admissum coerceri reprimique non potest ut propemodum iustioribus utamur illis qui omnino avocent a philosophia quam his qui rebus infinitis modum constituant in reque eo meliore quo maior sit mediocritatem desiderent Sive enim ad sapientiam perveniri potest non paranda nobis solum ea sed fruenda etiam sapientia est sive hoc difficile est tamen nec modus est ullus investigandi veri nisi inveneris et quaerendi defatigatio turpis est cum id quod quaeritur sit pulcherrimum etenim si delectamur cum scribimus quis est tam invidus qui ab eo nos abducat sin laboramus quis est qui alienae modum statuat industriae nam ut Terentianus Chremes non inhumanus qui novum vicinum non vult fodere aut arare aut aliquid ferre denique non enim illum ab industria sed ab inliberali labore deterret sic isti curiosi quos offendit noster minime nobis iniucundus labor Iis igitur est difficilius satis facere qui se Latina scripta dicunt contemnere in quibus hoc primum est in quo admirer cur in gravissimis rebus non delectet eos sermo patrius cum idem fabellas Latinas ad verbum e Graecis expressas non inviti legant quis enim tam inimicus paene nomini Romano est qui Ennii Medeam aut Antiopam Pacuvii spernat aut reiciat quod se isdem Euripidis fabulis delectari dicat Latinas litteras oderit Quid si nos non interpretum fungimur munere sed tuemur ea quae dicta sunt ab iis quos probamus eisque nostrum iudicium et nostrum scribendi ordinem adiungimus quid habent cur Graeca anteponant iis quae et splendide dicta sint neque sint conversa de Graecis nam si dicent ab illis has res esse tractatas ne ipsos quidem Graecos est cur tam multos legant quam legendi sunt quid enim est a Chrysippo praetermissum in Stoicis legimus tamen Diogenem Antipatrum Mnesarchum Panaetium multos alios in primisque familiarem nostrum Posidonium quid Theophrastus mediocriterne delectat cum tractat locos ab Aristotele ante tractatos quid Epicurei num desistunt de isdem de quibus et ab Epicuro scriptum est et ab antiquis ad arbitrium suum scribere quodsi Graeci leguntur a Graecis isdem de rebus alia ratione compositis quid est cur nostri a nostris non legantur
|
||||
80
test/program-mouse.js
Executable file
@ -0,0 +1,80 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
var blessed = require('../')
|
||||
, util = require('util')
|
||||
, program;
|
||||
|
||||
program = blessed.program({
|
||||
dump: __dirname + '/logs/mouse.log'
|
||||
});
|
||||
|
||||
// program.setMouse({
|
||||
// allMotion: true,
|
||||
// //utfMouse: true
|
||||
// urxvtMouse: true
|
||||
// }, true);
|
||||
|
||||
program.alternateBuffer();
|
||||
program.enableMouse();
|
||||
program.hideCursor();
|
||||
|
||||
program.setMouse({ sendFocus: true }, true);
|
||||
//program._currentMouse.sendFocus = true;
|
||||
//program.enableMouse(program._currentMouse);
|
||||
//program.write('\x1b[?1004h');
|
||||
|
||||
program.on('mouse', function(data) {
|
||||
program.cup(data.y, data.x);
|
||||
program.write(' ', 'blue bg');
|
||||
program.cup(0, 0);
|
||||
program.write(util.inspect(data));
|
||||
});
|
||||
|
||||
program.on('resize', function(data) {
|
||||
setTimeout(function() {
|
||||
program.clear();
|
||||
program.cup(0, 0);
|
||||
program.write(util.inspect({ cols: program.cols, rows: program.rows }));
|
||||
}, 200);
|
||||
});
|
||||
|
||||
process.on('SIGWINCH', function(data) {
|
||||
setTimeout(function() {
|
||||
program.cup(1, 0);
|
||||
program.write(util.inspect({ winch: true, cols: program.cols, rows: program.rows }));
|
||||
}, 200);
|
||||
});
|
||||
|
||||
program.on('focus', function(data) {
|
||||
program.clear();
|
||||
program.cup(0, 0);
|
||||
program.write('FOCUSIN');
|
||||
});
|
||||
|
||||
program.on('blur', function(data) {
|
||||
program.clear();
|
||||
program.cup(0, 0);
|
||||
program.write('FOCUSOUT');
|
||||
});
|
||||
|
||||
program.key(['q', 'escape', 'C-c'], function() {
|
||||
program.showCursor();
|
||||
program.disableMouse();
|
||||
program.normalBuffer();
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
program.on('keypress', function(ch, data) {
|
||||
if (data.name === 'mouse') return;
|
||||
program.clear();
|
||||
program.cup(0, 0);
|
||||
program.write(util.inspect(data));
|
||||
});
|
||||
|
||||
// program.getCursor(function(err, data) {
|
||||
// program.write(util.inspect(data));
|
||||
// });
|
||||
|
||||
// program.manipulateWindow(18, function(err, data) {
|
||||
// program.write(util.inspect(data));
|
||||
// });
|
||||
70
test/tail.js
Normal file
@ -0,0 +1,70 @@
|
||||
// `tail -f` a file.
|
||||
module.exports = function(file) {
|
||||
var self = this
|
||||
, fs = require('fs')
|
||||
, StringDecoder = require('string_decoder').StringDecoder
|
||||
, decode = new StringDecoder('utf8')
|
||||
, buffer = new Buffer(64 * 1024)
|
||||
, Stream = require('stream').Stream
|
||||
, s = new Stream
|
||||
, buff = ''
|
||||
, pos = 0;
|
||||
|
||||
s.readable = true;
|
||||
s.destroy = function() {
|
||||
s.destroyed = true;
|
||||
s.emit('end');
|
||||
s.emit('close');
|
||||
};
|
||||
|
||||
fs.open(file, 'a+', 0644, function(err, fd) {
|
||||
if (err) {
|
||||
s.emit('error', err);
|
||||
s.destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
(function read() {
|
||||
if (s.destroyed) {
|
||||
fs.close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
return fs.read(fd, buffer, 0, buffer.length, pos, function(err, bytes) {
|
||||
if (err) {
|
||||
s.emit('error', err);
|
||||
s.destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!bytes) {
|
||||
if (buff) {
|
||||
stream.emit('line', buff);
|
||||
buff = '';
|
||||
}
|
||||
return setTimeout(read, 1000);
|
||||
}
|
||||
|
||||
var data = decode.write(buffer.slice(0, bytes));
|
||||
|
||||
s.emit('data', data);
|
||||
|
||||
var data = (buff + data).split(/\n+/)
|
||||
, l = data.length - 1
|
||||
, i = 0;
|
||||
|
||||
for (; i < l; i++) {
|
||||
s.emit('line', data[i]);
|
||||
}
|
||||
|
||||
buff = data[l];
|
||||
|
||||
pos += bytes;
|
||||
|
||||
return read();
|
||||
});
|
||||
})();
|
||||
});
|
||||
|
||||
return s;
|
||||
};
|
||||
885
test/terminfo
Normal file
@ -0,0 +1,885 @@
|
||||
{ header:
|
||||
{ dataSize: 3337,
|
||||
headerSize: 12,
|
||||
magicNumber: 282,
|
||||
namesSize: 28,
|
||||
boolCount: 38,
|
||||
numCount: 15,
|
||||
strCount: 413,
|
||||
strTableSize: 1388,
|
||||
total: 2322,
|
||||
extended:
|
||||
{ dataSize: 1015,
|
||||
headerSize: 10,
|
||||
boolCount: 2,
|
||||
numCount: 0,
|
||||
strCount: 62,
|
||||
strTableSize: 126,
|
||||
lastStrTableOffset: 751,
|
||||
total: 262 } },
|
||||
name: 'xterm',
|
||||
names: [ 'xterm' ],
|
||||
desc: 'X11 terminal emulator',
|
||||
bools:
|
||||
{ auto_left_margin: false,
|
||||
auto_right_margin: true,
|
||||
no_esc_ctlc: false,
|
||||
ceol_standout_glitch: false,
|
||||
eat_newline_glitch: true,
|
||||
erase_overstrike: false,
|
||||
generic_type: false,
|
||||
hard_copy: false,
|
||||
has_meta_key: true,
|
||||
has_status_line: false,
|
||||
insert_null_glitch: false,
|
||||
memory_above: false,
|
||||
memory_below: false,
|
||||
move_insert_mode: true,
|
||||
move_standout_mode: true,
|
||||
over_strike: false,
|
||||
status_line_esc_ok: false,
|
||||
dest_tabs_magic_smso: false,
|
||||
tilde_glitch: false,
|
||||
transparent_underline: false,
|
||||
xon_xoff: false,
|
||||
needs_xon_xoff: false,
|
||||
prtr_silent: true,
|
||||
hard_cursor: false,
|
||||
non_rev_rmcup: false,
|
||||
no_pad_char: true,
|
||||
non_dest_scroll_region: false,
|
||||
can_change: false,
|
||||
back_color_erase: true,
|
||||
hue_lightness_saturation: false,
|
||||
col_addr_glitch: false,
|
||||
cr_cancels_micro_mode: false,
|
||||
has_print_wheel: false,
|
||||
row_addr_glitch: false,
|
||||
semi_auto_right_margin: false,
|
||||
cpi_changes_res: false,
|
||||
lpi_changes_res: false,
|
||||
backspaces_with_bs: true,
|
||||
AX: true,
|
||||
XT: true },
|
||||
numbers:
|
||||
{ columns: 80,
|
||||
init_tabs: 8,
|
||||
lines: 24,
|
||||
lines_of_memory: -1,
|
||||
magic_cookie_glitch: -1,
|
||||
padding_baud_rate: -1,
|
||||
virtual_terminal: -1,
|
||||
width_status_line: -1,
|
||||
num_labels: -1,
|
||||
label_height: -1,
|
||||
label_width: -1,
|
||||
max_attributes: -1,
|
||||
maximum_windows: -1,
|
||||
max_colors: 8,
|
||||
max_pairs: 64 },
|
||||
strings:
|
||||
{ back_tab: '\u001b[Z',
|
||||
bell: '\u0007',
|
||||
carriage_return: '\r',
|
||||
change_scroll_region: '\u001b[%i%p1%d;%p2%dr',
|
||||
clear_all_tabs: '\u001b[3g',
|
||||
clear_screen: '\u001b[H\u001b[2J',
|
||||
clr_eol: '\u001b[K',
|
||||
clr_eos: '\u001b[J',
|
||||
column_address: '\u001b[%i%p1%dG',
|
||||
cursor_address: '\u001b[%i%p1%d;%p2%dH',
|
||||
cursor_down: '\n',
|
||||
cursor_home: '\u001b[H',
|
||||
cursor_invisible: '\u001b[?25l',
|
||||
cursor_left: '\b',
|
||||
cursor_normal: '\u001b[?12l\u001b[?25h',
|
||||
cursor_right: '\u001b[C',
|
||||
cursor_up: '\u001b[A',
|
||||
cursor_visible: '\u001b[?12;25h',
|
||||
delete_character: '\u001b[P',
|
||||
delete_line: '\u001b[M',
|
||||
enter_alt_charset_mode: '\u001b(0',
|
||||
enter_blink_mode: '\u001b[5m',
|
||||
enter_bold_mode: '\u001b[1m',
|
||||
enter_ca_mode: '\u001b[?1049h',
|
||||
enter_insert_mode: '\u001b[4h',
|
||||
enter_secure_mode: '\u001b[8m',
|
||||
enter_reverse_mode: '\u001b[7m',
|
||||
enter_standout_mode: '\u001b[7m',
|
||||
enter_underline_mode: '\u001b[4m',
|
||||
erase_chars: '\u001b[%p1%dX',
|
||||
exit_alt_charset_mode: '\u001b(B',
|
||||
exit_attribute_mode: '\u001b(B\u001b[m',
|
||||
exit_ca_mode: '\u001b[?1049l',
|
||||
exit_insert_mode: '\u001b[4l',
|
||||
exit_standout_mode: '\u001b[27m',
|
||||
exit_underline_mode: '\u001b[24m',
|
||||
flash_screen: '\u001b[?5h$<100/>\u001b[?5l',
|
||||
init_2string: '\u001b[!p\u001b[?3;4l\u001b[4l\u001b>',
|
||||
insert_line: '\u001b[L',
|
||||
key_backspace: '\b',
|
||||
key_dc: '\u001b[3~',
|
||||
key_down: '\u001bOB',
|
||||
key_f1: '\u001bOP',
|
||||
key_f10: '\u001b[21~',
|
||||
key_f2: '\u001bOQ',
|
||||
key_f3: '\u001bOR',
|
||||
key_f4: '\u001bOS',
|
||||
key_f5: '\u001b[15~',
|
||||
key_f6: '\u001b[17~',
|
||||
key_f7: '\u001b[18~',
|
||||
key_f8: '\u001b[19~',
|
||||
key_f9: '\u001b[20~',
|
||||
key_home: '\u001bOH',
|
||||
key_ic: '\u001b[2~',
|
||||
key_left: '\u001bOD',
|
||||
key_npage: '\u001b[6~',
|
||||
key_ppage: '\u001b[5~',
|
||||
key_right: '\u001bOC',
|
||||
key_sf: '\u001b[1;2B',
|
||||
key_sr: '\u001b[1;2A',
|
||||
key_up: '\u001bOA',
|
||||
keypad_local: '\u001b[?1l\u001b>',
|
||||
keypad_xmit: '\u001b[?1h\u001b=',
|
||||
meta_off: '\u001b[?1034l',
|
||||
meta_on: '\u001b[?1034h',
|
||||
parm_dch: '\u001b[%p1%dP',
|
||||
parm_delete_line: '\u001b[%p1%dM',
|
||||
parm_down_cursor: '\u001b[%p1%dB',
|
||||
parm_ich: '\u001b[%p1%d@',
|
||||
parm_index: '\u001b[%p1%dS',
|
||||
parm_insert_line: '\u001b[%p1%dL',
|
||||
parm_left_cursor: '\u001b[%p1%dD',
|
||||
parm_right_cursor: '\u001b[%p1%dC',
|
||||
parm_rindex: '\u001b[%p1%dT',
|
||||
parm_up_cursor: '\u001b[%p1%dA',
|
||||
print_screen: '\u001b[i',
|
||||
prtr_off: '\u001b[4i',
|
||||
prtr_on: '\u001b[5i',
|
||||
reset_1string: '\u001bc',
|
||||
reset_2string: '\u001b[!p\u001b[?3;4l\u001b[4l\u001b>',
|
||||
restore_cursor: '\u001b8',
|
||||
row_address: '\u001b[%i%p1%dd',
|
||||
save_cursor: '\u001b7',
|
||||
scroll_forward: '\n',
|
||||
scroll_reverse: '\u001bM',
|
||||
set_attributes: '%?%p9%t\u001b(0%e\u001b(B%;\u001b[0%?%p6%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;%?%p7%t;8%;m',
|
||||
set_tab: '\u001bH',
|
||||
tab: '\t',
|
||||
key_b2: '\u001bOE',
|
||||
acs_chars: '``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~',
|
||||
key_btab: '\u001b[Z',
|
||||
enter_am_mode: '\u001b[?7h',
|
||||
exit_am_mode: '\u001b[?7l',
|
||||
key_end: '\u001bOF',
|
||||
key_enter: '\u001bOM',
|
||||
key_sdc: '\u001b[3;2~',
|
||||
key_send: '\u001b[1;2F',
|
||||
key_shome: '\u001b[1;2H',
|
||||
key_sic: '\u001b[2;2~',
|
||||
key_sleft: '\u001b[1;2D',
|
||||
key_snext: '\u001b[6;2~',
|
||||
key_sprevious: '\u001b[5;2~',
|
||||
key_sright: '\u001b[1;2C',
|
||||
key_f11: '\u001b[23~',
|
||||
key_f12: '\u001b[24~',
|
||||
key_f13: '\u001b[1;2P',
|
||||
key_f14: '\u001b[1;2Q',
|
||||
key_f15: '\u001b[1;2R',
|
||||
key_f16: '\u001b[1;2S',
|
||||
key_f17: '\u001b[15;2~',
|
||||
key_f18: '\u001b[17;2~',
|
||||
key_f19: '\u001b[18;2~',
|
||||
key_f20: '\u001b[19;2~',
|
||||
key_f21: '\u001b[20;2~',
|
||||
key_f22: '\u001b[21;2~',
|
||||
key_f23: '\u001b[23;2~',
|
||||
key_f24: '\u001b[24;2~',
|
||||
key_f25: '\u001b[1;5P',
|
||||
key_f26: '\u001b[1;5Q',
|
||||
key_f27: '\u001b[1;5R',
|
||||
key_f28: '\u001b[1;5S',
|
||||
key_f29: '\u001b[15;5~',
|
||||
key_f30: '\u001b[17;5~',
|
||||
key_f31: '\u001b[18;5~',
|
||||
key_f32: '\u001b[19;5~',
|
||||
key_f33: '\u001b[20;5~',
|
||||
key_f34: '\u001b[21;5~',
|
||||
key_f35: '\u001b[23;5~',
|
||||
key_f36: '\u001b[24;5~',
|
||||
key_f37: '\u001b[1;6P',
|
||||
key_f38: '\u001b[1;6Q',
|
||||
key_f39: '\u001b[1;6R',
|
||||
key_f40: '\u001b[1;6S',
|
||||
key_f41: '\u001b[15;6~',
|
||||
key_f42: '\u001b[17;6~',
|
||||
key_f43: '\u001b[18;6~',
|
||||
key_f44: '\u001b[19;6~',
|
||||
key_f45: '\u001b[20;6~',
|
||||
key_f46: '\u001b[21;6~',
|
||||
key_f47: '\u001b[23;6~',
|
||||
key_f48: '\u001b[24;6~',
|
||||
key_f49: '\u001b[1;3P',
|
||||
key_f50: '\u001b[1;3Q',
|
||||
key_f51: '\u001b[1;3R',
|
||||
key_f52: '\u001b[1;3S',
|
||||
key_f53: '\u001b[15;3~',
|
||||
key_f54: '\u001b[17;3~',
|
||||
key_f55: '\u001b[18;3~',
|
||||
key_f56: '\u001b[19;3~',
|
||||
key_f57: '\u001b[20;3~',
|
||||
key_f58: '\u001b[21;3~',
|
||||
key_f59: '\u001b[23;3~',
|
||||
key_f60: '\u001b[24;3~',
|
||||
key_f61: '\u001b[1;4P',
|
||||
key_f62: '\u001b[1;4Q',
|
||||
key_f63: '\u001b[1;4R',
|
||||
clr_bol: '\u001b[1K',
|
||||
user6: '\u001b[%i%d;%dR',
|
||||
user7: '\u001b[6n',
|
||||
user8: '\u001b[?1;2c',
|
||||
user9: '\u001b[c',
|
||||
orig_pair: '\u001b[39;49m',
|
||||
set_foreground: '\u001b[3%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m',
|
||||
set_background: '\u001b[4%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m',
|
||||
key_mouse: '\u001b[M',
|
||||
set_a_foreground: '\u001b[3%p1%dm',
|
||||
set_a_background: '\u001b[4%p1%dm',
|
||||
memory_lock: '\u001bl',
|
||||
memory_unlock: '\u001bm',
|
||||
Cr: '\u001b]112\u0007',
|
||||
Cs: '\u001b]12;%p1%s\u0007',
|
||||
E3: '\u001b[3;J',
|
||||
Ms: '\u001b]52;%p1%s;%p2%s\u0007',
|
||||
Se: '\u001b[2 q',
|
||||
Ss: '\u001b[%p1%d q',
|
||||
kDC3: '\u001b[3;3~',
|
||||
kDC4: '\u001b[3;4~',
|
||||
kDC5: '\u001b[3;5~',
|
||||
kDC6: '\u001b[3;6~',
|
||||
kDC7: '\u001b[3;7~',
|
||||
kDN: '\u001b[1;2B',
|
||||
kDN3: '\u001b[1;3B',
|
||||
kDN4: '\u001b[1;4B',
|
||||
kDN5: '\u001b[1;5B',
|
||||
kDN6: '\u001b[1;6B',
|
||||
kDN7: '\u001b[1;7B',
|
||||
kEND3: '\u001b[1;3F',
|
||||
kEND4: '\u001b[1;4F',
|
||||
kEND5: '\u001b[1;5F',
|
||||
kEND6: '\u001b[1;6F',
|
||||
kEND7: '\u001b[1;7F',
|
||||
kHOM3: '\u001b[1;3H',
|
||||
kHOM4: '\u001b[1;4H',
|
||||
kHOM5: '\u001b[1;5H',
|
||||
kHOM6: '\u001b[1;6H',
|
||||
kHOM7: '\u001b[1;7H',
|
||||
kIC3: '\u001b[2;3~',
|
||||
kIC4: '\u001b[2;4~',
|
||||
kIC5: '\u001b[2;5~',
|
||||
kIC6: '\u001b[2;6~',
|
||||
kIC7: '\u001b[2;7~',
|
||||
kLFT3: '\u001b[1;3D',
|
||||
kLFT4: '\u001b[1;4D',
|
||||
kLFT5: '\u001b[1;5D',
|
||||
kLFT6: '\u001b[1;6D',
|
||||
kLFT7: '\u001b[1;7D',
|
||||
kNXT3: '\u001b[6;3~',
|
||||
kNXT4: '\u001b[6;4~',
|
||||
kNXT5: '\u001b[6;5~',
|
||||
kNXT6: '\u001b[6;6~',
|
||||
kNXT7: '\u001b[6;7~',
|
||||
kPRV3: '\u001b[5;3~',
|
||||
kPRV4: '\u001b[5;4~',
|
||||
kPRV5: '\u001b[5;5~',
|
||||
kPRV6: '\u001b[5;6~',
|
||||
kPRV7: '\u001b[5;7~',
|
||||
kRIT3: '\u001b[1;3C',
|
||||
kRIT4: '\u001b[1;4C',
|
||||
kRIT5: '\u001b[1;5C',
|
||||
kRIT6: '\u001b[1;6C',
|
||||
kRIT7: '\u001b[1;7C',
|
||||
kUP: '\u001b[1;2A',
|
||||
kUP3: '\u001b[1;3A',
|
||||
kUP4: '\u001b[1;4A',
|
||||
kUP5: '\u001b[1;5A',
|
||||
kUP6: '\u001b[1;6A',
|
||||
kUP7: '\u001b[1;7A',
|
||||
ka2: '',
|
||||
kb1: '',
|
||||
kb3: '',
|
||||
kc2: '' },
|
||||
features:
|
||||
{ unicode: true,
|
||||
brokenACS: false,
|
||||
PCRomSet: false,
|
||||
magicCookie: true,
|
||||
padding: true,
|
||||
setbuf: true,
|
||||
acsc:
|
||||
{ '`': '◆',
|
||||
a: '▒',
|
||||
f: '°',
|
||||
g: '±',
|
||||
i: '\u000b',
|
||||
j: '┘',
|
||||
k: '┐',
|
||||
l: '┌',
|
||||
m: '└',
|
||||
n: '┼',
|
||||
o: '⎺',
|
||||
p: '⎻',
|
||||
q: '─',
|
||||
r: '⎼',
|
||||
s: '⎽',
|
||||
t: '├',
|
||||
u: '┤',
|
||||
v: '┴',
|
||||
w: '┬',
|
||||
x: '│',
|
||||
y: '≤',
|
||||
z: '≥',
|
||||
'{': 'π',
|
||||
'|': '≠',
|
||||
'}': '£',
|
||||
'~': '·' },
|
||||
acscr:
|
||||
{ '◆': '`',
|
||||
'▒': 'a',
|
||||
'°': 'f',
|
||||
'±': 'g',
|
||||
'\u000b': 'i',
|
||||
'┘': 'j',
|
||||
'┐': 'k',
|
||||
'┌': 'l',
|
||||
'└': 'm',
|
||||
'┼': 'n',
|
||||
'⎺': 'o',
|
||||
'⎻': 'p',
|
||||
'─': 'q',
|
||||
'⎼': 'r',
|
||||
'⎽': 's',
|
||||
'├': 't',
|
||||
'┤': 'u',
|
||||
'┴': 'v',
|
||||
'┬': 'w',
|
||||
'│': 'x',
|
||||
'≤': 'y',
|
||||
'≥': 'z',
|
||||
'π': '{',
|
||||
'≠': '|',
|
||||
'£': '}',
|
||||
'·': '~' } } }
|
||||
Compiling auto_left_margin: false
|
||||
Compiling auto_right_margin: true
|
||||
Compiling no_esc_ctlc: false
|
||||
Compiling ceol_standout_glitch: false
|
||||
Compiling eat_newline_glitch: true
|
||||
Compiling erase_overstrike: false
|
||||
Compiling generic_type: false
|
||||
Compiling hard_copy: false
|
||||
Compiling has_meta_key: true
|
||||
Compiling has_status_line: false
|
||||
Compiling insert_null_glitch: false
|
||||
Compiling memory_above: false
|
||||
Compiling memory_below: false
|
||||
Compiling move_insert_mode: true
|
||||
Compiling move_standout_mode: true
|
||||
Compiling over_strike: false
|
||||
Compiling status_line_esc_ok: false
|
||||
Compiling dest_tabs_magic_smso: false
|
||||
Compiling tilde_glitch: false
|
||||
Compiling transparent_underline: false
|
||||
Compiling xon_xoff: false
|
||||
Compiling needs_xon_xoff: false
|
||||
Compiling prtr_silent: true
|
||||
Compiling hard_cursor: false
|
||||
Compiling non_rev_rmcup: false
|
||||
Compiling no_pad_char: true
|
||||
Compiling non_dest_scroll_region: false
|
||||
Compiling can_change: false
|
||||
Compiling back_color_erase: true
|
||||
Compiling hue_lightness_saturation: false
|
||||
Compiling col_addr_glitch: false
|
||||
Compiling cr_cancels_micro_mode: false
|
||||
Compiling has_print_wheel: false
|
||||
Compiling row_addr_glitch: false
|
||||
Compiling semi_auto_right_margin: false
|
||||
Compiling cpi_changes_res: false
|
||||
Compiling lpi_changes_res: false
|
||||
Compiling backspaces_with_bs: true
|
||||
Compiling AX: true
|
||||
Compiling XT: true
|
||||
Compiling columns: 80
|
||||
Compiling init_tabs: 8
|
||||
Compiling lines: 24
|
||||
Compiling lines_of_memory: -1
|
||||
Compiling magic_cookie_glitch: -1
|
||||
Compiling padding_baud_rate: -1
|
||||
Compiling virtual_terminal: -1
|
||||
Compiling width_status_line: -1
|
||||
Compiling num_labels: -1
|
||||
Compiling label_height: -1
|
||||
Compiling label_width: -1
|
||||
Compiling max_attributes: -1
|
||||
Compiling maximum_windows: -1
|
||||
Compiling max_colors: 8
|
||||
Compiling max_pairs: 64
|
||||
Compiling back_tab: "\u001b[Z"
|
||||
return "\x1b[Z";
|
||||
Compiling bell: "\u0007"
|
||||
return "\x07";
|
||||
Compiling carriage_return: "\r"
|
||||
return "\r";
|
||||
Compiling change_scroll_region: "\u001b[%i%p1%d;%p2%dr"
|
||||
var out = ["\x1b["];(params[0]++, params[1]++),out.push(params[0]),out.push(";"),out.push(params[1]),out.push("r");return out.join("");
|
||||
Compiling clear_all_tabs: "\u001b[3g"
|
||||
return "\x1b[3g";
|
||||
Compiling clear_screen: "\u001b[H\u001b[2J"
|
||||
return "\x1b[H\x1b[2J";
|
||||
Compiling clr_eol: "\u001b[K"
|
||||
return "\x1b[K";
|
||||
Compiling clr_eos: "\u001b[J"
|
||||
return "\x1b[J";
|
||||
Compiling column_address: "\u001b[%i%p1%dG"
|
||||
var out = ["\x1b["];(params[0]++, params[1]++),out.push(params[0]),out.push("G");return out.join("");
|
||||
Compiling cursor_address: "\u001b[%i%p1%d;%p2%dH"
|
||||
var out = ["\x1b["];(params[0]++, params[1]++),out.push(params[0]),out.push(";"),out.push(params[1]),out.push("H");return out.join("");
|
||||
Compiling cursor_down: "\n"
|
||||
return "\n";
|
||||
Compiling cursor_home: "\u001b[H"
|
||||
return "\x1b[H";
|
||||
Compiling cursor_invisible: "\u001b[?25l"
|
||||
return "\x1b[?25l";
|
||||
Compiling cursor_left: "\b"
|
||||
return "\b";
|
||||
Compiling cursor_normal: "\u001b[?12l\u001b[?25h"
|
||||
return "\x1b[?12l\x1b[?25h";
|
||||
Compiling cursor_right: "\u001b[C"
|
||||
return "\x1b[C";
|
||||
Compiling cursor_up: "\u001b[A"
|
||||
return "\x1b[A";
|
||||
Compiling cursor_visible: "\u001b[?12;25h"
|
||||
return "\x1b[?12;25h";
|
||||
Compiling delete_character: "\u001b[P"
|
||||
return "\x1b[P";
|
||||
Compiling delete_line: "\u001b[M"
|
||||
return "\x1b[M";
|
||||
Compiling enter_alt_charset_mode: "\u001b(0"
|
||||
return "\x1b(0";
|
||||
Compiling enter_blink_mode: "\u001b[5m"
|
||||
return "\x1b[5m";
|
||||
Compiling enter_bold_mode: "\u001b[1m"
|
||||
return "\x1b[1m";
|
||||
Compiling enter_ca_mode: "\u001b[?1049h"
|
||||
return "\x1b[?1049h";
|
||||
Compiling enter_insert_mode: "\u001b[4h"
|
||||
return "\x1b[4h";
|
||||
Compiling enter_secure_mode: "\u001b[8m"
|
||||
return "\x1b[8m";
|
||||
Compiling enter_reverse_mode: "\u001b[7m"
|
||||
return "\x1b[7m";
|
||||
Compiling enter_standout_mode: "\u001b[7m"
|
||||
return "\x1b[7m";
|
||||
Compiling enter_underline_mode: "\u001b[4m"
|
||||
return "\x1b[4m";
|
||||
Compiling erase_chars: "\u001b[%p1%dX"
|
||||
var out = ["\x1b["];out.push(params[0]),out.push("X");return out.join("");
|
||||
Compiling exit_alt_charset_mode: "\u001b(B"
|
||||
return "\x1b(B";
|
||||
Compiling exit_attribute_mode: "\u001b(B\u001b[m"
|
||||
return "\x1b(B\x1b[m";
|
||||
Compiling exit_ca_mode: "\u001b[?1049l"
|
||||
return "\x1b[?1049l";
|
||||
Compiling exit_insert_mode: "\u001b[4l"
|
||||
return "\x1b[4l";
|
||||
Compiling exit_standout_mode: "\u001b[27m"
|
||||
return "\x1b[27m";
|
||||
Compiling exit_underline_mode: "\u001b[24m"
|
||||
return "\x1b[24m";
|
||||
Compiling flash_screen: "\u001b[?5h$<100/>\u001b[?5l"
|
||||
return "\x1b[?5h\x1b[?5l";
|
||||
Compiling init_2string: "\u001b[!p\u001b[?3;4l\u001b[4l\u001b>"
|
||||
return "\x1b[!p\x1b[?3;4l\x1b[4l\x1b>";
|
||||
Compiling insert_line: "\u001b[L"
|
||||
return "\x1b[L";
|
||||
Compiling key_backspace: "\b"
|
||||
return "\b";
|
||||
Compiling key_dc: "\u001b[3~"
|
||||
return "\x1b[3~";
|
||||
Compiling key_down: "\u001bOB"
|
||||
return "\x1bOB";
|
||||
Compiling key_f1: "\u001bOP"
|
||||
return "\x1bOP";
|
||||
Compiling key_f10: "\u001b[21~"
|
||||
return "\x1b[21~";
|
||||
Compiling key_f2: "\u001bOQ"
|
||||
return "\x1bOQ";
|
||||
Compiling key_f3: "\u001bOR"
|
||||
return "\x1bOR";
|
||||
Compiling key_f4: "\u001bOS"
|
||||
return "\x1bOS";
|
||||
Compiling key_f5: "\u001b[15~"
|
||||
return "\x1b[15~";
|
||||
Compiling key_f6: "\u001b[17~"
|
||||
return "\x1b[17~";
|
||||
Compiling key_f7: "\u001b[18~"
|
||||
return "\x1b[18~";
|
||||
Compiling key_f8: "\u001b[19~"
|
||||
return "\x1b[19~";
|
||||
Compiling key_f9: "\u001b[20~"
|
||||
return "\x1b[20~";
|
||||
Compiling key_home: "\u001bOH"
|
||||
return "\x1bOH";
|
||||
Compiling key_ic: "\u001b[2~"
|
||||
return "\x1b[2~";
|
||||
Compiling key_left: "\u001bOD"
|
||||
return "\x1bOD";
|
||||
Compiling key_npage: "\u001b[6~"
|
||||
return "\x1b[6~";
|
||||
Compiling key_ppage: "\u001b[5~"
|
||||
return "\x1b[5~";
|
||||
Compiling key_right: "\u001bOC"
|
||||
return "\x1bOC";
|
||||
Compiling key_sf: "\u001b[1;2B"
|
||||
return "\x1b[1;2B";
|
||||
Compiling key_sr: "\u001b[1;2A"
|
||||
return "\x1b[1;2A";
|
||||
Compiling key_up: "\u001bOA"
|
||||
return "\x1bOA";
|
||||
Compiling keypad_local: "\u001b[?1l\u001b>"
|
||||
return "\x1b[?1l\x1b>";
|
||||
Compiling keypad_xmit: "\u001b[?1h\u001b="
|
||||
return "\x1b[?1h\x1b=";
|
||||
Compiling meta_off: "\u001b[?1034l"
|
||||
return "\x1b[?1034l";
|
||||
Compiling meta_on: "\u001b[?1034h"
|
||||
return "\x1b[?1034h";
|
||||
Compiling parm_dch: "\u001b[%p1%dP"
|
||||
var out = ["\x1b["];out.push(params[0]),out.push("P");return out.join("");
|
||||
Compiling parm_delete_line: "\u001b[%p1%dM"
|
||||
var out = ["\x1b["];out.push(params[0]),out.push("M");return out.join("");
|
||||
Compiling parm_down_cursor: "\u001b[%p1%dB"
|
||||
var out = ["\x1b["];out.push(params[0]),out.push("B");return out.join("");
|
||||
Compiling parm_ich: "\u001b[%p1%d@"
|
||||
var out = ["\x1b["];out.push(params[0]),out.push("@");return out.join("");
|
||||
Compiling parm_index: "\u001b[%p1%dS"
|
||||
var out = ["\x1b["];out.push(params[0]),out.push("S");return out.join("");
|
||||
Compiling parm_insert_line: "\u001b[%p1%dL"
|
||||
var out = ["\x1b["];out.push(params[0]),out.push("L");return out.join("");
|
||||
Compiling parm_left_cursor: "\u001b[%p1%dD"
|
||||
var out = ["\x1b["];out.push(params[0]),out.push("D");return out.join("");
|
||||
Compiling parm_right_cursor: "\u001b[%p1%dC"
|
||||
var out = ["\x1b["];out.push(params[0]),out.push("C");return out.join("");
|
||||
Compiling parm_rindex: "\u001b[%p1%dT"
|
||||
var out = ["\x1b["];out.push(params[0]),out.push("T");return out.join("");
|
||||
Compiling parm_up_cursor: "\u001b[%p1%dA"
|
||||
var out = ["\x1b["];out.push(params[0]),out.push("A");return out.join("");
|
||||
Compiling print_screen: "\u001b[i"
|
||||
return "\x1b[i";
|
||||
Compiling prtr_off: "\u001b[4i"
|
||||
return "\x1b[4i";
|
||||
Compiling prtr_on: "\u001b[5i"
|
||||
return "\x1b[5i";
|
||||
Compiling reset_1string: "\u001bc"
|
||||
return "\x1bc";
|
||||
Compiling reset_2string: "\u001b[!p\u001b[?3;4l\u001b[4l\u001b>"
|
||||
return "\x1b[!p\x1b[?3;4l\x1b[4l\x1b>";
|
||||
Compiling restore_cursor: "\u001b8"
|
||||
return "\x1b8";
|
||||
Compiling row_address: "\u001b[%i%p1%dd"
|
||||
var out = ["\x1b["];(params[0]++, params[1]++),out.push(params[0]),out.push("d");return out.join("");
|
||||
Compiling save_cursor: "\u001b7"
|
||||
return "\x1b7";
|
||||
Compiling scroll_forward: "\n"
|
||||
return "\n";
|
||||
Compiling scroll_reverse: "\u001bM"
|
||||
return "\x1bM";
|
||||
Compiling set_attributes: "%?%p9%t\u001b(0%e\u001b(B%;\u001b[0%?%p6%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;%?%p7%t;8%;m"
|
||||
var v, stack = [], out = [];;if ((stack.push(v = params[8]), v)) {out.push("\x1b(0")} else {out.push("\x1b(B")}out.push("\x1b[0");if ((stack.push(v = params[5]), v)) {out.push(";1")};if ((stack.push(v = params[1]), v)) {out.push(";4")};if ((stack.push(v = params[0]), v),(stack.push(v = params[2]), v),(stack.push(v = (stack.pop() | stack.pop()) || 0), v)) {out.push(";7")};if ((stack.push(v = params[3]), v)) {out.push(";5")};if ((stack.push(v = params[6]), v)) {out.push(";8")}out.push("m");return out.join("");
|
||||
Compiling set_tab: "\u001bH"
|
||||
return "\x1bH";
|
||||
Compiling tab: "\t"
|
||||
return "\t";
|
||||
Compiling key_b2: "\u001bOE"
|
||||
return "\x1bOE";
|
||||
Compiling acs_chars: "``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~"
|
||||
return "``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~";
|
||||
Compiling key_btab: "\u001b[Z"
|
||||
return "\x1b[Z";
|
||||
Compiling enter_am_mode: "\u001b[?7h"
|
||||
return "\x1b[?7h";
|
||||
Compiling exit_am_mode: "\u001b[?7l"
|
||||
return "\x1b[?7l";
|
||||
Compiling key_end: "\u001bOF"
|
||||
return "\x1bOF";
|
||||
Compiling key_enter: "\u001bOM"
|
||||
return "\x1bOM";
|
||||
Compiling key_sdc: "\u001b[3;2~"
|
||||
return "\x1b[3;2~";
|
||||
Compiling key_send: "\u001b[1;2F"
|
||||
return "\x1b[1;2F";
|
||||
Compiling key_shome: "\u001b[1;2H"
|
||||
return "\x1b[1;2H";
|
||||
Compiling key_sic: "\u001b[2;2~"
|
||||
return "\x1b[2;2~";
|
||||
Compiling key_sleft: "\u001b[1;2D"
|
||||
return "\x1b[1;2D";
|
||||
Compiling key_snext: "\u001b[6;2~"
|
||||
return "\x1b[6;2~";
|
||||
Compiling key_sprevious: "\u001b[5;2~"
|
||||
return "\x1b[5;2~";
|
||||
Compiling key_sright: "\u001b[1;2C"
|
||||
return "\x1b[1;2C";
|
||||
Compiling key_f11: "\u001b[23~"
|
||||
return "\x1b[23~";
|
||||
Compiling key_f12: "\u001b[24~"
|
||||
return "\x1b[24~";
|
||||
Compiling key_f13: "\u001b[1;2P"
|
||||
return "\x1b[1;2P";
|
||||
Compiling key_f14: "\u001b[1;2Q"
|
||||
return "\x1b[1;2Q";
|
||||
Compiling key_f15: "\u001b[1;2R"
|
||||
return "\x1b[1;2R";
|
||||
Compiling key_f16: "\u001b[1;2S"
|
||||
return "\x1b[1;2S";
|
||||
Compiling key_f17: "\u001b[15;2~"
|
||||
return "\x1b[15;2~";
|
||||
Compiling key_f18: "\u001b[17;2~"
|
||||
return "\x1b[17;2~";
|
||||
Compiling key_f19: "\u001b[18;2~"
|
||||
return "\x1b[18;2~";
|
||||
Compiling key_f20: "\u001b[19;2~"
|
||||
return "\x1b[19;2~";
|
||||
Compiling key_f21: "\u001b[20;2~"
|
||||
return "\x1b[20;2~";
|
||||
Compiling key_f22: "\u001b[21;2~"
|
||||
return "\x1b[21;2~";
|
||||
Compiling key_f23: "\u001b[23;2~"
|
||||
return "\x1b[23;2~";
|
||||
Compiling key_f24: "\u001b[24;2~"
|
||||
return "\x1b[24;2~";
|
||||
Compiling key_f25: "\u001b[1;5P"
|
||||
return "\x1b[1;5P";
|
||||
Compiling key_f26: "\u001b[1;5Q"
|
||||
return "\x1b[1;5Q";
|
||||
Compiling key_f27: "\u001b[1;5R"
|
||||
return "\x1b[1;5R";
|
||||
Compiling key_f28: "\u001b[1;5S"
|
||||
return "\x1b[1;5S";
|
||||
Compiling key_f29: "\u001b[15;5~"
|
||||
return "\x1b[15;5~";
|
||||
Compiling key_f30: "\u001b[17;5~"
|
||||
return "\x1b[17;5~";
|
||||
Compiling key_f31: "\u001b[18;5~"
|
||||
return "\x1b[18;5~";
|
||||
Compiling key_f32: "\u001b[19;5~"
|
||||
return "\x1b[19;5~";
|
||||
Compiling key_f33: "\u001b[20;5~"
|
||||
return "\x1b[20;5~";
|
||||
Compiling key_f34: "\u001b[21;5~"
|
||||
return "\x1b[21;5~";
|
||||
Compiling key_f35: "\u001b[23;5~"
|
||||
return "\x1b[23;5~";
|
||||
Compiling key_f36: "\u001b[24;5~"
|
||||
return "\x1b[24;5~";
|
||||
Compiling key_f37: "\u001b[1;6P"
|
||||
return "\x1b[1;6P";
|
||||
Compiling key_f38: "\u001b[1;6Q"
|
||||
return "\x1b[1;6Q";
|
||||
Compiling key_f39: "\u001b[1;6R"
|
||||
return "\x1b[1;6R";
|
||||
Compiling key_f40: "\u001b[1;6S"
|
||||
return "\x1b[1;6S";
|
||||
Compiling key_f41: "\u001b[15;6~"
|
||||
return "\x1b[15;6~";
|
||||
Compiling key_f42: "\u001b[17;6~"
|
||||
return "\x1b[17;6~";
|
||||
Compiling key_f43: "\u001b[18;6~"
|
||||
return "\x1b[18;6~";
|
||||
Compiling key_f44: "\u001b[19;6~"
|
||||
return "\x1b[19;6~";
|
||||
Compiling key_f45: "\u001b[20;6~"
|
||||
return "\x1b[20;6~";
|
||||
Compiling key_f46: "\u001b[21;6~"
|
||||
return "\x1b[21;6~";
|
||||
Compiling key_f47: "\u001b[23;6~"
|
||||
return "\x1b[23;6~";
|
||||
Compiling key_f48: "\u001b[24;6~"
|
||||
return "\x1b[24;6~";
|
||||
Compiling key_f49: "\u001b[1;3P"
|
||||
return "\x1b[1;3P";
|
||||
Compiling key_f50: "\u001b[1;3Q"
|
||||
return "\x1b[1;3Q";
|
||||
Compiling key_f51: "\u001b[1;3R"
|
||||
return "\x1b[1;3R";
|
||||
Compiling key_f52: "\u001b[1;3S"
|
||||
return "\x1b[1;3S";
|
||||
Compiling key_f53: "\u001b[15;3~"
|
||||
return "\x1b[15;3~";
|
||||
Compiling key_f54: "\u001b[17;3~"
|
||||
return "\x1b[17;3~";
|
||||
Compiling key_f55: "\u001b[18;3~"
|
||||
return "\x1b[18;3~";
|
||||
Compiling key_f56: "\u001b[19;3~"
|
||||
return "\x1b[19;3~";
|
||||
Compiling key_f57: "\u001b[20;3~"
|
||||
return "\x1b[20;3~";
|
||||
Compiling key_f58: "\u001b[21;3~"
|
||||
return "\x1b[21;3~";
|
||||
Compiling key_f59: "\u001b[23;3~"
|
||||
return "\x1b[23;3~";
|
||||
Compiling key_f60: "\u001b[24;3~"
|
||||
return "\x1b[24;3~";
|
||||
Compiling key_f61: "\u001b[1;4P"
|
||||
return "\x1b[1;4P";
|
||||
Compiling key_f62: "\u001b[1;4Q"
|
||||
return "\x1b[1;4Q";
|
||||
Compiling key_f63: "\u001b[1;4R"
|
||||
return "\x1b[1;4R";
|
||||
Compiling clr_bol: "\u001b[1K"
|
||||
return "\x1b[1K";
|
||||
Compiling user6: "\u001b[%i%d;%dR"
|
||||
var stack = [], out = ["\x1b["];(params[0]++, params[1]++),out.push(stack.pop()),out.push(";"),out.push(stack.pop()),out.push("R");return out.join("");
|
||||
Compiling user7: "\u001b[6n"
|
||||
return "\x1b[6n";
|
||||
Compiling user8: "\u001b[?1;2c"
|
||||
return "\x1b[?1;2c";
|
||||
Compiling user9: "\u001b[c"
|
||||
return "\x1b[c";
|
||||
Compiling orig_pair: "\u001b[39;49m"
|
||||
return "\x1b[39;49m";
|
||||
Compiling set_foreground: "\u001b[3%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m"
|
||||
var v, stack = [], out = [];out.push("\x1b[3");if ((stack.push(v = params[0]), v),(stack.push(v = 1), v),(stack.push(v = (stack.pop() === stack.pop()) || 0), v)) {out.push("4")} else if ((stack.push(v = params[0]), v),(stack.push(v = 3), v),(stack.push(v = (stack.pop() === stack.pop()) || 0), v)) {out.push("6")} else if ((stack.push(v = params[0]), v),(stack.push(v = 4), v),(stack.push(v = (stack.pop() === stack.pop()) || 0), v)) {out.push("1")} else if ((stack.push(v = params[0]), v),(stack.push(v = 6), v),(stack.push(v = (stack.pop() === stack.pop()) || 0), v)) {out.push("3")} else {out.push(params[0])}out.push("m");return out.join("");
|
||||
Compiling set_background: "\u001b[4%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m"
|
||||
var v, stack = [], out = [];out.push("\x1b[4");if ((stack.push(v = params[0]), v),(stack.push(v = 1), v),(stack.push(v = (stack.pop() === stack.pop()) || 0), v)) {out.push("4")} else if ((stack.push(v = params[0]), v),(stack.push(v = 3), v),(stack.push(v = (stack.pop() === stack.pop()) || 0), v)) {out.push("6")} else if ((stack.push(v = params[0]), v),(stack.push(v = 4), v),(stack.push(v = (stack.pop() === stack.pop()) || 0), v)) {out.push("1")} else if ((stack.push(v = params[0]), v),(stack.push(v = 6), v),(stack.push(v = (stack.pop() === stack.pop()) || 0), v)) {out.push("3")} else {out.push(params[0])}out.push("m");return out.join("");
|
||||
Compiling key_mouse: "\u001b[M"
|
||||
return "\x1b[M";
|
||||
Compiling set_a_foreground: "\u001b[3%p1%dm"
|
||||
var out = ["\x1b[3"];out.push(params[0]),out.push("m");return out.join("");
|
||||
Compiling set_a_background: "\u001b[4%p1%dm"
|
||||
var out = ["\x1b[4"];out.push(params[0]),out.push("m");return out.join("");
|
||||
Compiling memory_lock: "\u001bl"
|
||||
return "\x1bl";
|
||||
Compiling memory_unlock: "\u001bm"
|
||||
return "\x1bm";
|
||||
Compiling Cr: "\u001b]112\u0007"
|
||||
return "\x1b]112\x07";
|
||||
Compiling Cs: "\u001b]12;%p1%s\u0007"
|
||||
var out = ["\x1b]12;"];out.push(params[0]),out.push("\x07");return out.join("");
|
||||
Compiling E3: "\u001b[3;J"
|
||||
return "\x1b[3;J";
|
||||
Compiling Ms: "\u001b]52;%p1%s;%p2%s\u0007"
|
||||
var out = ["\x1b]52;"];out.push(params[0]),out.push(";"),out.push(params[1]),out.push("\x07");return out.join("");
|
||||
Compiling Se: "\u001b[2 q"
|
||||
return "\x1b[2 q";
|
||||
Compiling Ss: "\u001b[%p1%d q"
|
||||
var out = ["\x1b["];out.push(params[0]),out.push(" q");return out.join("");
|
||||
Compiling kDC3: "\u001b[3;3~"
|
||||
return "\x1b[3;3~";
|
||||
Compiling kDC4: "\u001b[3;4~"
|
||||
return "\x1b[3;4~";
|
||||
Compiling kDC5: "\u001b[3;5~"
|
||||
return "\x1b[3;5~";
|
||||
Compiling kDC6: "\u001b[3;6~"
|
||||
return "\x1b[3;6~";
|
||||
Compiling kDC7: "\u001b[3;7~"
|
||||
return "\x1b[3;7~";
|
||||
Compiling kDN: "\u001b[1;2B"
|
||||
return "\x1b[1;2B";
|
||||
Compiling kDN3: "\u001b[1;3B"
|
||||
return "\x1b[1;3B";
|
||||
Compiling kDN4: "\u001b[1;4B"
|
||||
return "\x1b[1;4B";
|
||||
Compiling kDN5: "\u001b[1;5B"
|
||||
return "\x1b[1;5B";
|
||||
Compiling kDN6: "\u001b[1;6B"
|
||||
return "\x1b[1;6B";
|
||||
Compiling kDN7: "\u001b[1;7B"
|
||||
return "\x1b[1;7B";
|
||||
Compiling kEND3: "\u001b[1;3F"
|
||||
return "\x1b[1;3F";
|
||||
Compiling kEND4: "\u001b[1;4F"
|
||||
return "\x1b[1;4F";
|
||||
Compiling kEND5: "\u001b[1;5F"
|
||||
return "\x1b[1;5F";
|
||||
Compiling kEND6: "\u001b[1;6F"
|
||||
return "\x1b[1;6F";
|
||||
Compiling kEND7: "\u001b[1;7F"
|
||||
return "\x1b[1;7F";
|
||||
Compiling kHOM3: "\u001b[1;3H"
|
||||
return "\x1b[1;3H";
|
||||
Compiling kHOM4: "\u001b[1;4H"
|
||||
return "\x1b[1;4H";
|
||||
Compiling kHOM5: "\u001b[1;5H"
|
||||
return "\x1b[1;5H";
|
||||
Compiling kHOM6: "\u001b[1;6H"
|
||||
return "\x1b[1;6H";
|
||||
Compiling kHOM7: "\u001b[1;7H"
|
||||
return "\x1b[1;7H";
|
||||
Compiling kIC3: "\u001b[2;3~"
|
||||
return "\x1b[2;3~";
|
||||
Compiling kIC4: "\u001b[2;4~"
|
||||
return "\x1b[2;4~";
|
||||
Compiling kIC5: "\u001b[2;5~"
|
||||
return "\x1b[2;5~";
|
||||
Compiling kIC6: "\u001b[2;6~"
|
||||
return "\x1b[2;6~";
|
||||
Compiling kIC7: "\u001b[2;7~"
|
||||
return "\x1b[2;7~";
|
||||
Compiling kLFT3: "\u001b[1;3D"
|
||||
return "\x1b[1;3D";
|
||||
Compiling kLFT4: "\u001b[1;4D"
|
||||
return "\x1b[1;4D";
|
||||
Compiling kLFT5: "\u001b[1;5D"
|
||||
return "\x1b[1;5D";
|
||||
Compiling kLFT6: "\u001b[1;6D"
|
||||
return "\x1b[1;6D";
|
||||
Compiling kLFT7: "\u001b[1;7D"
|
||||
return "\x1b[1;7D";
|
||||
Compiling kNXT3: "\u001b[6;3~"
|
||||
return "\x1b[6;3~";
|
||||
Compiling kNXT4: "\u001b[6;4~"
|
||||
return "\x1b[6;4~";
|
||||
Compiling kNXT5: "\u001b[6;5~"
|
||||
return "\x1b[6;5~";
|
||||
Compiling kNXT6: "\u001b[6;6~"
|
||||
return "\x1b[6;6~";
|
||||
Compiling kNXT7: "\u001b[6;7~"
|
||||
return "\x1b[6;7~";
|
||||
Compiling kPRV3: "\u001b[5;3~"
|
||||
return "\x1b[5;3~";
|
||||
Compiling kPRV4: "\u001b[5;4~"
|
||||
return "\x1b[5;4~";
|
||||
Compiling kPRV5: "\u001b[5;5~"
|
||||
return "\x1b[5;5~";
|
||||
Compiling kPRV6: "\u001b[5;6~"
|
||||
return "\x1b[5;6~";
|
||||
Compiling kPRV7: "\u001b[5;7~"
|
||||
return "\x1b[5;7~";
|
||||
Compiling kRIT3: "\u001b[1;3C"
|
||||
return "\x1b[1;3C";
|
||||
Compiling kRIT4: "\u001b[1;4C"
|
||||
return "\x1b[1;4C";
|
||||
Compiling kRIT5: "\u001b[1;5C"
|
||||
return "\x1b[1;5C";
|
||||
Compiling kRIT6: "\u001b[1;6C"
|
||||
return "\x1b[1;6C";
|
||||
Compiling kRIT7: "\u001b[1;7C"
|
||||
return "\x1b[1;7C";
|
||||
Compiling kUP: "\u001b[1;2A"
|
||||
return "\x1b[1;2A";
|
||||
Compiling kUP3: "\u001b[1;3A"
|
||||
return "\x1b[1;3A";
|
||||
Compiling kUP4: "\u001b[1;4A"
|
||||
return "\x1b[1;4A";
|
||||
Compiling kUP5: "\u001b[1;5A"
|
||||
return "\x1b[1;5A";
|
||||
Compiling kUP6: "\u001b[1;6A"
|
||||
return "\x1b[1;6A";
|
||||
Compiling kUP7: "\u001b[1;7A"
|
||||
return "\x1b[1;7A";
|
||||
Compiling ka2: ""
|
||||
Compiling kb1: ""
|
||||
Compiling kb3: ""
|
||||
Compiling kc2: ""
|
||||
BIN
test/test-image.png
Normal file
|
After Width: | Height: | Size: 292 B |
20
test/tput
Executable file
@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
|
||||
term="$1"
|
||||
|
||||
dir=$(dirname $(readlink -f "$0"))
|
||||
cd "$dir/.."
|
||||
|
||||
if test -z "$term"; then
|
||||
term="$dir/../usr/xterm"
|
||||
set -- "$term" "$@"
|
||||
fi
|
||||
|
||||
node test/tput.js "$@" | grep -v 'dir:\|file:' | tee test/logs/terminfo.log
|
||||
out=$(git diff --color=always --no-index test/terminfo test/logs/terminfo.log)
|
||||
|
||||
if test -n "$out"; then
|
||||
echo "$out" | less -c -R
|
||||
else
|
||||
echo 'Files are identical.'
|
||||
fi
|
||||
152
test/tput.js
Normal file
@ -0,0 +1,152 @@
|
||||
/**
|
||||
* Tput for node.js
|
||||
* Copyright (c) 2013, Christopher Jeffrey (MIT License)
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
// Compile xterm terminfo/termcap:
|
||||
// $ tic -a -I -1 usr/xterm.terminfo
|
||||
// $ tic -a -C -U usr/xterm.termcap
|
||||
|
||||
// Compile xterm terminfo/termcap:
|
||||
// $ tic -a -1 usr/xterm.terminfo
|
||||
// $ tic -a -1 usr/xterm.terminfo && ls ~/.terminfo
|
||||
// $ tic -a -1 -o usr usr/xterm.terminfo && mv usr/x/xterm usr/ && rm -rf usr/v usr/x
|
||||
// $ tic -a -1 -o usr usr/xterm.terminfo && mv usr/x/xterm-256color usr/ && rm -rf usr/v usr/x
|
||||
|
||||
// Check tput output:
|
||||
// $ node test/tput.js xterm | tee out
|
||||
// $ node test/tput.js xterm --ifile usr/xterm | tee out
|
||||
// $ node test/tput.js xterm-256color --ifile usr/xterm-256color | tee out
|
||||
// $ node test/tput.js vt102 --termcap | tee out
|
||||
// $ node test/tput.js xterm --termcap --cfile usr/xterm.termcap | tee out
|
||||
// $ node test/tput.js xterm --iprefix ~/.terminfo | tee out
|
||||
// $ node test/tput.js xterm-256color --ifile ~/.terminfo/x/xterm-256color | tee out
|
||||
// $ cdiff test/terminfo out
|
||||
|
||||
var blessed = require('../');
|
||||
|
||||
// Simple argument parser
|
||||
// Copyright (c) 2012, Christopher Jeffrey (MIT License)
|
||||
|
||||
function parseArg() {
|
||||
var argv = process.argv.slice(2)
|
||||
, options = [];
|
||||
|
||||
function getarg() {
|
||||
var arg = argv.shift();
|
||||
|
||||
if (arg.indexOf('--') === 0) {
|
||||
// e.g. --opt
|
||||
arg = arg.split('=');
|
||||
if (arg.length > 1) {
|
||||
// e.g. --opt=val
|
||||
argv.unshift(arg.slice(1).join('='));
|
||||
}
|
||||
arg = arg[0];
|
||||
} else if (arg[0] === '-') {
|
||||
if (arg.length > 2) {
|
||||
// e.g. -abc
|
||||
argv = arg.substring(1).split('').map(function(ch) {
|
||||
return '-' + ch;
|
||||
}).concat(argv);
|
||||
arg = argv.shift();
|
||||
} else {
|
||||
// e.g. -a
|
||||
}
|
||||
} else {
|
||||
// e.g. foo
|
||||
}
|
||||
|
||||
return arg;
|
||||
}
|
||||
|
||||
while (argv.length) {
|
||||
arg = getarg();
|
||||
if (arg.indexOf('-') === 0) {
|
||||
arg = arg.replace(/^--?/, '');
|
||||
if (argv[0] && argv[0].indexOf('-') !== 0) {
|
||||
options[arg] = argv.shift();
|
||||
} else {
|
||||
options[arg] = true;
|
||||
}
|
||||
} else {
|
||||
options.push(arg);
|
||||
}
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
var argv = parseArg();
|
||||
|
||||
var tput = blessed.tput({
|
||||
terminal: argv[0] !== 'all' && argv[0] !== 'rand'
|
||||
? argv[0] || __dirname + '/../usr/xterm'
|
||||
: null,
|
||||
extended: true,
|
||||
debug: true,
|
||||
termcap: argv.termcap,
|
||||
terminfoFile: argv.i || argv.ifile,
|
||||
terminfoPrefix: argv.p || argv.iprefix,
|
||||
termcapFile: argv.c || argv.cfile
|
||||
});
|
||||
|
||||
if (argv[0] === 'all') {
|
||||
var rl = require('readline').createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout
|
||||
});
|
||||
|
||||
var text = '\x1b[31mWARNING:\x1b[m '
|
||||
+ 'This will compile every single terminfo file on your disk.\n'
|
||||
+ 'It will probably use a lot of CPU.\n'
|
||||
+ 'Do you wish to proceed? (Y/n) ';
|
||||
|
||||
rl.question(text, function(result) {
|
||||
result = result.trim().toLowerCase();
|
||||
if (result !== 'y') return process.exit(0);
|
||||
console.log('\x1b[32m(You bet your ass I wish to proceed.)\x1b[m');
|
||||
blessed.tput.print(
|
||||
'$<1000/>.$<1000/>.$<1000/>.$<100/>Let\'s go...',
|
||||
process.stdout.write.bind(process.stdout),
|
||||
function() {
|
||||
tput.compileAll(argv[1]);
|
||||
process.exit(0);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (argv[0] === 'rand') {
|
||||
var terms = tput.getAll()
|
||||
, term;
|
||||
|
||||
term = terms[(terms.length - 1) * Math.random() | 0];
|
||||
|
||||
console.log('Compiling ' + term + '...');
|
||||
tput.compileTerminfo(term);
|
||||
console.log('Compiled ' + term + '.');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// console.log('Max colors: %d.', tput.colors);
|
||||
|
||||
// console.log(tput.strings.acs_chars.split('').map(function(ch) { return ch.charCodeAt(0); }));
|
||||
// console.log(JSON.stringify(tput.strings.acs_chars));
|
||||
|
||||
// process.stdout.write(blessed.tput.sprintf('%-10s\n', 'hello'));
|
||||
|
||||
// tput._compile({ name: 'xterm' }, 'set_attributes',
|
||||
// '%?%p9%t\u001b(0%e\u001b(B%;\u001b[0%?%p6%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;%?%p7%t;8%;m');
|
||||
|
||||
// console.log(tput.setaf(4) + 'foo' + tput.sgr0());
|
||||
// console.log(tput.setaf(4) + 'foo' + tput.sgr(0));
|
||||
|
||||
// tput.padding = true;
|
||||
// tput._print('hello$<1000/>world', console.log, function() {
|
||||
// tput._print('$<1000/>foo$<1000/>bar', console.log, process.exit);
|
||||
// });
|
||||
33
test/widget-autopad.js
Normal file
@ -0,0 +1,33 @@
|
||||
var blessed = require('../')
|
||||
, screen;
|
||||
|
||||
screen = blessed.screen({
|
||||
dump: __dirname + '/logs/autopad.log',
|
||||
smartCSR: true,
|
||||
autoPadding: true,
|
||||
warnings: true
|
||||
});
|
||||
|
||||
var box1 = blessed.box({
|
||||
parent: screen,
|
||||
top: 'center',
|
||||
left: 'center',
|
||||
width: 20,
|
||||
height: 10,
|
||||
border: 'line'
|
||||
});
|
||||
|
||||
var box2 = blessed.box({
|
||||
parent: box1,
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: 10,
|
||||
height: 5,
|
||||
border: 'line'
|
||||
});
|
||||
|
||||
screen.key('q', function() {
|
||||
return screen.destroy();
|
||||
});
|
||||
|
||||
screen.render();
|
||||
33
test/widget-bigtext.js
Normal file
@ -0,0 +1,33 @@
|
||||
var blessed = require('../')
|
||||
, screen;
|
||||
|
||||
screen = blessed.screen({
|
||||
dump: __dirname + '/logs/bigtext.log',
|
||||
smartCSR: true,
|
||||
warnings: true
|
||||
});
|
||||
|
||||
var box = blessed.bigtext({
|
||||
parent: screen,
|
||||
content: 'Hello',
|
||||
shrink: true,
|
||||
width: '80%',
|
||||
// height: '80%',
|
||||
height: 'shrink',
|
||||
// width: 'shrink',
|
||||
border: 'line',
|
||||
fch: ' ',
|
||||
ch: '\u2592',
|
||||
style: {
|
||||
fg: 'red',
|
||||
bg: 'blue',
|
||||
bold: false
|
||||
}
|
||||
});
|
||||
|
||||
screen.key('q', function() {
|
||||
return screen.destroy();
|
||||
});
|
||||
|
||||
screen.render();
|
||||
|
||||
90
test/widget-csr.js
Normal file
@ -0,0 +1,90 @@
|
||||
var blessed = require('../')
|
||||
, screen;
|
||||
|
||||
screen = blessed.screen({
|
||||
dump: __dirname + '/logs/csr.log',
|
||||
smartCSR: true,
|
||||
warnings: true
|
||||
});
|
||||
|
||||
var lorem = require('fs').readFileSync(__dirname + '/git.diff', 'utf8');
|
||||
|
||||
var cleanSides = screen.cleanSides;
|
||||
function expectClean(value) {
|
||||
screen.cleanSides = function(el) {
|
||||
var ret = cleanSides.apply(this, arguments);
|
||||
if (ret !== value) {
|
||||
throw new Error('Failed. Expected '
|
||||
+ value + ' from cleanSides. Got '
|
||||
+ ret + '.');
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
blessed.box({
|
||||
parent: screen,
|
||||
left: 0,
|
||||
top: 'center',
|
||||
width: '50%',
|
||||
height: 2,
|
||||
style: {
|
||||
bg: 'green'
|
||||
},
|
||||
content: 'This will disallow CSR.'
|
||||
});
|
||||
expectClean(false);
|
||||
*/
|
||||
|
||||
var btext = blessed.box({
|
||||
parent: screen,
|
||||
left: 'center',
|
||||
top: 'center',
|
||||
width: '80%',
|
||||
height: '80%',
|
||||
style: {
|
||||
bg: 'green'
|
||||
},
|
||||
border: 'line',
|
||||
content: 'CSR should still work.'
|
||||
});
|
||||
btext._oscroll = btext.scroll;
|
||||
btext.scroll = function(offset, always) {
|
||||
expectClean(true);
|
||||
return btext._oscroll(offset, always);
|
||||
};
|
||||
|
||||
var text = blessed.scrollabletext({
|
||||
parent: screen,
|
||||
content: lorem,
|
||||
border: 'line',
|
||||
left: 'center',
|
||||
top: 'center',
|
||||
draggable: true,
|
||||
width: '50%',
|
||||
height: '50%',
|
||||
mouse: true,
|
||||
keys: true,
|
||||
vi: true
|
||||
});
|
||||
|
||||
text._oscroll = text.scroll;
|
||||
text.scroll = function(offset, always) {
|
||||
var el = this;
|
||||
var value = true;
|
||||
if (el.left < 0) value = true;
|
||||
if (el.top < 0) value = false;
|
||||
if (el.left + el.width > screen.width) value = true;
|
||||
if (el.top + el.height > screen.height) value = false;
|
||||
expectClean(value);
|
||||
return text._oscroll(offset, always);
|
||||
};
|
||||
|
||||
text.focus();
|
||||
|
||||
screen.key('q', function() {
|
||||
return screen.destroy();
|
||||
});
|
||||
|
||||
screen.render();
|
||||
88
test/widget-dock-noborder.js
Normal file
@ -0,0 +1,88 @@
|
||||
var blessed = require('../')
|
||||
, screen;
|
||||
|
||||
screen = blessed.screen({
|
||||
dump: __dirname + '/logs/dock.log',
|
||||
smartCSR: true,
|
||||
dockBorders: true,
|
||||
warnings: true
|
||||
});
|
||||
|
||||
blessed.box({
|
||||
parent: screen,
|
||||
left: -1,
|
||||
top: -1,
|
||||
width: '50%+1',
|
||||
height: '50%+1',
|
||||
border: 'line',
|
||||
content: 'Foo'
|
||||
});
|
||||
|
||||
blessed.box({
|
||||
parent: screen,
|
||||
left: '50%-1',
|
||||
top: -1,
|
||||
width: '50%+3',
|
||||
height: '50%+1',
|
||||
content: 'Bar',
|
||||
border: 'line'
|
||||
});
|
||||
|
||||
blessed.box({
|
||||
parent: screen,
|
||||
left: -1,
|
||||
top: '50%-1',
|
||||
width: '50%+1',
|
||||
height: '50%+3',
|
||||
border: 'line',
|
||||
content: 'Foo'
|
||||
});
|
||||
|
||||
blessed.listtable({
|
||||
parent: screen,
|
||||
left: '50%-1',
|
||||
top: '50%-1',
|
||||
width: '50%+3',
|
||||
height: '50%+3',
|
||||
border: 'line',
|
||||
align: 'center',
|
||||
tags: true,
|
||||
keys: true,
|
||||
vi: true,
|
||||
mouse: true,
|
||||
style: {
|
||||
header: {
|
||||
fg: 'blue',
|
||||
bold: true
|
||||
},
|
||||
cell: {
|
||||
fg: 'magenta',
|
||||
selected: {
|
||||
bg: 'blue'
|
||||
}
|
||||
}
|
||||
},
|
||||
data: [
|
||||
[ 'Animals', 'Foods', 'Times', 'Numbers' ],
|
||||
[ 'Elephant', 'Apple', '1:00am', 'One' ],
|
||||
[ 'Bird', 'Orange', '2:15pm', 'Two' ],
|
||||
[ 'T-Rex', 'Taco', '8:45am', 'Three' ],
|
||||
[ 'Mouse', 'Cheese', '9:05am', 'Four' ]
|
||||
]
|
||||
}).focus();
|
||||
|
||||
// blessed.box({
|
||||
// parent: screen,
|
||||
// left: '50%-1',
|
||||
// top: '50%-1',
|
||||
// width: '50%+1',
|
||||
// height: '50%+1',
|
||||
// border: 'line',
|
||||
// content: 'Bar'
|
||||
// });
|
||||
|
||||
screen.key('q', function() {
|
||||
return screen.destroy();
|
||||
});
|
||||
|
||||
screen.render();
|
||||
125
test/widget-dock.js
Normal file
@ -0,0 +1,125 @@
|
||||
var blessed = require('../')
|
||||
, screen;
|
||||
|
||||
screen = blessed.screen({
|
||||
dump: __dirname + '/logs/dock.log',
|
||||
smartCSR: true,
|
||||
dockBorders: true,
|
||||
warnings: true
|
||||
});
|
||||
|
||||
var topleft = blessed.box({
|
||||
parent: screen,
|
||||
left: 0,
|
||||
top: 0,
|
||||
width: '50%',
|
||||
height: '50%',
|
||||
border: {
|
||||
type: 'line',
|
||||
left: false,
|
||||
top: false,
|
||||
right: true,
|
||||
bottom: false
|
||||
},
|
||||
// border: 'line',
|
||||
content: 'Foo'
|
||||
});
|
||||
|
||||
var topright = blessed.box({
|
||||
parent: screen,
|
||||
left: '50%-1',
|
||||
top: 0,
|
||||
width: '50%+1',
|
||||
height: '50%',
|
||||
border: {
|
||||
type: 'line',
|
||||
left: true,
|
||||
top: false,
|
||||
right: false,
|
||||
bottom: false
|
||||
},
|
||||
// border: 'line',
|
||||
content: 'Bar'
|
||||
});
|
||||
|
||||
var bottomleft = blessed.box({
|
||||
parent: screen,
|
||||
left: 0,
|
||||
top: '50%-1',
|
||||
width: '50%',
|
||||
height: '50%+1',
|
||||
border: {
|
||||
type: 'line',
|
||||
left: false,
|
||||
top: true,
|
||||
right: false,
|
||||
bottom: false
|
||||
},
|
||||
border: 'line',
|
||||
content: 'Foo'
|
||||
});
|
||||
|
||||
var bottomright = blessed.listtable({
|
||||
parent: screen,
|
||||
left: '50%-1',
|
||||
top: '50%-1',
|
||||
width: '50%+1',
|
||||
height: '50%+1',
|
||||
border: {
|
||||
type: 'line',
|
||||
left: true,
|
||||
top: true,
|
||||
right: false,
|
||||
bottom: false
|
||||
},
|
||||
// border: 'line',
|
||||
align: 'center',
|
||||
tags: true,
|
||||
keys: true,
|
||||
vi: true,
|
||||
mouse: true,
|
||||
style: {
|
||||
header: {
|
||||
fg: 'blue',
|
||||
bold: true
|
||||
},
|
||||
cell: {
|
||||
fg: 'magenta',
|
||||
selected: {
|
||||
bg: 'blue'
|
||||
}
|
||||
}
|
||||
},
|
||||
data: [
|
||||
[ 'Animals', 'Foods', 'Times', 'Numbers' ],
|
||||
[ 'Elephant', 'Apple', '1:00am', 'One' ],
|
||||
[ 'Bird', 'Orange', '2:15pm', 'Two' ],
|
||||
[ 'T-Rex', 'Taco', '8:45am', 'Three' ],
|
||||
[ 'Mouse', 'Cheese', '9:05am', 'Four' ]
|
||||
]
|
||||
});
|
||||
|
||||
bottomright.focus();
|
||||
|
||||
var over = blessed.box({
|
||||
parent: screen,
|
||||
left: 'center',
|
||||
top: 'center',
|
||||
width: '50%',
|
||||
height: '50%',
|
||||
draggable: true,
|
||||
border: {
|
||||
type: 'line',
|
||||
left: false,
|
||||
top: true,
|
||||
right: true,
|
||||
bottom: true
|
||||
},
|
||||
content: 'Drag Me'
|
||||
});
|
||||
|
||||
screen.key('q', function() {
|
||||
return screen.destroy();
|
||||
});
|
||||
|
||||
screen.render();
|
||||
36
test/widget-exit.js
Normal file
@ -0,0 +1,36 @@
|
||||
var blessed = require('../');
|
||||
|
||||
var screen = blessed.screen({
|
||||
dump: __dirname + '/logs/exit.log',
|
||||
smartCSR: true,
|
||||
autoPadding: true,
|
||||
warnings: true,
|
||||
ignoreLocked: ['C-q']
|
||||
});
|
||||
|
||||
var box = blessed.prompt({
|
||||
parent: screen,
|
||||
left: 'center',
|
||||
top: 'center',
|
||||
width: '70%',
|
||||
height: 'shrink',
|
||||
border: 'line'
|
||||
});
|
||||
|
||||
screen.render();
|
||||
|
||||
box.input('Input: ', '', function(err, data) {
|
||||
screen.destroy();
|
||||
if (process.argv[2] === 'resume') {
|
||||
process.stdin.resume();
|
||||
} else if (process.argv[2] === 'end') {
|
||||
process.stdin.setRawMode(false);
|
||||
process.stdin.end();
|
||||
}
|
||||
if (err) throw err;
|
||||
console.log('Input: ' + data);
|
||||
});
|
||||
|
||||
screen.key('C-q', function(ch, key) {
|
||||
return screen.destroy();
|
||||
});
|
||||
70
test/widget-file.js
Normal file
@ -0,0 +1,70 @@
|
||||
var blessed = require('../');
|
||||
|
||||
var screen = blessed.screen({
|
||||
tput: true,
|
||||
smartCSR: true,
|
||||
dump: __dirname + '/logs/file.log',
|
||||
warnings: true
|
||||
});
|
||||
|
||||
var fm = blessed.filemanager({
|
||||
parent: screen,
|
||||
border: 'line',
|
||||
style: {
|
||||
selected: {
|
||||
bg: 'blue'
|
||||
}
|
||||
},
|
||||
height: 'half',
|
||||
width: 'half',
|
||||
top: 'center',
|
||||
left: 'center',
|
||||
label: ' {blue-fg}%path{/blue-fg} ',
|
||||
cwd: process.env.HOME,
|
||||
keys: true,
|
||||
vi: true,
|
||||
scrollbar: {
|
||||
bg: 'white',
|
||||
ch: ' '
|
||||
}
|
||||
});
|
||||
|
||||
var box = blessed.box({
|
||||
parent: screen,
|
||||
style: {
|
||||
bg: 'green'
|
||||
},
|
||||
border: 'line',
|
||||
height: 'half',
|
||||
width: 'half',
|
||||
top: 'center',
|
||||
left: 'center',
|
||||
hidden: true
|
||||
});
|
||||
|
||||
fm.refresh();
|
||||
|
||||
screen.render();
|
||||
|
||||
screen.key('q', function() {
|
||||
screen.destroy();
|
||||
});
|
||||
|
||||
screen.key(['s', 'p'], function() {
|
||||
fm.hide();
|
||||
screen.render();
|
||||
setTimeout(function() {
|
||||
fm.pick(function(err, file) {
|
||||
box.show();
|
||||
box.setContent(err ? err + '' : file);
|
||||
screen.render();
|
||||
setTimeout(function() {
|
||||
box.hide();
|
||||
fm.reset(function() {
|
||||
fm.show();
|
||||
screen.render();
|
||||
});
|
||||
}, 2000);
|
||||
});
|
||||
}, 2000);
|
||||
});
|
||||
253
test/widget-form.js
Normal file
@ -0,0 +1,253 @@
|
||||
var blessed = require('../')
|
||||
, screen;
|
||||
|
||||
screen = blessed.screen({
|
||||
dump: __dirname + '/logs/form.log',
|
||||
warnings: true
|
||||
});
|
||||
|
||||
var form = blessed.form({
|
||||
parent: screen,
|
||||
mouse: true,
|
||||
keys: true,
|
||||
vi: true,
|
||||
left: 0,
|
||||
top: 0,
|
||||
width: '100%',
|
||||
//height: 12,
|
||||
style: {
|
||||
bg: 'green',
|
||||
// border: {
|
||||
// inverse: true
|
||||
// },
|
||||
scrollbar: {
|
||||
inverse: true
|
||||
}
|
||||
},
|
||||
content: 'foobar',
|
||||
scrollable: true,
|
||||
// border: {
|
||||
// type: 'ch',
|
||||
// ch: ' '
|
||||
// },
|
||||
scrollbar: {
|
||||
ch: ' '
|
||||
}
|
||||
//alwaysScroll: true
|
||||
});
|
||||
|
||||
form.on('submit', function(data) {
|
||||
output.setContent(JSON.stringify(data, null, 2));
|
||||
screen.render();
|
||||
});
|
||||
|
||||
form.key('d', function() {
|
||||
form.scroll(1, true);
|
||||
screen.render();
|
||||
});
|
||||
|
||||
form.key('u', function() {
|
||||
form.scroll(-1, true);
|
||||
screen.render();
|
||||
});
|
||||
|
||||
var set = blessed.radioset({
|
||||
parent: form,
|
||||
left: 1,
|
||||
top: 1,
|
||||
shrink: true,
|
||||
//padding: 1,
|
||||
//content: 'f',
|
||||
style: {
|
||||
bg: 'magenta'
|
||||
}
|
||||
});
|
||||
|
||||
var radio1 = blessed.radiobutton({
|
||||
parent: set,
|
||||
mouse: true,
|
||||
keys: true,
|
||||
shrink: true,
|
||||
style: {
|
||||
bg: 'magenta'
|
||||
},
|
||||
height: 1,
|
||||
left: 0,
|
||||
top: 0,
|
||||
name: 'radio1',
|
||||
content: 'radio1'
|
||||
});
|
||||
|
||||
var radio2 = blessed.radiobutton({
|
||||
parent: set,
|
||||
mouse: true,
|
||||
keys: true,
|
||||
shrink: true,
|
||||
style: {
|
||||
bg: 'magenta'
|
||||
},
|
||||
height: 1,
|
||||
left: 15,
|
||||
top: 0,
|
||||
name: 'radio2',
|
||||
content: 'radio2'
|
||||
});
|
||||
|
||||
var text = blessed.textbox({
|
||||
parent: form,
|
||||
mouse: true,
|
||||
keys: true,
|
||||
style: {
|
||||
bg: 'blue'
|
||||
},
|
||||
height: 1,
|
||||
width: 20,
|
||||
left: 1,
|
||||
top: 3,
|
||||
name: 'text'
|
||||
});
|
||||
|
||||
text.on('focus', function() {
|
||||
text.readInput();
|
||||
});
|
||||
|
||||
var check = blessed.checkbox({
|
||||
parent: form,
|
||||
mouse: true,
|
||||
keys: true,
|
||||
shrink: true,
|
||||
style: {
|
||||
bg: 'magenta'
|
||||
},
|
||||
height: 1,
|
||||
left: 28,
|
||||
top: 1,
|
||||
name: 'check',
|
||||
content: 'check'
|
||||
});
|
||||
|
||||
var check2 = blessed.checkbox({
|
||||
parent: form,
|
||||
mouse: true,
|
||||
keys: true,
|
||||
shrink: true,
|
||||
style: {
|
||||
bg: 'magenta'
|
||||
},
|
||||
height: 1,
|
||||
left: 28,
|
||||
top: 14,
|
||||
name: 'foooooooo2',
|
||||
content: 'foooooooo2'
|
||||
});
|
||||
|
||||
var submit = blessed.button({
|
||||
parent: form,
|
||||
mouse: true,
|
||||
keys: true,
|
||||
shrink: true,
|
||||
padding: {
|
||||
left: 1,
|
||||
right: 1
|
||||
},
|
||||
left: 29,
|
||||
top: 3,
|
||||
shrink: true,
|
||||
name: 'submit',
|
||||
content: 'submit',
|
||||
style: {
|
||||
bg: 'blue',
|
||||
focus: {
|
||||
bg: 'red'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
submit.on('press', function() {
|
||||
form.submit();
|
||||
});
|
||||
|
||||
var box1 = blessed.box({
|
||||
parent: form,
|
||||
left: 1,
|
||||
top: 10,
|
||||
height: 10,
|
||||
width: 10,
|
||||
content: 'one',
|
||||
style: {
|
||||
bg: 'cyan'
|
||||
}
|
||||
});
|
||||
|
||||
var box2 = blessed.box({
|
||||
parent: box1,
|
||||
left: 1,
|
||||
top: 2,
|
||||
height: 8,
|
||||
width: 9,
|
||||
content: 'two',
|
||||
style: {
|
||||
bg: 'magenta'
|
||||
}
|
||||
});
|
||||
|
||||
var box3 = blessed.box({
|
||||
parent: box2,
|
||||
left: 1,
|
||||
top: 2,
|
||||
height: 6,
|
||||
width: 8,
|
||||
content: 'three',
|
||||
style: {
|
||||
bg: 'yellow'
|
||||
}
|
||||
});
|
||||
|
||||
var box4 = blessed.box({
|
||||
parent: box3,
|
||||
left: 1,
|
||||
top: 2,
|
||||
height: 4,
|
||||
width: 7,
|
||||
content: 'four',
|
||||
style: {
|
||||
bg: 'blue'
|
||||
}
|
||||
});
|
||||
|
||||
var output = blessed.scrollabletext({
|
||||
parent: form,
|
||||
mouse: true,
|
||||
keys: true,
|
||||
left: 0,
|
||||
top: 20,
|
||||
height: 5,
|
||||
left: 0,
|
||||
right: 0,
|
||||
style: {
|
||||
bg: 'red'
|
||||
},
|
||||
content: 'foobar'
|
||||
});
|
||||
|
||||
var bottom = blessed.line({
|
||||
parent: form,
|
||||
type: 'line',
|
||||
orientation: 'horizontal',
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: 50,
|
||||
style: {
|
||||
fg: 'blue'
|
||||
}
|
||||
});
|
||||
|
||||
screen.key('q', function() {
|
||||
return screen.destroy();
|
||||
});
|
||||
|
||||
form.focus();
|
||||
|
||||
form.submit();
|
||||
|
||||
screen.render();
|
||||
70
test/widget-image.js
Normal file
@ -0,0 +1,70 @@
|
||||
var blessed = require('../')
|
||||
, screen;
|
||||
|
||||
screen = blessed.screen({
|
||||
dump: __dirname + '/logs/image.log',
|
||||
smartCSR: true,
|
||||
warnings: true
|
||||
});
|
||||
|
||||
// To ensure our w3mimgdisplay search works:
|
||||
if (process.argv[2] === 'find') {
|
||||
blessed.image.w3mdisplay = '/does/not/exist';
|
||||
process.argv.length = 2;
|
||||
}
|
||||
|
||||
var file = process.argv[2] || __dirname + '/test-image.png';
|
||||
|
||||
var image = blessed.image({
|
||||
parent: screen,
|
||||
type: 'overlay',
|
||||
left: 'center',
|
||||
top: 'center',
|
||||
width: 'shrink',
|
||||
height: 'shrink',
|
||||
style: {
|
||||
bg: 'green'
|
||||
},
|
||||
draggable: true
|
||||
});
|
||||
|
||||
setTimeout(function() {
|
||||
image.setImage(file, function() {
|
||||
// XXX For some reason the image sometimes envelopes
|
||||
// the entire screen at the end if this is uncommented:
|
||||
// NOTE: Might have to do with an uncached ratio and
|
||||
// a bad termSize being reported.
|
||||
screen.render();
|
||||
setTimeout(function() {
|
||||
image.rtop = 4;
|
||||
image.rleft = 10;
|
||||
screen.render();
|
||||
setTimeout(function() {
|
||||
image.rtop = 2;
|
||||
image.rleft = 7;
|
||||
screen.render();
|
||||
setTimeout(function() {
|
||||
image.detach();
|
||||
screen.render();
|
||||
setTimeout(function() {
|
||||
screen.append(image);
|
||||
image.enableMouse();
|
||||
screen.render();
|
||||
}, 1000);
|
||||
}, 1000);
|
||||
}, 1000);
|
||||
}, 5000);
|
||||
});
|
||||
}, 1000);
|
||||
|
||||
image.focus();
|
||||
|
||||
screen.key('i', function() {
|
||||
screen.displayImage(file);
|
||||
});
|
||||
|
||||
screen.key('q', function() {
|
||||
return screen.destroy();
|
||||
});
|
||||
|
||||
screen.render();
|
||||
37
test/widget-insert.js
Normal file
@ -0,0 +1,37 @@
|
||||
var blessed = require('../');
|
||||
|
||||
var screen = blessed.screen({
|
||||
dump: __dirname + '/logs/insert.log',
|
||||
warnings: true
|
||||
});
|
||||
|
||||
var box = blessed.box({
|
||||
parent: screen,
|
||||
//align: 'center',
|
||||
style: {
|
||||
bg: 'blue'
|
||||
},
|
||||
height: 5,
|
||||
top: 'center',
|
||||
left: 0,
|
||||
width: 12,
|
||||
tags: true,
|
||||
content: '{yellow-fg}line{/yellow-fg}{|}1',
|
||||
//valign: 'middle'
|
||||
});
|
||||
|
||||
screen.render();
|
||||
|
||||
box.insertBottom('{yellow-fg}line{/yellow-fg}{|}2');
|
||||
box.insertTop('{yellow-fg}line{/yellow-fg}{|}0');
|
||||
|
||||
screen.render();
|
||||
|
||||
setTimeout(function() {
|
||||
box.deleteTop();
|
||||
screen.render();
|
||||
}, 2000);
|
||||
|
||||
screen.key('q', function() {
|
||||
screen.destroy();
|
||||
});
|
||||
165
test/widget-layout.js
Normal file
@ -0,0 +1,165 @@
|
||||
var blessed = require('../')
|
||||
, screen;
|
||||
|
||||
screen = blessed.screen({
|
||||
dump: __dirname + '/logs/layout.log',
|
||||
smartCSR: true,
|
||||
autoPadding: true,
|
||||
warnings: true
|
||||
});
|
||||
|
||||
var layout = blessed.layout({
|
||||
parent: screen,
|
||||
top: 'center',
|
||||
left: 'center',
|
||||
width: '50%',
|
||||
height: '50%',
|
||||
border: 'line',
|
||||
layout: process.argv[2] === 'grid' ? 'grid' : 'inline',
|
||||
style: {
|
||||
bg: 'red',
|
||||
border: {
|
||||
fg: 'blue'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var box1 = blessed.box({
|
||||
parent: layout,
|
||||
top: 'center',
|
||||
left: 'center',
|
||||
width: 20,
|
||||
height: 10,
|
||||
border: 'line',
|
||||
content: '1'
|
||||
});
|
||||
|
||||
var box2 = blessed.box({
|
||||
parent: layout,
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: 10,
|
||||
height: 5,
|
||||
border: 'line',
|
||||
content: '2'
|
||||
});
|
||||
|
||||
var box3 = blessed.box({
|
||||
parent: layout,
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: 10,
|
||||
height: 5,
|
||||
border: 'line',
|
||||
content: '3'
|
||||
});
|
||||
|
||||
var box4 = blessed.box({
|
||||
parent: layout,
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: 10,
|
||||
height: 5,
|
||||
border: 'line',
|
||||
content: '4'
|
||||
});
|
||||
|
||||
var box5 = blessed.box({
|
||||
parent: layout,
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: 10,
|
||||
height: 5,
|
||||
border: 'line',
|
||||
content: '5'
|
||||
});
|
||||
|
||||
var box6 = blessed.box({
|
||||
parent: layout,
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: 10,
|
||||
height: 5,
|
||||
border: 'line',
|
||||
content: '6'
|
||||
});
|
||||
|
||||
var box7 = blessed.box({
|
||||
parent: layout,
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: 10,
|
||||
height: 5,
|
||||
border: 'line',
|
||||
content: '7'
|
||||
});
|
||||
|
||||
var box8 = blessed.box({
|
||||
parent: layout,
|
||||
top: 'center',
|
||||
left: 'center',
|
||||
width: 20,
|
||||
height: 10,
|
||||
border: 'line',
|
||||
content: '8'
|
||||
});
|
||||
|
||||
var box9 = blessed.box({
|
||||
parent: layout,
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: 10,
|
||||
height: 5,
|
||||
border: 'line',
|
||||
content: '9'
|
||||
});
|
||||
|
||||
var box10 = blessed.box({
|
||||
parent: layout,
|
||||
top: 'center',
|
||||
left: 'center',
|
||||
width: 20,
|
||||
height: 10,
|
||||
border: 'line',
|
||||
content: '10'
|
||||
});
|
||||
|
||||
var box11 = blessed.box({
|
||||
parent: layout,
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: 10,
|
||||
height: 5,
|
||||
border: 'line',
|
||||
content: '11'
|
||||
});
|
||||
|
||||
var box12 = blessed.box({
|
||||
parent: layout,
|
||||
top: 'center',
|
||||
left: 'center',
|
||||
width: 20,
|
||||
height: 10,
|
||||
border: 'line',
|
||||
content: '12'
|
||||
});
|
||||
|
||||
if (process.argv[2] !== 'grid') {
|
||||
for (var i = 0; i < 10; i++) {
|
||||
blessed.box({
|
||||
parent: layout,
|
||||
// width: i % 2 === 0 ? 10 : 20,
|
||||
// height: i % 2 === 0 ? 5 : 10,
|
||||
width: Math.random() > 0.5 ? 10 : 20,
|
||||
height: Math.random() > 0.5 ? 5 : 10,
|
||||
border: 'line',
|
||||
content: (i + 1 + 12) + ''
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
screen.key('q', function() {
|
||||
return screen.destroy();
|
||||
});
|
||||
|
||||
screen.render();
|
||||
122
test/widget-listbar.js
Normal file
@ -0,0 +1,122 @@
|
||||
var blessed = require('../')
|
||||
, screen;
|
||||
|
||||
var auto = true;
|
||||
|
||||
screen = blessed.screen({
|
||||
dump: __dirname + '/logs/listbar.log',
|
||||
autoPadding: auto,
|
||||
warnings: true
|
||||
});
|
||||
|
||||
var box = blessed.box({
|
||||
parent: screen,
|
||||
top: 0,
|
||||
right: 0,
|
||||
width: 'shrink',
|
||||
height: 'shrink',
|
||||
content: '...'
|
||||
});
|
||||
|
||||
var bar = blessed.listbar({
|
||||
//parent: screen,
|
||||
bottom: 0,
|
||||
left: 3,
|
||||
right: 3,
|
||||
height: auto ? 'shrink' : 3,
|
||||
mouse: true,
|
||||
keys: true,
|
||||
autoCommandKeys: true,
|
||||
border: 'line',
|
||||
vi: true,
|
||||
style: {
|
||||
bg: 'green',
|
||||
item: {
|
||||
bg: 'red',
|
||||
hover: {
|
||||
bg: 'blue'
|
||||
},
|
||||
//focus: {
|
||||
// bg: 'blue'
|
||||
//}
|
||||
},
|
||||
selected: {
|
||||
bg: 'blue'
|
||||
}
|
||||
},
|
||||
commands: {
|
||||
'one': {
|
||||
keys: ['a'],
|
||||
callback: function() {
|
||||
box.setContent('Pressed one.');
|
||||
screen.render();
|
||||
}
|
||||
},
|
||||
'two': function() {
|
||||
box.setContent('Pressed two.');
|
||||
screen.render();
|
||||
},
|
||||
'three': function() {
|
||||
box.setContent('Pressed three.');
|
||||
screen.render();
|
||||
},
|
||||
'four': function() {
|
||||
box.setContent('Pressed four.');
|
||||
screen.render();
|
||||
},
|
||||
'five': function() {
|
||||
box.setContent('Pressed five.');
|
||||
screen.render();
|
||||
},
|
||||
'six': function() {
|
||||
box.setContent('Pressed six.');
|
||||
screen.render();
|
||||
},
|
||||
'seven': function() {
|
||||
box.setContent('Pressed seven.');
|
||||
screen.render();
|
||||
},
|
||||
'eight': function() {
|
||||
box.setContent('Pressed eight.');
|
||||
screen.render();
|
||||
},
|
||||
'nine': function() {
|
||||
box.setContent('Pressed nine.');
|
||||
screen.render();
|
||||
},
|
||||
'ten': function() {
|
||||
box.setContent('Pressed ten.');
|
||||
screen.render();
|
||||
},
|
||||
'eleven': function() {
|
||||
box.setContent('Pressed eleven.');
|
||||
screen.render();
|
||||
},
|
||||
'twelve': function() {
|
||||
box.setContent('Pressed twelve.');
|
||||
screen.render();
|
||||
},
|
||||
'thirteen': function() {
|
||||
box.setContent('Pressed thirteen.');
|
||||
screen.render();
|
||||
},
|
||||
'fourteen': function() {
|
||||
box.setContent('Pressed fourteen.');
|
||||
screen.render();
|
||||
},
|
||||
'fifteen': function() {
|
||||
box.setContent('Pressed fifteen.');
|
||||
screen.render();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
screen.append(bar);
|
||||
|
||||
bar.focus();
|
||||
|
||||
screen.key('q', function() {
|
||||
return screen.destroy();
|
||||
});
|
||||
|
||||
screen.render();
|
||||
100
test/widget-listtable.js
Normal file
@ -0,0 +1,100 @@
|
||||
var blessed = require('../')
|
||||
, screen;
|
||||
|
||||
screen = blessed.screen({
|
||||
dump: __dirname + '/logs/listtable.log',
|
||||
autoPadding: false,
|
||||
fullUnicode: true,
|
||||
warnings: true
|
||||
});
|
||||
|
||||
var DU = '杜';
|
||||
var JUAN = '鹃';
|
||||
|
||||
/*
|
||||
var box = blessed.box({
|
||||
parent: screen,
|
||||
top: 'center',
|
||||
left: 'center',
|
||||
data: null,
|
||||
border: 'line',
|
||||
align: 'center',
|
||||
tags: true,
|
||||
keys: true,
|
||||
width: '90%',
|
||||
height: '80%',
|
||||
style: {
|
||||
bg: 'red'
|
||||
}
|
||||
});
|
||||
*/
|
||||
|
||||
var table = blessed.listtable({
|
||||
//parent: screen,
|
||||
top: 'center',
|
||||
left: 'center',
|
||||
data: null,
|
||||
border: 'line',
|
||||
align: 'center',
|
||||
tags: true,
|
||||
keys: true,
|
||||
//width: '80%',
|
||||
width: 'shrink',
|
||||
height: '70%',
|
||||
vi: true,
|
||||
mouse: true,
|
||||
style: {
|
||||
border: {
|
||||
fg: 'red'
|
||||
},
|
||||
header: {
|
||||
fg: 'blue',
|
||||
bold: true
|
||||
},
|
||||
cell: {
|
||||
fg: 'magenta',
|
||||
selected: {
|
||||
bg: 'blue'
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var data1 = [
|
||||
[ 'Animals', 'Foods', 'Times' ],
|
||||
[ 'Elephant', 'Apple', '1:00am' ],
|
||||
[ 'Bird', 'Orange', '2:15pm' ],
|
||||
[ 'T-Rex', 'Taco', '8:45am' ],
|
||||
[ 'Mouse', 'Cheese', '9:05am' ]
|
||||
];
|
||||
|
||||
data1[1][0] = '{red-fg}' + data1[1][0] + '{/red-fg}';
|
||||
data1[2][0] += ' (' + DU + JUAN + ')';
|
||||
|
||||
var data2 = [
|
||||
[ 'Animals', 'Foods', 'Times', 'Numbers' ],
|
||||
[ 'Elephant', 'Apple', '1:00am', 'One' ],
|
||||
[ 'Bird', 'Orange', '2:15pm', 'Two' ],
|
||||
[ 'T-Rex', 'Taco', '8:45am', 'Three' ],
|
||||
[ 'Mouse', 'Cheese', '9:05am', 'Four' ]
|
||||
];
|
||||
|
||||
data2[1][0] = '{red-fg}' + data2[1][0] + '{/red-fg}';
|
||||
data2[2][0] += ' (' + DU + JUAN + ')';
|
||||
|
||||
screen.key('q', function() {
|
||||
return screen.destroy();
|
||||
});
|
||||
|
||||
table.focus();
|
||||
|
||||
table.setData(data2);
|
||||
|
||||
screen.append(table);
|
||||
|
||||
screen.render();
|
||||
|
||||
setTimeout(function() {
|
||||
table.setData(data1);
|
||||
screen.render();
|
||||
}, 3000);
|
||||