Compare commits
3147 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5bdf27fd78 | ||
|
|
f05783e64d | ||
|
|
c455fea729 | ||
|
|
5bf5454dbe | ||
|
|
b60d9f73ce | ||
|
|
31fe35cd38 | ||
|
|
607bc845fc | ||
|
|
a420d9d19c | ||
|
|
4b81e4936e | ||
|
|
295743a96e | ||
|
|
d3a1848c27 | ||
|
|
9cec924f32 | ||
|
|
67c963ab89 | ||
|
|
0f7ced25c1 | ||
|
|
42948ffff0 | ||
|
|
922ce5bdea | ||
|
|
1b42486026 | ||
|
|
95f1a971b2 | ||
|
|
7968c88c67 | ||
|
|
992e90b0a3 | ||
|
|
afada84f52 | ||
|
|
b978ff8930 | ||
|
|
053cede581 | ||
|
|
03720402a7 | ||
|
|
fca0999814 | ||
|
|
78056c659c | ||
|
|
30e1b4680d | ||
|
|
89a0c04d19 | ||
|
|
1ba027c277 | ||
|
|
d8e43a3412 | ||
|
|
644e46e91d | ||
|
|
e2a1f8dde7 | ||
|
|
7d09c6b762 | ||
|
|
6604e0d015 | ||
|
|
bb2ec9cde7 | ||
|
|
89a2545855 | ||
|
|
49f8c0eae6 | ||
|
|
268d687814 | ||
|
|
db5b4da388 | ||
|
|
71f8e50460 | ||
|
|
22fbdbca40 | ||
|
|
6253ee2a74 | ||
|
|
5b28aed0b1 | ||
|
|
9eabc9ecf1 | ||
|
|
a77852466c | ||
|
|
c68b82e4d0 | ||
|
|
16a4845a72 | ||
|
|
16da031f68 | ||
|
|
43b2935e52 | ||
|
|
8c7968a4d6 | ||
|
|
fba759a47c | ||
|
|
3bcb694b1b | ||
|
|
555020cfd5 | ||
|
|
391e2b8488 | ||
|
|
c856d5c058 | ||
|
|
f5a70adf0b | ||
|
|
e330c38d4a | ||
|
|
d595084395 | ||
|
|
b32ee5ee46 | ||
|
|
098dd10789 | ||
|
|
b5fa643c5d | ||
|
|
664dd29970 | ||
|
|
b7a4281985 | ||
|
|
9e9aa52553 | ||
|
|
77fbdfbb53 | ||
|
|
214416f1e3 | ||
|
|
800437ec6b | ||
|
|
957eafbef0 | ||
|
|
7f228bcbf5 | ||
|
|
fd4a682c5b | ||
|
|
ba9afc61a4 | ||
|
|
9a70709bba | ||
|
|
c437a36794 | ||
|
|
0e0578ff49 | ||
|
|
64a202a125 | ||
|
|
740d1ca146 | ||
|
|
7b75f055ea | ||
|
|
8d6a3cff25 | ||
|
|
10fdde6647 | ||
|
|
e1c45dc23f | ||
|
|
2efb8f6dc2 | ||
|
|
3b77f3b4bc | ||
|
|
31f763282f | ||
|
|
39434fb1f6 | ||
|
|
44ccdd36d6 | ||
|
|
4cc0138a28 | ||
|
|
6ca39d9d83 | ||
|
|
26c099639c | ||
|
|
329043ba08 | ||
|
|
e289f4959f | ||
|
|
b6760a59fa | ||
|
|
cd35f92607 | ||
|
|
ea8f223298 | ||
|
|
a4c3154dab | ||
|
|
6aa3405c78 | ||
|
|
da618584af | ||
|
|
9bc31a5651 | ||
|
|
314dd97059 | ||
|
|
0b66f20934 | ||
|
|
aba634ce88 | ||
|
|
033950dae9 | ||
|
|
a59e1adee1 | ||
|
|
5350eb29c1 | ||
|
|
2bb42e67d7 | ||
|
|
8745c4cd4a | ||
|
|
3288400005 | ||
|
|
1f499a7c6c | ||
|
|
012731c3be | ||
|
|
5deed81737 | ||
|
|
6f6e23bf61 | ||
|
|
d2d0487356 | ||
|
|
30df4e5de2 | ||
|
|
3f4588c408 | ||
|
|
4e4ca366d9 | ||
|
|
040ff0cc9d | ||
|
|
b01ad4bb3b | ||
|
|
4476251b76 | ||
|
|
0f4cb1955f | ||
|
|
c161ee7b5e | ||
|
|
a5bb2548a6 | ||
|
|
2898a3ef8c | ||
|
|
a0568334b5 | ||
|
|
4005cfdff2 | ||
|
|
1d8c5e65b9 | ||
|
|
56f45e8b0f | ||
|
|
48a9584688 | ||
|
|
bfcd324993 | ||
|
|
a75235a260 | ||
|
|
e8de2def96 | ||
|
|
5ffc4c6498 | ||
|
|
d0c50248ea | ||
|
|
ca2a121696 | ||
|
|
02d06d6726 | ||
|
|
18bf76d49e | ||
|
|
6961845167 | ||
|
|
4c5f7f50f7 | ||
|
|
572e920466 | ||
|
|
b81fb3c865 | ||
|
|
814dd8a275 | ||
|
|
1619687d1d | ||
|
|
65fc61a507 | ||
|
|
d027f524ce | ||
|
|
df5e6e1563 | ||
|
|
5541e3c2ff | ||
|
|
57dfc379ae | ||
|
|
b5467b8e26 | ||
|
|
a9f1928913 | ||
|
|
ae16fed39b | ||
|
|
848a795d26 | ||
|
|
deb8c3dacd | ||
|
|
3cb572b47a | ||
|
|
df3846fbb8 | ||
|
|
d73ceb26ae | ||
|
|
da9ffc9b93 | ||
|
|
63fa0c4e94 | ||
|
|
ce91b6d9d9 | ||
|
|
c982f24faf | ||
|
|
9f865adb83 | ||
|
|
b54dd1cb48 | ||
|
|
ef621aa099 | ||
|
|
df4738f080 | ||
|
|
8d0a06325c | ||
|
|
f3329fcd34 | ||
|
|
af48547d8b | ||
|
|
f228f8368a | ||
|
|
9bb2c1a27b | ||
|
|
aa0b07a90d | ||
|
|
d4075bfa9a | ||
|
|
2b7455e353 | ||
|
|
f42d2c63a6 | ||
|
|
6be3ae9efc | ||
|
|
2fd2e07342 | ||
|
|
1e0e32e282 | ||
|
|
b2d8f24499 | ||
|
|
12c99741a0 | ||
|
|
91dbcf4df0 | ||
|
|
6ebd82a84c | ||
|
|
c07178f43a | ||
|
|
78a5957863 | ||
|
|
cd6882d21e | ||
|
|
926a2828ab | ||
|
|
daa7df96d1 | ||
|
|
84ca83ef69 | ||
|
|
ac9c85e783 | ||
|
|
331f6d4903 | ||
|
|
2e422e5ba8 | ||
|
|
20cffc728e | ||
|
|
b06cbc9465 | ||
|
|
1348327414 | ||
|
|
cd3eeb7a95 | ||
|
|
7be6b28011 | ||
|
|
ef1bee0f48 | ||
|
|
702da542dd | ||
|
|
5ba92d06cf | ||
|
|
34a7b42063 | ||
|
|
963d1b58f8 | ||
|
|
fe598bac8a | ||
|
|
45736d7f1d | ||
|
|
0fe4f5a686 | ||
|
|
e9ce5c02d0 | ||
|
|
5916d82580 | ||
|
|
2c83b9902e | ||
|
|
fe07825ad9 | ||
|
|
56e83d7d07 | ||
|
|
c7e3c92a0a | ||
|
|
1a643441f3 | ||
|
|
2aee746da9 | ||
|
|
e64b1ba67c | ||
|
|
31be4f041e | ||
|
|
1f5ebc408d | ||
|
|
b4d9a22df8 | ||
|
|
d4168e3b80 | ||
|
|
241c7af855 | ||
|
|
080fcd8fc1 | ||
|
|
1aad4c7ec3 | ||
|
|
e0e0582b53 | ||
|
|
0a6276b007 | ||
|
|
2a2256f7d9 | ||
|
|
ed81a60065 | ||
|
|
5ad55dd165 | ||
|
|
6860f7ffd6 | ||
|
|
33a3e3fb61 | ||
|
|
d4df3f67b6 | ||
|
|
f15a2f0c1f | ||
|
|
252288aff2 | ||
|
|
65a20a2407 | ||
|
|
5f180dbd9a | ||
|
|
ee4e9aa678 | ||
|
|
9f1c9529aa | ||
|
|
5bba1a0851 | ||
|
|
e9823eb40c | ||
|
|
14fc3f6ac4 | ||
|
|
74714f942a | ||
|
|
0d116e6ef0 | ||
|
|
06108d66b1 | ||
|
|
21eece4c6d | ||
|
|
4dd696e4e0 | ||
|
|
d04d4444af | ||
|
|
a487a78200 | ||
|
|
f06a72b418 | ||
|
|
3270c9a527 | ||
|
|
a7b7fb560a | ||
|
|
384eba6cd4 | ||
|
|
dc7e3ba1ec | ||
|
|
b1e0adcfdc | ||
|
|
2a5922ce92 | ||
|
|
93694925ce | ||
|
|
adfcbb004f | ||
|
|
6595898b73 | ||
|
|
81b33f1f6f | ||
|
|
a1c4ffec20 | ||
|
|
89854cca8b | ||
|
|
4fe5211ed7 | ||
|
|
795b32efd7 | ||
|
|
153064ef3a | ||
|
|
183a31c884 | ||
|
|
adf47bed89 | ||
|
|
cc297a8984 | ||
|
|
4ef17edace | ||
|
|
e56fa9d31f | ||
|
|
791d4b30fb | ||
|
|
a9a9f1ac00 | ||
|
|
fd6bc55db6 | ||
|
|
97d7329d14 | ||
|
|
609d42e2bc | ||
|
|
3463931dad | ||
|
|
f637bf2377 | ||
|
|
2271eb5e60 | ||
|
|
a5cbb552f0 | ||
|
|
e43ca5b031 | ||
|
|
cc7e668ad6 | ||
|
|
a01dbbdf04 | ||
|
|
e0ce0a67cc | ||
|
|
0d83a8866b | ||
|
|
f7a7e39a36 | ||
|
|
67cb466ea9 | ||
|
|
376688ab9f | ||
|
|
8668087d15 | ||
|
|
9b1c23987c | ||
|
|
784daa1a4b | ||
|
|
06f9b73a7b | ||
|
|
62c0272df2 | ||
|
|
7ce2b4c641 | ||
|
|
08c2de541f | ||
|
|
94551623ec | ||
|
|
cb0d23bae8 | ||
|
|
cb5157f2d1 | ||
|
|
32dcbbb5e1 | ||
|
|
4eedf0d36c | ||
|
|
be458303c5 | ||
|
|
78542ede14 | ||
|
|
df8800b7ff | ||
|
|
9c30cd8891 | ||
|
|
dda28efd66 | ||
|
|
b78183972c | ||
|
|
fc06196a3e | ||
|
|
2a1809a2d8 | ||
|
|
ac5c312267 | ||
|
|
8f3174038b | ||
|
|
2d8113e0e0 | ||
|
|
e881850bb4 | ||
|
|
4cbae1db89 | ||
|
|
97bce7be18 | ||
|
|
5d2a276172 | ||
|
|
762dfe8315 | ||
|
|
1c0d1ec8a9 | ||
|
|
e650699217 | ||
|
|
5ff2b5be1c | ||
|
|
f1841d7c81 | ||
|
|
fd6231a778 | ||
|
|
751a52153d | ||
|
|
61b733bae9 | ||
|
|
624e96df9b | ||
|
|
a3f1a44d83 | ||
|
|
ed1547938e | ||
|
|
f96a13e9e4 | ||
|
|
7b70ed96b6 | ||
|
|
9379853d47 | ||
|
|
6ccfebd9e3 | ||
|
|
45186a17ca | ||
|
|
24bb4585af | ||
|
|
feb96f1be8 | ||
|
|
b7d3d64975 | ||
|
|
6114b49630 | ||
|
|
87d95caae0 | ||
|
|
9535bc94ff | ||
|
|
0841be7803 | ||
|
|
6cec89181b | ||
|
|
cb78e17594 | ||
|
|
285c399ae5 | ||
|
|
c9b14f6f78 | ||
|
|
6a101c51d2 | ||
|
|
8998970adc | ||
|
|
991fbacb99 | ||
|
|
72f3e8cd40 | ||
|
|
cf8113ea24 | ||
|
|
5d1cf49fb6 | ||
|
|
90f3c0f9af | ||
|
|
d02598688a | ||
|
|
1991f1ccd7 | ||
|
|
8fad8972d5 | ||
|
|
fc3e78e226 | ||
|
|
15aace29a1 | ||
|
|
12a3a2d7fe | ||
|
|
7e26a340a3 | ||
|
|
f0764c24d2 | ||
|
|
d080bf3b9c | ||
|
|
51698dff07 | ||
|
|
4154926be7 | ||
|
|
806ca2b224 | ||
|
|
92bbf08343 | ||
|
|
dc84e3de67 | ||
|
|
8011801549 | ||
|
|
dfec88ed15 | ||
|
|
5d3e2c7111 | ||
|
|
af1c48e0f7 | ||
|
|
d4bc906c5c | ||
|
|
62fe467336 | ||
|
|
ef3e9d1c2e | ||
|
|
09ddbbf600 | ||
|
|
4195c239c8 | ||
|
|
a6c3c57d40 | ||
|
|
de9263a117 | ||
|
|
7b7f1ecc54 | ||
|
|
d1b028c27a | ||
|
|
055aae2382 | ||
|
|
dbb084da7a | ||
|
|
8332cd2f79 | ||
|
|
4e29c0c16b | ||
|
|
320d45a3f5 | ||
|
|
73795b5257 | ||
|
|
16e59784c6 | ||
|
|
65a7ec3f85 | ||
|
|
360ff35061 | ||
|
|
5098792723 | ||
|
|
a4883e6d41 | ||
|
|
44c9d66dd4 | ||
|
|
c7718d078c | ||
|
|
2525994db4 | ||
|
|
81e6afa9b3 | ||
|
|
d8f5ccf9e4 | ||
|
|
774489c578 | ||
|
|
39bb0ecfcf | ||
|
|
b222ab1bf6 | ||
|
|
7a31c7ff50 | ||
|
|
132f87d152 | ||
|
|
aedda4bf9b | ||
|
|
40bba70bfe | ||
|
|
8202247b27 | ||
|
|
e2117ee8a4 | ||
|
|
e3a4150fea | ||
|
|
0ce2a23af3 | ||
|
|
6b2337c9c0 | ||
|
|
54661b7fc4 | ||
|
|
a1f895b781 | ||
|
|
199c271edc | ||
|
|
9ac744ae63 | ||
|
|
93b05bcd1e | ||
|
|
546cdbefae | ||
|
|
352c07987b | ||
|
|
f6a1eb19d7 | ||
|
|
a352804c14 | ||
|
|
28ae8c4d20 | ||
|
|
1eef584382 | ||
|
|
4e1cd0590b | ||
|
|
fa670e1f5d | ||
|
|
c7fa6f620a | ||
|
|
04690c8c7c | ||
|
|
4345ea6602 | ||
|
|
d39c212336 | ||
|
|
54d2f06abe | ||
|
|
237bfc9a6e | ||
|
|
29b3d49cd5 | ||
|
|
fe8892ec54 | ||
|
|
2d8dd7a53e | ||
|
|
b493599690 | ||
|
|
d9371dc265 | ||
|
|
ef2a12fbdf | ||
|
|
7215c6d6be | ||
|
|
bd9e1f58fe | ||
|
|
79dec269e1 | ||
|
|
d6ffbf4f3c | ||
|
|
32588939ae | ||
|
|
a02e07bfe8 | ||
|
|
03df0c3cca | ||
|
|
1aa50b73a1 | ||
|
|
c910f483bf | ||
|
|
14f4a8d28e | ||
|
|
ee931a17b0 | ||
|
|
0a2ba3fb66 | ||
|
|
512db660a1 | ||
|
|
b0666c9180 | ||
|
|
57d3d09679 | ||
|
|
3a17f54bca | ||
|
|
4c2800b294 | ||
|
|
8358377ec3 | ||
|
|
3ab12c616c | ||
|
|
ef4e784121 | ||
|
|
1ead20a5b9 | ||
|
|
31dfee8a95 | ||
|
|
d6492264c7 | ||
|
|
7281b9dbb1 | ||
|
|
4b63ee036e | ||
|
|
fb8eb69c20 | ||
|
|
4b1fa2609d | ||
|
|
a8b756f040 | ||
|
|
a94a0f3026 | ||
|
|
71c902eaf8 | ||
|
|
6e7af8ce2e | ||
|
|
6c80cd040c | ||
|
|
4ed413eaa7 | ||
|
|
86357d2c38 | ||
|
|
c0d4d01b88 | ||
|
|
b3fcb53625 | ||
|
|
4f29dea8ef | ||
|
|
4f8ef05058 | ||
|
|
7fc1735a21 | ||
|
|
1e49038747 | ||
|
|
295fbe42ad | ||
|
|
60d33f2847 | ||
|
|
cd369f633a | ||
|
|
c3df6d2fe3 | ||
|
|
72dfa74b3e | ||
|
|
1411269187 | ||
|
|
185d959f25 | ||
|
|
1652d41992 | ||
|
|
297dea881d | ||
|
|
01df828353 | ||
|
|
617115d447 | ||
|
|
31f9978599 | ||
|
|
dc068c16e8 | ||
|
|
89626a462f | ||
|
|
a043588b4a | ||
|
|
2e08ee16c2 | ||
|
|
2cc506476b | ||
|
|
0a462ad706 | ||
|
|
81c1bfe1c5 | ||
|
|
8ce80e39d9 | ||
|
|
fa823a37ae | ||
|
|
17f67fbe28 | ||
|
|
560b78bc35 | ||
|
|
f023f047ff | ||
|
|
5673359be2 | ||
|
|
666696d142 | ||
|
|
f95bc48f9b | ||
|
|
8d18fc09fa | ||
|
|
a3d42a90f2 | ||
|
|
1da5f2ecc6 | ||
|
|
d226e82f68 | ||
|
|
60cc2cb26c | ||
|
|
1ac90cf464 | ||
|
|
d3ffaebd17 | ||
|
|
bf01c549f5 | ||
|
|
6912d8c086 | ||
|
|
a89e1b5573 | ||
|
|
3a9c6088b2 | ||
|
|
fba629f385 | ||
|
|
90477825c2 | ||
|
|
1e56d39777 | ||
|
|
2829971412 | ||
|
|
c147fda6ca | ||
|
|
a27dfd8b7c | ||
|
|
a7c65efc45 | ||
|
|
646a524c8e | ||
|
|
f8d01d2c4f | ||
|
|
1d846f3744 | ||
|
|
6bbe58f876 | ||
|
|
36719fb086 | ||
|
|
78fd7a8458 | ||
|
|
f5976d0d63 | ||
|
|
b313fc3fbe | ||
|
|
cf667b8c47 | ||
|
|
7e3bd8586f | ||
|
|
d5df301317 | ||
|
|
628246c3da | ||
|
|
d228acd30a | ||
|
|
18cd97d914 | ||
|
|
5f13946bac | ||
|
|
8fb24fbc1e | ||
|
|
f0d4952055 | ||
|
|
7113580db2 | ||
|
|
163c211219 | ||
|
|
6993157b3a | ||
|
|
e2efdf674d | ||
|
|
9fcb8e5b6e | ||
|
|
a1a637c7f1 | ||
|
|
4f87f3e9f4 | ||
|
|
da6faa656c | ||
|
|
e1ad75e932 | ||
|
|
646bdbd002 | ||
|
|
9184de1997 | ||
|
|
eabc29ec4d | ||
|
|
e338cdab31 | ||
|
|
7001d609fa | ||
|
|
c8399ce3d2 | ||
|
|
3e1d701dce | ||
|
|
a385c39c2e | ||
|
|
5d1cf339a7 | ||
|
|
fafb8518e0 | ||
|
|
6807f4d4ea | ||
|
|
0ed7b2f3c0 | ||
|
|
116128ebb5 | ||
|
|
0c870c5fcd | ||
|
|
90bc3ab770 | ||
|
|
0021b0c242 | ||
|
|
6dc076f5d1 | ||
|
|
2dd1201c3f | ||
|
|
9be68966b4 | ||
|
|
47d482dca9 | ||
|
|
18dd13c872 | ||
|
|
c71bb877c3 | ||
|
|
eee8106f9e | ||
|
|
80ad596d3d | ||
|
|
9dbafcc368 | ||
|
|
9f5f113840 | ||
|
|
6afbdbe94f | ||
|
|
061a0c8cb6 | ||
|
|
ad128a3c29 | ||
|
|
b71d2e04ca | ||
|
|
cc3c7b0286 | ||
|
|
bf6c90a69a | ||
|
|
4c9a75c1ba | ||
|
|
98f46f8bd7 | ||
|
|
dec62b1929 | ||
|
|
79f7954048 | ||
|
|
fc217dafba | ||
|
|
a6aff817cf | ||
|
|
38cb18fe92 | ||
|
|
20b6a97159 | ||
|
|
98f6e24106 | ||
|
|
4ed6364b61 | ||
|
|
cd7751681d | ||
|
|
76531d2f7a | ||
|
|
eea652f1d0 | ||
|
|
f20f4762a8 | ||
|
|
c004fd1f4d | ||
|
|
f29039db29 | ||
|
|
fbf1ec43c7 | ||
|
|
a42200a430 | ||
|
|
ad576c333c | ||
|
|
5a0a980648 | ||
|
|
b3578a4fa5 | ||
|
|
3c952b01d3 | ||
|
|
b1453a51f6 | ||
|
|
2c3a7b5f41 | ||
|
|
0df5a6c6c8 | ||
|
|
bf4dc6365a | ||
|
|
ce3322bf91 | ||
|
|
835cb31501 | ||
|
|
762dd065f3 | ||
|
|
7b91447d89 | ||
|
|
1146c4ea3f | ||
|
|
729f7b8e03 | ||
|
|
d3ec632b9f | ||
|
|
cb01b5ee44 | ||
|
|
0828096e9e | ||
|
|
ebcbed290f | ||
|
|
d6afe6f2cb | ||
|
|
4daf70f636 | ||
|
|
2f3dd72c84 | ||
|
|
dca8c65376 | ||
|
|
12d8175d9a | ||
|
|
609bcd68dd | ||
|
|
313136803c | ||
|
|
b937033411 | ||
|
|
55eeb9c11e | ||
|
|
8fbec2dfd5 | ||
|
|
c4521290b8 | ||
|
|
e12a9f3caf | ||
|
|
56f8a06362 | ||
|
|
5c4abe749b | ||
|
|
62c27b3db7 | ||
|
|
1283a2b7e5 | ||
|
|
bec620a8d3 | ||
|
|
6b0bb2e845 | ||
|
|
135818f34b | ||
|
|
2a361d1de1 | ||
|
|
761a941d43 | ||
|
|
c03630a487 | ||
|
|
0b79cbdb3b | ||
|
|
1dc6b49e02 | ||
|
|
1962f8e5a0 | ||
|
|
cabfcbcb69 | ||
|
|
48bb43a2c4 | ||
|
|
af5e3e0c18 | ||
|
|
fb8398c2eb | ||
|
|
eefd4bb3e3 | ||
|
|
581c388838 | ||
|
|
7a63ea6480 | ||
|
|
65f1329635 | ||
|
|
0df9a5d5c5 | ||
|
|
6405849a1b | ||
|
|
e9340dfaaf | ||
|
|
0509855930 | ||
|
|
4c74462763 | ||
|
|
7f69381221 | ||
|
|
75942fb47e | ||
|
|
0893d7164a | ||
|
|
27906ea853 | ||
|
|
8540ca3990 | ||
|
|
e82c5a63b5 | ||
|
|
83602d7e53 | ||
|
|
64e30e5299 | ||
|
|
83ce23ff9f | ||
|
|
c5e5ec618d | ||
|
|
bd84ec03ce | ||
|
|
d71f18566e | ||
|
|
76e75d9f89 | ||
|
|
f5695ac4f4 | ||
|
|
b748cd21cf | ||
|
|
3a8bdf3b48 | ||
|
|
196c6b07aa | ||
|
|
1978cc5b55 | ||
|
|
ea47cee23f | ||
|
|
e6844ad6f2 | ||
|
|
02d5b3eafa | ||
|
|
151dacf17f | ||
|
|
117d1b02be | ||
|
|
cb55878efd | ||
|
|
ea4751eae5 | ||
|
|
cc4f1c0a24 | ||
|
|
3eb5320e29 | ||
|
|
4f63cff1a4 | ||
|
|
8381171c8d | ||
|
|
1b2d54d97a | ||
|
|
e7da874b82 | ||
|
|
ea8bed2a71 | ||
|
|
c747e681a2 | ||
|
|
a9a9ec80b5 | ||
|
|
eb84990f5a | ||
|
|
1938ba3108 | ||
|
|
0eee2db199 | ||
|
|
bba1455e28 | ||
|
|
8c41cc8d3e | ||
|
|
5efcb35cfb | ||
|
|
1b4cf1fea7 | ||
|
|
d3656bf7e9 | ||
|
|
aaffec1cbc | ||
|
|
ed9391d4d6 | ||
|
|
58333f260b | ||
|
|
cf8ccabad9 | ||
|
|
600c595fdf | ||
|
|
2427d2d9da | ||
|
|
4ca70bfa26 | ||
|
|
4e8eb2f7f0 | ||
|
|
b6cf4bc78f | ||
|
|
622cd5531a | ||
|
|
ec35b0cc7c | ||
|
|
0719c7f8bb | ||
|
|
bb7e4039e8 | ||
|
|
a0559e506b | ||
|
|
4ce4176bbe | ||
|
|
99409f0a8b | ||
|
|
13303416b8 | ||
|
|
9811d677e5 | ||
|
|
b9fd039668 | ||
|
|
6c1f20bb27 | ||
|
|
2b58316c64 | ||
|
|
f2df629634 | ||
|
|
8f46505a50 | ||
|
|
c48bf4fd85 | ||
|
|
8c67f5aea8 | ||
|
|
76f84e32c4 | ||
|
|
4a7125ec92 | ||
|
|
92c3af6a92 | ||
|
|
443f36ebc7 | ||
|
|
17632dea3c | ||
|
|
bb78dc5ccb | ||
|
|
2737cb7dd0 | ||
|
|
08b2ce444f | ||
|
|
289028b468 | ||
|
|
2b3be147e6 | ||
|
|
1a2d9c6fba | ||
|
|
af15b0313a | ||
|
|
b080296326 | ||
|
|
516e0e8bb3 | ||
|
|
57e23bd4e3 | ||
|
|
59534d620e | ||
|
|
068b7e8d63 | ||
|
|
2c1edb9611 | ||
|
|
510022c3c1 | ||
|
|
627c79ffbb | ||
|
|
e80cd36237 | ||
|
|
92ebada9a6 | ||
|
|
462ae3bb58 | ||
|
|
6d6d9cc26b | ||
|
|
a36d5dcde1 | ||
|
|
f9f6f98527 | ||
|
|
ee94114eb2 | ||
|
|
8e98fcf2f6 | ||
|
|
c4710bf9cb | ||
|
|
97a568a405 | ||
|
|
7bace19aed | ||
|
|
7282f1f684 | ||
|
|
9edb772a81 | ||
|
|
d123b6c377 | ||
|
|
c9ba3695d3 | ||
|
|
0ee970b418 | ||
|
|
8239cb1b5a | ||
|
|
97caa073b0 | ||
|
|
45bbe17559 | ||
|
|
288d16f7be | ||
|
|
ecb60b313e | ||
|
|
cf2a20e4ea | ||
|
|
bc4f40fea7 | ||
|
|
102097da5a | ||
|
|
0e3528df14 | ||
|
|
214631c2dd | ||
|
|
e919857dfc | ||
|
|
a5bd1dcb08 | ||
|
|
37cdaea9ed | ||
|
|
6bbaf5f1cf | ||
|
|
8808a252ae | ||
|
|
5f1376b9a0 | ||
|
|
efa873bf50 | ||
|
|
714461de76 | ||
|
|
b753cf6879 | ||
|
|
27010d0446 | ||
|
|
bdc039fbf5 | ||
|
|
72f92f3174 | ||
|
|
8fcd5e40d4 | ||
|
|
b76319b7e8 | ||
|
|
feeb8f28c4 | ||
|
|
55b21b741e | ||
|
|
6941884221 | ||
|
|
6174c2008f | ||
|
|
1a32e79470 | ||
|
|
dd032db89c | ||
|
|
f70e0e216c | ||
|
|
51362706d7 | ||
|
|
b2c317ebc6 | ||
|
|
90acbd0dd5 | ||
|
|
402fac3edf | ||
|
|
c4c62c1505 | ||
|
|
b569c01b49 | ||
|
|
c0d9b6e979 | ||
|
|
b94afbba13 | ||
|
|
1994c17c75 | ||
|
|
f88a4fe986 | ||
|
|
25616aaa7b | ||
|
|
19fdcec358 | ||
|
|
45eb4a0760 | ||
|
|
9e026983e6 | ||
|
|
be0a524e23 | ||
|
|
339af1b4b2 | ||
|
|
31fda568e4 | ||
|
|
3efbccc850 | ||
|
|
93c23f99cb | ||
|
|
6590d0690e | ||
|
|
230a9f4678 | ||
|
|
f2189b3e70 | ||
|
|
0ee5712e00 | ||
|
|
f9cad2c4ea | ||
|
|
4372cf2893 | ||
|
|
34c18bacd8 | ||
|
|
3af11e92d6 | ||
|
|
74d5f2c259 | ||
|
|
291f9e9a5e | ||
|
|
38e1d32065 | ||
|
|
b45fedd794 | ||
|
|
df9b13fb74 | ||
|
|
53788c4c89 | ||
|
|
831043b773 | ||
|
|
1daf745d74 | ||
|
|
d6c5b40ead | ||
|
|
57ea524464 | ||
|
|
e19ce6cce6 | ||
|
|
8d4f6681e8 | ||
|
|
9c855a8377 | ||
|
|
716813e38a | ||
|
|
e5322cdc52 | ||
|
|
b5701691c6 | ||
|
|
aab9482e31 | ||
|
|
775584b5a5 | ||
|
|
25f022cc14 | ||
|
|
981ad88309 | ||
|
|
e71b9091a3 | ||
|
|
bde468594e | ||
|
|
0fcfe104e3 | ||
|
|
4cf54d2dfb | ||
|
|
b866c3e783 | ||
|
|
c15a31e725 | ||
|
|
afaf866b15 | ||
|
|
af6b1837cb | ||
|
|
aab6f3e450 | ||
|
|
829ed0ec0d | ||
|
|
d9899cb489 | ||
|
|
1a370ea9b6 | ||
|
|
cc07b1f79d | ||
|
|
3ddea42660 | ||
|
|
236dbd95c9 | ||
|
|
6b078c4267 | ||
|
|
1dec5f2e08 | ||
|
|
e5f70b7306 | ||
|
|
e2bb856e41 | ||
|
|
88d597f6b2 | ||
|
|
d0c0b01724 | ||
|
|
4b7c50518e | ||
|
|
a1bfcd9fc5 | ||
|
|
eb024fa40a | ||
|
|
122475ad4d | ||
|
|
f7114bc1c5 | ||
|
|
feea6998f8 | ||
|
|
e187110611 | ||
|
|
c19e69855a | ||
|
|
7788f48dd5 | ||
|
|
073eecb6bb | ||
|
|
030e7e2db3 | ||
|
|
aead3c1c35 | ||
|
|
587f44ad4e | ||
|
|
c9ef4aa8c8 | ||
|
|
aabadd8517 | ||
|
|
b8866371a3 | ||
|
|
0f3883af02 | ||
|
|
5876ce0845 | ||
|
|
2c72c56e22 | ||
|
|
f15ce21da1 | ||
|
|
b3fa7310cb | ||
|
|
ade38870a0 | ||
|
|
11bc1b100c | ||
|
|
93a7b220c9 | ||
|
|
8f92c594f2 | ||
|
|
afebea8635 | ||
|
|
5d76cfb578 | ||
|
|
f085f853bd | ||
|
|
4ac2312b2a | ||
|
|
c6dcbe6521 | ||
|
|
49efbf0c6e | ||
|
|
1d8d669a43 | ||
|
|
f4d44f30b4 | ||
|
|
4c77b0c562 | ||
|
|
2f367fa90c | ||
|
|
970ec9c839 | ||
|
|
be52f29792 | ||
|
|
8ae2f06828 | ||
|
|
601b2a05ac | ||
|
|
b78fbb4521 | ||
|
|
c40ef01445 | ||
|
|
ab8a4c6b9f | ||
|
|
dd331ca12e | ||
|
|
c3b23679f3 | ||
|
|
d0398dca28 | ||
|
|
e66c732b41 | ||
|
|
e7b216ba68 | ||
|
|
838a85ee8b | ||
|
|
3ec93e0b4e | ||
|
|
e8a9bbb51d | ||
|
|
25c2a0e241 | ||
|
|
de12dddbef | ||
|
|
24eeeedb1f | ||
|
|
c2bc24de35 | ||
|
|
21446e36c1 | ||
|
|
0f734719e7 | ||
|
|
f3c96f308d | ||
|
|
8ff841f1ac | ||
|
|
709c4abb53 | ||
|
|
c1f06941f5 | ||
|
|
ecb74aed29 | ||
|
|
c72154782b | ||
|
|
9520006466 | ||
|
|
40f04284d4 | ||
|
|
832534aac9 | ||
|
|
6cc89416ce | ||
|
|
b3fc2cb118 | ||
|
|
69efd9801b | ||
|
|
c07f164154 | ||
|
|
a2d1140229 | ||
|
|
bae9b095b4 | ||
|
|
efe6ff6188 | ||
|
|
3257fdf24f | ||
|
|
3284d71300 | ||
|
|
cdb3e2c1cd | ||
|
|
57cffc71b7 | ||
|
|
a4f1caeb4e | ||
|
|
45de091ee6 | ||
|
|
00c1802319 | ||
|
|
02c2d24360 | ||
|
|
499c255e81 | ||
|
|
30cad2e0a6 | ||
|
|
6e838b83d8 | ||
|
|
5297223ee3 | ||
|
|
2340d5be8d | ||
|
|
7de1a145aa | ||
|
|
32426d61c3 | ||
|
|
3ce47660a0 | ||
|
|
0dff455ffa | ||
|
|
81739288e8 | ||
|
|
5641668bc1 | ||
|
|
5c03a52a0b | ||
|
|
087b52e3e0 | ||
|
|
733b8e7c1c | ||
|
|
aa83f42f2d | ||
|
|
4ed2854791 | ||
|
|
73cdd87d91 | ||
|
|
51c8e3b2c6 | ||
|
|
e522095fae | ||
|
|
6fc1226028 | ||
|
|
fb40280d3c | ||
|
|
746cb3684a | ||
|
|
16c6545e93 | ||
|
|
0c4b20aa4e | ||
|
|
15e3e8d8b1 | ||
|
|
6123de52c2 | ||
|
|
3db0aab24b | ||
|
|
ae77f696ce | ||
|
|
98369db7f5 | ||
|
|
bc9d6892d4 | ||
|
|
5c02c370d4 | ||
|
|
b944cdddeb | ||
|
|
a1d203d34a | ||
|
|
e151b8e604 | ||
|
|
3c67e991c2 | ||
|
|
cb7aed3234 | ||
|
|
ff80b906d0 | ||
|
|
8300436481 | ||
|
|
6b13454091 | ||
|
|
9eae4ad913 | ||
|
|
bfb8532c52 | ||
|
|
c41405fd57 | ||
|
|
276ba7754a | ||
|
|
8569be81ea | ||
|
|
a765d551e4 | ||
|
|
4309aa1ace | ||
|
|
6ef83a09d3 | ||
|
|
adcc616c92 | ||
|
|
6dc1617429 | ||
|
|
1837168b0b | ||
|
|
1be1864657 | ||
|
|
49c335972f | ||
|
|
aabc99c7bf | ||
|
|
7c91dc6183 | ||
|
|
ff8a99211d | ||
|
|
efda0ea455 | ||
|
|
906be21b8d | ||
|
|
5a36fbfe7b | ||
|
|
f9f69a0577 | ||
|
|
8ccbb96b8d | ||
|
|
8ae7256fd6 | ||
|
|
ba401c19c2 | ||
|
|
11343d42c3 | ||
|
|
6c628bc594 | ||
|
|
f6cbca1aeb | ||
|
|
51e7c8c136 | ||
|
|
f952694ffd | ||
|
|
59afdfc4e9 | ||
|
|
27ec1e4b3c | ||
|
|
e791a8a7bb | ||
|
|
66fe53ceb1 | ||
|
|
de3cc11423 | ||
|
|
901eae9604 | ||
|
|
1962519666 | ||
|
|
1e84cbe2ab | ||
|
|
06da2b88ff | ||
|
|
91b9110dcc | ||
|
|
d57abb56ce | ||
|
|
f6edb774fc | ||
|
|
ec0f3e9128 | ||
|
|
6f1404d17b | ||
|
|
3d9e47c295 | ||
|
|
afa6128155 | ||
|
|
72b1996423 | ||
|
|
6b1a9d635e | ||
|
|
dea79f16d0 | ||
|
|
2d772d7243 | ||
|
|
09fb246c8f | ||
|
|
0a5c16363c | ||
|
|
b444f4636e | ||
|
|
2b8acebd6e | ||
|
|
766010c292 | ||
|
|
0a2768e496 | ||
|
|
0fd7f3f7b5 | ||
|
|
d3472966d3 | ||
|
|
576ab24609 | ||
|
|
621453b068 | ||
|
|
6638546247 | ||
|
|
f99edbae3c | ||
|
|
150bf1a5b0 | ||
|
|
91a17e3f0c | ||
|
|
7160027c14 | ||
|
|
736d6cf7e6 | ||
|
|
82de6a1c56 | ||
|
|
1fbb4f763e | ||
|
|
20582431d6 | ||
|
|
7d9cf0b064 | ||
|
|
a834f221f1 | ||
|
|
c95dca4023 | ||
|
|
c05c0353fd | ||
|
|
e944e2ecae | ||
|
|
47b3c37bf0 | ||
|
|
190666dc8a | ||
|
|
8c6e7ce61a | ||
|
|
04ead526b9 | ||
|
|
135fb7e6e4 | ||
|
|
ce1e22ac95 | ||
|
|
a216f6bd46 | ||
|
|
c47e5372b5 | ||
|
|
daa673eff1 | ||
|
|
5099dd6aa3 | ||
|
|
f982e754e4 | ||
|
|
4a1ad7755a | ||
|
|
946589d1f1 | ||
|
|
7168ceab94 | ||
|
|
868d57b818 | ||
|
|
6057c57ea4 | ||
|
|
e8437fd435 | ||
|
|
9e317971b4 | ||
|
|
bdb55a02fa | ||
|
|
02e062af65 | ||
|
|
54c5faa12d | ||
|
|
9b0bd81661 | ||
|
|
52da68876d | ||
|
|
2780630a18 | ||
|
|
8f77cc65e2 | ||
|
|
7224363639 | ||
|
|
43851fc1c4 | ||
|
|
e33bf11012 | ||
|
|
0e21376538 | ||
|
|
7a463c1240 | ||
|
|
8e03da855f | ||
|
|
942881d1b7 | ||
|
|
2a50203fcd | ||
|
|
08ce8ffa54 | ||
|
|
90561682cf | ||
|
|
71027e74e0 | ||
|
|
be8bfbe370 | ||
|
|
f7e4447b66 | ||
|
|
df4e58bc39 | ||
|
|
441ea7d696 | ||
|
|
2b06ca5e1a | ||
|
|
434ef97952 | ||
|
|
e1504c4775 | ||
|
|
74f0057ec8 | ||
|
|
7cd74cb852 | ||
|
|
b2e74e4830 | ||
|
|
f54a3e8036 | ||
|
|
f3088c5646 | ||
|
|
db00adaf69 | ||
|
|
ea74add814 | ||
|
|
ba1b3c3c2d | ||
|
|
d5c48ddb94 | ||
|
|
9687318b22 | ||
|
|
f6fb36c58a | ||
|
|
c8a258f36b | ||
|
|
14e0b01b40 | ||
|
|
76de99a5a8 | ||
|
|
8613c6e1cd | ||
|
|
5bb6b29ca3 | ||
|
|
61558d518e | ||
|
|
3b724c8415 | ||
|
|
910565aa7c | ||
|
|
c7a2e060e3 | ||
|
|
740e787f54 | ||
|
|
bd87d50948 | ||
|
|
d3c0c422a5 | ||
|
|
72718cbab7 | ||
|
|
ea28951e0e | ||
|
|
39a78f6be3 | ||
|
|
fe8aaca320 | ||
|
|
f5cc58ea9d | ||
|
|
44992452cf | ||
|
|
f080871911 | ||
|
|
6789eb88e2 | ||
|
|
1a97be4a25 | ||
|
|
c9ef5c0715 | ||
|
|
0a9f8d4f6a | ||
|
|
cac2c153c2 | ||
|
|
f2d6ba8775 | ||
|
|
92abaad22c | ||
|
|
3df0194f6e | ||
|
|
f774841ee0 | ||
|
|
a9de91087a | ||
|
|
76a536ece0 | ||
|
|
719339e116 | ||
|
|
1c3910de5c | ||
|
|
39d3ef6fe8 | ||
|
|
064d0fa6f1 | ||
|
|
99a5843595 | ||
|
|
39e75e39e8 | ||
|
|
322a80e76e | ||
|
|
d4b048735d | ||
|
|
c23e04fd03 | ||
|
|
f67009f554 | ||
|
|
4013544efb | ||
|
|
31d9db7e74 | ||
|
|
384c56f834 | ||
|
|
3282c8200d | ||
|
|
ffbc9174f8 | ||
|
|
dceb00f669 | ||
|
|
920086ae88 | ||
|
|
a1311a2332 | ||
|
|
4c392426f6 | ||
|
|
4528173ff5 | ||
|
|
d3b63a9c45 | ||
|
|
c30a249cf6 | ||
|
|
20962d989f | ||
|
|
a1e4b19486 | ||
|
|
fd0262413e | ||
|
|
aa4d36cc57 | ||
|
|
8d119f06b3 | ||
|
|
708c5126b9 | ||
|
|
577de9f746 | ||
|
|
38a70f5b51 | ||
|
|
118306a9ff | ||
|
|
704717ff1d | ||
|
|
405c472d13 | ||
|
|
17c994db57 | ||
|
|
e227264bad | ||
|
|
8751ea79e7 | ||
|
|
3b3ffa7455 | ||
|
|
4322825ac7 | ||
|
|
d29fa7b382 | ||
|
|
08bb63fa92 | ||
|
|
5dde31f80c | ||
|
|
3bb869f725 | ||
|
|
11686b90f7 | ||
|
|
6df78fa67c | ||
|
|
53b1607c4d | ||
|
|
2341a27f63 | ||
|
|
0661caf9da | ||
|
|
5b5bd77c53 | ||
|
|
d36f6b39c7 | ||
|
|
b2a5b07f92 | ||
|
|
46889a3a32 | ||
|
|
958ebb72a6 | ||
|
|
febc5c53a6 | ||
|
|
6e921300e2 | ||
|
|
e167dec8a9 | ||
|
|
0019f07cc0 | ||
|
|
20fc1e6b0c | ||
|
|
908946a067 | ||
|
|
f1df7b1c1f | ||
|
|
65b9c69bd8 | ||
|
|
b91e47c3b6 | ||
|
|
0e3a11c53b | ||
|
|
53d8d2aaad | ||
|
|
84303cbf2e | ||
|
|
5e457da30b | ||
|
|
855718b179 | ||
|
|
d037c0b0fc | ||
|
|
90f5937413 | ||
|
|
cbbea37b0c | ||
|
|
4d74b23f20 | ||
|
|
79dd26a43a | ||
|
|
259e3076fa | ||
|
|
f2cb2422f0 | ||
|
|
4aea64261e | ||
|
|
cf0cd9acd9 | ||
|
|
b4b0bdc853 | ||
|
|
0b2837fcfa | ||
|
|
f20ad7df01 | ||
|
|
c9071a66ca | ||
|
|
b0ea960159 | ||
|
|
0e7f1d60d6 | ||
|
|
03c79502f9 | ||
|
|
d4d4e00f9d | ||
|
|
b52e5e795e | ||
|
|
68df13d3fe | ||
|
|
5f3d90e411 | ||
|
|
1b68e41db4 | ||
|
|
817ac82968 | ||
|
|
43fd8cb13c | ||
|
|
397fbe7ad3 | ||
|
|
3095e7a256 | ||
|
|
df9e893cbe | ||
|
|
6ff69c88df | ||
|
|
6e4d3c98da | ||
|
|
2404eba11f | ||
|
|
e5c57a679d | ||
|
|
33de55540b | ||
|
|
99e1605bba | ||
|
|
95c4e26b24 | ||
|
|
795953a341 | ||
|
|
75d5e386d3 | ||
|
|
00d2a8527f | ||
|
|
a1ade8fc42 | ||
|
|
7f9fec061a | ||
|
|
ec782d3296 | ||
|
|
2444864508 | ||
|
|
1ccc50b21b | ||
|
|
4552a474b7 | ||
|
|
85c6d8f16e | ||
|
|
14d391cc2e | ||
|
|
8fe87a0df5 | ||
|
|
ff01df3b16 | ||
|
|
c713dc0ca8 | ||
|
|
31ea5d74a7 | ||
|
|
31b01d42c0 | ||
|
|
482b853908 | ||
|
|
675411df85 | ||
|
|
f94d33fa6a | ||
|
|
7fe110dff1 | ||
|
|
591f711886 | ||
|
|
1dc7fc8ac7 | ||
|
|
ffa79d731c | ||
|
|
01dd0416ac | ||
|
|
0bd1676978 | ||
|
|
f3407959a6 | ||
|
|
30e635a934 | ||
|
|
f6706a55ec | ||
|
|
f0b79f88b2 | ||
|
|
262ba0197d | ||
|
|
31c2447fb8 | ||
|
|
54a4ebfe48 | ||
|
|
106c7a1706 | ||
|
|
e469b46ce5 | ||
|
|
0c79561977 | ||
|
|
9e82397de9 | ||
|
|
7c166e2194 | ||
|
|
0a2b09da40 | ||
|
|
c02d578468 | ||
|
|
e990d233e5 | ||
|
|
a7cdcfcc16 | ||
|
|
75224e1661 | ||
|
|
d236b34fd4 | ||
|
|
c8313409ff | ||
|
|
6cba8e0166 | ||
|
|
0067726bbe | ||
|
|
ce620cec0a | ||
|
|
e797ba4800 | ||
|
|
fe27ee2d79 | ||
|
|
95efeee7de | ||
|
|
da30536709 | ||
|
|
108ccffcd8 | ||
|
|
c3ce0c26e7 | ||
|
|
e0c984046c | ||
|
|
64d6337612 | ||
|
|
603684211f | ||
|
|
499b30d175 | ||
|
|
3f3efab221 | ||
|
|
ef9adc92c8 | ||
|
|
ad7c251f56 | ||
|
|
1c0d254ec6 | ||
|
|
f1ce8c0e8a | ||
|
|
1c558be524 | ||
|
|
7d653cb7bf | ||
|
|
b4cc38a1d9 | ||
|
|
8867317b6a | ||
|
|
4b6bfaffba | ||
|
|
fadae42715 | ||
|
|
77c9affc00 | ||
|
|
e5ba15949b | ||
|
|
a3e59697a1 | ||
|
|
0e2125cda3 | ||
|
|
95da414511 | ||
|
|
c0d5ace640 | ||
|
|
ae48407b20 | ||
|
|
e06bd68379 | ||
|
|
ae6665493a | ||
|
|
c6f37afeff | ||
|
|
59f656e3ca | ||
|
|
12658c4756 | ||
|
|
37c185462a | ||
|
|
53c8485a7a | ||
|
|
846021296f | ||
|
|
5c8651c7cd | ||
|
|
ad91f5af53 | ||
|
|
02a68e7541 | ||
|
|
6e5dbc5285 | ||
|
|
fda9415873 | ||
|
|
4054163447 | ||
|
|
e1f5ef59c8 | ||
|
|
44baeb6924 | ||
|
|
c00e8b1709 | ||
|
|
3fb7ce7100 | ||
|
|
86b15ad693 | ||
|
|
53c00ac631 | ||
|
|
99d0c2d846 | ||
|
|
55ede897b9 | ||
|
|
a71e7d7eb1 | ||
|
|
3c28a4f723 | ||
|
|
6b681df473 | ||
|
|
22c1ee7dc8 | ||
|
|
c24e16e8cd | ||
|
|
d452a5cdce | ||
|
|
198dd52700 | ||
|
|
2dfea0f213 | ||
|
|
5064b5c2b1 | ||
|
|
78b553e55e | ||
|
|
8ca3a511cc | ||
|
|
bf26a3f569 | ||
|
|
ddb8753548 | ||
|
|
e73525d0a2 | ||
|
|
f37d947dd5 | ||
|
|
4279f20daf | ||
|
|
2dd7c3b939 | ||
|
|
cf01480ec8 | ||
|
|
d8ed42ae8e | ||
|
|
297592242c | ||
|
|
1c0a8a49fc | ||
|
|
16298e49c7 | ||
|
|
abb0b95006 | ||
|
|
32f5ea7b63 | ||
|
|
90ed5959de | ||
|
|
d999cc4143 | ||
|
|
6c1d8d5c63 | ||
|
|
a316242a4b | ||
|
|
a4ae090c37 | ||
|
|
abdcc64053 | ||
|
|
ac407d42de | ||
|
|
19c4a3f0a8 | ||
|
|
3afd96d421 | ||
|
|
f421666a27 | ||
|
|
af6baa33be | ||
|
|
1096cbe236 | ||
|
|
998be9b90c | ||
|
|
854cb8f27e | ||
|
|
e359094cff | ||
|
|
db57230987 | ||
|
|
4de3cecbbe | ||
|
|
c37a8bd3b1 | ||
|
|
e103b280fd | ||
|
|
2235ea67e2 | ||
|
|
1f6a4f7bd4 | ||
|
|
8c7ffc90f3 | ||
|
|
29d85833f1 | ||
|
|
74c56d69ac | ||
|
|
cf520646a9 | ||
|
|
da5213346a | ||
|
|
bdcb98eafc | ||
|
|
ef637cd7d3 | ||
|
|
dbbabd73c5 | ||
|
|
436ef0074a | ||
|
|
0904dec810 | ||
|
|
0aa07ead7e | ||
|
|
d87cac87ff | ||
|
|
7e8c96896f | ||
|
|
2619db0e58 | ||
|
|
ee3632b85d | ||
|
|
1c88c13fc2 | ||
|
|
7f476eb924 | ||
|
|
2d4f7e3446 | ||
|
|
165c1240a9 | ||
|
|
ef5c66ee17 | ||
|
|
33abd31d1a | ||
|
|
f91463a494 | ||
|
|
30146007d3 | ||
|
|
d53f8f24c4 | ||
|
|
f9621b1e11 | ||
|
|
e2f16ff624 | ||
|
|
121778e5c6 | ||
|
|
ef32488890 | ||
|
|
9d349d618a | ||
|
|
9f0a4f43b8 | ||
|
|
a8826f0d02 | ||
|
|
6689d312a3 | ||
|
|
2d7cb25b20 | ||
|
|
da10eaca00 | ||
|
|
6d3995d4ac | ||
|
|
e3adf8c6bf | ||
|
|
b8e522484d | ||
|
|
ef4240e196 | ||
|
|
8fa4a48ae5 | ||
|
|
4f3da2bc00 | ||
|
|
7b8c2c846f | ||
|
|
b212fd5bcd | ||
|
|
0a297f4656 | ||
|
|
fa397a1d24 | ||
|
|
0610daaec7 | ||
|
|
8278e2b88d | ||
|
|
cb4a9d89cf | ||
|
|
7800c598f6 | ||
|
|
fc651b72ab | ||
|
|
a9a7912372 | ||
|
|
43f435c334 | ||
|
|
693fc0f0c7 | ||
|
|
12e011c481 | ||
|
|
668783ba1c | ||
|
|
c18ebef702 | ||
|
|
03f9f29ce4 | ||
|
|
f62acab715 | ||
|
|
28ab9bfa2a | ||
|
|
9c05481f14 | ||
|
|
8ca92e0536 | ||
|
|
c0f6201ac3 | ||
|
|
27f3a5e16a | ||
|
|
de10dfe91b | ||
|
|
444a690a86 | ||
|
|
3d7b3f7d72 | ||
|
|
741ef7f115 | ||
|
|
e0c84c7176 | ||
|
|
393425e3d1 | ||
|
|
fc9645832d | ||
|
|
c47f41cfc0 | ||
|
|
08221489fd | ||
|
|
3c6766ff06 | ||
|
|
e28aae620a | ||
|
|
c240e7deaf | ||
|
|
31a5965b01 | ||
|
|
7a2a849a97 | ||
|
|
2c96e49566 | ||
|
|
e7846f916a | ||
|
|
d4f4d56f94 | ||
|
|
0108037076 | ||
|
|
88091b4ab3 | ||
|
|
4487462b0d | ||
|
|
dac9b07f16 | ||
|
|
b59212696a | ||
|
|
7fe1376e34 | ||
|
|
e25b90c1b6 | ||
|
|
cb32a0b8fc | ||
|
|
05617f7dca | ||
|
|
2d2f4b9ba9 | ||
|
|
65c7ecbc30 | ||
|
|
da5e37620e | ||
|
|
261057396c | ||
|
|
a43f610555 | ||
|
|
45ae52e5d0 | ||
|
|
a565443d4a | ||
|
|
081d6a3f16 | ||
|
|
c9cc832875 | ||
|
|
595698d8e9 | ||
|
|
b28d94ac97 | ||
|
|
b9684879e7 | ||
|
|
63f974531b | ||
|
|
a559210923 | ||
|
|
8d36fb9edc | ||
|
|
f652b23169 | ||
|
|
d50a2ea288 | ||
|
|
80fc3a1faa | ||
|
|
9a04405ad2 | ||
|
|
fdc9835587 | ||
|
|
702bb2cd06 | ||
|
|
58e8609c1a | ||
|
|
69c5c49094 | ||
|
|
ff8de7607a | ||
|
|
cfd0872cea | ||
|
|
7007f2e7fc | ||
|
|
6d0721341b | ||
|
|
7a156d5ef3 | ||
|
|
185c3320a4 | ||
|
|
1c9cf32735 | ||
|
|
6bfb6da0ad | ||
|
|
56a5738018 | ||
|
|
919667129f | ||
|
|
e9f49a3292 | ||
|
|
711f8b024e | ||
|
|
53716c084b | ||
|
|
2b495bcf9d | ||
|
|
d10812c6b0 | ||
|
|
80202d2679 | ||
|
|
5d120a2f36 | ||
|
|
cc11326baa | ||
|
|
f63dbc0ebd | ||
|
|
88630731dc | ||
|
|
3e2a8d80d7 | ||
|
|
55626e5a41 | ||
|
|
7ff07f7620 | ||
|
|
d2f522277c | ||
|
|
0248edbdb9 | ||
|
|
d24248e93b | ||
|
|
dcd7890a0c | ||
|
|
f219b10c30 | ||
|
|
cc039afc1e | ||
|
|
d2288d8f83 | ||
|
|
4b4f904aac | ||
|
|
e06b774174 | ||
|
|
8d4772f804 | ||
|
|
3be00bd712 | ||
|
|
a0e4449fb2 | ||
|
|
ebfc19def5 | ||
|
|
a4abe26d32 | ||
|
|
5f8cb22d02 | ||
|
|
cafc3973ec | ||
|
|
436a57a61e | ||
|
|
da5111a267 | ||
|
|
ee5cf90684 | ||
|
|
108974f4f7 | ||
|
|
79fa9f1c95 | ||
|
|
40bf12af7a | ||
|
|
263d121f3e | ||
|
|
9222d002f7 | ||
|
|
9a6aab034d | ||
|
|
b931b06941 | ||
|
|
90dc9b6fe6 | ||
|
|
275ede6f0a | ||
|
|
9fd4f8e5c2 | ||
|
|
01b4654461 | ||
|
|
d40e6a9ece | ||
|
|
b2317e0f12 | ||
|
|
444d9bd341 | ||
|
|
8fbe96744b | ||
|
|
1c48ec7196 | ||
|
|
c4b3bbd057 | ||
|
|
502ed94f31 | ||
|
|
18ce091bfa | ||
|
|
60f675758f | ||
|
|
9bfa4553a8 | ||
|
|
358f30ca7a | ||
|
|
e32785831b | ||
|
|
728eceb620 | ||
|
|
57f591d1ce | ||
|
|
e4397a1c73 | ||
|
|
1170cf474f | ||
|
|
ce8b0cf748 | ||
|
|
696f371aa4 | ||
|
|
8ebd514251 | ||
|
|
d3bc6001d8 | ||
|
|
f5415ca824 | ||
|
|
0dbe27438d | ||
|
|
7448789951 | ||
|
|
dc6138d286 | ||
|
|
7457f637a2 | ||
|
|
c9da734c0e | ||
|
|
141c814d72 | ||
|
|
bdb98cf210 | ||
|
|
7cc3d5907f | ||
|
|
3c709a28f7 | ||
|
|
e9ea7b13b6 | ||
|
|
ac16880eec | ||
|
|
c54bdd921a | ||
|
|
fc17528337 | ||
|
|
9b2db6ec53 | ||
|
|
0fcfaa2a98 | ||
|
|
ba97a728f2 | ||
|
|
a3b046fdcd | ||
|
|
ddfda3efde | ||
|
|
a2269cb66e | ||
|
|
1358f00969 | ||
|
|
eedc849c45 | ||
|
|
89679d07ae | ||
|
|
01d866f482 | ||
|
|
73b0312dcb | ||
|
|
f9d9fe6db4 | ||
|
|
e31ca68875 | ||
|
|
8ae273ee3a | ||
|
|
73a197fcde | ||
|
|
648bff02b5 | ||
|
|
7740bc138b | ||
|
|
f5337096d5 | ||
|
|
dddff91fad | ||
|
|
f047678711 | ||
|
|
aa8b23395f | ||
|
|
7c36c19de0 | ||
|
|
49183ced3b | ||
|
|
007e9697c4 | ||
|
|
9989edbe42 | ||
|
|
9742e2ec48 | ||
|
|
b47711e23a | ||
|
|
3dfdb3ac89 | ||
|
|
4d3e2a07d1 | ||
|
|
a42eb3e643 | ||
|
|
39c77a9486 | ||
|
|
e22546c56a | ||
|
|
ced61096df | ||
|
|
c0ea127810 | ||
|
|
29b1e3fa46 | ||
|
|
b2faa0d9f7 | ||
|
|
ddb9b67de3 | ||
|
|
ffbc533565 | ||
|
|
206e490491 | ||
|
|
135066f38c | ||
|
|
51d591e177 | ||
|
|
80a62c8d71 | ||
|
|
90b54c5f7f | ||
|
|
99c81e6858 | ||
|
|
8fcb6278d7 | ||
|
|
89e0abd41d | ||
|
|
a1a0c9ab80 | ||
|
|
9ab2a38d5c | ||
|
|
b5676a53ee | ||
|
|
94898a8758 | ||
|
|
97a6a11066 | ||
|
|
9fe22a5c27 | ||
|
|
f9b35c71d7 | ||
|
|
6b47f6f769 | ||
|
|
37d8483728 | ||
|
|
4776a9e785 | ||
|
|
50bc5b0302 | ||
|
|
7d496f20a1 | ||
|
|
42fbd0a1af | ||
|
|
8960bfebc0 | ||
|
|
b1209c1e7a | ||
|
|
365583efd7 | ||
|
|
926c2d71ee | ||
|
|
ce57c747cc | ||
|
|
3e9129655a | ||
|
|
12f41f30b3 | ||
|
|
1e7edd0218 | ||
|
|
2fd8ef389e | ||
|
|
53589c3954 | ||
|
|
34a0218f35 | ||
|
|
6fa4110da9 | ||
|
|
43ceaf0b7e | ||
|
|
301ca76d14 | ||
|
|
a591304412 | ||
|
|
8fffd6070a | ||
|
|
a899a8ab6d | ||
|
|
9c13e8a549 | ||
|
|
68d2ea3f27 | ||
|
|
2c0269930f | ||
|
|
c4953504ba | ||
|
|
e7ee6d9e26 | ||
|
|
1cb3875cb5 | ||
|
|
14ae2d0862 | ||
|
|
539ec69d3f | ||
|
|
bc873ad838 | ||
|
|
f056b7c1da | ||
|
|
2e790a119a | ||
|
|
4a3ed62809 | ||
|
|
4110074580 | ||
|
|
c21f00c476 | ||
|
|
1ca1c2edad | ||
|
|
ba0f61d752 | ||
|
|
74e70d2548 | ||
|
|
74921c1373 | ||
|
|
a22f37b919 | ||
|
|
9f250fdf26 | ||
|
|
d92eba82bc | ||
|
|
a052958a20 | ||
|
|
81e7e6a356 | ||
|
|
953cf26369 | ||
|
|
7649e2f3ea | ||
|
|
2a6a77467c | ||
|
|
dc61adf9d8 | ||
|
|
e0c4a90aa3 | ||
|
|
5cdff7d6d0 | ||
|
|
4f6c16984a | ||
|
|
7e364b1606 | ||
|
|
a24df07d25 | ||
|
|
347c0d4de4 | ||
|
|
ca2e9f571f | ||
|
|
9be57de4a9 | ||
|
|
cc84ee9734 | ||
|
|
b5ad030a14 | ||
|
|
40b5c43920 | ||
|
|
9f2be8b696 | ||
|
|
4397e60206 | ||
|
|
caab98e70b | ||
|
|
11a4b75ffa | ||
|
|
d25dceacdd | ||
|
|
b9a612fb9c | ||
|
|
3b9a7914ee | ||
|
|
f646dfa238 | ||
|
|
0b2a533b44 | ||
|
|
0e1246c15b | ||
|
|
a987fb81a0 | ||
|
|
4d920b182f | ||
|
|
22f077b384 | ||
|
|
4c78a50dcf | ||
|
|
9d87b08c52 | ||
|
|
97e58c5b86 | ||
|
|
b3f678cf6f | ||
|
|
7f3715cd3e | ||
|
|
a3aaaa1efb | ||
|
|
d1531632a2 | ||
|
|
2151969ae5 | ||
|
|
44e3a6f0fb | ||
|
|
364bad504c | ||
|
|
0648b4f568 | ||
|
|
a47b3bf578 | ||
|
|
3aec573d40 | ||
|
|
5d4b0c0bef | ||
|
|
11c0343420 | ||
|
|
287b843d13 | ||
|
|
1fea4777fa | ||
|
|
b5a2f94185 | ||
|
|
1000376a4f | ||
|
|
02e1272502 | ||
|
|
393e5eb158 | ||
|
|
b2d0c35fc2 | ||
|
|
3ee12082f2 | ||
|
|
1ce4fc9c8c | ||
|
|
57e2866b68 | ||
|
|
195fc1a270 | ||
|
|
39e56f1864 | ||
|
|
da96dfcad2 | ||
|
|
053bb999d3 | ||
|
|
e914f0df8e | ||
|
|
78cd83845f | ||
|
|
f6228cc81e | ||
|
|
83884f42f8 | ||
|
|
fbaf3e2f49 | ||
|
|
c0be0f74d8 | ||
|
|
a9e014226e | ||
|
|
b498d86436 | ||
|
|
ff836a85aa | ||
|
|
688a3eaef7 | ||
|
|
3b15b46d08 | ||
|
|
f21ddae94f | ||
|
|
cd9b752926 | ||
|
|
655a5a2808 | ||
|
|
5f4e519d61 | ||
|
|
720bf7efd6 | ||
|
|
3867620be5 | ||
|
|
03a7361325 | ||
|
|
e8c683db8b | ||
|
|
0a3acd9738 | ||
|
|
08f159c2ba | ||
|
|
d4e7587686 | ||
|
|
d219654387 | ||
|
|
32e31a3c6b | ||
|
|
9419125387 | ||
|
|
1bbab217d0 | ||
|
|
05d648d411 | ||
|
|
5c832d3190 | ||
|
|
ce7282a53c | ||
|
|
0d33380e6a | ||
|
|
9944b895a6 | ||
|
|
fe7045dd2f | ||
|
|
d17757cc84 | ||
|
|
7ef73babdd | ||
|
|
a47aca6fdb | ||
|
|
bf9d47fddd | ||
|
|
4fe10fadb0 | ||
|
|
d29faa0986 | ||
|
|
88ee5e95fc | ||
|
|
9a119255fe | ||
|
|
7ce11050cd | ||
|
|
9b4d1219b8 | ||
|
|
4dd29c726a | ||
|
|
17e31565e2 | ||
|
|
dd72deb546 | ||
|
|
7e82179c79 | ||
|
|
d61e655953 | ||
|
|
cd0ca95877 | ||
|
|
d70610f5d9 | ||
|
|
f9cfb6f989 | ||
|
|
1f4372b34c | ||
|
|
76e7e7d61f | ||
|
|
c09dc73476 | ||
|
|
b090602fdb | ||
|
|
16d3e82515 | ||
|
|
9caa6bb306 | ||
|
|
acf227803f | ||
|
|
f255c15fa9 | ||
|
|
7ce74ac688 | ||
|
|
6090673bb5 | ||
|
|
d1b5420b08 | ||
|
|
e0f2b96fd2 | ||
|
|
47fdce6483 | ||
|
|
bac84f31b3 | ||
|
|
21bc5bf8c0 | ||
|
|
0ae928f409 | ||
|
|
7bf7cc284d | ||
|
|
ff1efebf70 | ||
|
|
9334ed773e | ||
|
|
5d8a0c4b09 | ||
|
|
c5e8a36f9b | ||
|
|
39f9efc816 | ||
|
|
17a3be8cb1 | ||
|
|
ee2c9775a7 | ||
|
|
da486153de | ||
|
|
dd192ad0b7 | ||
|
|
3c6c36487f | ||
|
|
85eedb96ac | ||
|
|
3a8d867c87 | ||
|
|
6a2522452f | ||
|
|
f9a4b6bb0d | ||
|
|
f1fbfe297d | ||
|
|
2c0ac895e6 | ||
|
|
e86c7d668c | ||
|
|
4778e0eb23 | ||
|
|
c3ded5eb72 | ||
|
|
323355d4bb | ||
|
|
92075a44d8 | ||
|
|
386bb837d8 | ||
|
|
ea28029581 | ||
|
|
507e570887 | ||
|
|
5182f79152 | ||
|
|
71106bcd39 | ||
|
|
cf91e1973b | ||
|
|
2170d4e21a | ||
|
|
2538e94390 | ||
|
|
0be0836890 | ||
|
|
725ddf4f8b | ||
|
|
ce6f99044e | ||
|
|
30b81d98f1 | ||
|
|
f0d2d01a36 | ||
|
|
ce32e64692 | ||
|
|
7ea8a7d45f | ||
|
|
b32edf54f8 | ||
|
|
06ff685f8e | ||
|
|
c6ecdf0fa4 | ||
|
|
ca4840717b | ||
|
|
c473df4393 | ||
|
|
fa6c74a9b1 | ||
|
|
8174ecb318 | ||
|
|
5f20d69309 | ||
|
|
aab121b35d | ||
|
|
1a374a7678 | ||
|
|
396906860d | ||
|
|
85254746bf | ||
|
|
c3c7ad78c1 | ||
|
|
77787bdc7c | ||
|
|
9813ad04c2 | ||
|
|
d2c20f9548 | ||
|
|
e51b520897 | ||
|
|
35207af3de | ||
|
|
96269510d3 | ||
|
|
ceb7c440a1 | ||
|
|
25e1edf52e | ||
|
|
7a903adeea | ||
|
|
914f4e9ec9 | ||
|
|
4c5673dc4d | ||
|
|
8529a60d77 | ||
|
|
58da5d4d29 | ||
|
|
4ce6d718c9 | ||
|
|
dd31ee60f2 | ||
|
|
8bb2da3c37 | ||
|
|
47dbaac54f | ||
|
|
346405299b | ||
|
|
a0476c03c3 | ||
|
|
9dd5410433 | ||
|
|
72745dfb62 | ||
|
|
3a0d8ada6a | ||
|
|
b53d756bc2 | ||
|
|
bb8ebf32ae | ||
|
|
704487f0ce | ||
|
|
a9bdf70275 | ||
|
|
017da1159c | ||
|
|
ab5b9fb329 | ||
|
|
e0700d45de | ||
|
|
a2c4f830b3 | ||
|
|
ecf4fcdeb0 | ||
|
|
0a89fe2e17 | ||
|
|
5b5651ca7d | ||
|
|
5e5cd1acc8 | ||
|
|
79fd01093a | ||
|
|
ce63ddfe54 | ||
|
|
a56471f7ed | ||
|
|
96b46c554e | ||
|
|
a819023ab7 | ||
|
|
9504f50bd4 | ||
|
|
8fe71e3dc8 | ||
|
|
34d7643bed | ||
|
|
682eb7d802 | ||
|
|
f86a954131 | ||
|
|
8e3f6d37d9 | ||
|
|
2c38360ca0 | ||
|
|
f9d2167c97 | ||
|
|
17cada7a6a | ||
|
|
19e6f70655 | ||
|
|
d106089cb9 | ||
|
|
0f7f69c218 | ||
|
|
f9171a767c | ||
|
|
34e939f9a1 | ||
|
|
ba76cacd74 | ||
|
|
fd1b64dcc6 | ||
|
|
7c33d7ef17 | ||
|
|
2ccfecb5ae | ||
|
|
a40ff85e1a | ||
|
|
62953c2057 | ||
|
|
0e6091773d | ||
|
|
4c8ef26141 | ||
|
|
7023c7a8ae | ||
|
|
b2bfc4408e | ||
|
|
5b8aca3a2f | ||
|
|
6715ee888e | ||
|
|
4293325539 | ||
|
|
24c44861ef | ||
|
|
eafd20b4b3 | ||
|
|
d9e5edac01 | ||
|
|
f7be4fab48 | ||
|
|
50c822e05a | ||
|
|
6c1fd3015f | ||
|
|
de3b9634ac | ||
|
|
722f6163aa | ||
|
|
82a4e72c85 | ||
|
|
c40bd7ce82 | ||
|
|
356897a32d | ||
|
|
ac0c10c170 | ||
|
|
362c4147e4 | ||
|
|
9b9eae7923 | ||
|
|
8622c47348 | ||
|
|
1bfc46a24f | ||
|
|
8de787a2f3 | ||
|
|
fcc75689d8 | ||
|
|
1eed35b8bb | ||
|
|
1454af2d41 | ||
|
|
cbb2597667 | ||
|
|
9ca691c0c6 | ||
|
|
b9f21f285c | ||
|
|
bf84f95a94 | ||
|
|
d42f2071c3 | ||
|
|
5c343c918d | ||
|
|
5bfed4fe2f | ||
|
|
6c139600a0 | ||
|
|
b80b8524e6 | ||
|
|
ffa63e27ea | ||
|
|
a155b081b7 | ||
|
|
04807453ec | ||
|
|
1b7582e85c | ||
|
|
e106562ef1 | ||
|
|
d3a20f00d6 | ||
|
|
de5443a4db | ||
|
|
e8b19e08fa | ||
|
|
a574081012 | ||
|
|
4f06ce9d72 | ||
|
|
6713580455 | ||
|
|
86f6c946b3 | ||
|
|
9194d1db6b | ||
|
|
420a1b018a | ||
|
|
8009b85073 | ||
|
|
2a58af2be9 | ||
|
|
4decac26f6 | ||
|
|
a6b74f190f | ||
|
|
bfbe60c90e | ||
|
|
384b2f8462 | ||
|
|
d875615c03 | ||
|
|
9aefcfe56f | ||
|
|
266e70222f | ||
|
|
d4639e2aea | ||
|
|
ca8975891b | ||
|
|
bed3d2eb50 | ||
|
|
78495a7f64 | ||
|
|
f66914f7bb | ||
|
|
58e1f6ee1f | ||
|
|
0625035202 | ||
|
|
f8fc272f58 | ||
|
|
6d61de8a8f | ||
|
|
4c08709df1 | ||
|
|
58a28da94d | ||
|
|
26b976d17d | ||
|
|
3141fc3f05 | ||
|
|
a45d6c8b55 | ||
|
|
dadf496a68 | ||
|
|
dae8ae33f0 | ||
|
|
b6254e4a67 | ||
|
|
53431c7ba8 | ||
|
|
afa0bb4c1d | ||
|
|
9ae2579dcb | ||
|
|
37fe98fdec | ||
|
|
fe91b74ba7 | ||
|
|
0fcc446298 | ||
|
|
e228f5105e | ||
|
|
719760fd7b | ||
|
|
d3e87bcd4f | ||
|
|
be771456e1 | ||
|
|
8514782ad2 | ||
|
|
a3e9e0f010 | ||
|
|
15615a4cd1 | ||
|
|
7246fb347c | ||
|
|
f1b6fb397b | ||
|
|
49fbeb9a56 | ||
|
|
f17d71454a | ||
|
|
59ea7485e4 | ||
|
|
ff63e58f95 | ||
|
|
79ec8b60b9 | ||
|
|
846c774ac2 | ||
|
|
940e311c74 | ||
|
|
251667a30e | ||
|
|
e45697f78a | ||
|
|
ea63efa522 | ||
|
|
60839cdb47 | ||
|
|
a867b4444d | ||
|
|
072fe91518 | ||
|
|
07e6171dc5 | ||
|
|
9a80fcee37 | ||
|
|
7731a558f0 | ||
|
|
7ea4c1e47f | ||
|
|
f6b748712c | ||
|
|
93abedd93f | ||
|
|
872cd7b2d5 | ||
|
|
a7e03f9c63 | ||
|
|
f53dfb27e2 | ||
|
|
36b4e0edd2 | ||
|
|
9081947751 | ||
|
|
f58013f2c6 | ||
|
|
ae35507f80 | ||
|
|
73ff508b51 | ||
|
|
b0ccf74029 | ||
|
|
6046dc8598 | ||
|
|
9bba38bd11 | ||
|
|
59505d17d5 | ||
|
|
bcecc61b67 | ||
|
|
f9af273150 | ||
|
|
8699f90fa4 | ||
|
|
0a9ba1bc08 | ||
|
|
37741ac808 | ||
|
|
6d790237c3 | ||
|
|
70d5a5134f | ||
|
|
ee166c5555 | ||
|
|
b965fb4806 | ||
|
|
e49b20bfa7 | ||
|
|
8abfb50aed | ||
|
|
10e0077a6f | ||
|
|
278477b387 | ||
|
|
58b7fb41d9 | ||
|
|
f71e0a6ee8 | ||
|
|
b59e42c9cc | ||
|
|
57888af4ea | ||
|
|
90f2ba474c | ||
|
|
09d025d88f | ||
|
|
e18ac4f0f5 | ||
|
|
63ab35ec7c | ||
|
|
d65ed5993c | ||
|
|
6436dfaf14 | ||
|
|
0c4bd96f87 | ||
|
|
6afabf7e2a | ||
|
|
a4d4cf5819 | ||
|
|
1be7425186 | ||
|
|
8f0825bc5c | ||
|
|
6a657eec33 | ||
|
|
ae952605d3 | ||
|
|
81753706d3 | ||
|
|
4120be3e2d | ||
|
|
832f73fde9 | ||
|
|
99d06f0714 | ||
|
|
e973c45968 | ||
|
|
4dbf0c89c3 | ||
|
|
1f264ffec5 | ||
|
|
547e4a3d7e | ||
|
|
d0fa0516f5 | ||
|
|
2c13005e0f | ||
|
|
b52990cb39 | ||
|
|
0a1390a7f6 | ||
|
|
5084f843c9 | ||
|
|
42b5b1cbf7 | ||
|
|
832f7a862b | ||
|
|
0d4a62ccb5 | ||
|
|
3d98501e57 | ||
|
|
a4fff7abe3 | ||
|
|
f51779d93a | ||
|
|
121d86fb1c | ||
|
|
5956639082 | ||
|
|
7e449dec4f | ||
|
|
a938b01246 | ||
|
|
a4cd10c6fb | ||
|
|
5fd17b4b99 | ||
|
|
8ae0ae2c93 | ||
|
|
59957a913a | ||
|
|
49d284cd16 | ||
|
|
dedbd14ace | ||
|
|
2c6d888b3d | ||
|
|
9b0a5d6465 | ||
|
|
32c4f4ccaa | ||
|
|
8e435dff16 | ||
|
|
98e44a8907 | ||
|
|
060362bee2 | ||
|
|
6bfe9bfe9a | ||
|
|
b4f7cd94a1 | ||
|
|
74f21ec774 | ||
|
|
5899e06b6b | ||
|
|
5f744368dd | ||
|
|
a4a9290577 | ||
|
|
77b15bf73f | ||
|
|
f41584c83b | ||
|
|
892b8c03eb | ||
|
|
ecdf901c19 | ||
|
|
5d1f58427e | ||
|
|
02a7316342 | ||
|
|
3d59e4eac1 | ||
|
|
50ce698524 | ||
|
|
32768e7939 | ||
|
|
62dbc1129c | ||
|
|
3d0d987984 | ||
|
|
2c78a22270 | ||
|
|
4a7ae0f524 | ||
|
|
bc25e5a8a2 | ||
|
|
4af2526f54 | ||
|
|
8f688fb33b | ||
|
|
6e351cd945 | ||
|
|
2d66e37dcb | ||
|
|
2da25d9187 | ||
|
|
11badac95d | ||
|
|
b4024bf7f2 | ||
|
|
759feac95b | ||
|
|
33de23d01d | ||
|
|
3f0ecbb241 | ||
|
|
e91c008357 | ||
|
|
7a2003c371 | ||
|
|
a7eb9850b7 | ||
|
|
f01446ff25 | ||
|
|
525a32be51 | ||
|
|
73386bd67f | ||
|
|
d1cf88e942 | ||
|
|
c11da595ef | ||
|
|
2546afb7aa | ||
|
|
56edb5cdbe | ||
|
|
bca3179a6d | ||
|
|
1f3d86a434 | ||
|
|
0456399ce5 | ||
|
|
799881af2d | ||
|
|
14047588ae | ||
|
|
9d9840a6d8 | ||
|
|
b36d8d6469 | ||
|
|
254ba401d4 | ||
|
|
3035ba08c3 | ||
|
|
16201ac873 | ||
|
|
42a2493286 | ||
|
|
6f48dda8b9 | ||
|
|
b8b495ac31 | ||
|
|
bd1276d079 | ||
|
|
bfb87854df | ||
|
|
f4aba9fc41 | ||
|
|
757c7900d9 | ||
|
|
3d2877eeb9 | ||
|
|
e04919098f | ||
|
|
5d05aeaace | ||
|
|
142b6fcc00 | ||
|
|
91c0f4e2d9 | ||
|
|
89a93af1d5 | ||
|
|
ef07e2941c | ||
|
|
0c3a8dadf6 | ||
|
|
6425715daf | ||
|
|
be110fb38c | ||
|
|
d743206b8c | ||
|
|
af7a104f5b | ||
|
|
c0b73986cb | ||
|
|
c48049a3bb | ||
|
|
1cb6250f14 | ||
|
|
8ed6ee97b2 | ||
|
|
1d88371604 | ||
|
|
8685558a2a | ||
|
|
d372b27ccd | ||
|
|
88410e032f | ||
|
|
622885853d | ||
|
|
0d3c7a64e2 | ||
|
|
0c274a9a0b | ||
|
|
0e5f51f195 | ||
|
|
49369d6279 | ||
|
|
bd288bd18f | ||
|
|
cdb1138465 | ||
|
|
c8c6f8691f | ||
|
|
9441cf15c3 | ||
|
|
276ed7263c | ||
|
|
6b38ca3bd2 | ||
|
|
c7bf54807e | ||
|
|
b28811846a | ||
|
|
5561aa1d37 | ||
|
|
8c0111cb08 | ||
|
|
0dc8bd5520 | ||
|
|
acdf06bf5d | ||
|
|
5e78b1c23e | ||
|
|
088b7cde4f | ||
|
|
6a8aeb2501 | ||
|
|
9c326397d0 | ||
|
|
28d89bdd53 | ||
|
|
69ba419afd | ||
|
|
afbaa36fd3 | ||
|
|
346ea8c8a0 | ||
|
|
4448444d4b | ||
|
|
daefb926d9 | ||
|
|
0a5c73dee4 | ||
|
|
cb09ae3e84 | ||
|
|
3d76c916a5 | ||
|
|
0a5ffe9b73 | ||
|
|
325603bf41 | ||
|
|
3e3744753d | ||
|
|
5bc2fa187c | ||
|
|
0a9005f5ce | ||
|
|
5d491b8067 | ||
|
|
16b4a4fa80 | ||
|
|
f6e0eb4005 | ||
|
|
a3370a1d18 | ||
|
|
2770a853f6 | ||
|
|
bd4399b5fc | ||
|
|
432df2089c | ||
|
|
d9d922546f | ||
|
|
00167cd9ab | ||
|
|
1692516955 | ||
|
|
0bcf73f980 | ||
|
|
e68914f46b | ||
|
|
fd331480fc | ||
|
|
ccf4a0e5e5 | ||
|
|
77aa3e7e11 | ||
|
|
716d588ba9 | ||
|
|
83041b1c97 | ||
|
|
e6311edf53 | ||
|
|
617316e8d9 | ||
|
|
bd21b79959 | ||
|
|
732ff7ee58 | ||
|
|
f081d6a421 | ||
|
|
3592a94517 | ||
|
|
e5de16bb01 | ||
|
|
a62e831932 | ||
|
|
b35dd5a869 | ||
|
|
ec28bd93c3 | ||
|
|
c44b5bb03f | ||
|
|
313add715c | ||
|
|
56ea741126 | ||
|
|
9dbdd58311 | ||
|
|
2ca13e886a | ||
|
|
314efe4f68 | ||
|
|
ebd2de042d | ||
|
|
c46c551fee | ||
|
|
cecca854c0 | ||
|
|
d7df4fa5dc | ||
|
|
3651a101d0 | ||
|
|
a97a05b1ec | ||
|
|
ee2520e036 | ||
|
|
88150b2012 | ||
|
|
9161c71b51 | ||
|
|
d7f569b341 | ||
|
|
5dfa02b45f | ||
|
|
45e629c56b | ||
|
|
ee437ca2d7 | ||
|
|
0293d957b2 | ||
|
|
89069407d2 | ||
|
|
495b29bf21 | ||
|
|
ec5165d958 | ||
|
|
1da8ad3839 | ||
|
|
e97afb3433 | ||
|
|
a824a45602 | ||
|
|
20e546b496 | ||
|
|
bf8e18441a | ||
|
|
c5af9613fd | ||
|
|
9ce807069a | ||
|
|
aa4fa4cc85 | ||
|
|
727c69ffdd | ||
|
|
b7a28afe7e | ||
|
|
12bcee3b78 | ||
|
|
f3376601f2 | ||
|
|
ecea1ba241 | ||
|
|
81467c2e7e | ||
|
|
889f2fce6d | ||
|
|
ae6318cb5a | ||
|
|
19e653ef1b | ||
|
|
d6949a7a3c | ||
|
|
5050a01856 | ||
|
|
564f865a63 | ||
|
|
c1cb196365 | ||
|
|
ca0fcada42 | ||
|
|
8e87b639fa | ||
|
|
fccba24f0b | ||
|
|
62e32ea108 | ||
|
|
b17fe747fc | ||
|
|
ccc2d7d2da | ||
|
|
a528b45d60 | ||
|
|
0c84285473 | ||
|
|
1df7400ad5 | ||
|
|
1cb65438fe | ||
|
|
cd5dd131d5 | ||
|
|
f0e8ab8f31 | ||
|
|
bfdb09d29f | ||
|
|
a81e5dd8a5 | ||
|
|
ddb1fcf430 | ||
|
|
646726b385 | ||
|
|
d47a80c8e8 | ||
|
|
5f4e326985 | ||
|
|
18e747babf | ||
|
|
a3ec988d07 | ||
|
|
b992a448b1 | ||
|
|
c29f50b0d6 | ||
|
|
d30ba9654f | ||
|
|
3e3dc26e3f | ||
|
|
a78138ab61 | ||
|
|
8fd5f184b7 | ||
|
|
fe075ea795 | ||
|
|
37b6677608 | ||
|
|
b91809eaa4 | ||
|
|
ca214ffe78 | ||
|
|
715925795f | ||
|
|
17a48f6b9f | ||
|
|
5c7a1d1b05 | ||
|
|
46e51811e8 | ||
|
|
34df7f6bc8 | ||
|
|
e8331b23d9 | ||
|
|
1a92f99831 | ||
|
|
6c95828e6e | ||
|
|
14142c320a | ||
|
|
727260e69b | ||
|
|
ad804cc01e | ||
|
|
dab51d33f5 | ||
|
|
77d7a6180f | ||
|
|
185669ec72 | ||
|
|
e68debc94e | ||
|
|
18ed56b639 | ||
|
|
dc2bac0068 | ||
|
|
005ab58b15 | ||
|
|
c0ff12a7de | ||
|
|
b11b04ef67 | ||
|
|
c8aba303e8 | ||
|
|
555efa4b70 | ||
|
|
da3c6945ae | ||
|
|
12c8fe32d5 | ||
|
|
053d9df0fe | ||
|
|
595ab448be | ||
|
|
86fec106e0 | ||
|
|
b9b50bf7b4 | ||
|
|
9abd5bf743 | ||
|
|
31bf212a60 | ||
|
|
624ef272fd | ||
|
|
7c59afbca9 | ||
|
|
67a92d7dc2 | ||
|
|
369f4125e1 | ||
|
|
aebf654e15 | ||
|
|
d936ede790 | ||
|
|
cd4ded6132 | ||
|
|
1603b4b522 | ||
|
|
0eac514e52 | ||
|
|
63399fe975 | ||
|
|
bc03b4dff6 | ||
|
|
cb2a99bd0e | ||
|
|
2cc3922108 | ||
|
|
e771e1ea8a | ||
|
|
6afaec1d62 | ||
|
|
80b5f31256 | ||
|
|
c96e6822e1 | ||
|
|
e4781b8af0 | ||
|
|
f3dd2a8bfd | ||
|
|
9fe9c74021 | ||
|
|
09c6c3e804 | ||
|
|
f5023e3269 | ||
|
|
2db7f559e3 | ||
|
|
b696d3f960 | ||
|
|
bc454b4417 | ||
|
|
aa6a800d1a | ||
|
|
536d6e00d9 | ||
|
|
725a04b321 | ||
|
|
3ff8cc58e1 | ||
|
|
4fc8267264 | ||
|
|
0965fc45f2 | ||
|
|
181178b0ea | ||
|
|
95e6e80921 | ||
|
|
f36b71350d | ||
|
|
3483722475 | ||
|
|
56e63baf5a | ||
|
|
0830e66e76 | ||
|
|
74a5d3a25e | ||
|
|
4fb29e1b6b | ||
|
|
2c4f616213 | ||
|
|
75afe7cd33 | ||
|
|
80eb78033f | ||
|
|
68013e8fe7 | ||
|
|
7fe32301c4 | ||
|
|
41ddc7d33f | ||
|
|
eff5840645 | ||
|
|
ddf0242f56 | ||
|
|
eae5c65d3e | ||
|
|
c85b545f8d | ||
|
|
f24dc80c49 | ||
|
|
9a9de0038c | ||
|
|
35626d3929 | ||
|
|
c8f26dd968 | ||
|
|
7e5cb50925 | ||
|
|
ffa755c723 | ||
|
|
a060bf7223 | ||
|
|
4ab5d97e9b | ||
|
|
81babd29e7 | ||
|
|
fac76ddedd | ||
|
|
f34cc1861a | ||
|
|
bd4ed38a3c | ||
|
|
8644fed534 | ||
|
|
ca9fdadf3c | ||
|
|
228364e317 | ||
|
|
e65aee4533 | ||
|
|
a1ca607f35 | ||
|
|
efbf156f82 | ||
|
|
a2533e9a46 | ||
|
|
09742af92b | ||
|
|
880de53d59 | ||
|
|
91a24dd2eb | ||
|
|
60e91b018a | ||
|
|
9be37f7d2d | ||
|
|
be79fc1c92 | ||
|
|
502960bfeb | ||
|
|
d95a00df73 | ||
|
|
b3a9c1a100 | ||
|
|
4318d2d7d0 | ||
|
|
c3ff888981 | ||
|
|
7c85616dcf | ||
|
|
353a48d913 | ||
|
|
4e736e83a3 | ||
|
|
57583d6b00 | ||
|
|
98dcb32a0c | ||
|
|
fba5e3a46d | ||
|
|
2122304515 | ||
|
|
80dbebf0ad | ||
|
|
0c160eab7b | ||
|
|
4841502959 | ||
|
|
8218df82f2 | ||
|
|
fadc1b539b | ||
|
|
c8162324ed | ||
|
|
2c46378886 | ||
|
|
cf7e43fa26 | ||
|
|
b5e8b5a124 | ||
|
|
6fa0a21b3c | ||
|
|
c43637f6cc | ||
|
|
f48a430493 | ||
|
|
a1eb341817 | ||
|
|
cc2419911c | ||
|
|
2f5d3b073d | ||
|
|
4c0a7a9566 | ||
|
|
35514e0cc3 | ||
|
|
0f23edeec3 | ||
|
|
69e54cb9c1 | ||
|
|
60b8023928 | ||
|
|
8099ae44d7 | ||
|
|
46f88494e3 | ||
|
|
4818ac0750 | ||
|
|
d96429e6b8 | ||
|
|
9cda076c93 | ||
|
|
d30c761b3b | ||
|
|
49a0e8e242 | ||
|
|
8630c7a700 | ||
|
|
905fbeec14 | ||
|
|
e1ec8dfe4f | ||
|
|
93558f75f2 | ||
|
|
7a66c1a01c | ||
|
|
9f7b975064 | ||
|
|
8e8a0d2df6 | ||
|
|
d9f4fadf2d | ||
|
|
3f3fe6b178 | ||
|
|
2e95cd7a62 | ||
|
|
9be7345ba6 | ||
|
|
950edb1110 | ||
|
|
c4b3723372 | ||
|
|
119841a2c4 | ||
|
|
2df6f9cdda | ||
|
|
55868da9d3 | ||
|
|
460373803d | ||
|
|
abf9cce6bf | ||
|
|
d9c400ac32 | ||
|
|
377607730c | ||
|
|
6da5a8073c | ||
|
|
68ad513dd5 | ||
|
|
40ff78b1c8 | ||
|
|
477baf390b | ||
|
|
76834c0975 | ||
|
|
a3b7a88e9c | ||
|
|
ce36b09593 | ||
|
|
ebaac70b27 | ||
|
|
b4a6ed8d8f | ||
|
|
7c161f2d78 | ||
|
|
39dcfb4e5d | ||
|
|
34d87b7a72 | ||
|
|
f2d2cfec8f | ||
|
|
46625d207b | ||
|
|
f35112378f | ||
|
|
bb5ded4e65 | ||
|
|
b2f406f021 | ||
|
|
7821e2508c | ||
|
|
3e6cfe3275 | ||
|
|
588313b9ac | ||
|
|
50e4811e6d | ||
|
|
c182f95684 | ||
|
|
c241524663 | ||
|
|
9517c3500d | ||
|
|
1b8978fede | ||
|
|
5796cbc040 | ||
|
|
49726384f7 | ||
|
|
e7386735f4 | ||
|
|
ddfa653197 | ||
|
|
fffee1049f | ||
|
|
cc502163cb | ||
|
|
d53d92b890 | ||
|
|
218582ced8 | ||
|
|
bc1c19b4f7 | ||
|
|
85cea78b3c | ||
|
|
7a9027a147 | ||
|
|
66db3f9764 | ||
|
|
7e84343f16 | ||
|
|
e82e57a30c | ||
|
|
336c7ddca8 | ||
|
|
4ffcbc8274 | ||
|
|
22673ebd90 | ||
|
|
b1c0398bba | ||
|
|
6310517ff2 | ||
|
|
4ff3d6a645 | ||
|
|
23570cc5f7 | ||
|
|
dc09a5183a | ||
|
|
8458b9e7d6 | ||
|
|
51900996ea | ||
|
|
663da130ae | ||
|
|
c8b1724ecf | ||
|
|
c289af8f07 | ||
|
|
da7fa53b1a | ||
|
|
d160db1bcd | ||
|
|
a788cd9f64 | ||
|
|
6997e36670 | ||
|
|
1893b3ce0f | ||
|
|
576abecf7d | ||
|
|
b9b799533b | ||
|
|
70a01955b8 | ||
|
|
5f9409a91d | ||
|
|
32805ca968 | ||
|
|
8dfb0c6675 | ||
|
|
7428d42c16 | ||
|
|
99d9cb0b0d | ||
|
|
80ab60f1b6 | ||
|
|
a1d24028b8 | ||
|
|
d03f4dbc98 | ||
|
|
f1573654b9 | ||
|
|
e703103fa8 | ||
|
|
6241369b6c | ||
|
|
2a637e4220 | ||
|
|
816360c275 | ||
|
|
c541d7e349 | ||
|
|
df70d8661a | ||
|
|
c3daa969fa | ||
|
|
66a7c3bc4d | ||
|
|
3553b3ce3d | ||
|
|
9289c2de69 | ||
|
|
dac1612cb0 | ||
|
|
87d79c7415 | ||
|
|
86d7aaa03a | ||
|
|
cae31ab336 | ||
|
|
2aa01c58a1 | ||
|
|
ee852cf5fc | ||
|
|
5eb87b9f10 | ||
|
|
820a893d75 | ||
|
|
ce823e4b08 | ||
|
|
21830048c9 | ||
|
|
1251f9ec80 | ||
|
|
4839cbe9d0 | ||
|
|
702bfccfa2 | ||
|
|
28386cc496 | ||
|
|
0c1a7347db | ||
|
|
c06a03ab96 | ||
|
|
93dbcab10a | ||
|
|
5f12fbc2ee | ||
|
|
2443dc135c | ||
|
|
40c046f86b | ||
|
|
aee5c317f6 | ||
|
|
0fdafd8398 | ||
|
|
3ca3c67828 | ||
|
|
336bc2c0e6 | ||
|
|
d3a3f99848 | ||
|
|
d31935b8eb | ||
|
|
13928d4d35 | ||
|
|
212af78032 | ||
|
|
60472fcee3 | ||
|
|
c899eb4ee3 | ||
|
|
d090db380f | ||
|
|
a26f041964 | ||
|
|
b22bda3cba | ||
|
|
69e903a4c4 | ||
|
|
6f19fd5912 | ||
|
|
9c2f96f7eb | ||
|
|
4494ddd8ff | ||
|
|
5cb36a4632 | ||
|
|
9b7342b231 | ||
|
|
01ebc8f15a | ||
|
|
472baf7337 | ||
|
|
c381716ecf | ||
|
|
0e08c6c660 | ||
|
|
6da79ab614 | ||
|
|
a44a3195ab | ||
|
|
f78feb5abf | ||
|
|
4385acd3c6 | ||
|
|
c0927a3643 | ||
|
|
37692119e1 | ||
|
|
0f193141af | ||
|
|
24d5fc5f15 | ||
|
|
1ab8d58bf7 | ||
|
|
691bf75b35 | ||
|
|
63e23d7fe3 | ||
|
|
23d0db5458 | ||
|
|
71c62664cd | ||
|
|
c9faf5dd59 | ||
|
|
baf080f147 | ||
|
|
0e29ee9299 | ||
|
|
d52e5fab1e | ||
|
|
9f442eb7e4 | ||
|
|
0d94ca5399 | ||
|
|
13b900faf7 | ||
|
|
32ad75c5ab | ||
|
|
7a45653575 | ||
|
|
b316e97a4f | ||
|
|
6c7420f4e7 | ||
|
|
80a357623d | ||
|
|
0a4dfa8fd2 | ||
|
|
4604558d35 | ||
|
|
089ab9ee9f | ||
|
|
4fb804efc6 | ||
|
|
5b2ba448b6 | ||
|
|
899b5078eb | ||
|
|
edd423aad6 | ||
|
|
518e0f4e21 | ||
|
|
7546e53c23 | ||
|
|
0f9944190d | ||
|
|
18aca275c8 | ||
|
|
6d02ef59f8 | ||
|
|
729cea88f3 | ||
|
|
9b957a1fdb | ||
|
|
e18b0cd4c8 | ||
|
|
b51be8382f | ||
|
|
a95a1f1158 | ||
|
|
be8fc47c5f | ||
|
|
4fd76b09d9 | ||
|
|
6546c1da9b | ||
|
|
8f0b3983ee | ||
|
|
7f2ce045ab | ||
|
|
38f1fe7742 | ||
|
|
a099d2364d | ||
|
|
5f91084968 | ||
|
|
cb9321e925 | ||
|
|
716ff187f9 | ||
|
|
16365f2014 | ||
|
|
0fa03da18c | ||
|
|
a4a7d49bed | ||
|
|
0de319fc73 | ||
|
|
c06823dd47 | ||
|
|
f9944e6140 | ||
|
|
426815f7ab | ||
|
|
2a842e36a1 | ||
|
|
90dfabc644 | ||
|
|
f302c2ae39 | ||
|
|
93aee3946f | ||
|
|
4b7de5d802 | ||
|
|
78c63e6a18 | ||
|
|
dcda2bff69 | ||
|
|
372c4da8f9 | ||
|
|
a95025752a | ||
|
|
a16ffcdde2 | ||
|
|
3c2e521dd7 | ||
|
|
f28d9bcd8c | ||
|
|
c6039fc399 | ||
|
|
706494016c | ||
|
|
a653233050 | ||
|
|
ed5accd702 | ||
|
|
3a247be758 | ||
|
|
d417aedde0 | ||
|
|
967aaad482 | ||
|
|
9c4942b190 | ||
|
|
67fd07a92a | ||
|
|
533b0ed591 | ||
|
|
3f1a0baa84 | ||
|
|
8057c420d9 | ||
|
|
a3717436b6 | ||
|
|
7852e0b618 | ||
|
|
5afb16ab8d | ||
|
|
8187ec2cef | ||
|
|
d55d8ac091 | ||
|
|
e13c34c2b8 | ||
|
|
8630c8830a | ||
|
|
da3f34603a | ||
|
|
97a8ff3478 | ||
|
|
2548896656 | ||
|
|
572df007df | ||
|
|
440640bbbc | ||
|
|
563b7ad2d0 | ||
|
|
b180702c97 | ||
|
|
c3f4e734f1 | ||
|
|
61a56a0561 | ||
|
|
820fb6dda9 | ||
|
|
85db87a121 | ||
|
|
dc11b76bea | ||
|
|
2b9408c217 | ||
|
|
5e033773dd | ||
|
|
855681200f | ||
|
|
456564f377 | ||
|
|
828e16b45d | ||
|
|
9289ebf9c9 | ||
|
|
f4b6cc6628 | ||
|
|
853f7cc59a | ||
|
|
5841776c65 | ||
|
|
fbf47f75d5 | ||
|
|
1b42f69119 | ||
|
|
a1b532334e | ||
|
|
edac0e8023 | ||
|
|
498d3d5906 | ||
|
|
57152a8e29 | ||
|
|
35d4e2d4e0 | ||
|
|
fe42b15ec6 | ||
|
|
1d4a86594b | ||
|
|
072e583835 | ||
|
|
463133abbe | ||
|
|
34d6c69b2a | ||
|
|
14d36e3727 | ||
|
|
ed95f7dfa0 | ||
|
|
f93a10da48 | ||
|
|
31e623afb3 | ||
|
|
2080b3d7fa | ||
|
|
a8e06a67c2 | ||
|
|
42a79cb269 | ||
|
|
1ba9cd6138 | ||
|
|
37f3328147 | ||
|
|
df1ecad7e9 | ||
|
|
5699c3ae7d | ||
|
|
1877a02378 | ||
|
|
e9f344c53f | ||
|
|
d15763f2ad | ||
|
|
76eab44f53 | ||
|
|
3a373a200c | ||
|
|
f6e518d2f9 | ||
|
|
14f9f64bce | ||
|
|
c79a0108a1 | ||
|
|
20fcc5e31b | ||
|
|
01299421ee | ||
|
|
5729e33412 | ||
|
|
f85f39e662 | ||
|
|
0e9be57119 | ||
|
|
ffd7b5779b | ||
|
|
1d1d55e2b4 | ||
|
|
3cea8f24d4 | ||
|
|
d6a43a7729 | ||
|
|
cfeeec95fa | ||
|
|
e6cff61f99 | ||
|
|
eeb02ceef4 | ||
|
|
eaa0ec4fc3 | ||
|
|
91a719f80e | ||
|
|
06f67e4765 | ||
|
|
7530bfd1a1 | ||
|
|
abf6a3f91d | ||
|
|
21d3856e90 | ||
|
|
2304d0ec5c | ||
|
|
5cafe198bf | ||
|
|
4ce2690bd2 | ||
|
|
ea186ac48d | ||
|
|
9ab5a03f53 | ||
|
|
7650c8bca9 | ||
|
|
3728d2cfd9 | ||
|
|
3214ba4541 | ||
|
|
4232904055 | ||
|
|
baf8976c2d | ||
|
|
b3ae857f3c | ||
|
|
8be0dd0d8e | ||
|
|
166ea9deb9 | ||
|
|
7a16ef2cc4 | ||
|
|
a0cee13652 | ||
|
|
a3b434d2fe | ||
|
|
36ab05f003 | ||
|
|
35dee0c46e | ||
|
|
cb1858ecc8 | ||
|
|
10fbf36e92 | ||
|
|
3c3e97aa6e | ||
|
|
f353380e86 | ||
|
|
b1375e5ed1 | ||
|
|
44bcbc4823 | ||
|
|
a402a3ad12 | ||
|
|
343eb56cdf | ||
|
|
3efa8b6322 | ||
|
|
7cd72f344d | ||
|
|
066dfc71aa | ||
|
|
769cd9be3f | ||
|
|
0f9d6a1e4a | ||
|
|
3c742a0037 | ||
|
|
9a3d99515f | ||
|
|
f3447d187d | ||
|
|
276696414e | ||
|
|
7d41aca0e4 | ||
|
|
c71d8fe1cc | ||
|
|
cc261db606 | ||
|
|
7e17ed21ce | ||
|
|
b1f4b2d8ed | ||
|
|
9cb5f6d9d7 | ||
|
|
f3177d8878 | ||
|
|
3bc7b5bad9 | ||
|
|
b70064d1be | ||
|
|
ffca2ecf19 | ||
|
|
a32b6d5cf5 | ||
|
|
3ce087a716 | ||
|
|
15cdeef552 | ||
|
|
a038477ce0 | ||
|
|
b05e939e05 | ||
|
|
6347daf0ac | ||
|
|
327f4ca327 | ||
|
|
fe0d1034aa | ||
|
|
d982a3c94e | ||
|
|
259ca4a11e | ||
|
|
b9ae1fa429 | ||
|
|
0d32c1656a | ||
|
|
2defd311e1 | ||
|
|
d078cb264a | ||
|
|
c45a656153 | ||
|
|
1cef544cff | ||
|
|
67cef371dc | ||
|
|
2fcfa8d3eb | ||
|
|
03391b4f7a | ||
|
|
2dae95bf0b | ||
|
|
558fad1630 | ||
|
|
c2641458e7 | ||
|
|
bbdfdb978d | ||
|
|
4112061a47 | ||
|
|
25e9ddb4a4 | ||
|
|
66bf39db93 | ||
|
|
be439cb887 | ||
|
|
f3b601aa06 | ||
|
|
f6a6ead0f3 | ||
|
|
43c04df98a | ||
|
|
581a373dae | ||
|
|
ca197a915c | ||
|
|
061111d822 | ||
|
|
41003d106a | ||
|
|
c9b1e66c71 | ||
|
|
17e95cb615 | ||
|
|
b5c086aedb | ||
|
|
1036132838 | ||
|
|
1d1d82ca50 | ||
|
|
85be3e4ed1 | ||
|
|
d5d52ec8b9 | ||
|
|
ecb0d1f325 | ||
|
|
68436c93a7 | ||
|
|
2a9dff2846 | ||
|
|
bcd1837924 | ||
|
|
77508bfe0d | ||
|
|
cf517effb3 | ||
|
|
901a075a38 | ||
|
|
76d6820af9 | ||
|
|
7cf73c10ac | ||
|
|
71963aa738 | ||
|
|
dcc0dabe68 | ||
|
|
348e632dd6 | ||
|
|
067502bd66 | ||
|
|
6b576fcf5c | ||
|
|
2fc972a173 | ||
|
|
a941b1af4e | ||
|
|
fbc8a1cdcb | ||
|
|
f0fab80f5b | ||
|
|
a0740d1616 | ||
|
|
8986d15a5b | ||
|
|
9f4f22743f | ||
|
|
9eebd2c921 | ||
|
|
5ce71506c8 | ||
|
|
ad5b43f6db | ||
|
|
aa9855516f | ||
|
|
fcd4649642 | ||
|
|
e12246983b | ||
|
|
e8e7ad3b75 | ||
|
|
e9d648d37c | ||
|
|
eaeece8177 | ||
|
|
aa9a991a85 | ||
|
|
0d37431def | ||
|
|
44dfd7a803 | ||
|
|
d2809a0acb | ||
|
|
4b074d723e | ||
|
|
deb6abe50e | ||
|
|
d042ea5ab9 | ||
|
|
bc7c1e4d05 | ||
|
|
a4c5e7c2ee | ||
|
|
504d915723 | ||
|
|
039ea95390 | ||
|
|
5f32d2e56f | ||
|
|
5b716df45f | ||
|
|
66e2e60ac4 | ||
|
|
69dc09489b | ||
|
|
33a6abfc07 | ||
|
|
f277cbf3f3 | ||
|
|
0a56ab7a1e | ||
|
|
a073936997 | ||
|
|
5c1dd69963 | ||
|
|
c08dc64581 | ||
|
|
5916bbd5b3 | ||
|
|
8c104b52f9 | ||
|
|
7266cb653d | ||
|
|
2a8fd278c1 | ||
|
|
4c25ceff29 | ||
|
|
26f0b53bb2 | ||
|
|
101377d7f2 | ||
|
|
2487f55bbc | ||
|
|
f69e718151 | ||
|
|
5d516a8584 | ||
|
|
b1322fbe04 | ||
|
|
38a5e38f88 | ||
|
|
78fd05c1c6 | ||
|
|
6993c905e3 | ||
|
|
14f8ce6e15 | ||
|
|
d726eb354d | ||
|
|
1136c64d49 | ||
|
|
3f3179db0c | ||
|
|
d224a4c39f | ||
|
|
3eee442f28 | ||
|
|
7c90812e51 | ||
|
|
5c8bcf9379 | ||
|
|
d40456d6a9 | ||
|
|
8e203af344 | ||
|
|
31ead3f088 | ||
|
|
efaeb0f0b2 | ||
|
|
9db9638bc3 | ||
|
|
74c1476f6d | ||
|
|
24255be0bd | ||
|
|
0d89eb2c40 | ||
|
|
2350952d05 | ||
|
|
53e38cb1d2 | ||
|
|
f9c99a61d4 | ||
|
|
2178c8e4af | ||
|
|
8aacf30f19 | ||
|
|
745e97e0ab | ||
|
|
af5c0b3b71 | ||
|
|
d7a1f3104a | ||
|
|
8fb48d7952 | ||
|
|
1ac3de4aeb | ||
|
|
0c5ea5c3c0 | ||
|
|
78e4f1cde4 | ||
|
|
fb0b94eaa1 | ||
|
|
7291fef7cc | ||
|
|
6db46850eb | ||
|
|
7997295d4c | ||
|
|
6daee3a0b5 | ||
|
|
87f6793552 | ||
|
|
40786427b0 | ||
|
|
59b84ae1a4 | ||
|
|
aafd8a8da4 | ||
|
|
5ff66f6bfa | ||
|
|
e8873804c0 | ||
|
|
0f37521592 | ||
|
|
8ad1180321 | ||
|
|
ced03c5d99 | ||
|
|
161a54ceaa | ||
|
|
c159ac287f | ||
|
|
4ddd2bf980 | ||
|
|
1d9425ecdc | ||
|
|
495981bade | ||
|
|
672cf9fffe | ||
|
|
72e15d8b4f | ||
|
|
075b4d252a | ||
|
|
1953ecdf4d | ||
|
|
89f8151579 | ||
|
|
d9cc1d67c0 | ||
|
|
d178f4c75d | ||
|
|
0668a3bf2a | ||
|
|
d548b21be2 | ||
|
|
ebcd053bf3 | ||
|
|
b282464604 | ||
|
|
42dcecde14 | ||
|
|
aa0b344b55 | ||
|
|
fa77128026 | ||
|
|
7f1c5d8534 | ||
|
|
d2a31a6a0f | ||
|
|
fb9c911ae9 | ||
|
|
5bc569c4dd | ||
|
|
8397970bf8 | ||
|
|
6fc7b3d946 | ||
|
|
0fe7796df0 | ||
|
|
40b50332de | ||
|
|
9a50dfc4b5 | ||
|
|
09c18f474f | ||
|
|
51244c4388 | ||
|
|
898f162369 | ||
|
|
2529ef2f0b | ||
|
|
fc528941bd | ||
|
|
8e9ee90d9f | ||
|
|
b03c6f70fe | ||
|
|
42da681f2b | ||
|
|
44561e8cea | ||
|
|
37735b962e | ||
|
|
34ec3eac44 | ||
|
|
59c14d07fd | ||
|
|
86ffb744f5 | ||
|
|
fab7cfb113 | ||
|
|
2715947830 | ||
|
|
eb2f3387c5 | ||
|
|
2472cea69f | ||
|
|
2a634af2bc | ||
|
|
81654c9874 | ||
|
|
28914d4450 | ||
|
|
4000cce81c | ||
|
|
35ad366427 | ||
|
|
c257adb56a | ||
|
|
929e0c126d | ||
|
|
b293e4d516 | ||
|
|
6571cf2e89 | ||
|
|
aa739cdfd4 | ||
|
|
35c608ae77 | ||
|
|
8d8095a2d1 | ||
|
|
1740821bb4 | ||
|
|
4cd6829657 | ||
|
|
ef76c075e0 | ||
|
|
b260a61c8f | ||
|
|
780e526143 | ||
|
|
1e0269faa2 | ||
|
|
73465aa44b | ||
|
|
1f5fa03015 | ||
|
|
000e1012c6 | ||
|
|
afc5821809 | ||
|
|
e8832a86bb | ||
|
|
f61b8608de | ||
|
|
92f428b6d1 | ||
|
|
8795bf8cf9 | ||
|
|
0dee0bfada | ||
|
|
482d3bb913 | ||
|
|
48035977e3 | ||
|
|
6b23921880 | ||
|
|
c98e4eb478 | ||
|
|
7cd05ad76b | ||
|
|
fa327d618d | ||
|
|
bc202aec6e | ||
|
|
606ce4e66f | ||
|
|
a10c19456a | ||
|
|
20688661aa | ||
|
|
cbbd9f475e | ||
|
|
f4b3948168 | ||
|
|
2245d4506f | ||
|
|
7f3da135e2 | ||
|
|
23f94b6e67 | ||
|
|
0ec10b52e0 | ||
|
|
2fcd57410a | ||
|
|
a993a71857 | ||
|
|
01ce0e1d1a | ||
|
|
040a152f1f | ||
|
|
f4f2013c2b | ||
|
|
6e172bdc09 | ||
|
|
725ec57bee | ||
|
|
8a9234ba4f | ||
|
|
a00e4ebe3f | ||
|
|
2d93a011df | ||
|
|
bffe7aba8f | ||
|
|
b581408137 | ||
|
|
2263cd1355 | ||
|
|
1bb87c71aa | ||
|
|
7dec7d615a | ||
|
|
2e5308ad40 | ||
|
|
d1015de700 | ||
|
|
934318adb1 | ||
|
|
179c2b21c0 | ||
|
|
85f6d3fed8 | ||
|
|
a4925eeeb4 | ||
|
|
196200d03f | ||
|
|
f2ca0424a0 | ||
|
|
07b971ad5f | ||
|
|
51fa25e03d | ||
|
|
bd5f100f13 | ||
|
|
3b8da7e4c2 | ||
|
|
4a9a021b2c | ||
|
|
d4dd226d8f | ||
|
|
0d4237f802 | ||
|
|
46b9aca16e | ||
|
|
4931477ef4 | ||
|
|
dfdd1697c5 | ||
|
|
801f0d51a1 | ||
|
|
bdebb19648 | ||
|
|
75df0cbcf5 | ||
|
|
e23b4ce6b4 | ||
|
|
1b88a68b55 | ||
|
|
a82bc6738c | ||
|
|
868626c79c | ||
|
|
e4cc8bf828 | ||
|
|
f57fb17d2b | ||
|
|
a69170b0ba | ||
|
|
4066c2389d | ||
|
|
cd7b4fcd8e | ||
|
|
b0c963b650 | ||
|
|
f67995d5d3 | ||
|
|
f0e7344bc8 | ||
|
|
aa525c68c7 | ||
|
|
a2e25331a5 | ||
|
|
d8f09d377f | ||
|
|
cc96cb1c75 | ||
|
|
5966f04656 | ||
|
|
dbce9a8f29 | ||
|
|
4333552523 | ||
|
|
c00e945f6e | ||
|
|
56cb628ee8 | ||
|
|
827b6598b2 | ||
|
|
59bafea06d | ||
|
|
d61aca40b8 | ||
|
|
bf704d35a2 | ||
|
|
fbc8881a96 | ||
|
|
8cfb1efb01 | ||
|
|
f399b8466c | ||
|
|
437ba69049 | ||
|
|
dbc7e8e85d | ||
|
|
f3333ce941 | ||
|
|
97a9261096 | ||
|
|
5a76dab3c6 | ||
|
|
5a92d3f312 | ||
|
|
b173dd1c39 | ||
|
|
473e1a6f22 | ||
|
|
9c4a890688 | ||
|
|
a803c8bcc5 | ||
|
|
5c7ce18379 | ||
|
|
aff6fdfa84 | ||
|
|
477a652b44 | ||
|
|
15e0b42f04 | ||
|
|
b25ea9c863 | ||
|
|
c838cb03c9 | ||
|
|
ba9adc127e | ||
|
|
b7d603c4de | ||
|
|
71f1f3aa64 | ||
|
|
7d1c26202a | ||
|
|
80db2f6558 | ||
|
|
e376c79dda | ||
|
|
5a47e0d2e4 | ||
|
|
ca9143bebc | ||
|
|
a49f6799de | ||
|
|
d916ecc4f3 | ||
|
|
e1ed9aca10 | ||
|
|
0e2f1b9405 | ||
|
|
db5a2d2141 | ||
|
|
a9771dccba | ||
|
|
4849e07c26 | ||
|
|
4645e78fa7 | ||
|
|
9e2590eb15 | ||
|
|
94575a5cf6 | ||
|
|
a597a8d86b | ||
|
|
3287798efe | ||
|
|
d01ac17334 | ||
|
|
2c96727c45 | ||
|
|
ca1b2454bd | ||
|
|
064fc17ce3 | ||
|
|
43ccf9cb41 | ||
|
|
96857a197c | ||
|
|
079ff7785c | ||
|
|
d6a6cbe153 | ||
|
|
2486cfd45d | ||
|
|
30cb7286db | ||
|
|
9e7253c179 | ||
|
|
276a82d1f7 | ||
|
|
57ced9bc83 | ||
|
|
3c3662b032 | ||
|
|
f490b9a8bd | ||
|
|
c7ccedae95 | ||
|
|
03517459db | ||
|
|
96326280e5 | ||
|
|
9b7899780b | ||
|
|
e01cd057e8 | ||
|
|
ba85ca1991 | ||
|
|
92a9b71f21 | ||
|
|
e50c26d1b9 | ||
|
|
7090c24321 | ||
|
|
55319cd6d6 | ||
|
|
8a6b51441c | ||
|
|
36670b49a0 | ||
|
|
a402d848d2 | ||
|
|
37c563802c | ||
|
|
2d7032973c | ||
|
|
70b5f5bce3 | ||
|
|
be34af4555 | ||
|
|
815539a933 | ||
|
|
ab889e2945 | ||
|
|
b3231c8003 | ||
|
|
5f6cb34f77 | ||
|
|
a99a080c50 | ||
|
|
4a1ca8d582 | ||
|
|
050eb5660d |
1
.github/FUNDING.yml
vendored
@@ -1,3 +1,4 @@
|
|||||||
|
github: kovidgoyal
|
||||||
patreon: kovidgoyal
|
patreon: kovidgoyal
|
||||||
liberapay: kovidgoyal
|
liberapay: kovidgoyal
|
||||||
custom: https://sw.kovidgoyal.net/kitty/support.html
|
custom: https://sw.kovidgoyal.net/kitty/support.html
|
||||||
|
|||||||
41
.github/workflows/ci.py
vendored
@@ -30,40 +30,45 @@ def install_deps():
|
|||||||
print('Installing kitty dependencies...')
|
print('Installing kitty dependencies...')
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
if is_macos:
|
if is_macos:
|
||||||
items = (x.strip() for x in open('Brewfile').readlines() if not x.startswith('#'))
|
items = (x.split()[1].strip('"') for x in open('Brewfile').readlines() if x.strip().startswith('brew '))
|
||||||
run('brew', 'install', *items)
|
openssl = 'openssl'
|
||||||
|
import ssl
|
||||||
|
if ssl.OPENSSL_VERSION_INFO[0] == 1:
|
||||||
|
openssl += '@1.1'
|
||||||
|
run('brew', 'install', 'fish', openssl, *items)
|
||||||
else:
|
else:
|
||||||
run('sudo apt-get update')
|
run('sudo apt-get update')
|
||||||
run('sudo apt-get install -y libgl1-mesa-dev libxi-dev libxrandr-dev libxinerama-dev'
|
run('sudo apt-get install -y libgl1-mesa-dev libxi-dev libxrandr-dev libxinerama-dev ca-certificates'
|
||||||
' libxcursor-dev libxcb-xkb-dev libdbus-1-dev libxkbcommon-dev libharfbuzz-dev libx11-xcb-dev'
|
' libxcursor-dev libxcb-xkb-dev libdbus-1-dev libxkbcommon-dev libharfbuzz-dev libx11-xcb-dev zsh'
|
||||||
' libpng-dev liblcms2-dev libfontconfig-dev libxkbcommon-x11-dev libcanberra-dev uuid-dev')
|
' libpng-dev liblcms2-dev libfontconfig-dev libxkbcommon-x11-dev libcanberra-dev librsync-dev uuid-dev'
|
||||||
|
' zsh bash dash')
|
||||||
|
# for some reason these directories are world writable which causes zsh
|
||||||
|
# compinit to break
|
||||||
|
run('sudo chmod -R og-w /usr/share/zsh')
|
||||||
if is_bundle:
|
if is_bundle:
|
||||||
install_bundle()
|
install_bundle()
|
||||||
else:
|
else:
|
||||||
if is_macos:
|
cmd = 'python3 -m pip install Pillow pygments'
|
||||||
# needed for zlib for pillow, should not be needed after pillow 8.0
|
|
||||||
os.environ['PKG_CONFIG_PATH'] = '/usr/local/opt/zlib/lib/pkgconfig'
|
|
||||||
cmd = 'pip3 install Pillow pygments'
|
|
||||||
if sys.version_info[:2] < (3, 7):
|
if sys.version_info[:2] < (3, 7):
|
||||||
cmd += ' importlib-resources'
|
cmd += ' importlib-resources dataclasses'
|
||||||
run(cmd)
|
run(cmd)
|
||||||
|
|
||||||
|
|
||||||
def build_kitty():
|
def build_kitty():
|
||||||
python = shutil.which('python3') if is_bundle else sys.executable
|
python = shutil.which('python3') if is_bundle else sys.executable
|
||||||
cmd = '{} setup.py build --verbose'.format(python)
|
cmd = f'{python} setup.py build --verbose'
|
||||||
if os.environ.get('KITTY_SANITIZE') == '1':
|
if os.environ.get('KITTY_SANITIZE') == '1':
|
||||||
cmd += ' --debug --sanitize'
|
cmd += ' --debug --sanitize'
|
||||||
run(cmd)
|
run(cmd)
|
||||||
|
|
||||||
|
|
||||||
def test_kitty():
|
def test_kitty():
|
||||||
run('./kitty/launcher/kitty +launch test.py')
|
run('./test.py')
|
||||||
|
|
||||||
|
|
||||||
def package_kitty():
|
def package_kitty():
|
||||||
py = 'python3' if is_macos else 'python'
|
python = 'python3' if is_macos else 'python'
|
||||||
run(py + ' setup.py linux-package --update-check-interval=0 --verbose')
|
run(f'{python} setup.py linux-package --update-check-interval=0 --verbose')
|
||||||
if is_macos:
|
if is_macos:
|
||||||
run('python3 setup.py kitty.app --update-check-interval=0 --verbose')
|
run('python3 setup.py kitty.app --update-check-interval=0 --verbose')
|
||||||
run('kitty.app/Contents/MacOS/kitty +runpy "from kitty.constants import *; print(kitty_exe())"')
|
run('kitty.app/Contents/MacOS/kitty +runpy "from kitty.constants import *; print(kitty_exe())"')
|
||||||
@@ -79,11 +84,11 @@ def replace_in_file(path, src, dest):
|
|||||||
def setup_bundle_env():
|
def setup_bundle_env():
|
||||||
global SW
|
global SW
|
||||||
os.environ['SW'] = SW = '/Users/Shared/kitty-build/sw/sw' if is_macos else os.path.join(os.environ['GITHUB_WORKSPACE'], 'sw')
|
os.environ['SW'] = SW = '/Users/Shared/kitty-build/sw/sw' if is_macos else os.path.join(os.environ['GITHUB_WORKSPACE'], 'sw')
|
||||||
os.environ['PKG_CONFIG_PATH'] = SW + '/lib/pkgconfig'
|
os.environ['PKG_CONFIG_PATH'] = os.path.join(SW, 'lib', 'pkgconfig')
|
||||||
if is_macos:
|
if is_macos:
|
||||||
os.environ['PATH'] = '{}:{}'.format('/usr/local/opt/sphinx-doc/bin', os.environ['PATH'])
|
os.environ['PATH'] = '{}:{}'.format('/usr/local/opt/sphinx-doc/bin', os.environ['PATH'])
|
||||||
else:
|
else:
|
||||||
os.environ['LD_LIBRARY_PATH'] = SW + '/lib'
|
os.environ['LD_LIBRARY_PATH'] = os.path.join(SW, 'lib')
|
||||||
os.environ['PYTHONHOME'] = SW
|
os.environ['PYTHONHOME'] = SW
|
||||||
os.environ['PATH'] = '{}:{}'.format(os.path.join(SW, 'bin'), os.environ['PATH'])
|
os.environ['PATH'] = '{}:{}'.format(os.path.join(SW, 'bin'), os.environ['PATH'])
|
||||||
|
|
||||||
@@ -114,7 +119,7 @@ def main():
|
|||||||
setup_bundle_env()
|
setup_bundle_env()
|
||||||
else:
|
else:
|
||||||
if not is_macos and 'pythonLocation' in os.environ:
|
if not is_macos and 'pythonLocation' in os.environ:
|
||||||
os.environ['LD_LIBRARY_PATH'] = '{}/lib'.format(os.environ['pythonLocation'])
|
os.environ['LD_LIBRARY_PATH'] = os.path.join(os.environ['pythonLocation'], 'lib')
|
||||||
action = sys.argv[-1]
|
action = sys.argv[-1]
|
||||||
if action in ('build', 'package'):
|
if action in ('build', 'package'):
|
||||||
install_deps()
|
install_deps()
|
||||||
@@ -125,7 +130,7 @@ def main():
|
|||||||
elif action == 'test':
|
elif action == 'test':
|
||||||
test_kitty()
|
test_kitty()
|
||||||
else:
|
else:
|
||||||
raise SystemExit('Unknown action: ' + action)
|
raise SystemExit(f'Unknown action: {action}')
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
35
.github/workflows/ci.yml
vendored
@@ -20,15 +20,15 @@ jobs:
|
|||||||
cc: [gcc, clang]
|
cc: [gcc, clang]
|
||||||
include:
|
include:
|
||||||
- python: a
|
- python: a
|
||||||
pyver: 3.6
|
pyver: "3.8"
|
||||||
sanitize: 0
|
sanitize: 0
|
||||||
|
|
||||||
- python: b
|
- python: b
|
||||||
pyver: 3.7
|
pyver: "3.9"
|
||||||
sanitize: 1
|
sanitize: 1
|
||||||
|
|
||||||
- python: c
|
- python: c
|
||||||
pyver: 3.8
|
pyver: "3.10"
|
||||||
sanitize: 1
|
sanitize: 1
|
||||||
|
|
||||||
|
|
||||||
@@ -42,11 +42,11 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout source code
|
- name: Checkout source code
|
||||||
uses: actions/checkout@master
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
fetch-depth: 10
|
fetch-depth: 10
|
||||||
- name: Set up Python ${{ matrix.pyver }}
|
- name: Set up Python ${{ matrix.pyver }}
|
||||||
uses: actions/setup-python@master
|
uses: actions/setup-python@v3
|
||||||
with:
|
with:
|
||||||
python-version: ${{ matrix.pyver }}
|
python-version: ${{ matrix.pyver }}
|
||||||
|
|
||||||
@@ -63,17 +63,17 @@ jobs:
|
|||||||
CFLAGS: -funsigned-char
|
CFLAGS: -funsigned-char
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout source code
|
- name: Checkout source code
|
||||||
uses: actions/checkout@master
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
fetch-depth: 10
|
fetch-depth: 0 # needed for :commit: docs role
|
||||||
|
|
||||||
- name: Test for trailing whitespace
|
- name: Test for trailing whitespace
|
||||||
run: if grep -Inr '\s$' kitty kitty_tests kittens docs *.py *.asciidoc *.rst .gitattributes .gitignore; then echo Trailing whitespace found, aborting.; exit 1; fi
|
run: if grep -Inr '\s$' kitty kitty_tests kittens docs *.py *.asciidoc *.rst .gitattributes .gitignore; then echo Trailing whitespace found, aborting.; exit 1; fi
|
||||||
|
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@master
|
uses: actions/setup-python@v3
|
||||||
with:
|
with:
|
||||||
python-version: 3.8
|
python-version: 3.9
|
||||||
|
|
||||||
- name: Install build-only deps
|
- name: Install build-only deps
|
||||||
run: pip install -r docs/requirements.txt flake8 mypy types-requests types-docutils
|
run: pip install -r docs/requirements.txt flake8 mypy types-requests types-docutils
|
||||||
@@ -84,14 +84,17 @@ jobs:
|
|||||||
- name: Build kitty package
|
- name: Build kitty package
|
||||||
run: python .github/workflows/ci.py package
|
run: python .github/workflows/ci.py package
|
||||||
|
|
||||||
|
- name: Build kitty
|
||||||
|
run: python setup.py build --debug
|
||||||
|
|
||||||
- name: Run mypy
|
- name: Run mypy
|
||||||
run: python test.py mypy
|
run: ./test.py mypy
|
||||||
|
|
||||||
- name: Build man page
|
- name: Build man page
|
||||||
run: make FAIL_WARN=-W man
|
run: make FAIL_WARN=1 man
|
||||||
|
|
||||||
- name: Build HTML docs
|
- name: Build HTML docs
|
||||||
run: make FAIL_WARN=-W html
|
run: make FAIL_WARN=1 html
|
||||||
|
|
||||||
bundle:
|
bundle:
|
||||||
name: Bundle test (${{ matrix.os }})
|
name: Bundle test (${{ matrix.os }})
|
||||||
@@ -120,7 +123,7 @@ jobs:
|
|||||||
- name: Checkout source code
|
- name: Checkout source code
|
||||||
uses: actions/checkout@master
|
uses: actions/checkout@master
|
||||||
with:
|
with:
|
||||||
fetch-depth: 10
|
fetch-depth: 0 # needed for :commit: docs role
|
||||||
|
|
||||||
- name: Build kitty
|
- name: Build kitty
|
||||||
run: python3 .github/workflows/ci.py build
|
run: python3 .github/workflows/ci.py build
|
||||||
@@ -128,5 +131,11 @@ jobs:
|
|||||||
- name: Test kitty
|
- name: Test kitty
|
||||||
run: python3 .github/workflows/ci.py test
|
run: python3 .github/workflows/ci.py test
|
||||||
|
|
||||||
|
- name: Install deps for docs
|
||||||
|
run: python3 -m pip install -r docs/requirements.txt
|
||||||
|
|
||||||
|
- name: Builds docs
|
||||||
|
run: make FAIL_WARN=1 docs
|
||||||
|
|
||||||
- name: Build kitty package
|
- name: Build kitty package
|
||||||
run: python3 .github/workflows/ci.py package
|
run: python3 .github/workflows/ci.py package
|
||||||
|
|||||||
13
.github/workflows/codeql-analysis.yml
vendored
@@ -16,23 +16,18 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
# We must fetch at least the immediate parents so that if this is
|
# We must fetch at least the immediate parents so that if this is
|
||||||
# a pull request then we can checkout the head.
|
# a pull request then we can checkout the head.
|
||||||
fetch-depth: 2
|
fetch-depth: 2
|
||||||
|
|
||||||
# If this run was triggered by a pull request event, then checkout
|
|
||||||
# the head of the pull request instead of the merge commit.
|
|
||||||
- run: git checkout HEAD^2
|
|
||||||
if: ${{ github.event_name == 'pull_request' }}
|
|
||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
# Initializes the CodeQL tools for scanning.
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v1
|
uses: github/codeql-action/init@v1
|
||||||
# Override language selection by uncommenting this and choosing your languages
|
with:
|
||||||
# with:
|
languages: python, c
|
||||||
# languages: go, javascript, csharp, python, cpp, java
|
setup-python-dependencies: false
|
||||||
|
|
||||||
- name: Build kitty
|
- name: Build kitty
|
||||||
run: python3 .github/workflows/ci.py build
|
run: python3 .github/workflows/ci.py build
|
||||||
|
|||||||
5
.gitignore
vendored
@@ -2,6 +2,8 @@
|
|||||||
*.pyc
|
*.pyc
|
||||||
*.pyo
|
*.pyo
|
||||||
*_stub.pyi
|
*_stub.pyi
|
||||||
|
*_generated.go
|
||||||
|
*_generated.h
|
||||||
/.dmypy.json
|
/.dmypy.json
|
||||||
/tags
|
/tags
|
||||||
/build/
|
/build/
|
||||||
@@ -10,7 +12,7 @@
|
|||||||
/compile_commands.json
|
/compile_commands.json
|
||||||
/link_commands.json
|
/link_commands.json
|
||||||
/glad/out/
|
/glad/out/
|
||||||
/kitty/launcher/
|
/kitty/launcher/kitty*
|
||||||
/*.dSYM/
|
/*.dSYM/
|
||||||
__pycache__/
|
__pycache__/
|
||||||
/glfw/wayland-*-client-protocol.[ch]
|
/glfw/wayland-*-client-protocol.[ch]
|
||||||
@@ -19,3 +21,4 @@ __pycache__/
|
|||||||
/.mypy_cache
|
/.mypy_cache
|
||||||
.DS_Store
|
.DS_Store
|
||||||
bypy/b
|
bypy/b
|
||||||
|
bypy/virtual-machines.conf
|
||||||
|
|||||||
13
Brewfile
@@ -1,6 +1,7 @@
|
|||||||
pkg-config
|
brew "pkg-config"
|
||||||
zlib
|
brew "zlib"
|
||||||
python
|
brew "librsync"
|
||||||
imagemagick
|
brew "python"
|
||||||
harfbuzz
|
brew "imagemagick"
|
||||||
sphinx-doc
|
brew "harfbuzz"
|
||||||
|
brew "sphinx-doc"
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
To build from source: <https://sw.kovidgoyal.net/kitty/build/>
|
[To build from source](https://sw.kovidgoyal.net/kitty/build/)
|
||||||
|
|
||||||
Pre-built binaries: <https://sw.kovidgoyal.net/kitty/binary/>
|
[Pre-built binaries](https://sw.kovidgoyal.net/kitty/binary/)
|
||||||
|
|||||||
2
LICENSE
@@ -671,4 +671,4 @@ into proprietary programs. If your program is a subroutine library, you
|
|||||||
may consider it more useful to permit linking proprietary applications with
|
may consider it more useful to permit linking proprietary applications with
|
||||||
the library. If this is what you want to do, use the GNU Lesser General
|
the library. If this is what you want to do, use the GNU Lesser General
|
||||||
Public License instead of this License. But first, please read
|
Public License instead of this License. But first, please read
|
||||||
<https://www.gnu.org/philosophy/why-not-lgpl.html>.
|
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||||||
|
|||||||
19
Makefile
@@ -5,6 +5,10 @@ ifdef VERBOSE
|
|||||||
VVAL=--verbose
|
VVAL=--verbose
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifdef FAIL_WARN
|
||||||
|
export FAIL_WARN
|
||||||
|
endif
|
||||||
|
|
||||||
all:
|
all:
|
||||||
python3 setup.py $(VVAL)
|
python3 setup.py $(VVAL)
|
||||||
|
|
||||||
@@ -31,14 +35,23 @@ profile:
|
|||||||
app:
|
app:
|
||||||
python3 setup.py kitty.app $(VVAL)
|
python3 setup.py kitty.app $(VVAL)
|
||||||
|
|
||||||
|
linux-package: FORCE
|
||||||
|
rm -rf linux-package
|
||||||
|
python3 setup.py linux-package
|
||||||
|
|
||||||
|
FORCE:
|
||||||
|
|
||||||
man:
|
man:
|
||||||
$(MAKE) FAIL_WARN=$(FAIL_WARN) -C docs man
|
$(MAKE) -C docs man
|
||||||
|
|
||||||
html:
|
html:
|
||||||
$(MAKE) FAIL_WARN=$(FAIL_WARN) -C docs html
|
$(MAKE) -C docs html
|
||||||
|
|
||||||
|
dirhtml:
|
||||||
|
$(MAKE) -C docs dirhtml
|
||||||
|
|
||||||
linkcheck:
|
linkcheck:
|
||||||
$(MAKE) FAIL_WARN=$(FAIL_WARN) -C docs linkcheck
|
$(MAKE) -C docs linkcheck
|
||||||
|
|
||||||
website:
|
website:
|
||||||
./publish.py --only website
|
./publish.py --only website
|
||||||
|
|||||||
@@ -11,4 +11,4 @@ https://www.reddit.com/r/KittyTerminal[Reddit community]
|
|||||||
|
|
||||||
Packaging status in various repositories:
|
Packaging status in various repositories:
|
||||||
|
|
||||||
image:https://repology.org/badge/vertical-allrepos/kitty.svg[https://repology.org/project/kitty/versions]
|
image:https://repology.org/badge/vertical-allrepos/kitty.svg["Packaging status", link="https://repology.org/project/kitty/versions"]
|
||||||
|
|||||||
146
__main__.py
@@ -1,151 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# vim:fileencoding=utf-8
|
|
||||||
# License: GPL v3 Copyright: 2015, Kovid Goyal <kovid at kovidgoyal.net>
|
# License: GPL v3 Copyright: 2015, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
from typing import List
|
|
||||||
|
|
||||||
|
|
||||||
def icat(args: List[str]) -> None:
|
|
||||||
from kittens.runner import run_kitten as rk
|
|
||||||
sys.argv = args
|
|
||||||
rk('icat')
|
|
||||||
|
|
||||||
|
|
||||||
def list_fonts(args: List[str]) -> None:
|
|
||||||
from kitty.fonts.list import main as list_main
|
|
||||||
list_main(args)
|
|
||||||
|
|
||||||
|
|
||||||
def remote_control(args: List[str]) -> None:
|
|
||||||
from kitty.remote_control import main as rc_main
|
|
||||||
rc_main(args)
|
|
||||||
|
|
||||||
|
|
||||||
def runpy(args: List[str]) -> None:
|
|
||||||
sys.argv = ['kitty'] + args[2:]
|
|
||||||
exec(args[1])
|
|
||||||
|
|
||||||
|
|
||||||
def hold(args: List[str]) -> None:
|
|
||||||
import subprocess
|
|
||||||
import tty
|
|
||||||
from contextlib import suppress
|
|
||||||
ret = subprocess.Popen(args[1:]).wait()
|
|
||||||
with suppress(BaseException):
|
|
||||||
print('\n\x1b[1;32mPress any key to exit', end='', flush=True)
|
|
||||||
with suppress(BaseException):
|
|
||||||
tty.setraw(sys.stdin.fileno())
|
|
||||||
sys.stdin.buffer.read(1)
|
|
||||||
raise SystemExit(ret)
|
|
||||||
|
|
||||||
|
|
||||||
def complete(args: List[str]) -> None:
|
|
||||||
from kitty.complete import main as complete_main
|
|
||||||
complete_main(args[1:], entry_points, namespaced_entry_points)
|
|
||||||
|
|
||||||
|
|
||||||
def launch(args: List[str]) -> None:
|
|
||||||
import runpy
|
|
||||||
sys.argv = args[1:]
|
|
||||||
try:
|
|
||||||
exe = args[1]
|
|
||||||
except IndexError:
|
|
||||||
raise SystemExit(
|
|
||||||
'usage: kitty +launch script.py [arguments to be passed to script.py ...]\n\n'
|
|
||||||
'script.py will be run with full access to kitty code. If script.py is '
|
|
||||||
'prefixed with a : it will be searched for in PATH'
|
|
||||||
)
|
|
||||||
if exe.startswith(':'):
|
|
||||||
import shutil
|
|
||||||
q = shutil.which(exe[1:])
|
|
||||||
if not q:
|
|
||||||
raise SystemExit(f'{exe[1:]} not found in PATH')
|
|
||||||
exe = q
|
|
||||||
if not os.path.exists(exe):
|
|
||||||
raise SystemExit(f'{exe} does not exist')
|
|
||||||
runpy.run_path(exe, run_name='__main__')
|
|
||||||
|
|
||||||
|
|
||||||
def run_kitten(args: List[str]) -> None:
|
|
||||||
try:
|
|
||||||
kitten = args[1]
|
|
||||||
except IndexError:
|
|
||||||
from kittens.runner import list_kittens
|
|
||||||
list_kittens()
|
|
||||||
raise SystemExit(1)
|
|
||||||
sys.argv = args[1:]
|
|
||||||
from kittens.runner import run_kitten as rk
|
|
||||||
rk(kitten)
|
|
||||||
|
|
||||||
|
|
||||||
def edit_config_file(args: List[str]) -> None:
|
|
||||||
from kitty.cli import create_default_opts
|
|
||||||
from kitty.fast_data_types import set_options
|
|
||||||
from kitty.utils import edit_config_file as f
|
|
||||||
set_options(create_default_opts())
|
|
||||||
f()
|
|
||||||
|
|
||||||
|
|
||||||
def namespaced(args: List[str]) -> None:
|
|
||||||
try:
|
|
||||||
func = namespaced_entry_points[args[1]]
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
func(args[1:])
|
|
||||||
return
|
|
||||||
raise SystemExit(f'{args[1]} is not a known entry point. Choices are: ' + ', '.join(namespaced_entry_points))
|
|
||||||
|
|
||||||
|
|
||||||
entry_points = {
|
|
||||||
# These two are here for backwards compat
|
|
||||||
'icat': icat,
|
|
||||||
'list-fonts': list_fonts,
|
|
||||||
'runpy': runpy,
|
|
||||||
'launch': launch,
|
|
||||||
'kitten': run_kitten,
|
|
||||||
'edit-config': edit_config_file,
|
|
||||||
|
|
||||||
'@': remote_control,
|
|
||||||
'+': namespaced,
|
|
||||||
}
|
|
||||||
namespaced_entry_points = {k: v for k, v in entry_points.items() if k[0] not in '+@'}
|
|
||||||
namespaced_entry_points['hold'] = hold
|
|
||||||
namespaced_entry_points['complete'] = complete
|
|
||||||
|
|
||||||
|
|
||||||
def setup_openssl_environment() -> None:
|
|
||||||
# Workaround for Linux distros that have still failed to get their heads
|
|
||||||
# out of their asses and implement a common location for SSL certificates.
|
|
||||||
# It's not that hard people, there exists a wonderful tool called the symlink
|
|
||||||
# See https://www.mobileread.com/forums/showthread.php?t=256095
|
|
||||||
if 'SSL_CERT_FILE' not in os.environ and 'SSL_CERT_DIR' not in os.environ:
|
|
||||||
if os.access('/etc/pki/tls/certs/ca-bundle.crt', os.R_OK):
|
|
||||||
os.environ['SSL_CERT_FILE'] = '/etc/pki/tls/certs/ca-bundle.crt'
|
|
||||||
setattr(sys, 'kitty_ssl_env_var', 'SSL_CERT_FILE')
|
|
||||||
elif os.path.isdir('/etc/ssl/certs'):
|
|
||||||
os.environ['SSL_CERT_DIR'] = '/etc/ssl/certs'
|
|
||||||
setattr(sys, 'kitty_ssl_env_var', 'SSL_CERT_DIR')
|
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
|
||||||
if getattr(sys, 'frozen', False) and 'darwin' not in sys.platform.lower():
|
|
||||||
setup_openssl_environment()
|
|
||||||
first_arg = '' if len(sys.argv) < 2 else sys.argv[1]
|
|
||||||
func = entry_points.get(first_arg)
|
|
||||||
if func is None:
|
|
||||||
if first_arg.startswith('@'):
|
|
||||||
remote_control(['@', first_arg[1:]] + sys.argv[2:])
|
|
||||||
elif first_arg.startswith('+'):
|
|
||||||
namespaced(['+', first_arg[1:]] + sys.argv[2:])
|
|
||||||
else:
|
|
||||||
from kitty.main import main as kitty_main
|
|
||||||
kitty_main()
|
|
||||||
else:
|
|
||||||
func(sys.argv[1:])
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
from kitty.entry_points import main
|
||||||
main()
|
main()
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
import glob
|
import glob
|
||||||
import os
|
import os
|
||||||
import re
|
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
@@ -13,11 +12,10 @@ import tempfile
|
|||||||
|
|
||||||
def compile_terminfo(base):
|
def compile_terminfo(base):
|
||||||
with tempfile.TemporaryDirectory() as tdir:
|
with tempfile.TemporaryDirectory() as tdir:
|
||||||
proc = subprocess.run(['tic', '-x', '-o' + tdir, 'terminfo/kitty.terminfo'], check=True, stderr=subprocess.PIPE)
|
proc = subprocess.run(['tic', '-x', f'-o{tdir}', 'terminfo/kitty.terminfo'], capture_output=True)
|
||||||
regex = '^"terminfo/kitty.terminfo", line [0-9]+, col [0-9]+, terminal \'xterm-kitty\': older tic versions may treat the description field as an alias$'
|
if proc.returncode != 0:
|
||||||
for error in proc.stderr.decode('utf-8').splitlines():
|
sys.stderr.buffer.write(proc.stderr)
|
||||||
if not re.match(regex, error):
|
raise SystemExit(proc.returncode)
|
||||||
print(error, file=sys.stderr)
|
|
||||||
tfiles = glob.glob(os.path.join(tdir, '*', 'xterm-kitty'))
|
tfiles = glob.glob(os.path.join(tdir, '*', 'xterm-kitty'))
|
||||||
if not tfiles:
|
if not tfiles:
|
||||||
raise SystemExit('tic failed to output the compiled kitty terminfo file')
|
raise SystemExit('tic failed to output the compiled kitty terminfo file')
|
||||||
@@ -40,6 +38,13 @@ def generate_terminfo():
|
|||||||
|
|
||||||
with open('terminfo/kitty.terminfo', 'w') as f:
|
with open('terminfo/kitty.terminfo', 'w') as f:
|
||||||
f.write(generate_terminfo())
|
f.write(generate_terminfo())
|
||||||
|
proc = subprocess.run(['tic', '-CrT0', 'terminfo/kitty.terminfo'], capture_output=True)
|
||||||
|
if proc.returncode != 0:
|
||||||
|
sys.stderr.buffer.write(proc.stderr)
|
||||||
|
raise SystemExit(proc.returncode)
|
||||||
|
tcap = proc.stdout.decode('utf-8').splitlines()[-1]
|
||||||
|
with open('terminfo/kitty.termcap', 'w') as f:
|
||||||
|
f.write(tcap)
|
||||||
|
|
||||||
compile_terminfo(os.path.join(base, 'terminfo'))
|
compile_terminfo(os.path.join(base, 'terminfo'))
|
||||||
|
|
||||||
|
|||||||
@@ -26,10 +26,11 @@ def initialize_constants():
|
|||||||
kitty_constants = {}
|
kitty_constants = {}
|
||||||
src = read_src_file('constants.py')
|
src = read_src_file('constants.py')
|
||||||
nv = re.search(r'Version\((\d+), (\d+), (\d+)\)', src)
|
nv = re.search(r'Version\((\d+), (\d+), (\d+)\)', src)
|
||||||
kitty_constants['version'] = '%s.%s.%s' % (nv.group(1), nv.group(2), nv.group(3))
|
kitty_constants['version'] = f'{nv.group(1)}.{nv.group(2)}.{nv.group(3)}'
|
||||||
kitty_constants['appname'] = re.search(
|
kitty_constants['appname'] = re.search(
|
||||||
r'appname: str\s+=\s+(u{0,1})[\'"]([^\'"]+)[\'"]', src
|
r'appname: str\s+=\s+(u{0,1})[\'"]([^\'"]+)[\'"]', src
|
||||||
).group(2)
|
).group(2)
|
||||||
|
kitty_constants['cacerts_url'] = 'https://curl.haxx.se/ca/cacert.pem'
|
||||||
return kitty_constants
|
return kitty_constants
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
image 'https://partner-images.canonical.com/core/xenial/current/ubuntu-xenial-core-cloudimg-{}-root.tar.gz'
|
image 'https://cloud-images.ubuntu.com/releases/bionic/release/ubuntu-18.04-server-cloudimg-{}.img'
|
||||||
|
|
||||||
deps 'bison flex libxcursor-dev libxrandr-dev libxi-dev libxinerama-dev libgl1-mesa-dev libxcb-xkb-dev libfontconfig1-dev libdbus-1-dev'
|
deps 'bison flex libxcursor-dev libxrandr-dev libxi-dev libxinerama-dev libgl1-mesa-dev libxcb-xkb-dev libfontconfig1-dev libdbus-1-dev'
|
||||||
|
|||||||
@@ -19,7 +19,11 @@ from bypy.freeze import (
|
|||||||
from bypy.utils import get_dll_path, mkdtemp, py_compile, walk
|
from bypy.utils import get_dll_path, mkdtemp, py_compile, walk
|
||||||
|
|
||||||
j = os.path.join
|
j = os.path.join
|
||||||
arch = 'x86_64' if is64bit else 'i686'
|
machine = (os.uname()[4] or '').lower()
|
||||||
|
if machine.startswith('arm64') or machine.startswith('aarch64'):
|
||||||
|
arch = 'arm64'
|
||||||
|
else:
|
||||||
|
arch = 'x86_64' if is64bit else 'i686'
|
||||||
self_dir = os.path.dirname(os.path.abspath(__file__))
|
self_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
py_ver = '.'.join(map(str, python_major_minor_version()))
|
py_ver = '.'.join(map(str, python_major_minor_version()))
|
||||||
iv = globals()['init_env']
|
iv = globals()['init_env']
|
||||||
@@ -29,12 +33,16 @@ kitty_constants = iv['kitty_constants']
|
|||||||
def binary_includes():
|
def binary_includes():
|
||||||
return tuple(map(get_dll_path, (
|
return tuple(map(get_dll_path, (
|
||||||
'expat', 'sqlite3', 'ffi', 'z', 'lzma', 'png16', 'lcms2', 'crypt',
|
'expat', 'sqlite3', 'ffi', 'z', 'lzma', 'png16', 'lcms2', 'crypt',
|
||||||
'iconv', 'pcre', 'graphite2', 'glib-2.0', 'freetype',
|
'iconv', 'pcre', 'graphite2', 'glib-2.0', 'freetype', 'rsync',
|
||||||
'harfbuzz', 'xkbcommon', 'xkbcommon-x11',
|
'harfbuzz', 'xkbcommon', 'xkbcommon-x11',
|
||||||
'ncursesw', 'readline', 'brotlicommon', 'brotlienc', 'brotlidec'
|
# fontconfig is not bundled because in typical brain dead Linux
|
||||||
|
# distro fashion, different distros use different default config
|
||||||
|
# paths for fontconfig.
|
||||||
|
'ncursesw', 'readline', 'brotlicommon', 'brotlienc', 'brotlidec',
|
||||||
|
'wayland-client', 'wayland-cursor',
|
||||||
))) + (
|
))) + (
|
||||||
get_dll_path('bz2', 2), get_dll_path('ssl', 2), get_dll_path('crypto', 2),
|
get_dll_path('bz2', 2), get_dll_path('ssl', 2), get_dll_path('crypto', 2),
|
||||||
get_dll_path('python' + py_ver, 2),
|
get_dll_path(f'python{py_ver}', 2),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -43,7 +51,7 @@ class Env:
|
|||||||
def __init__(self, package_dir):
|
def __init__(self, package_dir):
|
||||||
self.base = package_dir
|
self.base = package_dir
|
||||||
self.lib_dir = j(self.base, 'lib')
|
self.lib_dir = j(self.base, 'lib')
|
||||||
self.py_dir = j(self.lib_dir, 'python' + py_ver)
|
self.py_dir = j(self.lib_dir, f'python{py_ver}')
|
||||||
os.makedirs(self.py_dir)
|
os.makedirs(self.py_dir)
|
||||||
self.bin_dir = j(self.base, 'bin')
|
self.bin_dir = j(self.base, 'bin')
|
||||||
self.obj_dir = mkdtemp('launchers-')
|
self.obj_dir = mkdtemp('launchers-')
|
||||||
@@ -92,9 +100,18 @@ def copy_libs(env):
|
|||||||
subprocess.check_call(['chrpath', '-d', dest])
|
subprocess.check_call(['chrpath', '-d', dest])
|
||||||
|
|
||||||
|
|
||||||
|
def add_ca_certs(env):
|
||||||
|
print('Downloading CA certs...')
|
||||||
|
from urllib.request import urlopen
|
||||||
|
cdata = urlopen(kitty_constants['cacerts_url']).read()
|
||||||
|
dest = os.path.join(env.lib_dir, 'cacert.pem')
|
||||||
|
with open(dest, 'wb') as f:
|
||||||
|
f.write(cdata)
|
||||||
|
|
||||||
|
|
||||||
def copy_python(env):
|
def copy_python(env):
|
||||||
print('Copying python...')
|
print('Copying python...')
|
||||||
srcdir = j(PREFIX, 'lib/python' + py_ver)
|
srcdir = j(PREFIX, f'lib/python{py_ver}')
|
||||||
|
|
||||||
for x in os.listdir(srcdir):
|
for x in os.listdir(srcdir):
|
||||||
y = j(srcdir, x)
|
y = j(srcdir, x)
|
||||||
@@ -106,8 +123,7 @@ def copy_python(env):
|
|||||||
shutil.copy2(y, env.py_dir)
|
shutil.copy2(y, env.py_dir)
|
||||||
|
|
||||||
srcdir = j(srcdir, 'site-packages')
|
srcdir = j(srcdir, 'site-packages')
|
||||||
site_packages_dir = j(env.py_dir, 'site-packages')
|
import_site_packages(srcdir, env.py_dir)
|
||||||
import_site_packages(srcdir, site_packages_dir)
|
|
||||||
|
|
||||||
pdir = os.path.join(env.lib_dir, 'kitty-extensions')
|
pdir = os.path.join(env.lib_dir, 'kitty-extensions')
|
||||||
os.makedirs(pdir, exist_ok=True)
|
os.makedirs(pdir, exist_ok=True)
|
||||||
@@ -127,6 +143,7 @@ def copy_python(env):
|
|||||||
iv['sanitize_source_folder'](os.path.join(env.py_dir, x))
|
iv['sanitize_source_folder'](os.path.join(env.py_dir, x))
|
||||||
py_compile(env.py_dir)
|
py_compile(env.py_dir)
|
||||||
freeze_python(env.py_dir, pdir, env.obj_dir, ext_map, develop_mode_env_var='KITTY_DEVELOP_FROM', remove_pyc_files=True)
|
freeze_python(env.py_dir, pdir, env.obj_dir, ext_map, develop_mode_env_var='KITTY_DEVELOP_FROM', remove_pyc_files=True)
|
||||||
|
shutil.rmtree(env.py_dir)
|
||||||
|
|
||||||
|
|
||||||
def build_launcher(env):
|
def build_launcher(env):
|
||||||
@@ -175,11 +192,11 @@ def strip_files(files, argv_max=(256 * 1024)):
|
|||||||
|
|
||||||
|
|
||||||
def strip_binaries(files):
|
def strip_binaries(files):
|
||||||
print('Stripping %d files...' % len(files))
|
print(f'Stripping {len(files)} files...')
|
||||||
before = sum(os.path.getsize(x) for x in files)
|
before = sum(os.path.getsize(x) for x in files)
|
||||||
strip_files(files)
|
strip_files(files)
|
||||||
after = sum(os.path.getsize(x) for x in files)
|
after = sum(os.path.getsize(x) for x in files)
|
||||||
print('Stripped %.1f MB' % ((before - after) / (1024 * 1024.)))
|
print('Stripped {:.1f} MB'.format((before - after) / (1024 * 1024.)))
|
||||||
|
|
||||||
|
|
||||||
def create_tarfile(env, compression_level='9'):
|
def create_tarfile(env, compression_level='9'):
|
||||||
@@ -191,7 +208,7 @@ def create_tarfile(env, compression_level='9'):
|
|||||||
if err.errno != errno.ENOENT:
|
if err.errno != errno.ENOENT:
|
||||||
raise
|
raise
|
||||||
os.mkdir(base)
|
os.mkdir(base)
|
||||||
dist = os.path.join(base, '%s-%s-%s.tar' % (kitty_constants['appname'], kitty_constants['version'], arch))
|
dist = os.path.join(base, f'{kitty_constants["appname"]}-{kitty_constants["version"]}-{arch}.tar')
|
||||||
with tarfile.open(dist, mode='w', format=tarfile.PAX_FORMAT) as tf:
|
with tarfile.open(dist, mode='w', format=tarfile.PAX_FORMAT) as tf:
|
||||||
cwd = os.getcwd()
|
cwd = os.getcwd()
|
||||||
os.chdir(env.base)
|
os.chdir(env.base)
|
||||||
@@ -201,13 +218,13 @@ def create_tarfile(env, compression_level='9'):
|
|||||||
finally:
|
finally:
|
||||||
os.chdir(cwd)
|
os.chdir(cwd)
|
||||||
print('Compressing archive...')
|
print('Compressing archive...')
|
||||||
ans = dist.rpartition('.')[0] + '.txz'
|
ans = f'{dist.rpartition(".")[0]}.txz'
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
subprocess.check_call(['xz', '--threads=0', '-f', '-' + compression_level, dist])
|
subprocess.check_call(['xz', '--threads=0', '-f', f'-{compression_level}', dist])
|
||||||
secs = time.time() - start_time
|
secs = time.time() - start_time
|
||||||
print('Compressed in %d minutes %d seconds' % (secs // 60, secs % 60))
|
print('Compressed in {} minutes {} seconds'.format(secs // 60, secs % 60))
|
||||||
os.rename(dist + '.xz', ans)
|
os.rename(f'{dist}.xz', ans)
|
||||||
print('Archive %s created: %.2f MB' % (
|
print('Archive {} created: {:.2f} MB'.format(
|
||||||
os.path.basename(ans), os.stat(ans).st_size / (1024.**2)))
|
os.path.basename(ans), os.stat(ans).st_size / (1024.**2)))
|
||||||
|
|
||||||
|
|
||||||
@@ -220,6 +237,7 @@ def main():
|
|||||||
build_launcher(env)
|
build_launcher(env)
|
||||||
files = find_binaries(env)
|
files = find_binaries(env)
|
||||||
fix_permissions(files)
|
fix_permissions(files)
|
||||||
|
add_ca_certs(env)
|
||||||
if not args.dont_strip:
|
if not args.dont_strip:
|
||||||
strip_binaries(files)
|
strip_binaries(files)
|
||||||
if not args.skip_tests:
|
if not args.skip_tests:
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ def strip_files(files, argv_max=(256 * 1024)):
|
|||||||
def files_in(folder):
|
def files_in(folder):
|
||||||
for record in os.walk(folder):
|
for record in os.walk(folder):
|
||||||
for f in record[-1]:
|
for f in record[-1]:
|
||||||
yield os.path.join(record[0], f)
|
yield join(record[0], f)
|
||||||
|
|
||||||
|
|
||||||
def expand_dirs(items, exclude=lambda x: x.endswith('.so')):
|
def expand_dirs(items, exclude=lambda x: x.endswith('.so')):
|
||||||
@@ -103,7 +103,7 @@ def expand_dirs(items, exclude=lambda x: x.endswith('.so')):
|
|||||||
|
|
||||||
|
|
||||||
def do_sign(app_dir):
|
def do_sign(app_dir):
|
||||||
with current_dir(os.path.join(app_dir, 'Contents')):
|
with current_dir(join(app_dir, 'Contents')):
|
||||||
# Sign all .so files
|
# Sign all .so files
|
||||||
so_files = {x for x in files_in('.') if x.endswith('.so')}
|
so_files = {x for x in files_in('.') if x.endswith('.so')}
|
||||||
codesign(so_files)
|
codesign(so_files)
|
||||||
@@ -153,7 +153,7 @@ class Freeze(object):
|
|||||||
self.to_strip = []
|
self.to_strip = []
|
||||||
self.warnings = []
|
self.warnings = []
|
||||||
self.py_ver = py_ver
|
self.py_ver = py_ver
|
||||||
self.python_stdlib = join(self.resources_dir, 'Python', 'lib', 'python' + self.py_ver)
|
self.python_stdlib = join(self.resources_dir, 'Python', 'lib', f'python{self.py_ver}')
|
||||||
self.site_packages = self.python_stdlib # hack to avoid needing to add site-packages to path
|
self.site_packages = self.python_stdlib # hack to avoid needing to add site-packages to path
|
||||||
self.obj_dir = mkdtemp('launchers-')
|
self.obj_dir = mkdtemp('launchers-')
|
||||||
|
|
||||||
@@ -170,16 +170,35 @@ class Freeze(object):
|
|||||||
self.add_stdlib()
|
self.add_stdlib()
|
||||||
self.add_misc_libraries()
|
self.add_misc_libraries()
|
||||||
self.freeze_python()
|
self.freeze_python()
|
||||||
|
self.add_ca_certs()
|
||||||
if not self.dont_strip:
|
if not self.dont_strip:
|
||||||
self.strip_files()
|
self.strip_files()
|
||||||
if not self.skip_tests:
|
if not self.skip_tests:
|
||||||
self.run_tests()
|
self.run_tests()
|
||||||
# self.run_shell()
|
# self.run_shell()
|
||||||
|
|
||||||
ret = self.makedmg(self.build_dir, APPNAME + '-' + VERSION)
|
ret = self.makedmg(self.build_dir, f'{APPNAME}-{VERSION}')
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
@flush
|
||||||
|
def add_ca_certs(self):
|
||||||
|
print('\nDownloading CA certs...')
|
||||||
|
from urllib.request import urlopen
|
||||||
|
cdata = None
|
||||||
|
for i in range(5):
|
||||||
|
try:
|
||||||
|
cdata = urlopen(kitty_constants['cacerts_url']).read()
|
||||||
|
break
|
||||||
|
except Exception as e:
|
||||||
|
print(f'Downloading CA certs failed with error: {e}, retrying...')
|
||||||
|
|
||||||
|
if cdata is None:
|
||||||
|
raise SystemExit('Downloading C certs failed, giving up')
|
||||||
|
dest = join(self.contents_dir, 'Resources', 'cacert.pem')
|
||||||
|
with open(dest, 'wb') as f:
|
||||||
|
f.write(cdata)
|
||||||
|
|
||||||
@flush
|
@flush
|
||||||
def strip_files(self):
|
def strip_files(self):
|
||||||
print('\nStripping files...')
|
print('\nStripping files...')
|
||||||
@@ -187,7 +206,7 @@ class Freeze(object):
|
|||||||
|
|
||||||
@flush
|
@flush
|
||||||
def run_tests(self):
|
def run_tests(self):
|
||||||
iv['run_tests'](os.path.join(self.contents_dir, 'MacOS', 'kitty'))
|
iv['run_tests'](join(self.contents_dir, 'MacOS', 'kitty'))
|
||||||
|
|
||||||
@flush
|
@flush
|
||||||
def set_id(self, path_to_lib, new_id):
|
def set_id(self, path_to_lib, new_id):
|
||||||
@@ -212,10 +231,10 @@ class Freeze(object):
|
|||||||
@flush
|
@flush
|
||||||
def get_local_dependencies(self, path_to_lib):
|
def get_local_dependencies(self, path_to_lib):
|
||||||
for x, is_id in self.get_dependencies(path_to_lib):
|
for x, is_id in self.get_dependencies(path_to_lib):
|
||||||
for y in (PREFIX + '/lib/', PREFIX + '/python/Python.framework/'):
|
for y in (f'{PREFIX}/lib/', f'{PREFIX}/python/Python.framework/', '@rpath/'):
|
||||||
if x.startswith(y):
|
if x.startswith(y):
|
||||||
if y == PREFIX + '/python/Python.framework/':
|
if y == f'{PREFIX}/python/Python.framework/':
|
||||||
y = PREFIX + '/python/'
|
y = f'{PREFIX}/python/'
|
||||||
yield x, x[len(y):], is_id
|
yield x, x[len(y):], is_id
|
||||||
break
|
break
|
||||||
|
|
||||||
@@ -229,7 +248,7 @@ class Freeze(object):
|
|||||||
self.to_strip.append(path_to_lib)
|
self.to_strip.append(path_to_lib)
|
||||||
old_mode = flipwritable(path_to_lib)
|
old_mode = flipwritable(path_to_lib)
|
||||||
for dep, bname, is_id in self.get_local_dependencies(path_to_lib):
|
for dep, bname, is_id in self.get_local_dependencies(path_to_lib):
|
||||||
ndep = self.FID + '/' + bname
|
ndep = f'{self.FID}/{bname}'
|
||||||
self.change_dep(dep, ndep, is_id, path_to_lib)
|
self.change_dep(dep, ndep, is_id, path_to_lib)
|
||||||
ldeps = list(self.get_local_dependencies(path_to_lib))
|
ldeps = list(self.get_local_dependencies(path_to_lib))
|
||||||
if ldeps:
|
if ldeps:
|
||||||
@@ -242,7 +261,7 @@ class Freeze(object):
|
|||||||
@flush
|
@flush
|
||||||
def add_python_framework(self):
|
def add_python_framework(self):
|
||||||
print('\nAdding Python framework')
|
print('\nAdding Python framework')
|
||||||
src = join(PREFIX + '/python', 'Python.framework')
|
src = join(f'{PREFIX}/python', 'Python.framework')
|
||||||
x = join(self.frameworks_dir, 'Python.framework')
|
x = join(self.frameworks_dir, 'Python.framework')
|
||||||
curr = os.path.realpath(join(src, 'Versions', 'Current'))
|
curr = os.path.realpath(join(src, 'Versions', 'Current'))
|
||||||
currd = join(x, 'Versions', basename(curr))
|
currd = join(x, 'Versions', basename(curr))
|
||||||
@@ -252,12 +271,12 @@ class Freeze(object):
|
|||||||
shutil.copy2(join(curr, 'Python'), currd)
|
shutil.copy2(join(curr, 'Python'), currd)
|
||||||
self.set_id(
|
self.set_id(
|
||||||
join(currd, 'Python'),
|
join(currd, 'Python'),
|
||||||
self.FID + '/Python.framework/Versions/%s/Python' % basename(curr))
|
f'{self.FID}/Python.framework/Versions/{basename(curr)}/Python')
|
||||||
# The following is needed for codesign
|
# The following is needed for codesign
|
||||||
with current_dir(x):
|
with current_dir(x):
|
||||||
os.symlink(basename(curr), 'Versions/Current')
|
os.symlink(basename(curr), 'Versions/Current')
|
||||||
for y in ('Python', 'Resources'):
|
for y in ('Python', 'Resources'):
|
||||||
os.symlink('Versions/Current/%s' % y, y)
|
os.symlink(f'Versions/Current/{y}', y)
|
||||||
|
|
||||||
@flush
|
@flush
|
||||||
def install_dylib(self, path, set_id=True):
|
def install_dylib(self, path, set_id=True):
|
||||||
@@ -265,7 +284,7 @@ class Freeze(object):
|
|||||||
if set_id:
|
if set_id:
|
||||||
self.set_id(
|
self.set_id(
|
||||||
join(self.frameworks_dir, basename(path)),
|
join(self.frameworks_dir, basename(path)),
|
||||||
self.FID + '/' + basename(path))
|
f'{self.FID}/{basename(path)}')
|
||||||
self.fix_dependencies_in_lib(join(self.frameworks_dir, basename(path)))
|
self.fix_dependencies_in_lib(join(self.frameworks_dir, basename(path)))
|
||||||
|
|
||||||
@flush
|
@flush
|
||||||
@@ -278,13 +297,14 @@ class Freeze(object):
|
|||||||
'lcms2.2',
|
'lcms2.2',
|
||||||
'crypto.1.1',
|
'crypto.1.1',
|
||||||
'ssl.1.1',
|
'ssl.1.1',
|
||||||
|
'rsync.2',
|
||||||
):
|
):
|
||||||
print('\nAdding', x)
|
print('\nAdding', x)
|
||||||
x = 'lib%s.dylib' % x
|
x = f'lib{x}.dylib'
|
||||||
src = join(PREFIX, 'lib', x)
|
src = join(PREFIX, 'lib', x)
|
||||||
shutil.copy2(src, self.frameworks_dir)
|
shutil.copy2(src, self.frameworks_dir)
|
||||||
dest = join(self.frameworks_dir, x)
|
dest = join(self.frameworks_dir, x)
|
||||||
self.set_id(dest, self.FID + '/' + x)
|
self.set_id(dest, f'{self.FID}/{x}')
|
||||||
self.fix_dependencies_in_lib(dest)
|
self.fix_dependencies_in_lib(dest)
|
||||||
|
|
||||||
@flush
|
@flush
|
||||||
@@ -310,7 +330,7 @@ class Freeze(object):
|
|||||||
@flush
|
@flush
|
||||||
def add_stdlib(self):
|
def add_stdlib(self):
|
||||||
print('\nAdding python stdlib')
|
print('\nAdding python stdlib')
|
||||||
src = PREFIX + '/python/Python.framework/Versions/Current/lib/python' + self.py_ver
|
src = f'{PREFIX}/python/Python.framework/Versions/Current/lib/python{self.py_ver}'
|
||||||
dest = self.python_stdlib
|
dest = self.python_stdlib
|
||||||
if not os.path.exists(dest):
|
if not os.path.exists(dest):
|
||||||
os.makedirs(dest)
|
os.makedirs(dest)
|
||||||
@@ -334,21 +354,22 @@ class Freeze(object):
|
|||||||
kitty_dir = join(self.resources_dir, 'kitty')
|
kitty_dir = join(self.resources_dir, 'kitty')
|
||||||
bases = ('kitty', 'kittens', 'kitty_tests')
|
bases = ('kitty', 'kittens', 'kitty_tests')
|
||||||
for x in bases:
|
for x in bases:
|
||||||
dest = os.path.join(self.python_stdlib, x)
|
dest = join(self.python_stdlib, x)
|
||||||
os.rename(os.path.join(kitty_dir, x), dest)
|
os.rename(join(kitty_dir, x), dest)
|
||||||
if x == 'kitty':
|
if x == 'kitty':
|
||||||
shutil.rmtree(os.path.join(dest, 'launcher'))
|
shutil.rmtree(join(dest, 'launcher'))
|
||||||
os.rename(os.path.join(kitty_dir, '__main__.py'), os.path.join(self.python_stdlib, 'kitty_main.py'))
|
os.rename(join(kitty_dir, '__main__.py'), join(self.python_stdlib, 'kitty_main.py'))
|
||||||
shutil.rmtree(os.path.join(kitty_dir, '__pycache__'))
|
shutil.rmtree(join(kitty_dir, '__pycache__'))
|
||||||
pdir = os.path.join(dirname(self.python_stdlib), 'kitty-extensions')
|
pdir = join(dirname(self.python_stdlib), 'kitty-extensions')
|
||||||
os.mkdir(pdir)
|
os.mkdir(pdir)
|
||||||
print('Extracting extension modules from', self.python_stdlib, 'to', pdir)
|
print('Extracting extension modules from', self.python_stdlib, 'to', pdir)
|
||||||
ext_map = extract_extension_modules(self.python_stdlib, pdir)
|
ext_map = extract_extension_modules(self.python_stdlib, pdir)
|
||||||
shutil.copy(os.path.join(os.path.dirname(self_dir), 'site.py'), os.path.join(self.python_stdlib, 'site.py'))
|
shutil.copy(join(os.path.dirname(self_dir), 'site.py'), join(self.python_stdlib, 'site.py'))
|
||||||
for x in bases:
|
for x in bases:
|
||||||
iv['sanitize_source_folder'](os.path.join(self.python_stdlib, x))
|
iv['sanitize_source_folder'](join(self.python_stdlib, x))
|
||||||
self.compile_py_modules()
|
self.compile_py_modules()
|
||||||
freeze_python(self.python_stdlib, pdir, self.obj_dir, ext_map, develop_mode_env_var='KITTY_DEVELOP_FROM', remove_pyc_files=True)
|
freeze_python(self.python_stdlib, pdir, self.obj_dir, ext_map, develop_mode_env_var='KITTY_DEVELOP_FROM', remove_pyc_files=True)
|
||||||
|
shutil.rmtree(self.python_stdlib)
|
||||||
iv['build_frozen_launcher']([path_to_freeze_dir(), self.obj_dir])
|
iv['build_frozen_launcher']([path_to_freeze_dir(), self.obj_dir])
|
||||||
os.rename(join(dirname(self.contents_dir), 'bin', 'kitty'), join(self.contents_dir, 'MacOS', 'kitty'))
|
os.rename(join(dirname(self.contents_dir), 'bin', 'kitty'), join(self.contents_dir, 'MacOS', 'kitty'))
|
||||||
shutil.rmtree(join(dirname(self.contents_dir), 'bin'))
|
shutil.rmtree(join(dirname(self.contents_dir), 'bin'))
|
||||||
@@ -423,23 +444,23 @@ class Freeze(object):
|
|||||||
''' Copy a directory d into a dmg named volname '''
|
''' Copy a directory d into a dmg named volname '''
|
||||||
print('\nMaking dmg...')
|
print('\nMaking dmg...')
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
destdir = os.path.join(SW, 'dist')
|
destdir = join(SW, 'dist')
|
||||||
try:
|
try:
|
||||||
shutil.rmtree(destdir)
|
shutil.rmtree(destdir)
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
pass
|
pass
|
||||||
os.mkdir(destdir)
|
os.mkdir(destdir)
|
||||||
dmg = os.path.join(destdir, volname + '.dmg')
|
dmg = join(destdir, f'{volname}.dmg')
|
||||||
if os.path.exists(dmg):
|
if os.path.exists(dmg):
|
||||||
os.unlink(dmg)
|
os.unlink(dmg)
|
||||||
tdir = tempfile.mkdtemp()
|
tdir = tempfile.mkdtemp()
|
||||||
appdir = os.path.join(tdir, os.path.basename(d))
|
appdir = join(tdir, os.path.basename(d))
|
||||||
shutil.copytree(d, appdir, symlinks=True)
|
shutil.copytree(d, appdir, symlinks=True)
|
||||||
if self.sign_installers:
|
if self.sign_installers:
|
||||||
with timeit() as times:
|
with timeit() as times:
|
||||||
sign_app(appdir, self.notarize)
|
sign_app(appdir, self.notarize)
|
||||||
print('Signing completed in %d minutes %d seconds' % tuple(times))
|
print('Signing completed in {} minutes {} seconds'.format(*times))
|
||||||
os.symlink('/Applications', os.path.join(tdir, 'Applications'))
|
os.symlink('/Applications', join(tdir, 'Applications'))
|
||||||
size_in_mb = int(
|
size_in_mb = int(
|
||||||
subprocess.check_output(['du', '-s', '-k', tdir]).decode('utf-8')
|
subprocess.check_output(['du', '-s', '-k', tdir]).decode('utf-8')
|
||||||
.split()[0]) / 1024.
|
.split()[0]) / 1024.
|
||||||
@@ -455,10 +476,10 @@ class Freeze(object):
|
|||||||
print('\nCreating dmg...')
|
print('\nCreating dmg...')
|
||||||
with timeit() as times:
|
with timeit() as times:
|
||||||
subprocess.check_call(cmd + [dmg])
|
subprocess.check_call(cmd + [dmg])
|
||||||
print('dmg created in %d minutes and %d seconds' % tuple(times))
|
print('dmg created in {} minutes and {} seconds'.format(*times))
|
||||||
shutil.rmtree(tdir)
|
shutil.rmtree(tdir)
|
||||||
size = os.stat(dmg).st_size / (1024 * 1024.)
|
size = os.stat(dmg).st_size / (1024 * 1024.)
|
||||||
print('\nInstaller size: %.2fMB\n' % size)
|
print(f'\nInstaller size: {size:.2f}MB\n')
|
||||||
return dmg
|
return dmg
|
||||||
|
|
||||||
|
|
||||||
@@ -466,7 +487,7 @@ def main():
|
|||||||
args = globals()['args']
|
args = globals()['args']
|
||||||
ext_dir = globals()['ext_dir']
|
ext_dir = globals()['ext_dir']
|
||||||
Freeze(
|
Freeze(
|
||||||
os.path.join(ext_dir, kitty_constants['appname'] + '.app'),
|
join(ext_dir, f'{kitty_constants["appname"]}.app'),
|
||||||
dont_strip=args.dont_strip,
|
dont_strip=args.dont_strip,
|
||||||
sign_installers=args.sign_installers,
|
sign_installers=args.sign_installers,
|
||||||
notarize=args.notarize,
|
notarize=args.notarize,
|
||||||
|
|||||||
@@ -28,6 +28,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "openssl",
|
||||||
|
"unix": {
|
||||||
|
"filename": "openssl-1.1.1i.tar.gz",
|
||||||
|
"hash": "sha256:e8be6a35fe41d10603c3cc635e93289ed00bf34b79671a3a4de64fcee00d5242",
|
||||||
|
"urls": ["https://www.openssl.org/source/{filename}"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"name": "cmake",
|
"name": "cmake",
|
||||||
"os": "macos",
|
"os": "macos",
|
||||||
@@ -48,25 +57,22 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
"name": "libxml2",
|
"name": "libxml2",
|
||||||
"os": "linux",
|
|
||||||
"unix": {
|
"unix": {
|
||||||
"filename": "libxml2-2.9.10.tar.gz",
|
"filename": "libxml2-2.9.12.tar.gz",
|
||||||
"hash": "sha256:aafee193ffb8fe0c82d4afef6ef91972cbaf5feea100edc2f262750611b4be1f",
|
"hash": "sha256:c8d6681e38c56f172892c85ddc0852e1fd4b53b4209e7f4ebf17f7e2eae71d92",
|
||||||
"urls": ["ftp://xmlsoft.org/libxml2/{filename}"]
|
"urls": ["ftp://xmlsoft.org/libxml2/{filename}"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
"name": "xkbcommon",
|
"name": "xkbcommon",
|
||||||
"os": "linux",
|
"os": "linux",
|
||||||
"unix": {
|
"unix": {
|
||||||
"filename": "libxkbcommon-1.0.3.tar.xz",
|
"filename": "libxkbcommon-1.0.3.tar.xz",
|
||||||
"hash": "sha256:a2202f851e072b84e64a395212cbd976ee18a8ee602008b0bad02a13247dbc52",
|
"hash": "sha256:a2202f851e072b84e64a395212cbd976ee18a8ee602008b0bad02a13247dbc52",
|
||||||
"urls": ["http://xkbcommon.org/download/{filename}"]
|
"urls": ["https://xkbcommon.org/download/{filename}"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -90,15 +96,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
|
||||||
"name": "openssl",
|
|
||||||
"unix": {
|
|
||||||
"filename": "openssl-1.1.1i.tar.gz",
|
|
||||||
"hash": "sha256:e8be6a35fe41d10603c3cc635e93289ed00bf34b79671a3a4de64fcee00d5242",
|
|
||||||
"urls": ["https://www.openssl.org/source/{filename}"]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
{
|
||||||
"name": "ncurses",
|
"name": "ncurses",
|
||||||
"os": "linux",
|
"os": "linux",
|
||||||
@@ -115,7 +112,7 @@
|
|||||||
"unix": {
|
"unix": {
|
||||||
"filename": "readline-8.1.tar.gz",
|
"filename": "readline-8.1.tar.gz",
|
||||||
"hash": "sha256:f8ceb4ee131e3232226a17f51b164afc46cd0b9e6cef344be87c65962cb82b02",
|
"hash": "sha256:f8ceb4ee131e3232226a17f51b164afc46cd0b9e6cef344be87c65962cb82b02",
|
||||||
"urls": ["http://ftp.gnu.org/gnu/readline/{filename}"]
|
"urls": ["https://ftp.gnu.org/gnu/readline/{filename}"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -128,6 +125,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "librsync",
|
||||||
|
"unix": {
|
||||||
|
"filename": "librsync-2.3.2.tar.gz",
|
||||||
|
"hash": "sha256:ef8ce23df38d5076d25510baa2cabedffbe0af460d887d86c2413a1c2b0c676f",
|
||||||
|
"urls": ["https://github.com/librsync/librsync/releases/download/v2.3.2/{filename}"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
"name": "xcrypt",
|
"name": "xcrypt",
|
||||||
"os": "linux",
|
"os": "linux",
|
||||||
@@ -159,8 +166,8 @@
|
|||||||
{
|
{
|
||||||
"name": "pygments",
|
"name": "pygments",
|
||||||
"unix": {
|
"unix": {
|
||||||
"filename": "Pygments-2.7.4.tar.gz",
|
"filename": "Pygments-2.11.2.tar.gz",
|
||||||
"hash": "sha256:df49d09b498e83c1a73128295860250b0b7edd4c723a32e9bc0d295c7c2ec337",
|
"hash": "sha256:4e426f72023d88d03b2fa258de560726ce890ff3b630f88c21cbb8b2503b8c6a",
|
||||||
"urls": ["pypi"]
|
"urls": ["pypi"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -170,7 +177,7 @@
|
|||||||
"unix": {
|
"unix": {
|
||||||
"filename": "libpng-1.6.37.tar.xz",
|
"filename": "libpng-1.6.37.tar.xz",
|
||||||
"hash": "sha256:505e70834d35383537b6491e7ae8641f1a4bed1876dbfe361201fc80868d88ca",
|
"hash": "sha256:505e70834d35383537b6491e7ae8641f1a4bed1876dbfe361201fc80868d88ca",
|
||||||
"urls": ["http://downloads.sourceforge.net/sourceforge/libpng/{filename}"]
|
"urls": ["https://downloads.sourceforge.net/sourceforge/libpng/{filename}"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -189,7 +196,7 @@
|
|||||||
"unix": {
|
"unix": {
|
||||||
"filename": "graphite2-1.3.14.tgz",
|
"filename": "graphite2-1.3.14.tgz",
|
||||||
"hash": "sha256:f99d1c13aa5fa296898a181dff9b82fb25f6cc0933dbaa7a475d8109bd54209d",
|
"hash": "sha256:f99d1c13aa5fa296898a181dff9b82fb25f6cc0933dbaa7a475d8109bd54209d",
|
||||||
"urls": ["http://downloads.sourceforge.net/silgraphite/{filename}"]
|
"urls": ["https://downloads.sourceforge.net/silgraphite/{filename}"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -249,7 +256,7 @@
|
|||||||
"unix": {
|
"unix": {
|
||||||
"filename": "fontconfig-2.13.1.tar.bz2",
|
"filename": "fontconfig-2.13.1.tar.bz2",
|
||||||
"hash": "sha256:f655dd2a986d7aa97e052261b36aa67b0a64989496361eca8d604e6414006741",
|
"hash": "sha256:f655dd2a986d7aa97e052261b36aa67b0a64989496361eca8d604e6414006741",
|
||||||
"urls": ["http://www.fontconfig.org/release/{filename}"]
|
"urls": ["https://www.fontconfig.org/release/{filename}"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -266,8 +273,8 @@
|
|||||||
"name": "wayland",
|
"name": "wayland",
|
||||||
"os": "linux",
|
"os": "linux",
|
||||||
"unix": {
|
"unix": {
|
||||||
"filename": "wayland-1.19.0.tar.xz",
|
"filename": "wayland-1.20.0.tar.xz",
|
||||||
"hash": "sha256:baccd902300d354581cd5ad3cc49daa4921d55fb416a5883e218750fef166d15",
|
"hash": "sha256:b8a034154c7059772e0fdbd27dbfcda6c732df29cae56a82274f6ec5d7cd8725",
|
||||||
"urls": ["https://wayland.freedesktop.org/releases/{filename}"]
|
"urls": ["https://wayland.freedesktop.org/releases/{filename}"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -276,8 +283,8 @@
|
|||||||
"name": "wayland-protocols",
|
"name": "wayland-protocols",
|
||||||
"os": "linux",
|
"os": "linux",
|
||||||
"unix": {
|
"unix": {
|
||||||
"filename": "wayland-protocols-1.20.tar.xz",
|
"filename": "wayland-protocols-1.25.tar.xz",
|
||||||
"hash": "sha256:9782b7a1a863d82d7c92478497d13c758f52e7da4f197aa16443f73de77e4de7",
|
"hash": "sha256:f1ff0f7199d0a0da337217dd8c99979967808dc37731a1e759e822b75b571460",
|
||||||
"urls": ["https://wayland.freedesktop.org/releases/{filename}"]
|
"urls": ["https://wayland.freedesktop.org/releases/{filename}"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
# Minimal makefile for Sphinx documentation
|
# Minimal makefile for Sphinx documentation
|
||||||
#
|
#
|
||||||
|
|
||||||
|
ifdef FAIL_WARN
|
||||||
|
override FAIL_WARN=-W
|
||||||
|
endif
|
||||||
|
|
||||||
# You can set these variables from the command line.
|
# You can set these variables from the command line.
|
||||||
SPHINXOPTS = -n -q -j auto -T $(FAIL_WARN) $(OPTS)
|
SPHINXOPTS = -n -q -j auto -T $(FAIL_WARN) $(OPTS)
|
||||||
SPHINXBUILD = sphinx-build
|
SPHINXBUILD = sphinx-build
|
||||||
|
|||||||
17
docs/_static/custom.css
vendored
@@ -5,6 +5,10 @@
|
|||||||
* Distributed under terms of the MIT license.
|
* Distributed under terms of the MIT license.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
.italic {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
.sidebar-logo {
|
.sidebar-logo {
|
||||||
max-height: 128px;
|
max-height: 128px;
|
||||||
}
|
}
|
||||||
@@ -17,3 +21,16 @@
|
|||||||
.sidebar-tree a.current {
|
.sidebar-tree a.current {
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
details > summary {
|
||||||
|
color: var(--color-link);
|
||||||
|
cursor: pointer;
|
||||||
|
text-decoration-color: var(--color-link-underline);
|
||||||
|
text-decoration-line: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* pygments adds an underline to some white-space, this is particularly visible in
|
||||||
|
* dark mode. Remove it. */
|
||||||
|
.highlight .w {
|
||||||
|
text-decoration: none
|
||||||
|
}
|
||||||
|
|||||||
2
docs/_static/custom.js
vendored
@@ -22,7 +22,7 @@ function scroll_sidebar_node_into_view(a) {
|
|||||||
a = a.offsetParent;
|
a = a.offsetParent;
|
||||||
if (!a || a == ss) break;
|
if (!a || a == ss) break;
|
||||||
}
|
}
|
||||||
ss.scrollTop = pos;
|
ss.scrollTo({top: pos, behavior: 'instant'});
|
||||||
}
|
}
|
||||||
|
|
||||||
function mark_current_link(sidebar_tree, a, onload) {
|
function mark_current_link(sidebar_tree, a, onload) {
|
||||||
|
|||||||
BIN
docs/_static/poster.png
vendored
Normal file
|
After Width: | Height: | Size: 80 KiB |
18
docs/_templates/base.html
vendored
@@ -4,18 +4,14 @@
|
|||||||
{{ super() }}
|
{{ super() }}
|
||||||
|
|
||||||
{%- if analytics_id %}
|
{%- if analytics_id %}
|
||||||
<script type="text/javascript">
|
<!-- Global site tag (gtag.js) - Google Analytics -->
|
||||||
var _gaq = _gaq || [];
|
<script async src="https://www.googletagmanager.com/gtag/js?id={{ analytics_id }}"></script>
|
||||||
_gaq.push(['_setAccount', '{{ analytics_id }}']);
|
<script>
|
||||||
_gaq.push(['_setDomainName', 'none']);
|
window.dataLayer = window.dataLayer || [];
|
||||||
_gaq.push(['_setAllowLinker', true]);
|
function gtag(){dataLayer.push(arguments);}
|
||||||
_gaq.push(['_trackPageview']);
|
gtag('js', new Date());
|
||||||
|
|
||||||
(function() {
|
gtag('config', '{{ analytics_id }}');
|
||||||
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
|
||||||
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
|
||||||
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
|
||||||
})();
|
|
||||||
</script>
|
</script>
|
||||||
{% endif -%}
|
{% endif -%}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ Mappable actions
|
|||||||
.. highlight:: conf
|
.. highlight:: conf
|
||||||
|
|
||||||
The actions described below can be mapped to any key press or mouse action
|
The actions described below can be mapped to any key press or mouse action
|
||||||
using the ``map`` and ``mouse_map`` directives in :file:`kitty.conf`.
|
using the ``map`` and ``mouse_map`` directives in :file:`kitty.conf`. For
|
||||||
|
configuration examples, see the default shortcut links for each action.
|
||||||
|
|
||||||
.. include:: /generated/actions.rst
|
.. include:: /generated/actions.rst
|
||||||
|
|||||||
@@ -1,26 +1,31 @@
|
|||||||
Tabs and Windows
|
Tabs and Windows
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|kitty| is capable of running multiple programs organized into tabs and
|
|kitty| is capable of running multiple programs organized into tabs and windows.
|
||||||
windows. The top level of organization is the *Tab*. Each tab consists
|
The top level of organization is the :term:`OS window <os_window>`. Each OS
|
||||||
of one or more *windows*. The windows can be arranged in multiple
|
window consists of one or more :term:`tabs <tab>`. Each tab consists of one or more
|
||||||
different layouts, like windows are organized in a tiling window
|
:term:`kitty windows <window>`. The kitty windows can be arranged in multiple
|
||||||
manager. The keyboard controls (which are all customizable) for tabs and
|
different :term:`layouts <layout>`, like windows are organized in a tiling
|
||||||
windows are:
|
window manager. The keyboard controls (which are :ref:`all customizable
|
||||||
|
<conf-kitty-shortcuts>`) for tabs and windows are:
|
||||||
|
|
||||||
Scrolling
|
Scrolling
|
||||||
~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~
|
||||||
|
|
||||||
======================== =======================
|
========================= =======================
|
||||||
Action Shortcut
|
Action Shortcut
|
||||||
======================== =======================
|
========================= =======================
|
||||||
Scroll line up :sc:`scroll_line_up` (also :kbd:`⌥+⌘+⇞` and :kbd:`⌘+↑` on macOS)
|
Line up :sc:`scroll_line_up` (also :kbd:`⌥+⌘+⇞` and :kbd:`⌘+↑` on macOS)
|
||||||
Scroll line down :sc:`scroll_line_down` (also :kbd:`⌥+⌘+⇟` and :kbd:`⌘+↓` on macOS)
|
Line down :sc:`scroll_line_down` (also :kbd:`⌥+⌘+⇟` and :kbd:`⌘+↓` on macOS)
|
||||||
Scroll page up :sc:`scroll_page_up` (also :kbd:`⌘+⇞` on macOS)
|
Page up :sc:`scroll_page_up` (also :kbd:`⌘+⇞` on macOS)
|
||||||
Scroll page down :sc:`scroll_page_down` (also :kbd:`⌘+⇟` on macOS)
|
Page down :sc:`scroll_page_down` (also :kbd:`⌘+⇟` on macOS)
|
||||||
Scroll to top :sc:`scroll_home` (also :kbd:`⌘+↖` on macOS)
|
Top :sc:`scroll_home` (also :kbd:`⌘+↖` on macOS)
|
||||||
Scroll to bottom :sc:`scroll_end` (also :kbd:`⌘+↘` on macOS)
|
Bottom :sc:`scroll_end` (also :kbd:`⌘+↘` on macOS)
|
||||||
======================== =======================
|
Previous shell prompt :sc:`scroll_to_previous_prompt` (see :ref:`shell_integration`)
|
||||||
|
Next shell prompt :sc:`scroll_to_next_prompt` (see :ref:`shell_integration`)
|
||||||
|
Browse scrollback in less :sc:`show_scrollback`
|
||||||
|
Browse last cmd output :sc:`show_last_command_output` (see :ref:`shell_integration`)
|
||||||
|
========================= =======================
|
||||||
|
|
||||||
Tabs
|
Tabs
|
||||||
~~~~~~~~~~~
|
~~~~~~~~~~~
|
||||||
@@ -30,8 +35,8 @@ Action Shortcut
|
|||||||
======================== =======================
|
======================== =======================
|
||||||
New tab :sc:`new_tab` (also :kbd:`⌘+t` on macOS)
|
New tab :sc:`new_tab` (also :kbd:`⌘+t` on macOS)
|
||||||
Close tab :sc:`close_tab` (also :kbd:`⌘+w` on macOS)
|
Close tab :sc:`close_tab` (also :kbd:`⌘+w` on macOS)
|
||||||
Next tab :sc:`next_tab` (also :kbd:`^+⇥` and :kbd:`⇧+⌘+]` on macOS)
|
Next tab :sc:`next_tab` (also :kbd:`⌃+⇥` and :kbd:`⇧+⌘+]` on macOS)
|
||||||
Previous tab :sc:`previous_tab` (also :kbd:`⇧+^+⇥` and :kbd:`⇧+⌘+[` on macOS)
|
Previous tab :sc:`previous_tab` (also :kbd:`⇧+⌃+⇥` and :kbd:`⇧+⌘+[` on macOS)
|
||||||
Next layout :sc:`next_layout`
|
Next layout :sc:`next_layout`
|
||||||
Move tab forward :sc:`move_tab_forward`
|
Move tab forward :sc:`move_tab_forward`
|
||||||
Move tab backward :sc:`move_tab_backward`
|
Move tab backward :sc:`move_tab_backward`
|
||||||
@@ -53,13 +58,16 @@ Previous window :sc:`previous_window`
|
|||||||
Move window forward :sc:`move_window_forward`
|
Move window forward :sc:`move_window_forward`
|
||||||
Move window backward :sc:`move_window_backward`
|
Move window backward :sc:`move_window_backward`
|
||||||
Move window to top :sc:`move_window_to_top`
|
Move window to top :sc:`move_window_to_top`
|
||||||
|
Visually focus window :sc:`focus_visible_window`
|
||||||
|
Visually swap window :sc:`swap_with_window`
|
||||||
Focus specific window :sc:`first_window`, :sc:`second_window` ... :sc:`tenth_window`
|
Focus specific window :sc:`first_window`, :sc:`second_window` ... :sc:`tenth_window`
|
||||||
(also :kbd:`⌘+1`, :kbd:`⌘+2` ... :kbd:`⌘+9` on macOS)
|
(also :kbd:`⌘+1`, :kbd:`⌘+2` ... :kbd:`⌘+9` on macOS)
|
||||||
(clockwise from the top-left)
|
(clockwise from the top-left)
|
||||||
======================== =======================
|
======================== =======================
|
||||||
|
|
||||||
Additionally, you can define shortcuts in :file:`kitty.conf` to focus neighboring
|
Additionally, you can define shortcuts in :file:`kitty.conf` to focus
|
||||||
windows and move windows around (similar to window movement in vim)::
|
neighboring windows and move windows around (similar to window movement in
|
||||||
|
:program:`vim`)::
|
||||||
|
|
||||||
map ctrl+left neighboring_window left
|
map ctrl+left neighboring_window left
|
||||||
map shift+left move_window right
|
map shift+left move_window right
|
||||||
@@ -71,17 +79,20 @@ You can also define a shortcut to switch to the previously active window::
|
|||||||
|
|
||||||
map ctrl+p nth_window -1
|
map ctrl+p nth_window -1
|
||||||
|
|
||||||
``nth_window`` will focus the nth window for positive numbers and the
|
:ac:`nth_window` will focus the nth window for positive numbers (starting from
|
||||||
previously active windows for negative numbers.
|
zero) and the previously active windows for negative numbers.
|
||||||
|
|
||||||
|
To switch to the nth OS window, you can define :ac:`nth_os_window`. Only
|
||||||
|
positive numbers are accepted, starting from one.
|
||||||
|
|
||||||
.. _detach_window:
|
.. _detach_window:
|
||||||
|
|
||||||
You can define shortcuts to detach the current window and
|
You can define shortcuts to detach the current window and move it to another tab
|
||||||
move it to another tab or another OS window::
|
or another OS window::
|
||||||
|
|
||||||
# moves the window into a new OS window
|
# moves the window into a new OS window
|
||||||
map ctrl+f2 detach_window
|
map ctrl+f2 detach_window
|
||||||
# moves the window into a new Tab
|
# moves the window into a new tab
|
||||||
map ctrl+f3 detach_window new-tab
|
map ctrl+f3 detach_window new-tab
|
||||||
# moves the window into the previously active tab
|
# moves the window into the previously active tab
|
||||||
map ctrl+f3 detach_window tab-prev
|
map ctrl+f3 detach_window tab-prev
|
||||||
@@ -97,8 +108,8 @@ Similarly, you can detach the current tab, with::
|
|||||||
# asks which OS Window to move the tab into
|
# asks which OS Window to move the tab into
|
||||||
map ctrl+f4 detach_tab ask
|
map ctrl+f4 detach_tab ask
|
||||||
|
|
||||||
Finally, you can define a shortcut to close all windows in a tab other than
|
Finally, you can define a shortcut to close all windows in a tab other than the
|
||||||
the currently active window::
|
currently active window::
|
||||||
|
|
||||||
map f9 close_other_windows_in_tab
|
map f9 close_other_windows_in_tab
|
||||||
|
|
||||||
@@ -112,21 +123,22 @@ The full list of actions that can be mapped to key presses is available
|
|||||||
================================== =======================
|
================================== =======================
|
||||||
Action Shortcut
|
Action Shortcut
|
||||||
================================== =======================
|
================================== =======================
|
||||||
|
Show this help :sc:`show_kitty_doc`
|
||||||
Copy to clipboard :sc:`copy_to_clipboard` (also :kbd:`⌘+c` on macOS)
|
Copy to clipboard :sc:`copy_to_clipboard` (also :kbd:`⌘+c` on macOS)
|
||||||
Paste from clipboard :sc:`paste_from_clipboard` (also :kbd:`⌘+v` on macOS)
|
Paste from clipboard :sc:`paste_from_clipboard` (also :kbd:`⌘+v` on macOS)
|
||||||
Paste from selection :sc:`paste_from_selection`
|
Paste from selection :sc:`paste_from_selection`
|
||||||
|
Pass selection to program :sc:`pass_selection_to_program`
|
||||||
Increase font size :sc:`increase_font_size` (also :kbd:`⌘++` on macOS)
|
Increase font size :sc:`increase_font_size` (also :kbd:`⌘++` on macOS)
|
||||||
Decrease font size :sc:`decrease_font_size` (also :kbd:`⌘+-` on macOS)
|
Decrease font size :sc:`decrease_font_size` (also :kbd:`⌘+-` on macOS)
|
||||||
Restore font size :sc:`reset_font_size` (also :kbd:`⌘+0` on macOS)
|
Restore font size :sc:`reset_font_size` (also :kbd:`⌘+0` on macOS)
|
||||||
Toggle fullscreen :sc:`toggle_fullscreen` (also :kbd:`^+⌘+f` on macOS)
|
Toggle fullscreen :sc:`toggle_fullscreen` (also :kbd:`⌃+⌘+f` on macOS)
|
||||||
Toggle maximized :sc:`toggle_maximized`
|
Toggle maximized :sc:`toggle_maximized`
|
||||||
Input unicode character :sc:`input_unicode_character` (also :kbd:`^+⌘+space` on macOS)
|
Input Unicode character :sc:`input_unicode_character` (also :kbd:`⌃+⌘+space` on macOS)
|
||||||
Click URL using the keyboard :sc:`open_url`
|
Open URL in web browser :sc:`open_url`
|
||||||
Reset the terminal :sc:`reset_terminal`
|
Reset the terminal :sc:`reset_terminal` (also :kbd:`⌥+⌘+r` on macOS)
|
||||||
Reload :file:`kitty.conf` :sc:`reload_config_file` (also :kbd:`^+⌘+f5` on macOS)
|
Edit :file:`kitty.conf` :sc:`edit_config_file` (also :kbd:`⌘+,` on macOS)
|
||||||
Debug :file:`kitty.conf` :sc:`debug_config` (also :kbd:`⌘+option+f6` on macOS)
|
Reload :file:`kitty.conf` :sc:`reload_config_file` (also :kbd:`⌃+⌘+,` on macOS)
|
||||||
Pass current selection to program :sc:`pass_selection_to_program`
|
Debug :file:`kitty.conf` :sc:`debug_config` (also :kbd:`⌥+⌘+,` on macOS)
|
||||||
Edit |kitty| config file :sc:`edit_config_file`
|
|
||||||
Open a |kitty| shell :sc:`kitty_shell`
|
Open a |kitty| shell :sc:`kitty_shell`
|
||||||
Increase background opacity :sc:`increase_background_opacity`
|
Increase background opacity :sc:`increase_background_opacity`
|
||||||
Decrease background opacity :sc:`decrease_background_opacity`
|
Decrease background opacity :sc:`decrease_background_opacity`
|
||||||
|
|||||||
@@ -4,17 +4,14 @@ Install kitty
|
|||||||
Binary install
|
Binary install
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
.. |ins| replace:: curl -L :literal:`https://sw.kovidgoyal.net/kitty/installer.sh` | sh /dev/stdin
|
|
||||||
|
|
||||||
.. highlight:: sh
|
.. highlight:: sh
|
||||||
|
|
||||||
You can install pre-built binaries of |kitty| if you are on macOS or Linux using
|
You can install pre-built binaries of |kitty| if you are on macOS or Linux using
|
||||||
the following simple command:
|
the following simple command:
|
||||||
|
|
||||||
.. parsed-literal::
|
.. code-block:: sh
|
||||||
:class: pre
|
|
||||||
|
|
||||||
|ins|
|
_kitty_install_cmd
|
||||||
|
|
||||||
|
|
||||||
The binaries will be installed in the standard location for your OS,
|
The binaries will be installed in the standard location for your OS,
|
||||||
@@ -22,17 +19,23 @@ The binaries will be installed in the standard location for your OS,
|
|||||||
Linux. The installer only touches files in that directory. To update kitty,
|
Linux. The installer only touches files in that directory. To update kitty,
|
||||||
simply re-run the command.
|
simply re-run the command.
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
**Do not** copy the kitty binary out of the installation folder. If you want
|
||||||
|
to add it to your :envvar:`PATH`, create a symlink in :file:`~/.local/bin` or
|
||||||
|
:file:`/usr/bin` or wherever.
|
||||||
|
|
||||||
|
|
||||||
Manually installing
|
Manually installing
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
If something goes wrong or you simply do not want to run the installer, you can
|
If something goes wrong or you simply do not want to run the installer, you can
|
||||||
manually download and install |kitty| from the `GitHub releases page
|
manually download and install |kitty| from the `GitHub releases page
|
||||||
<https://github.com/kovidgoyal/kitty/releases>`_. If you are on macOS, download
|
<https://github.com/kovidgoyal/kitty/releases>`__. If you are on macOS, download
|
||||||
the :file:`.dmg` and install as normal. If you are on Linux, download the tarball
|
the :file:`.dmg` and install as normal. If you are on Linux, download the
|
||||||
and extract it into a directory. The |kitty| executable will be in the
|
tarball and extract it into a directory. The |kitty| executable will be in the
|
||||||
:file:`bin` sub-directory.
|
:file:`bin` sub-directory.
|
||||||
|
|
||||||
|
|
||||||
Desktop integration on Linux
|
Desktop integration on Linux
|
||||||
--------------------------------
|
--------------------------------
|
||||||
|
|
||||||
@@ -44,17 +47,30 @@ particular desktop, but it should work for most major desktop environments.
|
|||||||
.. code-block:: sh
|
.. code-block:: sh
|
||||||
|
|
||||||
# Create a symbolic link to add kitty to PATH (assuming ~/.local/bin is in
|
# Create a symbolic link to add kitty to PATH (assuming ~/.local/bin is in
|
||||||
# your PATH)
|
# your system-wide PATH)
|
||||||
ln -s ~/.local/kitty.app/bin/kitty ~/.local/bin/
|
ln -s ~/.local/kitty.app/bin/kitty ~/.local/bin/
|
||||||
# Place the kitty.desktop file somewhere it can be found by the OS
|
# Place the kitty.desktop file somewhere it can be found by the OS
|
||||||
cp ~/.local/kitty.app/share/applications/kitty.desktop ~/.local/share/applications/
|
cp ~/.local/kitty.app/share/applications/kitty.desktop ~/.local/share/applications/
|
||||||
# Update the path to the kitty icon in the kitty.desktop file
|
# If you want to open text files and images in kitty via your file manager also add the kitty-open.desktop file
|
||||||
sed -i "s|Icon=kitty|Icon=/home/$USER/.local/kitty.app/share/icons/hicolor/256x256/apps/kitty.png|g" ~/.local/share/applications/kitty.desktop
|
cp ~/.local/kitty.app/share/applications/kitty-open.desktop ~/.local/share/applications/
|
||||||
|
# Update the paths to the kitty and its icon in the kitty.desktop file(s)
|
||||||
|
sed -i "s|Icon=kitty|Icon=/home/$USER/.local/kitty.app/share/icons/hicolor/256x256/apps/kitty.png|g" ~/.local/share/applications/kitty*.desktop
|
||||||
|
sed -i "s|Exec=kitty|Exec=/home/$USER/.local/kitty.app/bin/kitty|g" ~/.local/share/applications/kitty*.desktop
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
If you use the venerable `stow <https://www.gnu.org/software/stow/>`_
|
In :file:`kitty-open.desktop`, kitty is registered to handle some supported
|
||||||
|
MIME types. This will cause kitty to take precedence on some systems where
|
||||||
|
the default apps are not explicitly set. For example, you expect to use
|
||||||
|
other GUI file managers to open dir paths when using commands such as
|
||||||
|
:program:`xdg-open`, you should configure the default opener for the MIME
|
||||||
|
type ``inode/directory``::
|
||||||
|
|
||||||
|
xdg-mime default org.kde.dolphin.desktop inode/directory
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
If you use the venerable `stow <https://www.gnu.org/software/stow/>`__
|
||||||
command to manage your manual installations, the following takes care of the
|
command to manage your manual installations, the following takes care of the
|
||||||
above for you (use with :file:`dest=~/.local/stow`)::
|
above for you (use with :code:`dest=~/.local/stow`)::
|
||||||
|
|
||||||
cd ~/.local/stow
|
cd ~/.local/stow
|
||||||
stow -v kitty.app
|
stow -v kitty.app
|
||||||
@@ -63,31 +79,46 @@ particular desktop, but it should work for most major desktop environments.
|
|||||||
Customizing the installation
|
Customizing the installation
|
||||||
--------------------------------
|
--------------------------------
|
||||||
|
|
||||||
|
.. _nightly:
|
||||||
|
|
||||||
|
* You can install the latest nightly kitty build with ``installer``:
|
||||||
|
|
||||||
|
.. code-block:: sh
|
||||||
|
|
||||||
|
_kitty_install_cmd \\
|
||||||
|
installer=nightly
|
||||||
|
|
||||||
|
If you want to install it in parallel to the released kitty specify a
|
||||||
|
different install locations with ``dest``:
|
||||||
|
|
||||||
|
.. code-block:: sh
|
||||||
|
|
||||||
|
_kitty_install_cmd \\
|
||||||
|
installer=nightly dest=/some/other/location
|
||||||
|
|
||||||
* You can specify a different install location, with ``dest``:
|
* You can specify a different install location, with ``dest``:
|
||||||
|
|
||||||
.. parsed-literal::
|
.. code-block:: sh
|
||||||
:class: pre
|
|
||||||
|
|
||||||
|ins| \\
|
_kitty_install_cmd \\
|
||||||
dest=/some/other/location
|
dest=/some/other/location
|
||||||
|
|
||||||
* You can tell the installer not to launch |kitty| after installing it with
|
* You can tell the installer not to launch |kitty| after installing it with
|
||||||
``launch=n``:
|
``launch=n``:
|
||||||
|
|
||||||
.. parsed-literal::
|
.. code-block:: sh
|
||||||
:class: pre
|
|
||||||
|
|
||||||
|ins| \\
|
_kitty_install_cmd \\
|
||||||
launch=n
|
launch=n
|
||||||
|
|
||||||
* You can use a previously downloaded dmg/tarball, with ``installer``:
|
* You can use a previously downloaded dmg/tarball, with ``installer``:
|
||||||
|
|
||||||
.. parsed-literal::
|
.. code-block:: sh
|
||||||
:class: pre
|
|
||||||
|
|
||||||
|ins| \\
|
_kitty_install_cmd \\
|
||||||
installer=/path/to/dmg or tarball
|
installer=/path/to/dmg or tarball
|
||||||
|
|
||||||
|
|
||||||
Uninstalling
|
Uninstalling
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
|
|||||||
162
docs/build.rst
@@ -5,19 +5,23 @@ Build from source
|
|||||||
:alt: Build status
|
:alt: Build status
|
||||||
:target: https://github.com/kovidgoyal/kitty/actions?query=workflow%3ACI
|
:target: https://github.com/kovidgoyal/kitty/actions?query=workflow%3ACI
|
||||||
|
|
||||||
|
.. highlight:: sh
|
||||||
|
|
||||||
|kitty| is designed to run from source, for easy hack-ability. Make sure
|
|kitty| is designed to run from source, for easy hack-ability. Make sure the
|
||||||
the following dependencies are installed first.
|
following dependencies are installed first.
|
||||||
|
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
If you are making small changes only to the python parts of kitty, there is no need to
|
If you just want to test the latest changes to kitty, you don't need to build
|
||||||
build kitty at all, instead, assuming you have installed the official kitty
|
from source. Instead install the :ref:`latest nightly build <nightly>`.
|
||||||
binaries, you can simply set the KITTY_DEVELOP_FROM enviroment variable to
|
|
||||||
point to the directory into which you have checked out the kitty source
|
.. note::
|
||||||
code. kitty will then load its python code from there. You should use a
|
If you are making small changes only to the Python parts of kitty, there is
|
||||||
version of the source that matches the binary version as closely as
|
no need to build kitty at all, instead, assuming you have installed the
|
||||||
possible, since the two are tightly coupled.
|
official kitty binaries, you can simply set the :envvar:`KITTY_DEVELOP_FROM`
|
||||||
|
enviroment variable to point to the directory into which you have checked out
|
||||||
|
the kitty source code. kitty will then load its Python code from there. You
|
||||||
|
should use a version of the source that matches the binary version as closely
|
||||||
|
as possible, since the two are tightly coupled.
|
||||||
|
|
||||||
|
|
||||||
Dependencies
|
Dependencies
|
||||||
@@ -25,11 +29,13 @@ Dependencies
|
|||||||
|
|
||||||
Run-time dependencies:
|
Run-time dependencies:
|
||||||
|
|
||||||
* ``python`` >= 3.6
|
* ``python`` >= 3.8
|
||||||
* ``harfbuzz`` >= 2.2.0
|
* ``harfbuzz`` >= 2.2.0
|
||||||
* ``zlib``
|
* ``zlib``
|
||||||
* ``libpng``
|
* ``libpng``
|
||||||
* ``liblcms2``
|
* ``liblcms2``
|
||||||
|
* ``librsync``
|
||||||
|
* ``openssl``
|
||||||
* ``freetype`` (not needed on macOS)
|
* ``freetype`` (not needed on macOS)
|
||||||
* ``fontconfig`` (not needed on macOS)
|
* ``fontconfig`` (not needed on macOS)
|
||||||
* ``libcanberra`` (not needed on macOS)
|
* ``libcanberra`` (not needed on macOS)
|
||||||
@@ -41,10 +47,22 @@ Build-time dependencies:
|
|||||||
|
|
||||||
* ``gcc`` or ``clang``
|
* ``gcc`` or ``clang``
|
||||||
* ``pkg-config``
|
* ``pkg-config``
|
||||||
* For building on Linux in addition to the above dependencies you might also need to install the ``-dev`` packages for:
|
* For building on Linux in addition to the above dependencies you might also
|
||||||
``libdbus-1-dev``, ``libxcursor-dev``, ``libxrandr-dev``, ``libxi-dev``, ``libxinerama-dev``,
|
need to install the following packages, if they are not already installed by
|
||||||
``libgl1-mesa-dev``, ``libxkbcommon-x11-dev``, ``libfontconfig-dev``, ``libx11-xcb-dev``,
|
your distro:
|
||||||
``liblcms2-dev``, and ``libpython3-dev``, if they are not already installed by your distro.
|
|
||||||
|
- ``libdbus-1-dev``
|
||||||
|
- ``libxcursor-dev``
|
||||||
|
- ``libxrandr-dev``
|
||||||
|
- ``libxi-dev``
|
||||||
|
- ``libxinerama-dev``
|
||||||
|
- ``libgl1-mesa-dev``
|
||||||
|
- ``libxkbcommon-x11-dev``
|
||||||
|
- ``libfontconfig-dev``
|
||||||
|
- ``libx11-xcb-dev``
|
||||||
|
- ``liblcms2-dev``
|
||||||
|
- ``libpython3-dev``
|
||||||
|
- ``librsync-dev``
|
||||||
|
|
||||||
|
|
||||||
Install and run from source
|
Install and run from source
|
||||||
@@ -62,9 +80,12 @@ You can run |kitty|, as::
|
|||||||
|
|
||||||
./kitty/launcher/kitty
|
./kitty/launcher/kitty
|
||||||
|
|
||||||
If that works, you can create a symlink to the launcher in :file:`~/bin` or
|
If that works, you can create a symlink to the launcher in :file:`~/bin` or some
|
||||||
some other directory on your PATH so that you can run |kitty| using
|
other directory on your PATH so that you can run |kitty| using just ``kitty``.
|
||||||
just ``kitty``.
|
|
||||||
|
To have the kitty documentation available locally, run::
|
||||||
|
|
||||||
|
python3 -m pip install -r docs/requirements.txt && make docs
|
||||||
|
|
||||||
|
|
||||||
Building kitty.app on macOS from source
|
Building kitty.app on macOS from source
|
||||||
@@ -72,78 +93,109 @@ Building kitty.app on macOS from source
|
|||||||
|
|
||||||
Run::
|
Run::
|
||||||
|
|
||||||
|
python3 -m pip install -r docs/requirements.txt && make docs
|
||||||
make app
|
make app
|
||||||
|
|
||||||
|
Building the docs needs to be done only once.
|
||||||
|
|
||||||
This :file:`kitty.app` unlike the released one does not include its own copy of
|
This :file:`kitty.app` unlike the released one does not include its own copy of
|
||||||
python and the other dependencies. So if you ever un-install/upgrade those dependencies
|
Python and the other dependencies. So if you ever un-install/upgrade those
|
||||||
you might have to rebuild the app.
|
dependencies you might have to rebuild the app.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
The released :file:`kitty.dmg` includes all dependencies, unlike the
|
The released :file:`kitty.dmg` includes all dependencies, unlike the
|
||||||
:file:`kitty.app` built above and is built automatically by using the
|
:file:`kitty.app` built above and is built automatically by using the
|
||||||
`bypy framework <https://github.com/kovidgoyal/bypy>`_ however, that is
|
`bypy framework <https://github.com/kovidgoyal/bypy>`__ however, that is
|
||||||
designed to run on Linux and is not for the faint of heart.
|
designed to run on Linux and is not for the faint of heart.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
Apple disallows certain functionality, such as notifications for unsigned
|
||||||
|
applications. If you need this functionality, you can try signing the built
|
||||||
|
:file:`kitty.app` with a self signed certificate, see for example, `here
|
||||||
|
<https://stackoverflow.com/questions/27474751/how-can-i-codesign-an-app-without-being-in-the-mac-developer-program/27474942>`__.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
Apple disallows certain functionality, such as notifications for unsigned applications.
|
If you are facing issues with ``linker`` while building, try with a ``brew``
|
||||||
If you need this functionality, you can try signing the built kitty.app with
|
installed Python instead, see :iss:`289` for more discussion.
|
||||||
a self signed certificate, see for example, `here
|
|
||||||
<https://stackoverflow.com/questions/27474751/how-can-i-codesign-an-app-without-being-in-the-mac-developer-program/27474942>`_.
|
|
||||||
|
|
||||||
Build and run from source with Nix
|
Build and run from source with Nix
|
||||||
-------------------------------------------
|
-------------------------------------------
|
||||||
|
|
||||||
On NixOS or any other Linux or macOS system with the Nix package manager
|
On NixOS or any other Linux or macOS system with the Nix package manager
|
||||||
installed, execute `nix-shell
|
installed, execute `nix-shell
|
||||||
<https://nixos.org/guides/nix-pills/developing-with-nix-shell.html>`_ to create
|
<https://nixos.org/guides/nix-pills/developing-with-nix-shell.html>`__ to create
|
||||||
the correct environment to build kitty or use ``nix-shell --pure`` instead to
|
the correct environment to build kitty or use ``nix-shell --pure`` instead to
|
||||||
eliminate most of the influence of the outside system, e.g. globally installed
|
eliminate most of the influence of the outside system, e.g. globally installed
|
||||||
packages. ``nix-shell`` will automatically fetch all required dependencies and
|
packages. ``nix-shell`` will automatically fetch all required dependencies and
|
||||||
make them available in the newly spawned shell.
|
make them available in the newly spawned shell.
|
||||||
|
|
||||||
Then proceed with ``make`` or ``make app`` according to the platform specific instructions above.
|
Then proceed with ``make`` or ``make app`` according to the platform specific
|
||||||
|
instructions above.
|
||||||
|
|
||||||
|
|
||||||
Note for Linux/macOS packagers
|
Debug builds
|
||||||
|
--------------
|
||||||
|
|
||||||
|
A basic debug build can be done with::
|
||||||
|
|
||||||
|
make debug
|
||||||
|
|
||||||
|
This includes debug info in the binary for better traces. To build with address
|
||||||
|
sanitizer, use::
|
||||||
|
|
||||||
|
make asan
|
||||||
|
|
||||||
|
Which will result in a debug binary that uses the address sanitizer as well.
|
||||||
|
|
||||||
|
.. _packagers:
|
||||||
|
|
||||||
|
Notes for Linux/macOS packagers
|
||||||
----------------------------------
|
----------------------------------
|
||||||
|
|
||||||
The released |kitty| source code is available as a `tarball`_ from
|
The released |kitty| source code is available as a `tarball`_ from
|
||||||
`the GitHub releases page <https://github.com/kovidgoyal/kitty/releases>`_.
|
`the GitHub releases page <https://github.com/kovidgoyal/kitty/releases>`__.
|
||||||
|
|
||||||
While |kitty| does use python, it is not a traditional python package, so please
|
While |kitty| does use Python, it is not a traditional Python package, so please
|
||||||
do not install it in site-packages.
|
do not install it in site-packages.
|
||||||
Instead run::
|
Instead run::
|
||||||
|
|
||||||
python3 setup.py linux-package
|
python3 setup.py linux-package
|
||||||
|
|
||||||
This will install |kitty| into the directory :file:`linux-package`. You can run |kitty|
|
This will install |kitty| into the directory :file:`linux-package`. You can run
|
||||||
with :file:`linux-package/bin/kitty`. All the files needed to run kitty will be in
|
|kitty| with :file:`linux-package/bin/kitty`. All the files needed to run kitty
|
||||||
:file:`linux-package/lib/kitty`. The terminfo file will be installed into
|
will be in :file:`linux-package/lib/kitty`. The terminfo file will be installed
|
||||||
:file:`linux-package/share/terminfo`. Simply copy these files into :file:`/usr` to install
|
into :file:`linux-package/share/terminfo`. Simply copy these files into
|
||||||
|kitty|. In other words, :file:`linux-package` is the staging area into which |kitty| is
|
:file:`/usr` to install |kitty|. In other words, :file:`linux-package` is the
|
||||||
installed. You can choose a different staging area, by passing the ``--prefix``
|
staging area into which |kitty| is installed. You can choose a different staging
|
||||||
argument to :file:`setup.py`.
|
area, by passing the ``--prefix`` argument to :file:`setup.py`.
|
||||||
|
|
||||||
You should probably split |kitty| into two packages, :file:`kitty-terminfo` that
|
You should probably split |kitty| into three packages:
|
||||||
installs the terminfo file and :file:`kitty` that installs the main program.
|
|
||||||
This allows users to install the terminfo file on servers into which they ssh,
|
:code:`kitty-terminfo`
|
||||||
without needing to install all of |kitty|.
|
Installs the terminfo file
|
||||||
|
|
||||||
|
:code:`kitty-shell-integration`
|
||||||
|
Installs the shell integration scripts (the contents of the
|
||||||
|
shell-integration directory in the kitty source code), probably to
|
||||||
|
:file:`/usr/share/kitty/shell-integration`
|
||||||
|
|
||||||
|
:code:`kitty`
|
||||||
|
Installs the main program
|
||||||
|
|
||||||
|
This allows users to install the terminfo and shell integration files on
|
||||||
|
servers into which they ssh, without needing to install all of |kitty|. The
|
||||||
|
shell integration files **must** still be present in
|
||||||
|
:file:`lib/kitty/shell-integration` when installing the kitty main package as
|
||||||
|
the kitty program expects to find them there.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
You need a couple of extra dependencies to build linux-package.
|
You need a couple of extra dependencies to build linux-package. :file:`tic`
|
||||||
:file:`tic` to compile terminfo files, usually found in the
|
to compile terminfo files, usually found in the development package of
|
||||||
development package of :file:`ncurses`. Also, if you are building from
|
:file:`ncurses`. Also, if you are building from a git checkout instead of the
|
||||||
a git checkout instead of the released source code tarball, you will
|
released source code tarball, you will need to install the dependencies from
|
||||||
need to install the dependencies from ``docs/requirements.txt`` to
|
:file:`docs/requirements.txt` to build the kitty documentation. They can be
|
||||||
build the kitty documentation. They can be installed most easily with
|
installed most easily with ``python -m pip -r docs/requirements.txt``.
|
||||||
``python -m pip -r docs/requirements.txt``.
|
|
||||||
|
|
||||||
This applies to creating packages for |kitty| for macOS package managers such as
|
This applies to creating packages for |kitty| for macOS package managers such as
|
||||||
brew or MacPorts as well.
|
Homebrew or MacPorts as well.
|
||||||
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|kitty| has its own update check mechanism, if you would like to turn
|
|
||||||
it off for your package, use
|
|
||||||
``python3 setup.py linux-package --update-check-interval=0``
|
|
||||||
|
|||||||
@@ -2,25 +2,25 @@ Saving and restoring colors
|
|||||||
==============================
|
==============================
|
||||||
|
|
||||||
It is often useful for a full screen application with its own color themes to
|
It is often useful for a full screen application with its own color themes to
|
||||||
set the default foreground, background, selection and cursor colors and the
|
set the default foreground, background, selection and cursor colors and the ANSI
|
||||||
ANSI color table. This allows for various performance optimizations when
|
color table. This allows for various performance optimizations when drawing the
|
||||||
drawing the screen. The problem is that if the user previously used the escape
|
screen. The problem is that if the user previously used the escape codes to
|
||||||
codes to change these colors herself, then running the full screen application
|
change these colors themselves, then running the full screen application will
|
||||||
will lose her changes even after it exits. To avoid this, kitty introduces a
|
lose those changes even after it exits. To avoid this, kitty introduces a new
|
||||||
new pair of *OSC* escape codes to push and pop the current color values from a
|
pair of *OSC* escape codes to push and pop the current color values from a
|
||||||
stack::
|
stack::
|
||||||
|
|
||||||
<ESC>]30001<ESC>\ # push onto stack
|
<ESC>]30001<ESC>\ # push onto stack
|
||||||
<ESC>]30101<ESC>\ # pop from stack
|
<ESC>]30101<ESC>\ # pop from stack
|
||||||
|
|
||||||
These escape codes save/restore the colors, default
|
These escape codes save/restore the colors, default background, default
|
||||||
background, default foreground, selection background, selection foreground and
|
foreground, selection background, selection foreground and cursor color and the
|
||||||
cursor color and the 256 colors of the ANSI color table.
|
256 colors of the ANSI color table.
|
||||||
|
|
||||||
.. note:: In July 2020, after several years, XTerm copied this protocol
|
.. note:: In July 2020, after several years, xterm copied this protocol
|
||||||
extension, without acknowledgement, and using incompatible escape codes
|
extension, without acknowledgement, and using incompatible escape codes
|
||||||
(XTPUSHCOLORS, XTPOPCOLORS, XTREPORTCOLORS). And they decided to save not
|
(XTPUSHCOLORS, XTPOPCOLORS, XTREPORTCOLORS). And they decided to save not
|
||||||
just the dynamic colors but the entire ANSI color table. In the interests of
|
just the dynamic colors but the entire ANSI color table. In the interests of
|
||||||
promoting interoperability, kitty added support for XTerm's escape codes as
|
promoting interoperability, kitty added support for xterm's escape codes as
|
||||||
well, and changed this extension to also save/restore the entire ANSI color
|
well, and changed this extension to also save/restore the entire ANSI color
|
||||||
table.
|
table.
|
||||||
|
|||||||
152
docs/conf.py
@@ -13,7 +13,7 @@ import subprocess
|
|||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from typing import Any, Callable, Dict, Iterable, List, Match, Optional, Tuple
|
from typing import Any, Callable, Dict, Iterable, List, Tuple
|
||||||
|
|
||||||
from docutils import nodes
|
from docutils import nodes
|
||||||
from docutils.parsers.rst.roles import set_classes
|
from docutils.parsers.rst.roles import set_classes
|
||||||
@@ -21,14 +21,14 @@ from pygments.lexer import RegexLexer, bygroups # type: ignore
|
|||||||
from pygments.token import ( # type: ignore
|
from pygments.token import ( # type: ignore
|
||||||
Comment, Keyword, Literal, Name, Number, String, Whitespace
|
Comment, Keyword, Literal, Name, Number, String, Whitespace
|
||||||
)
|
)
|
||||||
from sphinx import addnodes, version_info # type: ignore
|
from sphinx import addnodes, version_info
|
||||||
from sphinx.util.logging import getLogger # type: ignore
|
from sphinx.util.logging import getLogger
|
||||||
|
|
||||||
kitty_src = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
kitty_src = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
if kitty_src not in sys.path:
|
if kitty_src not in sys.path:
|
||||||
sys.path.insert(0, kitty_src)
|
sys.path.insert(0, kitty_src)
|
||||||
|
|
||||||
from kitty.conf.types import Definition # noqa
|
from kitty.conf.types import Definition, expand_opt_references # noqa
|
||||||
from kitty.constants import str_version, website_url # noqa
|
from kitty.constants import str_version, website_url # noqa
|
||||||
|
|
||||||
# config {{{
|
# config {{{
|
||||||
@@ -59,6 +59,7 @@ extensions = [
|
|||||||
'sphinx.ext.ifconfig',
|
'sphinx.ext.ifconfig',
|
||||||
'sphinx.ext.viewcode',
|
'sphinx.ext.viewcode',
|
||||||
'sphinx.ext.githubpages',
|
'sphinx.ext.githubpages',
|
||||||
|
'sphinx.ext.extlinks',
|
||||||
'sphinx_copybutton',
|
'sphinx_copybutton',
|
||||||
'sphinx_inline_tabs',
|
'sphinx_inline_tabs',
|
||||||
"sphinxext.opengraph",
|
"sphinxext.opengraph",
|
||||||
@@ -84,7 +85,7 @@ master_doc = 'index'
|
|||||||
#
|
#
|
||||||
# This is also used if you do content translation via gettext catalogs.
|
# This is also used if you do content translation via gettext catalogs.
|
||||||
# Usually you set "language" from the command line for these cases.
|
# Usually you set "language" from the command line for these cases.
|
||||||
language: Optional[str] = None
|
language: str = 'en'
|
||||||
|
|
||||||
# List of patterns, relative to source directory, that match files and
|
# List of patterns, relative to source directory, that match files and
|
||||||
# directories to ignore when looking for source files.
|
# directories to ignore when looking for source files.
|
||||||
@@ -98,13 +99,14 @@ rst_prolog = '''
|
|||||||
.. |kitty| replace:: *kitty*
|
.. |kitty| replace:: *kitty*
|
||||||
.. |version| replace:: VERSION
|
.. |version| replace:: VERSION
|
||||||
.. _tarball: https://github.com/kovidgoyal/kitty/releases/download/vVERSION/kitty-VERSION.tar.xz
|
.. _tarball: https://github.com/kovidgoyal/kitty/releases/download/vVERSION/kitty-VERSION.tar.xz
|
||||||
.. role:: green
|
|
||||||
.. role:: italic
|
.. role:: italic
|
||||||
.. role:: bold
|
|
||||||
.. role:: cyan
|
|
||||||
.. role:: title
|
|
||||||
|
|
||||||
'''.replace('VERSION', str_version)
|
'''.replace('VERSION', str_version)
|
||||||
|
smartquotes_action = 'qe' # educate quotes and ellipses but not dashes
|
||||||
|
|
||||||
|
string_replacements = {
|
||||||
|
'_kitty_install_cmd': 'curl -L https://sw.kovidgoyal.net/kitty/installer.sh | sh /dev/stdin',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
# -- Options for HTML output -------------------------------------------------
|
# -- Options for HTML output -------------------------------------------------
|
||||||
@@ -118,10 +120,23 @@ html_title = 'kitty'
|
|||||||
# Theme options are theme-specific and customize the look and feel of a theme
|
# Theme options are theme-specific and customize the look and feel of a theme
|
||||||
# further. For a list of options available for each theme, see the
|
# further. For a list of options available for each theme, see the
|
||||||
# documentation.
|
# documentation.
|
||||||
#
|
github_icon_path = 'M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z' # noqa
|
||||||
|
|
||||||
html_theme_options: Dict[str, Any] = {
|
html_theme_options: Dict[str, Any] = {
|
||||||
'sidebar_hide_name': True,
|
'sidebar_hide_name': True,
|
||||||
'navigation_with_keys': True,
|
'navigation_with_keys': True,
|
||||||
|
'footer_icons': [
|
||||||
|
{
|
||||||
|
"name": "GitHub",
|
||||||
|
"url": "https://github.com/kovidgoyal/kitty",
|
||||||
|
"html": f"""
|
||||||
|
<svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 16 16">
|
||||||
|
<path fill-rule="evenodd" d="{github_icon_path}"></path>
|
||||||
|
</svg>
|
||||||
|
""",
|
||||||
|
"class": "",
|
||||||
|
},
|
||||||
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -170,25 +185,16 @@ texinfo_documents = [
|
|||||||
|
|
||||||
# GitHub linking inline roles {{{
|
# GitHub linking inline roles {{{
|
||||||
|
|
||||||
def num_role(which: str, name: str, rawtext: str, text: str, lineno: int, inliner: Any, options: Any = {}, content: Any = []) -> Tuple[List, List]:
|
extlinks = {
|
||||||
' Link to a github issue '
|
'iss': ('https://github.com/kovidgoyal/kitty/issues/%s', '#%s'),
|
||||||
try:
|
'pull': ('https://github.com/kovidgoyal/kitty/pull/%s', '#%s'),
|
||||||
issue_num = int(text)
|
'disc': ('https://github.com/kovidgoyal/kitty/discussions/%s', '#%s'),
|
||||||
if issue_num <= 0:
|
}
|
||||||
raise ValueError
|
|
||||||
except ValueError:
|
|
||||||
msg = inliner.reporter.error(
|
|
||||||
'GitHub issue number must be a number greater than or equal to 1; '
|
|
||||||
'"%s" is invalid.' % text, line=lineno)
|
|
||||||
prb = inliner.problematic(rawtext, rawtext, msg)
|
|
||||||
return [prb], [msg]
|
|
||||||
url = f'https://github.com/kovidgoyal/kitty/{which}/{issue_num}'
|
|
||||||
set_classes(options)
|
|
||||||
node = nodes.reference(rawtext, f'#{issue_num}', refuri=url, **options)
|
|
||||||
return [node], []
|
|
||||||
|
|
||||||
|
|
||||||
def commit_role(name: str, rawtext: str, text: str, lineno: int, inliner: Any, options: Any = {}, content: Any = []) -> Tuple[List, List]:
|
def commit_role(
|
||||||
|
name: str, rawtext: str, text: str, lineno: int, inliner: Any, options: Any = {}, content: Any = []
|
||||||
|
) -> Tuple[List[nodes.reference], List[nodes.problematic]]:
|
||||||
' Link to a github commit '
|
' Link to a github commit '
|
||||||
try:
|
try:
|
||||||
commit_id = subprocess.check_output(
|
commit_id = subprocess.check_output(
|
||||||
@@ -211,6 +217,13 @@ def commit_role(name: str, rawtext: str, text: str, lineno: int, inliner: Any, o
|
|||||||
def write_cli_docs(all_kitten_names: Iterable[str]) -> None:
|
def write_cli_docs(all_kitten_names: Iterable[str]) -> None:
|
||||||
from kitty.cli import option_spec_as_rst
|
from kitty.cli import option_spec_as_rst
|
||||||
from kitty.launch import options_spec as launch_options_spec
|
from kitty.launch import options_spec as launch_options_spec
|
||||||
|
from kittens.ssh.copy import option_text
|
||||||
|
from kittens.ssh.options.definition import copy_message
|
||||||
|
with open('generated/ssh-copy.rst', 'w') as f:
|
||||||
|
f.write(option_spec_as_rst(
|
||||||
|
appname='copy', ospec=option_text, heading_char='^',
|
||||||
|
usage='file-or-dir-to-copy ...', message=copy_message
|
||||||
|
))
|
||||||
with open('generated/launch.rst', 'w') as f:
|
with open('generated/launch.rst', 'w') as f:
|
||||||
f.write(option_spec_as_rst(
|
f.write(option_spec_as_rst(
|
||||||
appname='launch', ospec=launch_options_spec, heading_char='_',
|
appname='launch', ospec=launch_options_spec, heading_char='_',
|
||||||
@@ -228,15 +241,17 @@ if you specify a program-to-run you can use the special placeholder
|
|||||||
from kitty.remote_control import cli_msg, global_options_spec
|
from kitty.remote_control import cli_msg, global_options_spec
|
||||||
with open('generated/cli-kitty-at.rst', 'w') as f:
|
with open('generated/cli-kitty-at.rst', 'w') as f:
|
||||||
p = partial(print, file=f)
|
p = partial(print, file=f)
|
||||||
p('kitty @\n' + '-' * 80)
|
p('kitty @')
|
||||||
|
p('-' * 80)
|
||||||
p('.. program::', 'kitty @')
|
p('.. program::', 'kitty @')
|
||||||
p('\n\n' + as_rst(
|
p('\n\n' + as_rst(
|
||||||
global_options_spec, message=cli_msg, usage='command ...', appname='kitty @'))
|
global_options_spec, message=cli_msg, usage='command ...', appname='kitty @'))
|
||||||
from kitty.rc.base import cli_params_for
|
from kitty.rc.base import cli_params_for
|
||||||
for cmd_name in sorted(all_command_names()):
|
for cmd_name in sorted(all_command_names()):
|
||||||
func = command_for_name(cmd_name)
|
func = command_for_name(cmd_name)
|
||||||
p(f'.. _at_{func.name}:\n')
|
p(f'.. _at-{func.name}:\n')
|
||||||
p('kitty @', func.name + '\n' + '-' * 120)
|
p('kitty @', func.name)
|
||||||
|
p('-' * 120)
|
||||||
p('.. program::', 'kitty @', func.name)
|
p('.. program::', 'kitty @', func.name)
|
||||||
p('\n\n' + as_rst(*cli_params_for(func)))
|
p('\n\n' + as_rst(*cli_params_for(func)))
|
||||||
from kittens.runner import get_kitten_cli_docs
|
from kittens.runner import get_kitten_cli_docs
|
||||||
@@ -245,12 +260,12 @@ if you specify a program-to-run you can use the special placeholder
|
|||||||
if data:
|
if data:
|
||||||
with open(f'generated/cli-kitten-{kitten}.rst', 'w') as f:
|
with open(f'generated/cli-kitten-{kitten}.rst', 'w') as f:
|
||||||
p = partial(print, file=f)
|
p = partial(print, file=f)
|
||||||
p('.. program::', f'kitty +kitten {kitten}')
|
p('.. program::', 'kitty +kitten', kitten)
|
||||||
p(f'\nSource code for {kitten}')
|
p('\nSource code for', kitten)
|
||||||
p('-' * 72)
|
p('-' * 72)
|
||||||
p(f'\nThe source code for this kitten is `available on GitHub <https://github.com/kovidgoyal/kitty/tree/master/kittens/{kitten}>`_.')
|
p(f'\nThe source code for this kitten is `available on GitHub <https://github.com/kovidgoyal/kitty/tree/master/kittens/{kitten}>`_.')
|
||||||
p('\nCommand Line Interface')
|
p('\nCommand Line Interface')
|
||||||
p('-' * 72, file=f)
|
p('-' * 72)
|
||||||
p('\n\n' + option_spec_as_rst(
|
p('\n\n' + option_spec_as_rst(
|
||||||
data['options'], message=data['help_text'], usage=data['usage'], appname=f'kitty +kitten {kitten}',
|
data['options'], message=data['help_text'], usage=data['usage'], appname=f'kitty +kitten {kitten}',
|
||||||
heading_char='^'))
|
heading_char='^'))
|
||||||
@@ -262,9 +277,9 @@ def write_remote_control_protocol_docs() -> None: # {{{
|
|||||||
from kitty.rc.base import (
|
from kitty.rc.base import (
|
||||||
RemoteCommand, all_command_names, command_for_name
|
RemoteCommand, all_command_names, command_for_name
|
||||||
)
|
)
|
||||||
field_pat = re.compile(r'\s*([a-zA-Z0-9_+]+)\s*:\s*(.+)')
|
field_pat = re.compile(r'\s*([a-zA-Z0-9_+/]+)\s*:\s*(.+)')
|
||||||
|
|
||||||
def format_cmd(p: Callable, name: str, cmd: RemoteCommand) -> None:
|
def format_cmd(p: Callable[..., None], name: str, cmd: RemoteCommand) -> None:
|
||||||
p(name)
|
p(name)
|
||||||
p('-' * 80)
|
p('-' * 80)
|
||||||
lines = (cmd.__doc__ or '').strip().splitlines()
|
lines = (cmd.__doc__ or '').strip().splitlines()
|
||||||
@@ -274,7 +289,7 @@ def write_remote_control_protocol_docs() -> None: # {{{
|
|||||||
if m is None:
|
if m is None:
|
||||||
p(line)
|
p(line)
|
||||||
else:
|
else:
|
||||||
fields.append((m.group(1), m.group(2)))
|
fields.append((m.group(1).split('/')[0], m.group(2)))
|
||||||
if fields:
|
if fields:
|
||||||
p('\nFields are:\n')
|
p('\nFields are:\n')
|
||||||
for (name, desc) in fields:
|
for (name, desc) in fields:
|
||||||
@@ -302,9 +317,17 @@ def write_remote_control_protocol_docs() -> None: # {{{
|
|||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
|
||||||
|
def replace_string(app: Any, docname: str, source: List[str]) -> None: # {{{
|
||||||
|
src = source[0]
|
||||||
|
for k, v in app.config.string_replacements.items():
|
||||||
|
src = src.replace(k, v)
|
||||||
|
source[0] = src
|
||||||
|
# }}}
|
||||||
|
|
||||||
# config file docs {{{
|
# config file docs {{{
|
||||||
|
|
||||||
class ConfLexer(RegexLexer):
|
|
||||||
|
class ConfLexer(RegexLexer): # type: ignore
|
||||||
name = 'Conf'
|
name = 'Conf'
|
||||||
aliases = ['conf']
|
aliases = ['conf']
|
||||||
filenames = ['*.conf']
|
filenames = ['*.conf']
|
||||||
@@ -343,7 +366,7 @@ class ConfLexer(RegexLexer):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class SessionLexer(RegexLexer):
|
class SessionLexer(RegexLexer): # type: ignore
|
||||||
name = 'Session'
|
name = 'Session'
|
||||||
aliases = ['session']
|
aliases = ['session']
|
||||||
filenames = ['*.session']
|
filenames = ['*.session']
|
||||||
@@ -359,7 +382,9 @@ class SessionLexer(RegexLexer):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def link_role(name: str, rawtext: str, text: str, lineno: int, inliner: Any, options: Any = {}, content: Any = []) -> Tuple[List, List]:
|
def link_role(
|
||||||
|
name: str, rawtext: str, text: str, lineno: int, inliner: Any, options: Any = {}, content: Any = []
|
||||||
|
) -> Tuple[List[nodes.reference], List[nodes.problematic]]:
|
||||||
text = text.replace('\n', ' ')
|
text = text.replace('\n', ' ')
|
||||||
m = re.match(r'(.+)\s+<(.+?)>', text)
|
m = re.match(r'(.+)\s+<(.+?)>', text)
|
||||||
if m is None:
|
if m is None:
|
||||||
@@ -373,19 +398,6 @@ def link_role(name: str, rawtext: str, text: str, lineno: int, inliner: Any, opt
|
|||||||
return [node], []
|
return [node], []
|
||||||
|
|
||||||
|
|
||||||
def expand_opt_references(conf_name: str, text: str) -> str:
|
|
||||||
conf_name += '.'
|
|
||||||
|
|
||||||
def expand(m: Match) -> str:
|
|
||||||
ref = m.group(1)
|
|
||||||
if '<' not in ref and '.' not in ref:
|
|
||||||
full_ref = conf_name + ref
|
|
||||||
return ':opt:`{} <{}>`'.format(ref, full_ref)
|
|
||||||
return str(m.group())
|
|
||||||
|
|
||||||
return re.sub(r':opt:`(.+?)`', expand, text)
|
|
||||||
|
|
||||||
|
|
||||||
opt_aliases: Dict[str, str] = {}
|
opt_aliases: Dict[str, str] = {}
|
||||||
shortcut_slugs: Dict[str, Tuple[str, str]] = {}
|
shortcut_slugs: Dict[str, Tuple[str, str]] = {}
|
||||||
|
|
||||||
@@ -408,7 +420,7 @@ def parse_opt_node(env: Any, sig: str, signode: Any) -> str:
|
|||||||
opt_aliases[optname] = firstname
|
opt_aliases[optname] = firstname
|
||||||
count += 1
|
count += 1
|
||||||
if not firstname:
|
if not firstname:
|
||||||
raise ValueError('{} is not a valid opt'.format(sig))
|
raise ValueError(f'{sig} is not a valid opt')
|
||||||
return firstname
|
return firstname
|
||||||
|
|
||||||
|
|
||||||
@@ -419,23 +431,33 @@ def parse_shortcut_node(env: Any, sig: str, signode: Any) -> str:
|
|||||||
return sig
|
return sig
|
||||||
|
|
||||||
|
|
||||||
|
def parse_action_node(env: Any, sig: str, signode: Any) -> str:
|
||||||
|
"""Transform an action description into RST nodes."""
|
||||||
|
signode += addnodes.desc_name(sig, sig)
|
||||||
|
return sig
|
||||||
|
|
||||||
|
|
||||||
def process_opt_link(env: Any, refnode: Any, has_explicit_title: bool, title: str, target: str) -> Tuple[str, str]:
|
def process_opt_link(env: Any, refnode: Any, has_explicit_title: bool, title: str, target: str) -> Tuple[str, str]:
|
||||||
conf_name, opt = target.partition('.')[::2]
|
conf_name, opt = target.partition('.')[::2]
|
||||||
if not opt:
|
if not opt:
|
||||||
conf_name, opt = 'kitty', conf_name
|
conf_name, opt = 'kitty', conf_name
|
||||||
full_name = conf_name + '.' + opt
|
full_name = f'{conf_name}.{opt}'
|
||||||
return title, opt_aliases.get(full_name, full_name)
|
return title, opt_aliases.get(full_name, full_name)
|
||||||
|
|
||||||
|
|
||||||
|
def process_action_link(env: Any, refnode: Any, has_explicit_title: bool, title: str, target: str) -> Tuple[str, str]:
|
||||||
|
return title, target
|
||||||
|
|
||||||
|
|
||||||
def process_shortcut_link(env: Any, refnode: Any, has_explicit_title: bool, title: str, target: str) -> Tuple[str, str]:
|
def process_shortcut_link(env: Any, refnode: Any, has_explicit_title: bool, title: str, target: str) -> Tuple[str, str]:
|
||||||
conf_name, slug = target.partition('.')[::2]
|
conf_name, slug = target.partition('.')[::2]
|
||||||
if not slug:
|
if not slug:
|
||||||
conf_name, slug = 'kitty', conf_name
|
conf_name, slug = 'kitty', conf_name
|
||||||
full_name = conf_name + '.' + slug
|
full_name = f'{conf_name}.{slug}'
|
||||||
try:
|
try:
|
||||||
target, stitle = shortcut_slugs[full_name]
|
target, stitle = shortcut_slugs[full_name]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
logger.warning('Unknown shortcut: {}'.format(target), location=refnode)
|
logger.warning(f'Unknown shortcut: {target}', location=refnode)
|
||||||
else:
|
else:
|
||||||
if not has_explicit_title:
|
if not has_explicit_title:
|
||||||
title = stitle
|
title = stitle
|
||||||
@@ -464,6 +486,15 @@ def write_conf_docs(app: Any, all_kitten_names: Iterable[str]) -> None:
|
|||||||
sc_role.process_link = process_shortcut_link
|
sc_role.process_link = process_shortcut_link
|
||||||
shortcut_slugs.clear()
|
shortcut_slugs.clear()
|
||||||
|
|
||||||
|
app.add_object_type(
|
||||||
|
'action', 'ac',
|
||||||
|
indextemplate="pair: %s; Action",
|
||||||
|
parse_node=parse_action_node,
|
||||||
|
)
|
||||||
|
ac_role = app.registry.domain_roles['std']['ac']
|
||||||
|
ac_role.warn_dangling = True
|
||||||
|
ac_role.process_link = process_action_link
|
||||||
|
|
||||||
def generate_default_config(definition: Definition, name: str) -> None:
|
def generate_default_config(definition: Definition, name: str) -> None:
|
||||||
with open(f'generated/conf-{name}.rst', 'w', encoding='utf-8') as f:
|
with open(f'generated/conf-{name}.rst', 'w', encoding='utf-8') as f:
|
||||||
print('.. highlight:: conf\n', file=f)
|
print('.. highlight:: conf\n', file=f)
|
||||||
@@ -510,11 +541,14 @@ def setup(app: Any) -> None:
|
|||||||
write_cli_docs(kn)
|
write_cli_docs(kn)
|
||||||
write_remote_control_protocol_docs()
|
write_remote_control_protocol_docs()
|
||||||
write_conf_docs(app, kn)
|
write_conf_docs(app, kn)
|
||||||
|
app.add_config_value('string_replacements', {}, True)
|
||||||
|
app.connect('source-read', replace_string)
|
||||||
app.add_config_value('analytics_id', '', 'env')
|
app.add_config_value('analytics_id', '', 'env')
|
||||||
app.connect('html-page-context', add_html_context)
|
app.connect('html-page-context', add_html_context)
|
||||||
app.add_lexer('session', SessionLexer() if version_info[0] < 3 else SessionLexer)
|
app.add_lexer('session', SessionLexer() if version_info[0] < 3 else SessionLexer)
|
||||||
app.add_role('link', link_role)
|
app.add_role('link', link_role)
|
||||||
app.add_role('iss', partial(num_role, 'issues'))
|
|
||||||
app.add_role('pull', partial(num_role, 'pull'))
|
|
||||||
app.add_role('disc', partial(num_role, 'discussions'))
|
|
||||||
app.add_role('commit', commit_role)
|
app.add_role('commit', commit_role)
|
||||||
|
# monkey patch sphinx_inline_tabs to avoid a warning about parallel reads
|
||||||
|
# see https://github.com/pradyunsg/sphinx-inline-tabs/issues/26
|
||||||
|
inline_tabs = app.extensions['sphinx_inline_tabs']
|
||||||
|
inline_tabs.parallel_read_safe = inline_tabs.parallel_write_safe = True
|
||||||
|
|||||||
@@ -3,37 +3,47 @@ kitty.conf
|
|||||||
|
|
||||||
.. highlight:: conf
|
.. highlight:: conf
|
||||||
|
|
||||||
|kitty| is highly customizable, everything from keyboard shortcuts, to
|
|kitty| is highly customizable, everything from keyboard shortcuts, to rendering
|
||||||
rendering frames-per-second. See below for an overview of all customization
|
frames-per-second. See below for an overview of all customization possibilities.
|
||||||
possibilities.
|
|
||||||
|
|
||||||
You can open the config file within kitty by pressing :sc:`edit_config_file`.
|
You can open the config file within kitty by pressing :sc:`edit_config_file`
|
||||||
You can reload the config file within kitty by pressing
|
(:kbd:`⌘+,` on macOS). A :file:`kitty.conf` with commented default
|
||||||
:sc:`reload_config_file` or sending kitty the ``SIGUSR1`` signal. You can also
|
configurations and descriptions will be created if the file does not exist.
|
||||||
display the current configuration by pressing the :sc:`debug_config` key.
|
You can reload the config file within kitty by pressing :sc:`reload_config_file`
|
||||||
|
(:kbd:`⌃+⌘+,` on macOS) or sending kitty the ``SIGUSR1`` signal.
|
||||||
|
You can also display the current configuration by pressing :sc:`debug_config`
|
||||||
|
(:kbd:`⌥+⌘+,` on macOS).
|
||||||
|
|
||||||
.. _confloc:
|
.. _confloc:
|
||||||
|
|
||||||
|kitty| looks for a config file in the OS config directories (usually
|
|kitty| looks for a config file in the OS config directories (usually
|
||||||
:file:`~/.config/kitty/kitty.conf`) but you can pass a specific path via the
|
:file:`~/.config/kitty/kitty.conf`) but you can pass a specific path via the
|
||||||
:option:`kitty --config` option or use the ``KITTY_CONFIG_DIRECTORY``
|
:option:`kitty --config` option or use the :envvar:`KITTY_CONFIG_DIRECTORY`
|
||||||
environment variable. See the :option:`kitty --config` option for full details.
|
environment variable. See :option:`kitty --config` for full details.
|
||||||
|
|
||||||
Comments can be added to the config file as lines starting with the ``#``
|
Comments can be added to the config file as lines starting with the ``#``
|
||||||
character. This works only if the ``#`` character is the first character
|
character. This works only if the ``#`` character is the first character in the
|
||||||
in the line.
|
line.
|
||||||
|
|
||||||
|
.. _include:
|
||||||
|
|
||||||
You can include secondary config files via the :code:`include` directive. If
|
You can include secondary config files via the :code:`include` directive. If
|
||||||
you use a relative path for include, it is resolved with respect to the
|
you use a relative path for :code:`include`, it is resolved with respect to the
|
||||||
location of the current config file. Note that environment variables are
|
location of the current config file. Note that environment variables are
|
||||||
expanded, so :code:`${USER}.conf` becomes :file:`name.conf` if
|
expanded, so :code:`${USER}.conf` becomes :file:`name.conf` if
|
||||||
:code:`USER=name`. For example::
|
:code:`USER=name`. Also, you can use :code:`globinclude` to include files
|
||||||
|
matching a shell glob pattern and :code:`envinclude` to include configuration
|
||||||
|
from environment variables. For example::
|
||||||
|
|
||||||
include other.conf
|
include other.conf
|
||||||
|
# Include *.conf files from all subdirs of kitty.d inside the kitty config dir
|
||||||
|
globinclude kitty.d/**/*.conf
|
||||||
|
# Include the *contents* of all env vars starting with KITTY_CONF_
|
||||||
|
envinclude KITTY_CONF_*
|
||||||
|
|
||||||
|
|
||||||
.. note:: Syntax highlighting for :file:`kitty.conf` in vim is available via
|
.. note:: Syntax highlighting for :file:`kitty.conf` in vim is available via
|
||||||
`vim-kitty <https://github.com/fladson/vim-kitty>`_.
|
`vim-kitty <https://github.com/fladson/vim-kitty>`__.
|
||||||
|
|
||||||
|
|
||||||
.. include:: /generated/conf-kitty.rst
|
.. include:: /generated/conf-kitty.rst
|
||||||
@@ -44,17 +54,17 @@ Sample kitty.conf
|
|||||||
|
|
||||||
.. only:: html
|
.. only:: html
|
||||||
|
|
||||||
You can download a sample :file:`kitty.conf` file with all default settings and
|
You can download a sample :file:`kitty.conf` file with all default settings
|
||||||
comments describing each setting by clicking: :download:`sample kitty.conf
|
and comments describing each setting by clicking: :download:`sample
|
||||||
</generated/conf/kitty.conf>`.
|
kitty.conf </generated/conf/kitty.conf>`.
|
||||||
|
|
||||||
.. only:: man
|
.. only:: man
|
||||||
|
|
||||||
You can edit a fully commented sample kitty.conf by pressing the
|
You can edit a fully commented sample kitty.conf by pressing the
|
||||||
:sc:`edit_config_file` shortcut in kitty. This will generate a config
|
:sc:`edit_config_file` shortcut in kitty. This will generate a config file
|
||||||
file with full documentation and all settings commented out. If you
|
with full documentation and all settings commented out. If you have a
|
||||||
have a pre-existing kitty.conf, then that will be used instead, delete
|
pre-existing :file:`kitty.conf`, then that will be used instead, delete it to
|
||||||
it to see the sample file.
|
see the sample file.
|
||||||
|
|
||||||
|
|
||||||
All mappable actions
|
All mappable actions
|
||||||
|
|||||||
@@ -3,19 +3,18 @@ Setting text styles/colors in arbitrary regions of the screen
|
|||||||
|
|
||||||
There already exists an escape code to set *some* text attributes in arbitrary
|
There already exists an escape code to set *some* text attributes in arbitrary
|
||||||
regions of the screen, `DECCARA
|
regions of the screen, `DECCARA
|
||||||
<https://vt100.net/docs/vt510-rm/DECCARA.html>`_. However, it is limited to
|
<https://vt100.net/docs/vt510-rm/DECCARA.html>`__. However, it is limited to
|
||||||
only a few attributes. |kitty| extends this to work with *all* SGR attributes.
|
only a few attributes. |kitty| extends this to work with *all* SGR attributes.
|
||||||
So, for example, this can be used to set the background color in an arbitrary
|
So, for example, this can be used to set the background color in an arbitrary
|
||||||
region of the screen.
|
region of the screen.
|
||||||
|
|
||||||
The motivation for this extension is the various problems with the existing
|
The motivation for this extension is the various problems with the existing
|
||||||
solution for erasing to background color, namely the *background color erase
|
solution for erasing to background color, namely the *background color erase
|
||||||
(bce)* capability. See
|
(bce)* capability. See :iss:`this discussion <160#issuecomment-346470545>`
|
||||||
`this discussion <https://github.com/kovidgoyal/kitty/issues/160#issuecomment-346470545>`_
|
and `this FAQ <https://invisible-island.net/ncurses/ncurses.faq.html#bce_mismatches>`__
|
||||||
and `this FAQ <https://invisible-island.net/ncurses/ncurses.faq.html#bce_mismatches>`_
|
|
||||||
for a summary of problems with *bce*.
|
for a summary of problems with *bce*.
|
||||||
|
|
||||||
For example, to set the background color to blue in a
|
For example, to set the background color to blue in a rectangular region of the
|
||||||
rectangular region of the screen from (3, 4) to (10, 11), you use::
|
screen from (3, 4) to (10, 11), you use::
|
||||||
|
|
||||||
<ESC>[2*x<ESC>[4;3;11;10;44$r<ESC>[*x
|
<ESC>[2*x<ESC>[4;3;11;10;44$r<ESC>[*x
|
||||||
|
|||||||
@@ -5,21 +5,20 @@ Desktop notifications
|
|||||||
=======================
|
=======================
|
||||||
|
|
||||||
|kitty| implements an extensible escape code (OSC 99) to show desktop
|
|kitty| implements an extensible escape code (OSC 99) to show desktop
|
||||||
notifications. It is easy to use from shell scripts and fully extensible to
|
notifications. It is easy to use from shell scripts and fully extensible to show
|
||||||
show title and body. Clicking on the notification can optionally focus the
|
title and body. Clicking on the notification can optionally focus the window it
|
||||||
window it came from, and/or send an escape code back to the application running
|
came from, and/or send an escape code back to the application running in that
|
||||||
in that window.
|
window.
|
||||||
|
|
||||||
The design of the escape code is partially based on the discussion in
|
The design of the escape code is partially based on the discussion in the
|
||||||
the defunct
|
defunct `terminal-wg <https://gitlab.freedesktop.org/terminal-wg/specifications/-/issues/13>`__
|
||||||
`terminal-wg <https://gitlab.freedesktop.org/terminal-wg/specifications/-/issues/13>`_
|
|
||||||
|
|
||||||
The escape code has the form::
|
The escape code has the form::
|
||||||
|
|
||||||
<OSC> 99 ; metadata ; payload <terminator>
|
<OSC> 99 ; metadata ; payload <terminator>
|
||||||
|
|
||||||
Here ``<OSC>`` is :code:`<ESC>]` and ``<terminator>`` is
|
Here ``<OSC>`` is :code:`<ESC>]` and ``<terminator>`` is
|
||||||
:code:`<ESC><backslash>`. The metadata is a section of colon separated
|
:code:`<ESC><backslash>`. The ``metadata`` is a section of colon separated
|
||||||
:code:`key=value` pairs. Every key must be a single character from the set
|
:code:`key=value` pairs. Every key must be a single character from the set
|
||||||
:code:`a-zA-Z` and every value must be a word consisting of characters from
|
:code:`a-zA-Z` and every value must be a word consisting of characters from
|
||||||
the set :code:`a-zA-Z0-9-_/\+.,(){}[]*&^%$#@!`~`. The payload must be
|
the set :code:`a-zA-Z0-9-_/\+.,(){}[]*&^%$#@!`~`. The payload must be
|
||||||
@@ -45,28 +44,27 @@ The design of the escape code is fundamentally chunked, this is because
|
|||||||
different terminal emulators have different limits on how large a single escape
|
different terminal emulators have different limits on how large a single escape
|
||||||
code can be. Chunking is accomplished by the ``i`` and ``d`` keys. The ``i``
|
code can be. Chunking is accomplished by the ``i`` and ``d`` keys. The ``i``
|
||||||
key is the *notification id* which can be any string containing the characters
|
key is the *notification id* which can be any string containing the characters
|
||||||
``[a-zA-Z0-9_-+.]``. The ``d`` key stands for *done* and
|
``[a-zA-Z0-9_-+.]``. The ``d`` key stands for *done* and can only take the
|
||||||
can only take the values ``0`` and ``1``. A value of ``0`` means the
|
values ``0`` and ``1``. A value of ``0`` means the notification is not yet done
|
||||||
notification is not yet done and the terminal emulator should hold off
|
and the terminal emulator should hold off displaying it. A value of ``1`` means
|
||||||
displaying it. A value of ``1`` means the notification is done, and should be
|
the notification is done, and should be displayed. You can specify the title or
|
||||||
displayed. You can specify the title or body multiple times and the terminal
|
body multiple times and the terminal emulator will concatenate them, thereby
|
||||||
emulator will concatenate them, thereby allowing arbitrarily long text
|
allowing arbitrarily long text (terminal emulators are free to impose a sensible
|
||||||
(terminal emulators are free to impose a sensible limit to avoid
|
limit to avoid Denial-of-Service attacks).
|
||||||
Denial-of-Service attacks).
|
|
||||||
|
|
||||||
Both the ``title`` and ``body`` payloads must be either UTF-8 encoded plain
|
Both the ``title`` and ``body`` payloads must be either UTF-8 encoded plain
|
||||||
text with no embedded escape codes, or UTF-8 text that is base64 encoded, in
|
text with no embedded escape codes, or UTF-8 text that is Base64 encoded, in
|
||||||
which case there must be an ``e=1`` key in the metadata to indicate the payload
|
which case there must be an ``e=1`` key in the metadata to indicate the payload
|
||||||
is base64 encoded.
|
is Base64 encoded.
|
||||||
|
|
||||||
When the user clicks the notification, a couple of things can happen, the
|
When the user clicks the notification, a couple of things can happen, the
|
||||||
terminal emulator can focus the window from which the notification came, and/or
|
terminal emulator can focus the window from which the notification came, and/or
|
||||||
it can send back an escape code to the application indicating the notification
|
it can send back an escape code to the application indicating the notification
|
||||||
was activated. This is controlled by the ``a`` key which takes a comma
|
was activated. This is controlled by the ``a`` key which takes a comma separated
|
||||||
separated set of values, ``report`` and ``focus``. The value ``focus`` means
|
set of values, ``report`` and ``focus``. The value ``focus`` means focus the
|
||||||
focus the window from which the notification was issued and is the default.
|
window from which the notification was issued and is the default. ``report``
|
||||||
``report`` means send an escape code back to the application. The format of the
|
means send an escape code back to the application. The format of the returned
|
||||||
returned escape code is::
|
escape code is::
|
||||||
|
|
||||||
<OSC> 99 ; i=identifier ; <terminator>
|
<OSC> 99 ; i=identifier ; <terminator>
|
||||||
|
|
||||||
@@ -87,9 +85,9 @@ to display it based on what it does understand.
|
|||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
It is possible to extend this escape code to allow specifying an icon for
|
It is possible to extend this escape code to allow specifying an icon for
|
||||||
the notification, however, given that some platforms, such as macOS, dont
|
the notification, however, given that some platforms, such as legacy versions
|
||||||
allow displaying custom icons on a notification, at all, it was decided to
|
of macOS, don't allow displaying custom images on a notification, it was
|
||||||
leave it out of the spec for the time being.
|
decided to leave it out of the spec for the time being.
|
||||||
|
|
||||||
Similarly, features such as scheduled notifications could be added in future
|
Similarly, features such as scheduled notifications could be added in future
|
||||||
revisions.
|
revisions.
|
||||||
@@ -107,7 +105,7 @@ Key Value Default Description
|
|||||||
``d`` ``0`` or ``1`` ``1`` Indicates if the notification is
|
``d`` ``0`` or ``1`` ``1`` Indicates if the notification is
|
||||||
complete or not.
|
complete or not.
|
||||||
|
|
||||||
``e`` ``0`` or ``1`` ``0`` If set to ``1`` means the payload is base64 encoded UTF-8,
|
``e`` ``0`` or ``1`` ``0`` If set to ``1`` means the payload is Base64 encoded UTF-8,
|
||||||
otherwise it is plain UTF-8 text with no C0 control codes in it
|
otherwise it is plain UTF-8 text with no C0 control codes in it
|
||||||
|
|
||||||
``i`` ``[a-zA-Z0-9-_+.]`` ``0`` Identifier for the notification
|
``i`` ``[a-zA-Z0-9-_+.]`` ``0`` Identifier for the notification
|
||||||
@@ -118,5 +116,6 @@ Key Value Default Description
|
|||||||
|
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|kitty| also supports the legacy OSC 9 protocol developed by iTerm2 for
|
|kitty| also supports the `legacy OSC 9 protocol developed by iTerm2
|
||||||
desktop notifications.
|
<https://iterm2.com/documentation-escape-codes.html>`__ for desktop
|
||||||
|
notifications.
|
||||||
|
|||||||
54
docs/extract-rst-targets.py
Executable file
@@ -0,0 +1,54 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# License: GPLv3 Copyright: 2022, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
from typing import Dict, Iterator
|
||||||
|
|
||||||
|
tgt_pat = re.compile(r'^.. _(\S+?):$', re.MULTILINE)
|
||||||
|
title_pat = re.compile('^(.+)\n[-=^#*]{5,}$', re.MULTILINE)
|
||||||
|
|
||||||
|
|
||||||
|
def find_explicit_targets(text: str) -> Iterator[str]:
|
||||||
|
for m in tgt_pat.finditer(text):
|
||||||
|
yield m.group(1)
|
||||||
|
|
||||||
|
|
||||||
|
def find_page_title(text: str) -> str:
|
||||||
|
for m in title_pat.finditer(text):
|
||||||
|
return m.group(1)
|
||||||
|
return ''
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> Dict[str, Dict[str, str]]:
|
||||||
|
refs = {}
|
||||||
|
docs = {}
|
||||||
|
base = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
for dirpath, dirnames, filenames in os.walk(base):
|
||||||
|
if 'generated' in dirnames:
|
||||||
|
dirnames.remove('generated')
|
||||||
|
for f in filenames:
|
||||||
|
if f.endswith('.rst'):
|
||||||
|
with open(os.path.join(dirpath, f)) as stream:
|
||||||
|
raw = stream.read()
|
||||||
|
href = os.path.relpath(stream.name, base).replace(os.sep, '/')
|
||||||
|
href = href.rpartition('.')[0] + '/'
|
||||||
|
docs[href.rstrip('/')] = find_page_title(raw)
|
||||||
|
first_line = raw.lstrip('\n').partition('\n')[0]
|
||||||
|
first_target_added = False
|
||||||
|
for explicit_target in find_explicit_targets(raw):
|
||||||
|
# Shorten the reference link to the top of the page.
|
||||||
|
# Note that anchor links should still be used in HTML docs
|
||||||
|
# to allow jumping within the same page.
|
||||||
|
if not first_target_added:
|
||||||
|
first_target_added = True
|
||||||
|
if first_line.startswith(f'.. _{explicit_target}:'):
|
||||||
|
refs[explicit_target] = href
|
||||||
|
continue
|
||||||
|
refs[explicit_target] = href + f'#{explicit_target.replace("_", "-")}'
|
||||||
|
return {'ref': refs, 'doc': docs}
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import json
|
||||||
|
print(json.dumps(main(), indent=2))
|
||||||
311
docs/faq.rst
@@ -6,34 +6,36 @@ Frequently Asked Questions
|
|||||||
Some special symbols are rendered small/truncated in kitty?
|
Some special symbols are rendered small/truncated in kitty?
|
||||||
-----------------------------------------------------------
|
-----------------------------------------------------------
|
||||||
|
|
||||||
The number of cells a unicode character takes up are controlled by the unicode
|
The number of cells a Unicode character takes up are controlled by the Unicode
|
||||||
standard. All characters are rendered in a single cell unless the unicode
|
standard. All characters are rendered in a single cell unless the Unicode
|
||||||
standard says they should be rendered in two cells. When a symbol does not fit,
|
standard says they should be rendered in two cells. When a symbol does not fit,
|
||||||
it will either be rescaled to be smaller or truncated (depending on how much
|
it will either be rescaled to be smaller or truncated (depending on how much
|
||||||
extra space it needs). This is often different from other terminals which just
|
extra space it needs). This is often different from other terminals which just
|
||||||
let the character overflow into neighboring cells, which is fine if the
|
let the character overflow into neighboring cells, which is fine if the
|
||||||
neighboring cell is empty, but looks terrible if it is not.
|
neighboring cell is empty, but looks terrible if it is not.
|
||||||
|
|
||||||
Some programs, like powerline, vim with fancy gutter symbols/status-bar, etc.
|
Some programs, like Powerline, vim with fancy gutter symbols/status-bar, etc.
|
||||||
misuse unicode characters from the private use area to represent symbols. Often
|
use Unicode characters from the private use area to represent symbols. Often
|
||||||
these symbols are square and should be rendered in two cells. However, since
|
these symbols are wide and should be rendered in two cells. However, since
|
||||||
private use area symbols all have their width set to one in the unicode
|
private use area symbols all have their width set to one in the Unicode
|
||||||
standard, |kitty| renders them either smaller or truncated. The exception is if
|
standard, |kitty| renders them either smaller or truncated. The exception is if
|
||||||
these characters are followed by a space or empty cell in which case kitty
|
these characters are followed by a space or empty cell in which case kitty
|
||||||
makes use of the extra cell to render them in two cells.
|
makes use of the extra cell to render them in two cells. This behavior can be
|
||||||
|
turned off for specific symbols using :opt:`narrow_symbols`.
|
||||||
|
|
||||||
|
|
||||||
Using a color theme with a background color does not work well in vim?
|
Using a color theme with a background color does not work well in vim?
|
||||||
-----------------------------------------------------------------------
|
-----------------------------------------------------------------------
|
||||||
|
|
||||||
First make sure you have not changed the TERM environment variable, it should
|
First make sure you have not changed the :envvar:`TERM` environment variable, it
|
||||||
be ``xterm-kitty``. vim uses *background color erase* even if the terminfo file
|
should be ``xterm-kitty``. vim uses *background color erase* even if the
|
||||||
does not contain the ``bce`` capability. This is a bug in vim. You can work around
|
terminfo file does not contain the ``bce`` capability. This is a bug in vim. You
|
||||||
it by adding the following to your vimrc::
|
can work around it by adding the following to your vimrc::
|
||||||
|
|
||||||
let &t_ut=''
|
let &t_ut=''
|
||||||
|
|
||||||
See :doc:`here <deccara>` for why |kitty| does not support background color erase.
|
See :doc:`here <deccara>` for why |kitty| does not support background color
|
||||||
|
erase.
|
||||||
|
|
||||||
|
|
||||||
I get errors about the terminal being unknown or opening the terminal failing when SSHing into a different computer?
|
I get errors about the terminal being unknown or opening the terminal failing when SSHing into a different computer?
|
||||||
@@ -45,39 +47,33 @@ terminfo files to the server::
|
|||||||
|
|
||||||
kitty +kitten ssh myserver
|
kitty +kitten ssh myserver
|
||||||
|
|
||||||
This ssh kitten takes all the same command line arguments
|
This :doc:`ssh kitten <kittens/ssh>` takes all the same command line arguments
|
||||||
as ssh, you can alias it to ssh in your shell's rc files to avoid having to
|
as :program:`ssh`, you can alias it to something small in your shell's rc files
|
||||||
type it each time::
|
to avoid having to type it each time::
|
||||||
|
|
||||||
alias ssh="kitty +kitten ssh"
|
alias s="kitty +kitten ssh"
|
||||||
|
|
||||||
If for some reason that does not work (typically because the server is using a
|
If the ssh kitten fails, use the following one-liner instead (it is slower as it
|
||||||
non POSIX compliant shell as ``/bin/sh``), you can try using it with ``python``
|
needs to ssh into the server twice, but will work with most servers)::
|
||||||
instead::
|
|
||||||
|
|
||||||
kitty +kitten ssh use-python myserver
|
|
||||||
|
|
||||||
If that also fails, perhaps because python is not installed on the remote
|
|
||||||
server, use the following one-liner instead (it
|
|
||||||
is slower as it needs to ssh into the server twice, but will work with most
|
|
||||||
servers)::
|
|
||||||
|
|
||||||
infocmp -a xterm-kitty | ssh myserver tic -x -o \~/.terminfo /dev/stdin
|
infocmp -a xterm-kitty | ssh myserver tic -x -o \~/.terminfo /dev/stdin
|
||||||
|
|
||||||
If you are behind a proxy (like Balabit) that prevents this, you must redirect the
|
If you are behind a proxy (like Balabit) that prevents this, or :program:`tic`
|
||||||
1st command to a file, copy that to the server and run ``tic`` manually. If you
|
comes with macOS that does not support reading from STDIN, you must redirect the
|
||||||
connect to a server, embedded or Android system that doesn't have ``tic``, copy over
|
first command to a file, copy that to the server and run :program:`tic`
|
||||||
your local file terminfo to the other system as :file:`~/.terminfo/x/xterm-kitty`.
|
manually. If you connect to a server, embedded or Android system that doesn't
|
||||||
|
have :program:`tic`, copy over your local file terminfo to the other system as
|
||||||
|
:file:`~/.terminfo/x/xterm-kitty`.
|
||||||
|
|
||||||
Really, the correct solution for this is to convince the OpenSSH maintainers to
|
Really, the correct solution for this is to convince the OpenSSH maintainers to
|
||||||
have ssh do this automatically, if possible, when connecting to a server, so that
|
have :program:`ssh` do this automatically, if possible, when connecting to a
|
||||||
all terminals work transparently.
|
server, so that all terminals work transparently.
|
||||||
|
|
||||||
If the server is running FreeBSD, or another system that relies on termcap
|
If the server is running FreeBSD, or another system that relies on termcap
|
||||||
rather than terminfo, you will need to convert the terminfo file on your local
|
rather than terminfo, you will need to convert the terminfo file on your local
|
||||||
machine by running (on local machine with |kitty|)::
|
machine by running (on local machine with |kitty|)::
|
||||||
|
|
||||||
infocmp -C xterm-kitty
|
infocmp -CrT0 xterm-kitty
|
||||||
|
|
||||||
The output of this command is the termcap description, which should be appended
|
The output of this command is the termcap description, which should be appended
|
||||||
to :file:`/usr/share/misc/termcap` on the remote server. Then run the following
|
to :file:`/usr/share/misc/termcap` on the remote server. Then run the following
|
||||||
@@ -89,22 +85,29 @@ command to apply your change (on the server)::
|
|||||||
Keys such as arrow keys, backspace, delete, home/end, etc. do not work when using su or sudo?
|
Keys such as arrow keys, backspace, delete, home/end, etc. do not work when using su or sudo?
|
||||||
-------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
Make sure the TERM environment variable, is ``xterm-kitty``. And either the
|
Make sure the :envvar:`TERM` environment variable, is ``xterm-kitty``. And
|
||||||
TERMINFO environment variable points to a directory containing :file:`x/xterm-kitty`
|
either the :envvar:`TERMINFO` environment variable points to a directory
|
||||||
or that file is under :file:`~/.terminfo/x/`.
|
containing :file:`x/xterm-kitty` or that file is under :file:`~/.terminfo/x/`.
|
||||||
|
|
||||||
Note that ``sudo`` might remove TERMINFO. Then setting it at the shell prompt can
|
For macOS, you may also need to put that file under :file:`~/.terminfo/78/`::
|
||||||
be too late, because command line editing may not be reinitialized. In that case
|
|
||||||
you can either ask ``sudo`` to set it or if that is not supported, insert an ``env``
|
mkdir -p ~/.terminfo/{78,x}
|
||||||
command before starting the shell, or, if not possible, after sudo start another
|
ln -snf ../x/xterm-kitty ~/.terminfo/78/xterm-kitty
|
||||||
Shell providing the right terminfo path::
|
tic -x -o ~/.terminfo "$KITTY_INSTALLATION_DIR/terminfo/kitty.terminfo"
|
||||||
|
|
||||||
|
Note that :program:`sudo` might remove :envvar:`TERMINFO`. Then setting it at
|
||||||
|
the shell prompt can be too late, because command line editing may not be
|
||||||
|
reinitialized. In that case you can either ask :program:`sudo` to set it or if
|
||||||
|
that is not supported, insert an :program:`env` command before starting the
|
||||||
|
shell, or, if not possible, after sudo start another shell providing the right
|
||||||
|
terminfo path::
|
||||||
|
|
||||||
sudo … TERMINFO=$HOME/.terminfo bash -i
|
sudo … TERMINFO=$HOME/.terminfo bash -i
|
||||||
sudo … env TERMINFO=$HOME/.terminfo bash -i
|
sudo … env TERMINFO=$HOME/.terminfo bash -i
|
||||||
TERMINFO=/home/ORIGINALUSER/.terminfo exec bash -i
|
TERMINFO=/home/ORIGINALUSER/.terminfo exec bash -i
|
||||||
|
|
||||||
You can configure sudo to preserve TERMINFO by running ``sudo
|
You can configure :program:`sudo` to preserve :envvar:`TERMINFO` by running
|
||||||
visudo`` and adding the following line::
|
``sudo visudo`` and adding the following line::
|
||||||
|
|
||||||
Defaults env_keep += "TERM TERMINFO"
|
Defaults env_keep += "TERM TERMINFO"
|
||||||
|
|
||||||
@@ -117,20 +120,27 @@ explicitly set a UTF-8 locale, like::
|
|||||||
How do I change the colors in a running kitty instance?
|
How do I change the colors in a running kitty instance?
|
||||||
------------------------------------------------------------
|
------------------------------------------------------------
|
||||||
|
|
||||||
You can either use the
|
The easiest way to do it is to use the :doc:`themes kitten </kittens/themes>`,
|
||||||
`OSC terminal escape codes <https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Operating-System-Commands>`_
|
to choose a new color theme. Simply run::
|
||||||
to set colors or you can define keyboard shortcuts to set colors, for example::
|
|
||||||
|
kitty +kitten themes
|
||||||
|
|
||||||
|
And choose your theme from the list.
|
||||||
|
|
||||||
|
You can also define keyboard shortcuts to set colors, for example::
|
||||||
|
|
||||||
map f1 set_colors --configured /path/to/some/config/file/colors.conf
|
map f1 set_colors --configured /path/to/some/config/file/colors.conf
|
||||||
|
|
||||||
Or you can enable :doc:`remote control <remote-control>` for |kitty| and use :ref:`at_set-colors`.
|
Or you can enable :doc:`remote control <remote-control>` for |kitty| and use
|
||||||
The shortcut mapping technique has the same syntax as the remote control
|
:ref:`at-set-colors`. The shortcut mapping technique has the same syntax as the
|
||||||
command, for details, see :ref:`at_set-colors`.
|
remote control command, for details, see :ref:`at-set-colors`.
|
||||||
|
|
||||||
A list of pre-made color themes for kitty is available at:
|
To change colors when SSHing into a remote host, use the :opt:`color_scheme
|
||||||
`kitty-themes <https://github.com/dexpota/kitty-themes>`_
|
<kitten-ssh.color_scheme>` setting for the :doc:`ssh kitten <kittens/ssh>`.
|
||||||
|
|
||||||
Examples of using OSC escape codes to set colors::
|
Additionally, You can use the
|
||||||
|
`OSC terminal escape codes <https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Operating-System-Commands>`__
|
||||||
|
to set colors. Examples of using OSC escape codes to set colors::
|
||||||
|
|
||||||
Change the default foreground color:
|
Change the default foreground color:
|
||||||
printf '\x1b]10;#ff0000\x1b\\'
|
printf '\x1b]10;#ff0000\x1b\\'
|
||||||
@@ -146,7 +156,7 @@ Examples of using OSC escape codes to set colors::
|
|||||||
printf '\x1b]4;n;green\x1b\\'
|
printf '\x1b]4;n;green\x1b\\'
|
||||||
|
|
||||||
You can use various syntaxes/names for color specifications in the above
|
You can use various syntaxes/names for color specifications in the above
|
||||||
examples. See `XParseColor <https://linux.die.net/man/3/xparsecolor>`_
|
examples. See `XParseColor <https://linux.die.net/man/3/xparsecolor>`__
|
||||||
for full details.
|
for full details.
|
||||||
|
|
||||||
If a ``?`` is given rather than a color specification, kitty will respond
|
If a ``?`` is given rather than a color specification, kitty will respond
|
||||||
@@ -159,14 +169,15 @@ How do I specify command line options for kitty on macOS?
|
|||||||
Apple does not want you to use command line options with GUI applications. To
|
Apple does not want you to use command line options with GUI applications. To
|
||||||
workaround that limitation, |kitty| will read command line options from the file
|
workaround that limitation, |kitty| will read command line options from the file
|
||||||
:file:`<kitty config dir>/macos-launch-services-cmdline` when it is launched
|
:file:`<kitty config dir>/macos-launch-services-cmdline` when it is launched
|
||||||
from the GUI, i.e. by clicking the |kitty| application icon or using ``open -a kitty``.
|
from the GUI, i.e. by clicking the |kitty| application icon or using
|
||||||
Note that this file is *only read* when running via the GUI.
|
``open -a kitty``. Note that this file is *only read* when running via the GUI.
|
||||||
|
|
||||||
You can, of course, also run |kitty| from a terminal with command line options, using:
|
You can, of course, also run |kitty| from a terminal with command line options,
|
||||||
:file:`/Applications/kitty.app/Contents/MacOS/kitty`.
|
using: :file:`/Applications/kitty.app/Contents/MacOS/kitty`.
|
||||||
|
|
||||||
|
And within |kitty| itself, you can always run |kitty| using just ``kitty`` as it
|
||||||
|
cleverly adds itself to the :envvar:`PATH`.
|
||||||
|
|
||||||
And within |kitty| itself, you can always run |kitty| using just `kitty` as it
|
|
||||||
cleverly adds itself to the ``PATH``.
|
|
||||||
|
|
||||||
I catted a binary file and now kitty is hung?
|
I catted a binary file and now kitty is hung?
|
||||||
-----------------------------------------------
|
-----------------------------------------------
|
||||||
@@ -174,10 +185,10 @@ I catted a binary file and now kitty is hung?
|
|||||||
**Never** output unknown binary data directly into a terminal.
|
**Never** output unknown binary data directly into a terminal.
|
||||||
|
|
||||||
Terminals have a single channel for both data and control. Certain bytes
|
Terminals have a single channel for both data and control. Certain bytes
|
||||||
are control codes. Some of these control codes are of arbitrary length, so
|
are control codes. Some of these control codes are of arbitrary length, so if
|
||||||
if the binary data you output into the terminal happens to contain the starting
|
the binary data you output into the terminal happens to contain the starting
|
||||||
sequence for one of these control codes, the terminal will hang waiting for
|
sequence for one of these control codes, the terminal will hang waiting for the
|
||||||
the closing sequence. Press :kbd:`ctrl+shift+delete` to reset the terminal.
|
closing sequence. Press :sc:`reset_terminal` to reset the terminal.
|
||||||
|
|
||||||
If you do want to cat unknown data, use ``cat -v``.
|
If you do want to cat unknown data, use ``cat -v``.
|
||||||
|
|
||||||
@@ -186,19 +197,33 @@ kitty is not able to use my favorite font?
|
|||||||
---------------------------------------------
|
---------------------------------------------
|
||||||
|
|
||||||
|kitty| achieves its stellar performance by caching alpha masks of each rendered
|
|kitty| achieves its stellar performance by caching alpha masks of each rendered
|
||||||
character on the GPU, so that every character needs to be rendered only once.
|
character on the GPU, and rendering them all in parallel. This means it is a
|
||||||
This means it is a strictly character cell based display. As such it can use
|
strictly character cell based display. As such it can use only monospace fonts,
|
||||||
only monospace fonts, since every cell in the grid has to be the same size.
|
since every cell in the grid has to be the same size. Furthermore, it needs
|
||||||
Furthermore, it needs fonts to be freely resizable, so it does not support
|
fonts to be freely resizable, so it does not support bitmapped fonts.
|
||||||
bitmapped fonts.
|
|
||||||
|
|
||||||
If your font is not listed in ``kitty list-fonts`` it means that it is not
|
.. note::
|
||||||
monospace or is a bitmapped font. On Linux you can list all monospace fonts with::
|
If you are trying to use a font patched with `Nerd Fonts
|
||||||
|
<https://nerdfonts.com/>`__ symbols, don't do that as patching destroys
|
||||||
|
fonts. There is no need, simply install the standalone ``Symbols Nerd Font``
|
||||||
|
(the file :file:`NerdFontsSymbolsOnly.zip` from the `Nerd Fonts releases page
|
||||||
|
<https://github.com/ryanoasis/nerd-fonts/releases>`__). kitty should pick up
|
||||||
|
symbols from it automatically, and you can tell it to do so explicitly in
|
||||||
|
case it doesn't with the :opt:`symbol_map` directive::
|
||||||
|
|
||||||
|
symbol_map U+23FB-U+23FE,U+2665,U+26A1,U+2B58,U+E000-U+E00A,U+E0A0-U+E0A3,U+E0B0-U+E0C8,U+E0CA,U+E0CC-U+E0D2,U+E0D4,U+E200-U+E2A9,U+E300-U+E3E3,U+E5FA-U+E62F,U+E700-U+E7C5,U+F000-U+F2E0,U+F300-U+F31C,U+F400-U+F4A9,U+F500-U+F8FF Symbols Nerd Font
|
||||||
|
|
||||||
|
Those Unicode symbols beyond the ``E000-F8FF`` Unicode private use area are
|
||||||
|
not included.
|
||||||
|
|
||||||
|
If your font is not listed in ``kitty +list-fonts`` it means that it is not
|
||||||
|
monospace or is a bitmapped font. On Linux you can list all monospace fonts
|
||||||
|
with::
|
||||||
|
|
||||||
fc-list : family spacing outline scalable | grep -e spacing=100 -e spacing=90 | grep -e outline=True | grep -e scalable=True
|
fc-list : family spacing outline scalable | grep -e spacing=100 -e spacing=90 | grep -e outline=True | grep -e scalable=True
|
||||||
|
|
||||||
Note that the spacing property is calculated by fontconfig based on actual
|
Note that the spacing property is calculated by fontconfig based on actual glyph
|
||||||
glyph widths in the font. If for some reason fontconfig concludes your favorite
|
widths in the font. If for some reason fontconfig concludes your favorite
|
||||||
monospace font does not have ``spacing=100`` you can override it by using the
|
monospace font does not have ``spacing=100`` you can override it by using the
|
||||||
following :file:`~/.config/fontconfig/fonts.conf`::
|
following :file:`~/.config/fontconfig/fonts.conf`::
|
||||||
|
|
||||||
@@ -220,7 +245,7 @@ command to rebuild your fontconfig cache::
|
|||||||
|
|
||||||
fc-cache -r
|
fc-cache -r
|
||||||
|
|
||||||
Then, the font will be available in ``kitty list-fonts``.
|
Then, the font will be available in ``kitty +list-fonts``.
|
||||||
|
|
||||||
|
|
||||||
How can I assign a single global shortcut to bring up the kitty terminal?
|
How can I assign a single global shortcut to bring up the kitty terminal?
|
||||||
@@ -229,7 +254,46 @@ How can I assign a single global shortcut to bring up the kitty terminal?
|
|||||||
Bringing up applications on a single key press is the job of the window
|
Bringing up applications on a single key press is the job of the window
|
||||||
manager/desktop environment. For ways to do it with kitty (or indeed any
|
manager/desktop environment. For ways to do it with kitty (or indeed any
|
||||||
terminal) in different environments,
|
terminal) in different environments,
|
||||||
see `here <https://github.com/kovidgoyal/kitty/issues/45>`_.
|
see :iss:`here <45>`.
|
||||||
|
|
||||||
|
|
||||||
|
I do not like the kitty icon!
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
There are many alternate icons available, click on an icon to visit its
|
||||||
|
homepage:
|
||||||
|
|
||||||
|
.. image:: https://github.com/k0nserv/kitty-icon/raw/main/icon_512x512.png
|
||||||
|
:target: https://github.com/k0nserv/kitty-icon
|
||||||
|
:width: 256
|
||||||
|
|
||||||
|
.. image:: https://github.com/DinkDonk/kitty-icon/raw/main/kitty-dark.png
|
||||||
|
:target: https://github.com/DinkDonk/kitty-icon
|
||||||
|
:width: 256
|
||||||
|
|
||||||
|
.. image:: https://github.com/DinkDonk/kitty-icon/raw/main/kitty-light.png
|
||||||
|
:target: https://github.com/DinkDonk/kitty-icon
|
||||||
|
:width: 256
|
||||||
|
|
||||||
|
.. image:: https://github.com/hristost/kitty-alternative-icon/raw/main/kitty_icon.png
|
||||||
|
:target: https://github.com/hristost/kitty-alternative-icon
|
||||||
|
:width: 256
|
||||||
|
|
||||||
|
.. image:: https://github.com/igrmk/whiskers/raw/main/whiskers.svg
|
||||||
|
:target: https://github.com/igrmk/whiskers
|
||||||
|
:width: 256
|
||||||
|
|
||||||
|
.. image:: https://github.com/samholmes/whiskers/raw/main/whiskers.png
|
||||||
|
:target: https://github.com/samholmes/whiskers
|
||||||
|
:width: 256
|
||||||
|
|
||||||
|
On macOS you can change the icon by following the steps:
|
||||||
|
|
||||||
|
#. Find :file:`kitty.app` in the Applications folder, select it and press :kbd:`⌘+I`
|
||||||
|
#. Drag :file:`kitty.icns` onto the application icon in the kitty info pane
|
||||||
|
#. Delete the icon cache and restart Dock::
|
||||||
|
|
||||||
|
$ rm /var/folders/*/*/*/com.apple.dock.iconcache; killall Dock
|
||||||
|
|
||||||
|
|
||||||
How do I map key presses in kitty to different keys in the terminal program?
|
How do I map key presses in kitty to different keys in the terminal program?
|
||||||
@@ -245,7 +309,14 @@ the :sc:`send_text <send_text>` you can use the ``show_key`` kitten. Run::
|
|||||||
|
|
||||||
kitty +kitten show_key
|
kitty +kitten show_key
|
||||||
|
|
||||||
Then press the key you want to emulate.
|
Then press the key you want to emulate. Note that this kitten will only show
|
||||||
|
keys that actually reach the terminal program, in particular, keys mapped to
|
||||||
|
actions in kitty will not be shown. To check those first map them to
|
||||||
|
:ac:`no_op`. You can also start a kitty instance without any shortcuts to
|
||||||
|
interfere::
|
||||||
|
|
||||||
|
kitty -o clear_all_shortcuts=yes kitty +kitten show_key
|
||||||
|
|
||||||
|
|
||||||
How do I open a new window or tab with the same working directory as the current window?
|
How do I open a new window or tab with the same working directory as the current window?
|
||||||
--------------------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------------------
|
||||||
@@ -253,7 +324,7 @@ How do I open a new window or tab with the same working directory as the current
|
|||||||
In :file:`kitty.conf` add the following::
|
In :file:`kitty.conf` add the following::
|
||||||
|
|
||||||
map f1 launch --cwd=current
|
map f1 launch --cwd=current
|
||||||
map f2 launch --cwd=current --type=tab
|
map f2 launch --cwd=current --type=tab
|
||||||
|
|
||||||
Pressing :kbd:`F1` will open a new kitty window with the same working directory
|
Pressing :kbd:`F1` will open a new kitty window with the same working directory
|
||||||
as the current window. The :doc:`launch command <launch>` is very powerful,
|
as the current window. The :doc:`launch command <launch>` is very powerful,
|
||||||
@@ -272,8 +343,8 @@ variables which kitty will now inherit.
|
|||||||
You need to make sure that the environment variables you define in your shell's
|
You need to make sure that the environment variables you define in your shell's
|
||||||
rc files are either also defined system wide or via the :opt:`env` directive in
|
rc files are either also defined system wide or via the :opt:`env` directive in
|
||||||
:file:`kitty.conf`. Common environment variables that cause issues are those
|
:file:`kitty.conf`. Common environment variables that cause issues are those
|
||||||
related to localization, such as ``LANG, LC_*`` and loading of configuration
|
related to localization, such as :envvar:`LANG`, ``LC_*`` and loading of
|
||||||
files such as ``XDG_*, KITTY_CONFIG_DIRECTORY``.
|
configuration files such as ``XDG_*``, :envvar:`KITTY_CONFIG_DIRECTORY`.
|
||||||
|
|
||||||
To see the environment variables that kitty sees, you can add the following
|
To see the environment variables that kitty sees, you can add the following
|
||||||
mapping to :file:`kitty.conf`::
|
mapping to :file:`kitty.conf`::
|
||||||
@@ -290,38 +361,42 @@ sorts of places where they may or may not work.
|
|||||||
I am using tmux and have a problem
|
I am using tmux and have a problem
|
||||||
--------------------------------------
|
--------------------------------------
|
||||||
|
|
||||||
First, terminal multiplexers are `a bad idea
|
First, terminal multiplexers are :iss:`a bad idea <391#issuecomment-638320745>`,
|
||||||
<https://github.com/kovidgoyal/kitty/issues/391#issuecomment-638320745>`_, do
|
do not use them, if at all possible. kitty contains features that do all of what
|
||||||
not use them, if at all possible. kitty contains features that do all of what
|
|
||||||
tmux does, but better, with the exception of remote persistence (:iss:`391`).
|
tmux does, but better, with the exception of remote persistence (:iss:`391`).
|
||||||
If you still want to use tmux, read on.
|
If you still want to use tmux, read on.
|
||||||
|
|
||||||
Image display will not work, see `tmux issue
|
Image display will not work, see `tmux issue
|
||||||
<https://github.com/tmux/tmux/issues/1391>`_.
|
<https://github.com/tmux/tmux/issues/1391>`__.
|
||||||
|
|
||||||
If you are using tmux with multiple terminals or you start it under one
|
Using ancient versions of tmux such as 1.8 will cause gibberish on screen when
|
||||||
terminal and then switch to another and these terminals have different TERM
|
pressing keys (:iss:`3541`).
|
||||||
variables, tmux will break. You will need to restart it as tmux does not
|
|
||||||
support multiple terminfo definitions.
|
If you are using tmux with multiple terminals or you start it under one terminal
|
||||||
|
and then switch to another and these terminals have different :envvar:`TERM`
|
||||||
|
variables, tmux will break. You will need to restart it as tmux does not support
|
||||||
|
multiple terminfo definitions.
|
||||||
|
|
||||||
If you use any of the advanced features that kitty has innovated, such as
|
If you use any of the advanced features that kitty has innovated, such as
|
||||||
styled underlines, desktop notifications, extended keyboard support, etc.
|
:doc:`styled underlines </underlines>`, :doc:`desktop notifications
|
||||||
they may or may not work, depending on the whims of tmux's maintainer, your
|
</desktop-notifications>`, :doc:`extended keyboard support
|
||||||
version of tmux, etc.
|
</keyboard-protocol>`, etc. they may or may not work, depending on the whims of
|
||||||
|
tmux's maintainer, your version of tmux, etc.
|
||||||
|
|
||||||
|
|
||||||
I opened and closed a lot of windows/tabs and top shows kitty's memory usage is very high?
|
I opened and closed a lot of windows/tabs and top shows kitty's memory usage is very high?
|
||||||
-------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
``top`` is not a good way to measure process memory usage. That is because on
|
:program:`top` is not a good way to measure process memory usage. That is
|
||||||
modern systems, when allocating memory to a process, the C library functions
|
because on modern systems, when allocating memory to a process, the C library
|
||||||
will typically allocate memory in large blocks, and give the process chunks of
|
functions will typically allocate memory in large blocks, and give the process
|
||||||
these blocks. When the process frees a chunk, the C library will not
|
chunks of these blocks. When the process frees a chunk, the C library will not
|
||||||
necessarily release the underlying block back to the OS. So even though the
|
necessarily release the underlying block back to the OS. So even though the
|
||||||
application has released the memory, ``top`` will still claim the process is
|
application has released the memory, :program:`top` will still claim the process
|
||||||
using it.
|
is using it.
|
||||||
|
|
||||||
To check for memory leaks, instead use a tool like ``valgrind``. Run::
|
To check for memory leaks, instead use a tool like `Valgrind
|
||||||
|
<https://valgrind.org/>`__. Run::
|
||||||
|
|
||||||
PYTHONMALLOC=malloc valgrind --tool=massif kitty
|
PYTHONMALLOC=malloc valgrind --tool=massif kitty
|
||||||
|
|
||||||
@@ -334,14 +409,40 @@ that window, maybe run yes or find again. Then quit kitty and run::
|
|||||||
You will see the allocations graph goes up when you opened the windows, then
|
You will see the allocations graph goes up when you opened the windows, then
|
||||||
goes back down when you closed them, indicating there were no memory leaks.
|
goes back down when you closed them, indicating there were no memory leaks.
|
||||||
|
|
||||||
For those interested, you can get a similar profile out of ``valgrind`` as you get
|
For those interested, you can get a similar profile out of :program:`valgrind`
|
||||||
with ``top`` by adding ``--pages-as-heap=yes`` then you will see that memory
|
as you get with :program:`top` by adding ``--pages-as-heap=yes`` then you will
|
||||||
allocated in malloc is not freed in free. This can be further refined if you
|
see that memory allocated in malloc is not freed in free. This can be further
|
||||||
use `glibc`` as your C library by setting the environment variable
|
refined if you use ``glibc`` as your C library by setting the environment
|
||||||
``MALLOC_MMAP_THRESHOLD_=64``. This will cause free to actually free memory
|
variable ``MALLOC_MMAP_THRESHOLD_=64``. This will cause free to actually free
|
||||||
allocated in sizes of more than 64 bytes. With this set, memory usage will
|
memory allocated in sizes of more than 64 bytes. With this set, memory usage
|
||||||
climb high, then fall when closing windows, but not fall all the way back. The
|
will climb high, then fall when closing windows, but not fall all the way back.
|
||||||
remaining used memory can be investigated using valgrind again, and it will
|
The remaining used memory can be investigated using valgrind again, and it will
|
||||||
come from arenas in the GPU drivers and the per thread arenas glibc's malloc
|
come from arenas in the GPU drivers and the per thread arenas glibc's malloc
|
||||||
maintains. These too allocate memory in large blocks and dont release it back
|
maintains. These too allocate memory in large blocks and don't release it back
|
||||||
to the OS immediately.
|
to the OS immediately.
|
||||||
|
|
||||||
|
|
||||||
|
Why does kitty sometimes start slowly on my Linux system?
|
||||||
|
-------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|kitty| takes no longer (within 100ms) to start than other similar GPU terminal
|
||||||
|
emulators, (and may be faster than some). If |kitty| occasionally takes a long
|
||||||
|
time to start, it could be a power management issue with the graphics card. On
|
||||||
|
a multi-GPU system (which many modern laptops are, having a power efficient GPU
|
||||||
|
that's built into the processor and a power hungry dedicated one that's usually
|
||||||
|
off), even if the answer of the GPU will only be "don't use me".
|
||||||
|
|
||||||
|
For example, if you have a system with an AMD CPU and an NVIDIA GPU, and you
|
||||||
|
know that you want to use the lower powered card to save battery life and
|
||||||
|
because kitty does not require a powerful GPU to function, you can choose not
|
||||||
|
to wake up the dedicated card, which has been reported on at least one system
|
||||||
|
(:iss:`4292`) to take ≈2 seconds, by running |kitty| as::
|
||||||
|
|
||||||
|
MESA_LOADER_DRIVER_OVERRIDE=radeonsi __EGL_VENDOR_LIBRARY_FILENAMES=/usr/share/glvnd/egl_vendor.d/50_mesa.json kitty
|
||||||
|
|
||||||
|
The correct command will depend on your situation and hardware.
|
||||||
|
``__EGL_VENDOR_LIBRARY_FILENAMES`` instructs the GL dispatch library to use
|
||||||
|
:file:`libEGL_mesa.so` and ignore :file:`libEGL_nvidia.so` also available on the
|
||||||
|
system, which will wake the NVIDIA card during device enumeration.
|
||||||
|
``MESA_LOADER_DRIVER_OVERRIDE`` also assures that Mesa won't offer any NVIDIA
|
||||||
|
card during enumeration, and will instead just use :file:`radeonsi_dri.so`.
|
||||||
|
|||||||
535
docs/file-transfer-protocol.rst
Normal file
@@ -0,0 +1,535 @@
|
|||||||
|
File transfer over the TTY
|
||||||
|
===============================
|
||||||
|
|
||||||
|
There are sometimes situations where the TTY is the only convenient pipe
|
||||||
|
between two connected systems, for example, nested SSH sessions, a serial
|
||||||
|
line, etc. In such scenarios, it is useful to be able to transfer files
|
||||||
|
over the TTY.
|
||||||
|
|
||||||
|
This protocol provides the ability to transfer regular files, directories and
|
||||||
|
links (both symbolic and hard) preserving most of their metadata. It can
|
||||||
|
optionally use compression and transmit only binary diffs to speed up
|
||||||
|
transfers. However, since all data is base64 encoded for transmission over the
|
||||||
|
TTY, this protocol will never be competitive with more direct file transfer
|
||||||
|
mechanisms.
|
||||||
|
|
||||||
|
Overall design
|
||||||
|
----------------
|
||||||
|
|
||||||
|
The basic design of this protocol is around transfer "sessions". Since
|
||||||
|
untrusted software should not be able to read/write to another machines
|
||||||
|
filesystem, a session must be approved by the user in the terminal emulator
|
||||||
|
before any actual data is transmitted, unless a :ref:`pre-shared password is
|
||||||
|
provided <bypass_auth>`.
|
||||||
|
|
||||||
|
There can be either send or receive sessions. In send sessions files are sent
|
||||||
|
from remote client to the terminal emulator and vice versa for receive sessions.
|
||||||
|
Every session basically consists of sending metadata for the files first and
|
||||||
|
then sending the actual data. The session is a series of commands, every command
|
||||||
|
carrying the session id (which should be a random unique-ish identifier, to
|
||||||
|
avoid conflicts). The session is bi-directional with commands going both to and
|
||||||
|
from the terminal emulator. Every command in a session also carries an
|
||||||
|
``action`` field that specifies what the command does. The remaining fields in
|
||||||
|
the command are dependent on the nature of the command.
|
||||||
|
|
||||||
|
Let's look at some simple examples of sessions to get a feel for the protocol.
|
||||||
|
|
||||||
|
|
||||||
|
Sending files to the computer running the terminal emulator
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
The client starts by sending a start send command::
|
||||||
|
|
||||||
|
→ action=send id=someid
|
||||||
|
|
||||||
|
It then waits for a status message from the terminal either
|
||||||
|
allowing the transfer or refusing it. Until this message is received
|
||||||
|
the client is not allowed to send any more commands for the session.
|
||||||
|
The terminal emulator should drop a session if it receives any commands
|
||||||
|
before sending an ``OK`` response. If the user accepts the transfer,
|
||||||
|
the terminal will send::
|
||||||
|
|
||||||
|
← action=status id=someid status=OK
|
||||||
|
|
||||||
|
Or if the transfer is refused::
|
||||||
|
|
||||||
|
← action=status id=someid status=EPERM:User refused the transfer
|
||||||
|
|
||||||
|
The client then sends one or more ``file`` commands with the metadata of the file it wants
|
||||||
|
to transfer::
|
||||||
|
|
||||||
|
→ action=file id=someid file_id=f1 name=/path/to/destination
|
||||||
|
→ action=file id=someid file_id=f2 name=/path/to/destination2 ftype=directory
|
||||||
|
|
||||||
|
The terminal responds with either ``OK`` for directories or ``STARTED`` for
|
||||||
|
files::
|
||||||
|
|
||||||
|
← action=status id=someid file_id=f1 status=STARTED
|
||||||
|
← action=status id=someid file_id=f2 status=OK
|
||||||
|
|
||||||
|
If there was an error with the file, for example, if the terminal does not have
|
||||||
|
permission to write to the specified location, it will instead respond with an
|
||||||
|
error, such as::
|
||||||
|
|
||||||
|
← action=status id=someid file_id=f1 status=EPERM:No permission
|
||||||
|
|
||||||
|
The client sends data for files using ``data`` commands. It does not need to
|
||||||
|
wait for the ``STARTED`` from the terminal for this, the terminal must discard data
|
||||||
|
for files that are not ``STARTED``. Data for a file is sent in individual
|
||||||
|
chunks of no larger than ``4096`` bytes. For example::
|
||||||
|
|
||||||
|
|
||||||
|
→ action=data id=someid file_id=f1 data=chunk of bytes
|
||||||
|
→ action=data id=someid file_id=f1 data=chunk of bytes
|
||||||
|
...
|
||||||
|
→ action=end_data id=someid file_id=f1 data=chunk of bytes
|
||||||
|
|
||||||
|
The sequence of data transmission for a file is ended with an ``end_data``
|
||||||
|
command. After each data packet is received the terminal replies with
|
||||||
|
an acknowledgement of the form::
|
||||||
|
|
||||||
|
← action=status id=someid file_id=f1 status=PROGRESS size=bytes written
|
||||||
|
|
||||||
|
After ``end_data`` the terminal replies with::
|
||||||
|
|
||||||
|
← action=status id=someid file_id=f1 status=OK size=bytes written
|
||||||
|
|
||||||
|
If an error occurs while writing the data, the terminal replies with an error
|
||||||
|
code and ignores further commands about that file, for example::
|
||||||
|
|
||||||
|
← action=status id=someid file_id=f1 status=EIO:Failed to write to file
|
||||||
|
|
||||||
|
Once the client has finished sending as many files as it wants to, it ends
|
||||||
|
the session with::
|
||||||
|
|
||||||
|
→ action=finish id=someid
|
||||||
|
|
||||||
|
At this point the terminal commits the session, applying file metadata,
|
||||||
|
creating links, etc. If any errors occur it responds with an error message,
|
||||||
|
such as::
|
||||||
|
|
||||||
|
← action=status id=someid status=Some error occurred
|
||||||
|
|
||||||
|
|
||||||
|
Receiving files from the computer running terminal emulator
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
The client starts by sending a start receive command::
|
||||||
|
|
||||||
|
→ action=receive id=someid size=num_of_paths
|
||||||
|
|
||||||
|
It then sends a list of ``num_of_paths`` paths it is interested in
|
||||||
|
receiving::
|
||||||
|
|
||||||
|
→ action=file id=someid file_id=f1 name=/some/path
|
||||||
|
→ action=file id=someid file_id=f2 name=/some/path2
|
||||||
|
...
|
||||||
|
|
||||||
|
The client must then wait for responses from the terminal emulator. It
|
||||||
|
is an error to send anymore commands to to the terminal until an ``OK``
|
||||||
|
response is received from the terminal. The terminal wait for the user to accept
|
||||||
|
the request. If accepted, it sends::
|
||||||
|
|
||||||
|
← action=status id=someid status=OK
|
||||||
|
|
||||||
|
If permission is denied it sends::
|
||||||
|
|
||||||
|
← action=status id=someid status=EPERM:User refused the transfer
|
||||||
|
|
||||||
|
The terminal then sends the metadata for all requested files. If any of them
|
||||||
|
are directories, it traverses the directories recursively, listing all files.
|
||||||
|
Note that symlinks must not be followed, but sent as symlinks::
|
||||||
|
|
||||||
|
← action=file id=someid file_id=f1 mtime=XXX permissions=XXX name=/absolute/path status=file_id1 size=size_in_bytes file_type=type parent=file_id of parent
|
||||||
|
← action=file id=someid file_id=f1 mtime=XXX permissions=XXX name=/absolute/path2 status=file_id2 size=size_in_bytes file_type=type parent=file_id of parent
|
||||||
|
...
|
||||||
|
|
||||||
|
Here the ``file_id`` field is set to the ``file_id`` value sent from the client
|
||||||
|
and the ``status`` field is set to the actual file id for each file. This is
|
||||||
|
because a file query sent from the client can result in multiple actual files if
|
||||||
|
it is a directory. The ``parent`` field is the actual ``file_id`` of the directory
|
||||||
|
containing this file and is set for entries that are generated from client
|
||||||
|
requests that match directories. This allows the client to build an unambiguous picture
|
||||||
|
of the file tree.
|
||||||
|
|
||||||
|
Once all the files are listed, the terminal sends an ``OK`` response that also
|
||||||
|
specifies the absolute path to the home directory for the user account running
|
||||||
|
the terminal::
|
||||||
|
|
||||||
|
← action=status id=someid status=OK name=/path/to/home
|
||||||
|
|
||||||
|
If an error occurs while listing any of the files asked for by the client,
|
||||||
|
the terminal will send an error response like::
|
||||||
|
|
||||||
|
← action=status id=someid file_id=f1 status=ENOENT: Does not exist
|
||||||
|
|
||||||
|
Here, ``file_id`` is the same as was sent by the client in its initial query.
|
||||||
|
|
||||||
|
Now, the client can send requests for file data using the paths sent by the
|
||||||
|
terminal emulator::
|
||||||
|
|
||||||
|
→ action=file id=someid file_id=f1 name=/some/path
|
||||||
|
...
|
||||||
|
|
||||||
|
The terminal emulator replies with the data for the files, as a sequence of
|
||||||
|
``data`` commands each with a chunk of data no larger than ``4096`` bytes,
|
||||||
|
for each file (the terminal emulator should send the data for
|
||||||
|
one file at a time)::
|
||||||
|
|
||||||
|
|
||||||
|
← action=data id=someid file_id=f1 data=chunk of bytes
|
||||||
|
...
|
||||||
|
← action=end_data id=someid file_id=f1 data=chunk of bytes
|
||||||
|
|
||||||
|
If any errors occur reading file data, the terminal emulator sends an error
|
||||||
|
message for the file, for example::
|
||||||
|
|
||||||
|
← action=status id=someid file_id=f1 status=EIO:Could not read
|
||||||
|
|
||||||
|
Once the client is done reading data for all the files it expects, it
|
||||||
|
terminates the session with::
|
||||||
|
|
||||||
|
→ action=finished id=someid
|
||||||
|
|
||||||
|
Canceling a session
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
A client can decide to cancel a session at any time (for example if the user
|
||||||
|
presses :kbd:`ctrl+c`). To cancel a session it sends a ``cancel`` action to the
|
||||||
|
terminal emulator::
|
||||||
|
|
||||||
|
→ action=cancel id=someid
|
||||||
|
|
||||||
|
The terminal emulator drops the session and sends a cancel acknowledgement::
|
||||||
|
|
||||||
|
← action=status id=someid status=CANCELED
|
||||||
|
|
||||||
|
The client **must** wait for the canceled response from the emulator discarding
|
||||||
|
any other responses till the cancel is received. If it does not wait, after
|
||||||
|
it quits the responses might end up being printed to screen.
|
||||||
|
|
||||||
|
Quieting responses from the terminal
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
The above protocol includes lots of messages from the terminal acknowledging
|
||||||
|
receipt of data, granting permission etc., acknowledging cancel requests, etc.
|
||||||
|
For extremely simple clients like shell scripts, it might be useful to suppress
|
||||||
|
these responses, which can be done by adding the ``quiet`` key to the start
|
||||||
|
session command::
|
||||||
|
|
||||||
|
→ action=send id=someid quiet=1
|
||||||
|
|
||||||
|
The key can take the values ``1`` - meaning suppress acknowledgement responses
|
||||||
|
or ``2`` - meaning suppress all responses including errors. Only actual data
|
||||||
|
responses are sent. Note that in particular this means acknowledgement of
|
||||||
|
permission for the transfer to go ahead is suppressed, so this is typically
|
||||||
|
useful only with :ref:`bypass_auth`.
|
||||||
|
|
||||||
|
.. _file_metadata:
|
||||||
|
|
||||||
|
File metadata
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
File metadata includes file paths, permissions and modification times. They are
|
||||||
|
somewhat tricky as different operating systems support different kinds of
|
||||||
|
metadata. This specification defines a common minimum set which should work
|
||||||
|
across most operating systems.
|
||||||
|
|
||||||
|
File paths
|
||||||
|
File paths must be valid UTF-8 encoded POSIX paths (i.e. using the forward slash
|
||||||
|
``/`` as a separator). Linux systems allow non UTF-8 file paths, these
|
||||||
|
are not supported. A leading ``~/`` means a path is relative to the
|
||||||
|
``HOME`` directory. All path must be either absolute (i.e. with a leading
|
||||||
|
``/``) or relative to the HOME directory. Individual components of the
|
||||||
|
path must be no longer than 255 UTF-8 bytes. Total path length must be no
|
||||||
|
more than 4096 bytes. Paths from Windows systems must use the forward slash
|
||||||
|
as the separator, the first path component must be the drive letter with a
|
||||||
|
colon. For example: :file:`C:\some\file.txt` is represented as
|
||||||
|
:file:`/C:/some/file.txt`. For maximum portability, the following
|
||||||
|
characters *should* be omitted from paths (however implementations are free
|
||||||
|
to try to support them returning errors for non-representable paths)::
|
||||||
|
|
||||||
|
\ * : < > ? | /
|
||||||
|
|
||||||
|
File modification times
|
||||||
|
Must be represented as the number of nanoseconds since the UNIX epoch. An
|
||||||
|
individual file system may not store file metadata with this level of
|
||||||
|
accuracy in which case it should use the closest possible approximation.
|
||||||
|
|
||||||
|
File permissions
|
||||||
|
Represented as a number with the usual UNIX read, write and execute bits.
|
||||||
|
In addition, the sticky, set-group-id and set-user-id bits may be present.
|
||||||
|
Implementations should make a best effort to preserve as many bits as
|
||||||
|
possible. On Windows, there is only a read-only bit. When reading file
|
||||||
|
metadata all the ``WRITE`` bits should be set if the read only bit is clear
|
||||||
|
and cleared if it is set. When writing files, the read-only bit should be
|
||||||
|
set if the bit indicating write permission for the user is clear. The other
|
||||||
|
UNIX bits must be ignored when writing. When reading, all the ``READ`` bits
|
||||||
|
should always be set and all the ``EXECUTE`` bits should be set if the file is
|
||||||
|
directly executable by the Windows Operating system. There is no attempt to
|
||||||
|
map Window's ACLs to permission bits.
|
||||||
|
|
||||||
|
|
||||||
|
Symbolic and hard links
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
Symbolic and hard links can be preserved by this protocol.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
In the following when target paths of symlinks are sent as actual paths, they must be
|
||||||
|
encoded in the same way as discussed in :ref:`file_metadata`. It is up to
|
||||||
|
the receiving side to translate them into appropriate paths for the local
|
||||||
|
operating system. This may not always be possible, in which case either the
|
||||||
|
symlink should not be created or a broken symlink should be created.
|
||||||
|
|
||||||
|
|
||||||
|
Sending links to the terminal emulator
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
When sending files to the terminal emulator, the file command has the form::
|
||||||
|
|
||||||
|
→ action=file id=someid file_id=f1 name=/path/to/link file_type=link
|
||||||
|
→ action=file id=someid file_id=f2 name=/path/to/symlink file_type=symlink
|
||||||
|
|
||||||
|
Then, when the client is sending data for the files, for hardlinks, the data
|
||||||
|
will be the ``file_id`` of the target file (assuming the target file is also
|
||||||
|
being transmitted, otherwise the hard link should be transmitted as a plain
|
||||||
|
file)::
|
||||||
|
|
||||||
|
→ action=end_data id=someid file_id=f1 data=target_file_id_encoded_as_utf8
|
||||||
|
|
||||||
|
For symbolic links, the data is a little more complex. If the symbolic link is
|
||||||
|
to a destination being transmitted, the data has the form::
|
||||||
|
|
||||||
|
→ action=end_data id=someid file_id=f1 data=fid:target_file_id_encoded_as_utf8
|
||||||
|
→ action=end_data id=someid file_id=f1 data=fid_abs:target_file_id_encoded_as_utf8
|
||||||
|
|
||||||
|
The ``fid_abs`` form is used if the symlink uses an absolute path, ``fid`` if
|
||||||
|
it uses a relative path. If the symlink is to a destination that is not being
|
||||||
|
transmitted, then the prefix ``path:`` and the actual path in the symlink is
|
||||||
|
transmitted.
|
||||||
|
|
||||||
|
Receiving links from the terminal emulator
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
When receiving files from the terminal emulator, link data is transmitted in
|
||||||
|
two parts. First when the emulator sends the initial file listing to the
|
||||||
|
client, the ``file_type`` is set to the link type and the ``data`` field is set
|
||||||
|
to file_id of the target file if the target file is included in the listing.
|
||||||
|
For example::
|
||||||
|
|
||||||
|
← action=file id=someid file_id=f1 status=file_id1 ...
|
||||||
|
← action=file id=someid file_id=f1 status=file_id2 file_type=symlink data=file_id1 ...
|
||||||
|
|
||||||
|
Here the rest of the metadata has been left out for clarity. Notice that the
|
||||||
|
second file is symlink whose ``data`` field is set to the file id of the first
|
||||||
|
file (the value of the ``status`` field of the first file). The same technique
|
||||||
|
is used for hard links.
|
||||||
|
|
||||||
|
The client should not request data for hard links, instead creating them
|
||||||
|
directly after transmission is complete. For symbolic links the terminal
|
||||||
|
must send the actual symbolic link target as a UTF-8 encoded path in the
|
||||||
|
data field. The client can use this path either as-is (when the target is not
|
||||||
|
a transmitted file) or to decide whether to create the symlink with a relative
|
||||||
|
or absolute path when the target is a transmitted file.
|
||||||
|
|
||||||
|
|
||||||
|
Transmitting binary deltas
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
Repeated transfer of large files that have only changed a little between
|
||||||
|
the receiving and sending side can be sped up significantly by transmitting
|
||||||
|
binary deltas of only the changed portions. This protocol has built-in support
|
||||||
|
for doing that. This support uses the `rsync algorithm
|
||||||
|
<https://github.com/librsync/librsync>`__. In this algorithm first the
|
||||||
|
receiving side sends a file signature that contains hashes of blocks
|
||||||
|
in the file. Then the sending side sends only those blocks that have changed.
|
||||||
|
The receiving side applies these deltas to the file to update it till it matches
|
||||||
|
the file on the sending side.
|
||||||
|
|
||||||
|
The modification to the basic protocol consists of setting the
|
||||||
|
``transmission_type`` key to ``rsync`` when requesting a file. This triggers
|
||||||
|
transmission of signatures and deltas instead of file data. The details are
|
||||||
|
different for sending and receiving.
|
||||||
|
|
||||||
|
Sending to the terminal emulator
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
When sending the metadata of the file it wants to transfer, the client adds the
|
||||||
|
``transmission_type`` key::
|
||||||
|
|
||||||
|
→ action=file id=someid file_id=f1 name=/path/to/destination transmission_type=rsync
|
||||||
|
|
||||||
|
The ``STARTED`` response from the terminal will have ``transmission_type`` set
|
||||||
|
to ``rsync`` if the file exists and the terminal is able to send signature data::
|
||||||
|
|
||||||
|
← action=status id=someid file_id=f1 status=STARTED transmission_type=rsync
|
||||||
|
|
||||||
|
The terminal then transmits the signature using ``data`` commands::
|
||||||
|
|
||||||
|
← action=data id=someid file_id=f1 data=...
|
||||||
|
...
|
||||||
|
← action=end_data id=someid file_id=f1 data=...
|
||||||
|
|
||||||
|
Once the client receives and processes the full signature, it transmits the
|
||||||
|
file delta to the terminal as ``data`` commands::
|
||||||
|
|
||||||
|
→ action=data id=someid file_id=f1 data=...
|
||||||
|
→ action=data id=someid file_id=f1 data=...
|
||||||
|
...
|
||||||
|
→ action=end_data id=someid file_id=f1 data=...
|
||||||
|
|
||||||
|
The terminal then uses this delta to update the file.
|
||||||
|
|
||||||
|
Receiving from the terminal emulator
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
When the client requests file data from the terminal emulator, it can
|
||||||
|
add the ``transmission_type=rsync`` key to indicate it will be sending
|
||||||
|
a signature for that file::
|
||||||
|
|
||||||
|
→ action=file id=someid file_id=f1 name=/some/path transmission_type=rsync
|
||||||
|
|
||||||
|
The client then sends the signature using ``data`` commands::
|
||||||
|
|
||||||
|
→ action=data id=someid file_id=f1 data=...
|
||||||
|
...
|
||||||
|
→ action=end_data id=someid file_id=f1 data=...
|
||||||
|
|
||||||
|
After receiving the signature the terminal replies with the delta as a series
|
||||||
|
of ``data`` commands::
|
||||||
|
|
||||||
|
← action=data id=someid file_id=f1 data=...
|
||||||
|
...
|
||||||
|
← action=end_data id=someid file_id=f1 data=...
|
||||||
|
|
||||||
|
The client then uses this delta to update the file.
|
||||||
|
|
||||||
|
The format of signatures and deltas
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
These come from `librsync <https://github.com/librsync/librsync>`__. If this
|
||||||
|
specification gains wider adoption, these formats should be documented here.
|
||||||
|
|
||||||
|
Compression
|
||||||
|
--------------
|
||||||
|
|
||||||
|
Individual files can be transmitted compressed if needed.
|
||||||
|
Currently, only :rfc:`1950` ZLIB based deflate compression is
|
||||||
|
supported, which is specified using the ``compression=zlib`` key when
|
||||||
|
requesting a file. For example when sending files to the terminal emulator,
|
||||||
|
when sending the file metadata the ``compression`` key can also be
|
||||||
|
specified::
|
||||||
|
|
||||||
|
→ action=file id=someid file_id=f1 name=/path/to/destination compression=zlib
|
||||||
|
|
||||||
|
Similarly when receiving files from the terminal emulator, the final file
|
||||||
|
command that the client sends to the terminal requesting the start of the
|
||||||
|
transfer of data for the file can include the ``compression`` key::
|
||||||
|
|
||||||
|
→ action=file id=someid file_id=f1 name=/some/path compression=zlib
|
||||||
|
|
||||||
|
.. _bypass_auth:
|
||||||
|
|
||||||
|
Bypassing explicit user authorization
|
||||||
|
------------------------------------------
|
||||||
|
|
||||||
|
In order to bypass the requirement of interactive user authentication,
|
||||||
|
this protocol has the ability to use a pre-shared secret (password).
|
||||||
|
When initiating a transfer session the client sends a hash of the password and
|
||||||
|
the session id::
|
||||||
|
|
||||||
|
→ action=send id=someid bypass=sha256:hash_value
|
||||||
|
|
||||||
|
For example, suppose that the session id is ``mysession`` and the
|
||||||
|
shared secret is ``mypassword``. Then the value of the ``bypass``
|
||||||
|
key above is ``sha256:SHA256("mysession" + ";" + "mypassword")``, which
|
||||||
|
is::
|
||||||
|
|
||||||
|
→ action=send id=mysession bypass=sha256:192bd215915eeaa8c2b2a4c0f8f851826497d12b30036d8b5b1b4fc4411caf2c
|
||||||
|
|
||||||
|
The value of ``bypass`` is of the form ``hash_function_name : hash_value``
|
||||||
|
(without spaces). Currently, only the SHA256 hash function is supported.
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
Hashing does not effectively hide the value of the password. So this
|
||||||
|
functionality should only be used in secure/trusted contexts. While there
|
||||||
|
exist hash functions harder to compute than SHA256, they are unsuitable as
|
||||||
|
they will introduce a lot of latency to starting a session and in any case
|
||||||
|
there is no mathematical proof that **any** hash function is not brute-forceable.
|
||||||
|
|
||||||
|
Encoding of transfer commands as escape codes
|
||||||
|
------------------------------------------------
|
||||||
|
|
||||||
|
Transfer commands are encoded as ``OSC`` escape codes of the form::
|
||||||
|
|
||||||
|
<OSC> 5113 ; key=value ; key=value ... <ST>
|
||||||
|
|
||||||
|
Here ``OSC`` is the bytes ``0x1b 0x5d`` and ``ST`` is the bytes
|
||||||
|
``0x1b 0x5c``. Keys are words containing only the characters ``[a-zA-Z0-9_]``
|
||||||
|
and ``value`` is arbitrary data, whose encoding is dependent on the value of
|
||||||
|
``key``. Unknown keys **must** be ignored when decoding a command.
|
||||||
|
The number ``5113`` is a constant and is unused by any known OSC codes. It is
|
||||||
|
the numeralization of the word ``file``.
|
||||||
|
|
||||||
|
|
||||||
|
.. table:: The keys and value types for this protocol
|
||||||
|
:align: left
|
||||||
|
|
||||||
|
================= ======== ============== =======================================================================
|
||||||
|
Key Key name Value type Notes
|
||||||
|
================= ======== ============== =======================================================================
|
||||||
|
action ac enum send, file, data, end_data, receive, cancel, status, finish
|
||||||
|
compression zip enum none, zlib
|
||||||
|
file_type ft enum regular, directory, symlink, link
|
||||||
|
transmission_type tt enum simple, rsync
|
||||||
|
id id safe_string A unique-ish value, to avoid collisions
|
||||||
|
file_id fid safe_string Must be unique per file in a session
|
||||||
|
bypass pw safe_string hash of the bypass password and the session id
|
||||||
|
quiet q integer 0 - verbose, 1 - only errors, 2 - totally silent
|
||||||
|
mtime mod integer the modification time of file in nanoseconds since the UNIX epoch
|
||||||
|
permissions prm integer the UNIX file permissions bits
|
||||||
|
size sz integer size in bytes
|
||||||
|
name n base64_string The path to a file
|
||||||
|
status st base64_string Status messages
|
||||||
|
parent pr safe_string The file id of the parent directory
|
||||||
|
data d base64_bytes Binary data
|
||||||
|
================= ======== ============== =======================================================================
|
||||||
|
|
||||||
|
The ``Key name`` is the actual serialized name of the key sent in the escape
|
||||||
|
code. So for example, ``permissions=123`` is serialized as ``prm=123``. This
|
||||||
|
is done to reduce overhead.
|
||||||
|
|
||||||
|
The value types are:
|
||||||
|
|
||||||
|
enum
|
||||||
|
One from a permitted set of values, for example::
|
||||||
|
|
||||||
|
ac=file
|
||||||
|
|
||||||
|
safe_string
|
||||||
|
A string consisting only of characters from the set ``[0-9a-zA-Z_:.,/!@#$%^&*()[]{}~`?"'\\|=+-]``
|
||||||
|
Note that the semi-colon is missing from this set.
|
||||||
|
|
||||||
|
integer
|
||||||
|
A base-10 number composed of the characters ``[0-9]`` with a possible
|
||||||
|
leading ``-`` sign
|
||||||
|
|
||||||
|
base64_string
|
||||||
|
A base64 encoded UTF-8 string using the standard base64 encoding
|
||||||
|
|
||||||
|
base64_bytes
|
||||||
|
Binary data encoded using the standard base64 encoding
|
||||||
|
|
||||||
|
|
||||||
|
An example of serializing an escape code is shown below::
|
||||||
|
|
||||||
|
action=send id=test name=somefile size=3 data=01 02 03
|
||||||
|
|
||||||
|
becomes::
|
||||||
|
|
||||||
|
<OSC> 5113 ; ac=send ; id=test ; n=c29tZWZpbGU= ; sz=3 ; d=AQID <ST>
|
||||||
|
|
||||||
|
Here ``c29tZWZpbGU`` is the base64 encoded form of somefile and ``AQID`` is the
|
||||||
|
base64 encoded form of the bytes ``0x01 0x02 0x03``. The spaces in the encoded
|
||||||
|
form are present for clarity and should be ignored.
|
||||||
@@ -30,14 +30,20 @@ Glossary
|
|||||||
overlay
|
overlay
|
||||||
An *overlay window* is a :term:`kitty window <window>` that is placed on
|
An *overlay window* is a :term:`kitty window <window>` that is placed on
|
||||||
top of an existing kitty window, entirely covering it. Overlays are used
|
top of an existing kitty window, entirely covering it. Overlays are used
|
||||||
throught kitty, for example, to display the :ref:`the scrollback buffer <scrollback>`,
|
throughout kitty, for example, to display the :ref:`the scrollback buffer <scrollback>`,
|
||||||
to display :doc:`hints </kittens/hints>`, for :doc:`unicode input
|
to display :doc:`hints </kittens/hints>`, for :doc:`unicode input
|
||||||
</kittens/unicode-input>` etc.
|
</kittens/unicode_input>` etc. Normal overlays are meant for short
|
||||||
|
duration popups and so are not considered the :italic:`active window`
|
||||||
|
when determining the current working directory or getting input text for
|
||||||
|
kittens, launch commands, etc. To create an overlay considered as a
|
||||||
|
:italic:`main window` use the :code:`overlay-main` argument to
|
||||||
|
:doc:`launch`.
|
||||||
|
|
||||||
hyperlinks
|
hyperlinks
|
||||||
Terminals can have hyperlinks, just like the internet. In kitty you can
|
Terminals can have hyperlinks, just like the internet. In kitty you can
|
||||||
:doc:`control exactly what happens <open_actions>` when clicking on a
|
:doc:`control exactly what happens <open_actions>` when clicking on a
|
||||||
hyperlink, based on the type of link and its URL.
|
hyperlink, based on the type of link and its URL. See also `Hyperlinks in terminal
|
||||||
|
emulators <https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda>`__.
|
||||||
|
|
||||||
.. _env_vars:
|
.. _env_vars:
|
||||||
|
|
||||||
@@ -45,6 +51,7 @@ Environment variables
|
|||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
Variables that influence kitty behavior
|
Variables that influence kitty behavior
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
.. envvar:: KITTY_CONFIG_DIRECTORY
|
.. envvar:: KITTY_CONFIG_DIRECTORY
|
||||||
|
|
||||||
@@ -52,71 +59,156 @@ Variables that influence kitty behavior
|
|||||||
files. Defaults to :file:`~/.config/kitty`. For full details of the config
|
files. Defaults to :file:`~/.config/kitty`. For full details of the config
|
||||||
directory lookup mechanism see, :option:`kitty --config`.
|
directory lookup mechanism see, :option:`kitty --config`.
|
||||||
|
|
||||||
|
.. envvar:: KITTY_CACHE_DIRECTORY
|
||||||
|
|
||||||
|
Controls where kitty stores cache files. Defaults to :file:`~/.cache/kitty`
|
||||||
|
or :file:`~/Library/Caches/kitty` on macOS.
|
||||||
|
|
||||||
|
.. envvar:: KITTY_RUNTIME_DIRECTORY
|
||||||
|
|
||||||
|
Controls where kitty stores runtime files like sockets. Defaults to
|
||||||
|
the :code:`XDG_RUNTIME_DIR` environment variable if that is defined
|
||||||
|
otherwise the run directory inside the kitty cache directory is used.
|
||||||
|
|
||||||
.. envvar:: VISUAL
|
.. envvar:: VISUAL
|
||||||
|
|
||||||
The terminal editor (such as ``vi`` or ``nano``) kitty uses, when, for
|
The terminal based text editor (such as :program:`vi` or :program:`nano`)
|
||||||
instance, opening :file:`kitty.conf` in response to :sc:`edit_config_file`.
|
kitty uses, when, for instance, opening :file:`kitty.conf` in response to
|
||||||
|
:sc:`edit_config_file`.
|
||||||
|
|
||||||
.. envvar:: EDITOR
|
.. envvar:: EDITOR
|
||||||
|
|
||||||
Same as :envvar:`VISUAL`. Used if :envvar:`VISUAL` is not set.
|
Same as :envvar:`VISUAL`. Used if :envvar:`VISUAL` is not set.
|
||||||
|
|
||||||
|
.. envvar:: GLFW_IM_MODULE
|
||||||
|
|
||||||
|
Set this to ``ibus`` to enable support for IME under X11.
|
||||||
|
|
||||||
|
.. envvar:: KITTY_WAYLAND_DETECT_MODIFIERS
|
||||||
|
|
||||||
|
When set to a non-empty value, kitty attempts to autodiscover XKB modifiers
|
||||||
|
under Wayland. This is useful if using non-standard modifers like hyper. It
|
||||||
|
is possible for the autodiscovery to fail; the default Wayland XKB mappings
|
||||||
|
are used in this case. See :pull:`3943` for details.
|
||||||
|
|
||||||
|
.. envvar:: SSH_ASKPASS
|
||||||
|
|
||||||
|
Specify the program for SSH to ask for passwords. When this is set, :doc:`ssh
|
||||||
|
kitten </kittens/ssh>` will use this environment variable by default. See
|
||||||
|
:opt:`askpass <kitten-ssh.askpass>` for details.
|
||||||
|
|
||||||
|
.. envvar:: KITTY_CLONE_SOURCE_CODE
|
||||||
|
|
||||||
|
Set this to some shell code that will be executed in the cloned window with
|
||||||
|
:code:`eval` when :ref:`clone-in-kitty <clone_shell>` is used.
|
||||||
|
|
||||||
|
.. envvar:: KITTY_CLONE_SOURCE_PATH
|
||||||
|
|
||||||
|
Set this to the path of a file that will be sourced in the cloned window when
|
||||||
|
:ref:`clone-in-kitty <clone_shell>` is used.
|
||||||
|
|
||||||
|
.. envvar:: KITTY_DEVELOP_FROM
|
||||||
|
|
||||||
|
Set this to the directory path of the kitty source code and its Python code
|
||||||
|
will be loaded from there. Only works with official binary builds.
|
||||||
|
|
||||||
|
.. envvar:: KITTY_RC_PASSWORD
|
||||||
|
|
||||||
|
Set this to a pass phrase to use the ``kitty @`` remote control command with
|
||||||
|
:opt:`remote_control_password`.
|
||||||
|
|
||||||
|
|
||||||
Variables that kitty sets when running child programs
|
Variables that kitty sets when running child programs
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. envvar:: LANG
|
||||||
|
|
||||||
|
This is only set on macOS. If the country and language from the macOS user
|
||||||
|
settings form an invalid locale, it will be set to :code:`en_US.UTF-8`.
|
||||||
|
|
||||||
|
.. envvar:: PATH
|
||||||
|
|
||||||
|
kitty prepends itself to the PATH of its own environment to ensure the
|
||||||
|
functions calling :program:`kitty` will work properly.
|
||||||
|
|
||||||
.. envvar:: KITTY_WINDOW_ID
|
.. envvar:: KITTY_WINDOW_ID
|
||||||
|
|
||||||
An integer that is the id for the kitty :term:`window` the program is running in.
|
An integer that is the id for the kitty :term:`window` the program is running in.
|
||||||
Can be used with the :doc:`kitty remote control facility <remote-control>`.
|
Can be used with the :doc:`kitty remote control facility <remote-control>`.
|
||||||
|
|
||||||
|
.. envvar:: KITTY_PID
|
||||||
|
|
||||||
|
An integer that is the process id for the kitty process in which the program
|
||||||
|
is running. Allows programs to tell kitty to reload its config by sending it
|
||||||
|
the SIGUSR1 signal.
|
||||||
|
|
||||||
|
.. envvar:: KITTY_PUBLIC_KEY
|
||||||
|
|
||||||
|
A public key that programs can use to communicate securely with kitty using
|
||||||
|
the remote control protocol. The format is: :code:`protocol:key data`.
|
||||||
|
|
||||||
.. envvar:: WINDOWID
|
.. envvar:: WINDOWID
|
||||||
|
|
||||||
The id for the :term:`OS Window <os_window>` the program is running in. Only available
|
The id for the :term:`OS Window <os_window>` the program is running in. Only available
|
||||||
on platforms that have ids for their windows, such as X11 and macOS.
|
on platforms that have ids for their windows, such as X11 and macOS.
|
||||||
|
|
||||||
|
|
||||||
.. envvar:: TERM
|
.. envvar:: TERM
|
||||||
|
|
||||||
The name of the terminal, defaults to ``xterm-kitty``. See :opt:`term`.
|
The name of the terminal, defaults to ``xterm-kitty``. See :opt:`term`.
|
||||||
|
|
||||||
|
|
||||||
.. envvar:: TERMINFO
|
.. envvar:: TERMINFO
|
||||||
|
|
||||||
Path to a directory containing the kitty terminfo database.
|
Path to a directory containing the kitty terminfo database.
|
||||||
|
|
||||||
|
.. envvar:: KITTY_INSTALLATION_DIR
|
||||||
|
|
||||||
|
Path to the kitty installation directory.
|
||||||
|
|
||||||
.. envvar:: COLORTERM
|
.. envvar:: COLORTERM
|
||||||
|
|
||||||
Set to the value ``truecolor`` to indicate that kitty supports 16 million
|
Set to the value ``truecolor`` to indicate that kitty supports 16 million
|
||||||
colors.
|
colors.
|
||||||
|
|
||||||
|
|
||||||
.. envvar:: KITTY_LISTEN_ON
|
.. envvar:: KITTY_LISTEN_ON
|
||||||
|
|
||||||
Set when the :doc:`remote control <remote-control>` facility is enabled and
|
Set when the :doc:`remote control <remote-control>` facility is enabled and
|
||||||
the a socket is used for control via :option:`kitty --listen-on` or :opt:`listen_on`.
|
the a socket is used for control via :option:`kitty --listen-on` or :opt:`listen_on`.
|
||||||
Contains the path to the socket. Avoids needs to use :option:`kitty @ --to` when
|
Contains the path to the socket. Avoid the need to use :option:`kitty @ --to` when
|
||||||
issuing remote control commands.
|
issuing remote control commands.
|
||||||
|
|
||||||
|
|
||||||
.. envvar:: KITTY_PIPE_DATA
|
.. envvar:: KITTY_PIPE_DATA
|
||||||
|
|
||||||
Set to data describing the layout of the screen when running child
|
Set to data describing the layout of the screen when running child
|
||||||
programs using :option:`launch --stdin-source` with the contents of the
|
programs using :option:`launch --stdin-source` with the contents of the
|
||||||
screen/scrollback piped to them.
|
screen/scrollback piped to them.
|
||||||
|
|
||||||
|
|
||||||
.. envvar:: KITTY_CHILD_CMDLINE
|
.. envvar:: KITTY_CHILD_CMDLINE
|
||||||
|
|
||||||
Set to the command line of the child process running in the kitty
|
Set to the command line of the child process running in the kitty
|
||||||
window when calling the notification callback program on terminal bell, see
|
window when calling the notification callback program on terminal bell, see
|
||||||
:opt:`command_on_bell`.
|
:opt:`command_on_bell`.
|
||||||
|
|
||||||
|
|
||||||
.. envvar:: KITTY_COMMON_OPTS
|
.. envvar:: KITTY_COMMON_OPTS
|
||||||
|
|
||||||
Set with the values of some common kitty options when running
|
Set with the values of some common kitty options when running
|
||||||
kittens, so kittens can use them without needing to load kitty.conf.
|
kittens, so kittens can use them without needing to load :file:`kitty.conf`.
|
||||||
|
|
||||||
|
.. envvar:: KITTY_SHELL_INTEGRATION
|
||||||
|
|
||||||
|
Set when enabling :ref:`shell_integration`. It is automatically removed by
|
||||||
|
the shell integration scripts.
|
||||||
|
|
||||||
|
.. envvar:: ZDOTDIR
|
||||||
|
|
||||||
|
Set when enabling :ref:`shell_integration` with :program:`zsh`, allowing
|
||||||
|
:program:`zsh` to automatically load the integration script.
|
||||||
|
|
||||||
|
.. envvar:: XDG_DATA_DIRS
|
||||||
|
|
||||||
|
Set when enabling :ref:`shell_integration` with :program:`fish`, allowing
|
||||||
|
:program:`fish` to automatically load the integration script.
|
||||||
|
|
||||||
|
.. envvar:: ENV
|
||||||
|
|
||||||
|
Set when enabling :ref:`shell_integration` with :program:`bash`, allowing
|
||||||
|
:program:`bash` to automatically load the integration script.
|
||||||
|
|||||||
@@ -12,8 +12,7 @@ emulator. The major design goals are:
|
|||||||
below as well as above the text, with alpha blending. The graphics should also scroll with the text, automatically.
|
below as well as above the text, with alpha blending. The graphics should also scroll with the text, automatically.
|
||||||
* Should use optimizations when the client is running on the same computer as the terminal emulator.
|
* Should use optimizations when the client is running on the same computer as the terminal emulator.
|
||||||
|
|
||||||
For some discussion regarding the design choices, see `#33
|
For some discussion regarding the design choices, see :iss:`33`.
|
||||||
<https://github.com/kovidgoyal/kitty/issues/33>`_.
|
|
||||||
|
|
||||||
To see a quick demo, inside a |kitty| terminal run::
|
To see a quick demo, inside a |kitty| terminal run::
|
||||||
|
|
||||||
@@ -32,6 +31,7 @@ Some programs and libraries that use the kitty graphics protocol:
|
|||||||
* `ranger <https://github.com/ranger/ranger>`_ - a terminal file manager, with
|
* `ranger <https://github.com/ranger/ranger>`_ - a terminal file manager, with
|
||||||
image previews, see this `PR <https://github.com/ranger/ranger/pull/1077>`_
|
image previews, see this `PR <https://github.com/ranger/ranger/pull/1077>`_
|
||||||
* :doc:`kitty-diff <kittens/diff>` - a side-by-side terminal diff program with support for images
|
* :doc:`kitty-diff <kittens/diff>` - a side-by-side terminal diff program with support for images
|
||||||
|
* `tpix <https://github.com/jesvedberg/tpix>`_ - a statically compiled binary that can be used to display images and easily installed on remote servers without root access
|
||||||
* `pixcat <https://github.com/mirukana/pixcat>`_ - a third party CLI and python library that wraps the graphics protocol
|
* `pixcat <https://github.com/mirukana/pixcat>`_ - a third party CLI and python library that wraps the graphics protocol
|
||||||
* `neofetch <https://github.com/dylanaraps/neofetch>`_ - A command line system
|
* `neofetch <https://github.com/dylanaraps/neofetch>`_ - A command line system
|
||||||
information tool
|
information tool
|
||||||
@@ -40,7 +40,16 @@ Some programs and libraries that use the kitty graphics protocol:
|
|||||||
* `ctx.graphics <https://ctx.graphics/>`_ - Library for drawing graphics
|
* `ctx.graphics <https://ctx.graphics/>`_ - Library for drawing graphics
|
||||||
* `timg <https://github.com/hzeller/timg>`_ - a terminal image and video viewer
|
* `timg <https://github.com/hzeller/timg>`_ - a terminal image and video viewer
|
||||||
* `notcurses <https://github.com/dankamongmen/notcurses>`_ - C library for terminal graphics with bindings for C++, Rust and Python
|
* `notcurses <https://github.com/dankamongmen/notcurses>`_ - C library for terminal graphics with bindings for C++, Rust and Python
|
||||||
* `rasterm <https://github.com/BourgeoisBear/rasterm>`_ - Go library to display images in the the terminal
|
* `rasterm <https://github.com/BourgeoisBear/rasterm>`_ - Go library to display images in the terminal
|
||||||
|
* `chafa <https://github.com/hpjansson/chafa>`_ - a terminal image viewer
|
||||||
|
* `hologram.nvim <https://github.com/edluffy/hologram.nvim>`_ - view images inside nvim
|
||||||
|
* `term-image <https://github.com/AnonymouX47/term-image>`_ - A Python library, CLI and TUI to display and browse images in the terminal
|
||||||
|
|
||||||
|
Other terminals that have implemented the graphics protocol:
|
||||||
|
|
||||||
|
* `WezTerm <https://github.com/wez/wezterm/issues/986>`_
|
||||||
|
* `Konsole <https://invent.kde.org/utilities/konsole/-/merge_requests/594>`_
|
||||||
|
* `wayst <https://github.com/91861/wayst>`_
|
||||||
|
|
||||||
|
|
||||||
Getting the window size
|
Getting the window size
|
||||||
@@ -103,7 +112,7 @@ features of the graphics protocol:
|
|||||||
|
|
||||||
def serialize_gr_command(**cmd):
|
def serialize_gr_command(**cmd):
|
||||||
payload = cmd.pop('payload', None)
|
payload = cmd.pop('payload', None)
|
||||||
cmd = ','.join('{}={}'.format(k, v) for k, v in cmd.items())
|
cmd = ','.join(f'{k}={v}' for k, v in cmd.items())
|
||||||
ans = []
|
ans = []
|
||||||
w = ans.append
|
w = ans.append
|
||||||
w(b'\033_G'), w(cmd.encode('ascii'))
|
w(b'\033_G'), w(cmd.encode('ascii'))
|
||||||
@@ -223,12 +232,13 @@ and can take the values:
|
|||||||
Value of `t` Meaning
|
Value of `t` Meaning
|
||||||
================== ============
|
================== ============
|
||||||
``d`` Direct (the data is transmitted within the escape code itself)
|
``d`` Direct (the data is transmitted within the escape code itself)
|
||||||
``f`` A simple file
|
``f`` A simple file (regular files only, not named pipes or similar)
|
||||||
``t`` A temporary file, the terminal emulator will delete the file after reading the pixel data. For security reasons
|
``t`` A temporary file, the terminal emulator will delete the file after reading the pixel data. For security reasons
|
||||||
the terminal emulator should only delete the file if it
|
the terminal emulator should only delete the file if it
|
||||||
is in a known temporary directory, such as :file:`/tmp`,
|
is in a known temporary directory, such as :file:`/tmp`,
|
||||||
:file:`/dev/shm`, :file:`TMPDIR env var if present` and any platform
|
:file:`/dev/shm`, :file:`TMPDIR env var if present` and any platform
|
||||||
specific temporary directories.
|
specific temporary directories and the file has the
|
||||||
|
string :code:`tty-graphics-protocol` in its full file path.
|
||||||
``s`` A *shared memory object*, which on POSIX systems is a
|
``s`` A *shared memory object*, which on POSIX systems is a
|
||||||
`POSIX shared memory object <https://pubs.opengroup.org/onlinepubs/9699919799/functions/shm_open.html>`_
|
`POSIX shared memory object <https://pubs.opengroup.org/onlinepubs/9699919799/functions/shm_open.html>`_
|
||||||
and on Windows is a
|
and on Windows is a
|
||||||
@@ -238,6 +248,10 @@ Value of `t` Meaning
|
|||||||
close it on Windows.
|
close it on Windows.
|
||||||
================== ============
|
================== ============
|
||||||
|
|
||||||
|
When opening files, the terminal emulator must follow symlinks. In case of
|
||||||
|
symlink loops or too many symlinks, it should fail and respond with an error,
|
||||||
|
similar to reporting any other kind of I/O error.
|
||||||
|
|
||||||
Local client
|
Local client
|
||||||
^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^
|
||||||
|
|
||||||
@@ -316,14 +330,14 @@ use the *query action*, set ``a=q``. Then the terminal emulator will try to load
|
|||||||
the image and respond with either OK or an error, as above, but it will not
|
the image and respond with either OK or an error, as above, but it will not
|
||||||
replace an existing image with the same id, nor will it store the image.
|
replace an existing image with the same id, nor will it store the image.
|
||||||
|
|
||||||
While as of May 2020, kitty is the only terminal emulator to support this
|
As of April 2022, kitty and WezTerm are the only terminal emulators to
|
||||||
graphics protocol, we intend that any terminal emulator that wishes to support
|
support this graphics protocol completely, with Konsole and wayst having partial support.
|
||||||
it can. To check if a terminal emulator supports the graphics protocol the best way
|
We intend that any terminal emulator that wishes to support it can do so. To
|
||||||
is to send the above *query action* followed by a request for the
|
check if a terminal emulator supports the graphics protocol the best way is to
|
||||||
`primary device attributes <https://vt100.net/docs/vt510-rm/DA1.html>`_. If you
|
send the above *query action* followed by a request for the `primary device
|
||||||
get back an answer for the device attributes without getting back an answer for
|
attributes <https://vt100.net/docs/vt510-rm/DA1.html>`_. If you get back an
|
||||||
the *query action* the terminal emulator does not support the graphics
|
answer for the device attributes without getting back an answer for the *query
|
||||||
protocol.
|
action* the terminal emulator does not support the graphics protocol.
|
||||||
|
|
||||||
This means that terminal emulators that support the graphics protocol, **must**
|
This means that terminal emulators that support the graphics protocol, **must**
|
||||||
reply to *query actions* immediately without processing other input. Most
|
reply to *query actions* immediately without processing other input. Most
|
||||||
@@ -366,7 +380,9 @@ id. To do so add the ``p`` key with a number between ``1`` and ``4294967295``.
|
|||||||
When you specify a placement id, it will be added to the acknowledgement code
|
When you specify a placement id, it will be added to the acknowledgement code
|
||||||
above. Every placement is uniquely identified by the pair of the ``image id``
|
above. Every placement is uniquely identified by the pair of the ``image id``
|
||||||
and the ``placement id``. If you specify a placement id for an image that does
|
and the ``placement id``. If you specify a placement id for an image that does
|
||||||
not have an id, it will be ignored. An example response::
|
not have an id (i.e. has id=0), it will be ignored. In particular this means
|
||||||
|
there can exist multiple images with ``image id=0, placement id=0``.
|
||||||
|
An example response::
|
||||||
|
|
||||||
<ESC>_Gi=<image id>,p=<placement id>;OK<ESC>\
|
<ESC>_Gi=<image id>,p=<placement id>;OK<ESC>\
|
||||||
|
|
||||||
@@ -403,7 +419,9 @@ they are semi-transparent. You can specify z-index values using the ``z`` key.
|
|||||||
Negative z-index values mean that the images will be drawn under the text. This
|
Negative z-index values mean that the images will be drawn under the text. This
|
||||||
allows rendering of text on top of images. Negative z-index values below
|
allows rendering of text on top of images. Negative z-index values below
|
||||||
INT32_MIN/2 (-1,073,741,824) will be drawn under cells with non-default background
|
INT32_MIN/2 (-1,073,741,824) will be drawn under cells with non-default background
|
||||||
colors.
|
colors. If two images with the same z-index overlap then the image with the
|
||||||
|
lower id is considered to have the lower z-index. If the images have the same
|
||||||
|
z-index and the same id, then the behavior is undefined.
|
||||||
|
|
||||||
.. note:: After placing an image on the screen the cursor must be moved to the
|
.. note:: After placing an image on the screen the cursor must be moved to the
|
||||||
right by the number of cols in the image placement rectangle and down by the
|
right by the number of cols in the image placement rectangle and down by the
|
||||||
|
|||||||
@@ -14,12 +14,13 @@ kitty
|
|||||||
changelog
|
changelog
|
||||||
integrations
|
integrations
|
||||||
protocol-extensions
|
protocol-extensions
|
||||||
|
press-mentions
|
||||||
|
|
||||||
|
|
||||||
.. tab:: Fast
|
.. tab:: Fast
|
||||||
|
|
||||||
* Offloads rendering to the GPU for :doc:`lower system load <performance>`
|
* Offloads rendering to the GPU for :doc:`lower system load <performance>`
|
||||||
* Uses threaded rendering for absolutely minimal latency
|
* Uses threaded rendering for :iss:`absolutely minimal latency <2701#issuecomment-636497270>`
|
||||||
* Performance tradeoffs can be :ref:`tuned <conf-kitty-performance>`
|
* Performance tradeoffs can be :ref:`tuned <conf-kitty-performance>`
|
||||||
|
|
||||||
.. tab:: Capable
|
.. tab:: Capable
|
||||||
@@ -36,8 +37,9 @@ kitty
|
|||||||
|
|
||||||
.. tab:: Composable
|
.. tab:: Composable
|
||||||
|
|
||||||
* Programmble tabs, :ref:`splits <splits_layout>` and multiple :doc:`layouts <layouts>` to manage windows
|
* Programmable tabs, :ref:`splits <splits_layout>` and multiple :doc:`layouts <layouts>` to manage windows
|
||||||
* Browse the :ref:`entire history <scrollback>` or the output from the last command comfortably in pagers and editors
|
* Browse the :ref:`entire history <scrollback>` or the :sc:`output from the last command <show_last_command_output>`
|
||||||
|
comfortably in pagers and editors
|
||||||
* Edit or download :doc:`remote files <kittens/remote_file>` in an existing SSH session
|
* Edit or download :doc:`remote files <kittens/remote_file>` in an existing SSH session
|
||||||
|
|
||||||
.. tab:: Cross-platform
|
.. tab:: Cross-platform
|
||||||
@@ -55,12 +57,18 @@ kitty
|
|||||||
* Lots more in :doc:`protocol-extensions`
|
* Lots more in :doc:`protocol-extensions`
|
||||||
|
|
||||||
|
|
||||||
.. figure:: screenshots/screenshot.png
|
.. only:: dirhtml
|
||||||
:alt: Screenshot, showing three programs in the 'Tall' layout
|
|
||||||
:align: center
|
|
||||||
:width: 100%
|
|
||||||
|
|
||||||
Screenshot, showing vim, tig and git running in |kitty| with the 'Tall' layout
|
.. raw:: html
|
||||||
|
|
||||||
|
<video controls width="640" height="360" poster="_static/poster.png">
|
||||||
|
<source src="https://download.calibre-ebook.com/videos/kitty.mp4" type="video/mp4">
|
||||||
|
<source src="https://download.calibre-ebook.com/videos/kitty.webm" type="video/webm">
|
||||||
|
</video>
|
||||||
|
|
||||||
|
.. rst-class:: caption caption-text
|
||||||
|
|
||||||
|
Watch kitty in action!
|
||||||
|
|
||||||
|
|
||||||
To get started see :doc:`quickstart`.
|
To get started see :doc:`quickstart`.
|
||||||
|
|||||||
@@ -1,249 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
# vim:fileencoding=utf-8
|
|
||||||
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
|
|
||||||
|
|
||||||
from __future__ import (
|
|
||||||
absolute_import, division, print_function, unicode_literals
|
|
||||||
)
|
|
||||||
|
|
||||||
import atexit
|
|
||||||
import json
|
|
||||||
import os
|
|
||||||
import platform
|
|
||||||
import re
|
|
||||||
import shlex
|
|
||||||
import shutil
|
|
||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
import tempfile
|
|
||||||
|
|
||||||
py3 = sys.version_info[0] > 2
|
|
||||||
is64bit = platform.architecture()[0] == '64bit'
|
|
||||||
is_macos = 'darwin' in sys.platform.lower()
|
|
||||||
if is_macos:
|
|
||||||
mac_ver = tuple(map(int, platform.mac_ver()[0].split('.')))
|
|
||||||
if mac_ver[:2] < (10, 12):
|
|
||||||
raise SystemExit('Your version of macOS is too old, at least 10.12 is required')
|
|
||||||
|
|
||||||
try:
|
|
||||||
__file__
|
|
||||||
from_file = True
|
|
||||||
except NameError:
|
|
||||||
from_file = False
|
|
||||||
|
|
||||||
if py3:
|
|
||||||
unicode = str
|
|
||||||
raw_input = input
|
|
||||||
import urllib.request as urllib
|
|
||||||
|
|
||||||
def encode_for_subprocess(x):
|
|
||||||
return x
|
|
||||||
else:
|
|
||||||
from future_builtins import map
|
|
||||||
import urllib2 as urllib
|
|
||||||
|
|
||||||
def encode_for_subprocess(x):
|
|
||||||
if isinstance(x, unicode):
|
|
||||||
x = x.encode('utf-8')
|
|
||||||
return x
|
|
||||||
|
|
||||||
|
|
||||||
def run(*args):
|
|
||||||
if len(args) == 1:
|
|
||||||
args = shlex.split(args[0])
|
|
||||||
args = list(map(encode_for_subprocess, args))
|
|
||||||
ret = subprocess.Popen(args).wait()
|
|
||||||
if ret != 0:
|
|
||||||
raise SystemExit(ret)
|
|
||||||
|
|
||||||
|
|
||||||
class Reporter: # {{{
|
|
||||||
|
|
||||||
def __init__(self, fname):
|
|
||||||
self.fname = fname
|
|
||||||
self.last_percent = 0
|
|
||||||
|
|
||||||
def __call__(self, blocks, block_size, total_size):
|
|
||||||
percent = (blocks*block_size)/float(total_size)
|
|
||||||
report = '\rDownloaded {:.1%} '.format(percent)
|
|
||||||
if percent - self.last_percent > 0.05:
|
|
||||||
self.last_percent = percent
|
|
||||||
print(report, end='')
|
|
||||||
sys.stdout.flush()
|
|
||||||
# }}}
|
|
||||||
|
|
||||||
|
|
||||||
def get_latest_release_data():
|
|
||||||
print('Checking for latest release on GitHub...')
|
|
||||||
req = urllib.Request('https://api.github.com/repos/kovidgoyal/kitty/releases/latest', headers={'Accept': 'application/vnd.github.v3+json'})
|
|
||||||
try:
|
|
||||||
res = urllib.urlopen(req).read().decode('utf-8')
|
|
||||||
except Exception as err:
|
|
||||||
raise SystemExit('Failed to contact {} with error: {}'.format(req.get_full_url(), err))
|
|
||||||
data = json.loads(res)
|
|
||||||
html_url = data['html_url'].replace('/tag/', '/download/').rstrip('/')
|
|
||||||
for asset in data.get('assets', ()):
|
|
||||||
name = asset['name']
|
|
||||||
if is_macos:
|
|
||||||
if name.endswith('.dmg'):
|
|
||||||
return html_url + '/' + name, asset['size']
|
|
||||||
else:
|
|
||||||
if name.endswith('.txz'):
|
|
||||||
if is64bit:
|
|
||||||
if name.endswith('-x86_64.txz'):
|
|
||||||
return html_url + '/' + name, asset['size']
|
|
||||||
else:
|
|
||||||
if name.endswith('-i686.txz'):
|
|
||||||
return html_url + '/' + name, asset['size']
|
|
||||||
raise SystemExit('Failed to find the installer package on github')
|
|
||||||
|
|
||||||
|
|
||||||
def do_download(url, size, dest):
|
|
||||||
print('Will download and install', os.path.basename(dest))
|
|
||||||
reporter = Reporter(os.path.basename(dest))
|
|
||||||
|
|
||||||
# Get content length and check if range is supported
|
|
||||||
rq = urllib.urlopen(url)
|
|
||||||
headers = rq.info()
|
|
||||||
sent_size = int(headers['content-length'])
|
|
||||||
if sent_size != size:
|
|
||||||
raise SystemExit('Failed to download from {} Content-Length ({}) != {}'.format(url, sent_size, size))
|
|
||||||
with open(dest, 'wb') as f:
|
|
||||||
while f.tell() < size:
|
|
||||||
raw = rq.read(8192)
|
|
||||||
if not raw:
|
|
||||||
break
|
|
||||||
f.write(raw)
|
|
||||||
reporter(f.tell(), 1, size)
|
|
||||||
rq.close()
|
|
||||||
if os.path.getsize(dest) < size:
|
|
||||||
raise SystemExit('Download failed, try again later')
|
|
||||||
print('\rDownloaded {} bytes'.format(os.path.getsize(dest)))
|
|
||||||
|
|
||||||
|
|
||||||
def clean_cache(cache, fname):
|
|
||||||
for x in os.listdir(cache):
|
|
||||||
if fname not in x:
|
|
||||||
os.remove(os.path.join(cache, x))
|
|
||||||
|
|
||||||
|
|
||||||
def download_installer(url, size):
|
|
||||||
fname = url.rpartition('/')[-1]
|
|
||||||
tdir = tempfile.gettempdir()
|
|
||||||
cache = os.path.join(tdir, 'kitty-installer-cache')
|
|
||||||
if not os.path.exists(cache):
|
|
||||||
os.makedirs(cache)
|
|
||||||
clean_cache(cache, fname)
|
|
||||||
dest = os.path.join(cache, fname)
|
|
||||||
if os.path.exists(dest) and os.path.getsize(dest) == size:
|
|
||||||
print('Using previously downloaded', fname)
|
|
||||||
return dest
|
|
||||||
if os.path.exists(dest):
|
|
||||||
os.remove(dest)
|
|
||||||
do_download(url, size, dest)
|
|
||||||
return dest
|
|
||||||
|
|
||||||
|
|
||||||
def macos_install(dmg, dest='/Applications', launch=True):
|
|
||||||
mp = tempfile.mkdtemp()
|
|
||||||
atexit.register(shutil.rmtree, mp)
|
|
||||||
run('hdiutil', 'attach', dmg, '-mountpoint', mp)
|
|
||||||
try:
|
|
||||||
os.chdir(mp)
|
|
||||||
app = 'kitty.app'
|
|
||||||
d = os.path.join(dest, app)
|
|
||||||
if os.path.exists(d):
|
|
||||||
shutil.rmtree(d)
|
|
||||||
dest = os.path.join(dest, app)
|
|
||||||
run('ditto', '-v', app, dest)
|
|
||||||
print('Successfully installed kitty into', dest)
|
|
||||||
if launch:
|
|
||||||
run('open', dest)
|
|
||||||
finally:
|
|
||||||
os.chdir('/')
|
|
||||||
run('hdiutil', 'detach', mp)
|
|
||||||
|
|
||||||
|
|
||||||
def linux_install(installer, dest=os.path.expanduser('~/.local'), launch=True):
|
|
||||||
dest = os.path.join(dest, 'kitty.app')
|
|
||||||
if os.path.exists(dest):
|
|
||||||
shutil.rmtree(dest)
|
|
||||||
os.makedirs(dest)
|
|
||||||
print('Extracting tarball...')
|
|
||||||
run('tar', '-C', dest, '-xJof', installer)
|
|
||||||
print('kitty successfully installed to', dest)
|
|
||||||
kitty = os.path.join(dest, 'bin', 'kitty')
|
|
||||||
print('Use', kitty, 'to run kitty')
|
|
||||||
if launch:
|
|
||||||
run(kitty, '--detach')
|
|
||||||
|
|
||||||
|
|
||||||
def main(dest=None, launch=True, installer=None):
|
|
||||||
if not dest:
|
|
||||||
if is_macos:
|
|
||||||
dest = '/Applications'
|
|
||||||
else:
|
|
||||||
dest = os.path.expanduser('~/.local')
|
|
||||||
machine = os.uname()[4]
|
|
||||||
if machine and machine.lower().startswith('arm'):
|
|
||||||
raise SystemExit(
|
|
||||||
'You are running on an ARM system. The kitty binaries are only'
|
|
||||||
' available for x86 systems. You will have to build from'
|
|
||||||
' source.')
|
|
||||||
if not installer:
|
|
||||||
url, size = get_latest_release_data()
|
|
||||||
installer = download_installer(url, size)
|
|
||||||
else:
|
|
||||||
installer = os.path.abspath(installer)
|
|
||||||
if not os.access(installer, os.R_OK):
|
|
||||||
raise SystemExit('Could not read from: {}'.format(installer))
|
|
||||||
if is_macos:
|
|
||||||
macos_install(installer, dest=dest, launch=launch)
|
|
||||||
else:
|
|
||||||
linux_install(installer, dest=dest, launch=launch)
|
|
||||||
|
|
||||||
|
|
||||||
def script_launch():
|
|
||||||
# To test: python3 -c "import runpy; runpy.run_path('installer.py', run_name='script_launch')"
|
|
||||||
def path(x):
|
|
||||||
return os.path.expandvars(os.path.expanduser(x))
|
|
||||||
|
|
||||||
def to_bool(x):
|
|
||||||
return x.lower() in {'y', 'yes', '1', 'true'}
|
|
||||||
|
|
||||||
type_map = {x: path for x in 'dest installer'.split()}
|
|
||||||
type_map['launch'] = to_bool
|
|
||||||
kwargs = {}
|
|
||||||
|
|
||||||
for arg in sys.argv[1:]:
|
|
||||||
if arg:
|
|
||||||
m = re.match('([a-z_]+)=(.+)', arg)
|
|
||||||
if m is None:
|
|
||||||
raise SystemExit('Unrecognized command line argument: ' + arg)
|
|
||||||
k = m.group(1)
|
|
||||||
if k not in type_map:
|
|
||||||
raise SystemExit('Unrecognized command line argument: ' + arg)
|
|
||||||
kwargs[k] = type_map[k](m.group(2))
|
|
||||||
main(**kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
def update_intaller_wrapper():
|
|
||||||
# To run: python3 -c "import runpy; runpy.run_path('installer.py', run_name='update_wrapper')" installer.sh
|
|
||||||
with open(__file__, 'rb') as f:
|
|
||||||
src = f.read().decode('utf-8')
|
|
||||||
wrapper = sys.argv[-1]
|
|
||||||
with open(wrapper, 'r+b') as f:
|
|
||||||
raw = f.read().decode('utf-8')
|
|
||||||
nraw = re.sub(r'^# HEREDOC_START.+^# HEREDOC_END', lambda m: '# HEREDOC_START\n{}\n# HEREDOC_END'.format(src), raw, flags=re.MULTILINE | re.DOTALL)
|
|
||||||
if 'update_intaller_wrapper()' not in nraw:
|
|
||||||
raise SystemExit('regex substitute of HEREDOC failed')
|
|
||||||
f.seek(0), f.truncate()
|
|
||||||
f.write(nraw.encode('utf-8'))
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__' and from_file:
|
|
||||||
main()
|
|
||||||
elif __name__ == 'update_wrapper':
|
|
||||||
update_intaller_wrapper()
|
|
||||||
elif __name__ == 'script_launch':
|
|
||||||
script_launch()
|
|
||||||
@@ -1,30 +1,173 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
#
|
|
||||||
# installer.sh
|
|
||||||
# Copyright (C) 2018 Kovid Goyal <kovid at kovidgoyal.net>
|
# Copyright (C) 2018 Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
#
|
#
|
||||||
# Distributed under terms of the GPLv3 license.
|
# Distributed under terms of the GPLv3 license.
|
||||||
#
|
|
||||||
|
|
||||||
python=$(command -v python3)
|
{ \unalias command; \unset -f command; } >/dev/null 2>&1
|
||||||
if [ -z "$python" ]; then
|
tdir=''
|
||||||
python=$(command -v python2)
|
cleanup() {
|
||||||
fi
|
[ -n "$tdir" ] && {
|
||||||
if [ -z "$python" ]; then
|
command rm -rf "$tdir"
|
||||||
python=$(command -v python2.7)
|
tdir=''
|
||||||
fi
|
}
|
||||||
if [ -z "$python" ]; then
|
}
|
||||||
python=$(command -v python)
|
|
||||||
fi
|
|
||||||
if [ -z "$python" ]; then
|
|
||||||
python=python
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo Using python executable: $python
|
die() {
|
||||||
|
cleanup
|
||||||
|
printf "\033[31m%s\033[m\n\r" "$*" > /dev/stderr;
|
||||||
|
exit 1;
|
||||||
|
}
|
||||||
|
|
||||||
$python -c "import sys; script_launch=lambda:sys.exit('Download of installer failed!'); exec(sys.stdin.read()); script_launch()" "$@" <<'INSTALLER_HEREDOC'
|
detect_network_tool() {
|
||||||
# {{{
|
if command -v curl 2> /dev/null > /dev/null; then
|
||||||
# HEREDOC_START
|
fetch() {
|
||||||
# HEREDOC_END
|
command curl -fL "$1"
|
||||||
# }}}
|
}
|
||||||
INSTALLER_HEREDOC
|
fetch_quiet() {
|
||||||
|
command curl -fsSL "$1"
|
||||||
|
}
|
||||||
|
elif command -v wget 2> /dev/null > /dev/null; then
|
||||||
|
fetch() {
|
||||||
|
command wget -O- "$1"
|
||||||
|
}
|
||||||
|
fetch_quiet() {
|
||||||
|
command wget --quiet -O- "$1"
|
||||||
|
}
|
||||||
|
else
|
||||||
|
die "Neither curl nor wget available, cannot download kitty"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
detect_os() {
|
||||||
|
arch=""
|
||||||
|
case "$(command uname)" in
|
||||||
|
'Darwin') OS="macos";;
|
||||||
|
'Linux')
|
||||||
|
OS="linux"
|
||||||
|
case "$(command uname -m)" in
|
||||||
|
x86_64) arch="x86_64";;
|
||||||
|
aarch64*) arch="arm64";;
|
||||||
|
armv8*) arch="arm64";;
|
||||||
|
i386) arch="i686";;
|
||||||
|
i686) arch="i686";;
|
||||||
|
*) die "Unknown CPU architecture $(command uname -m)";;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
*) die "kitty binaries are not available for $(command uname)"
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
expand_tilde() {
|
||||||
|
tilde_less="${1#\~/}"
|
||||||
|
[ "$1" != "$tilde_less" ] && tilde_less="$HOME/$tilde_less"
|
||||||
|
printf '%s' "$tilde_less"
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_args() {
|
||||||
|
dest='~/.local'
|
||||||
|
[ "$OS" = "macos" ] && dest="/Applications"
|
||||||
|
launch='y'
|
||||||
|
installer=''
|
||||||
|
while :; do
|
||||||
|
case "$1" in
|
||||||
|
dest=*) dest="${1#*=}";;
|
||||||
|
launch=*) launch="${1#*=}";;
|
||||||
|
installer=*) installer="${1#*=}";;
|
||||||
|
"") break;;
|
||||||
|
*) die "Unrecognized command line option: $1";;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
dest=$(expand_tilde "${dest}")
|
||||||
|
[ "$launch" != "y" -a "$launch" != "n" ] && die "Unrecognized command line option: launch=$launch"
|
||||||
|
dest="$dest/kitty.app"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
get_file_url() {
|
||||||
|
url="https://github.com/kovidgoyal/kitty/releases/download/$1/kitty-$2"
|
||||||
|
if [ "$OS" = "macos" ]; then
|
||||||
|
url="$url.dmg"
|
||||||
|
else
|
||||||
|
url="$url-$arch.txz"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
get_release_url() {
|
||||||
|
release_version=$(fetch_quiet "https://sw.kovidgoyal.net/kitty/current-version.txt")
|
||||||
|
[ $? -ne 0 -o -z "$release_version" ] && die "Could not get kitty latest release version"
|
||||||
|
get_file_url "v$release_version" "$release_version"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
get_nightly_url() {
|
||||||
|
get_file_url "nightly" "nightly"
|
||||||
|
}
|
||||||
|
|
||||||
|
get_download_url() {
|
||||||
|
installer_is_file="n"
|
||||||
|
case "$installer" in
|
||||||
|
"nightly") get_nightly_url ;;
|
||||||
|
"") get_release_url ;;
|
||||||
|
*) installer_is_file="y" ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
linux_install() {
|
||||||
|
if [ "$installer_is_file" = "y" ]; then
|
||||||
|
command tar -C "$dest" "-xJof" "$installer"
|
||||||
|
else
|
||||||
|
printf '%s\n\n' "Downloading from: $url"
|
||||||
|
fetch "$url" | command tar -C "$dest" "-xJof" "-"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
macos_install() {
|
||||||
|
tdir=$(command mktemp -d "/tmp/kitty-install-XXXXXXXXXXXX")
|
||||||
|
[ "$installer_is_file" != "y" ] && {
|
||||||
|
installer="$tdir/kitty.dmg"
|
||||||
|
printf '%s\n\n' "Downloading from: $url"
|
||||||
|
fetch "$url" > "$installer" || die "Failed to download: $url"
|
||||||
|
}
|
||||||
|
command mkdir "$tdir/mp"
|
||||||
|
command hdiutil attach "$installer" "-mountpoint" "$tdir/mp" || die "Failed to mount kitty.dmg"
|
||||||
|
command ditto -v "$tdir/mp/kitty.app" "$dest"
|
||||||
|
rc="$?"
|
||||||
|
command hdiutil detach "$tdir/mp"
|
||||||
|
command rm -rf "$tdir"
|
||||||
|
tdir=''
|
||||||
|
[ "$rc" != "0" ] && die "Failed to copy kitty.app from mounted dmg"
|
||||||
|
}
|
||||||
|
|
||||||
|
prepare_install_dest() {
|
||||||
|
printf "%s\n" "Installing to $dest"
|
||||||
|
command rm -rf "$dest"
|
||||||
|
command mkdir -p "$dest" || die "Failed to create the directory: $dest"
|
||||||
|
}
|
||||||
|
|
||||||
|
exec_kitty() {
|
||||||
|
if [ "$OS" = "macos" ]; then
|
||||||
|
exec "open" "$dest"
|
||||||
|
else
|
||||||
|
exec "$dest/bin/kitty" "--detach"
|
||||||
|
fi
|
||||||
|
die "Failed to launch kitty"
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
detect_os
|
||||||
|
parse_args "$@"
|
||||||
|
detect_network_tool
|
||||||
|
get_download_url
|
||||||
|
prepare_install_dest
|
||||||
|
if [ "$OS" = "macos" ]; then
|
||||||
|
macos_install
|
||||||
|
else
|
||||||
|
linux_install
|
||||||
|
fi
|
||||||
|
[ "$launch" = "y" ] && exec_kitty
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ Integrations with other tools
|
|||||||
================================
|
================================
|
||||||
|
|
||||||
kitty provides extremely powerful interfaces such as :doc:`remote-control` and
|
kitty provides extremely powerful interfaces such as :doc:`remote-control` and
|
||||||
:doc:`kittens/custom` and :doc:`kittens/icat`
|
:doc:`kittens/custom` and :doc:`kittens/icat` that allow it to be integrated
|
||||||
that allow it to be integrated with other tools seamlessly.
|
with other tools seamlessly.
|
||||||
|
|
||||||
|
|
||||||
Image and document viewers
|
Image and document viewers
|
||||||
@@ -30,19 +30,28 @@ Display markdown files nicely formatted with images in the terminal
|
|||||||
|
|
||||||
`ranger <https://github.com/ranger/ranger>`_
|
`ranger <https://github.com/ranger/ranger>`_
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
A terminal file manager, with previews of file contents powered by kitty's graphics protocol.
|
A terminal file manager, with previews of file contents powered by kitty's
|
||||||
|
graphics protocol.
|
||||||
|
|
||||||
.. _tool_nnn:
|
.. _tool_nnn:
|
||||||
|
|
||||||
`nnn <https://github.com/jarun/nnn/>`_
|
`nnn <https://github.com/jarun/nnn/>`_
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
Another terminal file manager, with previews of file contents powered by kitty's graphics protocol.
|
Another terminal file manager, with previews of file contents powered by kitty's
|
||||||
|
graphics protocol.
|
||||||
|
|
||||||
.. _tool_hunter:
|
.. _tool_hunter:
|
||||||
|
|
||||||
`hunter <https://github.com/rabite0/hunter>`_
|
`hunter <https://github.com/rabite0/hunter>`_
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
Another terminal file manager, with previews of file contents powered by kitty's graphics protocol.
|
Another terminal file manager, with previews of file contents powered by kitty's
|
||||||
|
graphics protocol.
|
||||||
|
|
||||||
|
.. _tool_term_image:
|
||||||
|
|
||||||
|
`term-image <https://github.com/AnonymouX47/term-image>`__
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
Tool to browse images in a terminal using kitty's graphics protocol.
|
||||||
|
|
||||||
.. _tool_koneko:
|
.. _tool_koneko:
|
||||||
|
|
||||||
@@ -61,8 +70,8 @@ View images in the terminal, similar to kitty's icat.
|
|||||||
|
|
||||||
`nb <https://github.com/xwmx/nb>`_
|
`nb <https://github.com/xwmx/nb>`_
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
command line and local web note-taking, bookmarking, archiving, and
|
Command line and local web note-taking, bookmarking, archiving, and knowledge
|
||||||
knowledge base application that uses kitty's graphics protocol for images.
|
base application that uses kitty's graphics protocol for images.
|
||||||
|
|
||||||
.. _tool_w3m:
|
.. _tool_w3m:
|
||||||
|
|
||||||
@@ -75,9 +84,9 @@ images.
|
|||||||
|
|
||||||
`timg <https://github.com/hzeller/timg>`_
|
`timg <https://github.com/hzeller/timg>`_
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
A terminal image and video viewer, that displays static and animated
|
A terminal image and video viewer, that displays static and animated images or
|
||||||
images or plays videos. Fast multi-threaded loading, JPEG exif rotation,
|
plays videos. Fast multi-threaded loading, JPEG exif rotation, grid view and
|
||||||
grid view and connecting to the webcam make it a versatile terminal utility.
|
connecting to the webcam make it a versatile terminal utility.
|
||||||
|
|
||||||
|
|
||||||
System and data visualisation tools
|
System and data visualisation tools
|
||||||
@@ -87,7 +96,8 @@ System and data visualisation tools
|
|||||||
|
|
||||||
`neofetch <https://github.com/dylanaraps/neofetch>`_
|
`neofetch <https://github.com/dylanaraps/neofetch>`_
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
A command line system information tool that shows images using kitty's graphics protocol
|
A command line system information tool that shows images using kitty's graphics
|
||||||
|
protocol
|
||||||
|
|
||||||
.. _tool_matplotlib:
|
.. _tool_matplotlib:
|
||||||
|
|
||||||
@@ -105,16 +115,16 @@ Show images from Julia directly in kitty
|
|||||||
|
|
||||||
`euporie <https://github.com/joouha/euporie>`_
|
`euporie <https://github.com/joouha/euporie>`_
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
A text-based user interface for running and editing Jupyter notebooks,
|
A text-based user interface for running and editing Jupyter notebooks, powered
|
||||||
powered by kitty's graphics protocol for displaying plots
|
by kitty's graphics protocol for displaying plots
|
||||||
|
|
||||||
.. _tool_gnuplot:
|
.. _tool_gnuplot:
|
||||||
|
|
||||||
`gnuplot <http://www.gnuplot.info/>`_
|
`gnuplot <http://www.gnuplot.info/>`_
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
A graphing and data visualization tool that can be made to display its
|
A graphing and data visualization tool that can be made to display its output in
|
||||||
output in kitty with the following bash snippet:
|
kitty with the following bash snippet:
|
||||||
|
|
||||||
.. code-block:: sh
|
.. code-block:: sh
|
||||||
|
|
||||||
@@ -171,26 +181,28 @@ Run applications on your system with fuzzy find inside a kitty window
|
|||||||
Editor integration
|
Editor integration
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
|kitty| can be integrated into many different terminal editors to add features
|
|kitty| can be integrated into many different terminal based text editors to add
|
||||||
such a split windows, previews, REPLs etc.
|
features such a split windows, previews, REPLs etc.
|
||||||
|
|
||||||
.. tool_kakoune:
|
.. tool_kakoune:
|
||||||
|
|
||||||
`kakoune <https://kakoune.org/>`_
|
`kakoune <https://kakoune.org/>`_
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
integrates with kitty to use native kitty windows for its windows/panels and REPLs.
|
Integrates with kitty to use native kitty windows for its windows/panels and
|
||||||
|
REPLs.
|
||||||
|
|
||||||
.. tool_vim_slime:
|
.. tool_vim_slime:
|
||||||
|
|
||||||
`vim-slime <https://github.com/jpalardy/vim-slime#kitty>`_
|
`vim-slime <https://github.com/jpalardy/vim-slime#kitty>`_
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
uses kitty remote control for a Lisp REPL.
|
Uses kitty remote control for a Lisp REPL.
|
||||||
|
|
||||||
.. tool_vim_kitty_navigator:
|
.. tool_vim_kitty_navigator:
|
||||||
|
|
||||||
`vim-kitty-navigator <https://github.com/knubie/vim-kitty-navigator>`_
|
`vim-kitty-navigator <https://github.com/knubie/vim-kitty-navigator>`_
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
allows you to navigate seamlessly between vim and kitty splits using a consistent set of hotkeys.
|
Allows you to navigate seamlessly between vim and kitty splits using a
|
||||||
|
consistent set of hotkeys.
|
||||||
|
|
||||||
.. tool_vim_test:
|
.. tool_vim_test:
|
||||||
|
|
||||||
@@ -202,7 +214,7 @@ Allows easily running tests in a terminal window
|
|||||||
|
|
||||||
`hologram.nvim <https://github.com/edluffy/hologram.nvim>`_
|
`hologram.nvim <https://github.com/edluffy/hologram.nvim>`_
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
Terminal image viewer for nvim
|
Terminal image viewer for Neovim
|
||||||
|
|
||||||
|
|
||||||
Scrollback manipulation
|
Scrollback manipulation
|
||||||
@@ -228,21 +240,21 @@ Miscellaneous
|
|||||||
|
|
||||||
`kitty-smart-tab <https://github.com/yurikhan/kitty-smart-tab>`_
|
`kitty-smart-tab <https://github.com/yurikhan/kitty-smart-tab>`_
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
use keys to either control tabs or pass them onto running applications if
|
Use keys to either control tabs or pass them onto running applications if no
|
||||||
no tabs are present
|
tabs are present
|
||||||
|
|
||||||
.. tool_kitty_smart_scroll:
|
.. tool_kitty_smart_scroll:
|
||||||
|
|
||||||
`kitty-smart-scroll <https://github.com/yurikhan/kitty-smart-scroll>`_
|
`kitty-smart-scroll <https://github.com/yurikhan/kitty-smart-scroll>`_
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
use keys to either scroll or pass them onto running applications if
|
Use keys to either scroll or pass them onto running applications if no
|
||||||
no scrollback buffer is present
|
scrollback buffer is present
|
||||||
|
|
||||||
.. tool_kitti3:
|
.. tool_kitti3:
|
||||||
|
|
||||||
`kitti3 <https://github.com/LandingEllipse/kitti3>`_
|
`kitti3 <https://github.com/LandingEllipse/kitti3>`_
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
allow using kitty as a drop-down terminal under the i3 window manager
|
Allow using kitty as a drop-down terminal under the i3 window manager
|
||||||
|
|
||||||
.. tool_weechat_hints:
|
.. tool_weechat_hints:
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,18 @@ You can see this protocol with all enhancements in action by running::
|
|||||||
|
|
||||||
inside the kitty terminal to report key events.
|
inside the kitty terminal to report key events.
|
||||||
|
|
||||||
|
In addition to kitty, this protocol is also implemented in:
|
||||||
|
|
||||||
|
* The `foot terminal <https://codeberg.org/dnkl/foot/issues/319>`__
|
||||||
|
* The `WezTerm terminal <https://wezfurlong.org/wezterm/config/lua/config/enable_kitty_keyboard.html>`__
|
||||||
|
* The `notcurses library
|
||||||
|
<https://github.com/dankamongmen/notcurses/issues/2131>`__
|
||||||
|
* The `crossterm library
|
||||||
|
<https://github.com/crossterm-rs/crossterm/pull/688>`__
|
||||||
|
* The `neovim text editor <https://github.com/neovim/neovim/pull/18181>`__
|
||||||
|
* The `kakoune text editor <https://github.com/mawww/kakoune/issues/4103>`__
|
||||||
|
* The `dte text editor <https://gitlab.com/craigbarnes/dte/-/issues/138>`__
|
||||||
|
|
||||||
.. versionadded:: 0.20.0
|
.. versionadded:: 0.20.0
|
||||||
|
|
||||||
Quickstart
|
Quickstart
|
||||||
@@ -66,10 +78,11 @@ key, such as ``97`` for the :kbd:`a` key, or one of the numbers from the
|
|||||||
modifiers pressed for the key event. The encoding is described in the
|
modifiers pressed for the key event. The encoding is described in the
|
||||||
:ref:`modifiers` section.
|
:ref:`modifiers` section.
|
||||||
|
|
||||||
The second form is used for a few functional keys, such as the :kbd:`Home, End,
|
The second form is used for a few functional keys, such as the :kbd:`Home`,
|
||||||
Arrow keys and F1-F4`, they are enumerated in the :ref:`functional` table below.
|
:kbd:`End`, :kbd:`Arrow` keys and :kbd:`F1` ... :kbd:`F4`, they are enumerated in
|
||||||
Note that if no modifiers are present the parameters are omitted entirely
|
the :ref:`functional` table below. Note that if no modifiers are present the
|
||||||
giving an escape code of the form ``CSI [ABCDEFHPQRS]``.
|
parameters are omitted entirely giving an escape code of the form ``CSI
|
||||||
|
[ABCDEFHPQRS]``.
|
||||||
|
|
||||||
If you want support for more advanced features such as repeat and release
|
If you want support for more advanced features such as repeat and release
|
||||||
events, alternate keys for shortcut matching et cetera, these can be turned on
|
events, alternate keys for shortcut matching et cetera, these can be turned on
|
||||||
@@ -142,11 +155,13 @@ sub-field for the shifted key, like this::
|
|||||||
Modifiers
|
Modifiers
|
||||||
~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~
|
||||||
|
|
||||||
This protocol supports six modifier keys, :kbd:`shift, alt, ctrl, super, hyper
|
This protocol supports six modifier keys, :kbd:`shift`, :kbd:`alt`,
|
||||||
and meta` as well as :kbd:`num_lock and caps_lock`. Here :kbd:`super` is either
|
:kbd:`ctrl`, :kbd:`super`, :kbd:`hyper`, :kbd:`meta`, :kbd:`num_lock` and
|
||||||
the *Windows/Linux* key or the *Cmd* key on mac keyboards. :kbd:`hyper` and
|
:kbd:`caps_lock`. Here :kbd:`super` is either the *Windows/Linux* key or the
|
||||||
:kbd:`meta` are typically present only on X11 based systems with special XKB
|
:kbd:`command` key on mac keyboards. The :kbd:`alt` key is the :kbd:`option`
|
||||||
rules. Modifiers are encoded as a bit field with::
|
key on mac keyboards. :kbd:`hyper` and :kbd:`meta` are typically present only
|
||||||
|
on X11/Wayland based systems with special XKB rules. Modifiers are encoded as a
|
||||||
|
bit field with::
|
||||||
|
|
||||||
shift 0b1 (1)
|
shift 0b1 (1)
|
||||||
alt 0b10 (2)
|
alt 0b10 (2)
|
||||||
@@ -209,9 +224,9 @@ Non-Unicode keys
|
|||||||
|
|
||||||
There are many keys that don't correspond to letters from human languages, and
|
There are many keys that don't correspond to letters from human languages, and
|
||||||
thus aren't represented in Unicode. Think of functional keys, such as
|
thus aren't represented in Unicode. Think of functional keys, such as
|
||||||
:kbd:`Escape, Play, Pause, F1, Home, etc`. These are encoded using Unicode code
|
:kbd:`Escape`, :kbd:`Play`, :kbd:`Pause`, :kbd:`F1`, :kbd:`Home`, etc. These
|
||||||
points from the Private Use Area (``57344 - 63743``). The mapping of key
|
are encoded using Unicode code points from the Private Use Area (``57344 -
|
||||||
names to code points for these keys is in the
|
63743``). The mapping of key names to code points for these keys is in the
|
||||||
:ref:`Functional key definition table below <functional>`.
|
:ref:`Functional key definition table below <functional>`.
|
||||||
|
|
||||||
|
|
||||||
@@ -277,11 +292,6 @@ oldest entry from the stack must be evicted.
|
|||||||
the editor would have to somehow know what the keyboard mode of the main
|
the editor would have to somehow know what the keyboard mode of the main
|
||||||
screen is and restore to that mode on exit.
|
screen is and restore to that mode on exit.
|
||||||
|
|
||||||
.. note:: In the interests of interoperation, the XTerm specific sequences
|
|
||||||
`CSI > 4; 1 m` and `CSI > 4; 0 m` are treated as `CSI > 1 u` and `CSI < 1 u`.
|
|
||||||
These codes cause XTerm to use the CSI u encoding for more keys and are therefore
|
|
||||||
treated as similar to the disambiguate progressive enhancement.
|
|
||||||
|
|
||||||
.. _disambiguate:
|
.. _disambiguate:
|
||||||
|
|
||||||
Disambiguate escape codes
|
Disambiguate escape codes
|
||||||
@@ -293,8 +303,8 @@ encodings overlapping with other control codes. For instance, pressing the
|
|||||||
start of an escape code. Similarly pressing the key :kbd:`alt+[` will generate
|
start of an escape code. Similarly pressing the key :kbd:`alt+[` will generate
|
||||||
the bytes used for CSI control codes.
|
the bytes used for CSI control codes.
|
||||||
|
|
||||||
Turning on this flag will cause the terminal to report the :kbd:`Esc, alt+key,
|
Turning on this flag will cause the terminal to report the :kbd:`Esc`, :kbd:`alt+key`,
|
||||||
ctrl+key, ctrl+alt+key, shift+alt+key` keys using ``CSI u`` sequences instead
|
:kbd:`ctrl+key`, :kbd:`ctrl+alt+key`, :kbd:`shift+alt+key` keys using ``CSI u`` sequences instead
|
||||||
of legacy ones. Here key is any ASCII key as described in :ref:`legacy_text`.
|
of legacy ones. Here key is any ASCII key as described in :ref:`legacy_text`.
|
||||||
Additionally, all keypad keys will be reported as separate keys with ``CSI u``
|
Additionally, all keypad keys will be reported as separate keys with ``CSI u``
|
||||||
encoding, using dedicated numbers from the :ref:`table below <functional>`.
|
encoding, using dedicated numbers from the :ref:`table below <functional>`.
|
||||||
@@ -309,7 +319,7 @@ This makes it very easy to parse key events in an application. In particular,
|
|||||||
:kbd:`ctrl+c` will no longer generate the ``SIGINT`` signal, but instead be
|
:kbd:`ctrl+c` will no longer generate the ``SIGINT`` signal, but instead be
|
||||||
delivered as a ``CSI u`` escape code. This has the nice side effect of making it
|
delivered as a ``CSI u`` escape code. This has the nice side effect of making it
|
||||||
much easier to integrate into the application event loop. The only exceptions
|
much easier to integrate into the application event loop. The only exceptions
|
||||||
are the :kbd:`Enter, Tab and Backspace` keys which still generate the same
|
are the :kbd:`Enter`, :kbd:`Tab` and :kbd:`Backspace` keys which still generate the same
|
||||||
bytes as in legacy mode this is to allow the user to type and execute commands
|
bytes as in legacy mode this is to allow the user to type and execute commands
|
||||||
in the shell such as ``reset`` after a program that sets this mode crashes
|
in the shell such as ``reset`` after a program that sets this mode crashes
|
||||||
without clearing it.
|
without clearing it.
|
||||||
@@ -349,8 +359,8 @@ only key events are sent. If the text is needed as well, combine with the
|
|||||||
Report associated text enhancement below.
|
Report associated text enhancement below.
|
||||||
|
|
||||||
Additionally, with this mode, events for pressing modifier keys are reported.
|
Additionally, with this mode, events for pressing modifier keys are reported.
|
||||||
Note that *all* keys are reported as escape codes, including :kbd:`Enter, Tab,
|
Note that *all* keys are reported as escape codes, including :kbd:`Enter`,
|
||||||
Backspace` etc.
|
:kbd:`Tab`, :kbd:`Backspace` etc.
|
||||||
|
|
||||||
.. _report_text:
|
.. _report_text:
|
||||||
|
|
||||||
@@ -371,7 +381,7 @@ An application can query the terminal for support of this protocol by sending
|
|||||||
the escape code querying for the :ref:`current progressive enhancement
|
the escape code querying for the :ref:`current progressive enhancement
|
||||||
<progressive_enhancement>` status
|
<progressive_enhancement>` status
|
||||||
followed by request for the `primary device attributes
|
followed by request for the `primary device attributes
|
||||||
<https://vt100.net/docs/vt510-rm/DA1.html>`. If an answer for the device
|
<https://vt100.net/docs/vt510-rm/DA1.html>`__. If an answer for the device
|
||||||
attributes is received without getting back an answer for the progressive
|
attributes is received without getting back an answer for the progressive
|
||||||
enhancement the terminal does not support this protocol.
|
enhancement the terminal does not support this protocol.
|
||||||
|
|
||||||
@@ -436,6 +446,7 @@ mode* (the ``smkx/rmkx`` terminfo capabilities). This form is used only in
|
|||||||
"F10", "kf10", "CSI 21 ~"
|
"F10", "kf10", "CSI 21 ~"
|
||||||
"F11", "kf11", "CSI 23 ~"
|
"F11", "kf11", "CSI 23 ~"
|
||||||
"F12", "kf12", "CSI 24 ~"
|
"F12", "kf12", "CSI 24 ~"
|
||||||
|
"MENU", "kf16", "CSI 29 ~"
|
||||||
|
|
||||||
There are a few more functional keys that have special cased legacy encodings.
|
There are a few more functional keys that have special cased legacy encodings.
|
||||||
These are present because they are commonly used and for the sake of legacy
|
These are present because they are commonly used and for the sake of legacy
|
||||||
@@ -462,10 +473,11 @@ distinguish these, use the :ref:`disambiguate <disambiguate>` flag.
|
|||||||
Legacy text keys
|
Legacy text keys
|
||||||
~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
For legacy compatibility, the keys
|
For legacy compatibility, the keys :kbd:`a`-:kbd:`z` :kbd:`0`-:kbd:`9`
|
||||||
:kbd:`a-z 0-9 \` - = [ ] \ ; ' , . /` with the modifiers
|
:kbd:`\`` :kbd:`-` :kbd:`=` :kbd:`[` :kbd:`]` :kbd:`\\` :kbd:`;` :kbd:`'`
|
||||||
:kbd:`shift, alt, ctrl, shift+alt, ctrl+alt` are output using the
|
:kbd:`,` :kbd:`.` :kbd:`/` with the modifiers :kbd:`shift`, :kbd:`alt`,
|
||||||
following algorithm:
|
:kbd:`ctrl`, :kbd:`shift+alt`, :kbd:`ctrl+alt` are output using the following
|
||||||
|
algorithm:
|
||||||
|
|
||||||
#. If the :kbd:`alt` key is pressed output the byte for ``ESC (0x1b)``
|
#. If the :kbd:`alt` key is pressed output the byte for ``ESC (0x1b)``
|
||||||
#. If the :kbd:`ctrl` modifier is pressed map the key using the table
|
#. If the :kbd:`ctrl` modifier is pressed map the key using the table
|
||||||
@@ -637,8 +649,8 @@ specification.
|
|||||||
* Incorrectly encoding shifted keys when shift modifier is used, for instance,
|
* Incorrectly encoding shifted keys when shift modifier is used, for instance,
|
||||||
for :kbd:`ctrl+shift+i` is encoded as :kbd:`ctrl+I`.
|
for :kbd:`ctrl+shift+i` is encoded as :kbd:`ctrl+I`.
|
||||||
|
|
||||||
* No way to have non-conflicting escape codes for :kbd:`alt+letter,
|
* No way to have non-conflicting escape codes for :kbd:`alt+letter`,
|
||||||
ctrl+letter, ctrl+alt+letter` key presses
|
:kbd:`ctrl+letter`, :kbd:`ctrl+alt+letter` key presses
|
||||||
|
|
||||||
* No way to specify both shifted and unshifted keys for robust shortcut
|
* No way to specify both shifted and unshifted keys for robust shortcut
|
||||||
matching (think matching :kbd:`ctrl+shift+equal` and :kbd:`ctrl+plus`)
|
matching (think matching :kbd:`ctrl+shift+equal` and :kbd:`ctrl+plus`)
|
||||||
|
|||||||
@@ -3,18 +3,21 @@ broadcast
|
|||||||
|
|
||||||
*Type text in all kitty windows simultaneously*
|
*Type text in all kitty windows simultaneously*
|
||||||
|
|
||||||
The ``broadcast`` kitten can be used to type text simultaneously in
|
The ``broadcast`` kitten can be used to type text simultaneously in all
|
||||||
all kitty windows (or a subset as desired).
|
:term:`kitty windows <window>` (or a subset as desired).
|
||||||
|
|
||||||
To use it, simply create a mapping in :file:`kitty.conf` such as::
|
To use it, simply create a mapping in :file:`kitty.conf` such as::
|
||||||
|
|
||||||
map F1 launch --allow-remote-control kitty +kitten broadcast
|
map f1 launch --allow-remote-control kitty +kitten broadcast
|
||||||
|
|
||||||
Then press the :kbd:`F1` key and whatever you type in the newly created widow
|
Then press the :kbd:`F1` key and whatever you type in the newly created window
|
||||||
will be sent to all kitty windows.
|
will be sent to all kitty windows.
|
||||||
|
|
||||||
You can use the options described below to control which windows
|
You can use the options described below to control which windows are selected.
|
||||||
are selected.
|
|
||||||
|
For example, only broadcast to other windows in the current tab::
|
||||||
|
|
||||||
|
map f1 launch --allow-remote-control kitty +kitten broadcast --match-tab state:focused
|
||||||
|
|
||||||
.. program:: kitty +kitten broadcast
|
.. program:: kitty +kitten broadcast
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +1,20 @@
|
|||||||
Custom kittens
|
Custom kittens
|
||||||
=================
|
=================
|
||||||
|
|
||||||
You can easily create your own kittens to extend kitty. They are just
|
You can easily create your own kittens to extend kitty. They are just terminal
|
||||||
terminal programs written in Python. When launching a kitten, kitty will
|
programs written in Python. When launching a kitten, kitty will open an overlay
|
||||||
open an overlay window over the current window and optionally pass the
|
window over the current window and optionally pass the contents of the current
|
||||||
contents of the current window/scrollback to the kitten over its :file:`STDIN`.
|
window/scrollback to the kitten over its :file:`STDIN`. The kitten can then
|
||||||
The kitten can then perform whatever actions it likes, just as a normal
|
perform whatever actions it likes, just as a normal terminal program. After
|
||||||
terminal program. After execution of the kitten is complete, it has access
|
execution of the kitten is complete, it has access to the running kitty instance
|
||||||
to the running kitty instance so it can perform arbitrary actions
|
so it can perform arbitrary actions such as closing windows, pasting text, etc.
|
||||||
such as closing windows, pasting text, etc.
|
|
||||||
|
|
||||||
Let's see a simple example of creating a kitten. It will ask the user for some
|
Let's see a simple example of creating a kitten. It will ask the user for some
|
||||||
input and paste it into the terminal window.
|
input and paste it into the terminal window.
|
||||||
|
|
||||||
Create a file in the kitty config folder, :file:`~/.config/kitty/mykitten.py`
|
Create a file in the kitty config directory, :file:`~/.config/kitty/mykitten.py`
|
||||||
(you might need to adjust the path to wherever the kitty config folder is on
|
(you might need to adjust the path to wherever the :ref:`kitty config directory
|
||||||
your machine).
|
<confloc>` is on your machine).
|
||||||
|
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
@@ -35,7 +34,7 @@ your machine).
|
|||||||
# get the kitty window into which to paste answer
|
# get the kitty window into which to paste answer
|
||||||
w = boss.window_id_map.get(target_window_id)
|
w = boss.window_id_map.get(target_window_id)
|
||||||
if w is not None:
|
if w is not None:
|
||||||
w.paste(answer)
|
w.paste_text(answer)
|
||||||
|
|
||||||
|
|
||||||
Now in :file:`kitty.conf` add the lines::
|
Now in :file:`kitty.conf` add the lines::
|
||||||
@@ -43,11 +42,30 @@ Now in :file:`kitty.conf` add the lines::
|
|||||||
map ctrl+k kitten mykitten.py
|
map ctrl+k kitten mykitten.py
|
||||||
|
|
||||||
|
|
||||||
Start kitty and press :kbd:`ctrl+k` and you should see the kitten running.
|
Start kitty and press :kbd:`Ctrl+K` and you should see the kitten running.
|
||||||
The best way to develop your own kittens is to modify one of the built in
|
The best way to develop your own kittens is to modify one of the built-in
|
||||||
kittens. Look in the kittens sub-directory of the kitty source code for those.
|
kittens. Look in the `kittens sub-directory
|
||||||
Or see below for a list of :ref:`third-party kittens <external_kittens>`,
|
<https://github.com/kovidgoyal/kitty/tree/master/kittens>`__ of the kitty source
|
||||||
that other kitty users have created.
|
code for those. Or see below for a list of :ref:`third-party kittens
|
||||||
|
<external_kittens>`, that other kitty users have created.
|
||||||
|
|
||||||
|
kitty API to use with kittens
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
Kittens have full access to internal kitty APIs. However these are neither
|
||||||
|
entirely stable nor documented. You can instead use the kitty
|
||||||
|
:doc:`Remote control API </remote-control>`. Simply call
|
||||||
|
:code:`boss.call_remote_control()`, with the same arguments you
|
||||||
|
would pass to ``kitty @``. For example:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
def handle_result(args: List[str], answer: str, target_window_id: int, boss: Boss) -> None:
|
||||||
|
# get the kitty window to which to send text
|
||||||
|
w = boss.window_id_map.get(target_window_id)
|
||||||
|
if w is not None:
|
||||||
|
boss.call_remote_control(w, ('send-text', 'hello world'))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Passing arguments to kittens
|
Passing arguments to kittens
|
||||||
@@ -60,62 +78,100 @@ You can pass arguments to kittens by defining them in the map directive in
|
|||||||
|
|
||||||
These will be available as the ``args`` parameter in the ``main()`` and
|
These will be available as the ``args`` parameter in the ``main()`` and
|
||||||
``handle_result()`` functions. Note also that the current working directory
|
``handle_result()`` functions. Note also that the current working directory
|
||||||
of the kitten is set to the working directory of whatever program is
|
of the kitten is set to the working directory of whatever program is running in
|
||||||
running in the active kitty window. The special argument ``@selection``
|
the active kitty window. The special argument ``@selection`` is replaced by the
|
||||||
is replaced by the currently selected text in the active kitty window.
|
currently selected text in the active kitty window.
|
||||||
|
|
||||||
|
|
||||||
Passing the contents of the screen to the kitten
|
Passing the contents of the screen to the kitten
|
||||||
---------------------------------------------------
|
---------------------------------------------------
|
||||||
|
|
||||||
If you would like your kitten to have access to the contents of the screen
|
If you would like your kitten to have access to the contents of the screen
|
||||||
and/or the scrollback buffer, you just need to add an annotation to the ``handle_result()``
|
and/or the scrollback buffer, you just need to add an annotation to the
|
||||||
function, telling kitty what kind of input your kitten would like. For example:
|
``handle_result()`` function, telling kitty what kind of input your kitten would
|
||||||
|
like. For example:
|
||||||
|
|
||||||
.. code-block:: py
|
.. code-block:: py
|
||||||
|
|
||||||
|
from typing import List
|
||||||
|
from kitty.boss import Boss
|
||||||
|
|
||||||
# in main, STDIN is for the kitten process and will contain
|
# in main, STDIN is for the kitten process and will contain
|
||||||
# the contents of the screen
|
# the contents of the screen
|
||||||
def main(args):
|
def main(args: List[str]) -> str:
|
||||||
return sys.stdin.read()
|
return sys.stdin.read()
|
||||||
|
|
||||||
# in handle_result, STDIN is for the kitty process itself, rather
|
# in handle_result, STDIN is for the kitty process itself, rather
|
||||||
# than the kitten process and should not be read from.
|
# than the kitten process and should not be read from.
|
||||||
from kittens.tui.handler import result_handler
|
from kittens.tui.handler import result_handler
|
||||||
@result_handler(type_of_input='text')
|
@result_handler(type_of_input='text')
|
||||||
def handle_result(args, stdin_data, target_window_id, boss):
|
def handle_result(args: List[str], stdin_data: str, target_window_id: int, boss: Boss) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
This will send the plain text of the active window to the kitten's
|
This will send the plain text of the active window to the kitten's
|
||||||
:file:`STDIN`. For text with formatting escape codes, use ``ansi``
|
:file:`STDIN`. There are many other types of input you can ask for, described in
|
||||||
instead. If you want line wrap markers as well, use ``screen-ansi``
|
the table below:
|
||||||
or just ``screen``. For the scrollback buffer as well, use
|
|
||||||
``history``, ``ansi-history`` or ``screen-history``. To get
|
.. table:: Types of input to kittens
|
||||||
the currently selected text, use ``selection``.
|
:align: left
|
||||||
|
|
||||||
|
=========================== =======================================================================================================
|
||||||
|
Keyword Type of :file:`STDIN` input
|
||||||
|
=========================== =======================================================================================================
|
||||||
|
``text`` Plain text of active window
|
||||||
|
``ansi`` Formatted text of active window
|
||||||
|
``screen`` Plain text of active window with line wrap markers
|
||||||
|
``screen-ansi`` Formatted text of active window with line wrap markers
|
||||||
|
|
||||||
|
``history`` Plain text of active window and its scrollback
|
||||||
|
``ansi-history`` Formatted text of active window and its scrollback
|
||||||
|
``screen-history`` Plain text of active window and its scrollback with line wrap markers
|
||||||
|
``screen-ansi-history`` Formatted text of active window and its scrollback with line wrap markers
|
||||||
|
|
||||||
|
``output`` Plain text of the output from the last run command
|
||||||
|
``output-screen`` Plain text of the output from the last run command with wrap markers
|
||||||
|
``output-ansi`` Formatted text of the output from the last run command
|
||||||
|
``output-screen-ansi`` Formatted text of the output from the last run command with wrap markers
|
||||||
|
|
||||||
|
``selection`` The text currently selected with the mouse
|
||||||
|
=========================== =======================================================================================================
|
||||||
|
|
||||||
|
In addition to ``output``, that gets the output of the last run command,
|
||||||
|
``last_visited_output`` gives the output of the command last jumped to
|
||||||
|
and ``first_output`` gives the output of the first command currently on screen.
|
||||||
|
These can also be combined with ``screen`` and ``ansi`` for formatting.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
For the types based on the output of a command, :ref:`shell_integration` is
|
||||||
|
required.
|
||||||
|
|
||||||
|
|
||||||
Using kittens to script kitty, without any terminal UI
|
Using kittens to script kitty, without any terminal UI
|
||||||
-----------------------------------------------------------
|
-----------------------------------------------------------
|
||||||
|
|
||||||
If you would like your kitten to script kitty, without bothering to write a
|
If you would like your kitten to script kitty, without bothering to write a
|
||||||
terminal program, you can tell the kittens system to run the
|
terminal program, you can tell the kittens system to run the ``handle_result()``
|
||||||
``handle_result()`` function without first running the ``main()`` function.
|
function without first running the ``main()`` function.
|
||||||
|
|
||||||
For example, here is a kitten that "zooms/unzooms" the current terminal window
|
For example, here is a kitten that "zooms in/zooms out" the current terminal
|
||||||
by switching to the stack layout or back to the previous layout. This is
|
window by switching to the stack layout or back to the previous layout. This is
|
||||||
equivalent to the builtin :ref:`action-toggle_layout` action.
|
equivalent to the builtin :ac:`toggle_layout` action.
|
||||||
|
|
||||||
Create a file in the kitty config folder, :file:`~/.config/kitty/zoom_toggle.py`
|
Create a Python file in the :ref:`kitty config directory <confloc>`,
|
||||||
|
:file:`~/.config/kitty/zoom_toggle.py`
|
||||||
|
|
||||||
.. code-block:: py
|
.. code-block:: py
|
||||||
|
|
||||||
def main(args):
|
from typing import List
|
||||||
|
from kitty.boss import Boss
|
||||||
|
|
||||||
|
def main(args: List[str]) -> str:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
from kittens.tui.handler import result_handler
|
from kittens.tui.handler import result_handler
|
||||||
@result_handler(no_ui=True)
|
@result_handler(no_ui=True)
|
||||||
def handle_result(args, answer, target_window_id, boss):
|
def handle_result(args: List[str], answer: str, target_window_id: int, boss: Boss) -> None:
|
||||||
tab = boss.active_tab
|
tab = boss.active_tab
|
||||||
if tab is not None:
|
if tab is not None:
|
||||||
if tab.current_layout.name == 'stack':
|
if tab.current_layout.name == 'stack':
|
||||||
@@ -124,7 +180,7 @@ Create a file in the kitty config folder, :file:`~/.config/kitty/zoom_toggle.py`
|
|||||||
tab.goto_layout('stack')
|
tab.goto_layout('stack')
|
||||||
|
|
||||||
|
|
||||||
Now in kitty.conf add::
|
Now in :file:`kitty.conf` add::
|
||||||
|
|
||||||
map f11 kitten zoom_toggle.py
|
map f11 kitten zoom_toggle.py
|
||||||
|
|
||||||
@@ -135,7 +191,7 @@ layout, by simply adding the line::
|
|||||||
boss.toggle_fullscreen()
|
boss.toggle_fullscreen()
|
||||||
|
|
||||||
|
|
||||||
To the ``handle_result()`` function, above.
|
to the ``handle_result()`` function, above.
|
||||||
|
|
||||||
|
|
||||||
.. _send_mouse_event:
|
.. _send_mouse_event:
|
||||||
@@ -143,7 +199,7 @@ To the ``handle_result()`` function, above.
|
|||||||
Sending mouse events
|
Sending mouse events
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
If the program running in a window is receiving mouse events you can simulate
|
If the program running in a window is receiving mouse events, you can simulate
|
||||||
those using::
|
those using::
|
||||||
|
|
||||||
from kitty.fast_data_types import send_mouse_event
|
from kitty.fast_data_types import send_mouse_event
|
||||||
@@ -170,15 +226,15 @@ that type, and will return ``True`` if it sent the event, and ``False`` if not.
|
|||||||
Debugging kittens
|
Debugging kittens
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
The part of the kitten that runs in ``main()`` is just a normal program and
|
The part of the kitten that runs in ``main()`` is just a normal program and the
|
||||||
the output of print statements will be visible in the kitten window. Or
|
output of print statements will be visible in the kitten window. Or alternately,
|
||||||
alternately, you can use::
|
you can use::
|
||||||
|
|
||||||
from kittens.tui.loop import debug
|
from kittens.tui.loop import debug
|
||||||
debug('whatever')
|
debug('whatever')
|
||||||
|
|
||||||
The ``debug()`` function is just like ``print()`` except that the output
|
The ``debug()`` function is just like ``print()`` except that the output will
|
||||||
will appear in the ``STDOUT`` of the kitty process inside which the kitten is
|
appear in the ``STDOUT`` of the kitty process inside which the kitten is
|
||||||
running.
|
running.
|
||||||
|
|
||||||
The ``handle_result()`` part of the kitten runs inside the kitty process.
|
The ``handle_result()`` part of the kitten runs inside the kitty process.
|
||||||
@@ -186,12 +242,13 @@ The output of print statements will go to the ``STDOUT`` of the kitty process.
|
|||||||
So if you run kitty from another kitty instance, the output will be visible
|
So if you run kitty from another kitty instance, the output will be visible
|
||||||
in the first kitty instance.
|
in the first kitty instance.
|
||||||
|
|
||||||
|
|
||||||
Adding options to kittens
|
Adding options to kittens
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
If you would like to use kitty's config framework to make your kittens
|
If you would like to use kitty's config framework to make your kittens
|
||||||
configurable, you will need some boilerplate. In the directory
|
configurable, you will need some boilerplate. Put the following files in the
|
||||||
of your kitten make the following files.
|
directory of your kitten.
|
||||||
|
|
||||||
:file:`kitten_options_definition.py`
|
:file:`kitten_options_definition.py`
|
||||||
|
|
||||||
@@ -281,8 +338,9 @@ You can parse and read the options in your kitten using the following code:
|
|||||||
opts.config_overrides = overrides
|
opts.config_overrides = overrides
|
||||||
return opts
|
return opts
|
||||||
|
|
||||||
See the code for the builtin diff kitten for examples of creating more options
|
See `the code <https://github.com/kovidgoyal/kitty/tree/master/kittens/diff>`__
|
||||||
and keyboard shortcuts.
|
for the builtin :doc:`diff kitten </kittens/diff>` for examples of creating more
|
||||||
|
options and keyboard shortcuts.
|
||||||
|
|
||||||
.. _external_kittens:
|
.. _external_kittens:
|
||||||
|
|
||||||
@@ -290,12 +348,13 @@ Kittens created by kitty users
|
|||||||
---------------------------------------------
|
---------------------------------------------
|
||||||
|
|
||||||
`vim-kitty-navigator <https://github.com/knubie/vim-kitty-navigator>`_
|
`vim-kitty-navigator <https://github.com/knubie/vim-kitty-navigator>`_
|
||||||
Allows you to navigate seamlessly between vim and kitty splits using a consistent set of hotkeys.
|
Allows you to navigate seamlessly between vim and kitty splits using a
|
||||||
|
consistent set of hotkeys.
|
||||||
|
|
||||||
`smart-scroll <https://github.com/yurikhan/kitty-smart-scroll>`_
|
`smart-scroll <https://github.com/yurikhan/kitty-smart-scroll>`_
|
||||||
Makes the kitty scroll bindings work in full screen applications
|
Makes the kitty scroll bindings work in full screen applications
|
||||||
|
|
||||||
`insert password <https://github.com/kovidgoyal/kitty/issues/1222>`_
|
:iss:`insert password <1222>`
|
||||||
Insert a password from a CLI password manager, taking care to only do it at
|
Insert a password from a CLI password manager, taking care to only do it at
|
||||||
a password prompt.
|
a password prompt.
|
||||||
|
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ Major Features
|
|||||||
|
|
||||||
* Displays diffs side-by-side in the kitty terminal
|
* Displays diffs side-by-side in the kitty terminal
|
||||||
|
|
||||||
* Does syntax highlighting of the displayed diffs, asynchronously, for maximum
|
* Does syntax highlighting of the displayed diffs, asynchronously, for
|
||||||
speed
|
maximum speed
|
||||||
|
|
||||||
* Displays images as well as text diffs, even over SSH
|
* Displays images as well as text diffs, even over SSH
|
||||||
|
|
||||||
@@ -31,11 +31,11 @@ Major Features
|
|||||||
Installation
|
Installation
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
Simply :ref:`install kitty <quickstart>`. You also need
|
Simply :ref:`install kitty <quickstart>`. You also need to have either the `git
|
||||||
to have either the `git <https://git-scm.com/>`_ program or the ``diff`` program
|
<https://git-scm.com/>`__ program or the :program:`diff` program installed.
|
||||||
installed. Additionally, for syntax highlighting to work,
|
Additionally, for syntax highlighting to work, `pygments
|
||||||
`pygments <https://pygments.org/>`_ must be installed (note that pygments is
|
<https://pygments.org/>`__ must be installed (note that pygments is included in
|
||||||
included in the macOS kitty app).
|
the official kitty binary builds).
|
||||||
|
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
@@ -45,9 +45,10 @@ In the kitty terminal, run::
|
|||||||
|
|
||||||
kitty +kitten diff file1 file2
|
kitty +kitten diff file1 file2
|
||||||
|
|
||||||
to see the diff between file1 and file2.
|
to see the diff between :file:`file1` and :file:`file2`.
|
||||||
|
|
||||||
Create an alias in your shell's startup file to shorten the command, for example:
|
Create an alias in your shell's startup file to shorten the command, for
|
||||||
|
example:
|
||||||
|
|
||||||
.. code-block:: sh
|
.. code-block:: sh
|
||||||
|
|
||||||
@@ -67,33 +68,33 @@ Keyboard controls
|
|||||||
========================= ===========================
|
========================= ===========================
|
||||||
Action Shortcut
|
Action Shortcut
|
||||||
========================= ===========================
|
========================= ===========================
|
||||||
Quit :kbd:`q, Ctrl+c, Esc`
|
Quit :kbd:`Q`, :kbd:`Ctrl+C`, :kbd:`Esc`
|
||||||
Scroll line up :kbd:`k, up`
|
Scroll line up :kbd:`K`, :kbd:`Up`
|
||||||
Scroll line down :kbd:`j, down`
|
Scroll line down :kbd:`J`, :kbd:`Down`
|
||||||
Scroll page up :kbd:`PgUp`
|
Scroll page up :kbd:`PgUp`
|
||||||
Scroll page down :kbd:`PgDn`
|
Scroll page down :kbd:`PgDn`
|
||||||
Scroll to top :kbd:`Home`
|
Scroll to top :kbd:`Home`
|
||||||
Scroll to bottom :kbd:`End`
|
Scroll to bottom :kbd:`End`
|
||||||
Scroll to next page :kbd:`Space, PgDn`
|
Scroll to next page :kbd:`Space`, :kbd:`PgDn`
|
||||||
Scroll to previous page :kbd:`PgUp`
|
Scroll to previous page :kbd:`PgUp`
|
||||||
Scroll to next change :kbd:`n`
|
Scroll to next change :kbd:`N`
|
||||||
Scroll to previous change :kbd:`p`
|
Scroll to previous change :kbd:`P`
|
||||||
Increase lines of context :kbd:`+`
|
Increase lines of context :kbd:`+`
|
||||||
Decrease lines of context :kbd:`-`
|
Decrease lines of context :kbd:`-`
|
||||||
All lines of context :kbd:`a`
|
All lines of context :kbd:`A`
|
||||||
Restore default context :kbd:`=`
|
Restore default context :kbd:`=`
|
||||||
Search forwards :kbd:`/`
|
Search forwards :kbd:`/`
|
||||||
Search backwards :kbd:`?`
|
Search backwards :kbd:`?`
|
||||||
Clear search :kbd:`Esc`
|
Clear search :kbd:`Esc`
|
||||||
Scroll to next match :kbd:`>, .`
|
Scroll to next match :kbd:`>`, :kbd:`.`
|
||||||
Scroll to previous match :kbd:`<, ,`
|
Scroll to previous match :kbd:`<`, :kbd:`,`
|
||||||
========================= ===========================
|
========================= ===========================
|
||||||
|
|
||||||
|
|
||||||
Integrating with git
|
Integrating with git
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
Add the following to `~/.gitconfig`:
|
Add the following to :file:`~/.gitconfig`:
|
||||||
|
|
||||||
.. code-block:: ini
|
.. code-block:: ini
|
||||||
|
|
||||||
@@ -119,24 +120,23 @@ Why does this work only in kitty?
|
|||||||
----------------------------------------
|
----------------------------------------
|
||||||
|
|
||||||
The diff kitten makes use of various features that are :doc:`kitty only
|
The diff kitten makes use of various features that are :doc:`kitty only
|
||||||
</protocol-extensions>`, such as the :doc:`kitty graphics protocol
|
</protocol-extensions>`, such as the :doc:`kitty graphics protocol
|
||||||
</graphics-protocol>`, the :doc:`extended keyboard protocol
|
</graphics-protocol>`, the :doc:`extended keyboard protocol
|
||||||
</keyboard-protocol>`, etc. It also leverages terminal program
|
</keyboard-protocol>`, etc. It also leverages terminal program infrastructure
|
||||||
infrastructure I created for all of kitty's other kittens to reduce the amount
|
I created for all of kitty's other kittens to reduce the amount of code needed
|
||||||
of code needed (the entire implementation is under 2000 lines of code).
|
(the entire implementation is under 2000 lines of code).
|
||||||
|
|
||||||
And fundamentally, it's kitty only because I wrote it for myself, and I am
|
And fundamentally, it's kitty only because I wrote it for myself, and I am
|
||||||
highly unlikely to use any other terminals :)
|
highly unlikely to use any other terminals :)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Configuration
|
Configuration
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
You can configure the colors used, keyboard shortcuts, the diff implementation,
|
You can configure the colors used, keyboard shortcuts, the diff implementation,
|
||||||
the default lines of context, etc. by creating a :file:`diff.conf` file in
|
the default lines of context, etc. by creating a :file:`diff.conf` file in your
|
||||||
your :ref:`kitty config folder <confloc>`. See below for the supported
|
:ref:`kitty config folder <confloc>`. See below for the supported configuration
|
||||||
configuration directives.
|
directives.
|
||||||
|
|
||||||
|
|
||||||
.. include:: /generated/conf-kitten-diff.rst
|
.. include:: /generated/conf-kitten-diff.rst
|
||||||
@@ -145,7 +145,6 @@ configuration directives.
|
|||||||
.. include:: /generated/cli-kitten-diff.rst
|
.. include:: /generated/cli-kitten-diff.rst
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Sample diff.conf
|
Sample diff.conf
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
Hints
|
Hints
|
||||||
==========
|
==========
|
||||||
|
|
||||||
|kitty| has a *hints mode* to select and act on arbitrary text snippets currently
|
|kitty| has a *hints mode* to select and act on arbitrary text snippets
|
||||||
visible on the screen. For example, you can press :sc:`open_url`
|
currently visible on the screen. For example, you can press :sc:`open_url`
|
||||||
to choose any URL visible on the screen and then open it using your system
|
to choose any URL visible on the screen and then open it using your default web
|
||||||
browser.
|
browser.
|
||||||
|
|
||||||
.. figure:: ../screenshots/hints_mode.png
|
.. figure:: ../screenshots/hints_mode.png
|
||||||
@@ -13,42 +13,51 @@ browser.
|
|||||||
|
|
||||||
URL hints mode
|
URL hints mode
|
||||||
|
|
||||||
Similarly, you can press :sc:`insert_selected_path` to
|
Similarly, you can press :sc:`insert_selected_path` to select anything that
|
||||||
select anything that looks like a path or filename and then insert it into the
|
looks like a path or filename and then insert it into the terminal, very useful
|
||||||
terminal, very useful for picking files from the output of a ``git`` or ``ls`` command and
|
for picking files from the output of a :program:`git` or :program:`ls` command
|
||||||
adding them to the command line for the next command.
|
and adding them to the command line for the next command.
|
||||||
|
|
||||||
You can also press :sc:`goto_file_line` to select anything that looks
|
You can also press :sc:`goto_file_line` to select anything that looks like a
|
||||||
like a path or filename followed by a colon and a line number and open
|
path or filename followed by a colon and a line number and open the file in
|
||||||
the file in vim at the specified line number. The patterns and editor
|
:program:`vim` at the specified line number. The patterns and editor to be used
|
||||||
to be used can be modified using options passed to the kitten. For example::
|
can be modified using options passed to the kitten. For example::
|
||||||
|
|
||||||
map ctrl+g kitten hints --type=linenum --linenum-action=tab nvim +{line} {path}
|
map ctrl+g kitten hints --type=linenum --linenum-action=tab nvim +{line} {path}
|
||||||
|
|
||||||
will open the selected file in a new tab inside neovim when you press
|
will open the selected file in a new tab inside `Neovim <https://neovim.io/>`__
|
||||||
:kbd:`ctrl+g`.
|
when you press :kbd:`Ctrl+G`.
|
||||||
|
|
||||||
Pressing :sc:`open_selected_hyperlink` will open hyperlinks, i.e. a URL
|
Pressing :sc:`open_selected_hyperlink` will open :term:`hyperlinks`, i.e. a URL
|
||||||
that has been marked as such by the program running in the terminal,
|
that has been marked as such by the program running in the terminal,
|
||||||
for example, by ``ls --hyperlink=auto``. You can also :doc:`customize what actions are
|
for example, by ``ls --hyperlink=auto``. If :program:`ls` comes with your OS
|
||||||
taken for different types of URLs <../open_actions>`.
|
does not support hyperlink, you may need to install `GNU Coreutils
|
||||||
|
<https://www.gnu.org/software/coreutils/>`__.
|
||||||
|
|
||||||
|
You can also :doc:`customize what actions are taken for different types of URLs
|
||||||
|
<../open_actions>`.
|
||||||
|
|
||||||
|
.. note:: If there are more hints than letters, hints will use multiple
|
||||||
|
letters. In this case, when you press the first letter, only hints
|
||||||
|
starting with that letter are displayed. Pressing the second letter will
|
||||||
|
select that hint or press :kbd:`Enter` or :kbd:`Space` to select the empty
|
||||||
|
hint.
|
||||||
|
|
||||||
The hints kitten is very powerful to see more detailed help on its various
|
The hints kitten is very powerful to see more detailed help on its various
|
||||||
options and modes of operation, see below. You can use these options to
|
options and modes of operation, see below. You can use these options to
|
||||||
create mappings in :file:`kitty.conf` to select various different text
|
create mappings in :file:`kitty.conf` to select various different text
|
||||||
snippets. See :sc:`insert_selected_path` for examples.
|
snippets. See :sc:`insert_selected_path <insert_selected_path>` for examples.
|
||||||
|
|
||||||
|
|
||||||
Completely customizing the matching and actions of the kitten
|
Completely customizing the matching and actions of the kitten
|
||||||
---------------------------------------------------------------
|
---------------------------------------------------------------
|
||||||
|
|
||||||
The hints kitten supports writing simple python scripts that can be used to
|
The hints kitten supports writing simple Python scripts that can be used to
|
||||||
completely customize how it finds matches and what happens when a match is
|
completely customize how it finds matches and what happens when a match is
|
||||||
selected. This allows the hints kitten to provide the user interface, while
|
selected. This allows the hints kitten to provide the user interface, while you
|
||||||
you can provide the logic for finding matches and performing actions on them.
|
can provide the logic for finding matches and performing actions on them. This
|
||||||
This is best illustrated with an example. Create the file
|
is best illustrated with an example. Create the file :file:`custom-hints.py` in
|
||||||
:file:`custom-hints.py` in the kitty config directory with the following
|
the :ref:`kitty config directory <confloc>` with the following contents:
|
||||||
contents:
|
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
@@ -92,10 +101,10 @@ look it up in the Google dictionary.
|
|||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
To avoid having to specify the same command line options on ever invocation,
|
To avoid having to specify the same command line options on every
|
||||||
you can use the :opt:`kitten_alias` option in :file:`kitty.conf` to create aliases
|
invocation, you can use the :opt:`action_alias` option in
|
||||||
that have common sets of options. For example::
|
:file:`kitty.conf`, creating aliases that have common sets of options.
|
||||||
|
For example::
|
||||||
|
|
||||||
kitten_alias myhints hints --alphabet qfjdkslaureitywovmcxzpq1234567890
|
action_alias myhints kitten hints --alphabet qfjdkslaureitywovmcxzpq1234567890
|
||||||
|
map f1 myhints --customize-processing custom-hints.py
|
||||||
Documentation for the full set of options is below.
|
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
Hyperlinked grep
|
Hyperlinked grep
|
||||||
=================
|
=================
|
||||||
|
|
||||||
|
|
||||||
This kitten allows you to search your files using `ripgrep
|
This kitten allows you to search your files using `ripgrep
|
||||||
<https://www.google.com/search?q=ripgrep>`_ and open the results
|
<https://github.com/BurntSushi/ripgrep>`__ and open the results directly in your
|
||||||
directly in your favorite editor in the terminal, at the line containing
|
favorite editor in the terminal, at the line containing the search result,
|
||||||
the search result, simply by clicking on the result you want.
|
simply by clicking on the result you want.
|
||||||
|
|
||||||
.. versionadded:: 0.19.0
|
.. versionadded:: 0.19.0
|
||||||
|
|
||||||
@@ -25,19 +24,19 @@ following contents:
|
|||||||
mime text/*
|
mime text/*
|
||||||
action launch --type=overlay ${EDITOR} ${FILE_PATH}
|
action launch --type=overlay ${EDITOR} ${FILE_PATH}
|
||||||
|
|
||||||
|
|
||||||
Now, run a search with::
|
Now, run a search with::
|
||||||
|
|
||||||
kitty +kitten hyperlinked_grep something
|
kitty +kitten hyperlinked_grep something
|
||||||
|
|
||||||
Hold down the :kbd:`ctrl+shift` keys and click on any of the
|
Hold down the :kbd:`Ctrl+Shift` keys and click on any of the result lines, to
|
||||||
result lines, to open the file in vim at the matching line. If
|
open the file in :program:`vim` at the matching line. If you use some editor
|
||||||
you use some editor other than vim, you should adjust the
|
other than :program:`vim`, you should adjust the :file:`open-actions.conf` file
|
||||||
:file:`open-actions.conf` file accordingly.
|
accordingly.
|
||||||
|
|
||||||
Finally, add an alias to your shell's rc files to invoke the kitten as ``hg``::
|
Finally, add an alias to your shell's rc files to invoke the kitten as
|
||||||
|
:command:`hg`::
|
||||||
|
|
||||||
alias hg='kitty +kitten hyperlinked_grep'
|
alias hg="kitty +kitten hyperlinked_grep"
|
||||||
|
|
||||||
|
|
||||||
You can now run searches with::
|
You can now run searches with::
|
||||||
@@ -45,27 +44,52 @@ You can now run searches with::
|
|||||||
hg some-search-term
|
hg some-search-term
|
||||||
|
|
||||||
If you want to enable completion, for the kitten, you can delegate completion
|
If you want to enable completion, for the kitten, you can delegate completion
|
||||||
to rg. For that, instead of using an alias create a simple wrapper script named
|
to :program:`rg`. How to do that varies based on the shell:
|
||||||
:file:`hg` somewhere in your ``PATH``:
|
|
||||||
|
|
||||||
.. code-block:: sh
|
|
||||||
|
|
||||||
#!/bin/sh
|
.. tab:: zsh
|
||||||
exec kitty +kitten hyperlinked_grep "$@"
|
|
||||||
|
|
||||||
Then, for example, for ZSH, add the following to :file:`.zshrc`::
|
Instead of using an alias, create a simple wrapper script named
|
||||||
|
:program:`hg` somewhere in your :envvar:`PATH`:
|
||||||
|
|
||||||
compdef _rg hg
|
.. code-block:: sh
|
||||||
|
|
||||||
|
#!/bin/sh
|
||||||
|
exec kitty +kitten hyperlinked_grep "$@"
|
||||||
|
|
||||||
|
Then, add the following to :file:`.zshrc`::
|
||||||
|
|
||||||
|
compdef _rg hg
|
||||||
|
|
||||||
|
.. tab:: fish
|
||||||
|
|
||||||
|
You can combine both the aliasing/wrapping and pointing fish to ripgrep's
|
||||||
|
autocompletion with a fish wrapper function in your :file:`config.fish`
|
||||||
|
or :file:`~/.config/fish/functions/hg.fish`:
|
||||||
|
|
||||||
|
.. code-block:: fish
|
||||||
|
|
||||||
|
function hg --wraps rg; kitty +kitten hyperlinked_grep $argv; end
|
||||||
|
|
||||||
To learn more about kitty's powerful framework for customizing URL click
|
To learn more about kitty's powerful framework for customizing URL click
|
||||||
actions, :doc:`see here </open_actions>`.
|
actions, see :doc:`here </open_actions>`.
|
||||||
|
|
||||||
|
By default, this kitten adds hyperlinks for several parts of ripgrep output:
|
||||||
|
the per-file header, match context lines, and match lines. You can control
|
||||||
|
which items are linked with a :command:`--kitten hyperlink` flag. For example,
|
||||||
|
:command:`--kitten hyperlink=matching_lines` will only add hyperlinks to the
|
||||||
|
match lines. :command:`--kitten hyperlink=file_headers,context_lines` will link
|
||||||
|
file headers and context lines but not match lines. :command:`--kitten
|
||||||
|
hyperlink=none` will cause the command line to be passed to directly to
|
||||||
|
:command:`rg` so no hyperlinking will be performed. :command:`--kitten
|
||||||
|
hyperlink` may be specified multiple times.
|
||||||
|
|
||||||
Hopefully, someday this functionality will make it into some `upstream grep
|
Hopefully, someday this functionality will make it into some `upstream grep
|
||||||
<https://github.com/BurntSushi/ripgrep/issues/665>`_
|
<https://github.com/BurntSushi/ripgrep/issues/665>`__ program directly removing
|
||||||
program directly removing the need for this kitten.
|
the need for this kitten.
|
||||||
|
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
While you can pass any of ripgrep's comand line options to the kitten and
|
While you can pass any of ripgrep's comand line options to the kitten and
|
||||||
they will be forwarded to rg, do not use options that change the output
|
they will be forwarded to :program:`rg`, do not use options that change the
|
||||||
formatting as the kitten works by parsing the output from ripgrep.
|
output formatting as the kitten works by parsing the output from ripgrep.
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ terminal. Using it is as simple as::
|
|||||||
kitty +kitten icat image.jpeg
|
kitty +kitten icat image.jpeg
|
||||||
|
|
||||||
It supports all image types supported by `ImageMagick
|
It supports all image types supported by `ImageMagick
|
||||||
<https://www.imagemagick.org>`_. It even works over SSH. For details, see
|
<https://www.imagemagick.org>`__. It even works over SSH. For details, see the
|
||||||
the :doc:`kitty graphics protocol </graphics-protocol>`.
|
:doc:`kitty graphics protocol </graphics-protocol>`.
|
||||||
|
|
||||||
You might want to create an alias in your shell's configuration files::
|
You might want to create an alias in your shell's configuration files::
|
||||||
|
|
||||||
@@ -20,14 +20,14 @@ Then you can simply use ``icat image.png`` to view images.
|
|||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
`ImageMagick <https://www.imagemagick.org>`_ must be installed for ``icat`` to
|
`ImageMagick <https://www.imagemagick.org>`__ must be installed for icat
|
||||||
work.
|
kitten to work.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
kitty's image display protocol may not work when used within a terminal
|
kitty's image display protocol may not work when used within a terminal
|
||||||
multiplexer such as ``screen`` or ``tmux``, depending on whether the
|
multiplexer such as :program:`screen` or :program:`tmux`, depending on
|
||||||
multiplexer has added support for it or not.
|
whether the multiplexer has added support for it or not.
|
||||||
|
|
||||||
|
|
||||||
.. program:: kitty +kitten icat
|
.. program:: kitty +kitten icat
|
||||||
@@ -35,6 +35,19 @@ Then you can simply use ``icat image.png`` to view images.
|
|||||||
|
|
||||||
The ``icat`` kitten has various command line arguments to allow it to be used
|
The ``icat`` kitten has various command line arguments to allow it to be used
|
||||||
from inside other programs to display images. In particular, :option:`--place`,
|
from inside other programs to display images. In particular, :option:`--place`,
|
||||||
:option:`--detect-support` and :option:`--print-window-size`.
|
:option:`--detect-support`, :option:`--silent` and
|
||||||
|
:option:`--print-window-size`.
|
||||||
|
|
||||||
|
If you are trying to integrate icat into a complex program like a file manager
|
||||||
|
or editor, there are a few things to keep in mind. icat works by communicating
|
||||||
|
over the TTY device, it both writes to and reads from the TTY. So it is
|
||||||
|
imperative that while it is running the host program does not do any TTY I/O.
|
||||||
|
Any key presses or other input from the user on the TTY device will be
|
||||||
|
discarded. At a minimum, you should use the :option:`--silent` and
|
||||||
|
:option:`--transfer-mode` command line arguments. To be really robust you should
|
||||||
|
consider writing proper support for the :doc:`kitty graphics protocol
|
||||||
|
</graphics-protocol>` in the program instead. Nowadays there are many libraries
|
||||||
|
that have support for it.
|
||||||
|
|
||||||
|
|
||||||
.. include:: /generated/cli-kitten-icat.rst
|
.. include:: /generated/cli-kitten-icat.rst
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ Draw a GPU accelerated dock panel on your desktop
|
|||||||
.. highlight:: sh
|
.. highlight:: sh
|
||||||
|
|
||||||
|
|
||||||
You can use this kitten to draw a GPU accelerated panel on the edge
|
You can use this kitten to draw a GPU accelerated panel on the edge of your
|
||||||
of your screen, that shows the output from an arbitrary terminal program.
|
screen, that shows the output from an arbitrary terminal program.
|
||||||
|
|
||||||
It is useful for showing status information or notifications on your desktop
|
It is useful for showing status information or notifications on your desktop
|
||||||
using terminal programs instead of GUI toolkits.
|
using terminal programs instead of GUI toolkits.
|
||||||
@@ -32,8 +32,8 @@ Using this kitten is simple, for example::
|
|||||||
kitty +kitten panel sh -c 'printf "\n\n\nHello, world."; sleep 5s'
|
kitty +kitten panel sh -c 'printf "\n\n\nHello, world."; sleep 5s'
|
||||||
|
|
||||||
This will show ``Hello, world.`` at the top edge of your screen for five
|
This will show ``Hello, world.`` at the top edge of your screen for five
|
||||||
seconds. Here the terminal program we are running is ``sh`` with a script to
|
seconds. Here the terminal program we are running is :program:`sh` with a script
|
||||||
print out ``Hello, world!``. You can make the terminal program as complex as
|
to print out ``Hello, world!``. You can make the terminal program as complex as
|
||||||
you like, as demonstrated in the screenshot above.
|
you like, as demonstrated in the screenshot above.
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
Query terminal
|
Query terminal
|
||||||
=================
|
=================
|
||||||
|
|
||||||
Used to query kitty from terminal programs about version, values of various
|
This kitten is used to query |kitty| from terminal programs about version, values
|
||||||
runtime options controlling its features, etc.
|
of various runtime options controlling its features, etc.
|
||||||
|
|
||||||
The querying is done using the (*semi*) standard XTGETTCAP escape sequence
|
The querying is done using the (*semi*) standard XTGETTCAP escape sequence
|
||||||
pioneered by XTerm, so it works over SSH as well. The downside is that it
|
pioneered by xterm, so it works over SSH as well. The downside is that it is
|
||||||
is slow, since it requires a roundtrip to the terminal emulator and back.
|
slow, since it requires a roundtrip to the terminal emulator and back.
|
||||||
|
|
||||||
If you want to do some of the same querying in your terminal program without
|
If you want to do some of the same querying in your terminal program without
|
||||||
depending on the kitten, you can do so, by processing the same escape codes.
|
depending on the kitten, you can do so, by processing the same escape codes.
|
||||||
Search `this page <https://invisible-island.net/xterm/ctlseqs/ctlseqs.html>`_
|
Search `this page <https://invisible-island.net/xterm/ctlseqs/ctlseqs.html>`__
|
||||||
for *XTGETTCAP* to see the syntax for the escape code and read the source
|
for *XTGETTCAP* to see the syntax for the escape code and read the source of
|
||||||
of this kitten to find the values of the keys for the various queries.
|
this kitten to find the values of the keys for the various queries.
|
||||||
|
|
||||||
|
|
||||||
.. include:: ../generated/cli-kitten-query_terminal.rst
|
.. include:: ../generated/cli-kitten-query_terminal.rst
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
Remote files
|
Remote files
|
||||||
==============
|
==============
|
||||||
|
|
||||||
|kitty| has the ability to easily *Edit*, *Open* or *Download* files
|
|kitty| has the ability to easily *Edit*, *Open* or *Download* files from a
|
||||||
from a computer into which you are SSHed. In your SSH session run::
|
computer into which you are SSHed. In your SSH session run::
|
||||||
|
|
||||||
ls --hyperlink=auto
|
ls --hyperlink=auto
|
||||||
|
|
||||||
Then hold down :kbd:`ctrl+shift` and click the name of the file.
|
Then hold down :kbd:`Ctrl+Shift` and click the name of the file.
|
||||||
|
|
||||||
.. figure:: ../screenshots/remote_file.png
|
.. figure:: ../screenshots/remote_file.png
|
||||||
:alt: Remote file actions
|
:alt: Remote file actions
|
||||||
@@ -19,20 +19,28 @@ Then hold down :kbd:`ctrl+shift` and click the name of the file.
|
|||||||
to *Edit* it in which case kitty will download it and open it locally in your
|
to *Edit* it in which case kitty will download it and open it locally in your
|
||||||
:envvar:`EDITOR`. As you make changes to the file, they are automatically
|
:envvar:`EDITOR`. As you make changes to the file, they are automatically
|
||||||
transferred to the remote computer. Note that this happens without needing
|
transferred to the remote computer. Note that this happens without needing
|
||||||
to install *any* special software on the server, beyond ``ls`` that supports
|
to install *any* special software on the server, beyond :program:`ls` that
|
||||||
hyperlinks.
|
supports hyperlinks.
|
||||||
|
|
||||||
|
.. seealso:: See the :ref:`edit-in-kitty <edit_file>` command
|
||||||
|
|
||||||
|
.. seealso:: See the :doc:`transfer` kitten
|
||||||
|
|
||||||
.. versionadded:: 0.19.0
|
.. versionadded:: 0.19.0
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
Nested SSH sessions are not supported. The kitten will always try to copy
|
For best results, use this kitten with the :doc:`ssh kitten <./ssh>`.
|
||||||
remote files from the first SSH host. This is because there is no way for
|
Otherwise, nested SSH sessions are not supported. The kitten will always try to copy
|
||||||
|kitty| to detect and follow a nested SSH session robustly.
|
remote files from the first SSH host. This is because, without the ssh
|
||||||
|
kitten, there is no way for
|
||||||
|
|kitty| to detect and follow a nested SSH session robustly. Use the
|
||||||
|
:doc:`transfer` kitten for such situations.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
If you have not setup automatic password-less SSH access, then, when
|
If you have not setup automatic password-less SSH access, and are not using
|
||||||
editing starts you will be asked to enter your password just once,
|
the ssh kitten, then, when editing
|
||||||
thereafter the SSH connection will be re-used.
|
starts you will be asked to enter your password just once, thereafter the SSH
|
||||||
|
connection will be re-used.
|
||||||
|
|
||||||
Similarly, you can choose to save the file to the local computer or download
|
Similarly, you can choose to save the file to the local computer or download
|
||||||
and open it in its default file handler.
|
and open it in its default file handler.
|
||||||
|
|||||||
164
docs/kittens/ssh.rst
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
Truly convenient SSH
|
||||||
|
=========================================
|
||||||
|
|
||||||
|
* Automatic :ref:`shell_integration` on remote hosts
|
||||||
|
|
||||||
|
* Easily :ref:`clone local shell/editor config <real_world_ssh_kitten_config>` on remote hosts
|
||||||
|
|
||||||
|
* Automatic :opt:`re-use of existing connections <kitten-ssh.share_connections>` to avoid connection setup latency
|
||||||
|
|
||||||
|
* Make kitty itself available in the remote host :opt:`on demand <kitten-ssh.remote_kitty>`
|
||||||
|
|
||||||
|
* Easily :opt:`change terminal colors <kitten-ssh.color_scheme>` when connecting to remote hosts
|
||||||
|
|
||||||
|
.. versionadded:: 0.25.0
|
||||||
|
Automatic shell integration, file transfer and reuse of connections
|
||||||
|
|
||||||
|
The ssh kitten allows you to login easily to remote hosts, and automatically
|
||||||
|
setup the environment there to be as comfortable as your local shell. You can
|
||||||
|
specify environment variables to set on the remote host and files to copy there,
|
||||||
|
making your remote experience just like your local shell. Additionally, it
|
||||||
|
automatically sets up :ref:`shell_integration` on the remote host and copies the
|
||||||
|
kitty terminfo database there.
|
||||||
|
|
||||||
|
The ssh kitten is a thin wrapper around the traditional `ssh <https://man.openbsd.org/ssh>`__
|
||||||
|
command line program and supports all the same options and arguments and configuration.
|
||||||
|
In interactive usage scenarios it is a drop in replacement for :program:`ssh`.
|
||||||
|
To try it out, simply run:
|
||||||
|
|
||||||
|
.. code-block:: sh
|
||||||
|
|
||||||
|
kitty +kitten ssh some-hostname-to-connect-to
|
||||||
|
|
||||||
|
You should end up at a shell prompt on the remote host, with shell integration
|
||||||
|
enabled. If you like it you can add an alias to it in your shell's rc files:
|
||||||
|
|
||||||
|
.. code-block:: sh
|
||||||
|
|
||||||
|
alias s="kitty +kitten ssh"
|
||||||
|
|
||||||
|
So now you can just type ``s hostname`` to connect.
|
||||||
|
|
||||||
|
If you define a mapping in :file:`kitty.conf` such as::
|
||||||
|
|
||||||
|
map f1 new_window_with_cwd
|
||||||
|
|
||||||
|
Then, pressing :kbd:`F1` will open a new window automatically logged into the
|
||||||
|
same host using the ssh kitten, at the same directory.
|
||||||
|
|
||||||
|
The ssh kitten can be configured using the :file:`~/.config/kitty/ssh.conf` file
|
||||||
|
where you can specify environment variables to set on the remote host and files
|
||||||
|
to copy from the local to the remote host. Let's see a quick example:
|
||||||
|
|
||||||
|
.. code-block:: conf
|
||||||
|
|
||||||
|
# Copy the files and directories needed to setup some common tools
|
||||||
|
copy .zshrc .vimrc .vim
|
||||||
|
# Setup some environment variables
|
||||||
|
env SOME_VAR=x
|
||||||
|
# COPIED_VAR will have the same value on the remote host as it does locally
|
||||||
|
env COPIED_VAR=_kitty_copy_env_var_
|
||||||
|
|
||||||
|
# Create some per hostname settings
|
||||||
|
hostname someserver-*
|
||||||
|
copy env-files
|
||||||
|
env SOMETHING=else
|
||||||
|
|
||||||
|
hostname someuser@somehost
|
||||||
|
copy --dest=foo/bar some-file
|
||||||
|
copy --glob some/files.*
|
||||||
|
|
||||||
|
|
||||||
|
See below for full details on the syntax and options of :file:`ssh.conf`.
|
||||||
|
Additionally, you can pass config options on the command line:
|
||||||
|
|
||||||
|
.. code-block:: sh
|
||||||
|
|
||||||
|
kitty +kitten ssh --kitten interpreter=python servername
|
||||||
|
|
||||||
|
The :code:`--kitten` argument can be specified multiple times, with directives
|
||||||
|
from :file:`ssh.conf`. These are merged with :file:`ssh.conf` as if they were
|
||||||
|
appended to the end of that file. They apply only to the host being SSHed to by
|
||||||
|
this invocation, so any :opt:`hostname <kitten-ssh.hostname>` directives are
|
||||||
|
ignored.
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
Due to limitations in the design of SSH, any typing you do before the
|
||||||
|
shell prompt appears may be lost. So ideally don't start typing till you see
|
||||||
|
the shell prompt. 😇
|
||||||
|
|
||||||
|
|
||||||
|
.. _real_world_ssh_kitten_config:
|
||||||
|
|
||||||
|
A real world example
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
Suppose you often SSH into a production server, and you would like to setup
|
||||||
|
your shell and editor there using your custom settings. However, other people
|
||||||
|
could SSH in as well and you don't want to clobber their settings. Here is how
|
||||||
|
this could be achieved using the ssh kitten with :program:`zsh` and
|
||||||
|
:program:`vim` as the shell and editor, respectively:
|
||||||
|
|
||||||
|
.. code-block:: conf
|
||||||
|
|
||||||
|
# Have these settings apply to servers in my organization
|
||||||
|
hostname myserver-*
|
||||||
|
|
||||||
|
# Setup zsh to read its files from my-conf/zsh
|
||||||
|
env ZDOTDIR $HOME/my-conf/zsh
|
||||||
|
copy --dest my-conf/zsh/.zshrc .zshrc
|
||||||
|
copy --dest my-conf/zsh/.zshenv .zshenv
|
||||||
|
# If you use other zsh init files add them in a similar manner
|
||||||
|
|
||||||
|
# Setup vim to read its config from my-conf/vim
|
||||||
|
env VIMINIT $HOME/my-conf/vim/vimrc
|
||||||
|
env VIMRUNTIME $HOME/my-conf/vim
|
||||||
|
copy --dest my-conf/vim .vim
|
||||||
|
copy --dest my-conf/vim/vimrc .vimrc
|
||||||
|
|
||||||
|
|
||||||
|
How it works
|
||||||
|
----------------
|
||||||
|
|
||||||
|
The ssh kitten works by having SSH transmit and execute a POSIX sh (or
|
||||||
|
:opt:`optionally <kitten-ssh.interpreter>` Python) bootstrap script on the
|
||||||
|
remote host using an :opt:`interpreter <kitten-ssh.interpreter>`. This script
|
||||||
|
reads setup data over the TTY device, which kitty sends as a Base64 encoded
|
||||||
|
compressed tarball. The script extracts it and places the :opt:`files <kitten-ssh.copy>`
|
||||||
|
and sets the :opt:`environment variables <kitten-ssh.env>` before finally
|
||||||
|
launching the :opt:`login shell <kitten-ssh.login_shell>` with :opt:`shell
|
||||||
|
integration <kitten-ssh.shell_integration>` enabled. The data is requested by
|
||||||
|
the kitten over the TTY with a random one time password. kitty reads the request
|
||||||
|
and if the password matches a password pre-stored in shared memory on the
|
||||||
|
localhost by the kitten, the transmission is allowed. If your local
|
||||||
|
`OpenSSH <https://www.openssh.com/>`__ version is >= 8.4 then the data is
|
||||||
|
transmitted instantly without any roundtrip delay.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
When connecting to BSD hosts, it is possible the bootstrap script will fail
|
||||||
|
or run slowly, because the default shells are crippled in various ways.
|
||||||
|
Your best bet is to install Python on the remote, make sure the login shell
|
||||||
|
is something POSIX sh compliant, and use :code:`python` as the
|
||||||
|
:opt:`interpreter <kitten-ssh.interpreter>` in :file:`ssh.conf`.
|
||||||
|
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
This may or may not work when using terminal multiplexers, depending on
|
||||||
|
whether they passthrough the escape codes and if the values of the
|
||||||
|
environment variables :envvar:`KITTY_PID` and :envvar:`KITTY_WINDOW_ID` are
|
||||||
|
correct in the current session (they can be wrong when connecting to a tmux
|
||||||
|
session running in a different window) and the ssh kitten is run in the
|
||||||
|
currently active multiplexer window.
|
||||||
|
|
||||||
|
.. include:: /generated/conf-kitten-ssh.rst
|
||||||
|
|
||||||
|
|
||||||
|
.. _ssh_copy_command:
|
||||||
|
|
||||||
|
The copy command
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
.. include:: /generated/ssh-copy.rst
|
||||||
79
docs/kittens/themes.rst
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
Changing kitty colors
|
||||||
|
========================
|
||||||
|
|
||||||
|
The themes kitten allows you to easily change color themes, from a collection of
|
||||||
|
over two hundred pre-built themes available at `kitty-themes
|
||||||
|
<https://github.com/kovidgoyal/kitty-themes>`_. To use it, simply run::
|
||||||
|
|
||||||
|
kitty +kitten themes
|
||||||
|
|
||||||
|
|
||||||
|
.. image:: ../screenshots/themes.png
|
||||||
|
:alt: The themes kitten in action
|
||||||
|
:width: 600
|
||||||
|
|
||||||
|
The kitten allows you to pick a theme, with live previews of the colors. You can
|
||||||
|
choose between light and dark themes and search by theme name by just typing a
|
||||||
|
few characters from the name.
|
||||||
|
|
||||||
|
The kitten maintains a list of recently used themes to allow quick switching.
|
||||||
|
|
||||||
|
If you want to restore the colors to default, you can do so by choosing the
|
||||||
|
``Default`` theme.
|
||||||
|
|
||||||
|
.. versionadded:: 0.23.0
|
||||||
|
The themes kitten
|
||||||
|
|
||||||
|
|
||||||
|
How it works
|
||||||
|
----------------
|
||||||
|
|
||||||
|
A theme in kitty is just a :file:`.conf` file containing kitty settings.
|
||||||
|
When you select a theme, the kitten simply copies the :file:`.conf` file
|
||||||
|
to :file:`~/.config/kitty/current-theme.conf` and adds an include for
|
||||||
|
:file:`current-theme.conf` to :file:`kitty.conf`. It also comments out any
|
||||||
|
existing color settings in :file:`kitty.conf` so they do not interfere.
|
||||||
|
|
||||||
|
Once that's done, the kitten sends kitty a signal to make it reload its config.
|
||||||
|
|
||||||
|
Using your own themes
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
You can also create your own themes as :file:`.conf` files. Put them in the
|
||||||
|
:file:`themes` sub-directory of the :ref:`kitty config directory <confloc>`,
|
||||||
|
usually, :file:`~/.config/kitty/themes`. The kitten will automatically add them
|
||||||
|
to the list of themes. You can use this to modify the builtin themes, by giving
|
||||||
|
the conf file the name :file:`Some theme name.conf` to override the builtin
|
||||||
|
theme of that name. Note that after doing so you have to run the kitten and
|
||||||
|
choose that theme once for your changes to be applied.
|
||||||
|
|
||||||
|
|
||||||
|
Contributing new themes
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
If you wish to contribute a new theme to the kitty theme repository, start by
|
||||||
|
going to the `kitty-themes <https://github.com/kovidgoyal/kitty-themes>`__
|
||||||
|
repository. `Fork it
|
||||||
|
<https://docs.github.com/en/get-started/quickstart/fork-a-repo>`__, and use the
|
||||||
|
file :download:`template.conf
|
||||||
|
<https://github.com/kovidgoyal/kitty-themes/raw/master/template.conf>` as a
|
||||||
|
template when creating your theme. Once you are satisfied with how it looks,
|
||||||
|
`submit a pull request
|
||||||
|
<https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request>`__
|
||||||
|
to have your theme merged into the `kitty-themes
|
||||||
|
<https://github.com/kovidgoyal/kitty-themes>`__ repository, which will make it
|
||||||
|
available in this kitten automatically.
|
||||||
|
|
||||||
|
|
||||||
|
Changing the theme non-interactively
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
You can specify the theme name as an argument when invoking the kitten to have
|
||||||
|
it change to that theme instantly. For example::
|
||||||
|
|
||||||
|
kitty +kitten themes --reload-in=all Dimmed Monokai
|
||||||
|
|
||||||
|
Will change the theme to ``Dimmed Monokai`` in all running kitty instances. See
|
||||||
|
below for more details on non-interactive operation.
|
||||||
|
|
||||||
|
.. include:: ../generated/cli-kitten-themes.rst
|
||||||
99
docs/kittens/transfer.rst
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
Transfer files
|
||||||
|
================
|
||||||
|
|
||||||
|
.. _rsync: https://en.wikipedia.org/wiki/Rsync
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
This kitten is currently experimental, use with care.
|
||||||
|
|
||||||
|
Transfer files to and from remote computers over the ``TTY`` device itself.
|
||||||
|
This means that file transfer works over nested SSH sessions, serial links,
|
||||||
|
etc. Anywhere you have a terminal device, you can transfer files.
|
||||||
|
|
||||||
|
.. image:: ../screenshots/transfer.png
|
||||||
|
:alt: The transfer kitten at work
|
||||||
|
|
||||||
|
This kitten supports transferring entire directory trees, preserving soft and
|
||||||
|
hard links, file permissions, times, etc. It even supports the rsync_ protocol
|
||||||
|
to transfer only changes to large files.
|
||||||
|
|
||||||
|
.. seealso:: See the :doc:`remote_file` kitten
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
This kitten (which practically means kitty) must be installed on the other
|
||||||
|
machine as well. If that is not possible you can use the :doc:`remote_file`
|
||||||
|
kitten instead. Or write your own script to use the underlying
|
||||||
|
:doc:`file transfer protocol </file-transfer-protocol>`.
|
||||||
|
|
||||||
|
.. versionadded:: 0.24.0
|
||||||
|
|
||||||
|
|
||||||
|
Basic usage
|
||||||
|
---------------
|
||||||
|
|
||||||
|
In what follows, the *local computer* is the computer running this kitten and
|
||||||
|
the *remote computer* is the computer connected to the other end of the TTY
|
||||||
|
pipe.
|
||||||
|
|
||||||
|
To send a file from the local computer to the remote computer, simply run::
|
||||||
|
|
||||||
|
kitty +kitten transfer /path/to/local/file /path/to/destination/on/remote/computer
|
||||||
|
|
||||||
|
You will be prompted by kitty for confirmation on allowing the transfer, and if
|
||||||
|
you grant permission, the file will be copied.
|
||||||
|
|
||||||
|
Similarly, to get a file from the remote computer to the local computer, use
|
||||||
|
the :option:`--direction <kitty +kitten transfer --direction>` option::
|
||||||
|
|
||||||
|
kitty +kitten transfer --direction=receive /path/to/remote/file /path/to/destination/on/local/computer
|
||||||
|
|
||||||
|
Multiple files and even directories can be transferred::
|
||||||
|
|
||||||
|
kitty +kitten transfer file1 dir1 destination/
|
||||||
|
|
||||||
|
Here :file:`file1` will be copied inside :file:`destination` and :file:`dir1`
|
||||||
|
will be recursively copied into :file:`destination`. Note the trailing slash on
|
||||||
|
:file:`destination`. This tells kitty the destination is a directory. While not
|
||||||
|
strictly necessary (kitty will infer the need for a destination directory from
|
||||||
|
the fact that you are copying multiple things) it is good practice to always
|
||||||
|
use a trailing slash when the destination is supposed to be a directory.
|
||||||
|
|
||||||
|
Also, when transferring multiple files/directories it is a good idea to
|
||||||
|
use the :option:`--confirm-paths <kitty +kitten transfer --confirm-paths>`
|
||||||
|
option which will give you an opportunity to review and confirm the files that
|
||||||
|
will be touched.
|
||||||
|
|
||||||
|
|
||||||
|
Avoiding the confirmation prompt
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
Normally, when you start a file transfer kitty will prompt you for confirmation.
|
||||||
|
This is to ensure that hostile programs running on a remote machine cannot
|
||||||
|
read/write files on your computer without your permission. If the remote machine
|
||||||
|
is trusted and the connection between your computer and the remote machine is
|
||||||
|
secure, then you can disable the confirmation prompt by:
|
||||||
|
|
||||||
|
#. Setting the :opt:`file_transfer_confirmation_bypass` option to some password.
|
||||||
|
|
||||||
|
#. When invoking the kitten use the :option:`--permissions-bypass
|
||||||
|
<kitty +kitten transfer --permissions-bypass>` to supply the password you set
|
||||||
|
in step one.
|
||||||
|
|
||||||
|
.. warning:: Using a password to bypass confirmation means any software running
|
||||||
|
on the remote machine could potentially learn that password and use it to
|
||||||
|
gain full access to your computer. Also anyone that can intercept the data
|
||||||
|
stream between your computer and the remote machine can also learn this
|
||||||
|
password. So use it only with secure connections to trusted computers.
|
||||||
|
|
||||||
|
|
||||||
|
Delta transfers
|
||||||
|
-----------------------------------
|
||||||
|
|
||||||
|
This kitten has the ability to use the rsync_ protocol to only transfer the
|
||||||
|
differences between files. To turn it on use the :option:`--transmit-deltas
|
||||||
|
<kitty +kitten transfer --transmit-deltas>` option. Note that this will actually
|
||||||
|
be slower when transferring small files because of round trip overhead, so use
|
||||||
|
with care.
|
||||||
|
|
||||||
|
|
||||||
|
.. include:: ../generated/cli-kitten-transfer.rst
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
Unicode input
|
|
||||||
================
|
|
||||||
|
|
||||||
You can input unicode characters by name, hex code, recently used and even an editable favorites list.
|
|
||||||
Press :sc:`input_unicode_character` to start the unicode input widget, shown below.
|
|
||||||
|
|
||||||
.. figure:: ../screenshots/unicode.png
|
|
||||||
:alt: A screenshot of the unicode input widget
|
|
||||||
:align: center
|
|
||||||
:width: 100%
|
|
||||||
|
|
||||||
A screenshot of the unicode input widget
|
|
||||||
|
|
||||||
In :guilabel:`Code` mode, you enter a unicode character by typing in the hex code for the
|
|
||||||
character and pressing enter, for example, type in ``2716`` and press enter to get
|
|
||||||
✖. You can also choose a character from the list of recently used characters by
|
|
||||||
typing a leading period and then the two character index and pressing Enter.
|
|
||||||
The up and down arrow keys can be used to choose the previous and next unicode
|
|
||||||
symbol respectively.
|
|
||||||
|
|
||||||
In :guilabel:`Name` mode you instead type words from the character name and use
|
|
||||||
the arrow keys/tab to select the character from the displayed matches. You can
|
|
||||||
also type a space followed by a period and the index for the match if you don't
|
|
||||||
like to use arrow keys.
|
|
||||||
|
|
||||||
You can switch between modes using either the function keys or by pressing
|
|
||||||
:kbd:`Ctrl+[` and :kbd:`Ctrl+]` or by pressing :kbd:`Ctrl+Tab` and
|
|
||||||
:kbd:`Ctrl+Shift+Tab`.
|
|
||||||
|
|
||||||
|
|
||||||
.. include:: ../generated/cli-kitten-unicode_input.rst
|
|
||||||
33
docs/kittens/unicode_input.rst
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
Unicode input
|
||||||
|
================
|
||||||
|
|
||||||
|
You can input Unicode characters by name, hex code, recently used and even an
|
||||||
|
editable favorites list. Press :sc:`input_unicode_character` to start the
|
||||||
|
unicode input kitten, shown below.
|
||||||
|
|
||||||
|
.. figure:: ../screenshots/unicode.png
|
||||||
|
:alt: A screenshot of the unicode input kitten
|
||||||
|
:align: center
|
||||||
|
:width: 100%
|
||||||
|
|
||||||
|
A screenshot of the unicode input kitten
|
||||||
|
|
||||||
|
In :guilabel:`Code` mode, you enter a Unicode character by typing in the hex
|
||||||
|
code for the character and pressing :kbd:`Enter`. For example, type in ``2716``
|
||||||
|
and press :kbd:`Enter` to get ``✖``. You can also choose a character from the
|
||||||
|
list of recently used characters by typing a leading period ``.`` and then the
|
||||||
|
two character index and pressing :kbd:`Enter`.
|
||||||
|
The :kbd:`Up` and :kbd:`Down` arrow keys can be used to choose the previous and
|
||||||
|
next Unicode symbol respectively.
|
||||||
|
|
||||||
|
In :guilabel:`Name` mode you instead type words from the character name and use
|
||||||
|
the :kbd:`ArrowKeys` / :kbd:`Tab` to select the character from the displayed
|
||||||
|
matches. You can also type a space followed by a period and the index for the
|
||||||
|
match if you don't like to use arrow keys.
|
||||||
|
|
||||||
|
You can switch between modes using either the keys :kbd:`F1` ... :kbd:`F4` or
|
||||||
|
:kbd:`Ctrl+1` ... :kbd:`Ctrl+4` or by pressing :kbd:`Ctrl+[` and :kbd:`Ctrl+]`
|
||||||
|
or by pressing :kbd:`Ctrl+Tab` and :kbd:`Ctrl+Shift+Tab`.
|
||||||
|
|
||||||
|
|
||||||
|
.. include:: ../generated/cli-kitten-unicode_input.rst
|
||||||
@@ -9,16 +9,19 @@ Extend with kittens
|
|||||||
|
|
||||||
kittens/icat
|
kittens/icat
|
||||||
kittens/diff
|
kittens/diff
|
||||||
kittens/unicode-input
|
kittens/unicode_input
|
||||||
|
kittens/themes
|
||||||
kittens/hints
|
kittens/hints
|
||||||
kittens/remote_file
|
kittens/remote_file
|
||||||
kittens/hyperlinked_grep
|
kittens/hyperlinked_grep
|
||||||
|
kittens/transfer
|
||||||
|
kittens/ssh
|
||||||
kittens/custom
|
kittens/custom
|
||||||
kittens/*
|
kittens/*
|
||||||
|
|
||||||
|kitty| has a framework for easily creating terminal programs that make use of
|
|kitty| has a framework for easily creating terminal programs that make use of
|
||||||
its advanced features. These programs are called kittens. They are used both
|
its advanced features. These programs are called kittens. They are used both to
|
||||||
to add features to |kitty| itself and to create useful standalone programs.
|
add features to |kitty| itself and to create useful standalone programs.
|
||||||
Some prominent kittens:
|
Some prominent kittens:
|
||||||
|
|
||||||
:doc:`icat <kittens/icat>`
|
:doc:`icat <kittens/icat>`
|
||||||
@@ -30,8 +33,8 @@ Some prominent kittens:
|
|||||||
images
|
images
|
||||||
|
|
||||||
|
|
||||||
:doc:`Unicode Input <kittens/unicode-input>`
|
:doc:`Unicode input <kittens/unicode_input>`
|
||||||
Easily input arbitrary unicode characters in |kitty| by name or hex code.
|
Easily input arbitrary Unicode characters in |kitty| by name or hex code.
|
||||||
|
|
||||||
|
|
||||||
:doc:`Hints <kittens/hints>`
|
:doc:`Hints <kittens/hints>`
|
||||||
@@ -44,20 +47,32 @@ Some prominent kittens:
|
|||||||
the filename.
|
the filename.
|
||||||
|
|
||||||
|
|
||||||
|
:doc:`Transfer files <kittens/transfer>`
|
||||||
|
Transfer files and directories seamlessly and easily from remote machines
|
||||||
|
over your existing SSH sessions with a simple command.
|
||||||
|
|
||||||
|
|
||||||
:doc:`Hyperlinked grep <kittens/hyperlinked_grep>`
|
:doc:`Hyperlinked grep <kittens/hyperlinked_grep>`
|
||||||
Search your files using `ripgrep <https://github.com/BurntSushi/ripgrep>`_
|
Search your files using `ripgrep <https://github.com/BurntSushi/ripgrep>`__
|
||||||
and open the results directly in your favorite editor in the terminal,
|
and open the results directly in your favorite editor in the terminal,
|
||||||
at the line containing the search result, simply by clicking on the result you want.
|
at the line containing the search result, simply by clicking on the result
|
||||||
|
you want.
|
||||||
|
|
||||||
|
|
||||||
:doc:`Broadcast <kittens/broadcast>`
|
:doc:`Broadcast <kittens/broadcast>`
|
||||||
Type in one :term:`kitty window <window>` and have it broadcast to all (or a subset) of
|
Type in one :term:`kitty window <window>` and have it broadcast to all (or a
|
||||||
other :term:`kitty windows <window>`.
|
subset) of other :term:`kitty windows <window>`.
|
||||||
|
|
||||||
|
|
||||||
|
:doc:`SSH <kittens/ssh>`
|
||||||
|
SSH with automatic :ref:`shell integration <shell_integration>`, connection
|
||||||
|
re-use for low latency and easy cloning of local shell and editor
|
||||||
|
configuration to the remote host.
|
||||||
|
|
||||||
|
|
||||||
:doc:`Panel <kittens/panel>`
|
:doc:`Panel <kittens/panel>`
|
||||||
Draw a GPU accelerated dock panel on your desktop showing the output
|
Draw a GPU accelerated dock panel on your desktop showing the output from an
|
||||||
from an arbitrary terminal program.
|
arbitrary terminal program.
|
||||||
|
|
||||||
|
|
||||||
:doc:`Clipboard <kittens/clipboard>`
|
:doc:`Clipboard <kittens/clipboard>`
|
||||||
|
|||||||
295
docs/kitty_at_template.py
Normal file
@@ -0,0 +1,295 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# License: GPLv3 Copyright: 2022, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
import argparse
|
||||||
|
import base64
|
||||||
|
import hashlib
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import termios
|
||||||
|
import time
|
||||||
|
import tty
|
||||||
|
from contextlib import contextmanager
|
||||||
|
from ctypes import (
|
||||||
|
CDLL, POINTER, byref, c_char_p, c_int, c_size_t, c_void_p,
|
||||||
|
create_string_buffer
|
||||||
|
)
|
||||||
|
from ctypes.util import find_library
|
||||||
|
|
||||||
|
_plat = sys.platform.lower()
|
||||||
|
is_macos: bool = 'darwin' in _plat
|
||||||
|
|
||||||
|
|
||||||
|
def build_crypto_tools(): # {{{
|
||||||
|
class EVP_PKEY_POINTER(c_void_p):
|
||||||
|
|
||||||
|
algorithm = 0
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
EVP_PKEY_free(self)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def public(self):
|
||||||
|
sz = c_size_t(0)
|
||||||
|
EVP_PKEY_get_raw_public_key(self, None, byref(sz))
|
||||||
|
buf = create_string_buffer(sz.value)
|
||||||
|
EVP_PKEY_get_raw_public_key(self, buf, byref(sz))
|
||||||
|
return buf.raw
|
||||||
|
|
||||||
|
def derive_secret(self, pubkey):
|
||||||
|
pubkey = EVP_PKEY_new_raw_public_key(self.algorithm, None, pubkey, len(pubkey))
|
||||||
|
ctx = EVP_PKEY_CTX_new(self, None)
|
||||||
|
EVP_PKEY_derive_init(ctx)
|
||||||
|
EVP_PKEY_derive_set_peer(ctx, pubkey)
|
||||||
|
sz = c_size_t(0)
|
||||||
|
EVP_PKEY_derive(ctx, None, byref(sz))
|
||||||
|
buf = create_string_buffer(sz.value)
|
||||||
|
EVP_PKEY_derive(ctx, buf, byref(sz))
|
||||||
|
return hashlib.sha256(buf.raw).digest()
|
||||||
|
|
||||||
|
class EVP_PKEY_CTX_POINTER(c_void_p):
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
EVP_PKEY_CTX_free(self)
|
||||||
|
|
||||||
|
class EVP_CIPHER_CTX_POINTER(c_void_p):
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
EVP_CIPHER_CTX_free(self)
|
||||||
|
|
||||||
|
class EVP_CIPHER_POINTER(c_void_p):
|
||||||
|
pass
|
||||||
|
|
||||||
|
cl = find_library('crypto')
|
||||||
|
if not cl:
|
||||||
|
raise SystemExit('Failed to find libcrypto on your system, make sure OpenSSL is installed')
|
||||||
|
crypto = CDLL(cl)
|
||||||
|
libc = CDLL(None)
|
||||||
|
|
||||||
|
def create_crypto_func(name, *argtypes, restype=c_int, int_return_ok=lambda x: x == 1):
|
||||||
|
|
||||||
|
impl = getattr(crypto, name)
|
||||||
|
impl.restype = restype
|
||||||
|
impl.argtypes = argtypes
|
||||||
|
|
||||||
|
def func(*a):
|
||||||
|
res = impl(*a)
|
||||||
|
if restype is c_int:
|
||||||
|
if not int_return_ok(res):
|
||||||
|
print('Call to', name, 'failed with return code:', res, file=sys.stderr)
|
||||||
|
abort_on_openssl_error()
|
||||||
|
elif restype is not None and issubclass(restype, c_void_p):
|
||||||
|
if res.value is None:
|
||||||
|
print('Call to', name, 'failed with NULL return', file=sys.stderr)
|
||||||
|
abort_on_openssl_error()
|
||||||
|
return res
|
||||||
|
return func
|
||||||
|
|
||||||
|
OBJ_txt2nid = create_crypto_func('OBJ_txt2nid', c_char_p, int_return_ok=bool)
|
||||||
|
EVP_PKEY_CTX_new_id = create_crypto_func('EVP_PKEY_CTX_new_id', c_int, c_void_p, restype=EVP_PKEY_CTX_POINTER)
|
||||||
|
EVP_PKEY_CTX_new = create_crypto_func('EVP_PKEY_CTX_new', EVP_PKEY_POINTER, c_void_p, restype=EVP_PKEY_CTX_POINTER)
|
||||||
|
EVP_PKEY_keygen_init = create_crypto_func('EVP_PKEY_keygen_init', EVP_PKEY_CTX_POINTER)
|
||||||
|
EVP_PKEY_keygen = create_crypto_func('EVP_PKEY_keygen', EVP_PKEY_CTX_POINTER, POINTER(EVP_PKEY_POINTER))
|
||||||
|
ERR_print_errors_fp = create_crypto_func('ERR_print_errors_fp', c_void_p, restype=None)
|
||||||
|
EVP_PKEY_free = create_crypto_func('EVP_PKEY_free', EVP_PKEY_POINTER, restype=None)
|
||||||
|
EVP_PKEY_CTX_free = create_crypto_func('EVP_PKEY_CTX_free', EVP_PKEY_CTX_POINTER, restype=None)
|
||||||
|
EVP_PKEY_get_raw_public_key = create_crypto_func('EVP_PKEY_get_raw_public_key', EVP_PKEY_POINTER, c_char_p, POINTER(c_size_t))
|
||||||
|
EVP_PKEY_new_raw_public_key = create_crypto_func('EVP_PKEY_new_raw_public_key', c_int, c_void_p, c_char_p, c_size_t, restype=EVP_PKEY_POINTER)
|
||||||
|
EVP_PKEY_derive_init = create_crypto_func('EVP_PKEY_derive_init', EVP_PKEY_CTX_POINTER)
|
||||||
|
EVP_PKEY_derive_set_peer = create_crypto_func('EVP_PKEY_derive_set_peer', EVP_PKEY_CTX_POINTER, EVP_PKEY_POINTER)
|
||||||
|
EVP_PKEY_derive = create_crypto_func('EVP_PKEY_derive', EVP_PKEY_CTX_POINTER, c_char_p, POINTER(c_size_t))
|
||||||
|
EVP_CIPHER_CTX_free = create_crypto_func('EVP_CIPHER_CTX_free', EVP_CIPHER_CTX_POINTER, restype=None)
|
||||||
|
EVP_get_cipherbyname = create_crypto_func('EVP_get_cipherbyname', c_char_p, restype=EVP_CIPHER_POINTER)
|
||||||
|
EVP_CIPHER_key_length = create_crypto_func('EVP_CIPHER_key_length', EVP_CIPHER_POINTER, int_return_ok=bool)
|
||||||
|
EVP_CIPHER_iv_length = create_crypto_func('EVP_CIPHER_iv_length', EVP_CIPHER_POINTER, int_return_ok=bool)
|
||||||
|
EVP_CIPHER_CTX_block_size = create_crypto_func('EVP_CIPHER_CTX_block_size', EVP_CIPHER_CTX_POINTER, int_return_ok=bool)
|
||||||
|
EVP_CIPHER_CTX_new = create_crypto_func('EVP_CIPHER_CTX_new', restype=EVP_CIPHER_CTX_POINTER)
|
||||||
|
EVP_EncryptInit_ex = create_crypto_func('EVP_EncryptInit_ex', EVP_CIPHER_CTX_POINTER, EVP_CIPHER_POINTER, c_void_p, c_char_p, c_char_p)
|
||||||
|
EVP_EncryptUpdate = create_crypto_func('EVP_EncryptUpdate', EVP_CIPHER_CTX_POINTER, c_char_p, POINTER(c_int), c_char_p, c_int)
|
||||||
|
EVP_EncryptFinal_ex = create_crypto_func('EVP_EncryptFinal_ex', EVP_CIPHER_CTX_POINTER, c_char_p, POINTER(c_int))
|
||||||
|
EVP_CIPHER_CTX_ctrl = create_crypto_func('EVP_CIPHER_CTX_ctrl', EVP_CIPHER_CTX_POINTER, c_int, c_int, c_char_p)
|
||||||
|
try:
|
||||||
|
EVP_CIPHER_CTX_tag_length = create_crypto_func('EVP_CIPHER_CTX_tag_length', EVP_CIPHER_CTX_POINTER, int_return_ok=bool)
|
||||||
|
except AttributeError: # need openssl >= 3
|
||||||
|
def EVP_CIPHER_CTX_tag_length(cipher):
|
||||||
|
return 16
|
||||||
|
EVP_CTRL_AEAD_GET_TAG, EVP_CTRL_AEAD_SET_TAG = 0x10, 0x11 # these are defines in the header dont know how to get them programmatically
|
||||||
|
EVP_CTRL_AEAD_SET_TAG
|
||||||
|
|
||||||
|
def abort_on_openssl_error():
|
||||||
|
stderr = c_void_p.in_dll(libc, 'stderr')
|
||||||
|
ERR_print_errors_fp(stderr)
|
||||||
|
raise SystemExit(1)
|
||||||
|
|
||||||
|
def elliptic_curve_keypair(algorithm='X25519'):
|
||||||
|
nid = OBJ_txt2nid(algorithm.encode())
|
||||||
|
pctx = EVP_PKEY_CTX_new_id(nid, None)
|
||||||
|
EVP_PKEY_keygen_init(pctx)
|
||||||
|
key = EVP_PKEY_POINTER()
|
||||||
|
EVP_PKEY_keygen(pctx, byref(key))
|
||||||
|
key.algorithm = nid
|
||||||
|
return key
|
||||||
|
|
||||||
|
def encrypt(plaintext, symmetric_key, algorithm='aes-256-gcm'):
|
||||||
|
cipher = EVP_get_cipherbyname(algorithm.encode())
|
||||||
|
if len(symmetric_key) != EVP_CIPHER_key_length(cipher):
|
||||||
|
raise KeyError(f'The symmetric key has length {len(symmetric_key)} != {EVP_CIPHER_key_length(cipher)} needed for {algorithm}')
|
||||||
|
ctx = EVP_CIPHER_CTX_new()
|
||||||
|
iv = os.urandom(EVP_CIPHER_iv_length(cipher))
|
||||||
|
EVP_EncryptInit_ex(ctx, cipher, None, symmetric_key, iv)
|
||||||
|
bs = EVP_CIPHER_CTX_block_size(ctx)
|
||||||
|
ciphertext = create_string_buffer(len(plaintext) + 2 * bs)
|
||||||
|
outlen = c_int(len(ciphertext))
|
||||||
|
EVP_EncryptUpdate(ctx, ciphertext, byref(outlen), plaintext, len(plaintext))
|
||||||
|
ans = ciphertext[:outlen.value]
|
||||||
|
outlen = c_int(len(ciphertext))
|
||||||
|
EVP_EncryptFinal_ex(ctx, ciphertext, byref(outlen))
|
||||||
|
if outlen.value:
|
||||||
|
ans += ciphertext[:outlen.value]
|
||||||
|
tag = create_string_buffer(EVP_CIPHER_CTX_tag_length(cipher))
|
||||||
|
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, len(tag), tag)
|
||||||
|
return iv, ans, tag.raw
|
||||||
|
return elliptic_curve_keypair, encrypt
|
||||||
|
# }}}
|
||||||
|
|
||||||
|
|
||||||
|
# utils {{{
|
||||||
|
def encrypt_cmd(cmd, password, pubkey=None):
|
||||||
|
elliptic_curve_keypair, encrypt = build_crypto_tools()
|
||||||
|
if pubkey is None:
|
||||||
|
pubkey = os.environ['KITTY_PUBLIC_KEY']
|
||||||
|
v, d = pubkey.split(':', 1)
|
||||||
|
if v != '1':
|
||||||
|
raise SystemExit(f'Unsupported encryption protocol: {v}')
|
||||||
|
pubkey = base64.b85decode(d)
|
||||||
|
k = elliptic_curve_keypair()
|
||||||
|
sk = k.derive_secret(pubkey)
|
||||||
|
cmd['timestamp'] = time.time_ns()
|
||||||
|
cmd['password'] = password
|
||||||
|
data = json.dumps(cmd).encode()
|
||||||
|
iv, encrypted, tag = encrypt(data, sk)
|
||||||
|
|
||||||
|
def e(x):
|
||||||
|
return base64.b85encode(x).decode('ascii')
|
||||||
|
|
||||||
|
return {
|
||||||
|
'encrypted': e(encrypted), 'iv': e(iv), 'tag': e(tag), 'pubkey': e(k.public), 'version': cmd['version']
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@contextmanager
|
||||||
|
def raw_mode(fd):
|
||||||
|
old = termios.tcgetattr(fd)
|
||||||
|
try:
|
||||||
|
tty.setraw(fd)
|
||||||
|
yield
|
||||||
|
finally:
|
||||||
|
termios.tcsetattr(fd, termios.TCSADRAIN, old)
|
||||||
|
|
||||||
|
|
||||||
|
def config_dir():
|
||||||
|
if 'KITTY_CONFIG_DIRECTORY' in os.environ:
|
||||||
|
return os.path.abspath(os.path.expanduser(os.environ['KITTY_CONFIG_DIRECTORY']))
|
||||||
|
locations = []
|
||||||
|
if 'XDG_CONFIG_HOME' in os.environ:
|
||||||
|
locations.append(os.path.abspath(os.path.expanduser(os.environ['XDG_CONFIG_HOME'])))
|
||||||
|
locations.append(os.path.expanduser('~/.config'))
|
||||||
|
if is_macos:
|
||||||
|
locations.append(os.path.expanduser('~/Library/Preferences'))
|
||||||
|
for loc in filter(None, os.environ.get('XDG_CONFIG_DIRS', '').split(os.pathsep)):
|
||||||
|
locations.append(os.path.abspath(os.path.expanduser(loc)))
|
||||||
|
for loc in locations:
|
||||||
|
if loc:
|
||||||
|
q = os.path.join(loc, 'kitty')
|
||||||
|
if os.access(q, os.W_OK) and os.path.exists(os.path.join(q, 'kitty.conf')):
|
||||||
|
return q
|
||||||
|
for loc in locations:
|
||||||
|
if loc:
|
||||||
|
q = os.path.join(loc, 'kitty')
|
||||||
|
if os.path.isdir(q) and os.access(q, os.W_OK):
|
||||||
|
return q
|
||||||
|
return ''
|
||||||
|
|
||||||
|
|
||||||
|
def resolve_custom_file(path):
|
||||||
|
path = os.path.expanduser(path)
|
||||||
|
path = os.path.expandvars(path)
|
||||||
|
if not os.path.isabs(path):
|
||||||
|
cdir = config_dir()
|
||||||
|
if cdir:
|
||||||
|
path = os.path.join(cdir, path)
|
||||||
|
return path
|
||||||
|
|
||||||
|
|
||||||
|
def get_password(opts):
|
||||||
|
if opts.use_password == 'never':
|
||||||
|
return ''
|
||||||
|
ans = ''
|
||||||
|
if opts.password:
|
||||||
|
ans = opts.password
|
||||||
|
if not ans and opts.password_file:
|
||||||
|
if opts.password_file == '-':
|
||||||
|
if sys.stdin.isatty():
|
||||||
|
from getpass import getpass
|
||||||
|
ans = getpass()
|
||||||
|
else:
|
||||||
|
ans = sys.stdin.read().rstrip()
|
||||||
|
try:
|
||||||
|
tty_fd = os.open(os.ctermid(), os.O_RDONLY | os.O_CLOEXEC)
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
with open(tty_fd, closefd=True):
|
||||||
|
os.dup2(tty_fd, sys.stdin.fileno())
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
with open(resolve_custom_file(opts.password_file)) as f:
|
||||||
|
ans = f.read().rstrip()
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
if not ans and opts.password_env:
|
||||||
|
ans = os.environ.get(opts.password_env, '')
|
||||||
|
if not ans and opts.use_password == 'always':
|
||||||
|
raise SystemExit('No password was found')
|
||||||
|
if ans and len(ans) > 1024:
|
||||||
|
raise SystemExit('Specified password is too long')
|
||||||
|
return ans
|
||||||
|
# }}}
|
||||||
|
|
||||||
|
|
||||||
|
arg_parser = argparse.ArgumentParser(prog='kitty@', description='Control kitty remotely.')
|
||||||
|
arg_parser.add_argument('--password', default='', help='''\
|
||||||
|
A password to use when contacting kitty. This will cause kitty to ask the user
|
||||||
|
for permission to perform the specified action, unless the password has been
|
||||||
|
accepted before or is pre-configured in kitty.conf''')
|
||||||
|
arg_parser.add_argument('--password-file', default='rc-pass', help='''\
|
||||||
|
A file from which to read the password. Trailing whitespace is ignored. Relative
|
||||||
|
paths are resolved from the kitty configuration directory. Use - to read from STDIN.
|
||||||
|
Used if no --password is supplied. Defaults to checking for the
|
||||||
|
rc-pass file in the kitty configuration directory.''')
|
||||||
|
arg_parser.add_argument('--password-env', default='KITTY_RC_PASSWORD', help='''\
|
||||||
|
The name of an environment variable to read the password from.
|
||||||
|
Used if no --password-file is supplied. Defaults to checking the KITTY_RC_PASSWORD.''')
|
||||||
|
arg_parser.add_argument('--use-password', default='if-available', choices=('if-available', 'always', 'never'), help='''\
|
||||||
|
If no password is available, kitty will usually just send the remote control command
|
||||||
|
without a password. This option can be used to force it to always or never use
|
||||||
|
the supplied password.''')
|
||||||
|
|
||||||
|
args = arg_parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
def populate_cmd(cmd):
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
|
password = get_password(args)
|
||||||
|
cmd = {'version': [0, 20, 0]} # use a random version that's fairly old
|
||||||
|
populate_cmd(cmd)
|
||||||
|
if password:
|
||||||
|
encrypt_cmd(cmd, password)
|
||||||
|
|
||||||
|
# cmd = {'version': [0, 14, 2], 'cmd': 'ls'}
|
||||||
|
# cmd = encrypt_cmd(cmd, 'test')
|
||||||
|
# with open(os.open(os.ctermid(), os.O_RDWR | os.O_CLOEXEC), 'w') as tty_file, raw_mode(tty_file.fileno()):
|
||||||
|
# print(end=f'\x1bP@kitty-cmd{json.dumps(cmd)}\x1b\\', flush=True, file=tty_file)
|
||||||
|
# os.read(tty_file.fileno(), 4096)
|
||||||
100
docs/launch.rst
@@ -5,22 +5,21 @@ The :command:`launch` command
|
|||||||
|
|
||||||
|
|
||||||
|kitty| has a :code:`launch` action that can be used to run arbitrary programs
|
|kitty| has a :code:`launch` action that can be used to run arbitrary programs
|
||||||
in new windows/tabs. It can be mapped to user defined shortcuts in kitty.conf.
|
in new windows/tabs. It can be mapped to user defined shortcuts in
|
||||||
It is very powerful and allows sending the contents of
|
:file:`kitty.conf`. It is very powerful and allows sending the contents of the
|
||||||
the current window to the launched program, as well as many other options.
|
current window to the launched program, as well as many other options.
|
||||||
|
|
||||||
In the simplest form, you can use it to open a new kitty window running the
|
In the simplest form, you can use it to open a new kitty window running the
|
||||||
shell, as shown below::
|
shell, as shown below::
|
||||||
|
|
||||||
map f1 launch
|
map f1 launch
|
||||||
|
|
||||||
To run a different program simply pass the command line as arguments to
|
To run a different program simply pass the command line as arguments to launch::
|
||||||
launch::
|
|
||||||
|
|
||||||
map f1 launch vim path/to/some/file
|
map f1 launch vim path/to/some/file
|
||||||
|
|
||||||
To open a new window with the same working directory as the currently
|
To open a new window with the same working directory as the currently active
|
||||||
active window::
|
window::
|
||||||
|
|
||||||
map f1 launch --cwd=current
|
map f1 launch --cwd=current
|
||||||
|
|
||||||
@@ -30,20 +29,33 @@ To open the new window in a new tab::
|
|||||||
|
|
||||||
To run multiple commands in a shell, use::
|
To run multiple commands in a shell, use::
|
||||||
|
|
||||||
map f1 launch sh -c "ls && zsh"
|
map f1 launch sh -c "ls && exec zsh"
|
||||||
|
|
||||||
To pass the contents of the current screen and scrollback to the started process::
|
To pass the contents of the current screen and scrollback to the started
|
||||||
|
process::
|
||||||
|
|
||||||
map f1 launch --stdin-source=@screen_scrollback less
|
map f1 launch --stdin-source=@screen_scrollback less
|
||||||
|
|
||||||
There are many more powerful options, refer to the complete list below.
|
There are many more powerful options, refer to the complete list below.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
To avoid duplicating launch actions with frequently used parameters, you can
|
||||||
|
use :opt:`action_alias` to define launch action aliases. For example::
|
||||||
|
|
||||||
|
action_alias launch_tab launch --cwd=current --type=tab
|
||||||
|
map f1 launch_tab vim
|
||||||
|
map f2 launch_tab emacs
|
||||||
|
|
||||||
|
The :kbd:`F1` key will now open :program:`vim` in a new tab with the current
|
||||||
|
windows working directory.
|
||||||
|
|
||||||
|
|
||||||
The piping environment
|
The piping environment
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
When using :option:`launch --stdin-source`, the program to which the data is
|
When using :option:`launch --stdin-source`, the program to which the data is
|
||||||
piped has a special environment variable declared, :envvar:`KITTY_PIPE_DATA` whose
|
piped has a special environment variable declared, :envvar:`KITTY_PIPE_DATA`
|
||||||
contents are::
|
whose contents are::
|
||||||
|
|
||||||
KITTY_PIPE_DATA={scrolled_by}:{cursor_x},{cursor_y}:{lines},{columns}
|
KITTY_PIPE_DATA={scrolled_by}:{cursor_x},{cursor_y}:{lines},{columns}
|
||||||
|
|
||||||
@@ -61,27 +73,33 @@ the command line:
|
|||||||
|
|
||||||
|
|
||||||
``@selection``
|
``@selection``
|
||||||
replaced by the currently selected text
|
Replaced by the currently selected text.
|
||||||
|
|
||||||
``@active-kitty-window-id``
|
``@active-kitty-window-id``
|
||||||
replaced by the id of the currently active kitty window
|
Replaced by the id of the currently active kitty window.
|
||||||
|
|
||||||
``@line-count``
|
``@line-count``
|
||||||
replaced by the number of lines in STDIN. Only present when passing some
|
Replaced by the number of lines in STDIN. Only present when passing some
|
||||||
data to STDIN
|
data to STDIN.
|
||||||
|
|
||||||
``@input-line-number``
|
``@input-line-number``
|
||||||
replaced the number of lines a pager should scroll to match the current
|
Replaced the number of lines a pager should scroll to match the current
|
||||||
scroll position in kitty. See :opt:`scrollback_pager` for details
|
scroll position in kitty. See :opt:`scrollback_pager` for details.
|
||||||
|
|
||||||
``@scrolled-by``
|
``@scrolled-by``
|
||||||
replaced by the number of lines kitty is currently scrolled by
|
Replaced by the number of lines kitty is currently scrolled by.
|
||||||
|
|
||||||
``@cursor-x``
|
``@cursor-x``
|
||||||
replaced by the current cursor x position with 1 being the leftmost cell
|
Replaced by the current cursor x position with 1 being the leftmost cell.
|
||||||
|
|
||||||
``@cursor-y``
|
``@cursor-y``
|
||||||
replaced by the current cursor y position with 1 being the topmost cell
|
Replaced by the current cursor y position with 1 being the topmost cell.
|
||||||
|
|
||||||
|
``@first-line-on-screen``
|
||||||
|
Replaced by the first line on screen. Can be used for pager positioning.
|
||||||
|
|
||||||
|
``@last-line-on-screen``
|
||||||
|
Replaced by the last line on screen. Can be used for pager positioning.
|
||||||
|
|
||||||
|
|
||||||
For example::
|
For example::
|
||||||
@@ -89,47 +107,57 @@ For example::
|
|||||||
map f1 launch my-program @active-kitty-window-id
|
map f1 launch my-program @active-kitty-window-id
|
||||||
|
|
||||||
|
|
||||||
|
.. _watchers:
|
||||||
|
|
||||||
Watching launched windows
|
Watching launched windows
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
The :option:`launch --watcher` option allows you to specify python functions
|
The :option:`launch --watcher` option allows you to specify Python functions
|
||||||
that will be called at specific events, such as when the window is resized or
|
that will be called at specific events, such as when the window is resized or
|
||||||
closed. Simply specify the path to a python module that specifies callback
|
closed. Simply specify the path to a Python module that specifies callback
|
||||||
functions for the events you are interested in, for example:
|
functions for the events you are interested in, for example:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
def on_resize(boss, window, data):
|
from typing import Any, Dict
|
||||||
|
|
||||||
|
from kitty.boss import Boss
|
||||||
|
from kitty.window import Window
|
||||||
|
|
||||||
|
|
||||||
|
def on_resize(boss: Boss, window: Window, data: Dict[str, Any]) -> None:
|
||||||
# Here data will contain old_geometry and new_geometry
|
# Here data will contain old_geometry and new_geometry
|
||||||
|
|
||||||
def on_focus_change(boss, window, data):
|
def on_focus_change(boss: Boss, window: Window, data: Dict[str, Any])-> None:
|
||||||
# Here data kill contain focused
|
# Here data will contain focused
|
||||||
|
|
||||||
def on_close(boss, window, data):
|
def on_close(boss: Boss, window: Window, data: Dict[str, Any])-> None:
|
||||||
# called when window is closed, typically when the program running in
|
# called when window is closed, typically when the program running in
|
||||||
# it exits.
|
# it exits.
|
||||||
|
|
||||||
|
|
||||||
Every callback is passed a reference to the global ``Boss`` object as well as
|
Every callback is passed a reference to the global ``Boss`` object as well as
|
||||||
the ``Window`` object the action is occurring on. The ``data`` object is
|
the ``Window`` object the action is occurring on. The ``data`` object is a dict
|
||||||
mapping that contains event dependent data. Some useful methods and attributes
|
that contains event dependent data. Some useful methods and attributes for the
|
||||||
for the ``Window`` object are: ``as_text(as_ans=False, add_history=False,
|
``Window`` object are: ``as_text(as_ans=False, add_history=False,
|
||||||
add_wrap_markers=False, alternate_screen=False)`` with which you can get the
|
add_wrap_markers=False, alternate_screen=False)`` with which you can get the
|
||||||
contents of the window and its scrollback buffer. Similarly,
|
contents of the window and its scrollback buffer. Similarly,
|
||||||
``window.child.pid`` is the PID of the processes that was launched
|
``window.child.pid`` is the PID of the processes that was launched
|
||||||
in the window and ``window.id`` is the internal kitty ``id`` of the
|
in the window and ``window.id`` is the internal kitty ``id`` of the window.
|
||||||
window.
|
|
||||||
|
|
||||||
|
|
||||||
Finding executables
|
Finding executables
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
When you specify a command to run as just a name rather than an absolute path,
|
When you specify a command to run as just a name rather than an absolute path,
|
||||||
it is searched for in the system-wide ``PATH`` environment variable. Note that
|
it is searched for in the system-wide :envvar:`PATH` environment variable. Note
|
||||||
this **may not** be the value of ``PATH`` inside a shell, as shell startup scripts
|
that this **may not** be the value of :envvar:`PATH` inside a shell, as shell
|
||||||
often change the value of this variable. If it is not found there, then a
|
startup scripts often change the value of this variable. If it is not found
|
||||||
system specific list of default paths is searched. If it is still not found,
|
there, then a system specific list of default paths is searched. If it is still
|
||||||
then your shell is run and the value of ``PATH`` inside the shell is used.
|
not found, then your shell is run and the value of :envvar:`PATH` inside the
|
||||||
|
shell is used.
|
||||||
|
|
||||||
|
See :opt:`exe_search_path` for details and how to control this.
|
||||||
|
|
||||||
Syntax reference
|
Syntax reference
|
||||||
------------------
|
------------------
|
||||||
|
|||||||
124
docs/layouts.rst
@@ -10,7 +10,8 @@ other in arbitrary arrangements, based on *Layouts*, see below for examples:
|
|||||||
:align: center
|
:align: center
|
||||||
:width: 100%
|
:width: 100%
|
||||||
|
|
||||||
Screenshot, showing vim, tig and git running in |kitty| with the 'Tall' layout
|
Screenshot, showing :program:`vim`, :program:`tig` and :program:`git`
|
||||||
|
running in |kitty| with the *Tall* layout
|
||||||
|
|
||||||
|
|
||||||
.. figure:: screenshots/splits.png
|
.. figure:: screenshots/splits.png
|
||||||
@@ -18,21 +19,22 @@ other in arbitrary arrangements, based on *Layouts*, see below for examples:
|
|||||||
:align: center
|
:align: center
|
||||||
:width: 100%
|
:width: 100%
|
||||||
|
|
||||||
Screenshot, showing windows with arbitrary arrangement in the 'Splits'
|
Screenshot, showing windows with arbitrary arrangement in the *Splits*
|
||||||
layout
|
layout
|
||||||
|
|
||||||
|
|
||||||
There are many different layouts available. They are all enabled by default,
|
There are many different layouts available. They are all enabled by default, you
|
||||||
you can switch layouts using :sc:`next_layout`. To control which layouts
|
can switch layouts using :ac:`next_layout` (:sc:`next_layout` by default). To
|
||||||
are available use :opt:`enabled_layouts`, the first listed layout becomes
|
control which layouts are available use :opt:`enabled_layouts`, the first listed
|
||||||
the default. Individual layouts and how to use them are described below.
|
layout becomes the default. Individual layouts and how to use them are described
|
||||||
|
below.
|
||||||
|
|
||||||
|
|
||||||
The Stack Layout
|
The Stack Layout
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
This is the simplest layout it displays a single window using all available
|
This is the simplest layout. It displays a single window using all available
|
||||||
space, other windows are hidden behind it. It has no options::
|
space, other windows are hidden behind it. This layout has no options::
|
||||||
|
|
||||||
enabled_layouts stack
|
enabled_layouts stack
|
||||||
|
|
||||||
@@ -40,14 +42,14 @@ space, other windows are hidden behind it. It has no options::
|
|||||||
The Tall Layout
|
The Tall Layout
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
Displays one (or optionally more) full height windows on the left half of the
|
Displays one (or optionally more) full-height windows on the left half of the
|
||||||
screen. Remaining windows are tiled vertically on the right half of the screen.
|
screen. Remaining windows are tiled vertically on the right half of the screen.
|
||||||
There are options to control how the screen is split horizontally ``bias``
|
There are options to control how the screen is split horizontally ``bias``
|
||||||
(an integer between ``10`` and ``90``) and options to control how many
|
(an integer between ``10`` and ``90``) and options to control how many
|
||||||
full-height windows there are ``full_size`` (a positive integer). The
|
full-height windows there are ``full_size`` (a positive integer). The
|
||||||
``mirrored`` option when set to ``true`` will cause the short windows to be
|
``mirrored`` option when set to ``true`` will cause the full-height windows to
|
||||||
on the left side of the screen instead of the right. The syntax
|
be on the right side of the screen instead of the left. The syntax
|
||||||
for the options is shown below::
|
for the options is::
|
||||||
|
|
||||||
enabled_layouts tall:bias=50;full_size=1;mirrored=false
|
enabled_layouts tall:bias=50;full_size=1;mirrored=false
|
||||||
|
|
||||||
@@ -65,24 +67,32 @@ for the options is shown below::
|
|||||||
│ │ │
|
│ │ │
|
||||||
└──────────────┴───────────────┘
|
└──────────────┴───────────────┘
|
||||||
|
|
||||||
In addition, you can map keys to increase or decrease the number of full size
|
In addition, you can map keys to increase or decrease the number of full-height
|
||||||
windows, for example::
|
windows, or toggle the mirrored setting, for example::
|
||||||
|
|
||||||
map ctrl+[ layout_action decrease_num_full_size_windows
|
map ctrl+[ layout_action decrease_num_full_size_windows
|
||||||
map ctrl+] layout_action increase_num_full_size_windows
|
map ctrl+] layout_action increase_num_full_size_windows
|
||||||
|
map ctrl+/ layout_action mirror toggle
|
||||||
|
map ctrl+y layout_action mirror true
|
||||||
|
map ctrl+n layout_action mirror false
|
||||||
|
|
||||||
|
You can also map a key to change the bias by providing a list of percentages
|
||||||
|
and it will rotate through the list as you press the key. If you only provide
|
||||||
|
one number it'll toggle between that percentage and 50, for example::
|
||||||
|
|
||||||
|
map ctrl+. layout_action bias 50 62 70
|
||||||
|
map ctrl+, layout_action bias 62
|
||||||
|
|
||||||
The Fat Layout
|
The Fat Layout
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
Displays one (or optionally more) full width windows on the top half of the
|
Displays one (or optionally more) full-width windows on the top half of the
|
||||||
screen. Remaining windows are tiled horizontally on the bottom half of the screen.
|
screen. Remaining windows are tiled horizontally on the bottom half of the
|
||||||
There are options to control how the screen is split vertically ``bias``
|
screen. There are options to control how the screen is split vertically ``bias``
|
||||||
(an integer between ``10`` and ``90``) and options to control how many
|
(an integer between ``10`` and ``90``) and options to control how many
|
||||||
full-height windows there are ``full_size`` (a positive integer). The
|
full-width windows there are ``full_size`` (a positive integer). The
|
||||||
``mirrored`` option when set to ``true`` will cause the narrow windows to be
|
``mirrored`` option when set to ``true`` will cause the full-width windows to be
|
||||||
on the top of the screen instead of the bottom. The syntax for the options is
|
on the bottom of the screen instead of the top. The syntax for the options is::
|
||||||
shown below::
|
|
||||||
|
|
||||||
enabled_layouts fat:bias=50;full_size=1;mirrored=false
|
enabled_layouts fat:bias=50;full_size=1;mirrored=false
|
||||||
|
|
||||||
@@ -100,11 +110,15 @@ shown below::
|
|||||||
└─────────┴──────────┴─────────┘
|
└─────────┴──────────┴─────────┘
|
||||||
|
|
||||||
|
|
||||||
|
This layout also supports the same layout actions as the *Tall* layout, shown above.
|
||||||
|
|
||||||
|
|
||||||
The Grid Layout
|
The Grid Layout
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
Display windows in a balanced grid with all windows the same size except the
|
Display windows in a balanced grid with all windows the same size except the
|
||||||
last column if there are not enough windows to fill the grid. Has no options::
|
last column if there are not enough windows to fill the grid. This layout has no
|
||||||
|
options::
|
||||||
|
|
||||||
enabled_layouts grid
|
enabled_layouts grid
|
||||||
|
|
||||||
@@ -128,30 +142,47 @@ The Splits Layout
|
|||||||
|
|
||||||
This is the most flexible layout. You can create any arrangement of windows
|
This is the most flexible layout. You can create any arrangement of windows
|
||||||
by splitting exiting windows repeatedly. To best use this layout you should
|
by splitting exiting windows repeatedly. To best use this layout you should
|
||||||
define a few extra keybindings in :file:`kitty.conf`::
|
define a few extra key bindings in :file:`kitty.conf`::
|
||||||
|
|
||||||
map F5 launch --location=hsplit
|
# Create a new window splitting the space used by the existing one so that
|
||||||
map F6 launch --location=vsplit
|
# the two windows are placed one above the other
|
||||||
map F7 layout_action rotate
|
map f5 launch --location=hsplit
|
||||||
|
|
||||||
|
# Create a new window splitting the space used by the existing one so that
|
||||||
|
# the two windows are placed side by side
|
||||||
|
map f6 launch --location=vsplit
|
||||||
|
|
||||||
|
# Create a new window splitting the space used by the existing one so that
|
||||||
|
# the two windows are placed side by side if the existing window is wide or
|
||||||
|
# one above the other if the existing window is tall.
|
||||||
|
map f4 launch --location=split
|
||||||
|
|
||||||
|
# Rotate the current split, chaging its split axis from vertical to
|
||||||
|
# horizontal or vice versa
|
||||||
|
map f7 layout_action rotate
|
||||||
|
|
||||||
|
# Move the active window in the indicated direction
|
||||||
map shift+up move_window up
|
map shift+up move_window up
|
||||||
map shift+left move_window left
|
map shift+left move_window left
|
||||||
map shift+right move_window right
|
map shift+right move_window right
|
||||||
map shift+down move_window down
|
map shift+down move_window down
|
||||||
|
|
||||||
|
# Switch focus to the neighboring window in the indicated direction
|
||||||
map ctrl+left neighboring_window left
|
map ctrl+left neighboring_window left
|
||||||
map ctrl+right neighboring_window right
|
map ctrl+right neighboring_window right
|
||||||
map ctrl+up neighboring_window up
|
map ctrl+up neighboring_window up
|
||||||
map ctrl+down neighboring_window down
|
map ctrl+down neighboring_window down
|
||||||
|
|
||||||
Now you can create horizontal and vertical splits by using :kbd:`F5` and
|
Windows can be resized using :ref:`window_resizing`. You can swap the windows
|
||||||
:kbd:`F6`. You can move them around using :kbd:`shift+arrow keys`
|
in a split using the ``rotate`` action with an argument of ``180`` and rotate
|
||||||
and you can move focus to neighboring windows using :kbd:`ctrl+arrow keys`.
|
and swap with an argument of ``270``.
|
||||||
You can switch an existing split from horizontal to vertical and vice versa
|
|
||||||
using :kbd:`F7`. Finally, windows can be resized using :ref:`window_resizing`.
|
|
||||||
|
|
||||||
This layout takes one option, ``split_axis`` that controls whether new windows
|
This layout takes one option, ``split_axis`` that controls whether new windows
|
||||||
are placed into vertical or horizontal splits, by default::
|
are placed into vertical or horizontal splits when a :option:`--location <launch
|
||||||
|
--location>` is not specified. A value of ``horizontal`` (same as
|
||||||
|
``--location=vsplit``) means when a new split is created the two windows will be
|
||||||
|
placed side by side and a value of ``vertical`` (same as ``--location=hsplit``)
|
||||||
|
means the two windows will be placed one on top of the other. By default::
|
||||||
|
|
||||||
enabled_layouts splits:split_axis=horizontal
|
enabled_layouts splits:split_axis=horizontal
|
||||||
|
|
||||||
@@ -176,7 +207,7 @@ are placed into vertical or horizontal splits, by default::
|
|||||||
The Horizontal Layout
|
The Horizontal Layout
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
All windows are shown side by side. Has no options::
|
All windows are shown side by side. This layout has no options::
|
||||||
|
|
||||||
enabled_layouts horizontal
|
enabled_layouts horizontal
|
||||||
|
|
||||||
@@ -196,7 +227,7 @@ All windows are shown side by side. Has no options::
|
|||||||
The Vertical Layout
|
The Vertical Layout
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
All windows are shown one below the other. Has no options::
|
All windows are shown one below the other. This layout has no options::
|
||||||
|
|
||||||
enabled_layouts vertical
|
enabled_layouts vertical
|
||||||
|
|
||||||
@@ -222,37 +253,38 @@ Resizing windows
|
|||||||
|
|
||||||
You can resize windows inside layouts. Press :sc:`start_resizing_window` (also
|
You can resize windows inside layouts. Press :sc:`start_resizing_window` (also
|
||||||
:kbd:`⌘+r` on macOS) to enter resizing mode and follow the on-screen
|
:kbd:`⌘+r` on macOS) to enter resizing mode and follow the on-screen
|
||||||
instructions. In a given window layout only some operations may be possible
|
instructions. In a given window layout only some operations may be possible for
|
||||||
for a particular window. For example, in the Tall layout you can make the first
|
a particular window. For example, in the *Tall* layout you can make the first
|
||||||
window wider/narrower, but not taller/shorter. Note that what you are resizing
|
window wider/narrower, but not taller/shorter. Note that what you are resizing
|
||||||
is actually not a window, but a row/column in the layout, all windows in that
|
is actually not a window, but a row/column in the layout, all windows in that
|
||||||
row/column will be resized.
|
row/column will be resized.
|
||||||
|
|
||||||
You can also define shortcuts in :file:`kitty.conf` to make the active window
|
You can also define shortcuts in :file:`kitty.conf` to make the active window
|
||||||
wider, narrower, taller, or shorter by mapping to the ``resize_window``
|
wider, narrower, taller, or shorter by mapping to the :ac:`resize_window`
|
||||||
action, for example::
|
action, for example::
|
||||||
|
|
||||||
map ctrl+left resize_window narrower
|
map ctrl+left resize_window narrower
|
||||||
map ctrl+right resize_window wider
|
map ctrl+right resize_window wider
|
||||||
map ctrl+up resize_window taller
|
map ctrl+up resize_window taller
|
||||||
map ctrl+down resize_window shorter 3
|
map ctrl+down resize_window shorter 3
|
||||||
|
# reset all windows in the tab to default sizes
|
||||||
|
map ctrl+home resize_window reset
|
||||||
|
|
||||||
The ``resize_window`` action has a second, optional argument to control
|
The :ac:`resize_window` action has a second optional argument to control
|
||||||
the resizing increment (a positive integer that defaults to 1).
|
the resizing increment (a positive integer that defaults to 1).
|
||||||
|
|
||||||
|
Some layouts take options to control their behavior. For example, the *Fat*
|
||||||
Some layouts take options to control their behavior. For example, the ``fat``
|
and *Tall* layouts accept the ``bias`` and ``full_size`` options to control
|
||||||
and ``tall`` layouts accept the ``bias`` and ``full_size`` options to control
|
how the available space is split up. To specify the option, in :opt:`kitty.conf
|
||||||
how the available space is split up.
|
<enabled_layouts>` use::
|
||||||
To specify the option, in :opt:`kitty.conf <enabled_layouts>` use::
|
|
||||||
|
|
||||||
enabled_layouts tall:bias=70;full_size=2
|
enabled_layouts tall:bias=70;full_size=2
|
||||||
|
|
||||||
This will have ``2`` instead of a single tall window, that occupy ``70%``
|
This will have ``2`` instead of a single tall window, that occupy ``70%``
|
||||||
instead of ``50%`` of available width. ``bias`` can be any number between 10
|
instead of ``50%`` of available width. ``bias`` can be any number between ``10``
|
||||||
and 90.
|
and ``90``.
|
||||||
|
|
||||||
Writing a new layout only requires about two hundred lines of code, so if there
|
Writing a new layout only requires about two hundred lines of code, so if there
|
||||||
is some layout you want, take a look at one of the existing layouts in the
|
is some layout you want, take a look at one of the existing layouts in the
|
||||||
`layout <https://github.com/kovidgoyal/kitty/tree/master/kitty/layout>`_
|
`layout <https://github.com/kovidgoyal/kitty/tree/master/kitty/layout>`__
|
||||||
package and submit a pull request!
|
package and submit a pull request!
|
||||||
|
|||||||
@@ -9,12 +9,12 @@ running programs or similar. Lets start with a few examples:
|
|||||||
Examples
|
Examples
|
||||||
----------
|
----------
|
||||||
|
|
||||||
Suppose we want to be able to highlight the word ERROR in the current window.
|
Suppose we want to be able to highlight the word :code:`ERROR` in the current
|
||||||
Add the following to :file:`kitty.conf`::
|
window. Add the following to :file:`kitty.conf`::
|
||||||
|
|
||||||
map f1 toggle_marker text 1 ERROR
|
map f1 toggle_marker text 1 ERROR
|
||||||
|
|
||||||
Now when you press :kbd:`F1` all instances of the word :code:`ERROR` will be
|
Now when you press :kbd:`F1`, all instances of the word :code:`ERROR` will be
|
||||||
highlighted. To turn off the highlighting, press :kbd:`F1` again.
|
highlighted. To turn off the highlighting, press :kbd:`F1` again.
|
||||||
If you want to make it case-insensitive, use::
|
If you want to make it case-insensitive, use::
|
||||||
|
|
||||||
@@ -39,41 +39,40 @@ can control the colors used for these groups in :file:`kitty.conf` with::
|
|||||||
|
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
For performance reasons, matching is done per line only, and only when that line is
|
For performance reasons, matching is done per line only, and only when that
|
||||||
altered in any way. So you cannot match text that stretches across multiple
|
line is altered in any way. So you cannot match text that stretches across
|
||||||
lines.
|
multiple lines.
|
||||||
|
|
||||||
|
|
||||||
Creating markers dynamically
|
Creating markers dynamically
|
||||||
---------------------------------
|
---------------------------------
|
||||||
|
|
||||||
If you want to create markers dynamically rather than pre-defining them in
|
If you want to create markers dynamically rather than pre-defining them in
|
||||||
:file:`kitty.conf` you can do so as follows::
|
:file:`kitty.conf`, you can do so as follows::
|
||||||
|
|
||||||
map f1 create_marker
|
map f1 create_marker
|
||||||
map f2 remove_marker
|
map f2 remove_marker
|
||||||
|
|
||||||
Then pressing :kbd:`F1` will allow you to enter the marker definition and set
|
Then pressing :kbd:`F1` will allow you to enter the marker definition and set it
|
||||||
it and pressing :kbd:`F2` will remove the marker. ``create_marker`` accepts
|
and pressing :kbd:`F2` will remove the marker. :ac:`create_marker` accepts the
|
||||||
the same syntax as ``toggle_marker`` above. Note that while creating
|
same syntax as :ac:`toggle_marker` above. Note that while creating markers, the
|
||||||
markers, the prompt has history so you can easily re-use previous marker
|
prompt has history so you can easily re-use previous marker expressions.
|
||||||
expressions.
|
|
||||||
|
|
||||||
You can also use the facilities for :doc:`remote-control` to dynamically
|
You can also use the facilities for :doc:`remote-control` to dynamically add or
|
||||||
add/remove markers.
|
remove markers.
|
||||||
|
|
||||||
|
|
||||||
Scrolling to marks
|
Scrolling to marks
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
kitty has an action to scroll to the next line that contains a mark. You can
|
kitty has a :ac:`scroll_to_mark` action to scroll to the next line that contains
|
||||||
use it by mapping it to some shortcut in :file:`kitty.conf`::
|
a mark. You can use it by mapping it to some shortcut in :file:`kitty.conf`::
|
||||||
|
|
||||||
map ctrl+p scroll_to_mark prev
|
map ctrl+p scroll_to_mark prev
|
||||||
map ctrl+n scroll_to_mark next
|
map ctrl+n scroll_to_mark next
|
||||||
|
|
||||||
Then pressing :kbd:`ctrl+p` will scroll to the first line in the scrollback
|
Then pressing :kbd:`Ctrl+P` will scroll to the first line in the scrollback
|
||||||
buffer above the current top line that contains a mark. Pressing :kbd:`ctrl+n`
|
buffer above the current top line that contains a mark. Pressing :kbd:`Ctrl+N`
|
||||||
will scroll to show the first line below the current last line that contains
|
will scroll to show the first line below the current last line that contains
|
||||||
a mark. If you wish to jump to a mark of a specific type, you can add that to
|
a mark. If you wish to jump to a mark of a specific type, you can add that to
|
||||||
the mapping::
|
the mapping::
|
||||||
@@ -86,26 +85,26 @@ Which will scroll only to marks of type 1.
|
|||||||
The full syntax for creating marks
|
The full syntax for creating marks
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
|
|
||||||
The syntax of the :code:`toggle_marker` command is::
|
The syntax of the :ac:`toggle_marker` action is::
|
||||||
|
|
||||||
toggle_marker <marker-type> <specification>
|
toggle_marker <marker-type> <specification>
|
||||||
|
|
||||||
Here :code:`marker-type` is one of:
|
Here :code:`marker-type` is one of:
|
||||||
|
|
||||||
* :code:`text` - simple substring matching
|
* :code:`text` - Simple substring matching
|
||||||
* :code:`itext` - case-insensitive substring matching
|
* :code:`itext` - Case-insensitive substring matching
|
||||||
* :code:`regex` - A python regular expression
|
* :code:`regex` - A Python regular expression
|
||||||
* :code:`iregex` - A case-insensitive python regular expression
|
* :code:`iregex` - A case-insensitive Python regular expression
|
||||||
* :code:`function` - An arbitrary function defined in a python file, see :ref:`marker_funcs`.
|
* :code:`function` - An arbitrary function defined in a Python file, see :ref:`marker_funcs`.
|
||||||
|
|
||||||
.. _marker_funcs:
|
.. _marker_funcs:
|
||||||
|
|
||||||
Arbitrary marker functions
|
Arbitrary marker functions
|
||||||
-----------------------------
|
-----------------------------
|
||||||
|
|
||||||
You can create your own marker functions. Create a python file named
|
You can create your own marker functions. Create a Python file named
|
||||||
:file:`mymarker.py` and in it create a :code:`marker` function. This
|
:file:`mymarker.py` and in it create a :code:`marker` function. This function
|
||||||
function receives the text of the line as input and must yield three numbers,
|
receives the text of the line as input and must yield three numbers,
|
||||||
the starting character position, the ending character position and the mark
|
the starting character position, the ending character position and the mark
|
||||||
group (1-3). For example:
|
group (1-3). For example:
|
||||||
|
|
||||||
@@ -122,6 +121,7 @@ Save this file somewhere and in :file:`kitty.conf`, use::
|
|||||||
|
|
||||||
map f1 toggle_marker function /path/to/mymarker.py
|
map f1 toggle_marker function /path/to/mymarker.py
|
||||||
|
|
||||||
If you save the file in the kitty config directory, you can use::
|
If you save the file in the :ref:`kitty config directory <confloc>`, you can
|
||||||
|
use::
|
||||||
|
|
||||||
map f1 toggle_marker function mymarker.py
|
map f1 toggle_marker function mymarker.py
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
Scripting the mouse click
|
Scripting the mouse click
|
||||||
======================================================
|
======================================================
|
||||||
|
|
||||||
|kitty| has support for `terminal hyperlinks
|
|kitty| has support for :term:`terminal hyperlinks <hyperlinks>`. These are
|
||||||
<https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda>`_. These
|
generated by many terminal programs, such as ``ls``, ``gcc``, ``systemd``,
|
||||||
are generated by many terminal programs, such as ``ls``, ``gcc``, ``systemd``,
|
:ref:`tool_mdcat`, etc. You can customize exactly what happens when clicking on
|
||||||
:ref:`tool_mdcat`, etc. You can customize exactly what happens when clicking on these
|
these hyperlinks in |kitty|.
|
||||||
hyperlinks in |kitty|.
|
|
||||||
|
|
||||||
You can tell kitty to take arbitrarily many, complex actions
|
You can tell kitty to take arbitrarily many, complex actions when a link is
|
||||||
when a link is clicked. Let us illustrate with some examples, first. Create
|
clicked. Let us illustrate with some examples, first. Create the file
|
||||||
the file :file:`~/.config/kitty/open-actions.conf` with the following:
|
:file:`~/.config/kitty/open-actions.conf` with the following:
|
||||||
|
|
||||||
.. code:: conf
|
.. code:: conf
|
||||||
|
|
||||||
@@ -22,6 +21,13 @@ Now, run ``ls --hyperlink=auto`` in kitty and click on the filename of an
|
|||||||
image, holding down :kbd:`ctrl+shift`. It will be opened over the current
|
image, holding down :kbd:`ctrl+shift`. It will be opened over the current
|
||||||
window. Press any key to close it.
|
window. Press any key to close it.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
The :program:`ls` comes with macOS does not support hyperlink, you need to
|
||||||
|
install `GNU Coreutils <https://www.gnu.org/software/coreutils/>`__. If you
|
||||||
|
install it via `Homebrew <https://formulae.brew.sh/formula/coreutils>`__, it
|
||||||
|
will be :program:`gls`.
|
||||||
|
|
||||||
Each entry in :file:`open-actions.conf` consists of one or more
|
Each entry in :file:`open-actions.conf` consists of one or more
|
||||||
:ref:`matching_criteria`, such as ``protocol`` and ``mime`` and one or more
|
:ref:`matching_criteria`, such as ``protocol`` and ``mime`` and one or more
|
||||||
``action`` entries. In the example above kitty uses the :doc:`launch <launch>`
|
``action`` entries. In the example above kitty uses the :doc:`launch <launch>`
|
||||||
@@ -29,8 +35,8 @@ action which can be used to run external programs. Entries are separated by
|
|||||||
blank lines.
|
blank lines.
|
||||||
|
|
||||||
Actions are very powerful, anything that you can map to a key combination in
|
Actions are very powerful, anything that you can map to a key combination in
|
||||||
`kitty.conf` can be used as an action. You can specify more than one action per
|
:file:`kitty.conf` can be used as an action. You can specify more than one
|
||||||
entry if you like, for example:
|
action per entry if you like, for example:
|
||||||
|
|
||||||
|
|
||||||
.. code:: conf
|
.. code:: conf
|
||||||
@@ -58,6 +64,16 @@ some special variables, documented below:
|
|||||||
``FRAGMENT``
|
``FRAGMENT``
|
||||||
The fragment (unquoted), if any of the URL or the empty string.
|
The fragment (unquoted), if any of the URL or the empty string.
|
||||||
|
|
||||||
|
``URL_PATH``
|
||||||
|
The path, query and fragment portions of the URL, without any
|
||||||
|
unquoting.
|
||||||
|
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
You can use the :opt:`action_alias` option just as in :file:`kitty.conf` to
|
||||||
|
define aliases for frequently used actions.
|
||||||
|
|
||||||
|
|
||||||
.. _matching_criteria:
|
.. _matching_criteria:
|
||||||
|
|
||||||
Matching criteria
|
Matching criteria
|
||||||
@@ -71,7 +87,7 @@ lines. The various available criteria are:
|
|||||||
|
|
||||||
``protocol``
|
``protocol``
|
||||||
A comma separated list of protocols, for example: ``http, https``. If
|
A comma separated list of protocols, for example: ``http, https``. If
|
||||||
absent, there is no constraint on protocol
|
absent, there is no constraint on protocol.
|
||||||
|
|
||||||
``url``
|
``url``
|
||||||
A regular expression that must match against the entire (unquoted) URL
|
A regular expression that must match against the entire (unquoted) URL
|
||||||
@@ -82,11 +98,12 @@ lines. The various available criteria are:
|
|||||||
|
|
||||||
``mime``
|
``mime``
|
||||||
A comma separated list of MIME types, for example: ``text/*, image/*,
|
A comma separated list of MIME types, for example: ``text/*, image/*,
|
||||||
application/pdf``. You can add MIME types to kitty by creating the
|
application/pdf``. You can add MIME types to kitty by creating a file named
|
||||||
:file:`mime.types` in the kitty configuration directory. Useful if your
|
:file:`mime.types` in the :ref:`kitty configuration directory <confloc>`.
|
||||||
system MIME database does not have definitions you need. This file is
|
Useful if your system MIME database does not have definitions you need. This
|
||||||
in the standard format of one definition per line, like: ``text/plain rst
|
file is in the standard format of one definition per line, like:
|
||||||
md``. Note that the MIME type for directories is ``inode/directory``.
|
``text/plain rst md``. Note that the MIME type for directories is
|
||||||
|
``inode/directory``.
|
||||||
|
|
||||||
``ext``
|
``ext``
|
||||||
A comma separated list of file extensions, for example: ``jpeg, tar.gz``
|
A comma separated list of file extensions, for example: ``jpeg, tar.gz``
|
||||||
@@ -94,3 +111,44 @@ lines. The various available criteria are:
|
|||||||
``file``
|
``file``
|
||||||
A shell glob pattern that must match the filename, for example:
|
A shell glob pattern that must match the filename, for example:
|
||||||
``image-??.png``
|
``image-??.png``
|
||||||
|
|
||||||
|
|
||||||
|
.. _launch_actions:
|
||||||
|
|
||||||
|
Scripting the opening of files with kitty on macOS
|
||||||
|
-------------------------------------------------------
|
||||||
|
|
||||||
|
On macOS you can use :guilabel:`Open With` in Finder or drag and drop files and
|
||||||
|
URLs onto the kitty dock icon to open them with kitty. The default actions are:
|
||||||
|
|
||||||
|
* Open text files in your editor and images using the icat kitten.
|
||||||
|
* Run shell scripts in a shell
|
||||||
|
* Open SSH urls using the ssh command
|
||||||
|
|
||||||
|
These actions can also be executed from the command line by running::
|
||||||
|
|
||||||
|
kitty +open file_or_url another_url ...
|
||||||
|
|
||||||
|
# macOS only
|
||||||
|
open -a kitty.app file_or_url another_url ...
|
||||||
|
|
||||||
|
Since macOS lacks an official interface to set default URL scheme handlers,
|
||||||
|
kitty has a command you can use for it. The first argument for is the URL
|
||||||
|
scheme, and the second optional argument is the bundle id of the app, which
|
||||||
|
defaults to kitty, if not specified. For example:
|
||||||
|
|
||||||
|
.. code-block:: sh
|
||||||
|
|
||||||
|
# Set kitty as the handler for ssh:// URLs
|
||||||
|
kitty +runpy 'from kitty.fast_data_types import cocoa_set_url_handler; import sys; cocoa_set_url_handler(*sys.argv[1:]); print("OK")' ssh
|
||||||
|
# Set someapp as the handler for xyz:// URLs
|
||||||
|
kitty +runpy 'from kitty.fast_data_types import cocoa_set_url_handler; import sys; cocoa_set_url_handler(*sys.argv[1:]); print("OK")' xyz someapp.bundle.identifier
|
||||||
|
|
||||||
|
You can customize these actions by creating a :file:`launch-actions.conf` file
|
||||||
|
in the :ref:`kitty config directory <confloc>`, just like the
|
||||||
|
:file:`open-actions.conf` file above. For example:
|
||||||
|
|
||||||
|
.. literalinclude:: ../kitty/open_actions.py
|
||||||
|
:language: conf
|
||||||
|
:start-at: # Open script files
|
||||||
|
:end-before: '''.splitlines()))
|
||||||
|
|||||||
@@ -4,23 +4,22 @@ Overview
|
|||||||
Design philosophy
|
Design philosophy
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|kitty| is designed for power keyboard users. To that end all its controls
|
|kitty| is designed for power keyboard users. To that end all its controls work
|
||||||
work with the keyboard (although it fully supports mouse interactions as
|
with the keyboard (although it fully supports mouse interactions as well). Its
|
||||||
well). Its configuration is a simple, human editable, single file for
|
configuration is a simple, human editable, single file for easy reproducibility
|
||||||
easy reproducibility (I like to store configuration in source control).
|
(I like to store configuration in source control).
|
||||||
|
|
||||||
The code in |kitty| is designed to be simple, modular and hackable. It is
|
The code in |kitty| is designed to be simple, modular and hackable. It is
|
||||||
written in a mix of C (for performance sensitive parts) and Python (for
|
written in a mix of C (for performance sensitive parts) and Python (for easy
|
||||||
easy hackability of the UI). It does not depend on any large and complex
|
hackability of the UI). It does not depend on any large and complex UI toolkit,
|
||||||
UI toolkit, using only OpenGL for rendering everything.
|
using only OpenGL for rendering everything.
|
||||||
|
|
||||||
Finally, |kitty| is designed from the ground up to support all modern
|
Finally, |kitty| is designed from the ground up to support all modern terminal
|
||||||
terminal features, such as unicode, true color, bold/italic fonts, text
|
features, such as Unicode, true color, bold/italic fonts, text formatting, etc.
|
||||||
formatting, etc. It even extends existing text formatting escape codes,
|
It even extends existing text formatting escape codes, to add support for
|
||||||
to add support for features not available elsewhere, such as colored and
|
features not available elsewhere, such as colored and styled (curly) underlines.
|
||||||
styled (curly) underlines. One of the design goals of |kitty| is to be
|
One of the design goals of |kitty| is to be easily extensible so that new
|
||||||
easily extensible so that new features can be added in the future with
|
features can be added in the future with relatively little effort.
|
||||||
relatively little effort.
|
|
||||||
|
|
||||||
.. include:: basic.rst
|
.. include:: basic.rst
|
||||||
|
|
||||||
@@ -28,10 +27,10 @@ relatively little effort.
|
|||||||
Configuring kitty
|
Configuring kitty
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|kitty| is highly configurable, everything from keyboard shortcuts to
|
|kitty| is highly configurable, everything from keyboard shortcuts to painting
|
||||||
painting frames-per-second. Press :sc:`edit_config_file` in kitty
|
frames-per-second. Press :sc:`edit_config_file` in kitty to open its fully
|
||||||
to open its fully commented sample config file in your text editor.
|
commented sample config file in your text editor. For details see the
|
||||||
For details see the :doc:`configuration docs <conf>`.
|
:doc:`configuration docs <conf>`.
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:hidden:
|
:hidden:
|
||||||
@@ -51,17 +50,26 @@ windows automatically, resizing and moving them as needed. You can create a new
|
|||||||
|
|
||||||
Currently, there are seven layouts available:
|
Currently, there are seven layouts available:
|
||||||
|
|
||||||
* **Fat** -- One (or optionally more) windows are shown full width on the top, the rest of the windows are shown side-by-side on the bottom
|
* **Fat** -- One (or optionally more) windows are shown full width on the top,
|
||||||
|
the rest of the windows are shown side-by-side on the bottom
|
||||||
|
|
||||||
* **Grid** -- All windows are shown in a grid
|
* **Grid** -- All windows are shown in a grid
|
||||||
|
|
||||||
* **Horizontal** -- All windows are shown side-by-side
|
* **Horizontal** -- All windows are shown side-by-side
|
||||||
* **Splits** -- Windows arranged in arbitrary patterns created using horizontal and vertical splits
|
|
||||||
|
* **Splits** -- Windows arranged in arbitrary patterns created using horizontal
|
||||||
|
and vertical splits
|
||||||
|
|
||||||
* **Stack** -- Only a single maximized window is shown at a time
|
* **Stack** -- Only a single maximized window is shown at a time
|
||||||
* **Tall** -- One (or optionally more) windows are shown full height on the left, the rest of the windows are shown one below the other on the right
|
|
||||||
|
* **Tall** -- One (or optionally more) windows are shown full height on the
|
||||||
|
left, the rest of the windows are shown one below the other on the right
|
||||||
|
|
||||||
* **Vertical** -- All windows are shown one below the other
|
* **Vertical** -- All windows are shown one below the other
|
||||||
|
|
||||||
By default, all layouts are enabled and you can switch between layouts using
|
By default, all layouts are enabled and you can switch between layouts using
|
||||||
the :sc:`next_layout` key combination. You can also create shortcuts to select
|
the :sc:`next_layout` key combination. You can also create shortcuts to select
|
||||||
particular layouts, and choose which layouts you want to enable/disable, see
|
particular layouts, and choose which layouts you want to enable, see
|
||||||
:ref:`conf-kitty-shortcuts.layout` for examples. The first layout listed in
|
:ref:`conf-kitty-shortcuts.layout` for examples. The first layout listed in
|
||||||
:opt:`enabled_layouts` becomes the default layout.
|
:opt:`enabled_layouts` becomes the default layout.
|
||||||
|
|
||||||
@@ -79,9 +87,9 @@ Extending kitty
|
|||||||
kitty has a powerful framework for scripting. You can create small terminal
|
kitty has a powerful framework for scripting. You can create small terminal
|
||||||
programs called :doc:`kittens <kittens_intro>`. These can used to add features
|
programs called :doc:`kittens <kittens_intro>`. These can used to add features
|
||||||
to kitty, for example, :doc:`editing remote files <kittens/remote_file>` or
|
to kitty, for example, :doc:`editing remote files <kittens/remote_file>` or
|
||||||
:doc:`inputting unicode characters <kittens/unicode-input>`. They can also be
|
:doc:`inputting Unicode characters <kittens/unicode_input>`. They can also be
|
||||||
used to create programs that leverage kitty's powerful features, for example,
|
used to create programs that leverage kitty's powerful features, for example,
|
||||||
:doc:`viewing images <kittens/icat>` or :doc:`diffing files with images
|
:doc:`viewing images <kittens/icat>` or :doc:`diffing files with image support
|
||||||
<kittens/diff>`.
|
<kittens/diff>`.
|
||||||
|
|
||||||
You can :doc:`create your own kittens to scratch your own itches
|
You can :doc:`create your own kittens to scratch your own itches
|
||||||
@@ -101,9 +109,9 @@ Remote control
|
|||||||
|kitty| has a very powerful system that allows you to control it from the
|
|kitty| has a very powerful system that allows you to control it from the
|
||||||
:doc:`shell prompt, even over SSH <remote-control>`. You can change colors,
|
:doc:`shell prompt, even over SSH <remote-control>`. You can change colors,
|
||||||
fonts, open new :term:`windows <window>`, :term:`tabs <tab>`, set their titles,
|
fonts, open new :term:`windows <window>`, :term:`tabs <tab>`, set their titles,
|
||||||
change window layout, get text
|
change window layout, get text from one window and send text to another, etc.
|
||||||
from one window and send text to another, etc, etc. The possibilities are
|
The possibilities are endless. See the :doc:`tutorial <remote-control>` to get
|
||||||
endless. See the :doc:`tutorial <remote-control>` to get started.
|
started.
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:hidden:
|
:hidden:
|
||||||
@@ -116,11 +124,10 @@ endless. See the :doc:`tutorial <remote-control>` to get started.
|
|||||||
Startup Sessions
|
Startup Sessions
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
You can control the :term:`tabs <tab>`, `:term:`kitty window <window>` layout,
|
You can control the :term:`tabs <tab>`, :term:`kitty window <window>` layout,
|
||||||
working directory, startup programs,
|
working directory, startup programs, etc. by creating a *session* file and using
|
||||||
etc. by creating a "session" file and using the :option:`kitty --session`
|
the :option:`kitty --session` command line flag or the :opt:`startup_session`
|
||||||
command line flag or the :opt:`startup_session` option in :file:`kitty.conf`.
|
option in :file:`kitty.conf`. For example:
|
||||||
For example:
|
|
||||||
|
|
||||||
.. code-block:: session
|
.. code-block:: session
|
||||||
|
|
||||||
@@ -130,37 +137,39 @@ For example:
|
|||||||
cd ~
|
cd ~
|
||||||
# Create a window and run the specified command in it
|
# Create a window and run the specified command in it
|
||||||
launch zsh
|
launch zsh
|
||||||
# Create a window with some environment variables set and run
|
# Create a window with some environment variables set and run vim in it
|
||||||
# vim in it
|
|
||||||
launch --env FOO=BAR vim
|
launch --env FOO=BAR vim
|
||||||
# Set the title for the next window
|
# Set the title for the next window
|
||||||
launch --title "Chat with x" irssi --profile x
|
launch --title "Chat with x" irssi --profile x
|
||||||
|
|
||||||
# Create a new tab (the part after new_tab is the optional tab
|
# Create a new tab
|
||||||
# name which will be displayed in the tab bar, if omitted, the
|
# The part after new_tab is the optional tab title which will be displayed in
|
||||||
# title of the active window will be used instead)
|
# the tab bar, if omitted, the title of the active window will be used instead.
|
||||||
new_tab my tab
|
new_tab my tab
|
||||||
cd ~/somewhere
|
cd ~/somewhere
|
||||||
# Set the layouts allowed in this tab
|
# Set the layouts allowed in this tab
|
||||||
enabled_layouts tall, stack
|
enabled_layouts tall,stack
|
||||||
# Set the current layout
|
# Set the current layout
|
||||||
layout stack
|
layout stack
|
||||||
launch zsh
|
launch zsh
|
||||||
|
|
||||||
# Create a new OS window
|
# Create a new OS window
|
||||||
|
# Any definitions specifed before the first new_os_window will apply to first OS window.
|
||||||
new_os_window
|
new_os_window
|
||||||
# set new window size to 80x25 cells
|
# Set new window size to 80x24 cells
|
||||||
os_window_size 80c 25c
|
os_window_size 80c 24c
|
||||||
# set the --class for the new OS window
|
# Set the --class for the new OS window
|
||||||
os_window_class mywindow
|
os_window_class mywindow
|
||||||
launch sh
|
launch sh
|
||||||
|
# Resize the current window (see the resize_window action for details)
|
||||||
|
resize_window wider 2
|
||||||
# Make the current window the active (focused) window
|
# Make the current window the active (focused) window
|
||||||
focus
|
focus
|
||||||
launch emacs
|
launch emacs
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
The :doc:`launch <launch>` command when used in a session file
|
The :doc:`launch <launch>` command when used in a session file cannot create
|
||||||
cannot create new OS windows, or tabs.
|
new OS windows, or tabs.
|
||||||
|
|
||||||
|
|
||||||
Creating tabs/windows
|
Creating tabs/windows
|
||||||
@@ -182,23 +191,25 @@ Mouse features
|
|||||||
* You can click on a URL to open it in a browser.
|
* You can click on a URL to open it in a browser.
|
||||||
* You can double click to select a word and then drag to select more words.
|
* You can double click to select a word and then drag to select more words.
|
||||||
* You can triple click to select a line and then drag to select more lines.
|
* You can triple click to select a line and then drag to select more lines.
|
||||||
* You can triple click while holding :kbd:`ctrl+alt` to select from clicked
|
* You can triple click while holding :kbd:`Ctrl+Alt` to select from clicked
|
||||||
point to end of line.
|
point to end of line.
|
||||||
* You can right click to extend a previous selection.
|
* You can right click to extend a previous selection.
|
||||||
* You can hold down :kbd:`ctrl+alt` and drag with the mouse to select in
|
* You can hold down :kbd:`Ctrl+Alt` and drag with the mouse to select in
|
||||||
columns.
|
columns.
|
||||||
* Selecting text automatically copies it to the primary clipboard (on
|
* Selecting text automatically copies it to the primary clipboard (on platforms
|
||||||
platforms with a primary clipboard).
|
|
||||||
* You can middle click to paste from the primary clipboard (on platforms
|
|
||||||
with a primary clipboard).
|
with a primary clipboard).
|
||||||
* You can select text with kitty even when a terminal program has grabbed
|
* You can middle click to paste from the primary clipboard (on platforms with a
|
||||||
the mouse by holding down the :kbd:`shift` key.
|
primary clipboard).
|
||||||
|
* You can right click while holding :kbd:`Ctrl+Shift` to open the output of the
|
||||||
|
clicked on command in a pager (requires :ref:`shell_integration`)
|
||||||
|
* You can select text with kitty even when a terminal program has grabbed the
|
||||||
|
mouse by holding down the :kbd:`Shift` key
|
||||||
|
|
||||||
All these actions can be customized in :file:`kitty.conf` as described
|
All these actions can be customized in :file:`kitty.conf` as described
|
||||||
:ref:`here <conf-kitty-mouse.mousemap>`.
|
:ref:`here <conf-kitty-mouse.mousemap>`.
|
||||||
|
|
||||||
You can also customize what happens when clicking on :term:`hyperlinks` in kitty,
|
You can also customize what happens when clicking on :term:`hyperlinks` in
|
||||||
having it open files in your editor, download remote files, open things
|
kitty, having it open files in your editor, download remote files, open things
|
||||||
in your browser, etc.
|
in your browser, etc.
|
||||||
|
|
||||||
For details, see :doc:`here <open_actions>`.
|
For details, see :doc:`here <open_actions>`.
|
||||||
@@ -212,12 +223,11 @@ Font control
|
|||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|kitty| has extremely flexible and powerful font selection features. You can
|
|kitty| has extremely flexible and powerful font selection features. You can
|
||||||
specify individual families for the regular, bold, italic and bold+italic
|
specify individual families for the regular, bold, italic and bold+italic fonts.
|
||||||
fonts. You can even specify specific font families for specific ranges of
|
You can even specify specific font families for specific ranges of Unicode
|
||||||
unicode characters. This allows precise control over text rendering. It can
|
characters. This allows precise control over text rendering. It can comein handy
|
||||||
come in handy for applications like powerline, without the need to use patched
|
for applications like powerline, without the need to use patched fonts. See the
|
||||||
fonts. See the various font related configuration directives in
|
various font related configuration directives in :ref:`conf-kitty-fonts`.
|
||||||
:ref:`conf-kitty-fonts`.
|
|
||||||
|
|
||||||
|
|
||||||
.. _scrollback:
|
.. _scrollback:
|
||||||
@@ -226,48 +236,62 @@ The scrollback buffer
|
|||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
|kitty| supports scrolling back to view history, just like most terminals. You
|
|kitty| supports scrolling back to view history, just like most terminals. You
|
||||||
can use either keyboard shortcuts or the mouse scroll wheel to do so. However,
|
can use either keyboard shortcuts or the mouse scroll wheel to do so. However,
|
||||||
|kitty| has an extra, neat feature. Sometimes you need to explore the
|
|kitty| has an extra, neat feature. Sometimes you need to explore the scrollback
|
||||||
scrollback buffer in more detail, maybe search for some text or refer to it
|
buffer in more detail, maybe search for some text or refer to it side-by-side
|
||||||
side-by-side while typing in a follow-up command. |kitty| allows you to do this
|
while typing in a follow-up command. |kitty| allows you to do this by pressing
|
||||||
by pressing the :sc:`show_scrollback` key-combination, which will open the
|
the :sc:`show_scrollback` shortcut, which will open the scrollback buffer in
|
||||||
scrollback buffer in your favorite pager program (which is ``less`` by default).
|
your favorite pager program (which is :program:`less` by default). Colors and
|
||||||
Colors and text formatting are preserved. You can explore the scrollback buffer
|
text formatting are preserved. You can explore the scrollback buffer comfortably
|
||||||
comfortably within the pager.
|
within the pager.
|
||||||
|
|
||||||
Additionally, you can pipe the contents of the scrollback buffer to an
|
Additionally, you can pipe the contents of the scrollback buffer to an
|
||||||
arbitrary, command running in a new :term:`window`, :term:`tab` or :term:`overlay`,
|
arbitrary, command running in a new :term:`window`, :term:`tab` or
|
||||||
for example::
|
:term:`overlay`. For example::
|
||||||
|
|
||||||
map f1 launch --stdin-source=@screen_scrollback --stdin-add-formatting less +G -R
|
map f1 launch --stdin-source=@screen_scrollback --stdin-add-formatting less +G -R
|
||||||
|
|
||||||
Would open the scrollback buffer in a new :term:`window` when you press the :kbd:`F1`
|
Would open the scrollback buffer in a new :term:`window` when you press the
|
||||||
key. See :sc:`show_scrollback` for details.
|
:kbd:`F1` key. See :sc:`show_scrollback <show_scrollback>` for details.
|
||||||
|
|
||||||
If you want to use it with an editor such as vim to get more powerful features,
|
If you want to use it with an editor such as :program:`vim` to get more powerful
|
||||||
you can see tips for doing so, in
|
features, you can see tips for doing so, in :iss:`this thread <719>`.
|
||||||
`this thread <https://github.com/kovidgoyal/kitty/issues/719>`_.
|
|
||||||
|
|
||||||
If you wish to store very large amounts of scrollback to view using the piping or
|
If you wish to store very large amounts of scrollback to view using the piping
|
||||||
:sc:`show_scrollback` features, you can use the :opt:`scrollback_pager_history_size`
|
or :sc:`show_scrollback <show_scrollback>` features, you can use the
|
||||||
option.
|
:opt:`scrollback_pager_history_size` option.
|
||||||
|
|
||||||
|
|
||||||
|
Integration with shells
|
||||||
|
---------------------------------
|
||||||
|
|
||||||
|
kitty has the ability to integrate closely within common shells, such as `zsh
|
||||||
|
<https://www.zsh.org/>`__, `fish <https://fishshell.com>`__ and `bash
|
||||||
|
<https://www.gnu.org/software/bash/>`__ to enable features such as jumping to
|
||||||
|
previous prompts in the scrollback, viewing the output of the last command in
|
||||||
|
:program:`less`, using the mouse to move the cursor while editing prompts, etc.
|
||||||
|
See :doc:`shell-integration` for details.
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
|
||||||
|
shell-integration
|
||||||
|
|
||||||
.. _cpbuf:
|
.. _cpbuf:
|
||||||
|
|
||||||
Multiple copy/paste buffers
|
Multiple copy/paste buffers
|
||||||
-----------------------------
|
-----------------------------
|
||||||
|
|
||||||
In addition to being able to copy/paste from the system clipboard, in |kitty| you
|
In addition to being able to copy/paste from the system clipboard, in |kitty|
|
||||||
can also setup an arbitrary number of copy paste buffers. To do so, simply add
|
you can also setup an arbitrary number of copy paste buffers. To do so, simply
|
||||||
something like the following to your :file:`kitty.conf`::
|
add something like the following to your :file:`kitty.conf`::
|
||||||
|
|
||||||
map f1 copy_to_buffer a
|
map f1 copy_to_buffer a
|
||||||
map f2 paste_from_buffer a
|
map f2 paste_from_buffer a
|
||||||
|
|
||||||
This will allow you to press :kbd:`F1` to copy the current selection to an
|
This will allow you to press :kbd:`F1` to copy the current selection to an
|
||||||
internal buffer named ``a`` and :kbd:`F2` to paste from that buffer. The buffer
|
internal buffer named ``a`` and :kbd:`F2` to paste from that buffer. The buffer
|
||||||
names are arbitrary strings, so you can define as many such buffers as you
|
names are arbitrary strings, so you can define as many such buffers as you need.
|
||||||
need.
|
|
||||||
|
|
||||||
|
|
||||||
Marks
|
Marks
|
||||||
|
|||||||
@@ -2,30 +2,31 @@ Performance
|
|||||||
===================
|
===================
|
||||||
|
|
||||||
The main goals for |kitty| performance are user perceived latency while typing
|
The main goals for |kitty| performance are user perceived latency while typing
|
||||||
and "smoothness" while scrolling as well as CPU usage. |kitty| tries hard to find
|
and "smoothness" while scrolling as well as CPU usage. |kitty| tries hard to
|
||||||
an optimum balance for these. To that end it keeps a cache of each rendered
|
find an optimum balance for these. To that end it keeps a cache of each rendered
|
||||||
glyph in video RAM so that font rendering is not a bottleneck. Interaction
|
glyph in video RAM so that font rendering is not a bottleneck. Interaction with
|
||||||
with child programs takes place in a separate thread from rendering, to improve
|
child programs takes place in a separate thread from rendering, to improve
|
||||||
smoothness.
|
smoothness.
|
||||||
|
|
||||||
There are two parameters you can tune to adjust the performance. :opt:`repaint_delay`
|
There are two config options you can tune to adjust the performance,
|
||||||
and :opt:`input_delay`. These control the artificial delays introduced into the
|
:opt:`repaint_delay` and :opt:`input_delay`. These control the artificial delays
|
||||||
render loop to reduce CPU usage. See :ref:`conf-kitty-performance` for details.
|
introduced into the render loop to reduce CPU usage. See
|
||||||
See also the :opt:`sync_to_monitor` option to further decrease latency at the cost
|
:ref:`conf-kitty-performance` for details. See also the :opt:`sync_to_monitor`
|
||||||
of some `tearing <https://en.wikipedia.org/wiki/Screen_tearing>`_ while scrolling.
|
option to further decrease latency at the cost of some `screen tearing
|
||||||
|
<https://en.wikipedia.org/wiki/Screen_tearing>`__ while scrolling.
|
||||||
|
|
||||||
You can generate detailed per-function performance data using `gperftools
|
You can generate detailed per-function performance data using
|
||||||
<https://github.com/gperftools/gperftools>`_. Build |kitty| with `make
|
`gperftools <https://github.com/gperftools/gperftools>`__. Build |kitty| with
|
||||||
profile`. Run kitty and perform the task you want to analyse, for example,
|
``make profile``. Run kitty and perform the task you want to analyse, for
|
||||||
scrolling a large file with `less`. After you quit, function call statistics
|
example, scrolling a large file with :program:`less`. After you quit, function
|
||||||
will be printed to `stdout` and you can use tools like *kcachegrind* for more
|
call statistics will be printed to STDOUT and you can use tools like
|
||||||
detailed analysis.
|
*KCachegrind* for more detailed analysis.
|
||||||
|
|
||||||
Here are some CPU usage numbers for the task of scrolling a file continuously
|
Here are some CPU usage numbers for the task of scrolling a file continuously in
|
||||||
in less. The CPU usage is for the terminal process and X together and is
|
:program:`less`. The CPU usage is for the terminal process and X together and is
|
||||||
measured using htop. The measurements are taken at the same font and window
|
measured using :program:`htop`. The measurements are taken at the same font and
|
||||||
size for all terminals on a ``Intel(R) Core(TM) i7-4820K CPU @ 3.70GHz`` CPU
|
window size for all terminals on a ``Intel(R) Core(TM) i7-4820K CPU @ 3.70GHz``
|
||||||
with a ``Advanced Micro Devices, Inc. [AMD/ATI] Cape Verde XT [Radeon HD
|
CPU with a ``Advanced Micro Devices, Inc. [AMD/ATI] Cape Verde XT [Radeon HD
|
||||||
7770/8760 / R7 250X]`` GPU.
|
7770/8760 / R7 250X]`` GPU.
|
||||||
|
|
||||||
============== =========================
|
============== =========================
|
||||||
@@ -49,11 +50,11 @@ admittedly biased, eyes).
|
|||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
Some people have asked why kitty does not perform better than terminal XXX in
|
Some people have asked why kitty does not perform better than terminal XXX
|
||||||
the test of sinking large amounts of data, such as catting a large text
|
in the test of sinking large amounts of data, such as catting a large text
|
||||||
file. The answer is because this is not a goal for kitty. kitty
|
file. The answer is because this is not a goal for kitty. kitty deliberately
|
||||||
deliberately throttles input parsing and output rendering to minimize
|
throttles input parsing and output rendering to minimize resource usage
|
||||||
resource usage while still being able to sink output faster than any real
|
while still being able to sink output faster than any real world program can
|
||||||
world program can produce it. Reducing CPU usage, and hence battery drain
|
produce it. Reducing CPU usage, and hence battery drain while achieving
|
||||||
while achieving instant response times and smooth scrolling to a human eye
|
instant response times and smooth scrolling to a human eye is a far more
|
||||||
is a far more important goal.
|
important goal.
|
||||||
|
|||||||
18
docs/press-mentions.rst
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
Press mentions of kitty
|
||||||
|
========================
|
||||||
|
|
||||||
|
`Python Bytes 272 <https://youtu.be/8HKliSbA-gQ?t=815>`__ (Feb 2022)
|
||||||
|
A podcast demoing some of kitty's coolness
|
||||||
|
|
||||||
|
`Console #88 <https://console.substack.com/p/console-88>`__ (Jan 2022)
|
||||||
|
An interview with Kovid about kitty
|
||||||
|
|
||||||
|
|
||||||
|
Video reviews
|
||||||
|
--------------
|
||||||
|
|
||||||
|
`Review (Jan 2021) <https://www.youtube.com/watch?v=TTzP2zYJn2k>`__
|
||||||
|
A kitty review by distrotube
|
||||||
|
|
||||||
|
`Review (Dec 2020) <https://www.youtube.com/watch?v=KUMkLhFeBrI>`__
|
||||||
|
A kitty review/intro by TechHut
|
||||||
@@ -1,23 +1,24 @@
|
|||||||
Terminal protocol extensions
|
Terminal protocol extensions
|
||||||
===================================
|
===================================
|
||||||
|
|
||||||
|kitty| has extensions to the legacy terminal protocol, to enable advanced features.
|
|kitty| has extensions to the legacy terminal protocol, to enable advanced
|
||||||
These are typically in the form of new or re-purposed escape codes. While these
|
features. These are typically in the form of new or re-purposed escape codes.
|
||||||
extensions are currently |kitty| specific, it would be nice to get some of them
|
While these extensions are currently |kitty| specific, it would be nice to get
|
||||||
adopted more broadly, to push the state of terminal emulators forward.
|
some of them adopted more broadly, to push the state of terminal emulators
|
||||||
|
forward.
|
||||||
|
|
||||||
The goal of these extensions is to be as small and unobtrusive as possible,
|
The goal of these extensions is to be as small and unobtrusive as possible,
|
||||||
while filling in some gaps in the existing xterm protocol. In particular, one
|
while filling in some gaps in the existing xterm protocol. In particular, one of
|
||||||
of the goals of this specification is explicitly not to "re-imagine" the tty.
|
the goals of this specification is explicitly not to "re-imagine" the TTY. The
|
||||||
The tty should remain what it is -- a device for efficiently processing text
|
TTY should remain what it is -- a device for efficiently processing text
|
||||||
received as a simple byte stream. Another objective is to only move the minimum
|
received as a simple byte stream. Another objective is to only move the minimum
|
||||||
possible amount of extra functionality into the terminal program itself. This
|
possible amount of extra functionality into the terminal program itself. This is
|
||||||
is to make it as easy to implement these protocol extensions as possible,
|
to make it as easy to implement these protocol extensions as possible, thereby
|
||||||
thereby hopefully encouraging their widespread adoption.
|
hopefully encouraging their widespread adoption.
|
||||||
|
|
||||||
If you wish to discuss these extensions, propose additions/changes to them
|
If you wish to discuss these extensions, propose additions or changes to them,
|
||||||
please do so by opening issues in the `GitHub
|
please do so by opening issues in the `GitHub bug tracker
|
||||||
<https://github.com/kovidgoyal/kitty/issues>`_ bug tracker.
|
<https://github.com/kovidgoyal/kitty/issues>`__.
|
||||||
|
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
@@ -26,6 +27,7 @@ please do so by opening issues in the `GitHub
|
|||||||
underlines
|
underlines
|
||||||
graphics-protocol
|
graphics-protocol
|
||||||
keyboard-protocol
|
keyboard-protocol
|
||||||
|
file-transfer-protocol
|
||||||
desktop-notifications
|
desktop-notifications
|
||||||
unscroll
|
unscroll
|
||||||
color-stack
|
color-stack
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ Quickstart
|
|||||||
binary
|
binary
|
||||||
build
|
build
|
||||||
|
|
||||||
Pre-built binaries of |kitty| are available for both macOS and Linux.
|
Pre-built binaries of |kitty| are available for both macOS and Linux. See the
|
||||||
See the :doc:`binary install instructions </binary>`. You can also
|
:doc:`binary install instructions </binary>`. You can also :doc:`build from
|
||||||
:doc:`build from source </build>`.
|
source </build>`.
|
||||||
|
|
||||||
Additionally, you can use your favorite package manager to install the |kitty|
|
Additionally, you can use your favorite package manager to install the |kitty|
|
||||||
package, but note that some Linux distribution packages are woefully outdated.
|
package, but note that some Linux distribution packages are woefully outdated.
|
||||||
@@ -25,4 +25,4 @@ and Linux.
|
|||||||
See :doc:`Configuring kitty <conf>` for help on configuring |kitty| and
|
See :doc:`Configuring kitty <conf>` for help on configuring |kitty| and
|
||||||
:doc:`Invocation <invocation>` for the command line arguments |kitty| supports.
|
:doc:`Invocation <invocation>` for the command line arguments |kitty| supports.
|
||||||
|
|
||||||
For a tour of kitty's design and features, see the :doc:`/overview`.
|
For a tour of kitty's design and features, see the :doc:`overview`.
|
||||||
|
|||||||
@@ -7,34 +7,74 @@ form::
|
|||||||
|
|
||||||
<ESC>P@kitty-cmd<JSON object><ESC>\
|
<ESC>P@kitty-cmd<JSON object><ESC>\
|
||||||
|
|
||||||
Where ``<ESC>`` is the byte ``0x1b``. The JSON object has the form::
|
Where ``<ESC>`` is the byte ``0x1b``. The JSON object has the form:
|
||||||
|
|
||||||
|
.. code-block:: json
|
||||||
|
|
||||||
{
|
{
|
||||||
"cmd": "command name",
|
"cmd": "command name",
|
||||||
"version": <kitty version>,
|
"version": "<kitty version>",
|
||||||
"no_response": <Optional Boolean>,
|
"no_response": "<Optional Boolean>",
|
||||||
"payload": <Optional JSON object>,
|
"payload": "<Optional JSON object>"
|
||||||
}
|
}
|
||||||
|
|
||||||
The ``version`` above is an array of the form :code:`[0, 14, 2]`. If you are developing a
|
The ``version`` above is an array of the form :code:`[0, 14, 2]`. If you are
|
||||||
standalone client, use the kitty version that you are developing against. Using
|
developing a standalone client, use the kitty version that you are developing
|
||||||
a version greater than the version of the kitty instance you are talking to,
|
against. Using a version greater than the version of the kitty instance you are
|
||||||
will cause a failure.
|
talking to, will cause a failure.
|
||||||
|
|
||||||
Set ``no_response`` to ``true`` if you don't want a response from kitty.
|
Set ``no_response`` to ``true`` if you don't want a response from kitty.
|
||||||
|
|
||||||
The optional payload is a JSON object that is specific to the actual command being sent.
|
The optional payload is a JSON object that is specific to the actual command
|
||||||
The fields in the object for every command are documented below.
|
being sent. The fields in the object for every command are documented below.
|
||||||
|
|
||||||
As a quick example showing how easy to use this protocol is, we will implement
|
As a quick example showing how easy to use this protocol is, we will implement
|
||||||
the ``@ ls`` command from the shell using only shell tools. First, run kitty
|
the ``@ ls`` command from the shell using only shell tools.
|
||||||
as::
|
|
||||||
|
First, run kitty as::
|
||||||
|
|
||||||
kitty -o allow_remote_control=socket-only --listen-on unix:/tmp/test
|
kitty -o allow_remote_control=socket-only --listen-on unix:/tmp/test
|
||||||
|
|
||||||
Now, in a different terminal, you can get the pretty printed ``@ ls`` output
|
Now, in a different terminal, you can get the pretty printed ``@ ls`` output
|
||||||
with the following command line::
|
with the following command line::
|
||||||
|
|
||||||
echo -en '\eP@kitty-cmd{"cmd":"ls","version":[0,14,2]}\e\' | socat - unix:/tmp/test | awk '{ print substr($0, 13, length($0) - 14) }' | jq -c '.data | fromjson' | jq .
|
echo -en '\eP@kitty-cmd{"cmd":"ls","version":[0,14,2]}\e\\' | socat - unix:/tmp/test | awk '{ print substr($0, 13, length($0) - 14) }' | jq -c '.data | fromjson' | jq .
|
||||||
|
|
||||||
|
.. _rc_crypto:
|
||||||
|
|
||||||
|
Encrypted communication
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
.. versionadded:: 0.26.0
|
||||||
|
|
||||||
|
When using the :opt:`remote_control_password` option communication to the
|
||||||
|
terminal is encrypted to keep the password secure. A public key is used from
|
||||||
|
the :envvar:`KITTY_PUBLIC_KEY` environment variable. Currently, only one
|
||||||
|
encryption protocol is supported. The protocol number is present in
|
||||||
|
:envvar:`KITTY_PUBLIC_KEY` as ``1``. The key data in this environment variable
|
||||||
|
is :rfc:`Base-85 <1924>` encoded. The algorithm used is `Elliptic Curve Diffie
|
||||||
|
Helman <https://en.wikipedia.org/wiki/Elliptic-curve_Diffie–Hellman>`__ with
|
||||||
|
the `X25519 curve <https://en.wikipedia.org/wiki/Curve25519>`__. A time based
|
||||||
|
nonce is used to minimise replay attacks. The original JSON command has the
|
||||||
|
fields: ``password`` and ``timestamp`` added. The timestamp is the number of
|
||||||
|
nanoseconds since the epoch, excluding leap seconds. Commands with a timestamp
|
||||||
|
more than 5 minutes from the current time are rejected. The command is then
|
||||||
|
encrypted using AES-256-GCM in authenticated encryption mode, with a symmetric
|
||||||
|
key that is derived from the ECDH key-pair by running the shared secret through
|
||||||
|
SHA-256 hashing, once. An IV of at least 96 bits of CSPRNG data is used. The
|
||||||
|
tag for authenticated encryption **must** be at least 128 bits long. The tag
|
||||||
|
**must** authenticate only the value of the ``encrypted`` field. A new command
|
||||||
|
is created and transmitted that contains the fields:
|
||||||
|
|
||||||
|
.. code-block:: json
|
||||||
|
|
||||||
|
{
|
||||||
|
"version": "<kitty version>",
|
||||||
|
"iv": "base85 encoded IV",
|
||||||
|
"tag": "base85 encoded AEAD tag",
|
||||||
|
"pubkey": "base85 encoded ECDH public key of sender",
|
||||||
|
"encrypted": "The original command encrypted and base85 encoded"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.. include:: generated/rc.rst
|
.. include:: generated/rc.rst
|
||||||
|
|||||||
@@ -4,9 +4,12 @@ Control kitty from scripts
|
|||||||
.. highlight:: sh
|
.. highlight:: sh
|
||||||
|
|
||||||
|kitty| can be controlled from scripts or the shell prompt. You can open new
|
|kitty| can be controlled from scripts or the shell prompt. You can open new
|
||||||
windows, send arbitrary text input to any window, name windows and tabs, etc.
|
windows, send arbitrary text input to any window, change the title of windows
|
||||||
|
and tabs, etc.
|
||||||
|
|
||||||
Let's walk through a few examples of controlling |kitty|.
|
Let's walk through a few examples of controlling |kitty|.
|
||||||
|
|
||||||
|
|
||||||
Tutorial
|
Tutorial
|
||||||
------------
|
------------
|
||||||
|
|
||||||
@@ -14,50 +17,52 @@ Start by running |kitty| as::
|
|||||||
|
|
||||||
kitty -o allow_remote_control=yes -o enabled_layouts=tall
|
kitty -o allow_remote_control=yes -o enabled_layouts=tall
|
||||||
|
|
||||||
In order for control to work, :opt:`allow_remote_control` must be enabled in
|
In order for control to work, :opt:`allow_remote_control` or
|
||||||
:file:`kitty.conf`. Here we turn it on explicitly at the command line.
|
:opt:`remote_control_password` must be enabled in :file:`kitty.conf`. Here we
|
||||||
|
turn it on explicitly at the command line.
|
||||||
|
|
||||||
Now, in the new |kitty| window, enter the command::
|
Now, in the new |kitty| window, enter the command::
|
||||||
|
|
||||||
kitty @ launch --title Output --keep-focus cat
|
kitty @ launch --title Output --keep-focus cat
|
||||||
|
|
||||||
This will open a new window, running the ``cat`` program that will appear next
|
This will open a new window, running the :program:`cat` program that will appear
|
||||||
to the current window.
|
next to the current window.
|
||||||
|
|
||||||
Let's send some text to this new window::
|
Let's send some text to this new window::
|
||||||
|
|
||||||
kitty @ send-text --match cmdline:cat Hello, World
|
kitty @ send-text --match cmdline:cat Hello, World
|
||||||
|
|
||||||
This will make ``Hello, World`` show up in the window running the ``cat`` program.
|
This will make ``Hello, World`` show up in the window running the :program:`cat`
|
||||||
The :option:`kitty @ send-text --match` option is very powerful, it allows selecting windows by their
|
program. The :option:`kitty @ send-text --match` option is very powerful, it
|
||||||
titles, the command line of the program running in the window, the working
|
allows selecting windows by their titles, the command line of the program
|
||||||
directory of the program running in the window, etc. See ``kitty @ send-text
|
running in the window, the working directory of the program running in the
|
||||||
--help`` for details.
|
window, etc. See :ref:`kitty @ send-text --help <at-send-text>` for details.
|
||||||
|
|
||||||
More usefully, you can pipe the output of a command running in one window to
|
More usefully, you can pipe the output of a command running in one window to
|
||||||
another window, for example::
|
another window, for example::
|
||||||
|
|
||||||
ls | kitty @ send-text --match title:Output --stdin
|
ls | kitty @ send-text --match 'title:^Output' --stdin
|
||||||
|
|
||||||
This will show the output of ls in the output window instead of the current
|
This will show the output of :program:`ls` in the output window instead of the
|
||||||
window. You can use this technique to, for example, show the output of running
|
current window. You can use this technique to, for example, show the output of
|
||||||
``make`` in your editor in a different window. The possibilities are endless.
|
running :program:`make` in your editor in a different window. The possibilities
|
||||||
|
are endless.
|
||||||
|
|
||||||
You can even have things you type show up in a different window. Run::
|
You can even have things you type show up in a different window. Run::
|
||||||
|
|
||||||
kitty @ send-text --match title:Output --stdin
|
kitty @ send-text --match 'title:^Output' --stdin
|
||||||
|
|
||||||
And type some text, it will show up in the output window, instead of the current
|
And type some text, it will show up in the output window, instead of the current
|
||||||
window. Type ``Ctrl+D`` when you are ready to stop.
|
window. Type :kbd:`Ctrl+D` when you are ready to stop.
|
||||||
|
|
||||||
Now, let's open a new tab::
|
Now, let's open a new tab::
|
||||||
|
|
||||||
kitty @ launch --type=tab --tab-title "My Tab" --keep-focus bash
|
kitty @ launch --type=tab --tab-title "My Tab" --keep-focus bash
|
||||||
|
|
||||||
This will open a new tab running the bash shell with the title "My Tab".
|
This will open a new tab running the bash shell with the title "My Tab".
|
||||||
We can change the title of the tab with::
|
We can change the title of the tab to "New Title" with::
|
||||||
|
|
||||||
kitty @ set-tab-title --match title:My New Title
|
kitty @ set-tab-title --match 'title:^My' New Title
|
||||||
|
|
||||||
Let's change the title of the current tab::
|
Let's change the title of the current tab::
|
||||||
|
|
||||||
@@ -65,79 +70,196 @@ Let's change the title of the current tab::
|
|||||||
|
|
||||||
Now lets switch to the newly opened tab::
|
Now lets switch to the newly opened tab::
|
||||||
|
|
||||||
kitty @ focus-tab --match title:New
|
kitty @ focus-tab --match 'title:^New'
|
||||||
|
|
||||||
Similarly, to focus the previously opened output window (which will also switch
|
Similarly, to focus the previously opened output window (which will also switch
|
||||||
back to the old tab, automatically)::
|
back to the old tab, automatically)::
|
||||||
|
|
||||||
kitty @ focus-window --match title:Output
|
kitty @ focus-window --match 'title:^Output'
|
||||||
|
|
||||||
You can get a listing of available tabs and windows, by running::
|
You can get a listing of available tabs and windows, by running::
|
||||||
|
|
||||||
kitty @ ls
|
kitty @ ls
|
||||||
|
|
||||||
This outputs a tree of data in JSON format. The top level of the tree is all
|
This outputs a tree of data in JSON format. The top level of the tree is all
|
||||||
operating system kitty windows. Each OS window has an id and a list of tabs.
|
:term:`OS windows <os_window>`. Each OS window has an id and a list of
|
||||||
Each tab has its own id, a title and a list of windows. Each window has an id,
|
:term:`tabs <tab>`. Each tab has its own id, a title and a list of :term:`kitty
|
||||||
title, current working directory, process id (PID) and command-line of the
|
windows <window>`. Each window has an id, title, current working directory,
|
||||||
process running in the window. You can use this information with :option:`kitty @ focus-window --match`
|
process id (PID) and command-line of the process running in the window. You can
|
||||||
to control individual windows.
|
use this information with :option:`kitty @ focus-window --match` to control
|
||||||
|
individual windows.
|
||||||
|
|
||||||
As you can see, it is very easy to control |kitty| using the
|
As you can see, it is very easy to control |kitty| using the ``kitty @``
|
||||||
``kitty @`` messaging system. This tutorial touches only the
|
messaging system. This tutorial touches only the surface of what is possible.
|
||||||
surface of what is possible. See ``kitty @ --help`` for more details.
|
See ``kitty @ --help`` for more details.
|
||||||
|
|
||||||
Note that in the example's above, ``kitty @`` messaging works only when run inside a |kitty| window,
|
In the example's above, ``kitty @`` messaging works only when run
|
||||||
not anywhere. But, within a |kitty| window it even works over SSH. If you want to control
|
inside a |kitty| window, not anywhere. But, within a |kitty| window it even
|
||||||
|kitty| from programs/scripts not running inside a |kitty| window, you have to implement a couple of
|
works over SSH. If you want to control |kitty| from programs/scripts not running
|
||||||
extra steps. First start |kitty| as::
|
inside a |kitty| window, see the section on :ref:`using a socket for remote control <rc_via_socket>`
|
||||||
|
below.
|
||||||
|
|
||||||
|
|
||||||
|
Note that if all you want to do is run a single |kitty| "daemon" and have
|
||||||
|
subsequent |kitty| invocations appear as new top-level windows, you can use the
|
||||||
|
simpler :option:`kitty --single-instance` option, see ``kitty --help`` for that.
|
||||||
|
|
||||||
|
|
||||||
|
.. _rc_via_socket:
|
||||||
|
|
||||||
|
Remote control via a socket
|
||||||
|
--------------------------------
|
||||||
|
First, start |kitty| as::
|
||||||
|
|
||||||
kitty -o allow_remote_control=yes --listen-on unix:/tmp/mykitty
|
kitty -o allow_remote_control=yes --listen-on unix:/tmp/mykitty
|
||||||
|
|
||||||
The :option:`kitty --listen-on` option tells |kitty| to listen for control messages at the
|
The :option:`kitty --listen-on` option tells |kitty| to listen for control
|
||||||
specified path. See ``kitty --help`` for details. Now you can control this
|
messages at the specified UNIX-domain socket. See ``kitty --help`` for details.
|
||||||
instance of |kitty| using the :option:`kitty @ --to` command line argument to ``kitty @``. For example::
|
Now you can control this instance of |kitty| using the :option:`kitty @ --to`
|
||||||
|
command line argument to ``kitty @``. For example::
|
||||||
|
|
||||||
kitty @ --to unix:/tmp/mykitty ls
|
kitty @ --to unix:/tmp/mykitty ls
|
||||||
|
|
||||||
|
|
||||||
Note that if all you want to do is run a single |kitty| "daemon" and have subsequent
|
|
||||||
|kitty| invocations appear as new top-level windows, you can use the simpler :option:`kitty --single-instance`
|
|
||||||
option, see ``kitty --help`` for that.
|
|
||||||
|
|
||||||
The builtin kitty shell
|
The builtin kitty shell
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
You can explore the |kitty| command language more easily using the builtin |kitty|
|
You can explore the |kitty| command language more easily using the builtin
|
||||||
shell. Run ``kitty @`` with no arguments and you will be dropped into the |kitty|
|
|kitty| shell. Run ``kitty @`` with no arguments and you will be dropped into
|
||||||
shell with completion for |kitty| command names and options.
|
the |kitty| shell with completion for |kitty| command names and options.
|
||||||
|
|
||||||
You can even open the |kitty| shell inside a running |kitty| using a simple
|
You can even open the |kitty| shell inside a running |kitty| using a simple
|
||||||
keyboard shortcut (:sc:`kitty_shell` by default).
|
keyboard shortcut (:sc:`kitty_shell` by default).
|
||||||
|
|
||||||
.. note:: This has the added advantage that you don't need to use
|
.. note:: This has the added advantage that you don't need to use
|
||||||
``allow_remote_control`` to make it work.
|
:opt:`allow_remote_control` to make it work.
|
||||||
|
|
||||||
|
|
||||||
Allowing only some windows to control kitty
|
Allowing only some windows to control kitty
|
||||||
----------------------------------------------
|
----------------------------------------------
|
||||||
|
|
||||||
If you do not want to allow all programs running in |kitty| to control it, you can selectively
|
If you do not want to allow all programs running in |kitty| to control it, you
|
||||||
enable remote control for only some |kitty| windows. Simply create a shortcut
|
can selectively enable remote control for only some |kitty| windows. Simply
|
||||||
such as::
|
create a shortcut such as::
|
||||||
|
|
||||||
map ctrl+k launch --allow-remote-control some_program
|
map ctrl+k launch --allow-remote-control some_program
|
||||||
|
|
||||||
Then programs running in windows created with that shortcut can use ``kitty @``
|
Then programs running in windows created with that shortcut can use ``kitty @``
|
||||||
to control kitty. Note that any program with the right level of permissions can
|
to control kitty. Note that any program with the right level of permissions can
|
||||||
still write to the pipes of any other program on the same computer and
|
still write to the pipes of any other program on the same computer and therefore
|
||||||
therefore can control |kitty|. It can, however, be useful to block programs
|
can control |kitty|. It can, however, be useful to block programs running on
|
||||||
running on other computers (for example, over ssh) or as other users.
|
other computers (for example, over SSH) or as other users.
|
||||||
|
|
||||||
.. note:: You dont need ``allow_remote_control`` to make this work as it is
|
.. note:: You don't need :opt:`allow_remote_control` to make this work as it is
|
||||||
limited to only programs running in that specific window. Be careful with
|
limited to only programs running in that specific window. Be careful with
|
||||||
what programs you run in such windows, since they can effectively control
|
what programs you run in such windows, since they can effectively control
|
||||||
kitty, as if you were running with ``allow_remote_control`` turned on.
|
kitty, as if you were running with :opt:`allow_remote_control` turned on.
|
||||||
|
|
||||||
|
You can further restrict what is allowed in these windows by using
|
||||||
|
:option:`kitty @ launch --remote-control-password`.
|
||||||
|
|
||||||
|
|
||||||
|
Fine grained permissions for remote control
|
||||||
|
----------------------------------------------
|
||||||
|
|
||||||
|
.. versionadded:: 0.26.0
|
||||||
|
|
||||||
|
The :opt:`allow_remote_control` option discussed so far is a blunt
|
||||||
|
instrument, granting the ability to any program running on your computer
|
||||||
|
or even on remote computers via SSH the ability to use remote control.
|
||||||
|
|
||||||
|
You can instead define remote control passwords that can be used to grant
|
||||||
|
different levels of control to different places. You can even write your
|
||||||
|
own script to decide which remote control requests are allowed. This is
|
||||||
|
done using the :opt:`remote_control_password` option in :file:`kitty.conf`.
|
||||||
|
Set :opt:`allow_remote_control` to :code:`password` to use this feature.
|
||||||
|
Let's see some examples:
|
||||||
|
|
||||||
|
.. code-block:: conf
|
||||||
|
|
||||||
|
remote_control_password "control colors" get-colors set-colors
|
||||||
|
|
||||||
|
Now, using this password, you can, in scripts run the command::
|
||||||
|
|
||||||
|
kitty @ --password="control colors" set-colors background=red
|
||||||
|
|
||||||
|
Any script with access to the password can now change colors in kitty using
|
||||||
|
remote control, but only that and nothing else. You can even supply the
|
||||||
|
password via the :envvar:`KITTY_RC_PASSWORD` environment variable, or the
|
||||||
|
file :file:`~/.config/kitty/rc-password` to avoid having to type it repeatedly.
|
||||||
|
See :option:`kitty @ --password-file` and :option:`kitty @ --password-env`.
|
||||||
|
|
||||||
|
The :opt:`remote_control_password` can be specified multiple times to create
|
||||||
|
different passwords with different capabilities. Run the following to get a
|
||||||
|
list of all action names::
|
||||||
|
|
||||||
|
kitty @ --help
|
||||||
|
|
||||||
|
You can even use glob patterns to match action names, for example:
|
||||||
|
|
||||||
|
.. code-block:: conf
|
||||||
|
|
||||||
|
remote_control_password "control colors" *-colors
|
||||||
|
|
||||||
|
If no action names are specified, all actions are allowed.
|
||||||
|
|
||||||
|
If ``kitty @`` is run with a password that is not present in
|
||||||
|
:file:`kitty.conf`, then kitty will interactively prompt the user to allow or
|
||||||
|
disallow the remote control request. The user can choose to allow or disallow
|
||||||
|
either just that request or all requests using that password. The user's
|
||||||
|
decision is remembered for the duration of that kitty instance.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
For password based authentication to work over SSH, you must pass the
|
||||||
|
:envvar:`KITTY_PUBLIC_KEY` environment variable to the remote host. The
|
||||||
|
:doc:`ssh kitten <kittens/ssh>` does this for you automatically. When
|
||||||
|
using a password, :ref:`rc_crypto` is used to ensure the password
|
||||||
|
is kept secure. This does mean that using password based authentication
|
||||||
|
is slower as the entire command is encrypted before transmission. This
|
||||||
|
can be noticeable when using a command like ``kitty @ set-background-image``
|
||||||
|
which transmits large amounts of image data. Also, the clock on the remote
|
||||||
|
system must match (within a few minutes) the clock on the local system.
|
||||||
|
kitty uses a time based nonce to minimise the potential for replay attacks.
|
||||||
|
|
||||||
|
.. _rc_custom_auth:
|
||||||
|
|
||||||
|
Customizing authorization with your own program
|
||||||
|
____________________________________________________________
|
||||||
|
|
||||||
|
If the ability to control access by action names is not fine grained enough,
|
||||||
|
you can define your own Python script to examine every remote control command
|
||||||
|
and allow/disallow it. To do so create a file in the kitty configuration
|
||||||
|
directory, :file:`~/.config/kitty/my_rc_auth.py` and add the following
|
||||||
|
to :file:`kitty.conf`:
|
||||||
|
|
||||||
|
.. code-block:: conf
|
||||||
|
|
||||||
|
remote_control_password "testing custom auth" my_rc_auth.py
|
||||||
|
|
||||||
|
:file:`my_rc_auth.py` should define a :code:`is_cmd_allowed` function
|
||||||
|
as shown below:
|
||||||
|
|
||||||
|
.. code-block:: py
|
||||||
|
|
||||||
|
def is_cmd_allowed(pcmd, window, from_socket, extra_data):
|
||||||
|
cmd_name = pcmd['cmd'] # the name of the command
|
||||||
|
cmd_payload = pcmd['payload'] # the arguments to the command
|
||||||
|
# examine the cmd_name and cmd_payload and return True to allow
|
||||||
|
# the command or False to disallow it. Return None to have no
|
||||||
|
# effect on the command.
|
||||||
|
|
||||||
|
# The command payload will vary from command to command, see
|
||||||
|
# the rc protocol docs for details. Below is an example of
|
||||||
|
# restricting the launch command to allow only running the
|
||||||
|
# default shell.
|
||||||
|
|
||||||
|
if cmd_name != 'launch':
|
||||||
|
return None
|
||||||
|
if cmd_payload.get('args') or cmd_payload.get('env') or cmd_payload.get('copy_cmdline') or cmd_payload.get('copy_env'):
|
||||||
|
return False
|
||||||
|
# prints in this function go to the parent kitty process STDOUT
|
||||||
|
print('Allowing launch command:', cmd_payload)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
.. _rc_mapping:
|
.. _rc_mapping:
|
||||||
@@ -148,15 +270,21 @@ Mapping key presses to remote control commands
|
|||||||
If you wish to trigger a remote control command easily with just a keypress,
|
If you wish to trigger a remote control command easily with just a keypress,
|
||||||
you can map it in :file:`kitty.conf`. For example::
|
you can map it in :file:`kitty.conf`. For example::
|
||||||
|
|
||||||
map F1 remote_control set-spacing margin=30
|
map f1 remote_control set-spacing margin=30
|
||||||
|
|
||||||
Then pressing the :kbd:`F1` key will set the active window margins to 30.
|
Then pressing the :kbd:`F1` key will set the active window margins to
|
||||||
The syntax for what follows :code:`remote_control` is exactly the same
|
:code:`30`. The syntax for what follows :ac:`remote_control` is exactly the same
|
||||||
as the syntax for what follows :code:`kitty @` above.
|
as the syntax for what follows :code:`kitty @` above.
|
||||||
|
|
||||||
.. note:: You do not need ``allow_remote_control`` to use these mappings,
|
If you wish to ignore errors from the command, prefix the command with an
|
||||||
as they are not actual remote programs, but are simply a way to resuse
|
``!``. For example, the following will not return an error when no windows
|
||||||
the remote control infrastructure via keybings.
|
are matched::
|
||||||
|
|
||||||
|
map f1 remote_control !focus-window --match XXXXXX
|
||||||
|
|
||||||
|
.. note:: You do not need :opt:`allow_remote_control` to use these mappings,
|
||||||
|
as they are not actual remote programs, but are simply a way to resuse the
|
||||||
|
remote control infrastructure via keybings.
|
||||||
|
|
||||||
|
|
||||||
Broadcasting what you type to all kitty windows
|
Broadcasting what you type to all kitty windows
|
||||||
@@ -166,17 +294,36 @@ As a simple illustration of the power of remote control, lets
|
|||||||
have what we type sent to all open kitty windows. To do that define the
|
have what we type sent to all open kitty windows. To do that define the
|
||||||
following mapping in :file:`kitty.conf`::
|
following mapping in :file:`kitty.conf`::
|
||||||
|
|
||||||
map F1 launch --allow-remote-control kitty +kitten broadcast
|
map f1 launch --allow-remote-control kitty +kitten broadcast
|
||||||
|
|
||||||
Now press, F1 and start typing, what you type will be sent to all windows,
|
Now press :kbd:`F1` and start typing, what you type will be sent to all windows,
|
||||||
live, as you type it.
|
live, as you type it.
|
||||||
|
|
||||||
|
|
||||||
The remote control protocol
|
The remote control protocol
|
||||||
-----------------------------------------------
|
-----------------------------------------------
|
||||||
|
|
||||||
If you wish to develop your own client to talk to |kitty|, you
|
If you wish to develop your own client to talk to |kitty|, you can use the
|
||||||
can use the :doc:`protocol specification <rc_protocol>`.
|
:doc:`remote control protocol specification <rc_protocol>`.
|
||||||
|
|
||||||
|
|
||||||
|
.. _search_syntax:
|
||||||
|
|
||||||
|
Matching windows and tabs
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
Many remote control operations operate on windows or tabs. To select these, the
|
||||||
|
:code:`--match` option is often used. This allows matching using various
|
||||||
|
sophisticated criteria such as title, ids, cmdlines, etc. These criteria are
|
||||||
|
expressions of the form :code:`field:query`. Where :italic:`field` is the field
|
||||||
|
against which to match and :italic:`query` is the expression to match. They can
|
||||||
|
be further combined using Boolean operators, best illustrated with some
|
||||||
|
examples::
|
||||||
|
|
||||||
|
title:"My special window" or id:43
|
||||||
|
title:bash and env:USER=kovid
|
||||||
|
not id:1
|
||||||
|
(id:2 or id:3) and title:something
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:hidden:
|
:hidden:
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 131 KiB After Width: | Height: | Size: 118 KiB |
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 1.2 MiB After Width: | Height: | Size: 958 KiB |
BIN
docs/screenshots/select-window.png
Normal file
|
After Width: | Height: | Size: 111 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 40 KiB |
BIN
docs/screenshots/themes.png
Normal file
|
After Width: | Height: | Size: 110 KiB |
BIN
docs/screenshots/transfer.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 76 KiB |
BIN
docs/screenshots/window-logo.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
385
docs/shell-integration.rst
Normal file
@@ -0,0 +1,385 @@
|
|||||||
|
.. _shell_integration:
|
||||||
|
|
||||||
|
Shell integration
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
kitty has the ability to integrate closely within common shells, such as `zsh
|
||||||
|
<https://www.zsh.org/>`__, `fish <https://fishshell.com>`__ and `bash
|
||||||
|
<https://www.gnu.org/software/bash/>`__ to enable features such as jumping to
|
||||||
|
previous prompts in the scrollback, viewing the output of the last command in
|
||||||
|
:program:`less`, using the mouse to move the cursor while editing prompts, etc.
|
||||||
|
|
||||||
|
.. versionadded:: 0.24.0
|
||||||
|
|
||||||
|
Features
|
||||||
|
-------------
|
||||||
|
|
||||||
|
* Open the output of the last command in a pager such as :program:`less`
|
||||||
|
(:sc:`show_last_command_output`)
|
||||||
|
|
||||||
|
* Jump to the previous/next prompt in the scrollback
|
||||||
|
(:sc:`scroll_to_previous_prompt` / :sc:`scroll_to_next_prompt`)
|
||||||
|
|
||||||
|
* Click with the mouse anywhere in the current command to move the cursor there
|
||||||
|
|
||||||
|
* Hold :kbd:`Ctrl+Shift` and right-click on any command output in the scrollback
|
||||||
|
to view it in a pager
|
||||||
|
|
||||||
|
* The current working directory or the command being executed are automatically
|
||||||
|
displayed in the kitty window titlebar/tab title
|
||||||
|
|
||||||
|
* The text cursor is changed to a bar when editing commands at the shell prompt
|
||||||
|
|
||||||
|
* :ref:`clone_shell` with all environment variables and the working directory
|
||||||
|
copied
|
||||||
|
|
||||||
|
* :ref:`Edit files in new kitty windows <edit_file>` even over SSH
|
||||||
|
|
||||||
|
* Glitch free window resizing even with complex prompts. Achieved by erasing
|
||||||
|
the prompt on resize and allowing the shell to redraw it cleanly.
|
||||||
|
|
||||||
|
* Sophisticated completion for the :program:`kitty` command in the shell.
|
||||||
|
|
||||||
|
* When confirming a quit command if a window is sitting at a shell prompt,
|
||||||
|
it is not counted (for details, see :opt:`confirm_os_window_close`)
|
||||||
|
|
||||||
|
|
||||||
|
Configuration
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Shell integration is controlled by the :opt:`shell_integration` option. By
|
||||||
|
default, all integration features are enabled. Individual features can be turned
|
||||||
|
off or it can be disabled entirely as well. The :opt:`shell_integration` option
|
||||||
|
takes a space separated list of keywords:
|
||||||
|
|
||||||
|
disabled
|
||||||
|
Turn off all shell integration. The shell's launch environment is not
|
||||||
|
modified and :envvar:`KITTY_SHELL_INTEGRATION` is not set. Useful for
|
||||||
|
:ref:`manual integration <manual_shell_integration>`.
|
||||||
|
|
||||||
|
no-rc
|
||||||
|
Do not modify the shell's launch environment to enable integration. Useful
|
||||||
|
if you prefer to load the kitty shell integration code yourself, either as
|
||||||
|
part of :ref:`manually integration <manual_shell_integration>` or because
|
||||||
|
you have some other software that sets up shell integration.
|
||||||
|
This will still set the :envvar:`KITTY_SHELL_INTEGRATION` environment
|
||||||
|
variable when kitty runs the shell.
|
||||||
|
|
||||||
|
no-cursor
|
||||||
|
Turn off changing of the text cursor to a bar when editing shell command
|
||||||
|
line.
|
||||||
|
|
||||||
|
no-title
|
||||||
|
Turn off setting the kitty window/tab title based on shell state.
|
||||||
|
Note that for the fish shell kitty relies on fish's native title setting
|
||||||
|
functionality instead.
|
||||||
|
|
||||||
|
no-cwd
|
||||||
|
Turn off reporting the current working directory. This is used to allow
|
||||||
|
:ac:`new_window_with_cwd` and similar to open windows logged into remote
|
||||||
|
machines using the :doc:`ssh kitten <kittens/ssh>` automatically with the
|
||||||
|
same working directory as the current window.
|
||||||
|
Note that for the fish shell this will not disable its built-in current
|
||||||
|
working directory reporting.
|
||||||
|
|
||||||
|
no-prompt-mark
|
||||||
|
Turn off marking of prompts. This disables jumping to prompt, browsing
|
||||||
|
output of last command and click to move cursor functionality.
|
||||||
|
|
||||||
|
no-complete
|
||||||
|
Turn off completion for the kitty command.
|
||||||
|
Note that for the fish shell this does not take effect, since fish already
|
||||||
|
comes with a kitty completion script.
|
||||||
|
|
||||||
|
|
||||||
|
More ways to browse command output
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
You can add further key and mouse bindings to browse the output of commands
|
||||||
|
easily. For example to select the output of a command by right clicking the
|
||||||
|
mouse on the output, define the following in :file:`kitty.conf`:
|
||||||
|
|
||||||
|
.. code:: conf
|
||||||
|
|
||||||
|
mouse_map right press ungrabbed mouse_select_command_output
|
||||||
|
|
||||||
|
Now, when you right click on the output, the entire output is selected, ready
|
||||||
|
to be copied.
|
||||||
|
|
||||||
|
The feature to jump to previous prompts (
|
||||||
|
:sc:`scroll_to_previous_prompt` and :sc:`scroll_to_next_prompt`) and mouse
|
||||||
|
actions (:ac:`mouse_select_command_output` and :ac:`mouse_show_command_output`)
|
||||||
|
can be integrated with browsing command output as well. For example, define the
|
||||||
|
following mapping in :file:`kitty.conf`:
|
||||||
|
|
||||||
|
.. code:: conf
|
||||||
|
|
||||||
|
map f1 show_last_visited_command_output
|
||||||
|
|
||||||
|
Now, pressing :kbd:`F1` will cause the output of the last jumped to command or
|
||||||
|
the last mouse clicked command output to be opened in a pager for easy browsing.
|
||||||
|
|
||||||
|
In addition, You can define shortcut to get the first command output on screen.
|
||||||
|
For example, define the following in :file:`kitty.conf`:
|
||||||
|
|
||||||
|
.. code:: conf
|
||||||
|
|
||||||
|
map f1 show_first_command_output_on_screen
|
||||||
|
|
||||||
|
Now, pressing :kbd:`F1` will cause the output of the first command output on
|
||||||
|
screen to be opened in a pager.
|
||||||
|
|
||||||
|
You can also add shortcut to scroll to the last jumped position. For example,
|
||||||
|
define the following in :file:`kitty.conf`:
|
||||||
|
|
||||||
|
.. code:: conf
|
||||||
|
|
||||||
|
map f1 scroll_to_prompt 0
|
||||||
|
|
||||||
|
|
||||||
|
How it works
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
At startup, kitty detects if the shell you have configured (either system wide
|
||||||
|
or the :opt:`shell` option in :file:`kitty.conf`) is a supported shell. If so,
|
||||||
|
kitty injects some shell specific code into the shell, to enable shell
|
||||||
|
integration. How it does so varies for different shells.
|
||||||
|
|
||||||
|
|
||||||
|
.. tab:: zsh
|
||||||
|
|
||||||
|
For zsh, kitty sets the :envvar:`ZDOTDIR` environment variable to make zsh
|
||||||
|
load kitty's :file:`.zshenv` which restores the original value of
|
||||||
|
:envvar:`ZDOTDIR` and sources the original :file:`.zshenv`. It then loads
|
||||||
|
the shell integration code. The remainder of zsh's startup process proceeds
|
||||||
|
as normal.
|
||||||
|
|
||||||
|
.. tab:: fish
|
||||||
|
|
||||||
|
For fish, to make it automatically load the integration code provided by
|
||||||
|
kitty, the integration script directory path is prepended to the
|
||||||
|
:envvar:`XDG_DATA_DIRS` environment variable. This is only applied to the
|
||||||
|
fish process and will be cleaned up by the integration script after startup.
|
||||||
|
No files are added or modified.
|
||||||
|
|
||||||
|
.. tab:: bash
|
||||||
|
|
||||||
|
For bash, kitty starts bash in POSIX mode, using the environment variable
|
||||||
|
:envvar:`ENV` to load the shell integration script. This prevents bash from
|
||||||
|
loading any startup files itself. The loading of the startup files is done
|
||||||
|
by the integration script, after disabling POSIX mode. From the perspective
|
||||||
|
of those scripts there should be no difference to running vanilla bash.
|
||||||
|
|
||||||
|
|
||||||
|
Then, when launching the shell, kitty sets the environment variable
|
||||||
|
:envvar:`KITTY_SHELL_INTEGRATION` to the value of the :opt:`shell_integration`
|
||||||
|
option. The shell integration code reads the environment variable, turns on the
|
||||||
|
specified integration functionality and then unsets the variable so as to not
|
||||||
|
pollute the system.
|
||||||
|
|
||||||
|
The actual shell integration code uses hooks provided by each shell to send
|
||||||
|
special escape codes to kitty, to perform the various tasks. You can see the
|
||||||
|
code used for each shell below:
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Click to toggle shell integration code</summary>
|
||||||
|
|
||||||
|
.. tab:: zsh
|
||||||
|
|
||||||
|
.. literalinclude:: ../shell-integration/zsh/kitty-integration
|
||||||
|
:language: zsh
|
||||||
|
|
||||||
|
|
||||||
|
.. tab:: fish
|
||||||
|
|
||||||
|
.. literalinclude:: ../shell-integration/fish/vendor_conf.d/kitty-shell-integration.fish
|
||||||
|
:language: fish
|
||||||
|
:force:
|
||||||
|
|
||||||
|
.. tab:: bash
|
||||||
|
|
||||||
|
.. literalinclude:: ../shell-integration/bash/kitty.bash
|
||||||
|
:language: bash
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
|
||||||
|
Shell integration over SSH
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
The easiest way to have shell integration work when SSHing into remote systems
|
||||||
|
is to use the :doc:`ssh kitten <kittens/ssh>`. Simply run::
|
||||||
|
|
||||||
|
kitty +kitten ssh hostname
|
||||||
|
|
||||||
|
And, by magic, you will be logged into the remote system with fully functional
|
||||||
|
shell integration. Alternately, you can :ref:`setup shell integration manually
|
||||||
|
<manual_shell_integration>`, by copying the kitty shell integration scripts to
|
||||||
|
the remote server and editing the shell rc files there, as described below.
|
||||||
|
|
||||||
|
|
||||||
|
.. _clone_shell:
|
||||||
|
|
||||||
|
Clone the current shell into a new window
|
||||||
|
-----------------------------------------------
|
||||||
|
|
||||||
|
You can clone the current shell into a new kitty window by simply running the
|
||||||
|
:command:`clone-in-kitty` command, for example:
|
||||||
|
|
||||||
|
.. code-block:: sh
|
||||||
|
|
||||||
|
clone-in-kitty
|
||||||
|
clone-in-kitty --type=tab
|
||||||
|
clone-in-kitty --title "I am a clone"
|
||||||
|
|
||||||
|
This will open a new window running a new shell instance but with all
|
||||||
|
environment variables and the current working directory copied. This even works
|
||||||
|
over SSH when using :doc:`kittens/ssh`.
|
||||||
|
|
||||||
|
The :command:`clone-in-kitty` command takes almost all the same arguments as the
|
||||||
|
:doc:`launch <launch>` command, so you can open a new tab instead or a new OS
|
||||||
|
window, etc. Arguments of launch that can cause code execution or that don't
|
||||||
|
make sense when cloning are ignored. Most prominently, the following options are
|
||||||
|
ignored: :option:`--allow-remote-control <launch --allow-remote-control>`,
|
||||||
|
:option:`--copy-cmdline <launch --copy-cmdline>`, :option:`--copy-env <launch
|
||||||
|
--copy-env>`, :option:`--stdin-source <launch --stdin-source>`,
|
||||||
|
:option:`--marker <launch --marker>` and :option:`--watcher <launch --watcher>`.
|
||||||
|
|
||||||
|
:command:`clone-in-kitty` can be configured to source arbitrary code in the
|
||||||
|
cloned window using environment variables. It will automatically clone virtual
|
||||||
|
environments created by the :link:`Python venv module
|
||||||
|
<https://docs.python.org/3/library/venv.html>` or :link:`Conda
|
||||||
|
<https://conda.io/>`. In addition, setting the
|
||||||
|
env var :envvar:`KITTY_CLONE_SOURCE_CODE` to some shell code will cause that
|
||||||
|
code to be run in the cloned window with :code:`eval`. Similarly, setting
|
||||||
|
:envvar:`KITTY_CLONE_SOURCE_PATH` to the path of a file will cause that file to
|
||||||
|
be sourced in the cloned window. This can be controlled by
|
||||||
|
:opt:`clone_source_strategies`.
|
||||||
|
|
||||||
|
:command:`clone-in-kitty` works by asking the shell to serialize its internal
|
||||||
|
state (mainly CWD and env vars) and this state is transmitted to kitty and
|
||||||
|
restored by the shell integration scripts in the cloned window.
|
||||||
|
|
||||||
|
|
||||||
|
.. _edit_file:
|
||||||
|
|
||||||
|
Edit files in new kitty windows even over SSH
|
||||||
|
------------------------------------------------
|
||||||
|
|
||||||
|
.. code-block:: sh
|
||||||
|
|
||||||
|
edit-in-kitty myfile.txt
|
||||||
|
edit-in-kitty --type tab --title "Editing My File" myfile.txt
|
||||||
|
# open myfile.txt at line 75 (works with vim, neovim, emacs, nano, micro)
|
||||||
|
edit-in-kitty +75 myfile.txt
|
||||||
|
|
||||||
|
The :command:`edit-in-kitty` command allows you to seamlessly edit files
|
||||||
|
in your default :opt:`editor` in new kitty windows. This works even over
|
||||||
|
SSH (if you use the :doc:`ssh kitten <kittens/ssh>`), allowing you
|
||||||
|
to easily edit remote files in your local editor with all its bells and
|
||||||
|
whistles.
|
||||||
|
|
||||||
|
The :command:`edit-in-kitty` command takes almost all the same arguments as the
|
||||||
|
:doc:`launch <launch>` command, so you can open a new tab instead or a new OS
|
||||||
|
window, etc. Not all arguments are supported, see the discussion in the
|
||||||
|
:ref:`clone_shell` section above.
|
||||||
|
|
||||||
|
In order to avoid remote code execution, kitty will only execute the configured
|
||||||
|
editor and pass the file path to edit to it.
|
||||||
|
|
||||||
|
|
||||||
|
.. _manual_shell_integration:
|
||||||
|
|
||||||
|
Manual shell integration
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
The automatic shell integration is designed to be minimally intrusive, as such
|
||||||
|
it wont work for sub-shells, terminal multiplexers, containers, etc.
|
||||||
|
For such systems, you should setup manual shell integration by adding some code
|
||||||
|
to your shells startup files to load the shell integration script.
|
||||||
|
|
||||||
|
First, in :file:`kitty.conf` set:
|
||||||
|
|
||||||
|
.. code-block:: conf
|
||||||
|
|
||||||
|
shell_integration disabled
|
||||||
|
|
||||||
|
Then in your shell's rc file, add the lines:
|
||||||
|
|
||||||
|
.. tab:: zsh
|
||||||
|
|
||||||
|
.. code-block:: sh
|
||||||
|
|
||||||
|
if test -n "$KITTY_INSTALLATION_DIR"; then
|
||||||
|
export KITTY_SHELL_INTEGRATION="enabled"
|
||||||
|
autoload -Uz -- "$KITTY_INSTALLATION_DIR"/shell-integration/zsh/kitty-integration
|
||||||
|
kitty-integration
|
||||||
|
unfunction kitty-integration
|
||||||
|
fi
|
||||||
|
|
||||||
|
.. tab:: fish
|
||||||
|
|
||||||
|
.. code-block:: fish
|
||||||
|
|
||||||
|
if set -q KITTY_INSTALLATION_DIR
|
||||||
|
set --global KITTY_SHELL_INTEGRATION enabled
|
||||||
|
source "$KITTY_INSTALLATION_DIR/shell-integration/fish/vendor_conf.d/kitty-shell-integration.fish"
|
||||||
|
set --prepend fish_complete_path "$KITTY_INSTALLATION_DIR/shell-integration/fish/vendor_completions.d"
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
.. tab:: bash
|
||||||
|
|
||||||
|
.. code-block:: sh
|
||||||
|
|
||||||
|
if test -n "$KITTY_INSTALLATION_DIR"; then
|
||||||
|
export KITTY_SHELL_INTEGRATION="enabled"
|
||||||
|
source "$KITTY_INSTALLATION_DIR/shell-integration/bash/kitty.bash"
|
||||||
|
fi
|
||||||
|
|
||||||
|
The value of :envvar:`KITTY_SHELL_INTEGRATION` is the same as that for
|
||||||
|
:opt:`shell_integration`, except if you want to disable shell integration
|
||||||
|
completely, in which case simply do not set the
|
||||||
|
:envvar:`KITTY_SHELL_INTEGRATION` variable at all.
|
||||||
|
|
||||||
|
In a container, you will need to install the kitty shell integration scripts
|
||||||
|
and make sure the :envvar:`KITTY_INSTALLATION_DIR` environment variable is set
|
||||||
|
to point to the location of the scripts.
|
||||||
|
|
||||||
|
Integration with other shells
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
There exist third-party integrations to use these features for various other
|
||||||
|
shells:
|
||||||
|
|
||||||
|
* Jupyter console and IPython via a patch (:iss:`4475`)
|
||||||
|
* `xonsh <https://github.com/xonsh/xonsh/issues/4623>`__
|
||||||
|
|
||||||
|
|
||||||
|
Notes for shell developers
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
The protocol used for marking the prompt is very simple. You should consider
|
||||||
|
adding it to your shell as a builtin. Many modern terminals make use of it, for
|
||||||
|
example: kitty, iTerm2, WezTerm, DomTerm
|
||||||
|
|
||||||
|
Just before starting to draw the PS1 prompt send the escape code::
|
||||||
|
|
||||||
|
<OSC>133;A<ST>
|
||||||
|
|
||||||
|
Just before starting to draw the PS2 prompt send the escape code::
|
||||||
|
|
||||||
|
<OSC>133;A;k=s<ST>
|
||||||
|
|
||||||
|
Just before running a command/program, send the escape code::
|
||||||
|
|
||||||
|
<OSC>133;C<ST>
|
||||||
|
|
||||||
|
Here ``<OSC>`` is the bytes ``0x1b 0x5d`` and ``<ST>`` is the bytes ``0x1b
|
||||||
|
0x5c``. This is exactly what is needed for shell integration in kitty. For the
|
||||||
|
full protocol, that also marks the command region, see `the iTerm2 docs
|
||||||
|
<https://iterm2.com/documentation-escape-codes.html>`_.
|
||||||
@@ -1,7 +1,12 @@
|
|||||||
<style>
|
<style>
|
||||||
|
#support-buttons {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
.support-button {
|
.support-button {
|
||||||
|
box-sizing: border-box;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
box-shadow: rgb(255, 246, 175) 0px 1px 0px 0px;
|
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: rgb(51, 51, 51);
|
color: rgb(51, 51, 51);
|
||||||
@@ -10,15 +15,16 @@
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
padding: 8px 24px;
|
padding: 8px 24px;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
margin-left: 1em;
|
||||||
|
outline: 0;
|
||||||
|
border-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.support-button:hover {
|
.support-button:hover {
|
||||||
transform: scale(1.5);
|
transform: scale(1.2);
|
||||||
|
border: solid 1px rgb(92, 184, 92);
|
||||||
}
|
}
|
||||||
|
|
||||||
.support-button {
|
|
||||||
outline: 0;
|
|
||||||
}
|
|
||||||
.support-button:visited {
|
.support-button:visited {
|
||||||
color: rgb(51, 51, 51);
|
color: rgb(51, 51, 51);
|
||||||
outline: 0;
|
outline: 0;
|
||||||
@@ -30,28 +36,34 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
#paypal input[type=submit] {
|
#paypal input[type=submit] {
|
||||||
background: linear-gradient(rgb(255, 236, 100) 5%, rgb(255, 171, 35) 100%) rgb(255, 236, 100);
|
background: linear-gradient(rgb(92, 184, 92) 5%, rgb(62, 142, 62) 100%) rgb(92, 184, 92);
|
||||||
border: 1px solid rgb(255, 171, 35);
|
padding-top: 10px; padding-bottom: 10px;
|
||||||
|
color: rgb(51, 51, 51);
|
||||||
|
border: 1px solid rgb(92, 184, 92);
|
||||||
}
|
}
|
||||||
|
|
||||||
#liberapay a {
|
a.support-button {
|
||||||
background: linear-gradient(rgb(92, 184, 92) 5%, rgb(62, 142, 62) 100%) rgb(92, 184, 92);
|
background: linear-gradient(rgb(92, 184, 92) 5%, rgb(62, 142, 62) 100%) rgb(92, 184, 92);
|
||||||
border: 1px solid rgb(62, 142, 62);
|
|
||||||
color: rgb(51, 51, 51);
|
color: rgb(51, 51, 51);
|
||||||
}
|
}
|
||||||
|
|
||||||
#patreon a {
|
|
||||||
background: linear-gradient(rgb(11, 100, 163) 5%, rgb(5, 45, 73) 100%) rgb(11, 100, 163);
|
|
||||||
border: 1px solid rgb(5, 45, 73);
|
|
||||||
color: #eee;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<div id="support-buttons">
|
<div id="support-buttons">
|
||||||
|
|
||||||
|
<div id="github">
|
||||||
|
<a class="support-button" href="https://github.com/sponsors/kovidgoyal">Patronage via GitHub</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div id="patreon">
|
<div id="patreon">
|
||||||
<a class="support-button" href="https://www.patreon.com/bePatron?u=917933">Patronage via Patreon</a>
|
<a class="support-button" href="https://www.patreon.com/bePatron?u=917933">Patronage via Patreon</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="liberapay">
|
||||||
|
<a class="support-button" href="https://liberapay.com/kovidgoyal/donate">Patronage via Liberapay</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<form id="paypal" action="https://www.paypal.com/cgi-bin/webscr" method="post" title="Contribute to support calibre development">
|
<form id="paypal" action="https://www.paypal.com/cgi-bin/webscr" method="post" title="Contribute to support calibre development">
|
||||||
<input type="hidden" name="cmd" value="_s-xclick" />
|
<input type="hidden" name="cmd" value="_s-xclick" />
|
||||||
@@ -61,9 +73,5 @@
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="liberapay">
|
|
||||||
<a class="support-button" href="https://liberapay.com/kovidgoyal/donate">Patronage via Liberapay</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
Support kitty development
|
Support kitty development ❤️
|
||||||
===========================
|
==============================
|
||||||
|
|
||||||
My goal with |kitty| is to move the stagnant terminal ecosystem forward. To that
|
My goal with |kitty| is to move the stagnant terminal ecosystem forward. To that
|
||||||
end kitty has many foundational features, such as: :doc:`image support
|
end kitty has many foundational features, such as: :doc:`image support
|
||||||
@@ -7,7 +7,7 @@ end kitty has many foundational features, such as: :doc:`image support
|
|||||||
:doc:`various enhancements to the terminal protocol <protocol-extensions>`,
|
:doc:`various enhancements to the terminal protocol <protocol-extensions>`,
|
||||||
etc. These features allow the development of rich terminal applications, such
|
etc. These features allow the development of rich terminal applications, such
|
||||||
as :doc:`Side-by-side diff <kittens/diff>` and :doc:`Unicode input
|
as :doc:`Side-by-side diff <kittens/diff>` and :doc:`Unicode input
|
||||||
<kittens/unicode-input>`.
|
<kittens/unicode_input>`.
|
||||||
|
|
||||||
If you wish to support this mission and see the terminal ecosystem evolve,
|
If you wish to support this mission and see the terminal ecosystem evolve,
|
||||||
consider donating so that I can devote more time to |kitty| development.
|
consider donating so that I can devote more time to |kitty| development.
|
||||||
@@ -15,8 +15,7 @@ I have personally written `almost all kitty code
|
|||||||
<https://github.com/kovidgoyal/kitty/graphs/contributors>`_.
|
<https://github.com/kovidgoyal/kitty/graphs/contributors>`_.
|
||||||
|
|
||||||
You can choose to make either a one-time payment via PayPal or become a
|
You can choose to make either a one-time payment via PayPal or become a
|
||||||
*patron* of kitty development via the Patreon or Liberapay services
|
*patron* of kitty development via one of the services below:
|
||||||
below:
|
|
||||||
|
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|||||||
@@ -1,24 +1,25 @@
|
|||||||
Colored and styled underlines
|
Colored and styled underlines
|
||||||
================================
|
================================
|
||||||
|
|
||||||
|kitty| supports colored and styled (wavy) underlines. This is of particular
|
|kitty| supports colored and styled (wavy) underlines. This is of particular use
|
||||||
use in terminal editors such as vim and emacs to display red, wavy underlines
|
in terminal based text editors such as :program:`vim` and :program:`emacs` to
|
||||||
under mis-spelled words and/or syntax errors. This is done by re-purposing some
|
display red, wavy underlines under mis-spelled words and/or syntax errors. This
|
||||||
SGR escape codes that are not used in modern terminals (`CSI codes
|
is done by re-purposing some SGR escape codes that are not used in modern
|
||||||
<https://en.wikipedia.org/wiki/ANSI_escape_code#CSI_(Control_Sequence_Introducer)_sequences>`_)
|
terminals (`CSI codes <https://en.wikipedia.org/wiki/ANSI_escape_code#CSI_(Control_Sequence_Introducer)_sequences>`__)
|
||||||
|
|
||||||
To set the underline style::
|
To set the underline style::
|
||||||
|
|
||||||
<ESC>[4:0m # this is no underline
|
<ESC>[4:0m # no underline
|
||||||
<ESC>[4:1m # this is a straight underline
|
<ESC>[4:1m # straight underline
|
||||||
<ESC>[4:2m # this is a double underline
|
<ESC>[4:2m # double underline
|
||||||
<ESC>[4:3m # this is a curly underline
|
<ESC>[4:3m # curly underline
|
||||||
<ESC>[4:4m # this is a dotted underline (not implemented in kitty)
|
<ESC>[4:4m # dotted underline
|
||||||
<ESC>[4:5m # this is a dashed underline (not implemented in kitty)
|
<ESC>[4:5m # dashed underline
|
||||||
<ESC>[4m # this is a straight underline (for backwards compat)
|
<ESC>[4m # straight underline (for backwards compat)
|
||||||
<ESC>[24m # this is no underline (for backwards compat)
|
<ESC>[24m # no underline (for backwards compat)
|
||||||
|
|
||||||
To set the underline color (this is reserved and as far as I can tell not actually used for anything)::
|
To set the underline color (this is reserved and as far as I can tell not
|
||||||
|
actually used for anything)::
|
||||||
|
|
||||||
<ESC>[58...m
|
<ESC>[58...m
|
||||||
|
|
||||||
@@ -29,8 +30,8 @@ To reset the underline color (also previously reserved and unused)::
|
|||||||
|
|
||||||
<ESC>[59m
|
<ESC>[59m
|
||||||
|
|
||||||
The underline color must remain the same under reverse video, if it has a
|
The underline color must remain the same under reverse video, if it has a color,
|
||||||
color, if not, it should follow the foreground color.
|
if not, it should follow the foreground color.
|
||||||
|
|
||||||
To detect support for this feature in a terminal emulator, query the terminfo database
|
To detect support for this feature in a terminal emulator, query the terminfo
|
||||||
for the ``Su`` boolean capability.
|
database for the ``Su`` boolean capability.
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ Unscrolling the screen
|
|||||||
========================
|
========================
|
||||||
|
|
||||||
This is a small extension to the `SD (Pan up) escape code
|
This is a small extension to the `SD (Pan up) escape code
|
||||||
<https://vt100.net/docs/vt510-rm/SD.html>`_ from the VT-420 terminal. The
|
<https://vt100.net/docs/vt510-rm/SD.html>`_ from the VT-420 terminal. The ``SD``
|
||||||
``SD`` escape code normally causes the text on screen to scroll down by the
|
escape code normally causes the text on screen to scroll down by the specified
|
||||||
specified number of lines, with empty lines appearing at the top of the screen.
|
number of lines, with empty lines appearing at the top of the screen. This
|
||||||
This extension allows the new lines to be filled in from the scrollback buffer
|
extension allows the new lines to be filled in from the scrollback buffer
|
||||||
instead of being blank.
|
instead of being blank.
|
||||||
|
|
||||||
The motivation for this is that many modern shells will show completions in a
|
The motivation for this is that many modern shells will show completions in a
|
||||||
@@ -22,13 +22,17 @@ scrolled down is implementation defined, but must be at least one screen worth.
|
|||||||
|
|
||||||
The syntax of the escape code is identical to that of ``SD`` except that it has
|
The syntax of the escape code is identical to that of ``SD`` except that it has
|
||||||
a trailing ``+`` modifier. This is legal under the `ECMA 48 standard
|
a trailing ``+`` modifier. This is legal under the `ECMA 48 standard
|
||||||
<https://www.ecma-international.org/publications-and-standards/standards/ecma-48/>`_
|
<https://www.ecma-international.org/publications-and-standards/standards/ecma-48/>`__
|
||||||
and unused for any other purpose as far as I can tell. So for example, to
|
and unused for any other purpose as far as I can tell. So for example, to
|
||||||
unscroll three lines, the escape code would be::
|
unscroll three lines, the escape code would be::
|
||||||
|
|
||||||
CSI 3 + T
|
CSI 3 + T
|
||||||
|
|
||||||
See `discussion here
|
See `discussion here
|
||||||
<https://gitlab.freedesktop.org/terminal-wg/specifications/-/issues/30>`_.
|
<https://gitlab.freedesktop.org/terminal-wg/specifications/-/issues/30>`__.
|
||||||
|
|
||||||
.. versionadded:: 0.20.2
|
.. versionadded:: 0.20.2
|
||||||
|
|
||||||
|
Also supported by the terminals:
|
||||||
|
|
||||||
|
* `mintty <https://github.com/mintty/mintty/releases/tag/3.5.2>`__
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# vim:fileencoding=utf-8
|
|
||||||
# License: GPLv3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
|
# License: GPLv3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from typing import Any, DefaultDict, Dict, FrozenSet, List, Tuple, Union
|
from typing import Any, DefaultDict, Dict, FrozenSet, List, Tuple, Union
|
||||||
@@ -43,7 +43,7 @@ def parse_flag(keymap: KeymapType, type_map: Dict[str, Any], command_class: str)
|
|||||||
lines = []
|
lines = []
|
||||||
for ch in type_map['flag']:
|
for ch in type_map['flag']:
|
||||||
attr, allowed_values = keymap[ch]
|
attr, allowed_values = keymap[ch]
|
||||||
q = ' && '.join(f"g.{attr} != '{x}'" for x in allowed_values)
|
q = ' && '.join(f"g.{attr} != '{x}'" for x in sorted(allowed_values))
|
||||||
lines.append(f'''
|
lines.append(f'''
|
||||||
case {attr}: {{
|
case {attr}: {{
|
||||||
g.{attr} = screen->parser_buf[pos++] & 0xff;
|
g.{attr} = screen->parser_buf[pos++] & 0xff;
|
||||||
@@ -68,7 +68,7 @@ def cmd_for_report(report_name: str, keymap: KeymapType, type_map: Dict[str, Any
|
|||||||
flag_fmt, flag_attrs = [], []
|
flag_fmt, flag_attrs = [], []
|
||||||
cv = {'flag': 'c', 'int': 'i', 'uint': 'I'}[atype]
|
cv = {'flag': 'c', 'int': 'i', 'uint': 'I'}[atype]
|
||||||
for ch in type_map[atype]:
|
for ch in type_map[atype]:
|
||||||
flag_fmt.append('s' + cv)
|
flag_fmt.append(f's{cv}')
|
||||||
attr = keymap[ch][0]
|
attr = keymap[ch][0]
|
||||||
flag_attrs.append(f'"{attr}", {conv}g.{attr}')
|
flag_attrs.append(f'"{attr}", {conv}g.{attr}')
|
||||||
return ' '.join(flag_fmt), ', '.join(flag_attrs)
|
return ' '.join(flag_fmt), ', '.join(flag_attrs)
|
||||||
@@ -241,7 +241,7 @@ static inline void
|
|||||||
|
|
||||||
def write_header(text: str, path: str) -> None:
|
def write_header(text: str, path: str) -> None:
|
||||||
with open(path, 'w') as f:
|
with open(path, 'w') as f:
|
||||||
print(f'// This file is generated by {__file__} do not edit!', file=f, end='\n\n')
|
print(f'// This file is generated by {os.path.basename(__file__)} do not edit!', file=f, end='\n\n')
|
||||||
print('#pragma once', file=f)
|
print('#pragma once', file=f)
|
||||||
print(text, file=f)
|
print(text, file=f)
|
||||||
subprocess.check_call(['clang-format', '-i', path])
|
subprocess.check_call(['clang-format', '-i', path])
|
||||||
|
|||||||
@@ -1,16 +1,45 @@
|
|||||||
#!/usr/bin/env python
|
#!./kitty/launcher/kitty +launch
|
||||||
# vim:fileencoding=utf-8
|
|
||||||
# License: GPLv3 Copyright: 2021, Kovid Goyal <kovid at kovidgoyal.net>
|
# License: GPLv3 Copyright: 2021, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
|
|
||||||
|
import re
|
||||||
|
from typing import List
|
||||||
|
|
||||||
from kitty.conf.generate import write_output
|
from kitty.conf.generate import write_output
|
||||||
|
|
||||||
|
|
||||||
|
def patch_color_list(path: str, colors: List[str], name: str, spc: str = ' ') -> None:
|
||||||
|
with open(path, 'r+') as f:
|
||||||
|
raw = f.read()
|
||||||
|
nraw = re.sub(
|
||||||
|
fr'(# {name}_COLORS_START).+?(\s+# {name}_COLORS_END)',
|
||||||
|
r'\1' + f'\n{spc}' + f'\n{spc}'.join(map(lambda x: f'{x!r},', sorted(colors))) + r'\2',
|
||||||
|
raw, flags=re.DOTALL | re.MULTILINE)
|
||||||
|
if nraw != raw:
|
||||||
|
f.seek(0)
|
||||||
|
f.truncate()
|
||||||
|
f.write(nraw)
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
from kitty.options.definition import definition
|
from kitty.options.definition import definition
|
||||||
write_output('kitty', definition)
|
write_output('kitty', definition)
|
||||||
|
nullable_colors = []
|
||||||
|
all_colors = []
|
||||||
|
for opt in definition.iter_all_options():
|
||||||
|
if callable(opt.parser_func):
|
||||||
|
if opt.parser_func.__name__ in ('to_color_or_none', 'cursor_text_color'):
|
||||||
|
nullable_colors.append(opt.name)
|
||||||
|
all_colors.append(opt.name)
|
||||||
|
elif opt.parser_func.__name__ in ('to_color', 'titlebar_color', 'macos_titlebar_color'):
|
||||||
|
all_colors.append(opt.name)
|
||||||
|
patch_color_list('kitty/rc/set_colors.py', nullable_colors, 'NULLABLE')
|
||||||
|
patch_color_list('kittens/themes/collection.py', all_colors, 'ALL', ' ' * 8)
|
||||||
|
|
||||||
from kittens.diff.options.definition import definition as kd
|
from kittens.diff.options.definition import definition as kd
|
||||||
write_output('kittens.diff', kd)
|
write_output('kittens.diff', kd)
|
||||||
|
from kittens.ssh.options.definition import definition as sd
|
||||||
|
write_output('kittens.ssh', sd)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# vim:fileencoding=utf-8
|
|
||||||
# License: GPLv3 Copyright: 2021, Kovid Goyal <kovid at kovidgoyal.net>
|
# License: GPLv3 Copyright: 2021, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
import string
|
import string
|
||||||
@@ -239,13 +238,13 @@ def patch_file(path: str, what: str, text: str, start_marker: str = '/* ', end_m
|
|||||||
end = raw.index(end_q)
|
end = raw.index(end_q)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise SystemExit(f'Failed to find "{end_q}" in {path}')
|
raise SystemExit(f'Failed to find "{end_q}" in {path}')
|
||||||
raw = raw[:start] + start_q + '\n' + text + '\n' + raw[end:]
|
raw = f'{raw[:start]}{start_q}\n{text}\n{raw[end:]}'
|
||||||
f.seek(0)
|
f.seek(0)
|
||||||
f.truncate(0)
|
f.truncate(0)
|
||||||
f.write(raw)
|
f.write(raw)
|
||||||
|
|
||||||
|
|
||||||
def serialize_dict(x: dict) -> str:
|
def serialize_dict(x: Dict[Any, Any]) -> str:
|
||||||
return pformat(x, indent=4).replace('{', '{\n ', 1)
|
return pformat(x, indent=4).replace('{', '{\n ', 1)
|
||||||
|
|
||||||
|
|
||||||
@@ -349,7 +348,7 @@ def generate_legacy_text_key_maps() -> None:
|
|||||||
patch_file('kitty_tests/keys.py', 'legacy letter tests', '\n'.join(tests), start_marker='# ', end_marker='')
|
patch_file('kitty_tests/keys.py', 'legacy letter tests', '\n'.join(tests), start_marker='# ', end_marker='')
|
||||||
|
|
||||||
|
|
||||||
def chunks(lst: List, n: int) -> Any:
|
def chunks(lst: List[Any], n: int) -> Any:
|
||||||
"""Yield successive n-sized chunks from lst."""
|
"""Yield successive n-sized chunks from lst."""
|
||||||
for i in range(0, len(lst), n):
|
for i in range(0, len(lst), n):
|
||||||
yield lst[i:i + n]
|
yield lst[i:i + n]
|
||||||
@@ -369,7 +368,7 @@ def generate_ctrl_mapping() -> None:
|
|||||||
val = str(ctrl_mapping[k])
|
val = str(ctrl_mapping[k])
|
||||||
items.append(val)
|
items.append(val)
|
||||||
if k in "\\'":
|
if k in "\\'":
|
||||||
k = '\\' + k
|
k = f'\\{k}'
|
||||||
mi.append(f" case '{k}': return {val};")
|
mi.append(f" case '{k}': return {val};")
|
||||||
|
|
||||||
for line_items in chunks(items, 6):
|
for line_items in chunks(items, 6):
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# vim:fileencoding=utf-8
|
|
||||||
# License: GPL v3 Copyright: 2017, Kovid Goyal <kovid at kovidgoyal.net>
|
# License: GPL v3 Copyright: 2017, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
import os
|
import os
|
||||||
@@ -50,10 +49,25 @@ class_maps: Dict[str, Set[int]] = {}
|
|||||||
all_symbols: Set[int] = set()
|
all_symbols: Set[int] = set()
|
||||||
name_map: Dict[int, str] = {}
|
name_map: Dict[int, str] = {}
|
||||||
word_search_map: DefaultDict[str, Set[int]] = defaultdict(set)
|
word_search_map: DefaultDict[str, Set[int]] = defaultdict(set)
|
||||||
zwj = 0x200d
|
soft_hyphen = 0xad
|
||||||
flag_codepoints = frozenset(range(0x1F1E6, 0x1F1E6 + 26))
|
flag_codepoints = frozenset(range(0x1F1E6, 0x1F1E6 + 26))
|
||||||
marks = set(emoji_skin_tone_modifiers) | {zwj} | flag_codepoints
|
# See https://github.com/harfbuzz/harfbuzz/issues/169
|
||||||
|
marks = set(emoji_skin_tone_modifiers) | flag_codepoints
|
||||||
not_assigned = set(range(0, sys.maxunicode))
|
not_assigned = set(range(0, sys.maxunicode))
|
||||||
|
property_maps: Dict[str, Set[int]] = defaultdict(set)
|
||||||
|
|
||||||
|
|
||||||
|
def parse_prop_list() -> None:
|
||||||
|
global marks
|
||||||
|
for line in get_data('ucd/PropList.txt'):
|
||||||
|
if line.startswith('#'):
|
||||||
|
continue
|
||||||
|
cp_or_range, rest = line.split(';', 1)
|
||||||
|
chars = parse_range_spec(cp_or_range.strip())
|
||||||
|
name = rest.strip().split()[0]
|
||||||
|
property_maps[name] |= chars
|
||||||
|
# see https://www.unicode.org/faq/unsup_char.html#3
|
||||||
|
marks |= property_maps['Other_Default_Ignorable_Code_Point']
|
||||||
|
|
||||||
|
|
||||||
def parse_ucd() -> None:
|
def parse_ucd() -> None:
|
||||||
@@ -97,6 +111,12 @@ def parse_ucd() -> None:
|
|||||||
marks.add(codepoint)
|
marks.add(codepoint)
|
||||||
elif category.startswith('S'):
|
elif category.startswith('S'):
|
||||||
all_symbols.add(codepoint)
|
all_symbols.add(codepoint)
|
||||||
|
elif category == 'Cf':
|
||||||
|
# we add Cf to marks as it contains things like tags and zero
|
||||||
|
# width chars. Not sure if *all* of Cf should be treated as
|
||||||
|
# combining chars, might need to add individual exceptions in
|
||||||
|
# the future.
|
||||||
|
marks.add(codepoint)
|
||||||
|
|
||||||
with open('nerd-fonts-glyphs.txt') as f:
|
with open('nerd-fonts-glyphs.txt') as f:
|
||||||
for line in f:
|
for line in f:
|
||||||
@@ -213,7 +233,7 @@ def parse_eaw() -> None:
|
|||||||
if eaw == 'A':
|
if eaw == 'A':
|
||||||
ambiguous |= chars
|
ambiguous |= chars
|
||||||
seen |= chars
|
seen |= chars
|
||||||
elif eaw == 'W' or eaw == 'F':
|
elif eaw in ('W', 'F'):
|
||||||
doublewidth |= chars
|
doublewidth |= chars
|
||||||
seen |= chars
|
seen |= chars
|
||||||
doublewidth |= set(range(0x3400, 0x4DBF + 1)) - seen
|
doublewidth |= set(range(0x3400, 0x4DBF + 1)) - seen
|
||||||
@@ -234,15 +254,15 @@ def get_ranges(items: List[int]) -> Generator[Union[int, Tuple[int, int]], None,
|
|||||||
yield a, b
|
yield a, b
|
||||||
|
|
||||||
|
|
||||||
def write_case(spec: Union[Tuple, int], p: Callable) -> None:
|
def write_case(spec: Union[Tuple[int, ...], int], p: Callable[..., None]) -> None:
|
||||||
if isinstance(spec, tuple):
|
if isinstance(spec, tuple):
|
||||||
p('\t\tcase 0x{:x} ... 0x{:x}:'.format(*spec))
|
p('\t\tcase 0x{:x} ... 0x{:x}:'.format(*spec))
|
||||||
else:
|
else:
|
||||||
p('\t\tcase 0x{:x}:'.format(spec))
|
p(f'\t\tcase 0x{spec:x}:')
|
||||||
|
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def create_header(path: str, include_data_types: bool = True) -> Generator[Callable, None, None]:
|
def create_header(path: str, include_data_types: bool = True) -> Generator[Callable[..., None], None, None]:
|
||||||
with open(path, 'w') as f:
|
with open(path, 'w') as f:
|
||||||
p = partial(print, file=f)
|
p = partial(print, file=f)
|
||||||
p('// unicode data, built from the unicode standard on:', date.today())
|
p('// unicode data, built from the unicode standard on:', date.today())
|
||||||
@@ -282,7 +302,7 @@ def gen_emoji() -> None:
|
|||||||
|
|
||||||
def category_test(
|
def category_test(
|
||||||
name: str,
|
name: str,
|
||||||
p: Callable,
|
p: Callable[..., None],
|
||||||
classes: Iterable[str],
|
classes: Iterable[str],
|
||||||
comment: str,
|
comment: str,
|
||||||
use_static: bool = False,
|
use_static: bool = False,
|
||||||
@@ -312,7 +332,7 @@ def category_test(
|
|||||||
p('\treturn false;\n}\n')
|
p('\treturn false;\n}\n')
|
||||||
|
|
||||||
|
|
||||||
def codepoint_to_mark_map(p: Callable, mark_map: List[int]) -> Dict[int, int]:
|
def codepoint_to_mark_map(p: Callable[..., None], mark_map: List[int]) -> Dict[int, int]:
|
||||||
p('\tswitch(c) { // {{{')
|
p('\tswitch(c) { // {{{')
|
||||||
rmap = {c: m for m, c in enumerate(mark_map)}
|
rmap = {c: m for m, c in enumerate(mark_map)}
|
||||||
for spec in get_ranges(mark_map):
|
for spec in get_ranges(mark_map):
|
||||||
@@ -336,10 +356,10 @@ def classes_to_regex(classes: Iterable[str], exclude: str = '') -> Iterable[str]
|
|||||||
|
|
||||||
def as_string(codepoint: int) -> str:
|
def as_string(codepoint: int) -> str:
|
||||||
if codepoint < 256:
|
if codepoint < 256:
|
||||||
return r'\x{:02x}'.format(codepoint)
|
return fr'\x{codepoint:02x}'
|
||||||
if codepoint <= 0xffff:
|
if codepoint <= 0xffff:
|
||||||
return r'\u{:04x}'.format(codepoint)
|
return fr'\u{codepoint:04x}'
|
||||||
return r'\U{:08x}'.format(codepoint)
|
return fr'\U{codepoint:08x}'
|
||||||
|
|
||||||
for spec in get_ranges(list(chars)):
|
for spec in get_ranges(list(chars)):
|
||||||
if isinstance(spec, tuple):
|
if isinstance(spec, tuple):
|
||||||
@@ -354,16 +374,21 @@ def gen_ucd() -> None:
|
|||||||
p('#include "unicode-data.h"')
|
p('#include "unicode-data.h"')
|
||||||
category_test(
|
category_test(
|
||||||
'is_combining_char', p,
|
'is_combining_char', p,
|
||||||
{c for c in class_maps if c.startswith('M')},
|
(),
|
||||||
'M category (marks)',
|
'Combining and default ignored characters',
|
||||||
# See https://github.com/harfbuzz/harfbuzz/issues/169
|
extra_chars=marks,
|
||||||
extra_chars=emoji_skin_tone_modifiers | {zwj},
|
|
||||||
least_check_return='false'
|
least_check_return='false'
|
||||||
)
|
)
|
||||||
category_test(
|
category_test(
|
||||||
'is_ignored_char', p, 'Cc Cf Cs'.split(),
|
'is_ignored_char', p, 'Cc Cs'.split(),
|
||||||
'Control characters and non-characters',
|
'Control characters and non-characters',
|
||||||
extra_chars=non_characters, exclude={zwj},
|
extra_chars=non_characters,
|
||||||
|
ascii_range='false'
|
||||||
|
)
|
||||||
|
category_test(
|
||||||
|
'is_non_rendered_char', p, 'Cc Cs Cf'.split(),
|
||||||
|
'Other_Default_Ignorable_Code_Point and soft hyphen',
|
||||||
|
extra_chars=property_maps['Other_Default_Ignorable_Code_Point'] | set(range(0xfe00, 0xfe0f + 1)),
|
||||||
ascii_range='false'
|
ascii_range='false'
|
||||||
)
|
)
|
||||||
category_test('is_word_char', p, {c for c in class_maps if c[0] in 'LN'}, 'L and N categories')
|
category_test('is_word_char', p, {c for c in class_maps if c[0] in 'LN'}, 'L and N categories')
|
||||||
@@ -378,15 +403,19 @@ def gen_ucd() -> None:
|
|||||||
p('combining_type mark_for_codepoint(char_type c) {')
|
p('combining_type mark_for_codepoint(char_type c) {')
|
||||||
rmap = codepoint_to_mark_map(p, mark_map)
|
rmap = codepoint_to_mark_map(p, mark_map)
|
||||||
p('}\n')
|
p('}\n')
|
||||||
with open('kitty/unicode-data.h') as f:
|
with open('kitty/unicode-data.h', 'r+') as f:
|
||||||
unicode_data = f.read()
|
raw = f.read()
|
||||||
m = re.search(r'^#define VS15 (\d+)', unicode_data, re.M)
|
f.seek(0)
|
||||||
if m is not None:
|
raw, num = re.subn(
|
||||||
expected = int(m.group(1))
|
r'^// START_KNOWN_MARKS.+?^// END_KNOWN_MARKS',
|
||||||
if rmap[0xfe0e] != expected:
|
'// START_KNOWN_MARKS\nstatic const combining_type '
|
||||||
raise ValueError('The mark for 0xfe0e has changed, you have to update VS15 to {} and VS16 to {} in unicode-data.h'.format(
|
f'VS15 = {rmap[0xfe0e]}, VS16 = {rmap[0xfe0f]};'
|
||||||
rmap[0xfe0e], rmap[0xfe0f]
|
'\n// END_KNOWN_MARKS', raw, flags=re.MULTILINE | re.DOTALL)
|
||||||
))
|
if not num:
|
||||||
|
raise SystemExit('Faile dto patch mark definitions in unicode-data.h')
|
||||||
|
f.truncate()
|
||||||
|
f.write(raw)
|
||||||
|
|
||||||
with open('kittens/hints/url_regex.py', 'w') as f:
|
with open('kittens/hints/url_regex.py', 'w') as f:
|
||||||
f.write('# generated by gen-wcwidth.py, do not edit\n\n')
|
f.write('# generated by gen-wcwidth.py, do not edit\n\n')
|
||||||
f.write("url_delimiters = '{}' # noqa".format(''.join(classes_to_regex(cz, exclude='\n\r'))))
|
f.write("url_delimiters = '{}' # noqa".format(''.join(classes_to_regex(cz, exclude='\n\r'))))
|
||||||
@@ -496,7 +525,7 @@ def gen_names() -> None:
|
|||||||
def gen_wcwidth() -> None:
|
def gen_wcwidth() -> None:
|
||||||
seen: Set[int] = set()
|
seen: Set[int] = set()
|
||||||
|
|
||||||
def add(p: Callable, comment: str, chars_: Union[Set[int], FrozenSet[int]], ret: int) -> None:
|
def add(p: Callable[..., None], comment: str, chars_: Union[Set[int], FrozenSet[int]], ret: int) -> None:
|
||||||
chars = chars_ - seen
|
chars = chars_ - seen
|
||||||
seen.update(chars)
|
seen.update(chars)
|
||||||
p(f'\t\t// {comment} ({len(chars)} codepoints)' + ' {{' '{')
|
p(f'\t\t// {comment} ({len(chars)} codepoints)' + ' {{' '{')
|
||||||
@@ -537,6 +566,7 @@ def gen_wcwidth() -> None:
|
|||||||
|
|
||||||
|
|
||||||
parse_ucd()
|
parse_ucd()
|
||||||
|
parse_prop_list()
|
||||||
parse_emoji()
|
parse_emoji()
|
||||||
parse_eaw()
|
parse_eaw()
|
||||||
gen_ucd()
|
gen_ucd()
|
||||||
|
|||||||
6
glfw/backend_utils.c
vendored
@@ -91,7 +91,7 @@ compare_timers(const void *a_, const void *b_) {
|
|||||||
return (a->trigger_at > b->trigger_at) ? 1 : (a->trigger_at < b->trigger_at) ? -1 : 0;
|
return (a->trigger_at > b->trigger_at) ? 1 : (a->trigger_at < b->trigger_at) ? -1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static void
|
||||||
update_timers(EventLoopData *eld) {
|
update_timers(EventLoopData *eld) {
|
||||||
if (eld->timers_count > 1) qsort(eld->timers, eld->timers_count, sizeof(eld->timers[0]), compare_timers);
|
if (eld->timers_count > 1) qsort(eld->timers, eld->timers_count, sizeof(eld->timers[0]), compare_timers);
|
||||||
}
|
}
|
||||||
@@ -164,7 +164,7 @@ prepareForPoll(EventLoopData *eld, monotonic_t timeout) {
|
|||||||
return timeout;
|
return timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct timespec
|
static struct timespec
|
||||||
calc_time(monotonic_t nsec) {
|
calc_time(monotonic_t nsec) {
|
||||||
struct timespec result;
|
struct timespec result;
|
||||||
result.tv_sec = nsec / (1000LL * 1000LL * 1000LL);
|
result.tv_sec = nsec / (1000LL * 1000LL * 1000LL);
|
||||||
@@ -271,7 +271,7 @@ wakeupEventLoop(EventLoopData *eld) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef HAS_EVENT_FD
|
#ifndef HAS_EVENT_FD
|
||||||
static inline void
|
static void
|
||||||
closeFds(int *fds, size_t count) {
|
closeFds(int *fds, size_t count) {
|
||||||
while(count--) {
|
while(count--) {
|
||||||
if (*fds > 0) {
|
if (*fds > 0) {
|
||||||
|
|||||||
@@ -264,6 +264,8 @@ display_reconfigured(CGDirectDisplayID display UNUSED, CGDisplayChangeSummaryFla
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static NSDictionary<NSString*,NSNumber*> *global_shortcuts = nil;
|
||||||
|
|
||||||
@interface GLFWHelper : NSObject
|
@interface GLFWHelper : NSObject
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@@ -280,6 +282,16 @@ display_reconfigured(CGDirectDisplayID display UNUSED, CGDisplayChangeSummaryFla
|
|||||||
(void)object;
|
(void)object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// watch for settings change and rebuild global_shortcuts using key/value observing on NSUserDefaults
|
||||||
|
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
|
||||||
|
{
|
||||||
|
(void)keyPath; (void)object; (void)change; (void)context;
|
||||||
|
if (global_shortcuts != nil) {
|
||||||
|
[global_shortcuts release];
|
||||||
|
global_shortcuts = nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@end // GLFWHelper
|
@end // GLFWHelper
|
||||||
|
|
||||||
// Delegate for application related notifications {{{
|
// Delegate for application related notifications {{{
|
||||||
@@ -346,32 +358,49 @@ static GLFWapplicationwillfinishlaunchingfun finish_launching_callback = NULL;
|
|||||||
finish_launching_callback();
|
finish_launching_callback();
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename {
|
- (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename {
|
||||||
(void)theApplication;
|
(void)sender;
|
||||||
if (!filename || !_glfw.ns.file_open_callback) return NO;
|
if (!filename || !_glfw.ns.url_open_callback) return NO;
|
||||||
const char *path = NULL;
|
const char *url = NULL;
|
||||||
@try {
|
@try {
|
||||||
path = [[NSFileManager defaultManager] fileSystemRepresentationWithPath: filename];
|
url = [[[NSURL fileURLWithPath:filename] absoluteString] UTF8String];
|
||||||
} @catch(NSException *exc) {
|
} @catch(NSException *exc) {
|
||||||
NSLog(@"Converting openFile filename: %@ failed with error: %@", filename, exc.reason);
|
NSLog(@"Converting openFile filename: %@ failed with error: %@", filename, exc.reason);
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
if (!path) return NO;
|
if (!url) return NO;
|
||||||
return _glfw.ns.file_open_callback(path);
|
return _glfw.ns.url_open_callback(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)application:(NSApplication *)sender openFiles:(NSArray *)filenames {
|
- (void)application:(NSApplication *)sender openFiles:(NSArray *)filenames {
|
||||||
(void)sender;
|
(void)sender;
|
||||||
if (!_glfw.ns.file_open_callback || !filenames) return;
|
if (!_glfw.ns.url_open_callback || !filenames) return;
|
||||||
for (id x in filenames) {
|
for (id x in filenames) {
|
||||||
NSString *filename = x;
|
NSString *filename = x;
|
||||||
const char *path = NULL;
|
const char *url = NULL;
|
||||||
@try {
|
@try {
|
||||||
path = [[NSFileManager defaultManager] fileSystemRepresentationWithPath: filename];
|
url = [[[NSURL fileURLWithPath:filename] absoluteString] UTF8String];
|
||||||
} @catch(NSException *exc) {
|
} @catch(NSException *exc) {
|
||||||
NSLog(@"Converting openFiles filename: %@ failed with error: %@", filename, exc.reason);
|
NSLog(@"Converting openFiles filename: %@ failed with error: %@", filename, exc.reason);
|
||||||
}
|
}
|
||||||
if (path) _glfw.ns.file_open_callback(path);
|
if (url) _glfw.ns.url_open_callback(url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove openFile and openFiles when the minimum supported macOS version is 10.13
|
||||||
|
- (void)application:(NSApplication *)sender openURLs:(NSArray<NSURL *> *)urls
|
||||||
|
{
|
||||||
|
(void)sender;
|
||||||
|
if (!_glfw.ns.url_open_callback || !urls) return;
|
||||||
|
for (id x in urls) {
|
||||||
|
NSURL *ns_url = x;
|
||||||
|
const char *url = NULL;
|
||||||
|
@try {
|
||||||
|
url = [[ns_url absoluteString] UTF8String];
|
||||||
|
} @catch(NSException *exc) {
|
||||||
|
NSLog(@"Converting openURLs url: %@ failed with error: %@", ns_url, exc.reason);
|
||||||
|
}
|
||||||
|
if (url) _glfw.ns.url_open_callback(url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -379,7 +408,6 @@ static GLFWapplicationwillfinishlaunchingfun finish_launching_callback = NULL;
|
|||||||
{
|
{
|
||||||
(void)notification;
|
(void)notification;
|
||||||
[NSApp stop:nil];
|
[NSApp stop:nil];
|
||||||
if (_glfw.ns.file_open_callback) _glfw.ns.file_open_callback(":cocoa::application launched::");
|
|
||||||
|
|
||||||
CGDisplayRegisterReconfigurationCallback(display_reconfigured, NULL);
|
CGDisplayRegisterReconfigurationCallback(display_reconfigured, NULL);
|
||||||
_glfwCocoaPostEmptyEvent();
|
_glfwCocoaPostEmptyEvent();
|
||||||
@@ -453,22 +481,298 @@ void* _glfwLoadLocalVulkanLoaderNS(void)
|
|||||||
////// GLFW platform API //////
|
////// GLFW platform API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
static inline bool
|
/**
|
||||||
is_ctrl_tab(NSEvent *event, NSEventModifierFlags modifierFlags) {
|
* Apple Symbolic HotKeys Ids
|
||||||
if (
|
* To find this symbolic hot keys indices do:
|
||||||
(modifierFlags == NSEventModifierFlagControl &&
|
* 1. open Terminal
|
||||||
[event.charactersIgnoringModifiers isEqualToString:@"\t"]) ||
|
* 2. restore defaults in System Preferences > Keyboard > Shortcuts
|
||||||
(modifierFlags == (NSEventModifierFlagControl | NSEventModifierFlagShift) &&
|
* 3. defaults read com.apple.symbolichotkeys > current.txt
|
||||||
[event.charactersIgnoringModifiers isEqualToString:@"\x19"])
|
* 4. enable/disable given symbolic hot key in System Preferences > Keyboard > Shortcuts
|
||||||
) return true;
|
* 5. defaults read com.apple.symbolichotkeys | diff -C 5 current.txt -
|
||||||
return false;
|
* 6. restore defaults in System Preferences > Keyboard > Shortcuts
|
||||||
|
*/
|
||||||
|
typedef enum AppleShortcutNames {
|
||||||
|
// launchpad & dock
|
||||||
|
kSHKTurnDockHidingOnOrOff = 52, // Opt, Cmd, D
|
||||||
|
kSHKShowLaunchpad = 160, //
|
||||||
|
|
||||||
|
// display
|
||||||
|
kSHKDecreaseDisplayBrightness1 = 53, // F14 (Fn)
|
||||||
|
kSHKDecreaseDisplayBrightness2 = 55, // F14 (Fn, Ctrl)
|
||||||
|
kSHKIncreaseDisplayBrightness1 = 54, // F15 (Fn)
|
||||||
|
kSHKIncreaseDisplayBrightness2 = 56, // F15 (Fn, Ctrl)
|
||||||
|
|
||||||
|
// mission control
|
||||||
|
kSHKMissionControl = 32, // Ctrl, Arrow Up
|
||||||
|
kSHKShowNotificationCenter = 163, //
|
||||||
|
kSHKTurnDoNotDisturbOnOrOff = 175, //
|
||||||
|
kSHKApplicationWindows = 33, // Ctrl, Arrow Down
|
||||||
|
kSHKShowDesktop = 36, // F11
|
||||||
|
kSHKMoveLeftASpace = 79, // Ctrl, Arrow Left
|
||||||
|
kSHKMoveRightASpace = 81, // Ctrl, Arrow Right
|
||||||
|
kSHKSwitchToDesktop1 = 118, // Ctrl, 1
|
||||||
|
kSHKSwitchToDesktop2 = 119, // Ctrl, 2
|
||||||
|
kSHKSwitchToDesktop3 = 120, // Ctrl, 3
|
||||||
|
kSHKSwitchToDesktop4 = 121, // Ctrl, 4
|
||||||
|
kSHKQuickNote = 190, // Fn, Q
|
||||||
|
|
||||||
|
// keyboard
|
||||||
|
kSHKChangeTheWayTabMovesFocus = 13, // Ctrl, F7
|
||||||
|
kSHKTurnKeyboardAccessOnOrOff = 12, // Ctrl, F1
|
||||||
|
kSHKMoveFocusToTheMenuBar = 7, // Ctrl, F2
|
||||||
|
kSHKMoveFocusToTheDock = 8, // Ctrl, F3
|
||||||
|
kSHKMoveFocusToActiveOrNextWindow = 9, // Ctrl, F4
|
||||||
|
kSHKMoveFocusToTheWindowToolbar = 10, // Ctrl, F5
|
||||||
|
kSHKMoveFocusToTheFloatingWindow = 11, // Ctrl, F6
|
||||||
|
kSHKMoveFocusToNextWindow = 27, // Cmd, `
|
||||||
|
kSHKMoveFocusToStatusMenus = 57, // Ctrl, F8
|
||||||
|
|
||||||
|
// input sources
|
||||||
|
kSHKSelectThePreviousInputSource = 60, // Ctrl, Space bar
|
||||||
|
kSHKSelectNextSourceInInputMenu = 61, // Ctrl, Opt, Space bar
|
||||||
|
|
||||||
|
// screenshots
|
||||||
|
kSHKSavePictureOfScreenAsAFile = 28, // Shift, Cmd, 3
|
||||||
|
kSHKCopyPictureOfScreenToTheClipboard = 29, // Ctrl, Shift, Cmd, 3
|
||||||
|
kSHKSavePictureOfSelectedAreaAsAFile = 30, // Shift, Cmd, 4
|
||||||
|
kSHKCopyPictureOfSelectedAreaToTheClipboard = 31, // Ctrl, Shift, Cmd, 4
|
||||||
|
kSHKScreenshotAndRecordingOptions = 184, // Shift, Cmd, 5
|
||||||
|
|
||||||
|
// spotlight
|
||||||
|
kSHKShowSpotlightSearch = 64, // Cmd, Space bar
|
||||||
|
kSHKShowFinderSearchWindow = 65, // Opt, Cmd, Space bar
|
||||||
|
|
||||||
|
// accessibility
|
||||||
|
kSHKTurnZoomOnOrOff = 15, // Opt, Cmd, 8
|
||||||
|
kSHKTurnImageSmoothingOnOrOff = 23, // Opt, Cmd, Backslash "\"
|
||||||
|
kSHKZoomOut = 19, // Opt, Cmd, -
|
||||||
|
kSHKZoomIn = 17, // Opt, Cmd, =
|
||||||
|
kSHKTurnFocusFollowingOnOrOff = 179, //
|
||||||
|
|
||||||
|
kSHKIncreaseContrast = 25, // Ctrl, Opt, Cmd, .
|
||||||
|
kSHKDecreaseContrast = 26, // Ctrl, Opt, Cmd, ,
|
||||||
|
|
||||||
|
kSHKInvertColors = 21, // Ctrl, Opt, Cmd, 8
|
||||||
|
kSHKTurnVoiceOverOnOrOff = 59, // Cmd, F5
|
||||||
|
kSHKShowAccessibilityControls = 162, // Opt, Cmd, F5
|
||||||
|
|
||||||
|
// app shortcuts
|
||||||
|
kSHKShowHelpMenu = 98, // Shift, Cmd, /
|
||||||
|
|
||||||
|
// deprecated (Not shown on macOS Monterey)
|
||||||
|
kSHKMoveFocusToTheWindowDrawer = 51, // Opt, Cmd, `
|
||||||
|
kSHKShowDashboard = 62, // F12
|
||||||
|
kSHKLookUpInDictionary = 70, // Shift, Cmd, E
|
||||||
|
kSHKHideAndShowFrontRow = 73, // Cmd, Esc
|
||||||
|
kSHKActivateSpaces = 75, // F8
|
||||||
|
|
||||||
|
// unknown
|
||||||
|
kSHKUnknown = 0, //
|
||||||
|
} AppleShortcutNames;
|
||||||
|
|
||||||
|
static bool
|
||||||
|
is_shiftable_shortcut(int scv) {
|
||||||
|
return scv == kSHKMoveFocusToActiveOrNextWindow || scv == kSHKMoveFocusToNextWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool
|
#define USEFUL_MODS(x) (x & (NSEventModifierFlagShift | NSEventModifierFlagOption | NSEventModifierFlagCommand | NSEventModifierFlagControl))
|
||||||
is_cmd_period(NSEvent *event, NSEventModifierFlags modifierFlags) {
|
|
||||||
if (modifierFlags != NSEventModifierFlagCommand) return false;
|
static void
|
||||||
if ([event.charactersIgnoringModifiers isEqualToString:@"."]) return true;
|
build_global_shortcuts_lookup(void) {
|
||||||
return false;
|
// dump these in a terminal with: defaults read com.apple.symbolichotkeys
|
||||||
|
NSMutableDictionary<NSString*, NSNumber*> *temp = [NSMutableDictionary dictionaryWithCapacity:128]; // will be autoreleased
|
||||||
|
NSMutableSet<NSNumber*> *temp_configured = [NSMutableSet setWithCapacity:128]; // will be autoreleased
|
||||||
|
NSMutableSet<NSNumber*> *temp_missing_value = [NSMutableSet setWithCapacity:128]; // will be autoreleased
|
||||||
|
NSDictionary *apple_settings = [[NSUserDefaults standardUserDefaults] persistentDomainForName:@"com.apple.symbolichotkeys"];
|
||||||
|
if (apple_settings) {
|
||||||
|
NSDictionary<NSString*, id> *symbolic_hotkeys = [apple_settings objectForKey:@"AppleSymbolicHotKeys"];
|
||||||
|
if (symbolic_hotkeys) {
|
||||||
|
for (NSString *key in symbolic_hotkeys) {
|
||||||
|
id obj = symbolic_hotkeys[key];
|
||||||
|
if (![key isKindOfClass:[NSString class]] || ![obj isKindOfClass:[NSDictionary class]]) continue;
|
||||||
|
NSInteger sc = [key integerValue];
|
||||||
|
NSDictionary *sc_value = obj;
|
||||||
|
id enabled = [sc_value objectForKey:@"enabled"];
|
||||||
|
if (!enabled || ![enabled isKindOfClass:[NSNumber class]]) continue;
|
||||||
|
[temp_configured addObject:@(sc)];
|
||||||
|
if (![enabled boolValue]) continue;
|
||||||
|
id v = [sc_value objectForKey:@"value"];
|
||||||
|
if (!v || ![v isKindOfClass:[NSDictionary class]]) {
|
||||||
|
if ([enabled boolValue]) [temp_missing_value addObject:@(sc)];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
NSDictionary *value = v;
|
||||||
|
id t = [value objectForKey:@"type"];
|
||||||
|
if (!t || ![t isKindOfClass:[NSString class]] || ![t isEqualToString:@"standard"]) continue;
|
||||||
|
id p = [value objectForKey:@"parameters"];
|
||||||
|
if (!p || ![p isKindOfClass:[NSArray class]] || [(NSArray*)p count] < 2) continue;
|
||||||
|
NSArray<NSNumber*> *parameters = p;
|
||||||
|
NSInteger ch = [parameters[0] isKindOfClass:[NSNumber class]] ? [parameters[0] integerValue] : 0xffff;
|
||||||
|
NSInteger vk = [parameters[1] isKindOfClass:[NSNumber class]] ? [parameters[1] integerValue] : 0xffff;
|
||||||
|
NSEventModifierFlags mods = ([parameters count] > 2 && [parameters[2] isKindOfClass:[NSNumber class]]) ? [parameters[2] unsignedIntegerValue] : 0;
|
||||||
|
mods = USEFUL_MODS(mods);
|
||||||
|
static char buf[64];
|
||||||
|
#define S(x, k) snprintf(buf, sizeof(buf) - 1, #x":%lx:%ld", (unsigned long)mods, (long)k)
|
||||||
|
if (ch == 0xffff) { if (vk == 0xffff) continue; S(v, vk); } else S(c, ch);
|
||||||
|
temp[@(buf)] = @(sc);
|
||||||
|
// the move to next window shortcuts also respond to the same shortcut + shift
|
||||||
|
if (is_shiftable_shortcut([key intValue]) && !(mods & NSEventModifierFlagShift)) {
|
||||||
|
mods |= NSEventModifierFlagShift;
|
||||||
|
if (ch == 0xffff) S(v, vk); else S(c, ch);
|
||||||
|
temp[@(buf)] = @(sc);
|
||||||
|
}
|
||||||
|
#undef S
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add global shortcut definitions when the default enabled shortcut is not defined,
|
||||||
|
// or when the default enabled shortcut is not disabled and is missing a value.
|
||||||
|
// Here are the shortcuts that are enabled by default in the standard ANSI (US) layout.
|
||||||
|
// macOS provides separate configurations for some languages or keyboards.
|
||||||
|
// In general, the rules here will not take effect.
|
||||||
|
static char buf[64];
|
||||||
|
#define S(i, t, m, k) if ([temp_configured member:@(i)] == nil || [temp_missing_value member:@(i)] != nil) { \
|
||||||
|
snprintf(buf, sizeof(buf) - 1, #t":%lx:%ld", (unsigned long)m, (long)k); \
|
||||||
|
temp[@(buf)] = @(i); \
|
||||||
|
}
|
||||||
|
|
||||||
|
// launchpad & dock
|
||||||
|
S(kSHKTurnDockHidingOnOrOff, c, (NSEventModifierFlagOption | NSEventModifierFlagCommand), 'd'); // Opt, Cmd, D
|
||||||
|
// mission control
|
||||||
|
S(kSHKMissionControl, v, NSEventModifierFlagControl, 126); // Ctrl, Arrow Up
|
||||||
|
S(kSHKApplicationWindows, v, NSEventModifierFlagControl, 125); // Ctrl, Arrow Down
|
||||||
|
// keyboard
|
||||||
|
S(kSHKMoveFocusToTheMenuBar, v, NSEventModifierFlagControl, 120); // Ctrl, F2
|
||||||
|
S(kSHKMoveFocusToTheDock, v, NSEventModifierFlagControl, 99); // Ctrl, F3
|
||||||
|
S(kSHKMoveFocusToActiveOrNextWindow, v, NSEventModifierFlagControl, 118); // Ctrl, F4
|
||||||
|
S(kSHKMoveFocusToActiveOrNextWindow, v, (NSEventModifierFlagShift | NSEventModifierFlagControl), 118); // Shift, Ctrl, F4
|
||||||
|
S(kSHKMoveFocusToNextWindow, c, NSEventModifierFlagCommand, 96); // Cmd, `
|
||||||
|
S(kSHKMoveFocusToNextWindow, c, (NSEventModifierFlagShift | NSEventModifierFlagCommand), 96); // Shift, Cmd, `
|
||||||
|
S(kSHKMoveFocusToStatusMenus, v, NSEventModifierFlagControl, 100); // Ctrl, F8
|
||||||
|
// input sources
|
||||||
|
S(kSHKSelectThePreviousInputSource, c, NSEventModifierFlagControl, 32); // Ctrl, Space bar
|
||||||
|
S(kSHKSelectNextSourceInInputMenu, c, (NSEventModifierFlagControl | NSEventModifierFlagOption), 32); // Ctrl, Opt, Space bar
|
||||||
|
// spotlight
|
||||||
|
S(kSHKShowSpotlightSearch, c, NSEventModifierFlagCommand, 32); // Cmd, Space bar
|
||||||
|
S(kSHKShowFinderSearchWindow, c, (NSEventModifierFlagOption | NSEventModifierFlagCommand), 32); // Opt, Cmd, Space bar
|
||||||
|
|
||||||
|
#undef S
|
||||||
|
global_shortcuts = [[NSDictionary dictionaryWithDictionary:temp] retain];
|
||||||
|
/* NSLog(@"global_shortcuts: %@", global_shortcuts); */
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
is_active_apple_global_shortcut(NSEvent *event) {
|
||||||
|
if (global_shortcuts == nil) build_global_shortcuts_lookup();
|
||||||
|
NSEventModifierFlags modifierFlags = USEFUL_MODS([event modifierFlags]);
|
||||||
|
static char lookup_key[64];
|
||||||
|
#define LOOKUP(t, k) \
|
||||||
|
snprintf(lookup_key, sizeof(lookup_key) - 1, #t":%lx:%ld", (unsigned long)modifierFlags, (long)k); \
|
||||||
|
NSNumber *sc = global_shortcuts[@(lookup_key)]; \
|
||||||
|
if (sc != nil) return [sc intValue]; \
|
||||||
|
|
||||||
|
if ([event.charactersIgnoringModifiers length] == 1) {
|
||||||
|
if (modifierFlags & NSEventModifierFlagShift) {
|
||||||
|
const uint32_t ch_without_shift = vk_to_unicode_key_with_current_layout([event keyCode]);
|
||||||
|
if (ch_without_shift < GLFW_FKEY_FIRST || ch_without_shift > GLFW_FKEY_LAST) {
|
||||||
|
LOOKUP(c, ch_without_shift);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const unichar ch = [event.charactersIgnoringModifiers characterAtIndex:0];
|
||||||
|
LOOKUP(c, ch);
|
||||||
|
}
|
||||||
|
unsigned short vk = [event keyCode];
|
||||||
|
if (vk != 0xffff) {
|
||||||
|
LOOKUP(v, vk);
|
||||||
|
}
|
||||||
|
#undef LOOKUP
|
||||||
|
return kSHKUnknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
is_useful_apple_global_shortcut(int sc) {
|
||||||
|
switch(sc) {
|
||||||
|
// launchpad & dock
|
||||||
|
case kSHKTurnDockHidingOnOrOff: // Opt, Cmd, D
|
||||||
|
case kSHKShowLaunchpad: //
|
||||||
|
|
||||||
|
// display
|
||||||
|
case kSHKDecreaseDisplayBrightness1: // F14 (Fn)
|
||||||
|
case kSHKDecreaseDisplayBrightness2: // F14 (Fn, Ctrl)
|
||||||
|
case kSHKIncreaseDisplayBrightness1: // F15 (Fn)
|
||||||
|
case kSHKIncreaseDisplayBrightness2: // F14 (Fn, Ctrl)
|
||||||
|
|
||||||
|
// mission control
|
||||||
|
case kSHKMissionControl: // Ctrl, Arrow Up
|
||||||
|
case kSHKShowNotificationCenter: //
|
||||||
|
case kSHKTurnDoNotDisturbOnOrOff: //
|
||||||
|
case kSHKApplicationWindows: // Ctrl, Arrow Down
|
||||||
|
case kSHKShowDesktop: // F11
|
||||||
|
case kSHKMoveLeftASpace: // Ctrl, Arrow Left
|
||||||
|
case kSHKMoveRightASpace: // Ctrl, Arrow Right
|
||||||
|
case kSHKSwitchToDesktop1: // Ctrl, 1
|
||||||
|
case kSHKSwitchToDesktop2: // Ctrl, 2
|
||||||
|
case kSHKSwitchToDesktop3: // Ctrl, 3
|
||||||
|
case kSHKSwitchToDesktop4: // Ctrl, 4
|
||||||
|
case kSHKQuickNote: // Fn, Q
|
||||||
|
|
||||||
|
// keyboard
|
||||||
|
/* case kSHKChangeTheWayTabMovesFocus: // Ctrl, F7 */
|
||||||
|
/* case kSHKTurnKeyboardAccessOnOrOff: // Ctrl, F1 */
|
||||||
|
case kSHKMoveFocusToTheMenuBar: // Ctrl, F2
|
||||||
|
case kSHKMoveFocusToTheDock: // Ctrl, F3
|
||||||
|
case kSHKMoveFocusToActiveOrNextWindow: // Ctrl, F4
|
||||||
|
/* case kSHKMoveFocusToTheWindowToolbar: // Ctrl, F5 */
|
||||||
|
/* case kSHKMoveFocusToTheFloatingWindow: // Ctrl, F6 */
|
||||||
|
case kSHKMoveFocusToNextWindow: // Cmd, `
|
||||||
|
case kSHKMoveFocusToStatusMenus: // Ctrl, F8
|
||||||
|
|
||||||
|
// input sources
|
||||||
|
case kSHKSelectThePreviousInputSource: // Ctrl, Space bar
|
||||||
|
case kSHKSelectNextSourceInInputMenu: // Ctrl, Opt, Space bar
|
||||||
|
|
||||||
|
// screenshots
|
||||||
|
/* case kSHKSavePictureOfScreenAsAFile: // Shift, Cmd, 3 */
|
||||||
|
/* case kSHKCopyPictureOfScreenToTheClipboard: // Ctrl, Shift, Cmd, 3 */
|
||||||
|
/* case kSHKSavePictureOfSelectedAreaAsAFile: // Shift, Cmd, 4 */
|
||||||
|
/* case kSHKCopyPictureOfSelectedAreaToTheClipboard: // Ctrl, Shift, Cmd, 4 */
|
||||||
|
/* case kSHKScreenshotAndRecordingOptions: // Shift, Cmd, 5 */
|
||||||
|
|
||||||
|
// spotlight
|
||||||
|
case kSHKShowSpotlightSearch: // Cmd, Space bar
|
||||||
|
case kSHKShowFinderSearchWindow: // Opt, Cmd, Space bar
|
||||||
|
|
||||||
|
// accessibility
|
||||||
|
/* case kSHKTurnZoomOnOrOff: // Opt, Cmd, 8 */
|
||||||
|
/* case kSHKTurnImageSmoothingOnOrOff: // Opt, Cmd, Backslash "\" */
|
||||||
|
/* case kSHKZoomOut: // Opt, Cmd, - */
|
||||||
|
/* case kSHKZoomIn: // Opt, Cmd, = */
|
||||||
|
/* case kSHKTurnFocusFollowingOnOrOff: // */
|
||||||
|
/* case kSHKIncreaseContrast: // Ctrl, Opt, Cmd, . */
|
||||||
|
/* case kSHKDecreaseContrast: // Ctrl, Opt, Cmd, , */
|
||||||
|
/* case kSHKInvertColors: // Ctrl, Opt, Cmd, 8 */
|
||||||
|
/* case kSHKTurnVoiceOverOnOrOff: // Cmd, F5 */
|
||||||
|
/* case kSHKShowAccessibilityControls: // Opt, Cmd, F5 */
|
||||||
|
|
||||||
|
// app shortcuts
|
||||||
|
/* case kSHKShowHelpMenu: // Shift, Cmd, / */
|
||||||
|
|
||||||
|
// deprecated (Not shown on macOS Monterey)
|
||||||
|
/* case kSHKMoveFocusToTheWindowDrawer: // Opt, Cmd, ` */
|
||||||
|
/* case kSHKShowDashboard: // F12 */
|
||||||
|
/* case kSHKLookUpInDictionary: // Shift, Cmd, E */
|
||||||
|
/* case kSHKHideAndShowFrontRow: // Cmd, Esc */
|
||||||
|
/* case kSHKActivateSpaces: // F8 */
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
is_apple_jis_layout_function_key(NSEvent *event) {
|
||||||
|
return [event keyCode] == 0x66 /* kVK_JIS_Eisu */ || [event keyCode] == 0x68 /* kVK_JIS_Kana */;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI GLFWapplicationshouldhandlereopenfun glfwSetApplicationShouldHandleReopen(GLFWapplicationshouldhandlereopenfun callback) {
|
GLFWAPI GLFWapplicationshouldhandlereopenfun glfwSetApplicationShouldHandleReopen(GLFWapplicationshouldhandlereopenfun callback) {
|
||||||
@@ -507,33 +811,84 @@ int _glfwPlatformInit(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
[NSApp setDelegate:_glfw.ns.delegate];
|
[NSApp setDelegate:_glfw.ns.delegate];
|
||||||
|
static struct {
|
||||||
|
unsigned short virtual_key_code;
|
||||||
|
NSEventModifierFlags input_source_switch_modifiers;
|
||||||
|
NSTimeInterval timestamp;
|
||||||
|
} last_keydown_shortcut_event;
|
||||||
|
last_keydown_shortcut_event.virtual_key_code = 0xffff;
|
||||||
|
last_keydown_shortcut_event.input_source_switch_modifiers = 0;
|
||||||
|
|
||||||
NSEvent* (^keydown_block)(NSEvent*) = ^ NSEvent* (NSEvent* event)
|
NSEvent* (^keydown_block)(NSEvent*) = ^ NSEvent* (NSEvent* event)
|
||||||
{
|
{
|
||||||
NSEventModifierFlags modifierFlags = [event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask;
|
debug_key("---------------- key down -------------------\n");
|
||||||
if (is_ctrl_tab(event, modifierFlags) || is_cmd_period(event, modifierFlags)) {
|
debug_key("%s\n", [[event description] UTF8String]);
|
||||||
// Cocoa swallows Ctrl+Tab to cycle between views
|
if (!_glfw.ignoreOSKeyboardProcessing) {
|
||||||
[[NSApp keyWindow].contentView keyDown:event];
|
// first check if there is a global menu bar shortcut
|
||||||
|
if ([[NSApp mainMenu] performKeyEquivalent:event]) {
|
||||||
|
debug_key("keyDown triggerred global menu bar action ignoring\n");
|
||||||
|
last_keydown_shortcut_event.virtual_key_code = [event keyCode];
|
||||||
|
last_keydown_shortcut_event.input_source_switch_modifiers = 0;
|
||||||
|
last_keydown_shortcut_event.timestamp = [event timestamp];
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
// now check if there is a useful apple shortcut
|
||||||
|
int global_shortcut = is_active_apple_global_shortcut(event);
|
||||||
|
if (is_useful_apple_global_shortcut(global_shortcut)) {
|
||||||
|
debug_key("keyDown triggerred global macOS shortcut ignoring\n");
|
||||||
|
last_keydown_shortcut_event.virtual_key_code = [event keyCode];
|
||||||
|
// record the modifier keys if switching to the next input source
|
||||||
|
last_keydown_shortcut_event.input_source_switch_modifiers = (global_shortcut == kSHKSelectNextSourceInInputMenu) ? USEFUL_MODS([event modifierFlags]) : 0;
|
||||||
|
last_keydown_shortcut_event.timestamp = [event timestamp];
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
// check for JIS keyboard layout function keys
|
||||||
|
if (is_apple_jis_layout_function_key(event)) {
|
||||||
|
debug_key("keyDown triggerred JIS layout function key ignoring\n");
|
||||||
|
last_keydown_shortcut_event.virtual_key_code = [event keyCode];
|
||||||
|
last_keydown_shortcut_event.input_source_switch_modifiers = 0;
|
||||||
|
last_keydown_shortcut_event.timestamp = [event timestamp];
|
||||||
|
return event;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
last_keydown_shortcut_event.virtual_key_code = 0xffff;
|
||||||
return event;
|
NSWindow *kw = [NSApp keyWindow];
|
||||||
|
if (kw && kw.contentView) [kw.contentView keyDown:event];
|
||||||
|
else debug_key("keyDown ignored as no keyWindow present\n");
|
||||||
|
return nil;
|
||||||
};
|
};
|
||||||
|
|
||||||
NSEvent* (^keyup_block)(NSEvent*) = ^ NSEvent* (NSEvent* event)
|
NSEvent* (^keyup_block)(NSEvent*) = ^ NSEvent* (NSEvent* event)
|
||||||
{
|
{
|
||||||
NSEventModifierFlags modifierFlags = [event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask;
|
debug_key("----------------- key up --------------------\n");
|
||||||
if (modifierFlags & NSEventModifierFlagCommand) {
|
debug_key("%s\n", [[event description] UTF8String]);
|
||||||
// From http://cocoadev.com/index.pl?GameKeyboardHandlingAlmost
|
if (last_keydown_shortcut_event.virtual_key_code != 0xffff && last_keydown_shortcut_event.virtual_key_code == [event keyCode]) {
|
||||||
// This works around an AppKit bug, where key up events while holding
|
// ignore as the corresponding key down event triggered a menu bar or macOS shortcut
|
||||||
// down the command key don't get sent to the key window.
|
last_keydown_shortcut_event.virtual_key_code = 0xffff;
|
||||||
[[NSApp keyWindow] sendEvent:event];
|
debug_key("keyUp ignored as corresponds to previous keyDown that trigerred a shortcut\n");
|
||||||
}
|
return nil;
|
||||||
if (is_ctrl_tab(event, modifierFlags) || is_cmd_period(event, modifierFlags)) {
|
|
||||||
// Cocoa swallows Ctrl+Tab to cycle between views
|
|
||||||
[[NSApp keyWindow].contentView keyUp:event];
|
|
||||||
}
|
}
|
||||||
|
NSWindow *kw = [NSApp keyWindow];
|
||||||
|
if (kw && kw.contentView) [kw.contentView keyUp:event];
|
||||||
|
else debug_key("keyUp ignored as no keyWindow present\n");
|
||||||
|
return nil;
|
||||||
|
};
|
||||||
|
|
||||||
return event;
|
NSEvent* (^flags_changed_block)(NSEvent*) = ^ NSEvent* (NSEvent* event)
|
||||||
|
{
|
||||||
|
debug_key("-------------- flags changed -----------------\n");
|
||||||
|
debug_key("%s\n", [[event description] UTF8String]);
|
||||||
|
last_keydown_shortcut_event.virtual_key_code = 0xffff;
|
||||||
|
// switching to the next input source is only confirmed when all modifier keys are released
|
||||||
|
if (last_keydown_shortcut_event.input_source_switch_modifiers) {
|
||||||
|
if (!([event modifierFlags] & last_keydown_shortcut_event.input_source_switch_modifiers))
|
||||||
|
last_keydown_shortcut_event.input_source_switch_modifiers = 0;
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
NSWindow *kw = [NSApp keyWindow];
|
||||||
|
if (kw && kw.contentView) [kw.contentView flagsChanged:event];
|
||||||
|
else debug_key("flagsChanged ignored as no keyWindow present\n");
|
||||||
|
return nil;
|
||||||
};
|
};
|
||||||
|
|
||||||
_glfw.ns.keyUpMonitor =
|
_glfw.ns.keyUpMonitor =
|
||||||
@@ -542,6 +897,9 @@ int _glfwPlatformInit(void)
|
|||||||
_glfw.ns.keyDownMonitor =
|
_glfw.ns.keyDownMonitor =
|
||||||
[NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskKeyDown
|
[NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskKeyDown
|
||||||
handler:keydown_block];
|
handler:keydown_block];
|
||||||
|
_glfw.ns.flagsChangedMonitor =
|
||||||
|
[NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskFlagsChanged
|
||||||
|
handler:flags_changed_block];
|
||||||
|
|
||||||
if (_glfw.hints.init.ns.chdir)
|
if (_glfw.hints.init.ns.chdir)
|
||||||
changeToResourcesDirectory();
|
changeToResourcesDirectory();
|
||||||
@@ -554,6 +912,13 @@ int _glfwPlatformInit(void)
|
|||||||
};
|
};
|
||||||
[[NSUserDefaults standardUserDefaults] registerDefaults:defaults];
|
[[NSUserDefaults standardUserDefaults] registerDefaults:defaults];
|
||||||
|
|
||||||
|
NSUserDefaults *apple_settings = [[NSUserDefaults alloc] initWithSuiteName:@"com.apple.symbolichotkeys"];
|
||||||
|
[apple_settings addObserver:_glfw.ns.helper
|
||||||
|
forKeyPath:@"AppleSymbolicHotKeys"
|
||||||
|
options:NSKeyValueObservingOptionNew
|
||||||
|
context:NULL];
|
||||||
|
_glfw.ns.appleSettings = apple_settings;
|
||||||
|
|
||||||
[[NSNotificationCenter defaultCenter]
|
[[NSNotificationCenter defaultCenter]
|
||||||
addObserver:_glfw.ns.helper
|
addObserver:_glfw.ns.helper
|
||||||
selector:@selector(selectedKeyboardInputSourceChanged:)
|
selector:@selector(selectedKeyboardInputSourceChanged:)
|
||||||
@@ -609,6 +974,8 @@ void _glfwPlatformTerminate(void)
|
|||||||
object:nil];
|
object:nil];
|
||||||
[[NSNotificationCenter defaultCenter]
|
[[NSNotificationCenter defaultCenter]
|
||||||
removeObserver:_glfw.ns.helper];
|
removeObserver:_glfw.ns.helper];
|
||||||
|
if (_glfw.ns.appleSettings)
|
||||||
|
[_glfw.ns.appleSettings removeObserver:_glfw.ns.helper forKeyPath:@"AppleSymbolicHotKeys"];
|
||||||
[_glfw.ns.helper release];
|
[_glfw.ns.helper release];
|
||||||
_glfw.ns.helper = nil;
|
_glfw.ns.helper = nil;
|
||||||
}
|
}
|
||||||
@@ -617,10 +984,18 @@ void _glfwPlatformTerminate(void)
|
|||||||
[NSEvent removeMonitor:_glfw.ns.keyUpMonitor];
|
[NSEvent removeMonitor:_glfw.ns.keyUpMonitor];
|
||||||
if (_glfw.ns.keyDownMonitor)
|
if (_glfw.ns.keyDownMonitor)
|
||||||
[NSEvent removeMonitor:_glfw.ns.keyDownMonitor];
|
[NSEvent removeMonitor:_glfw.ns.keyDownMonitor];
|
||||||
|
if (_glfw.ns.flagsChangedMonitor)
|
||||||
|
[NSEvent removeMonitor:_glfw.ns.flagsChangedMonitor];
|
||||||
|
|
||||||
|
if (_glfw.ns.appleSettings != nil) {
|
||||||
|
[_glfw.ns.appleSettings release];
|
||||||
|
_glfw.ns.appleSettings = nil;
|
||||||
|
}
|
||||||
|
|
||||||
free(_glfw.ns.clipboardString);
|
free(_glfw.ns.clipboardString);
|
||||||
|
|
||||||
_glfwTerminateNSGL();
|
_glfwTerminateNSGL();
|
||||||
|
if (global_shortcuts != nil) { [global_shortcuts release]; global_shortcuts = nil; }
|
||||||
|
|
||||||
} // autoreleasepool
|
} // autoreleasepool
|
||||||
}
|
}
|
||||||
@@ -703,7 +1078,7 @@ typedef struct {
|
|||||||
static Timer timers[128] = {{0}};
|
static Timer timers[128] = {{0}};
|
||||||
static size_t num_timers = 0;
|
static size_t num_timers = 0;
|
||||||
|
|
||||||
static inline void
|
static void
|
||||||
remove_timer_at(size_t idx) {
|
remove_timer_at(size_t idx) {
|
||||||
if (idx < num_timers) {
|
if (idx < num_timers) {
|
||||||
Timer *t = timers + idx;
|
Timer *t = timers + idx;
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ getDisplayName(CGDirectDisplayID displayID, NSScreen* screen)
|
|||||||
io_service_t service;
|
io_service_t service;
|
||||||
CFDictionaryRef info;
|
CFDictionaryRef info;
|
||||||
|
|
||||||
if (IOServiceGetMatchingServices(kIOMainPortDefault,
|
if (IOServiceGetMatchingServices(0,
|
||||||
IOServiceMatching("IODisplayConnect"),
|
IOServiceMatching("IODisplayConnect"),
|
||||||
&it) != 0)
|
&it) != 0)
|
||||||
{
|
{
|
||||||
@@ -259,7 +259,7 @@ static double getFallbackRefreshRate(CGDirectDisplayID displayID)
|
|||||||
io_iterator_t it;
|
io_iterator_t it;
|
||||||
io_service_t service;
|
io_service_t service;
|
||||||
|
|
||||||
if (IOServiceGetMatchingServices(kIOMainPortDefault,
|
if (IOServiceGetMatchingServices(0,
|
||||||
IOServiceMatching("IOFramebuffer"),
|
IOServiceMatching("IOFramebuffer"),
|
||||||
&it) != 0)
|
&it) != 0)
|
||||||
{
|
{
|
||||||
|
|||||||
19
glfw/cocoa_platform.h
vendored
@@ -39,9 +39,6 @@ typedef void* CVDisplayLinkRef;
|
|||||||
// NOTE: Many Cocoa enum values have been renamed and we need to build across
|
// NOTE: Many Cocoa enum values have been renamed and we need to build across
|
||||||
// SDK versions where one is unavailable or the other deprecated
|
// SDK versions where one is unavailable or the other deprecated
|
||||||
// We use the newer names in code and these macros to handle compatibility
|
// We use the newer names in code and these macros to handle compatibility
|
||||||
#if (MAC_OS_X_VERSION_MAX_ALLOWED < 120000) // Before macOS 12 Monterey
|
|
||||||
#define kIOMainPortDefault kIOMasterPortDefault
|
|
||||||
#endif
|
|
||||||
#if MAC_OS_X_VERSION_MAX_ALLOWED < 101200
|
#if MAC_OS_X_VERSION_MAX_ALLOWED < 101200
|
||||||
#define NSBitmapFormatAlphaNonpremultiplied NSAlphaNonpremultipliedBitmapFormat
|
#define NSBitmapFormatAlphaNonpremultiplied NSAlphaNonpremultipliedBitmapFormat
|
||||||
#define NSEventMaskAny NSAnyEventMask
|
#define NSEventMaskAny NSAnyEventMask
|
||||||
@@ -67,10 +64,11 @@ typedef void* CVDisplayLinkRef;
|
|||||||
#define NSOpenGLContextParameterSurfaceOpacity NSOpenGLCPSurfaceOpacity
|
#define NSOpenGLContextParameterSurfaceOpacity NSOpenGLCPSurfaceOpacity
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define debug_key(...) if (_glfw.hints.init.debugKeyboard) { fprintf(stderr, __VA_ARGS__); fflush(stderr); }
|
||||||
|
|
||||||
typedef int (* GLFWcocoatextinputfilterfun)(int,int,unsigned int, unsigned long);
|
typedef int (* GLFWcocoatextinputfilterfun)(int,int,unsigned int, unsigned long);
|
||||||
typedef bool (* GLFWapplicationshouldhandlereopenfun)(int);
|
typedef bool (* GLFWapplicationshouldhandlereopenfun)(int);
|
||||||
typedef bool (* GLFWhandlefileopen)(const char*);
|
typedef bool (* GLFWhandleurlopen)(const char*);
|
||||||
typedef void (* GLFWapplicationwillfinishlaunchingfun)(void);
|
typedef void (* GLFWapplicationwillfinishlaunchingfun)(void);
|
||||||
typedef bool (* GLFWcocoatogglefullscreenfun)(GLFWwindow*);
|
typedef bool (* GLFWcocoatogglefullscreenfun)(GLFWwindow*);
|
||||||
typedef void (* GLFWcocoarenderframefun)(GLFWwindow*);
|
typedef void (* GLFWcocoarenderframefun)(GLFWwindow*);
|
||||||
@@ -133,6 +131,7 @@ typedef struct _GLFWwindowNS
|
|||||||
bool maximized;
|
bool maximized;
|
||||||
bool retina;
|
bool retina;
|
||||||
bool in_traditional_fullscreen;
|
bool in_traditional_fullscreen;
|
||||||
|
bool in_fullscreen_transition;
|
||||||
bool titlebar_hidden;
|
bool titlebar_hidden;
|
||||||
unsigned long pre_full_screen_style_mask;
|
unsigned long pre_full_screen_style_mask;
|
||||||
|
|
||||||
@@ -155,6 +154,8 @@ typedef struct _GLFWwindowNS
|
|||||||
// Whether a render frame has been requested for this window
|
// Whether a render frame has been requested for this window
|
||||||
bool renderFrameRequested;
|
bool renderFrameRequested;
|
||||||
GLFWcocoarenderframefun renderFrameCallback;
|
GLFWcocoarenderframefun renderFrameCallback;
|
||||||
|
// update cursor after switching desktops with Mission Control
|
||||||
|
bool delayed_cursor_update_requested;
|
||||||
} _GLFWwindowNS;
|
} _GLFWwindowNS;
|
||||||
|
|
||||||
typedef struct _GLFWDisplayLinkNS
|
typedef struct _GLFWDisplayLinkNS
|
||||||
@@ -176,8 +177,8 @@ typedef struct _GLFWlibraryNS
|
|||||||
IOHIDManagerRef hidManager;
|
IOHIDManagerRef hidManager;
|
||||||
id unicodeData;
|
id unicodeData;
|
||||||
id helper;
|
id helper;
|
||||||
id keyUpMonitor;
|
id keyUpMonitor, keyDownMonitor, flagsChangedMonitor;
|
||||||
id keyDownMonitor;
|
id appleSettings;
|
||||||
id nibObjects;
|
id nibObjects;
|
||||||
|
|
||||||
char keyName[64];
|
char keyName[64];
|
||||||
@@ -201,8 +202,8 @@ typedef struct _GLFWlibraryNS
|
|||||||
_GLFWDisplayLinkNS entries[256];
|
_GLFWDisplayLinkNS entries[256];
|
||||||
size_t count;
|
size_t count;
|
||||||
} displayLinks;
|
} displayLinks;
|
||||||
// the callback to handle file open events
|
// the callback to handle url open events
|
||||||
GLFWhandlefileopen file_open_callback;
|
GLFWhandleurlopen url_open_callback;
|
||||||
|
|
||||||
} _GLFWlibraryNS;
|
} _GLFWlibraryNS;
|
||||||
|
|
||||||
@@ -234,7 +235,6 @@ typedef struct _GLFWtimerNS
|
|||||||
|
|
||||||
} _GLFWtimerNS;
|
} _GLFWtimerNS;
|
||||||
|
|
||||||
|
|
||||||
void _glfwPollMonitorsNS(void);
|
void _glfwPollMonitorsNS(void);
|
||||||
void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired);
|
void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired);
|
||||||
void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor);
|
void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor);
|
||||||
@@ -251,3 +251,4 @@ void _glfwShutdownCVDisplayLink(unsigned long long, void*);
|
|||||||
void _glfwCocoaPostEmptyEvent(void);
|
void _glfwCocoaPostEmptyEvent(void);
|
||||||
void _glfw_create_cv_display_link(_GLFWDisplayLinkNS *entry);
|
void _glfw_create_cv_display_link(_GLFWDisplayLinkNS *entry);
|
||||||
_GLFWDisplayLinkNS* _glfw_create_display_link(CGDirectDisplayID);
|
_GLFWDisplayLinkNS* _glfw_create_display_link(CGDirectDisplayID);
|
||||||
|
uint32_t vk_to_unicode_key_with_current_layout(uint16_t keycode);
|
||||||
|
|||||||
9
glfw/context.c
vendored
@@ -396,15 +396,6 @@ bool _glfwRefreshContextAttribs(_GLFWwindow* window,
|
|||||||
window->context.release = GLFW_RELEASE_BEHAVIOR_FLUSH;
|
window->context.release = GLFW_RELEASE_BEHAVIOR_FLUSH;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clearing the front buffer to black to avoid garbage pixels left over from
|
|
||||||
// previous uses of our bit of VRAM
|
|
||||||
{
|
|
||||||
PFNGLCLEARPROC glClear = (PFNGLCLEARPROC)
|
|
||||||
window->context.getProcAddress("glClear");
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
|
||||||
window->context.swapBuffers(window);
|
|
||||||
}
|
|
||||||
|
|
||||||
glfwMakeContextCurrent((GLFWwindow*) previous);
|
glfwMakeContextCurrent((GLFWwindow*) previous);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
6
glfw/dbus_glfw.c
vendored
@@ -31,7 +31,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
static inline void
|
static void
|
||||||
report_error(DBusError *err, const char *fmt, ...) {
|
report_error(DBusError *err, const char *fmt, ...) {
|
||||||
static char buf[1024];
|
static char buf[1024];
|
||||||
va_list args;
|
va_list args;
|
||||||
@@ -64,7 +64,7 @@ on_dbus_watch_ready(int fd UNUSED, int events, void *data) {
|
|||||||
dbus_watch_handle(watch, flags);
|
dbus_watch_handle(watch, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static int
|
||||||
events_for_watch(DBusWatch *watch) {
|
events_for_watch(DBusWatch *watch) {
|
||||||
int events = 0;
|
int events = 0;
|
||||||
unsigned int flags = dbus_watch_get_flags(watch);
|
unsigned int flags = dbus_watch_get_flags(watch);
|
||||||
@@ -263,7 +263,7 @@ call_method_with_msg(DBusConnection *conn, DBusMessage *msg, int timeout, dbus_p
|
|||||||
|
|
||||||
static bool
|
static bool
|
||||||
call_method(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, int timeout, dbus_pending_callback callback, void *user_data, va_list ap) {
|
call_method(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, int timeout, dbus_pending_callback callback, void *user_data, va_list ap) {
|
||||||
if (!conn) return false;
|
if (!conn || !path) return false;
|
||||||
DBusMessage *msg = dbus_message_new_method_call(node, path, interface, method);
|
DBusMessage *msg = dbus_message_new_method_call(node, path, interface, method);
|
||||||
if (!msg) return false;
|
if (!msg) return false;
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
|
|||||||
4
glfw/egl_context.c
vendored
@@ -428,6 +428,8 @@ bool _glfwInitEGL(void)
|
|||||||
extensionSupportedEGL("EGL_KHR_get_all_proc_addresses");
|
extensionSupportedEGL("EGL_KHR_get_all_proc_addresses");
|
||||||
_glfw.egl.KHR_context_flush_control =
|
_glfw.egl.KHR_context_flush_control =
|
||||||
extensionSupportedEGL("EGL_KHR_context_flush_control");
|
extensionSupportedEGL("EGL_KHR_context_flush_control");
|
||||||
|
_glfw.egl.EXT_present_opaque =
|
||||||
|
extensionSupportedEGL("EGL_EXT_present_opaque");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -598,6 +600,8 @@ bool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||||||
if (_glfw.egl.KHR_gl_colorspace)
|
if (_glfw.egl.KHR_gl_colorspace)
|
||||||
setAttrib(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR);
|
setAttrib(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR);
|
||||||
}
|
}
|
||||||
|
if (_glfw.egl.EXT_present_opaque)
|
||||||
|
setAttrib(EGL_PRESENT_OPAQUE_EXT, !fbconfig->transparent);
|
||||||
|
|
||||||
setAttrib(EGL_NONE, EGL_NONE);
|
setAttrib(EGL_NONE, EGL_NONE);
|
||||||
|
|
||||||
|
|||||||
9
glfw/egl_context.h
vendored
@@ -160,11 +160,11 @@ typedef EGLSurface (EGLAPIENTRY * PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC)(EGLD
|
|||||||
//
|
//
|
||||||
typedef struct _GLFWcontextEGL
|
typedef struct _GLFWcontextEGL
|
||||||
{
|
{
|
||||||
EGLConfig config;
|
EGLConfig config;
|
||||||
EGLContext handle;
|
EGLContext handle;
|
||||||
EGLSurface surface;
|
EGLSurface surface;
|
||||||
|
|
||||||
void* client;
|
void* client;
|
||||||
|
|
||||||
} _GLFWcontextEGL;
|
} _GLFWcontextEGL;
|
||||||
|
|
||||||
@@ -186,6 +186,7 @@ typedef struct _GLFWlibraryEGL
|
|||||||
bool EXT_platform_base;
|
bool EXT_platform_base;
|
||||||
bool EXT_platform_x11;
|
bool EXT_platform_x11;
|
||||||
bool EXT_platform_wayland;
|
bool EXT_platform_wayland;
|
||||||
|
bool EXT_present_opaque;
|
||||||
bool ANGLE_platform_angle;
|
bool ANGLE_platform_angle;
|
||||||
bool ANGLE_platform_angle_opengl;
|
bool ANGLE_platform_angle_opengl;
|
||||||
bool ANGLE_platform_angle_d3d;
|
bool ANGLE_platform_angle_d3d;
|
||||||
|
|||||||
61
glfw/glfw.py
@@ -6,7 +6,7 @@ import json
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
from typing import Callable, Dict, List, Optional, Tuple
|
from typing import Callable, Dict, List, NamedTuple, Optional, Sequence, Tuple
|
||||||
|
|
||||||
_plat = sys.platform.lower()
|
_plat = sys.platform.lower()
|
||||||
is_linux = 'linux' in _plat
|
is_linux = 'linux' in _plat
|
||||||
@@ -14,9 +14,23 @@ is_openbsd = 'openbsd' in _plat
|
|||||||
base = os.path.dirname(os.path.abspath(__file__))
|
base = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
|
||||||
|
|
||||||
|
class CompileKey(NamedTuple):
|
||||||
|
src: str
|
||||||
|
dest: str
|
||||||
|
|
||||||
|
|
||||||
|
class Command(NamedTuple):
|
||||||
|
desc: str
|
||||||
|
cmd: Sequence[str]
|
||||||
|
is_newer_func: Callable[[], bool]
|
||||||
|
on_success: Callable[[], None] = lambda: None
|
||||||
|
key: Optional[CompileKey] = None
|
||||||
|
keyfile: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
class Env:
|
class Env:
|
||||||
|
|
||||||
cc: str = ''
|
cc: List[str] = []
|
||||||
cppflags: List[str] = []
|
cppflags: List[str] = []
|
||||||
cflags: List[str] = []
|
cflags: List[str] = []
|
||||||
ldflags: List[str] = []
|
ldflags: List[str] = []
|
||||||
@@ -33,11 +47,12 @@ class Env:
|
|||||||
wayland_protocols: Tuple[str, ...] = ()
|
wayland_protocols: Tuple[str, ...] = ()
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self, cc: str = '', cppflags: List[str] = [], cflags: List[str] = [], ldflags: List[str] = [],
|
self, cc: List[str] = [], cppflags: List[str] = [], cflags: List[str] = [], ldflags: List[str] = [],
|
||||||
library_paths: Dict[str, List[str]] = {}, ldpaths: Optional[List[str]] = None, ccver: Tuple[int, int] = (0, 0)
|
library_paths: Dict[str, List[str]] = {}, ldpaths: Optional[List[str]] = None, ccver: Tuple[int, int] = (0, 0)
|
||||||
):
|
):
|
||||||
self.cc, self.cppflags, self.cflags, self.ldflags, self.library_paths = cc, cppflags, cflags, ldflags, library_paths
|
self.cc, self.cppflags, self.cflags, self.ldflags, self.library_paths = cc, cppflags, cflags, ldflags, library_paths
|
||||||
self.ldpaths, self.ccver = [] if ldpaths is None else ldpaths, ccver
|
self.ldpaths = ldpaths or []
|
||||||
|
self.ccver = ccver
|
||||||
|
|
||||||
def copy(self) -> 'Env':
|
def copy(self) -> 'Env':
|
||||||
ans = Env(self.cc, list(self.cppflags), list(self.cflags), list(self.ldflags), dict(self.library_paths), list(self.ldpaths), self.ccver)
|
ans = Env(self.cc, list(self.cppflags), list(self.cflags), list(self.ldflags), dict(self.library_paths), list(self.ldpaths), self.ccver)
|
||||||
@@ -52,13 +67,20 @@ class Env:
|
|||||||
|
|
||||||
def wayland_protocol_file_name(base: str, ext: str = 'c') -> str:
|
def wayland_protocol_file_name(base: str, ext: str = 'c') -> str:
|
||||||
base = os.path.basename(base).rpartition('.')[0]
|
base = os.path.basename(base).rpartition('.')[0]
|
||||||
return 'wayland-{}-client-protocol.{}'.format(base, ext)
|
return f'wayland-{base}-client-protocol.{ext}'
|
||||||
|
|
||||||
|
|
||||||
def init_env(env: Env, pkg_config: Callable, pkg_version: Callable, at_least_version: Callable, test_compile: Callable, module: str = 'x11') -> Env:
|
def init_env(
|
||||||
|
env: Env,
|
||||||
|
pkg_config: Callable[..., List[str]],
|
||||||
|
pkg_version: Callable[[str], Tuple[int, int]],
|
||||||
|
at_least_version: Callable[..., None],
|
||||||
|
test_compile: Callable[..., bool],
|
||||||
|
module: str = 'x11'
|
||||||
|
) -> Env:
|
||||||
ans = env.copy()
|
ans = env.copy()
|
||||||
ans.cflags.append('-fPIC')
|
ans.cflags.append('-fPIC')
|
||||||
ans.cppflags.append('-D_GLFW_' + module.upper())
|
ans.cppflags.append(f'-D_GLFW_{module.upper()}')
|
||||||
ans.cppflags.append('-D_GLFW_BUILD_DLL')
|
ans.cppflags.append('-D_GLFW_BUILD_DLL')
|
||||||
|
|
||||||
with open(os.path.join(base, 'source-info.json')) as f:
|
with open(os.path.join(base, 'source-info.json')) as f:
|
||||||
@@ -89,7 +111,7 @@ def init_env(env: Env, pkg_config: Callable, pkg_version: Callable, at_least_ver
|
|||||||
|
|
||||||
elif module == 'cocoa':
|
elif module == 'cocoa':
|
||||||
ans.cppflags.append('-DGL_SILENCE_DEPRECATION')
|
ans.cppflags.append('-DGL_SILENCE_DEPRECATION')
|
||||||
for f_ in 'Cocoa Carbon IOKit CoreFoundation CoreVideo'.split():
|
for f_ in 'Cocoa IOKit CoreFoundation CoreVideo'.split():
|
||||||
ans.ldpaths.extend(('-framework', f_))
|
ans.ldpaths.extend(('-framework', f_))
|
||||||
|
|
||||||
elif module == 'wayland':
|
elif module == 'wayland':
|
||||||
@@ -117,21 +139,26 @@ def init_env(env: Env, pkg_config: Callable, pkg_version: Callable, at_least_ver
|
|||||||
return ans
|
return ans
|
||||||
|
|
||||||
|
|
||||||
def build_wayland_protocols(env: Env, Command: Callable, parallel_run: Callable, emphasis: Callable, newer: Callable, dest_dir: str) -> None:
|
def build_wayland_protocols(
|
||||||
|
env: Env,
|
||||||
|
parallel_run: Callable[[List[Command]], None],
|
||||||
|
emphasis: Callable[[str], str],
|
||||||
|
newer: Callable[..., bool],
|
||||||
|
dest_dir: str
|
||||||
|
) -> None:
|
||||||
items = []
|
items = []
|
||||||
for protocol in env.wayland_protocols:
|
for protocol in env.wayland_protocols:
|
||||||
src = os.path.join(env.wayland_packagedir, protocol)
|
src = os.path.join(env.wayland_packagedir, protocol)
|
||||||
if not os.path.exists(src):
|
if not os.path.exists(src):
|
||||||
raise SystemExit('The wayland-protocols package on your system is missing the {} protocol definition file'.format(protocol))
|
raise SystemExit(f'The wayland-protocols package on your system is missing the {protocol} protocol definition file')
|
||||||
for ext in 'hc':
|
for ext in 'hc':
|
||||||
dest = wayland_protocol_file_name(src, ext)
|
dest = wayland_protocol_file_name(src, ext)
|
||||||
dest = os.path.join(dest_dir, dest)
|
dest = os.path.join(dest_dir, dest)
|
||||||
if newer(dest, src):
|
if newer(dest, src):
|
||||||
q = 'client-header' if ext == 'h' else env.wayland_scanner_code
|
q = 'client-header' if ext == 'h' else env.wayland_scanner_code
|
||||||
items.append(Command(
|
items.append(Command(
|
||||||
'Generating {} ...'.format(emphasis(os.path.basename(dest))),
|
f'Generating {emphasis(os.path.basename(dest))} ...',
|
||||||
[env.wayland_scanner, q, src, dest],
|
[env.wayland_scanner, q, src, dest], lambda: True))
|
||||||
lambda: True, None, None, None))
|
|
||||||
if items:
|
if items:
|
||||||
parallel_run(items)
|
parallel_run(items)
|
||||||
|
|
||||||
@@ -147,7 +174,7 @@ class Arg:
|
|||||||
self.type = self.type + '*'
|
self.type = self.type + '*'
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return 'Arg({}, {})'.format(self.type, self.name)
|
return f'Arg({self.type}, {self.name})'
|
||||||
|
|
||||||
|
|
||||||
class Function:
|
class Function:
|
||||||
@@ -206,7 +233,7 @@ def generate_wrappers(glfw_header: str) -> None:
|
|||||||
void* glfwGetNSGLContext(GLFWwindow *window)
|
void* glfwGetNSGLContext(GLFWwindow *window)
|
||||||
uint32_t glfwGetCocoaMonitor(GLFWmonitor* monitor)
|
uint32_t glfwGetCocoaMonitor(GLFWmonitor* monitor)
|
||||||
GLFWcocoatextinputfilterfun glfwSetCocoaTextInputFilter(GLFWwindow* window, GLFWcocoatextinputfilterfun callback)
|
GLFWcocoatextinputfilterfun glfwSetCocoaTextInputFilter(GLFWwindow* window, GLFWcocoatextinputfilterfun callback)
|
||||||
GLFWhandlefileopen glfwSetCocoaFileOpenCallback(GLFWhandlefileopen callback)
|
GLFWhandleurlopen glfwSetCocoaURLOpenCallback(GLFWhandleurlopen callback)
|
||||||
GLFWcocoatogglefullscreenfun glfwSetCocoaToggleFullscreenIntercept(GLFWwindow *window, GLFWcocoatogglefullscreenfun callback)
|
GLFWcocoatogglefullscreenfun glfwSetCocoaToggleFullscreenIntercept(GLFWwindow *window, GLFWcocoatogglefullscreenfun callback)
|
||||||
GLFWapplicationshouldhandlereopenfun glfwSetApplicationShouldHandleReopen(GLFWapplicationshouldhandlereopenfun callback)
|
GLFWapplicationshouldhandlereopenfun glfwSetApplicationShouldHandleReopen(GLFWapplicationshouldhandlereopenfun callback)
|
||||||
GLFWapplicationwillfinishlaunchingfun glfwSetApplicationWillFinishLaunching(GLFWapplicationwillfinishlaunchingfun callback)
|
GLFWapplicationwillfinishlaunchingfun glfwSetApplicationWillFinishLaunching(GLFWapplicationwillfinishlaunchingfun callback)
|
||||||
@@ -250,7 +277,7 @@ const char *action_text, int32_t timeout, GLFWDBusnotificationcreatedfun callbac
|
|||||||
|
|
||||||
typedef int (* GLFWcocoatextinputfilterfun)(int,int,unsigned int,unsigned long);
|
typedef int (* GLFWcocoatextinputfilterfun)(int,int,unsigned int,unsigned long);
|
||||||
typedef bool (* GLFWapplicationshouldhandlereopenfun)(int);
|
typedef bool (* GLFWapplicationshouldhandlereopenfun)(int);
|
||||||
typedef bool (* GLFWhandlefileopen)(const char*);
|
typedef bool (* GLFWhandleurlopen)(const char*);
|
||||||
typedef void (* GLFWapplicationwillfinishlaunchingfun)(void);
|
typedef void (* GLFWapplicationwillfinishlaunchingfun)(void);
|
||||||
typedef bool (* GLFWcocoatogglefullscreenfun)(GLFWwindow*);
|
typedef bool (* GLFWcocoatogglefullscreenfun)(GLFWwindow*);
|
||||||
typedef void (* GLFWcocoarenderframefun)(GLFWwindow*);
|
typedef void (* GLFWcocoarenderframefun)(GLFWwindow*);
|
||||||
@@ -265,6 +292,8 @@ const char* load_glfw(const char* path);
|
|||||||
f.write(header)
|
f.write(header)
|
||||||
|
|
||||||
code = '''
|
code = '''
|
||||||
|
// generated by glfw.py DO NOT edit
|
||||||
|
|
||||||
#define GFW_EXTERN
|
#define GFW_EXTERN
|
||||||
#include "data-types.h"
|
#include "data-types.h"
|
||||||
#include "glfw-wrapper.h"
|
#include "glfw-wrapper.h"
|
||||||
|
|||||||
25
glfw/glfw3.h
vendored
@@ -512,6 +512,7 @@ typedef enum {
|
|||||||
* GLFW_LOCK_KEY_MODS input mode is set.
|
* GLFW_LOCK_KEY_MODS input mode is set.
|
||||||
*/
|
*/
|
||||||
#define GLFW_MOD_NUM_LOCK 0x0080
|
#define GLFW_MOD_NUM_LOCK 0x0080
|
||||||
|
#define GLFW_MOD_LAST GLFW_MOD_NUM_LOCK
|
||||||
#define GLFW_LOCK_MASK (GLFW_MOD_NUM_LOCK | GLFW_MOD_CAPS_LOCK)
|
#define GLFW_LOCK_MASK (GLFW_MOD_NUM_LOCK | GLFW_MOD_CAPS_LOCK)
|
||||||
|
|
||||||
/*! @} */
|
/*! @} */
|
||||||
@@ -1024,6 +1025,16 @@ typedef enum GLFWMouseButton {
|
|||||||
* [window hint](@ref GLFW_COCOA_GRAPHICS_SWITCHING_hint).
|
* [window hint](@ref GLFW_COCOA_GRAPHICS_SWITCHING_hint).
|
||||||
*/
|
*/
|
||||||
#define GLFW_COCOA_GRAPHICS_SWITCHING 0x00023003
|
#define GLFW_COCOA_GRAPHICS_SWITCHING 0x00023003
|
||||||
|
/*! @brief macOS specific
|
||||||
|
* [window hint](@ref GLFW_COCOA_COLOR_SPACE_hint).
|
||||||
|
*/
|
||||||
|
#define GLFW_COCOA_COLOR_SPACE 0x00023004
|
||||||
|
typedef enum {
|
||||||
|
DEFAULT_COLORSPACE = 0,
|
||||||
|
SRGB_COLORSPACE = 1,
|
||||||
|
DISPLAY_P3_COLORSPACE = 2,
|
||||||
|
} GlfwCocoaColorSpaces;
|
||||||
|
|
||||||
/*! @brief X11 specific
|
/*! @brief X11 specific
|
||||||
* [window hint](@ref GLFW_X11_CLASS_NAME_hint).
|
* [window hint](@ref GLFW_X11_CLASS_NAME_hint).
|
||||||
*/
|
*/
|
||||||
@@ -1206,7 +1217,8 @@ typedef enum {
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
GLFW_IME_NONE,
|
GLFW_IME_NONE,
|
||||||
GLFW_IME_PREEDIT_CHANGED,
|
GLFW_IME_PREEDIT_CHANGED,
|
||||||
GLFW_IME_COMMIT_TEXT
|
GLFW_IME_COMMIT_TEXT,
|
||||||
|
GLFW_IME_WAYLAND_DONE_EVENT,
|
||||||
} GLFWIMEState;
|
} GLFWIMEState;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -1245,6 +1257,10 @@ typedef struct GLFWkeyevent
|
|||||||
// A value of GLFW_IME_PREEDIT_CHANGED means the pre-edit text for the input event has been changed.
|
// A value of GLFW_IME_PREEDIT_CHANGED means the pre-edit text for the input event has been changed.
|
||||||
// A value of GLFW_IME_COMMIT_TEXT means the text should be committed.
|
// A value of GLFW_IME_COMMIT_TEXT means the text should be committed.
|
||||||
GLFWIMEState ime_state;
|
GLFWIMEState ime_state;
|
||||||
|
|
||||||
|
// For internal use only. On Linux it is the actual keycode reported by the windowing system, in contrast
|
||||||
|
// to native_key which can be the result of a compose operation. On macOS it is the same as native_key.
|
||||||
|
uint32_t native_key_id;
|
||||||
} GLFWkeyevent;
|
} GLFWkeyevent;
|
||||||
|
|
||||||
/*! @brief The function pointer type for error callbacks.
|
/*! @brief The function pointer type for error callbacks.
|
||||||
@@ -1701,6 +1717,7 @@ typedef void (* GLFWjoystickfun)(int,int);
|
|||||||
typedef void (* GLFWuserdatafun)(unsigned long long, void*);
|
typedef void (* GLFWuserdatafun)(unsigned long long, void*);
|
||||||
typedef void (* GLFWtickcallback)(void*);
|
typedef void (* GLFWtickcallback)(void*);
|
||||||
typedef bool (* GLFWdrawtextfun)(GLFWwindow *window, const char *text, uint32_t fg, uint32_t bg, uint8_t *output_buf, size_t width, size_t height, float x_offset, float y_offset, size_t right_margin);
|
typedef bool (* GLFWdrawtextfun)(GLFWwindow *window, const char *text, uint32_t fg, uint32_t bg, uint8_t *output_buf, size_t width, size_t height, float x_offset, float y_offset, size_t right_margin);
|
||||||
|
typedef char* (* GLFWcurrentselectionfun)(void);
|
||||||
|
|
||||||
/*! @brief Video mode type.
|
/*! @brief Video mode type.
|
||||||
*
|
*
|
||||||
@@ -1858,6 +1875,7 @@ GLFWAPI unsigned long long glfwAddTimer(monotonic_t interval, bool repeats, GLFW
|
|||||||
GLFWAPI void glfwUpdateTimer(unsigned long long timer_id, monotonic_t interval, bool enabled);
|
GLFWAPI void glfwUpdateTimer(unsigned long long timer_id, monotonic_t interval, bool enabled);
|
||||||
GLFWAPI void glfwRemoveTimer(unsigned long long);
|
GLFWAPI void glfwRemoveTimer(unsigned long long);
|
||||||
GLFWAPI GLFWdrawtextfun glfwSetDrawTextFunction(GLFWdrawtextfun function);
|
GLFWAPI GLFWdrawtextfun glfwSetDrawTextFunction(GLFWdrawtextfun function);
|
||||||
|
GLFWAPI GLFWcurrentselectionfun glfwSetCurrentSelectionCallback(GLFWcurrentselectionfun callback);
|
||||||
|
|
||||||
/*! @brief Terminates the GLFW library.
|
/*! @brief Terminates the GLFW library.
|
||||||
*
|
*
|
||||||
@@ -2752,6 +2770,8 @@ GLFWAPI void glfwWindowHintString(int hint, const char* value);
|
|||||||
*/
|
*/
|
||||||
GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, const char* title, GLFWmonitor* monitor, GLFWwindow* share);
|
GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, const char* title, GLFWmonitor* monitor, GLFWwindow* share);
|
||||||
GLFWAPI bool glfwToggleFullscreen(GLFWwindow *window, unsigned int flags);
|
GLFWAPI bool glfwToggleFullscreen(GLFWwindow *window, unsigned int flags);
|
||||||
|
GLFWAPI bool glfwIsFullscreen(GLFWwindow *window, unsigned int flags);
|
||||||
|
GLFWAPI bool glfwAreSwapsAllowed(const GLFWwindow* window);
|
||||||
|
|
||||||
/*! @brief Destroys the specified window and its context.
|
/*! @brief Destroys the specified window and its context.
|
||||||
*
|
*
|
||||||
@@ -4114,6 +4134,9 @@ GLFWAPI GLFWwindowcontentscalefun glfwSetWindowContentScaleCallback(GLFWwindow*
|
|||||||
*/
|
*/
|
||||||
GLFWAPI void glfwPostEmptyEvent(void);
|
GLFWAPI void glfwPostEmptyEvent(void);
|
||||||
|
|
||||||
|
GLFWAPI bool glfwGetIgnoreOSKeyboardProcessing(void);
|
||||||
|
GLFWAPI void glfwSetIgnoreOSKeyboardProcessing(bool enabled);
|
||||||
|
|
||||||
/*! @brief Returns the value of an input option for the specified window.
|
/*! @brief Returns the value of an input option for the specified window.
|
||||||
*
|
*
|
||||||
* This function returns the value of an input option for the specified window.
|
* This function returns the value of an input option for the specified window.
|
||||||
|
|||||||