mirror of https://github.com/jarun/nnn.git
Compare commits
1190 Commits
Author | SHA1 | Date |
---|---|---|
Arun Prakash Jana | 0f10bd6cdc | |
Arun | e27d059552 | |
NRK | 4f3662cf88 | |
Arun | 9e95578c22 | |
NRK | 78b9677abd | |
Arun Prakash Jana | 55137600e0 | |
Arun Prakash Jana | be6988d1c8 | |
Arun Prakash Jana | 191e77ec5d | |
Arun Prakash Jana | 46b5255814 | |
Arun | 2fb7490bf0 | |
Arun | d61c983dd0 | |
NRK | e60be2eaa2 | |
NRK | 72ee94ed6e | |
Oktay Imanzade | b20886a29c | |
Arun | ad04944bdf | |
François Bechet | 133c0d329b | |
Arun | 5853ac8e48 | |
Martin Ziemer | 28d993a8e8 | |
Arun | 22aa1455a6 | |
KlzXS | 7806d5d371 | |
Arun | 5456ba4582 | |
c79cea05 | 297b85492f | |
Arun Prakash Jana | f71b1309a9 | |
Arun | eb66598145 | |
KlzXS | 3d6777920a | |
Arun | 4a9587a5e6 | |
KlzXS | b392dd3723 | |
Arun | 0f62c6258a | |
João F. (BeyondMagic/koetemagie) | 2a442ec30c | |
Michel DHOOGE | 5b05c8b9b1 | |
90 | eb3888cb09 | |
Arun Prakash Jana | 94aeaccdbd | |
NRK | 0738f39cf0 | |
Antonio Mancera Gamez | e76d7bbf1d | |
Arun | f2a8648861 | |
Arun | 82f9e544f2 | |
me | 3d2caf861d | |
João F. (BeyondMagic/koetemagie) | eb775914af | |
Arun | 5595d93d29 | |
Arun | bb650eb9dd | |
me | ab718387c2 | |
Jeff Davis | 3849430ebc | |
Arun | f2a909dafd | |
Arun | 404eed5fc7 | |
me | 9aaf9491ad | |
Arun | 485079d3ec | |
me | bca441e00f | |
NRK | 60eabb6170 | |
NRK | 3665541dac | |
Arun | 744a7554ef | |
blissful | c0b3cc8689 | |
blissful | 703d349389 | |
Arun Prakash Jana | 9259170afd | |
Arun | 2f22afcacc | |
luukvbaal | 4009e211f3 | |
Luuk van Baal | 3160442f0c | |
Abhinav Lakhani | 9ff81ca1f9 | |
CronyAkatsuki | 8e8289373a | |
Arun | 1051d7213d | |
Luuk van Baal | f8f6d6a482 | |
Arun | 7f63bef4d6 | |
black | bfb46159a1 | |
Arun | f3397d5ea4 | |
NRK | 336ec8be5d | |
J-Kappes | afe84862ff | |
Arun | 3176eaa85c | |
NRK | 4d5e29c3dd | |
NRK | 6d6fc3419e | |
Arun Prakash Jana | 9b921761b6 | |
Arun | 09bf8fe469 | |
blissful | 3b3ad9ccc6 | |
Arun Prakash Jana | dd07aeb703 | |
Arun Prakash Jana | 9c7c7284c0 | |
Arun | ba439084c5 | |
Xerillic | 06d8da9052 | |
Arun | ed59aa2ac3 | |
umaranis | a06af824ee | |
Xerillic | 66447d52a7 | |
Syed Umar Anis | 547508aa78 | |
Arun Prakash Jana | d72ab3497a | |
Arun Prakash Jana | 2472554e9a | |
Arun Prakash Jana | 785dd3ddf1 | |
Arun Prakash Jana | 33126ee813 | |
Arun | d8c1c99e45 | |
Syed Umar Anis | b28f209c84 | |
Arun | 1ba85825c5 | |
Arun | 66f636de13 | |
Tadeas Uhlir | e500179188 | |
Quan Tong | d220c50773 | |
Arun Prakash Jana | 186f9d01ea | |
Arun Prakash Jana | 693ba757c0 | |
Arun Prakash Jana | 3539e5c1b1 | |
Arun | d65a095d9b | |
ANtlord | dedf0554e5 | |
Arun | b835cfcc2a | |
Anomalocaridid | 80bbf76b5b | |
Anomalocaridid | 5723023491 | |
Anomalocaridid | 280068c5da | |
Arun | 53e4fec75b | |
NRK | db8b61866b | |
Arun | 26d5b5c614 | |
Arun | 899fd5b4cf | |
JingMatrix | e6ce7a614e | |
NRK | 5e3ee08e64 | |
NRK | 4c2ce0a84d | |
Arun | 0dfc6881b4 | |
Luuk van Baal | 05990dc9e5 | |
Arun | fb6e7403cf | |
NRK | b2b830e69d | |
Arun | 4149a2619d | |
Aseem Athale | aed2725cb3 | |
Arun | 04d9f6738d | |
Arun | e013a867da | |
Arun | ed58e07a98 | |
NRK | 16899bda53 | |
Arun | 4c0305f11c | |
leo-arch | 4babedc3e4 | |
NRK | ddcf331205 | |
Delgan | bd4a4454fe | |
Arun | aaf60b93d7 | |
Arun | 145ea41490 | |
Arun | 29779acc57 | |
Delgan | a7262eb4ee | |
Jasper | fb3a648756 | |
UnleashedMarf | 9be3ee9abf | |
UnleashedMarf | d873eb393d | |
Arun Prakash Jana | efd5bc9db1 | |
Arun | 737ebaa9ef | |
J. Brock | 95183fbef8 | |
Arun | fe96bd6bc7 | |
Luuk van Baal | 20e944f5e5 | |
Arun Prakash Jana | 5d81aeb477 | |
Arun | 8fd1822ca6 | |
NRK | 20725b0b4d | |
Arun | 6a8d74a43a | |
Luuk van Baal | d3b5d0e49d | |
musjj | 432b0755d3 | |
Arun | 621dbba02e | |
spfanning | 63891578d7 | |
Arun Prakash Jana | 8a1dce888a | |
Arun Prakash Jana | 9319b638e7 | |
Arun Prakash Jana | 6dd8cf8b4d | |
Arun | 18b5371d08 | |
Kian-Meng Ang | 3d1bc6e8e5 | |
Arun | 79007074f7 | |
yosh | 98d3b2135d | |
Arun | a3759abd4e | |
NRK | 57882ffab7 | |
Arun Prakash Jana | c4678e3116 | |
Arun | 03ae86cca4 | |
Arun | 15e55f5e18 | |
Arun | 2af79c9ad2 | |
Henri Bourcereau | eaffd311d4 | |
NRK | 003228afba | |
birik | 8b8e3eb522 | |
Arun | 9656c809d2 | |
Henri Bourcereau | 69882b3bff | |
NRK | 3a30211e6c | |
Arun | 2a38132012 | |
NRK | 8dbd9da0cc | |
NRK | a59a91c312 | |
amalgame21 | 1dc4c96139 | |
Arun | 9503703517 | |
Luuk van Baal | 675e50c941 | |
Arun | a4745272db | |
Jacob Moena | 2dc7f19be0 | |
NRK | bc6a09475d | |
Arun Prakash Jana | b874da395c | |
Arun | b49cc28d80 | |
NRK | 8c23c3da4e | |
Arun | f1c85b977a | |
NRK | 4867fa2bc7 | |
NRK | 9cc4b66868 | |
NRK | 8ad5c87107 | |
Arun | 9357825b34 | |
Luuk van Baal | fc26493602 | |
Arun | ade477e705 | |
Luuk van Baal | 08d2ba0b5d | |
Arun Prakash Jana | bbfb16db42 | |
Arun | d7bfe38728 | |
Luuk van Baal | 80c07741e5 | |
Arun | 3739aab578 | |
Nizamuddin Sulieman | 70204a2d0f | |
Nizamuddin Sulieman | 1ad6d30a36 | |
Nizamuddin Sulieman | 0ac8b7aa54 | |
Arun Prakash Jana | 58b77411c8 | |
Arun | d0631707fc | |
Fernando Ramos | c4c720a59a | |
Arun | 326e76b9d0 | |
Luuk van Baal | 778d6617b1 | |
Arun Prakash Jana | 33827109d5 | |
Arun Prakash Jana | 4f95796ede | |
Arun Prakash Jana | b80e047d50 | |
Arun Prakash Jana | ad4ecb19cb | |
Arun Prakash Jana | 03e0531e81 | |
Arun | 786ecf9fc2 | |
Arun | 1a5a7da8eb | |
Arun | d4575e99c8 | |
NRK | ca8fcf454a | |
KlzXS | 867726d870 | |
KlzXS | 7abfb77a13 | |
KlzXS | 827e84a56f | |
KlzXS | 8d21e5e832 | |
Arun Prakash Jana | 6b94911bc9 | |
Arun Prakash Jana | 653cab9dff | |
Arun Prakash Jana | f9295780ef | |
Arun Prakash Jana | cac5b9ba33 | |
Arun Prakash Jana | df05f593de | |
Arun Prakash Jana | 243301603e | |
Arun | f9281c8eab | |
Arun | 428c652d36 | |
KlzXS | 8a1e32d9eb | |
KlzXS | 1a2f783b75 | |
KlzXS | 6c23fdfd5f | |
Arun | fef3c673cd | |
NRK | 1887cd1a77 | |
Arun | 12aedd521d | |
NRK | cf68675478 | |
Arun | 2b6fb3f388 | |
Léo Villeveygoux | dac5fb0af9 | |
Arun Prakash Jana | 789449a464 | |
Arun | fa62b08243 | |
Arun Prakash Jana | dd214c50f3 | |
NRK | fb5b2e5e64 | |
Raffaele Mancuso | c9b384f009 | |
N-R-K | 2000ed5080 | |
8B411 | a51437ff16 | |
Arun Prakash Jana | e236bd0b3a | |
Raffaele Mancuso | 1b5cfbca3d | |
Arun Prakash Jana | 1688b07d0e | |
Arun | 4d54490433 | |
KlzXS | 87627a6e08 | |
Arun Prakash Jana | 17ed380b57 | |
Arun Prakash Jana | 38d7090e64 | |
Arun Prakash Jana | 824e7a2c18 | |
Arun Prakash Jana | 2e84716e76 | |
Arun Prakash Jana | e8bc59a816 | |
Arun Prakash Jana | 32a6a63f44 | |
Arun Prakash Jana | cf46da60d9 | |
Arun Prakash Jana | 1a04e813be | |
Arun Prakash Jana | 02dec98bf8 | |
Arun Prakash Jana | 608fbb4ad7 | |
Arun Prakash Jana | d4c3e52f2f | |
Arun Prakash Jana | 93de728eab | |
Arun Prakash Jana | c9dbae0586 | |
Arun Prakash Jana | b6bfc740ce | |
Arun Prakash Jana | 28ea6e0f36 | |
Arun Prakash Jana | 2a673b4eb1 | |
Arun Prakash Jana | cd145b982d | |
Arun Prakash Jana | 92a0158f93 | |
Arun Prakash Jana | 0c234060bf | |
Arun | 07c5590db3 | |
Sijmen J. Mulder | 2fc9d518d1 | |
Arun Prakash Jana | 1de825b5bb | |
Arun Prakash Jana | fbf9279973 | |
Arun Prakash Jana | 7330e6642b | |
Darukutsu | 4bb7ffcd4a | |
Arun | 3359b8f7cd | |
LGTM Migrator | 66fd131f2d | |
Arun | a1477c2668 | |
NRK | f13b527a93 | |
NRK | 83c4c880cc | |
daru | e7abf87c54 | |
Darukutsu | e80ba2e44a | |
Arun | 2a4231ea89 | |
NRK | 985f6537ce | |
NRK | 080a061969 | |
NRK | ff27d9ee14 | |
nblock | b511506fa3 | |
Arun | f89ba77516 | |
Arun | 0c4180f2d8 | |
NRK | e5074ebc83 | |
NRK | b00700ce4d | |
Dean G | 38b7282050 | |
Arun | 31b83ef1f0 | |
Luuk van Baal | bc4233767a | |
Arun Prakash Jana | 59eed597c2 | |
Arun Prakash Jana | de3ad1b146 | |
Christian Rackerseder | c24ede2d4a | |
Arun Prakash Jana | 0907895865 | |
Arun | 1cefc326e3 | |
Patrick | a7ce7bb36c | |
Patrick | c9c74dd753 | |
Patrick | 3dac035819 | |
Arun | f6edcc41b9 | |
pataquets | 78019a758e | |
Arun | 23f8c37094 | |
Luuk van Baal | 4f57e0df37 | |
Arun Prakash Jana | f56a8caf65 | |
Arun | 340ba19098 | |
NRK | f8ee991254 | |
Arun | d49ddd1331 | |
NRK | 29a5992dee | |
Arun | ad62463b48 | |
Luuk van Baal | 95e1d56ee4 | |
Arun Prakash Jana | a335f94d05 | |
Arun Prakash Jana | a937bc0a4c | |
Arun | 92873352e0 | |
NRK | e57bb26295 | |
Arun | 7086d030f0 | |
KlzXS | 65dec55e23 | |
Arun Prakash Jana | ab9d8bee89 | |
Arun Prakash Jana | 926c4014b3 | |
Arun Prakash Jana | a7ebc7858a | |
Arun Prakash Jana | e8acae3274 | |
Arun Prakash Jana | 21eebbb003 | |
Arun Prakash Jana | f530b2ca18 | |
Arun Prakash Jana | e298f7eeaf | |
Arun Prakash Jana | e73b57c78a | |
Arun Prakash Jana | 49a0d9d02c | |
Arun Prakash Jana | b76cea3a34 | |
Arun Prakash Jana | 83825a7d11 | |
Arun Prakash Jana | 22db656b8d | |
Arun | 07c1e8e655 | |
NRK | 61e1356fbd | |
N-R-K | f618b78866 | |
Arun Prakash Jana | f2a38b0e22 | |
Arun Prakash Jana | 0988268a61 | |
Tharindu Abeydeera | 98287158aa | |
Arun | e2e1d80d58 | |
NRK | e6b6466c49 | |
Arun Prakash Jana | f415924c7e | |
Arun Prakash Jana | ab0dc52c49 | |
Arun | f829afe60b | |
NRK | fe9c1bbb3a | |
NRK | 63a254951d | |
Arun | aab5ab53a5 | |
NRK | 12f5faa10d | |
NRK | f1932967e2 | |
Arun Prakash Jana | 197717ce68 | |
Arun | 117025c1a4 | |
Arun | 0381db1875 | |
NRK | e98d9288d2 | |
NRK | c3a42f0d92 | |
NRK | 3b09fd1c75 | |
Luuk van Baal | 3fb9cc1e5a | |
Arun Prakash Jana | d95755cce1 | |
Arun Prakash Jana | 12b5416b2c | |
Arun Prakash Jana | a937265833 | |
Anomalocaridid | f2c7495f50 | |
Arun Prakash Jana | b0580905f2 | |
Arun Prakash Jana | b75a22f72d | |
Arun Prakash Jana | b752744ca0 | |
Arun Prakash Jana | db7cb4da1e | |
Luuk van Baal | 910763441d | |
Arun Prakash Jana | b658f324c2 | |
Arun Prakash Jana | 3f4efbefe4 | |
Arun | c09ac1c174 | |
Luuk van Baal | a3cef1611d | |
Arun | f4116a5f42 | |
Jie | a7f243beed | |
Arun Prakash Jana | 8520fe5a0a | |
Arun | a998938b9d | |
NRK | fd69fc2dca | |
NRK | 7121a6fe43 | |
happy wang | dc2cfe78cd | |
Arun | 96cfd3a41a | |
NRK | 0df6eebea0 | |
NRK | 744e9aaf70 | |
NRK | 1d347b1ce9 | |
NRK | 2df0cbd08b | |
Arun | b9a1f1747f | |
Luuk van Baal | 0ab9189bc5 | |
Arun Prakash Jana | 52f4ee5aee | |
Arun | 5ace352d2c | |
Luuk van Baal | 3e84c275ba | |
Arun Prakash Jana | 89bd541562 | |
Arun Prakash Jana | 02d48a9144 | |
Arun | c69067b502 | |
NRK | af5cdca043 | |
NRK | eb66cb5d11 | |
Arun Prakash Jana | 6c197f5f02 | |
Arun Prakash Jana | 2130e1b33a | |
Arun Prakash Jana | 0c626d49a6 | |
Arun Prakash Jana | d898d174f5 | |
Arun Prakash Jana | 581e629c20 | |
Arun Prakash Jana | 56f96c3d0a | |
Arun Prakash Jana | 51f2fde0e6 | |
Arun | 40f75e9c38 | |
Luuk van Baal | 5b5a62bb0d | |
Arun Prakash Jana | 1b31f5cf9b | |
Arun Prakash Jana | 783ea754f7 | |
Arun | c02605a907 | |
Luuk van Baal | fbd6f69f25 | |
Arun Prakash Jana | 19b2ea324a | |
Arun Prakash Jana | 03fc3b99c5 | |
Arun Prakash Jana | e104b749be | |
Arun Prakash Jana | 8fb7feb61c | |
Arun Prakash Jana | 49f21ae013 | |
Göran Gustafsson | 4baee859f8 | |
Arun Prakash Jana | de004d944e | |
Arun | 4784587024 | |
Luuk van Baal | 6fc8f63c0d | |
Arun | 88306e2d9c | |
Arun | 4c6c06b743 | |
Göran Gustafsson | 5023abe2df | |
Göran Gustafsson | 93db9bb2be | |
Arun | 46a5092eee | |
NRK | 5ae3891ee5 | |
Arun | 01ab453cff | |
Luuk van Baal | 3072aa7891 | |
Arun | 0499998e2a | |
Luuk van Baal | bb604bdf1d | |
Arun Prakash Jana | a70ad9c480 | |
Arun Prakash Jana | 10e2d37d0f | |
Arun Prakash Jana | 85be28c019 | |
Arun | d859e81444 | |
Arun | 33ec6dece4 | |
Luuk van Baal | 4c974f286c | |
N-R-K | 1e98e2e126 | |
Arun | f8b8e77be9 | |
Luuk van Baal | 0095948d8d | |
Arun Prakash Jana | d618922177 | |
Arun Prakash Jana | 4337214f50 | |
Arun Prakash Jana | 31a273fdd0 | |
Arun | c2a2a9dee7 | |
Luuk van Baal | 8cdeddeb4a | |
Arun | 772fd30fa0 | |
Luuk van Baal | ae36d30b66 | |
Arun Prakash Jana | 14e80c3872 | |
Arun Prakash Jana | 8175571952 | |
Arun Prakash Jana | 3a50be93fd | |
Arun Prakash Jana | ec7692bb9e | |
Arun | e4c2cb9fd4 | |
Arun Prakash Jana | 8d83af811f | |
Dan Baz | ef5d90f4bb | |
Arun Prakash Jana | ec076f5886 | |
Arun | 81f96ecc1e | |
luukvbaal | ed7afd2dd1 | |
Arun | ab8505efa4 | |
cain-dev | b3f16e7671 | |
Arun Prakash Jana | f6783c2065 | |
Arun | a3fbda02d7 | |
NRK | ba72fca69a | |
Arun | e1e47f909f | |
NRK | 6f332e5260 | |
Arun Prakash Jana | c23125ba50 | |
Arun Prakash Jana | 0a67c5d657 | |
Arun Prakash Jana | af94c7704f | |
Desmond Kabus | b45be9bc5b | |
Arun Prakash Jana | 18a6a010cf | |
Patrick | 4ddd048feb | |
Arun Prakash Jana | fd998b3045 | |
Arun Prakash Jana | 3f58f6111c | |
Arun | 4366247441 | |
Luuk van Baal | 7793cb8b5c | |
Arun Prakash Jana | cc965d1c2d | |
Arun Prakash Jana | dc16ca2340 | |
Arun Prakash Jana | 6b9f8f3666 | |
Arun | 15243186c5 | |
SlIdE42 | 0812c7afac | |
Arun Prakash Jana | be4460c1da | |
Arun Prakash Jana | eb42f7a948 | |
Arun Prakash Jana | 2c5cb4c5aa | |
Arun | a555a7d122 | |
NRK | d0bf2abb37 | |
Arun | 59cf883437 | |
JingMatrix | 5bc75ef4fd | |
Arun | bb875cd5e7 | |
Paolo Capriotti | 4220f4e2eb | |
Arun Prakash Jana | d66492ac10 | |
Arun Prakash Jana | 88e9122c79 | |
Arun Prakash Jana | 5745597fd5 | |
Arun | 0a7742089a | |
JingMatrix | 0a59005acd | |
Arun | 81226db24e | |
NRK | 72ecf6c4b8 | |
Arun | 675016eb55 | |
NRK | 9be6c1a5e2 | |
Arun Prakash Jana | d38841d5f3 | |
Arun | 136549b1ba | |
NRK | c3534bd7e0 | |
Arun Prakash Jana | 57d212c3ca | |
Arun Prakash Jana | 66639c6053 | |
Arun | b718d6d305 | |
Arun | 994bc80e82 | |
daru | 633a9ca8e1 | |
daru | d1de515532 | |
Darukutsu | cd2445607b | |
Darukutsu | 83b6d6aff7 | |
NRK | 2fedc92efc | |
Arun Prakash Jana | 953643b9f1 | |
Arun | 816680ed01 | |
NRK | a8e9d279ac | |
Arun | cb410e25d8 | |
NRK | 799b8fd378 | |
Arun | 30bd6a4e33 | |
KlzXS | 184f134c9e | |
Arun Prakash Jana | 23b54ba0cf | |
Arun | 866612bfda | |
NRK | ff1c1eb2e1 | |
Arun | fbb2172627 | |
NRK | 24db74fd7b | |
NRK | ffd0468f67 | |
Arun Prakash Jana | e67587204b | |
Arun Prakash Jana | aa2147f3ef | |
Arun Prakash Jana | e140e34483 | |
Arun Prakash Jana | fe4ea8a029 | |
Arun | bfa2d4fce5 | |
Luuk van Baal | ecad3e0524 | |
Arun | b8b0bab426 | |
Arun | 9c6ce560f1 | |
Anomalocaridid | efa960d022 | |
lwnctd | 49aa4dabf1 | |
Arun | 2eadf35fa0 | |
NRK | 04181084c0 | |
Arun | dcf3a35cd5 | |
NRK | e2b856904d | |
Arun Prakash Jana | 693df568e0 | |
Arun | 3368a7905b | |
NRK | 02d6feb9b9 | |
NRK | 1608c8763f | |
NRK | 78c0d54400 | |
Arun | e44f8d3fcc | |
Arun | 282266705e | |
Patrick | fe0608116a | |
Arun Prakash Jana | 0fb7a25612 | |
Arun Prakash Jana | b69f838fb8 | |
Luuk van Baal | beafeaaea2 | |
Luuk van Baal | a3d660b673 | |
NRK | ac86fbed0f | |
Luuk van Baal | 48bcc929e8 | |
Luuk van Baal | 06bf4f5dce | |
KlzXS | 3be2dd8390 | |
NRK | ce58aab6b2 | |
NRK | 62f1004836 | |
NRK | d215a9c61d | |
NRK | c234c05b3d | |
NRK | f7298efa99 | |
NRK | 9a26739132 | |
NRK | 23edf571a7 | |
Arun Prakash Jana | 892e4c0082 | |
Arun Prakash Jana | bd6e7e8147 | |
Arun | ecfe819a73 | |
Luuk van Baal | b851b58e83 | |
Arun | 2c31615256 | |
Luuk van Baal | 95f709f86a | |
Arun | a1b15eb766 | |
Arun | 48e478bb90 | |
Luuk van Baal | 8ba43edffc | |
NRK | 7aef60a9d5 | |
Luuk van Baal | e0c1ed273f | |
Arun | 40b2250209 | |
Arun | eb62775852 | |
yeetologist | c147414bc7 | |
Arun Prakash Jana | 1e8b8d14ff | |
KlzXS | 8f2e17303e | |
Arun | 1bc234b0eb | |
NRK | bd8faa2dd8 | |
NRK | 578e6d1aaa | |
NRK | f7091f78e5 | |
Arun | c87b67e073 | |
Omar Polo | fb3d3ab0ef | |
Omar Polo | deead97e23 | |
Arun Prakash Jana | 8ec2fe7f81 | |
Arun Prakash Jana | 65eddfe7b9 | |
Arun | 2f986253e4 | |
Luuk van Baal | 1a6d54515b | |
Arun | 256f0d008f | |
KlzXS | ca9b5e04c7 | |
Arun | f3df0816d9 | |
Toni Jarjour | 8755a3c0cf | |
Arun Prakash Jana | f66183937d | |
Arun | 6178be7e06 | |
Luuk van Baal | 84bfbcf4e7 | |
Arun | 9cb0a13ffe | |
Luuk van Baal | e94f90c89a | |
Arun | 8b7feff4b6 | |
Arun | bd7f127ad9 | |
Arun | fec0479da3 | |
KlzXS | 875a4d8c23 | |
KlzXS | a300e3267f | |
Luuk van Baal | 0d657b47b9 | |
NRK | 39a3cc5309 | |
Arun | c9b9c14481 | |
Arun | 182ac51b8d | |
Luuk van Baal | 66dfa60465 | |
Luuk van Baal | 26f380f154 | |
KlzXS | 48415c5e1c | |
Arun | 1508874b5a | |
Arun | e686b94f7e | |
KlzXS | 22096ee0cd | |
Krisan Alifari | eff4bd6e67 | |
Arun | f854b3c748 | |
Luuk van Baal | 1621c0303b | |
Arun Prakash Jana | b84ad2d552 | |
Arun Prakash Jana | 07a47db8fe | |
Arun Prakash Jana | e2c4445d74 | |
KlzXS | eb769c0de5 | |
Terminator X | b56e488f1c | |
NRK | 5e6c62cd8e | |
Terminator X | b5f5b2f55c | |
Marco Cantoro | da03016c79 | |
Terminator X | bcae254ff2 | |
NRK | 65ae3abc24 | |
NRK | d2dff487e0 | |
NRK | afb7a6e9c1 | |
NRK | a47376ee04 | |
Arun Prakash Jana | bdbd182c65 | |
Arun Prakash Jana | cffcd655e9 | |
Arun Prakash Jana | 2a87694e6a | |
Arun Prakash Jana | 473cd271b5 | |
Arun Prakash Jana | 8efcc24e0e | |
Arun Prakash Jana | aa8baa3d91 | |
Avimitin | 254fd9b7a3 | |
Terminator X | 684a8c7b99 | |
Alexis Praga | e3e4159e11 | |
Arun Prakash Jana | 856896f55d | |
Terminator X | b72090c9a3 | |
Arun Prakash Jana | 4d864d438f | |
Luuk van Baal | de017b7aa2 | |
Arun Prakash Jana | f4f78276e2 | |
Terminator X | b411dfe1ba | |
KlzXS | 7857b7bc5a | |
KlzXS | 1022340aa1 | |
KlzXS | 73ef170da7 | |
Terminator X | 0c0afd4799 | |
Luuk van Baal | fa9067afd4 | |
Arun Prakash Jana | cb5aefa59a | |
Arun Prakash Jana | 00c73512b9 | |
Luuk van Baal | 2801832c4d | |
Terminator X | 5f76b69c36 | |
NRK | dd7c13dd77 | |
Terminator X | f3e027c283 | |
Luuk van Baal | a0fcd78df2 | |
KlzXS | bc69c968be | |
Arun Prakash Jana | 53fbab1f44 | |
Arun Prakash Jana | 24b71bcf1f | |
Arun Prakash Jana | 12fa5344cf | |
Arun Prakash Jana | d5d559ae7f | |
Arun Prakash Jana | acfec62a13 | |
Terminator X | 4dc70f4a3f | |
Arun Prakash Jana | a06ff83c22 | |
Sacha Telgenhof | 44b983f71e | |
Arun Prakash Jana | 9c36f0df34 | |
Arun Prakash Jana | 3490a959be | |
Arun Prakash Jana | c611720cba | |
Arun Prakash Jana | be549f330a | |
An Phung | e20cfd67a1 | |
Arun Prakash Jana | 3091a6f240 | |
Arun Prakash Jana | 3acbc65adb | |
Terminator X | 98585153cc | |
Terminator X | 57bae766ea | |
luukvbaal | e9dbadd465 | |
Luuk van Baal | 17bf7c97f6 | |
Terminator X | 1020f37320 | |
Luuk van Baal | 151312eb37 | |
Terminator X | 2435263052 | |
Terminator X | 831b434021 | |
Luuk van Baal | c48691fe3d | |
KlzXS | b492dfd7ca | |
Terminator X | fa7c19c409 | |
NRK | 8a1a5db92a | |
Arun Prakash Jana | 7477bd15bb | |
Arun Prakash Jana | 74b779abc9 | |
Arun Prakash Jana | 2f6c180433 | |
Arun Prakash Jana | 79b3688e49 | |
Terminator X | d772223e1f | |
Luuk van Baal | 541b936bcf | |
Arun Prakash Jana | e74aa95e3f | |
Arun Prakash Jana | fc86152fa2 | |
Terminator X | 1723aeb470 | |
Max Schillinger | 1c9ecd781c | |
Max Schillinger | f39ee39a36 | |
Arun Prakash Jana | 046d676a73 | |
Terminator X | f3e0f23718 | |
Luuk van Baal | 07c8089eaf | |
Terminator X | 2c82c77a05 | |
Luuk van Baal | 52d8aa0945 | |
Terminator X | a447c12866 | |
Luuk van Baal | d96a7bc2b7 | |
Arun Prakash Jana | ffe472ac32 | |
CantoroMC | bfc493c753 | |
luukvbaal | 532532704e | |
CantoroMC | 2a6cc41972 | |
Terminator X | 5bf9b52beb | |
Arun Prakash Jana | aea97cf3a7 | |
Arun Prakash Jana | 27e1eb54c4 | |
Arun Prakash Jana | e7aec90889 | |
Jakob Beckmann | 7f84fbc8a0 | |
Arun Prakash Jana | 9df7e5f03e | |
Arun Prakash Jana | 359d7bc29c | |
Arun Prakash Jana | fa7cef2df7 | |
Assaf Ben-Amitai | d34741107a | |
Assaf Ben-Amitai | 7de52ff890 | |
Arun Prakash Jana | 51829c8027 | |
Arun Prakash Jana | 49be2cfcd1 | |
Arun Prakash Jana | ab0ab2b5f4 | |
Daniel Eklöf | 0556ac14ec | |
Terminator X | 64c2c68bd0 | |
Luan Belem Rivello | f9cf6dad48 | |
Arun Prakash Jana | c974690482 | |
Arun Prakash Jana | 742759f32d | |
Terminator X | ad968b88da | |
joelazar | dba6eeb431 | |
Arun Prakash Jana | 55fc0c500b | |
Arun Prakash Jana | a62dbf093a | |
Arun Prakash Jana | 900513710f | |
Arun Prakash Jana | 6243de06f4 | |
Arun Prakash Jana | e11cbc289a | |
elder-n00b | e4813f06c1 | |
Arun Prakash Jana | 6c5eab5e55 | |
luukvbaal | ad6b6bd3df | |
CantoroMC | a65055fc32 | |
Arun Prakash Jana | 6c3a3dbc15 | |
CantoroMC | 43da9a9c46 | |
Arun Prakash Jana | 78ea6702f7 | |
Terminator X | 0aed67f329 | |
Luuk van Baal | 82d1510213 | |
Arun Prakash Jana | 983d689a05 | |
0xACE | 9d4330e382 | |
Arun Prakash Jana | 86648ab391 | |
Arun Prakash Jana | 46294e9f3d | |
Terminator X | 840fb75208 | |
Luuk van Baal | b5750c9e38 | |
Luuk van Baal | 2b45c1be55 | |
Luuk van Baal | b7c6fede5f | |
Arun Prakash Jana | 943a7c13ac | |
Arun Prakash Jana | 7cbc79a5fc | |
Arun Prakash Jana | 0b07b77e85 | |
Arun Prakash Jana | e4c1abb6b8 | |
Arun Prakash Jana | bf2b8d8c84 | |
Arun Prakash Jana | fc00faf7d0 | |
Arun Prakash Jana | 42061b0399 | |
Arun Prakash Jana | b2c99b9e4e | |
Arun Prakash Jana | 06e2676421 | |
Arun Prakash Jana | 97ac88dec2 | |
Arun Prakash Jana | e146ad0d7a | |
Arun Prakash Jana | 59d90aa2ce | |
Arun Prakash Jana | 1df63a78e4 | |
Arun Prakash Jana | db1efba256 | |
Arun Prakash Jana | 49ee5b21e7 | |
Arun Prakash Jana | 62a0486480 | |
Terminator X | 2c32f24073 | |
Nikolay Korotkiy | f8aaf3b34c | |
Arun Prakash Jana | 7d17cf3f63 | |
Arun Prakash Jana | 87380732dc | |
Terminator X | 1d5efa7074 | |
NRK | 5fcd3d1198 | |
Arun Prakash Jana | b54f771a44 | |
Terminator X | 23a806864f | |
NRK | f3c29fe81a | |
Arun Prakash Jana | 88e38f1efc | |
Arun Prakash Jana | 6ba0a8357f | |
Arun Prakash Jana | 8cebc69e71 | |
Arun Prakash Jana | f6856f61f7 | |
Arun Prakash Jana | f1dbb9622d | |
Terminator X | 0db988b9b2 | |
jcromero | 258a5846f7 | |
Arun Prakash Jana | d80fdf335b | |
Arun Prakash Jana | e2545f9596 | |
Arun Prakash Jana | 25fab4cb2e | |
N-R-K | 3a98dfb0b0 | |
Arun Prakash Jana | 0150c69844 | |
Arun Prakash Jana | b561772ada | |
Arun Prakash Jana | ad163fb574 | |
Arun Prakash Jana | bc5b39d54c | |
Arun Prakash Jana | 14663b964b | |
Arun Prakash Jana | 3f07a8ca76 | |
Jonathan Rash | 4b4355c733 | |
Arun Prakash Jana | 7b31a356d2 | |
Arun Prakash Jana | 9972c4bdb0 | |
Arun Prakash Jana | c470143113 | |
Arun Prakash Jana | 3b5800fc7a | |
Arun Prakash Jana | 29a7a25445 | |
Arun Prakash Jana | 6f14190e6d | |
Arun Prakash Jana | d54bc230f6 | |
Arun Prakash Jana | e31f71285d | |
Arun Prakash Jana | 1e182a1fe5 | |
Arun Prakash Jana | f7aa4ed324 | |
Arun Prakash Jana | 0ef34a930c | |
Arun Prakash Jana | 07b627a725 | |
Arun Prakash Jana | a911b3044a | |
Arun Prakash Jana | 26f44f0dfc | |
Arun Prakash Jana | fa0f9ddc93 | |
Arun Prakash Jana | 3ef50f06f8 | |
Arun Prakash Jana | d40dbfd69a | |
Arun Prakash Jana | 8af773eb0d | |
Arun Prakash Jana | 8ad807d4a9 | |
Arun Prakash Jana | 4ec87e3021 | |
Arun Prakash Jana | 0159c08602 | |
Arun Prakash Jana | 064f5ea998 | |
Arun Prakash Jana | 9526fb7612 | |
Arun Prakash Jana | 61d8a29d84 | |
Arun Prakash Jana | cef9bd289f | |
Arun Prakash Jana | b3ef30a8ba | |
Arun Prakash Jana | 96f2dfa8a5 | |
Arun Prakash Jana | 60f310160a | |
Arun Prakash Jana | baca4693ec | |
Terminator X | e94ac0b91b | |
KlzXS | b5d1a1b036 | |
KlzXS | c0dceb18c6 | |
Arun Prakash Jana | d9db6b045c | |
Arun Prakash Jana | 5f5ee10e94 | |
Arun Prakash Jana | facdc5fdeb | |
Piña Colada | 1269dd2695 | |
Luuk van Baal | ddf845be88 | |
Piña Colada | c482cf54f0 | |
Luuk van Baal | 4abced6142 | |
Piña Colada | 77c16ac143 | |
Luuk van Baal | 36ddbac10a | |
Arun Prakash Jana | d4a4c72e00 | |
Piña Colada | a7aae40069 | |
Luuk van Baal | fe07ae35f2 | |
Piña Colada | a7603ba1f2 | |
Luuk van Baal | a199156cae | |
Piña Colada | ce8b9fdb2f | |
1bman | 99bd80137d | |
Piña Colada | 2fda5c78e0 | |
KlzXS | c39e54b288 | |
Arun Prakash Jana | 1729a10ef4 | |
Arun Prakash Jana | 96fb61a6a2 | |
Piña Colada | 15b60a80ad | |
Arun Prakash Jana | 04a806dc09 | |
Toni Jarjour | 1607200a75 | |
Arun Prakash Jana | 63ef6d7340 | |
Arun Prakash Jana | 73a175cc39 | |
Arun Prakash Jana | d1df9343c6 | |
Arun Prakash Jana | e7f73d95ce | |
Arun Prakash Jana | eae60c3048 | |
KlzXS | 20e0c49292 | |
Arun Prakash Jana | 7ce5bbcdf7 | |
Arun Prakash Jana | 94c399e2cf | |
Arun Prakash Jana | d9f988e7ed | |
Arun Prakash Jana | 983babc5f6 | |
Arun Prakash Jana | c597f3be9b | |
Arun Prakash Jana | 0e8819fea8 | |
Arun Prakash Jana | 2ffb0f7c79 | |
Arun Prakash Jana | 556941c2b2 | |
Arun Prakash Jana | 4f297fa147 | |
Arun Prakash Jana | 9f86015c16 | |
Arun Prakash Jana | c0ed6d1d04 | |
Arun Prakash Jana | b626cfa00f | |
Arun Prakash Jana | 3e91c2c977 | |
Arun Prakash Jana | 8f3785f2e5 | |
Arun Prakash Jana | d5359f0455 | |
Arun Prakash Jana | 17bb0cfb52 | |
Arun Prakash Jana | e8f0c53287 | |
Arun Prakash Jana | 96cbb4ff84 | |
Arun Prakash Jana | 35aa864554 | |
Arun Prakash Jana | 825effb264 | |
Michael Lan | b2e7f7794c | |
luukvbaal | 02b5b15001 | |
Arun Prakash Jana | 640a56e1cc | |
Arun Prakash Jana | 239c7e7970 | |
Arun Prakash Jana | 0b99247774 | |
Arun Prakash Jana | 1590103ab7 | |
Arun Prakash Jana | 3db1dfd17f | |
Arun Prakash Jana | 0884ad4af9 | |
Arun Prakash Jana | 745a30ccb5 | |
Arun Prakash Jana | a007fe8493 | |
Arun Prakash Jana | 4c66a8c0c3 | |
Arun Prakash Jana | 3834d75d77 | |
Arun Prakash Jana | e256353fbf | |
Arun Prakash Jana | 54258749e1 | |
Arun Prakash Jana | 361521b769 | |
Arun Prakash Jana | 16a15fc976 | |
Arun Prakash Jana | 06c5b17c02 | |
Arun Prakash Jana | 8c116eea2c | |
Arun Prakash Jana | f4f6919c02 | |
Anna Arad | 4f977ff269 | |
Arun Prakash Jana | 0dd76e7aec | |
Arun Prakash Jana | 69926a8eff | |
Arun Prakash Jana | 9a124ae935 | |
Arun Prakash Jana | 145ca91df2 | |
Arun Prakash Jana | e537c22281 | |
Piña Colada | 8238410d4c | |
Kevin Sjöberg | 8fc18fb9d6 | |
Kevin Sjöberg | f443768260 | |
Arun Prakash Jana | cbbac4728b | |
Arun Prakash Jana | 54b2eb51d5 | |
Arun Prakash Jana | 46b48cf71c | |
Arun Prakash Jana | 6d2d901a91 | |
Arun Prakash Jana | 51ac3d02c9 | |
Arun Prakash Jana | 15eed29227 | |
Arun Prakash Jana | 3b6938f782 | |
Arun Prakash Jana | f24b82a750 | |
Arun Prakash Jana | 9de941306c | |
Arun Prakash Jana | 5e34181bb3 | |
Arun Prakash Jana | d87414eb61 | |
Arun Prakash Jana | 488fe6b941 | |
Arun Prakash Jana | fb6ca79197 | |
Piña Colada | 29bce804be | |
Luuk van Baal | 7edf14139b | |
Arun Prakash Jana | e1a9aa0aa5 | |
Piña Colada | b8851bdf16 | |
Luuk van Baal | c9c0be32a8 | |
Piña Colada | 4637a5a84d | |
Luuk van Baal | 0fff92b396 | |
Piña Colada | 7b32e3bae0 | |
Luuk van Baal | 5533f152bd | |
Piña Colada | f681a5b3f1 | |
Luuk van Baal | 99e039d504 | |
Arun Prakash Jana | f03b5dd4a9 | |
Arun Prakash Jana | 2df1e64127 | |
Arun Prakash Jana | 5a6df62b1c | |
luukvbaal | c205177ac6 | |
Piña Colada | 14be56057c | |
Luuk van Baal | de430efafb | |
luukvbaal | f3eac98678 | |
Arun Prakash Jana | 29ef232301 | |
Arun Prakash Jana | 88e9171266 | |
Arun Prakash Jana | f27e93fba0 | |
Arun Prakash Jana | ccce80a1e9 | |
Arun Prakash Jana | b52c09dd23 | |
Arun Prakash Jana | bf673744fb | |
luukvbaal | 93e7995ab5 | |
Piña Colada | 6f862131e1 | |
Luuk van Baal | 40031b81ae | |
Arun Prakash Jana | 859ddf8d88 | |
Piña Colada | a79ef66abb | |
Luuk van Baal | 272e47c64a | |
Arun Prakash Jana | 6a904f7cf5 | |
Piña Colada | 63913115df | |
Luuk van Baal | cc8a21fa61 | |
Piña Colada | 2238fa9cbc | |
Luuk van Baal | e4988f0264 | |
Piña Colada | 6eda83097a | |
Luuk van Baal | b6fd7d928c | |
Piña Colada | 609b6a426a | |
Luuk van Baal | 2f9c700537 | |
Arun Prakash Jana | 6d817a41e3 | |
Arun Prakash Jana | 6f29138299 | |
Arun Prakash Jana | c54ba35ce0 | |
Arun Prakash Jana | 4ea0d70217 | |
Arun Prakash Jana | 46e1d6bdda | |
Arun Prakash Jana | 85c108a5d6 | |
Arun Prakash Jana | 6bb6ddfe8a | |
Arun Prakash Jana | 4bc8e1a8be | |
Arun Prakash Jana | a6eeceec55 | |
Arun Prakash Jana | f6b14f6505 | |
Arun Prakash Jana | b397606d0a | |
Arun Prakash Jana | 462531b8c7 | |
Arun Prakash Jana | 831287c92e | |
Arun Prakash Jana | 30ee27802e | |
Arun Prakash Jana | a8c52134f6 | |
Piña Colada | 28731a10f7 | |
Luuk van Baal | 0a569496c8 | |
Arun Prakash Jana | 326d5a4fae | |
luukvbaal | 78b2170e03 | |
Arun Prakash Jana | 284a3c4866 | |
Arun Prakash Jana | 025b570e05 | |
Arun Prakash Jana | db8079f552 | |
Arun Prakash Jana | fdeba8a87e | |
Arun Prakash Jana | 1017413474 | |
Arun Prakash Jana | 53e98a9fd1 | |
Arun Prakash Jana | 88f71ff35d | |
Arun Prakash Jana | 54d760b9f5 | |
Arun Prakash Jana | 36e1544b32 | |
Luuk van Baal | b89c32b9fa | |
Arun Prakash Jana | 2bd72d1b29 | |
Arun Prakash Jana | edab98ab6d | |
Piña Colada | bb5642291c | |
Luuk van Baal | d64242aec3 | |
Arun Prakash Jana | 45ac90d5e6 | |
Piña Colada | 9a949b7c33 | |
Luuk van Baal | 88eb45944c | |
Piña Colada | 8a36196e98 | |
Luuk van Baal | 8eced6c5d4 | |
Arun Prakash Jana | cbc4587630 | |
Piña Colada | 715abc7a3f | |
Luuk van Baal | 5cc98987c5 | |
Piña Colada | a95ed82f60 | |
Luuk van Baal | 5fba2ba749 | |
Arun Prakash Jana | 31c34740bc | |
Arun Prakash Jana | 79cbcc18e1 | |
Piña Colada | db240eeeda | |
Luuk van Baal | f7e84bed70 | |
Arun Prakash Jana | 7bbacd0f0d | |
Arun Prakash Jana | 4dcefcc4d4 | |
Kabouik | 69d63ff50e | |
Arun Prakash Jana | 5e8ef070dc | |
Arun Prakash Jana | 24080569b8 | |
luukvbaal | bb37c9dd46 | |
Kabouik | b14d2311e6 | |
Arun Prakash Jana | 7a76ca8548 | |
Arun Prakash Jana | f343f315b5 | |
Arun Prakash Jana | 513b4f24a6 | |
Arun Prakash Jana | 1fabac27ba | |
Arun Prakash Jana | 3316e2acdb | |
Arun Prakash Jana | 6222cac4bf | |
Arun Prakash Jana | 177b60e6c2 | |
Piña Colada | 2ca11a34e7 | |
Piña Colada | d83acda68b | |
Luuk van Baal | 9560a91f97 | |
Luuk van Baal | 2edf59fef1 | |
Arun Prakash Jana | d46918946f | |
Arun Prakash Jana | d0b4508798 | |
Arun Prakash Jana | 0427f70c4e | |
Arun Prakash Jana | bca5763cf7 | |
lawnowner | 9cbb7f540c | |
Piña Colada | dd02afc58b | |
Luuk van Baal | 16b2f40ffe | |
Arun Prakash Jana | 6b0f308f26 | |
Arun Prakash Jana | 448a4203bc | |
Arun Prakash Jana | 04c38ecf3d | |
Arun Prakash Jana | 1b88062310 | |
Piña Colada | 9756ce4650 | |
Arun Prakash Jana | 4a4628e2fc | |
Piña Colada | 375d1057c1 | |
Marco Cantoro | d6af0d2ed4 | |
KlzXS | 56d3f2d976 | |
Arun Prakash Jana | 907616a058 | |
Arun Prakash Jana | 1f95c355a9 | |
Arun Prakash Jana | 9c5214c24a | |
Arun Prakash Jana | de80bba9db | |
Arun Prakash Jana | 466d138cc7 | |
Arun Prakash Jana | e4c3f7d739 | |
Arun Prakash Jana | 9b6e7e86bc | |
Arun Prakash Jana | b44d2c5071 | |
Arun Prakash Jana | 8575711227 | |
Piña Colada | c506da4419 | |
Luuk van Baal | a359a8152c | |
Arun Prakash Jana | c0ccf098ec | |
Luuk van Baal | a327ee4a3d | |
Arun Prakash Jana | eec6366272 | |
Arun Prakash Jana | b5654e3188 | |
Piña Colada | e075b98cfe | |
Piña Colada | f45967c4a0 | |
Luuk van Baal | 6c450bee94 | |
Arun Prakash Jana | f3fe27e694 | |
Arun Prakash Jana | e5c1b0bdd2 | |
Arun Prakash Jana | 0691c4fb47 | |
Arun Prakash Jana | da7dc8e6e2 | |
Arun Prakash Jana | 7acc9196d5 | |
Arun Prakash Jana | 4727b3baa8 | |
luukvbaal | f4eb89029c | |
Arun Prakash Jana | 69df38dfd4 | |
Arun Prakash Jana | 54aa971a6b | |
Piña Colada | 7a562d7b03 | |
Luuk van Baal | 6730c0fd01 | |
Arun Prakash Jana | b58e9fc384 | |
Arun Prakash Jana | 0d21813b11 | |
Arun Prakash Jana | 765986b916 | |
Arun Prakash Jana | 41d414c2fc | |
Arun Prakash Jana | 0eeae6ee7b | |
Arun Prakash Jana | bd47846185 | |
Arun Prakash Jana | 949f76ec16 | |
Arun Prakash Jana | d4767e6d47 | |
Piña Colada | 19a5ef8a61 | |
Luuk van Baal | d73569be73 | |
Piña Colada | 703be56930 | |
Luuk van Baal | 65e306feec | |
luukvbaal | 74785069e0 | |
Arun Prakash Jana | 2ac70152a4 | |
Arun Prakash Jana | 3ab8bf1c16 | |
KlzXS | 002758063e | |
KlzXS | 36d86a294d | |
Kabouik | c2aeb51bcc | |
luukvbaal | 5ed2998023 | |
Arun Prakash Jana | e8bebac168 | |
Arun Prakash Jana | 714d806341 | |
luukvbaal | 802a7794ae | |
Arun Prakash Jana | 163102e8ae | |
Luuk van Baal | 7a7fd5fcab | |
luukvbaal | 4ebc396250 | |
Arun Prakash Jana | 0c88d1c210 | |
luukvbaal | d998943119 | |
luukvbaal | b97e2d02ea | |
Arun Prakash Jana | eea4d34423 | |
Arun Prakash Jana | 34c3d2116a | |
Arun Prakash Jana | 1fde10b022 | |
luukvbaal | 1241a4d75d | |
akimdi | c673840d5d | |
Piña Colada | b0a985bca8 | |
Luuk van Baal | cbbefe805a | |
Arun Prakash Jana | 4648a56178 | |
Piña Colada | 59dfffd004 | |
Luuk van Baal | 15031f7d9e | |
Piña Colada | f0c64a89b8 | |
Luuk van Baal | 77640a6434 | |
Piña Colada | a629707eec | |
Luuk van Baal | ec3f754192 | |
Piña Colada | 47a779b1bf | |
luukvbaal | 48898eeb8b | |
Roland Kammerer | 5c1c732fb7 | |
Piña Colada | cd070a6228 | |
akimdi | 5f67acd8b8 | |
akimdi | 794048b306 | |
Piña Colada | c49f24c696 | |
Luuk van Baal | 14350b94a8 | |
Arun Prakash Jana | e09148e386 | |
Arun Prakash Jana | b08aa8330d | |
Arun Prakash Jana | 6d2325e18a | |
Arun Prakash Jana | 69431e49a9 | |
Arun Prakash Jana | 430833326b | |
Arun Prakash Jana | 25157592df | |
Arun Prakash Jana | 2b94c29e1d | |
Arun Prakash Jana | 30e1c54e0e | |
Arun Prakash Jana | b5015b8e6c | |
Arun Prakash Jana | f4c5b1a937 | |
Arun Prakash Jana | 5bfc868321 | |
Mischievous Meerkat | 285463253c | |
Luuk van Baal | ad4f0cbbef | |
Luuk van Baal | 1fd61ca5f5 | |
Arun Prakash Jana | ad40ae9b53 | |
Arun Prakash Jana | a482e8afe5 | |
Arun Prakash Jana | 0c55e74fb5 | |
Arun Prakash Jana | ee04215d91 | |
Mischievous Meerkat | 99a8f761cf | |
Luuk van Baal | 710e621735 | |
Luuk van Baal | eb98b9076b | |
Luuk van Baal | a5a1c7b82c | |
Arun Prakash Jana | a1cb764943 | |
Arun Prakash Jana | 903a4b3a66 | |
Mischievous Meerkat | 9a73057272 | |
Luuk van Baal | ada4695bb6 | |
Arun Prakash Jana | dc9d877941 | |
Luuk van Baal | f1f147c928 | |
Mischievous Meerkat | a0be1c33cb | |
akim | 534aa355a1 | |
Arun Prakash Jana | a44b23786f | |
Arun Prakash Jana | b3132d6398 | |
Arun Prakash Jana | f27df77777 | |
Arun Prakash Jana | edacfcc828 | |
Arun Prakash Jana | 0223d53584 | |
Arun Prakash Jana | b0fd7a5ffe | |
Arun Prakash Jana | dd5588650d | |
Arun Prakash Jana | ed23e494a9 | |
Arun Prakash Jana | a62bcd3f87 | |
Arun Prakash Jana | ed55fbd9d5 | |
Arun Prakash Jana | 98308b8444 | |
exoton | 98a0f7484a | |
Arun Prakash Jana | a6a09338a2 | |
Mischievous Meerkat | df6dbbb84c | |
Luuk van Baal | c3a472a7e2 | |
Arun Prakash Jana | 3f47c6ee55 | |
Mischievous Meerkat | da734c50da | |
Luuk van Baal | 9fcdf78643 | |
luukvbaal | 5cf723fbe4 | |
Arun Prakash Jana | 34f20ea678 | |
Mischievous Meerkat | e459d912b0 | |
Yuri Kloubakov | 1a0c9d0c90 | |
exoton | 42aa97b112 | |
luukvbaal | 832676984b | |
Rudolf Adamkovič | 655e8886f1 | |
Arun Prakash Jana | 603c1580e8 | |
Arun Prakash Jana | 6dfea38999 | |
Arun Prakash Jana | b29d898350 | |
Arun Prakash Jana | 8542f5bc33 | |
Arun Prakash Jana | ccf2927b6d | |
Arun Prakash Jana | e5d44ce223 | |
Benawi Adha | 0f4dfee6c6 | |
Arun Prakash Jana | 37fbed2fb7 | |
Arun Prakash Jana | 980fd80aa9 | |
Arun Prakash Jana | 7f5dbd11e3 | |
Arun Prakash Jana | 7c63dc8d73 | |
luukvbaal | d5dac4c686 | |
Arun Prakash Jana | 9c218d41e8 | |
Benawi Adha | b0aa1fe379 | |
Arun Prakash Jana | f602cbee07 | |
Mischievous Meerkat | 7233935109 | |
Léo Villeveygoux | 5bba7b45fa | |
Benawi Adha | f176d81ea0 | |
Arun Prakash Jana | d8e370e579 | |
Benawi Adha | c61a716e11 | |
lvgx | 1c2cb7fd31 | |
luukvbaal | f90e567a17 | |
Benawi Adha | 638676a689 | |
luukvbaal | e0822fdef4 | |
Arun Prakash Jana | 9f0a374255 | |
Arun Prakash Jana | 2f6046e6da | |
luukvbaal | 73a54e7550 | |
luukvbaal | bc59961d98 | |
luukvbaal | 9544eb91d2 | |
luukvbaal | bebad983ca | |
luukvbaal | ac29a7c166 | |
Arun Prakash Jana | 49c458517f | |
Arun Prakash Jana | 71083b0670 | |
Arun Prakash Jana | c625679d58 | |
Arun Prakash Jana | 2fc61a8f48 | |
Arun Prakash Jana | 4a45e45b30 | |
luukvbaal | fdf40df5e9 | |
Arun Prakash Jana | 943728dd14 | |
luukvbaal | 2e4aca5e6b | |
Arun Prakash Jana | a88bbe1a9c | |
luukvbaal | f596ae2359 | |
Luuk van Baal | 77cde578e0 | |
Arun Prakash Jana | 4c8e2e25b8 | |
Arun Prakash Jana | 5f0b3b74d0 | |
Arun Prakash Jana | c825a9e541 | |
Arun Prakash Jana | 381b251fd0 | |
Arun Prakash Jana | 317076b893 | |
Arun Prakash Jana | fddc5086dd | |
Arun Prakash Jana | 93ca773c59 | |
Arun Prakash Jana | 2dccb94f3f | |
Arun Prakash Jana | 12e7e2c7e0 | |
Mischievous Meerkat | 571363b0f9 | |
Rudolf Adamkovič | 02eb42b0ed | |
Arun Prakash Jana | d40137f7b3 |
|
@ -3,10 +3,11 @@ version: 2
|
|||
jobs:
|
||||
compile:
|
||||
docker:
|
||||
- image: ubuntu:20.04
|
||||
- image: ubuntu:22.04
|
||||
working_directory: ~/nnn
|
||||
environment:
|
||||
CI_FORCE_TEST: 1
|
||||
parallelism: 4
|
||||
steps:
|
||||
- run:
|
||||
command: |
|
||||
|
@ -14,24 +15,14 @@ jobs:
|
|||
DEBIAN_FRONTEND="noninteractive" TZ="America/New_York" apt-get -y install tzdata
|
||||
apt install -y --no-install-recommends software-properties-common wget gpg-agent shellcheck
|
||||
apt install -y --no-install-recommends git make pkg-config libncurses-dev libreadline-dev
|
||||
apt install -y --no-install-recommends gcc-7 gcc-8 gcc-9 gcc-10
|
||||
apt install -y --no-install-recommends clang-6.0 clang-7 clang-8 clang-9 clang-10 clang-tidy-10
|
||||
apt install -y --no-install-recommends gcc-9 gcc-10 gcc-11 gcc-12
|
||||
apt install -y --no-install-recommends clang-11 clang-12 clang-13 clang-14 clang-15 clang-tidy-15
|
||||
- checkout
|
||||
- run:
|
||||
command: |
|
||||
export CFLAGS=-Werror
|
||||
make clean
|
||||
echo
|
||||
echo "########## gcc-7 ##########"
|
||||
CC=gcc-7 make strip
|
||||
ls -l nnn
|
||||
make clean
|
||||
echo
|
||||
echo "########## gcc-8 ##########"
|
||||
CC=gcc-8 make strip
|
||||
ls -l nnn
|
||||
make clean
|
||||
echo
|
||||
echo "########## gcc-9 ##########"
|
||||
CC=gcc-9 make strip
|
||||
ls -l nnn
|
||||
|
@ -42,35 +33,40 @@ jobs:
|
|||
ls -l nnn
|
||||
make clean
|
||||
echo
|
||||
echo "########## clang-6 ##########"
|
||||
CC=clang-6.0 make strip
|
||||
echo "########## gcc-11 ##########"
|
||||
CC=gcc-11 make strip
|
||||
ls -l nnn
|
||||
make clean
|
||||
echo
|
||||
echo "########## clang-7 ##########"
|
||||
CC=clang-7 make strip
|
||||
echo "########## gcc-12 ##########"
|
||||
CC=gcc-12 make strip
|
||||
ls -l nnn
|
||||
make clean
|
||||
echo
|
||||
echo "########## clang-8 ##########"
|
||||
CC=clang-8 make strip
|
||||
echo "########## clang-11 ##########"
|
||||
CC=clang-11 make strip
|
||||
ls -l nnn
|
||||
make clean
|
||||
echo
|
||||
echo "########## clang-9 ##########"
|
||||
CC=clang-9 make strip
|
||||
echo "########## clang-12 ##########"
|
||||
CC=clang-12 make strip
|
||||
ls -l nnn
|
||||
make clean
|
||||
echo
|
||||
echo "########## clang-10 ##########"
|
||||
CC=clang-10 make strip
|
||||
echo "########## clang-13 ##########"
|
||||
CC=clang-13 make strip
|
||||
ls -l nnn
|
||||
make clean
|
||||
echo
|
||||
echo "########## clang-tidy-10 ##########"
|
||||
clang-tidy-10 src/* -- -I/usr/include -I/usr/include/ncursesw
|
||||
echo "########## clang-14 ##########"
|
||||
CC=clang-14 make strip
|
||||
ls -l nnn
|
||||
make clean
|
||||
echo
|
||||
echo "########## clang-tidy-15 ##########"
|
||||
clang-tidy-15 src/* -- -I/usr/include -I/usr/include/ncursesw
|
||||
echo "########## shellcheck ##########"
|
||||
find plugins/ -type f -not -name "*.md" -exec shellcheck -e SC1090,SC2230 {} +
|
||||
find plugins/ -type f ! \( -name "*.md" -o -name "*-mac" \) -exec shellcheck {} +
|
||||
|
||||
package-and-publish:
|
||||
machine: true
|
||||
|
@ -78,29 +74,31 @@ jobs:
|
|||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: "package with packagecore"
|
||||
name: "auto-generate packages"
|
||||
command: |
|
||||
# Create dist directory if it doesn't exist
|
||||
mkdir ./dist
|
||||
# Clean up
|
||||
rm -rf ./dist/*
|
||||
# Pack source
|
||||
git archive -o ../${CIRCLE_PROJECT_REPONAME}-${CIRCLE_TAG}.tar.gz --format tar.gz --prefix=${CIRCLE_PROJECT_REPONAME}-${CIRCLE_TAG#v}/ ${CIRCLE_TAG}
|
||||
# Use latest installed python3 from pyenv
|
||||
export PYENV_VERSION="$(pyenv versions | grep -Po '\b3\.\d+\.\d+' | tail -1)"
|
||||
pip install packagecore
|
||||
packagecore -c misc/packagecore/packagecore.yaml -o ./dist/ ${CIRCLE_TAG#v}
|
||||
#pip install packagecore
|
||||
#packagecore -c misc/packagecore/packagecore.yaml -o ./dist/ ${CIRCLE_TAG#v}
|
||||
# Move source pack to dist
|
||||
mv ../${CIRCLE_PROJECT_REPONAME}-${CIRCLE_TAG}.tar.gz dist/
|
||||
mv ../${CIRCLE_PROJECT_REPONAME}-${CIRCLE_TAG}.tar.gz ./dist/
|
||||
|
||||
- run:
|
||||
name: "publish to GitHub"
|
||||
command: |
|
||||
go get github.com/tcnksm/ghr
|
||||
go install github.com/tcnksm/ghr@latest
|
||||
ghr -t ${GITHUB_API_TOKEN} -u ${CIRCLE_PROJECT_USERNAME} -r ${CIRCLE_PROJECT_REPONAME} -c ${CIRCLE_SHA1} -replace ${CIRCLE_TAG} ./dist/
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
|
||||
test:
|
||||
CircleCI:
|
||||
jobs: &all-tests
|
||||
- compile
|
||||
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
# These are supported funding model platforms
|
||||
|
||||
custom: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=RMLTQ76JSXJ4Q
|
||||
github: jarun
|
||||
|
|
|
@ -29,13 +29,14 @@ If we need more information and there is no communication from the bug reporter
|
|||
|
||||
#### Environment details (Put `x` in the checkbox along with the information)
|
||||
|
||||
[ ] Operating System:
|
||||
[ ] Desktop Environment:
|
||||
[ ] Terminal Emulator:
|
||||
[ ] Shell:
|
||||
[ ] Custom desktop opener (if applicable):
|
||||
[ ] Program options used:
|
||||
[ ] Configuration options set:
|
||||
[ ] Issue exists on `nnn` master
|
||||
- [ ] Operating System:
|
||||
- [ ] Desktop Environment:
|
||||
- [ ] Terminal Emulator:
|
||||
- [ ] Shell:
|
||||
- [ ] Custom desktop opener (if applicable):
|
||||
- [ ] Program options used:
|
||||
- [ ] Configuration options set:
|
||||
- [ ] Plugins are installed
|
||||
- [ ] Issue exists on `nnn` master
|
||||
|
||||
#### Exact steps to reproduce the issue
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
contact_links:
|
||||
- name: Idea, Enhancement, Question, Support
|
||||
url: https://github.com/jarun/nnn/discussions
|
||||
about: If you have a question, need support or want to discuss new ideas then please open a discussion thread.
|
|
@ -1,29 +0,0 @@
|
|||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
---
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
|
||||
A clear and concise description of what the problem is.
|
||||
|
||||
**Describe the solution you'd like**
|
||||
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
|
||||
A clear and concise description of any alternative solutions or features you've
|
||||
considered.
|
||||
|
||||
**Additional context**
|
||||
|
||||
Add any other context or screenshots about the feature request here.
|
||||
|
||||
**Consider contributing**
|
||||
|
||||
Please consider contributing the feature back to `nnn`.
|
||||
|
||||
Feel free to discuss in the ToDo list thread. We are more than happy to help.
|
|
@ -1,4 +1,4 @@
|
|||
name: ci
|
||||
name: GitHubCI
|
||||
|
||||
on:
|
||||
push:
|
||||
|
@ -27,11 +27,23 @@ jobs:
|
|||
env:
|
||||
CC: clang
|
||||
run: |
|
||||
brew update
|
||||
brew install llvm
|
||||
# see: https://github.com/actions/setup-python/issues/577
|
||||
brew update || true
|
||||
brew install llvm || true
|
||||
brew unlink python@3.11 && brew link python@3.11
|
||||
export PATH="/usr/local/opt/llvm/bin:$PATH"
|
||||
export PATH="/opt/homebrew/opt/llvm/bin:$PATH"
|
||||
export CFLAGS="$CFLAGS -Werror"
|
||||
make clean
|
||||
make
|
||||
make clean
|
||||
clang-tidy src/* -- -I/usr/include
|
||||
ubuntu-patches:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Compile patches with gcc
|
||||
env:
|
||||
CC: gcc
|
||||
run: |
|
||||
make checkpatches
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
pull_request:
|
||||
branches: [ "master" ]
|
||||
schedule:
|
||||
- cron: "11 23 * * 3"
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ cpp, python ]
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
queries: +security-and-quality
|
||||
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
if: ${{ matrix.language == 'cpp' || matrix.language == 'python' }}
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
with:
|
||||
category: "/language:${{ matrix.language }}"
|
|
@ -3,12 +3,21 @@ name: 'Lock threads'
|
|||
on:
|
||||
schedule:
|
||||
- cron: '0 0 * * *'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
discussions: write
|
||||
|
||||
concurrency:
|
||||
group: lock-threads
|
||||
|
||||
jobs:
|
||||
lock:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: dessant/lock-threads@v2
|
||||
- uses: dessant/lock-threads@v5
|
||||
with:
|
||||
github-token: ${{ github.token }}
|
||||
issue-lock-inactive-days: '30'
|
||||
|
|
|
@ -1,2 +1,5 @@
|
|||
*.o
|
||||
*.dSYM
|
||||
nnn
|
||||
src/icons-generated*.h
|
||||
src/icons-hash-gen
|
||||
|
|
329
CHANGELOG
329
CHANGELOG
|
@ -1,3 +1,330 @@
|
|||
nnn v4.9 Elixir
|
||||
2023-08-27
|
||||
|
||||
- config option `NNN_ARCHMNT` to specify archive mounter utility
|
||||
- key <kbd>^y</kbd> to jump to next young file
|
||||
- filter adjustment when opening context from plugin
|
||||
- properly update mode after `chmod`
|
||||
- pre-fill selected file name to create link if sel is preferred over hovered
|
||||
- fix crash when `PWD` is empty
|
||||
- make `quitcd.bash_zsh` POSIX-compliant
|
||||
- `nmount` - support `udiskctl` as default
|
||||
- `preview-tui` - support wezterm split size percentage
|
||||
- `preview-tui` - move to bash for environment manipulation through arrays
|
||||
- `fzopen` - handle empty selection
|
||||
- `finder` - use default path to find
|
||||
- add icons for `djvu` files
|
||||
- support Nerd Fonts v3.0.0 and above (older versions are broken by v3.0.0)
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
nnn v4.8 Spritz
|
||||
2023-04-13
|
||||
|
||||
- show total size (key <kbd>S</kbd>) of non-filtered selection in a directory
|
||||
- fix tilde (~) handling in file name
|
||||
- plugin `.nmv` now respects `-u` flag
|
||||
- env var `$NNN_PREFER_SELECTION` exported to all plugins
|
||||
- support for wezterm in `preview-tui`
|
||||
- create new file or directory (tree) on startup
|
||||
- run command as plugin now supports exported variables
|
||||
- use `"$nnn"` anywhere when running command as plugin
|
||||
- set defaults for some prompts on <kbd>Enter</kbd>
|
||||
- improve archive, rename and create new workflows
|
||||
- optimize link creation
|
||||
- allow overwriting regular files on new empty file creation
|
||||
- add patch for colemak keyboard (existing renamed to colemak-dh)
|
||||
- add correct check for Wayland in clipboard plugins
|
||||
- add quitcd script for nushell
|
||||
- plugin `kdeconnect` - send multiple files
|
||||
- plugin `preview-tui`: add `chafa` as preferred image viewer, multiple fixes
|
||||
- plugin `nmount` - misc. improvements
|
||||
- add icon for jxl files
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
nnn v4.7 Cuba libre
|
||||
2022-11-24
|
||||
|
||||
|
||||
- fix <kbd>^N</kbd> not working sometimes (#1449)
|
||||
- fix file remove confirmation prompt
|
||||
- bring back `atool` as the default archive handler
|
||||
- add option `-B` to use `bsdtar` as the archive utility
|
||||
- find and list mode improvements
|
||||
ntinue even if max paths/data size limit is exceeded
|
||||
eed improvements
|
||||
pport listing maximum 16K paths of 64 MiB of data
|
||||
- key <kbd>J</kbd> to jump to an entry or relative offset from current entry
|
||||
- prefill the hard link creation prompt when there's a single target (#1507)
|
||||
- documented workaround for docker container crash (#1407, #1476)
|
||||
- plugin `imgview`: handle arguments as strings (#1509)
|
||||
- plugin `wallpaper`: support Wayland (#1512)
|
||||
- plugin `upload`: handle selection using `ffsend` (#1523)
|
||||
- add Rust icons (#1502)
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
nnn v4.6 Absinthe
|
||||
2022-07-26
|
||||
|
||||
- icon handling overhaul (#1432, #1436)
|
||||
- better performance, memory usage and reduced binary size
|
||||
- emoji support for supporting distros and terminals (#1346)
|
||||
- open the target directory of symlinked bookmarks (#1353)
|
||||
- enable show hidden when a hidden file is passed as argument
|
||||
- add Colemak-DH layout keybinds to patch framework (#1421)
|
||||
- set `bsdtar` as the default archive utility
|
||||
- support 4 byte unicode keybinds (#1428)
|
||||
- enable directory auto-enter during filter operation (`-A` to disable)
|
||||
- enable filter prompt inside the bookmark/plugin dirs
|
||||
- show volume usage information in help
|
||||
- add new icon colors for mp4 and flac files
|
||||
- use `stat -x` for file details on *BSD and macOS (#1389)
|
||||
- interpret suffix `$nnn` when paging (#1355)
|
||||
- disable key <kbd>e</kbd> (edit file) in explorer mode (#1394)
|
||||
- fix double order chars on filter case match change
|
||||
- `.cbcp`: more verbose message on paste without a selection
|
||||
- plugin `preview-tui`: scale-up kitty previews
|
||||
- plugin `preview-tui`: account for ueberzug offset
|
||||
- plugin `preview-tui`: support `SPLIT_SIZE` for preview pane (#1431)
|
||||
- plugin `autojump`: support z.lua
|
||||
- new Makefile target `shellcheck` to verify plugins
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
nnn v4.5 Cachaça
|
||||
2022-04-26
|
||||
|
||||
- disable filter info if file details (option `-i`) enabled
|
||||
- open previous active context on context quit
|
||||
- switch <kbd>^J</kbd> and <kbd>+</kbd> functionality:
|
||||
- <kbd>+</kbd>: toggle file selection
|
||||
- <kbd>^J</kbd>: toggle auto-jump on file open
|
||||
- allow symlink creation with name `@` to a single file (#1345)
|
||||
- clear selection on successful operation at native prompt with "%j" (#1330)
|
||||
- reverse timestamps of entries modified/created within 5 minutes
|
||||
- avoid using non-portable `xargs` flags on macOS (#1299)
|
||||
- quitcd script for Elvish shell > 0.17.0 (#1344)
|
||||
- plugin `openall` to open selected files together (#1333)
|
||||
- plugin `gitroot` to jump to git root directory from a subtree
|
||||
- plugin `gsconnect` to send the selected files to Android using gsconnect
|
||||
- icon for opus and webp files
|
||||
- `preview-tui` - fix gif conversion and whitespace name
|
||||
- `preview-tui` - add support for windows terminal split
|
||||
- `preview-tui` - djvu file previews
|
||||
- `nuke` - add support for `imv` when named _imv_
|
||||
- `gsconnect` - support connection to multiple devices
|
||||
- export `NNN_INCLUDE_HIDDEN` to plugins (#1308)
|
||||
- respect `NNN_TRASH` in `.nmv` (#1306)
|
||||
- add GNU sed as a dependency with support for env var `SED`
|
||||
- use bold `>` to point at current entry in detail mode
|
||||
- add 2 spaces after icons for better visibility
|
||||
- documentation refresh
|
||||
- make option `O_NOSORT` to load directories unsorted on entry
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
nnn v4.4 Tequila
|
||||
2021-11-23
|
||||
|
||||
- support macOS iterm2 in plugin preview-tui (#1196)
|
||||
- use selection at native command prompt with `%j` and `%J`
|
||||
- docs - https://github.com/jarun/nnn/wiki/concepts#special-variables
|
||||
- scroll strings longer than columns in rename/new prompts (#1213, #279)
|
||||
- batch rename symlink targets in listing mode (#1214)
|
||||
- option for recursive rename in plugin .nmv (#1186)
|
||||
- more frequent checks for cancellation during du (#1236)
|
||||
- picker mode: enable auto-proceed
|
||||
- picker mode: don't pick hovered file on <kbd>Enter</kbd> if selection exists
|
||||
- picker mode: fix issue in plugin `fzopen` when used to pick files
|
||||
- send file to explorer FIFO on double left click instead of opening it
|
||||
- new neovim plugin [nnn.nvim](https://github.com/luukvbaal/nnn.nvim)
|
||||
- nvim-only, featuring explorer mode (`-F` flag)
|
||||
- explorer mode for [nnn.vim](https://github.com/mcchrish/nnn.vim#explorer)
|
||||
- remove option `-w`: always place HW cursor on current entry
|
||||
- accept link name when linking a single target (#1201)
|
||||
- option `-i` to show current file information in info bar
|
||||
- force GNU sed on *BSD and Solaris
|
||||
- add `nsxiv` support to nuke, preview-tabbed and imgview (#1230)
|
||||
- fix preview-tui without `-a` (#1208)
|
||||
- pass `pts` in env var for preview-tui to use in `tput` (#1235)
|
||||
- disable editing file in picker mode (#1183)
|
||||
- save session in picker mode (#1190)
|
||||
- use nerd icons for gitstatus patch (#1220)
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
nnn v4.3 Martini
|
||||
2021-09-29
|
||||
|
||||
- cool ASCII art logo in the help screen
|
||||
- add `bookmarks` directory for flexible symlinked bookmarks
|
||||
- new key <kbd>B</kbd> to add a symlinked bookmark for current dir
|
||||
- special variables `$dN`, `$fN` available for plugins/prompt/shell to access
|
||||
dir/hovered file in each context
|
||||
- config `NNN_ORDER` to set directory-specific ordering
|
||||
- show/hide hidden files as per context state in plugin based batch rename
|
||||
- retain search filter history for plugin `finder`
|
||||
- sync multiple instances of `nnn` after operation on selection
|
||||
- signal CWD change to terminal via OSC-7 (#1147)
|
||||
- save complete per-context filter when saving sessions
|
||||
- disable symlink resolution for paths in `NNN_BMS` and arg `PATH`
|
||||
- do not end selection mode on running plugins/prompt/shell
|
||||
- plugin `bookmarks` replaced by symlinked bookmarks support
|
||||
- list open locations in active contexts in help page
|
||||
- make option `O_MATCHFLTR` to discard filter key if no match
|
||||
- configurable `NNN_TMPFILE` to _cd on quit_
|
||||
- disable auto marking directories (use <kbd>-</kbd>)
|
||||
- picker mode improvements
|
||||
- open tty for input if `STDIN` is non-tty
|
||||
- truncate output file before writing
|
||||
- do not double select a file on <kbd>Enter</kbd>
|
||||
- legacy macOS (< 10.12.0) support
|
||||
- no redraw during du calculation, show processed dir name
|
||||
- plugin `xdgdefault`: add dmenu support
|
||||
- user patch `restorepreview`: close/restore `preview-tui` for internal edits
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
nnn v4.2 Mojito
|
||||
2021-07-21
|
||||
|
||||
- `NNN_PLUG` indicator symbol interpretation has **changed**:
|
||||
- `!` - _run-cmd-as-plugin_ (earlier `_`)
|
||||
- `&` - _run-gui-cmd-as-plugin_ (earlier `|`)
|
||||
- `|` (new) - page noninteractive _run-cmd-as-plugin_ output
|
||||
- persistent selection markers (#1086)
|
||||
- option _extract to..._ for archives
|
||||
- mount remote and mount/extract archive to a smart context
|
||||
- confirm file trashing to avoid accidental press of <kbd>x</kbd> (#1101)
|
||||
- insert the last command executed at prompt on <kbd>Up</kbd> or <kbd>Down</kbd>
|
||||
- insert the current file name at empty prompt on <kbd>TAB</kbd>
|
||||
- handle redraw issue on missed `KEY_RESIZE` (#1067)
|
||||
- add force-tty capability to spawn and set pagers to it (#1064)
|
||||
- clear selection mode on deselecting last selected file (#1098)
|
||||
- remove selected hovered entry from selection on deletion
|
||||
- disable filtering in empty directories
|
||||
- ignore last pressed filter character when no matches
|
||||
- fix broken screen on resize while paging (#1072)
|
||||
- fix archive not hovered on creation
|
||||
- remove libgit2 dependency in `gitstatus` patch (#1095)
|
||||
- add `-G` flag for `gitstatus` patch
|
||||
- option `-X` for explorer (persistent picker) mode
|
||||
- option `-F` decommissioned in favour of config `NNN_HELP`
|
||||
- `-F` redefined to multiplex `NNN_FIFO` to preview or explore
|
||||
- support paging noninterative _run-cmd-as-plugin_ output
|
||||
- `nuke` - add option to execute binaries (#1111)
|
||||
- plugin `fzopen` - call `open` on macOS, add option to use `nuke`
|
||||
- plugin `fzcd` will not modify selection
|
||||
- plugin `suedit` - preserve environment
|
||||
- several `preview-tui` fixes
|
||||
- plugin `wall` renamed to `wallpaper`
|
||||
- remove plugin `fzz` - merged into plugin `autojump`
|
||||
- remove plugin `upgrade` - packaging is on OBS now
|
||||
- remove plugin `treeview` - needs minor `preview-tui` tweak
|
||||
- remove plugin `picker` - `nnn -p -` does the same
|
||||
- remove plugin `pdfview` - needs simple change in `pdfread`
|
||||
- remove plugin `uidgid` - use program option `-U`
|
||||
- remove plugins `mediainf`, `hexview` - simple one-liners
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
nnn v4.1.1 Sake
|
||||
2021-06-03
|
||||
|
||||
- fix segfault on session save (#1041)
|
||||
- remove redundant `_Atomic` usage
|
||||
- move [`patches`](../tree/master/patches) directory to top-level
|
||||
- fix and cleanup gitstatus patch
|
||||
- plugin `imgview` improvements (#1049)
|
||||
- restore source-code packing on CircleCI
|
||||
- add Makefile target to compile with musl
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
nnn v4.1
|
||||
2021-06-02
|
||||
|
||||
- a patch management model for approved patches
|
||||
- multi-threaded disk usage calculation using pthreads and FTS
|
||||
- dynamic view update when calculating disk usage
|
||||
- <kbd>Bksp</kbd>/<kbd>Del</kbd> at empty filter prompt to refresh dir
|
||||
- Try to create new context with <kbd>Shift-TAB</kbd>, else reverse cycle
|
||||
- <kbd>Alt+Esc</kbd> to quit context from filter prompt
|
||||
- fix zombies left behind after running plugins (#999)
|
||||
- named persistent sessions (mcchrish/nnn.vim#43)
|
||||
- consider nanosecond resolution when sorting by time (#978)
|
||||
- check external selection in `'c'urrent / 's'el` prompt (#976)
|
||||
- show number of files selected in local selection buffer, if any
|
||||
- `nnn` & picker plugin (e.g. `fzopen`) sync (mcchrish/nnn.vim#82)
|
||||
- make batch rename interactive (#971)
|
||||
- cached uid/gid for performance improvement
|
||||
- fixes for `nnn` with `netbsd-curses`, `musl-fts`, `musl` (#998)
|
||||
- script to statically compile `nnn` with `musl gcc` on Ubuntu
|
||||
- restore hovered file when plugin is chosen from plugin dir
|
||||
- support QuickLook on WSL in `preview-tui` (#959)
|
||||
- toggle `preview-tui` with the same _custom_ plugin key
|
||||
- smoother preview toggling in `preview-tui` (#966)
|
||||
- `listen_on` should be set in kitty.conf for `preview-tui` (#970)
|
||||
- minimal `bat` style in `preview-tui`, honors `$BAT_STYLE`
|
||||
- plugin `preview-tui-ext` supersedes `preview-tui` (#1033)
|
||||
- plugin `fzcd` can now fuzzy search multiple directories
|
||||
- plugin `imgview` supersedes `imgthumb` and `vidthumb`
|
||||
- plugin `umounttree`: unmount remote mntpoint from within
|
||||
- plugin `xdgdefault`: set the default app for hovered file type
|
||||
- plugin `fzplug`: fuzzy find, preview and run other plugins
|
||||
- plugin `cmusq`: queue/play music in `cmus`
|
||||
- plugin `mocplay` renamed to `mocq`
|
||||
- plugin `cleanfilename` renamed to `fixname`
|
||||
- go to last dir on <kbd>~</kbd> (HOME) or <kbd>`</kbd> (ROOT) key repeat
|
||||
- ambiguous key <kbd>^Space</kbd> to select/clear range dropped (#998)
|
||||
- user wiki page for [Themes](https://github.com/jarun/nnn/wiki/Themes)
|
||||
- show selection mark (`+`) in reverse bold for improved visibility
|
||||
- reverse block replaces `>` to mark hovered entry in detail mode
|
||||
- make option `O_CKBOARD` removed
|
||||
- make option `O_NOLOC` renamed to `O_NOLC`
|
||||
- ignore `O_NOLC` if `O_ICONS` or `O_NERD` is specified (#1026)
|
||||
- unicode arrow indicators if `O_ICONS` or `O_NERD` is specified
|
||||
- make option `NOX11`: disable notis, sel-clipboard sync, xterm title
|
||||
- retain filter in _nav-to-type_ mode after file open
|
||||
- fix no files picked with `NNN_TMPFILE` exported and <kbd>q</kbd> to quit
|
||||
- disable xterm title setting in picker mode (#974)
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
nnn v4.0 Sushi
|
||||
2021-04-13
|
||||
|
||||
- show xterm title on option `-x`
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
nnn v3.7
|
||||
2021-04-13
|
||||
|
||||
- allow plugins to clear selection (#884, #889, #917)
|
||||
- do not clear selection on hovered file deletion
|
||||
- resurrect `'c'urrent/'s'el` prompt and option `-u` (#889)
|
||||
- show only file name in reverse in detail mode
|
||||
- more file/mime types supported in `preview-tui-ext`
|
||||
- plugin `mtpmount` - (un)mount MTP devices
|
||||
- plugin `cleanfilename` - more shell-friendly file names
|
||||
- plugin `rsynccp` - copy-paste with visual progress
|
||||
- replace `$HOME` by `~` in address bar
|
||||
- show current path in terminal title (#911)
|
||||
- total links and inode number of hardlink in statusbar
|
||||
- fix symlink to text file not opening in CLI editor (#890)
|
||||
- fix symlink size shown as 0B in statusbar (#888)
|
||||
- show symlink target in statusbar (#893)
|
||||
- show correct disk free/total on macOS (#888)
|
||||
- fix directory disk usage showing as 0 on macOS (#941)
|
||||
- fix name col len with `-C` and icons compiled-in (#936)
|
||||
- refactor printing entries in light/detail modes (#934)
|
||||
- make option `O_CKBOARD` for checker board as indicator
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
nnn v3.6 Nina
|
||||
2021-03-16
|
||||
|
||||
|
@ -186,7 +513,7 @@ nnn v3.1
|
|||
- hover and connect by dir name (within config dir)
|
||||
- move to next entry on current file delete
|
||||
- on single file copy/move, select the copied/moved file
|
||||
- option `-f` to to use readline history file (off by default)
|
||||
- option `-f` to use readline history file (off by default)
|
||||
- use `s` in status bar to indicate selection in progress
|
||||
- make var `O_NOMOUSE` to disable mouse support
|
||||
- do not store `NNN_TRASH` and `-Q` in config/session
|
||||
|
|
2
LICENSE
2
LICENSE
|
@ -2,7 +2,7 @@ BSD 2-Clause License
|
|||
|
||||
Copyright (c) 2014-2016, Lazaros Koromilas <lostd@2f30.org>
|
||||
Copyright (c) 2014-2016, Dimitris Papastamos <sin@2f30.org>
|
||||
Copyright (c) 2016-2021, Arun Prakash Jana <engineerarun@gmail.com>
|
||||
Copyright (c) 2016-2023, Arun Prakash Jana <engineerarun@gmail.com>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
186
Makefile
186
Makefile
|
@ -14,17 +14,29 @@ CFLAGS_OPTIMIZATION ?= -O3
|
|||
O_DEBUG := 0 # debug binary
|
||||
O_NORL := 0 # no readline support
|
||||
O_PCRE := 0 # link with PCRE library
|
||||
O_NOLOC := 0 # no locale support
|
||||
O_NOLC := 0 # no locale support
|
||||
O_NOMOUSE := 0 # no mouse support
|
||||
O_NOBATCH := 0 # no built-in batch renamer
|
||||
O_NOFIFO := 0 # no FIFO previewer support
|
||||
O_CTX8 := 0 # enable 8 contexts
|
||||
O_ICONS := 0 # support icons-in-terminal
|
||||
O_NERD := 0 # support icons-nerdfont
|
||||
O_EMOJI := 0 # support emoji
|
||||
O_QSORT := 0 # use Alexey Tourbin's QSORT implementation
|
||||
O_BENCH := 0 # benchmark mode (stops at first user input)
|
||||
O_NOSSN := 0 # enable session support
|
||||
O_NOSSN := 0 # disable session support
|
||||
O_NOUG := 0 # disable user, group name in status bar
|
||||
O_NOX11 := 0 # disable X11 integration
|
||||
O_MATCHFLTR := 0 # allow filters without matches
|
||||
O_NOSORT := 0 # disable sorting entries on dir load
|
||||
|
||||
# User patches
|
||||
O_COLEMAK := 0 # change key bindings to colemak compatible layout
|
||||
O_GITSTATUS := 0 # add git status to detail view
|
||||
O_NAMEFIRST := 0 # print file name first, add uid and guid to detail view
|
||||
O_RESTOREPREVIEW := 0 # add preview pipe to close and restore preview pane
|
||||
|
||||
T_ICONS := 0 # test if multiple icons options are set and fail
|
||||
|
||||
# convert targets to flags for backwards compatibility
|
||||
ifneq ($(filter debug,$(MAKECMDGOALS)),)
|
||||
|
@ -33,14 +45,14 @@ endif
|
|||
ifneq ($(filter norl,$(MAKECMDGOALS)),)
|
||||
O_NORL := 1
|
||||
endif
|
||||
ifneq ($(filter noloc,$(MAKECMDGOALS)),)
|
||||
ifneq ($(filter nolc,$(MAKECMDGOALS)),)
|
||||
O_NORL := 1
|
||||
O_NOLOC := 1
|
||||
O_NOLC := 1
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(O_DEBUG)),1)
|
||||
CPPFLAGS += -DDBGMODE
|
||||
CFLAGS += -g
|
||||
CPPFLAGS += -DDEBUG
|
||||
CFLAGS += -g3
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(O_NORL)),1)
|
||||
|
@ -56,8 +68,16 @@ ifeq ($(strip $(O_PCRE)),1)
|
|||
LDLIBS += -lpcre
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(O_NOLOC)),1)
|
||||
CPPFLAGS += -DNOLOCALE
|
||||
ifeq ($(strip $(O_NOLC)),1)
|
||||
ifeq ($(strip $(O_ICONS)),1)
|
||||
$(info *** Ignoring O_NOLC since O_ICONS is set ***)
|
||||
else ifeq ($(strip $(O_NERD)),1)
|
||||
$(info *** Ignoring O_NOLC since O_NERD is set ***)
|
||||
else ifeq ($(strip $(O_EMOJI)),1)
|
||||
$(info *** Ignoring O_NOLC since O_EMOJI is set ***)
|
||||
else
|
||||
CPPFLAGS += -DNOLC
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(O_NOMOUSE)),1)
|
||||
|
@ -77,11 +97,30 @@ ifeq ($(strip $(O_CTX8)),1)
|
|||
endif
|
||||
|
||||
ifeq ($(strip $(O_ICONS)),1)
|
||||
CPPFLAGS += -DICONS
|
||||
ICONS_INCLUDE = icons-generated-icons-in-term.h
|
||||
CPPFLAGS += -DICONS_IN_TERM -DICONS_INCLUDE=\"$(ICONS_INCLUDE)\"
|
||||
ifeq ($(strip $(T_ICONS)),1)
|
||||
$(error Choose only one system for icons (O_ICONS, O_NERD or O_EMOJI))
|
||||
endif
|
||||
T_ICONS := 1
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(O_NERD)),1)
|
||||
CPPFLAGS += -DNERD
|
||||
ICONS_INCLUDE = icons-generated-nerd.h
|
||||
CPPFLAGS += -DNERD -DICONS_INCLUDE=\"$(ICONS_INCLUDE)\"
|
||||
ifeq ($(strip $(T_ICONS)),1)
|
||||
$(error Choose only one system for icons (O_ICONS, O_NERD or O_EMOJI))
|
||||
endif
|
||||
T_ICONS := 1
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(O_EMOJI)),1)
|
||||
ICONS_INCLUDE = icons-generated-emoji.h
|
||||
CPPFLAGS += -DEMOJI -DICONS_INCLUDE=\"$(ICONS_INCLUDE)\"
|
||||
ifeq ($(strip $(T_ICONS)),1)
|
||||
$(error Choose only one system for icons (O_ICONS, O_NERD or O_EMOJI))
|
||||
endif
|
||||
T_ICONS := 1
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(O_QSORT)),1)
|
||||
|
@ -100,6 +139,18 @@ ifeq ($(strip $(O_NOUG)),1)
|
|||
CPPFLAGS += -DNOUG
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(O_NOX11)),1)
|
||||
CPPFLAGS += -DNOX11
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(O_MATCHFLTR)),1)
|
||||
CPPFLAGS += -DMATCHFLTR
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(O_NOSORT)),1)
|
||||
CPPFLAGS += -DNOSORT
|
||||
endif
|
||||
|
||||
ifeq ($(shell $(PKG_CONFIG) ncursesw && echo 1),1)
|
||||
CFLAGS_CURSES ?= $(shell $(PKG_CONFIG) --cflags ncursesw)
|
||||
LDLIBS_CURSES ?= $(shell $(PKG_CONFIG) --libs ncursesw)
|
||||
|
@ -114,7 +165,7 @@ CFLAGS += -std=c11 -Wall -Wextra -Wshadow
|
|||
CFLAGS += $(CFLAGS_OPTIMIZATION)
|
||||
CFLAGS += $(CFLAGS_CURSES)
|
||||
|
||||
LDLIBS += $(LDLIBS_CURSES)
|
||||
LDLIBS += $(LDLIBS_CURSES) -lpthread
|
||||
|
||||
# static compilation needs libgpm development package
|
||||
ifeq ($(strip $(O_STATIC)),1)
|
||||
|
@ -130,15 +181,57 @@ DESKTOPFILE = misc/desktop/nnn.desktop
|
|||
LOGOSVG = misc/logo/logo.svg
|
||||
LOGO64X64 = misc/logo/logo-64x64.png
|
||||
|
||||
COLEMAK = patches/colemak
|
||||
GITSTATUS = patches/gitstatus
|
||||
NAMEFIRST = patches/namefirst
|
||||
RESTOREPREVIEW = patches/restorepreview
|
||||
|
||||
# test if we are on Mac OS X and get X.Y.Z OS version with system binary /usr/bin/sw_vers
|
||||
MACOS_VERSION := $(strip $(shell command -v sw_vers >/dev/null && [ "`sw_vers -productName`" = "Mac OS X" ] && sw_vers -productVersion))
|
||||
# if Mac OS X detected, test if its version is below 10.12.0 relying on "sort -c" returning "disorder" message if the input is not sorted
|
||||
ifneq ($(MACOS_VERSION),)
|
||||
MACOS_BELOW_1012 := $(if $(strip $(shell printf '10.12.0\n%s' "$(MACOS_VERSION)" | sort -ct. -k1,1n -k2,2n -k3,3n 2>&1)),1)
|
||||
endif
|
||||
# if Mac OS X version is below 10.12.0, compile in the replacement clock_gettime and define MACOS_BELOW_1012 so that it's included in nnn.c
|
||||
ifneq ($(MACOS_BELOW_1012),)
|
||||
GETTIME_C = misc/macos-legacy/mach_gettime.c
|
||||
GETTIME_H = misc/macos-legacy/mach_gettime.h
|
||||
SRC += $(GETTIME_C)
|
||||
HEADERS += $(GETTIME_H)
|
||||
CPPFLAGS += -DMACOS_BELOW_1012
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(O_DEBUG)),1)
|
||||
HEADERS += src/dbg.h
|
||||
endif
|
||||
ifeq ($(strip $(O_QSORT)),1)
|
||||
HEADERS += src/qsort.h
|
||||
endif
|
||||
ifeq ($(strip $(O_EMOJI)),1)
|
||||
HEADERS += src/icons.h src/$(ICONS_INCLUDE)
|
||||
endif
|
||||
ifeq ($(strip $(O_NERD)),1)
|
||||
HEADERS += src/icons.h src/$(ICONS_INCLUDE)
|
||||
endif
|
||||
ifeq ($(strip $(O_ICONS)),1)
|
||||
HEADERS += src/icons.h src/$(ICONS_INCLUDE) src/icons-in-terminal.h
|
||||
endif
|
||||
|
||||
all: $(BIN)
|
||||
|
||||
$(BIN): $(SRC) $(HEADERS)
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LDLIBS)
|
||||
$(BIN): $(SRC) $(HEADERS) Makefile
|
||||
@$(MAKE) --silent prepatch
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $(GETTIME_C) $< $(LDLIBS)
|
||||
@$(MAKE) --silent postpatch
|
||||
|
||||
# targets for backwards compatibility
|
||||
debug: $(BIN)
|
||||
norl: $(BIN)
|
||||
noloc: $(BIN)
|
||||
nolc: $(BIN)
|
||||
|
||||
src/$(ICONS_INCLUDE): src/icons-hash.c src/icons.h src/icons-in-terminal.h
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -DICONS_GENERATE -o src/icons-hash-gen src/icons-hash.c
|
||||
./src/icons-hash-gen > $@
|
||||
|
||||
install-desktop: $(DESKTOPFILE)
|
||||
$(INSTALL) -m 0755 -d $(DESTDIR)$(DESKTOPPREFIX)
|
||||
|
@ -180,6 +273,17 @@ static:
|
|||
# static binary with patched nerd font support
|
||||
make O_STATIC=1 O_NERD=1 strip
|
||||
mv $(BIN) $(BIN)-nerd-static
|
||||
# static binary with emoji support
|
||||
make O_STATIC=1 O_EMOJI=1 strip
|
||||
mv $(BIN) $(BIN)-emoji-static
|
||||
|
||||
musl:
|
||||
cp misc/musl/musl-static-ubuntu.sh .
|
||||
./musl-static-ubuntu.sh 1
|
||||
rm ./musl-static-ubuntu.sh
|
||||
|
||||
shellcheck:
|
||||
find ./plugins/ -type f -not -name "*.md" -exec shellcheck {} +
|
||||
|
||||
dist:
|
||||
mkdir -p nnn-$(VERSION)
|
||||
|
@ -192,23 +296,24 @@ sign:
|
|||
gpg --detach-sign --yes nnn-$(VERSION).tar.gz
|
||||
rm -f nnn-$(VERSION).tar.gz
|
||||
|
||||
upload-local: sign static
|
||||
upload-local: sign static musl
|
||||
$(eval ID=$(shell curl -s 'https://api.github.com/repos/jarun/nnn/releases/tags/v$(VERSION)' | jq .id))
|
||||
# upload sign file
|
||||
curl -XPOST 'https://uploads.github.com/repos/jarun/nnn/releases/$(ID)/assets?name=nnn-$(VERSION).tar.gz.sig' \
|
||||
-H 'Authorization: token $(NNN_SIG_UPLOAD_TOKEN)' -H 'Content-Type: application/pgp-signature' \
|
||||
--upload-file nnn-$(VERSION).tar.gz.sig
|
||||
tar -zcf $(BIN)-static-$(VERSION).x86_64.tar.gz $(BIN)-static
|
||||
# upx compress all static binaries
|
||||
upx -qqq $(BIN)-static
|
||||
upx -qqq $(BIN)-icons-static
|
||||
upx -qqq $(BIN)-nerd-static
|
||||
upx -qqq $(BIN)-emoji-static
|
||||
# upload static binary
|
||||
tar -zcf $(BIN)-static-$(VERSION).x86_64.tar.gz $(BIN)-static
|
||||
curl -XPOST 'https://uploads.github.com/repos/jarun/nnn/releases/$(ID)/assets?name=$(BIN)-static-$(VERSION).x86_64.tar.gz' \
|
||||
-H 'Authorization: token $(NNN_SIG_UPLOAD_TOKEN)' -H 'Content-Type: application/x-sharedlib' \
|
||||
--upload-file $(BIN)-static-$(VERSION).x86_64.tar.gz
|
||||
tar -zcf $(BIN)-icons-static-$(VERSION).x86_64.tar.gz $(BIN)-icons-static
|
||||
# upload icons-in-terminal compiled static binary
|
||||
tar -zcf $(BIN)-icons-static-$(VERSION).x86_64.tar.gz $(BIN)-icons-static
|
||||
curl -XPOST 'https://uploads.github.com/repos/jarun/nnn/releases/$(ID)/assets?name=$(BIN)-icons-static-$(VERSION).x86_64.tar.gz' \
|
||||
-H 'Authorization: token $(NNN_SIG_UPLOAD_TOKEN)' -H 'Content-Type: application/x-sharedlib' \
|
||||
--upload-file $(BIN)-icons-static-$(VERSION).x86_64.tar.gz
|
||||
|
@ -217,9 +322,54 @@ upload-local: sign static
|
|||
curl -XPOST 'https://uploads.github.com/repos/jarun/nnn/releases/$(ID)/assets?name=$(BIN)-nerd-static-$(VERSION).x86_64.tar.gz' \
|
||||
-H 'Authorization: token $(NNN_SIG_UPLOAD_TOKEN)' -H 'Content-Type: application/x-sharedlib' \
|
||||
--upload-file $(BIN)-nerd-static-$(VERSION).x86_64.tar.gz
|
||||
# upload emoji compiled static binary
|
||||
tar -zcf $(BIN)-emoji-static-$(VERSION).x86_64.tar.gz $(BIN)-emoji-static
|
||||
curl -XPOST 'https://uploads.github.com/repos/jarun/nnn/releases/$(ID)/assets?name=$(BIN)-emoji-static-$(VERSION).x86_64.tar.gz' \
|
||||
-H 'Authorization: token $(NNN_SIG_UPLOAD_TOKEN)' -H 'Content-Type: application/x-sharedlib' \
|
||||
--upload-file $(BIN)-emoji-static-$(VERSION).x86_64.tar.gz
|
||||
# upload musl static binary
|
||||
tar -zcf $(BIN)-musl-static-$(VERSION).x86_64.tar.gz $(BIN)-musl-static
|
||||
curl -XPOST 'https://uploads.github.com/repos/jarun/nnn/releases/$(ID)/assets?name=$(BIN)-musl-static-$(VERSION).x86_64.tar.gz' \
|
||||
-H 'Authorization: token $(NNN_SIG_UPLOAD_TOKEN)' -H 'Content-Type: application/x-sharedlib' \
|
||||
--upload-file $(BIN)-musl-static-$(VERSION).x86_64.tar.gz
|
||||
|
||||
clean:
|
||||
$(RM) -f $(BIN) nnn-$(VERSION).tar.gz *.sig $(BIN)-static $(BIN)-static-$(VERSION).x86_64.tar.gz $(BIN)-icons-static $(BIN)-icons-static-$(VERSION).x86_64.tar.gz $(BIN)-nerd-static $(BIN)-nerd-static-$(VERSION).x86_64.tar.gz
|
||||
$(RM) -f $(BIN) nnn-$(VERSION).tar.gz *.sig $(BIN)-static $(BIN)-static-$(VERSION).x86_64.tar.gz $(BIN)-icons-static $(BIN)-icons-static-$(VERSION).x86_64.tar.gz $(BIN)-nerd-static $(BIN)-nerd-static-$(VERSION).x86_64.tar.gz $(BIN)-emoji-static $(BIN)-emoji-static-$(VERSION).x86_64.tar.gz $(BIN)-musl-static $(BIN)-musl-static-$(VERSION).x86_64.tar.gz src/icons-hash-gen src/icons-generated-*.h
|
||||
|
||||
checkpatches:
|
||||
./patches/check-patches.sh
|
||||
|
||||
prepatch:
|
||||
ifeq ($(strip $(O_NAMEFIRST)),1)
|
||||
patch --forward $(PATCH_OPTS) --strip=1 --input=$(NAMEFIRST)/mainline.diff
|
||||
ifeq ($(strip $(O_GITSTATUS)),1)
|
||||
patch --forward $(PATCH_OPTS) --strip=1 --input=$(GITSTATUS)/namefirst.diff
|
||||
endif
|
||||
else ifeq ($(strip $(O_GITSTATUS)),1)
|
||||
patch --forward $(PATCH_OPTS) --strip=1 --input=$(GITSTATUS)/mainline.diff
|
||||
endif
|
||||
ifeq ($(strip $(O_RESTOREPREVIEW)),1)
|
||||
patch --forward $(PATCH_OPTS) --strip=1 --input=$(RESTOREPREVIEW)/mainline.diff
|
||||
endif
|
||||
ifeq ($(strip $(O_COLEMAK)),1)
|
||||
patch --forward $(PATCH_OPTS) --strip=1 --input=$(COLEMAK)/mainline.diff
|
||||
endif
|
||||
|
||||
postpatch:
|
||||
ifeq ($(strip $(O_NAMEFIRST)),1)
|
||||
ifeq ($(strip $(O_GITSTATUS)),1)
|
||||
patch --reverse $(PATCH_OPTS) --strip=1 --input=$(GITSTATUS)/namefirst.diff
|
||||
endif
|
||||
patch --reverse $(PATCH_OPTS) --strip=1 --input=$(NAMEFIRST)/mainline.diff
|
||||
else ifeq ($(strip $(O_GITSTATUS)),1)
|
||||
patch --reverse $(PATCH_OPTS) --strip=1 --input=$(GITSTATUS)/mainline.diff
|
||||
endif
|
||||
ifeq ($(strip $(O_RESTOREPREVIEW)),1)
|
||||
patch --reverse $(PATCH_OPTS) --strip=1 --input=$(RESTOREPREVIEW)/mainline.diff
|
||||
endif
|
||||
ifeq ($(strip $(O_COLEMAK)),1)
|
||||
patch --reverse $(PATCH_OPTS) --strip=1 --input=$(COLEMAK)/mainline.diff
|
||||
endif
|
||||
|
||||
skip: ;
|
||||
|
||||
|
|
125
README.md
125
README.md
|
@ -9,67 +9,32 @@
|
|||
<a href="https://github.com/jarun/nnn/blob/master/LICENSE"><img src="https://img.shields.io/badge/©-BSD%202--Clause-important.svg?maxAge=2592000" alt="License" /></a>
|
||||
</p>
|
||||
|
||||
<p align="center"><a href="https://asciinema.org/a/353811"><img src="https://i.imgur.com/InHB5DB.png" /></a></p>
|
||||
<p align="center"><i>icons and colors asciicast</i></p>
|
||||
<p align="center"><a href="http://i.imgur.com/kOld6HT.gif"><img src="https://i.imgur.com/NUsSA2u.jpg"></a></p>
|
||||
|
||||
<h3 align="center">[<a
|
||||
href="https://github.com/jarun/nnn#features">Features</a>] [<a
|
||||
href="https://github.com/jarun/nnn#quickstart">Quickstart</a>] [<a
|
||||
href="https://github.com/jarun/nnn/tree/master/plugins#nnn-plugins">Plugins</a>] [<a
|
||||
href="https://github.com/jarun/nnn/wiki">Documentation</a>]</h3>
|
||||
href="https://github.com/jarun/nnn/wiki">Wiki</a>]</h3>
|
||||
|
||||
<br>
|
||||
|
||||
[![](https://user-images.githubusercontent.com/324519/94587860-062d7a80-0238-11eb-99b1-a9c9f0c32ac2.png)](https://www.youtube.com/embed/-knZwdd1ScU)
|
||||
|
||||
<br>
|
||||
|
||||
`nnn` (_n³_) is a full-featured terminal file manager. It's tiny and nearly 0-config with an [incredible speed](https://github.com/jarun/nnn/wiki/Performance).
|
||||
`nnn` (_n³_) is a full-featured terminal file manager. It's tiny, nearly 0-config and [incredibly fast](https://github.com/jarun/nnn/wiki/Performance).
|
||||
|
||||
It is designed to be unobtrusive with smart workflows to match the trains of thought.
|
||||
|
||||
`nnn` can analyze disk usage, batch rename, launch apps and pick files. The plugin repository has tons of plugins and documentation to extend the capabilities further e.g. [preview](https://github.com/jarun/nnn/wiki/Live-previews), (un)mount disks, find & list, file/dir diff, upload files.
|
||||
`nnn` can analyze disk usage, batch rename, launch apps and pick files. The plugin repository has tons of plugins to extend the capabilities further e.g. [live previews](https://github.com/jarun/nnn/wiki/Live-previews), (un)mount disks, find & list, file/dir diff, upload files. A [patch framework](https://github.com/jarun/nnn/tree/master/patches) hosts sizable user-submitted patches which are subjective in nature.
|
||||
|
||||
There are 2 independent (neo)vim plugins - [nnn.vim](https://github.com/mcchrish/nnn.vim) and [vim-floaterm nnn wrapper](https://github.com/voldikss/vim-floaterm#nnn).
|
||||
Independent (neo)vim plugins - [nnn.vim](https://github.com/mcchrish/nnn.vim), [vim-floaterm nnn wrapper](https://github.com/voldikss/vim-floaterm#nnn) and [nnn.nvim](https://github.com/luukvbaal/nnn.nvim) (neovim exclusive).
|
||||
|
||||
It runs smoothly on the Pi, [Termux](https://www.youtube.com/embed/AbaauM7gUJw) (Android), Linux, macOS, BSD, Haiku, Cygwin, WSL, across DEs and GUI utilities or a strictly CLI environment.
|
||||
Runs on the Pi, [Termux](https://www.youtube.com/embed/AbaauM7gUJw) (Android), Linux, macOS, BSD, Haiku, Cygwin, WSL, across DEs or a strictly CLI env.
|
||||
|
||||
<details><summary><i><b>Expand</b></i> for some nnn magic! :dark_sunglasses:</summary><br><ul>
|
||||
<li>Instantly load, sort, filter thousands of files</li>
|
||||
<li>Type to navigate with automatic dir selection</li>
|
||||
<li>List input stream and pick entries to stdout or file</li>
|
||||
<li>find/fd/grep/ripgrep/fzf from nnn and list in nnn</li>
|
||||
<li> Never lose context - start where you quit</li>
|
||||
<li>Mount any cloud storage service in a few keypresses</li>
|
||||
<li>Select files from anywhere (not just a single dir)</li>
|
||||
<li>Unlimited bookmarks, plugins, cmds with custom hotkeys</li>
|
||||
<li>Write a plugin in any language you know</li>
|
||||
<li>Edit and preview markdown, man page, html</li>
|
||||
<li>Open a file and auto-advance to the next</li>
|
||||
<li>Filter filtered entries, export list of visible files</li>
|
||||
<li>Configure the middle mouse click to do anything</li>
|
||||
<li>Fuzzy search subtree and open a file (or its parent dir)</li>
|
||||
<li>Load four dirs with custom settings at once</li>
|
||||
<li>Notifications on cp, mv, rm completion</li>
|
||||
<li>Auto-sync selection to system clipboard</li>
|
||||
<li>Access selection from another instance of nnn</li>
|
||||
<li>Open text files detached in another pane/tab/window</li>
|
||||
<li>Mount and modify archives</li>
|
||||
<li>Create files/dirs/duplicates with parents (like <i>mkdir -p</i>)</li>
|
||||
<li>Toggle hidden with <kbd>.</kbd>, visit HOME with <kbd>~</kbd>, last dir with <kbd>-</kbd></li>
|
||||
<li>Mark a frequently visited dir at runtime</li>
|
||||
<li>Sort by modification, access and inode change time</li>
|
||||
<li>Compile out/in features with make variables</li>
|
||||
<li>Watch matrix text fly or read fortune messages</li>
|
||||
<li>Configure in 5 minutes!</li>
|
||||
</ul></details>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=RMLTQ76JSXJ4Q"><img src="https://img.shields.io/badge/donate-@PayPal-1eb0fc.svg" alt="Donate via PayPal!" /></a>
|
||||
</p>
|
||||
[_(there's more)_](https://github.com/jarun/nnn/wiki/Basic-use-cases#the_nnn-magic)
|
||||
|
||||
## Features
|
||||
|
||||
- Quality
|
||||
- Privacy-aware (no unconfirmed user data collection)
|
||||
- POSIX-compliant, follows Linux kernel coding style
|
||||
- Highly optimized, static analysis integrated code
|
||||
- Frugal
|
||||
- Typically needs less than 3.5MB resident memory
|
||||
- Works with 8 colors (and xterm 256 colors)
|
||||
|
@ -86,71 +51,72 @@ It runs smoothly on the Pi, [Termux](https://www.youtube.com/embed/AbaauM7gUJw)
|
|||
- No config file, minimal config with sensible defaults
|
||||
- Plugin to backup configuration
|
||||
- Widely available on many packagers
|
||||
- Touch enabled, comfortable on handhelds too!
|
||||
- Touch enabled, handheld-friendly shortcuts
|
||||
- Unicode support
|
||||
- Quality
|
||||
- Privacy-aware (no unconfirmed user data collection)
|
||||
- POSIX-compliant, follows Linux kernel coding style
|
||||
- Highly optimized, static analysis integrated code
|
||||
- Modes
|
||||
- Light (default), detail
|
||||
- Disk usage analyzer (block/apparent)
|
||||
- File picker, (neo)vim plugin
|
||||
- Navigation
|
||||
- *Type-to-nav* mode with dir auto-select
|
||||
- Filter with automatic dir entry on unique match
|
||||
- *Type-to-nav* (turbo navigation/always filter) mode
|
||||
- Contexts (_aka_ tabs/workspaces) with custom colors
|
||||
- Sessions, bookmarks with hotkeys; mark and visit a dir
|
||||
- Remote mounts (needs sshfs, rclone)
|
||||
- Sessions, bookmarks, mark and visit a dir
|
||||
- Remote mounts (needs `sshfs`, `rclone`)
|
||||
- Familiar shortcuts (arrows, <kbd>~</kbd>, <kbd>-</kbd>, <kbd>@</kbd>), quick look-up
|
||||
- CD on quit (*easy* shell integration)
|
||||
- Auto-advance on opening files
|
||||
- `cd` on quit (*easy* shell integration)
|
||||
- Proceed to next file on file open and selection
|
||||
- Search
|
||||
- Instant filtering with *search-as-you-type*
|
||||
- Regex (POSIX/PCRE) and string (default) filters
|
||||
- Subtree search plugin to open or edit files
|
||||
- Sort
|
||||
- Ordered pure numeric names by default (visit _/proc_)
|
||||
- Ordered pure numeric names by default (visit `/proc`)
|
||||
- Case-insensitive version (_aka_ natural) sort
|
||||
- By name, access/change/mod (default) time, size, extn
|
||||
- Reverse sort
|
||||
- Directory-specific ordering
|
||||
- Mimes
|
||||
- Preview hovered files in FIFO-based previewer
|
||||
- Open with desktop opener or specify a custom opener
|
||||
- File-specific colors (or minimal _dirs in context color_)
|
||||
- Icons (customize and compile-in)
|
||||
- Plugins for image and video thumbnails
|
||||
- Create, list, extract, mount (FUSE based) archives
|
||||
- Option to open all text files in EDITOR
|
||||
- Information
|
||||
- Detailed file information
|
||||
- Media information plugin
|
||||
- Icons and Emojis support (customize and compile-in)
|
||||
- Plugin for image, video and audio thumbnails
|
||||
- Create, list, extract (to), mount (FUSE based) archives
|
||||
- Option to open all text files in `$EDITOR`
|
||||
- Convenience
|
||||
- Detailed file stats and mime information
|
||||
- Run plugins and custom commands with hotkeys
|
||||
- FreeDesktop compliant trash (needs trash-cli)
|
||||
- FreeDesktop compliant trash utility integration
|
||||
- Cross-dir file/all/range selection
|
||||
- Create (with parents), rename, duplicate files and dirs
|
||||
- Create new file or directory (tree) on startup
|
||||
- Batch renamer for selection or dir
|
||||
- List input stream of file paths from stdin or plugin
|
||||
- Copy (as), move (as), delete, archive, link selection
|
||||
- Dir updates, notification on cp, mv, rm completion
|
||||
- Dir updates, notification on `cp`, `mv`, `rm` completion
|
||||
- Copy file paths to system clipboard on select
|
||||
- Launch apps, run commands, spawn a shell, toggle exe
|
||||
- Access hovered file as `$nnn` at prompt or spawned shell
|
||||
- Access context paths/files at prompt or spawned shell
|
||||
- Lock terminal after configurable idle timeout
|
||||
- Capture and show output of a program in help screen
|
||||
- Basic support for screen readers and braille displays
|
||||
|
||||
## Quickstart
|
||||
|
||||
1. [Install](https://github.com/jarun/nnn/wiki/Usage) `nnn` and any dependencies you need. All files are opened with the desktop opener by default.
|
||||
2. Add option `-e` to your alias to open text files in `$VISUAL`/`$EDITOR`/ vi. [Open detached](https://github.com/jarun/nnn/wiki/Basic-use-cases#detached-text) if you wish.
|
||||
3. Configure [cd on quit](https://github.com/jarun/nnn/wiki/Basic-use-cases#configure-cd-on-quit).
|
||||
1. [Install](https://github.com/jarun/nnn/wiki/Usage) `nnn` and the dependencies you need.
|
||||
2. The desktop opener is default. Use `-e` to open text files in the terminal. Optionally [open detached](https://github.com/jarun/nnn/wiki/Basic-use-cases#detached-text).
|
||||
3. Configure [`cd` on quit](https://github.com/jarun/nnn/wiki/Basic-use-cases#configure-cd-on-quit).
|
||||
4. [Sync subshell `$PWD`](https://github.com/jarun/nnn/wiki/Basic-use-cases#sync-subshell-pwd) to `nnn`.
|
||||
5. [Install plugins](https://github.com/jarun/nnn/tree/master/plugins#installation).
|
||||
6. Use option `-x` to copy selected file paths to system clipboard and show notis on cp, mv, rm completion.
|
||||
7. For a CLI-only environment, customize and use plugin [`nuke`](https://github.com/jarun/nnn/blob/master/plugins/nuke) with option `-c` (overrides `-e`).
|
||||
8. Bid _ls_ goodbye! `alias ls='nnn -de'` :sunglasses:
|
||||
6. Use `-x` to sync selection to clipboard, show notis on `cp`, `mv`, `rm` and set xterm title.
|
||||
7. For a CLI-only environment, set [`NNN_OPENER`](https://github.com/jarun/nnn/wiki/Usage#configuration) to [`nuke`](https://github.com/jarun/nnn/blob/master/plugins/nuke). Use option `-c`.
|
||||
8. Bid `ls` goodbye! `alias ls='nnn -de'` :sunglasses:
|
||||
9. Visit the [Live previews](https://github.com/jarun/nnn/wiki/Live-previews) and [Troubleshooting](https://github.com/jarun/nnn/wiki/Troubleshooting) Wiki pages.
|
||||
|
||||
Don't memorize! Arrows (or <kbd>h</kbd> <kbd>j</kbd> <kbd>k</kbd> <kbd>l</kbd>), <kbd>/</kbd>, <kbd>q</kbd> suffice. <kbd>Tab</kbd> creates, cycles contexts. <kbd>?</kbd> lists shortcuts.
|
||||
Don't memorize! Arrows, <kbd>/</kbd>, <kbd>q</kbd> suffice. <kbd>Tab</kbd> creates and/or cycles contexts. <kbd>?</kbd> lists shortcuts.
|
||||
|
||||
[![](https://i.imgur.com/TN3xYQz.jpg)](https://www.youtube.com/embed/-knZwdd1ScU)
|
||||
|
||||
[![Wiki](https://img.shields.io/badge/RTFM-nnn%20Wiki-important?maxAge=2592000)](https://github.com/jarun/nnn/wiki)
|
||||
|
||||
|
@ -176,7 +142,9 @@ Don't memorize! Arrows (or <kbd>h</kbd> <kbd>j</kbd> <kbd>k</kbd> <kbd>l</kbd>),
|
|||
- LinuxLinks [[1](https://www.linuxlinks.com/nnn-fast-and-flexible-file-manager/)] [[2](https://www.linuxlinks.com/bestconsolefilemanagers/)] [[3](https://www.linuxlinks.com/excellent-system-tools-nnn-portable-terminal-file-manager/)]
|
||||
- [Linux Magazine; FOSSPicks](https://www.linux-magazine.com/Issues/2017/205/FOSSPicks/(offset)/15)
|
||||
- [Make Tech Easier](https://www.maketecheasier.com/nnn-file-manager-terminal/)
|
||||
- [Opensource.com](https://opensource.com/article/22/12/linux-file-manager-nnn)
|
||||
- [Open Source For You](https://www.opensourceforu.com/2019/12/nnn-this-feature-rich-terminal-file-manager-will-enhance-your-productivity/)
|
||||
- [PCLinuxOS Magazine Issue June 2021](https://pclosmag.com/html/Issues/202106/page08.html)
|
||||
- [Suckless Rocks](https://suckless.org/rocks/)
|
||||
- [Ubuntu Full Circle Magazine Issue 135; Review: nnn](https://fullcirclemagazine.org/issue-135/)
|
||||
- [Using and Administering Linux: Volume 2: Zero to SysAdmin: Advanced Topics](https://books.google.com/books?id=MqjDDwAAQBAJ&pg=PA32)
|
||||
|
@ -184,13 +152,14 @@ Don't memorize! Arrows (or <kbd>h</kbd> <kbd>j</kbd> <kbd>k</kbd> <kbd>l</kbd>),
|
|||
|
||||
## Developers
|
||||
|
||||
- [Arun Prakash Jana](https://github.com/jarun) (Copyright © 2016-2021)
|
||||
- [Arun Prakash Jana](https://github.com/jarun) (Copyright © 2016-2023)
|
||||
- [0xACE](https://github.com/0xACE)
|
||||
- [Anna Arad](https://github.com/annagrram)
|
||||
- [KlzXS](https://github.com/KlzXS)
|
||||
- [Léo Villeveygoux](https://github.com/leovilok)
|
||||
- [Maxim Baz](https://github.com/maximbaz)
|
||||
- [Todd Yamakawa](https://github.com/toddyamakawa)
|
||||
- [Luuk van Baal](https://github.com/luukvbaal)
|
||||
- [NRK](https://codeberg.org/NRK)
|
||||
- [Sijmen J. Mulder](https://github.com/sjmulder)
|
||||
- and other contributors
|
||||
|
||||
Visit the [ToDo list](https://github.com/jarun/nnn/issues/881) to contribute or see the features in progress.
|
||||
Visit the [Tracker](https://github.com/jarun/nnn/issues/1546) thread for a list of features in progress and anything up for grabs. Feel free to [discuss](https://github.com/jarun/nnn/discussions) new ideas or enhancement requests.
|
||||
|
|
|
@ -1,12 +1,19 @@
|
|||
# Contributing
|
||||
Contributions to nnn are welcome! There's always an open issue with the current ToDo list, which contains the proposed features for the next release you can get your hands on. Any small changes or ideas should go in there, rather than in a separate issue.
|
||||
|
||||
Before suggesting changes, please read a bit about [the design principles nnn follows](https://github.com/jarun/nnn/wiki#design), and make sure you aren't breaking any of them.
|
||||
Before suggesting changes, please read a bit about [the design principles nnn follows](https://github.com/jarun/nnn/wiki/concepts#design), and make sure you aren't breaking any of them.
|
||||
|
||||
Feel free to join the [Discussions](https://github.com/jarun/nnn/discussions). We highly recommended a discussion before raising a PR.
|
||||
|
||||
## Coding standard
|
||||
|
||||
`nnn` follows the Linux kernel coding style closely. The C source code uses TABs and the plugins use 4 spaces for indentation.
|
||||
|
||||
- Code changes should not break the patch framework. Please run `make checkpatches` to ensure.
|
||||
- Run `make shellcheck` if adding/modifying plugins.
|
||||
|
||||
CI runs patch framework sanity test and `shellcheck`. Please watch out for any failures after raising the PR.
|
||||
|
||||
## Resources
|
||||
The [wiki](https://github.com/jarun/nnn/wiki/Developer-guides) has some resources for developers you might be interested in: building, debugging...
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ _nnn ()
|
|||
-a
|
||||
-A
|
||||
-b
|
||||
-B
|
||||
-c
|
||||
-C
|
||||
-d
|
||||
|
@ -22,9 +23,9 @@ _nnn ()
|
|||
-e
|
||||
-E
|
||||
-f
|
||||
-F
|
||||
-g
|
||||
-H
|
||||
-i
|
||||
-J
|
||||
-K
|
||||
-l
|
||||
|
@ -39,9 +40,9 @@ _nnn ()
|
|||
-S
|
||||
-t
|
||||
-T
|
||||
-u
|
||||
-U
|
||||
-V
|
||||
-w
|
||||
-x
|
||||
-h
|
||||
)
|
||||
|
|
|
@ -12,8 +12,9 @@ else
|
|||
end
|
||||
|
||||
complete -c nnn -s a -d 'auto-create NNN_FIFO'
|
||||
complete -c nnn -s A -d 'disable dir auto-select'
|
||||
complete -c nnn -s A -d 'disable dir auto-enter'
|
||||
complete -c nnn -s b -r -d 'bookmark key to open' -x -a '(echo $NNN_BMS | awk -F: -v RS=\; \'{print $1"\t"$2}\')'
|
||||
complete -c nnn -s B -d 'use bsdtar for archives'
|
||||
complete -c nnn -s c -d 'cli-only opener'
|
||||
complete -c nnn -s C -d 'color by context'
|
||||
complete -c nnn -s d -d 'start in detail mode'
|
||||
|
@ -21,11 +22,11 @@ complete -c nnn -s D -d 'dirs in context color'
|
|||
complete -c nnn -s e -d 'open text files in $VISUAL/$EDITOR/vi'
|
||||
complete -c nnn -s E -d 'use EDITOR for undetached edits'
|
||||
complete -c nnn -s f -d 'use readline history file'
|
||||
complete -c nnn -s F -d 'show fortune'
|
||||
complete -c nnn -s g -d 'regex filters'
|
||||
complete -c nnn -s H -d 'show hidden files'
|
||||
complete -c nnn -s J -d 'no auto-proceed on select'
|
||||
complete -c nnn -s K -d 'detect key collision'
|
||||
complete -c nnn -s i -d 'show current file info'
|
||||
complete -c nnn -s J -d 'no auto-advance on selection'
|
||||
complete -c nnn -s K -d 'detect key collision and exit'
|
||||
complete -c nnn -s l -r -d 'lines to move per scroll'
|
||||
complete -c nnn -s n -d 'start in type-to-nav mode'
|
||||
complete -c nnn -s o -d 'open files only on Enter'
|
||||
|
@ -38,8 +39,8 @@ complete -c nnn -s s -r -d 'load session by name' -x -a '@\t"last session" (ls $
|
|||
complete -c nnn -s S -d 'persistent session'
|
||||
complete -c nnn -s t -r -d 'timeout in seconds to lock'
|
||||
complete -c nnn -s T -r -d 'a d e r s t v'
|
||||
complete -c nnn -s u -d 'use selection (no prompt)'
|
||||
complete -c nnn -s U -d 'show user and group'
|
||||
complete -c nnn -s V -d 'show program version and exit'
|
||||
complete -c nnn -s w -d 'hardware cursor mode'
|
||||
complete -c nnn -s x -d 'notis, sel to system clipboard'
|
||||
complete -c nnn -s x -d 'notis, sel to system clipboard, xterm title'
|
||||
complete -c nnn -s h -d 'show program help'
|
||||
|
|
|
@ -10,8 +10,9 @@ setopt localoptions noshwordsplit noksharrays
|
|||
local -a args
|
||||
args=(
|
||||
'(-a)-a[auto-create NNN_FIFO]'
|
||||
'(-A)-A[disable dir auto-select]'
|
||||
'(-A)-A[disable dir auto-enter]'
|
||||
'(-b)-b[bookmark key to open]:key char'
|
||||
'(-B)-B[use bsdtar for archives]'
|
||||
'(-c)-c[cli-only opener]'
|
||||
'(-C)-C[color by context]'
|
||||
'(-d)-d[start in detail mode]'
|
||||
|
@ -19,16 +20,16 @@ args=(
|
|||
'(-e)-e[open text files in $VISUAL/$EDITOR/vi]'
|
||||
'(-E)-E[use EDITOR for undetached edits]'
|
||||
'(-f)-f[use readline history file]'
|
||||
'(-F)-F[show fortune]'
|
||||
'(-g)-g[regex filters]'
|
||||
'(-H)-H[show hidden files]'
|
||||
'(-J)-J[no auto-proceed on select]'
|
||||
'(-K)-K[detect key collision]'
|
||||
'(-i)-i[show current file info]'
|
||||
'(-J)-J[no auto-advance on selection]'
|
||||
'(-K)-K[detect key collision and exit]'
|
||||
'(-l)-l[lines to move per scroll]:val'
|
||||
'(-n)-n[start in type-to-nav mode]'
|
||||
'(-o)-o[open files only on Enter]'
|
||||
'(-p)-p[copy selection to file]:file name'
|
||||
'(-P)-P[plugin key to runn]:key char'
|
||||
'(-P)-P[plugin key to run]:key char'
|
||||
'(-Q)-Q[disable quit confirmation]'
|
||||
'(-r)-r[show cp, mv progress (Linux-only)]'
|
||||
'(-R)-R[disable rollover at edges]'
|
||||
|
@ -36,10 +37,10 @@ args=(
|
|||
'(-S)-S[persistent session]'
|
||||
'(-t)-t[timeout to lock]:seconds'
|
||||
'(-T)-T[a d e r s t v]:key'
|
||||
'(-u)-u[use selection (no prompt)]'
|
||||
'(-U)-U[show user and group]'
|
||||
'(-V)-V[show program version and exit]'
|
||||
'(-w)-C[hardware cursor mode]'
|
||||
'(-x)-x[notis, sel to system clipboard]'
|
||||
'(-x)-x[notis, sel to system clipboard, xterm title]'
|
||||
'(-h)-h[show program help]'
|
||||
'*:filename:_files'
|
||||
)
|
||||
|
|
|
@ -12,7 +12,7 @@ CFLAGS_OPTIMIZATION ?= -O3
|
|||
O_DEBUG := 0 # debug binary
|
||||
O_NORL := 0 # no readline support
|
||||
O_PCRE := 0 # link with PCRE library
|
||||
O_NOLOC := 0 # no locale support
|
||||
O_NOLC := 0 # no locale support
|
||||
O_NOMOUSE := 0 # no mouse support
|
||||
O_NOBATCH := 0 # no built-in batch renamer
|
||||
O_NOFIFO := 0 # no FIFO previewer support
|
||||
|
@ -21,8 +21,18 @@ O_ICONS := 0 # support icons-in-terminal
|
|||
O_NERD := 0 # support icons-nerdfont
|
||||
O_QSORT := 0 # use Alexey Tourbin's QSORT implementation
|
||||
O_BENCH := 0 # benchmark mode (stops at first user input)
|
||||
O_NOSSN := 0 # enable session support
|
||||
O_NOSSN := 0 # disable session support
|
||||
O_NOUG := 0 # disable user, group name in status bar
|
||||
O_NOX11 := 0 # disable X11 integration
|
||||
O_MATCHFLTR := 0 # allow filters without matches
|
||||
|
||||
# User patches
|
||||
O_GITSTATUS := 0 # add git status to detail view
|
||||
O_NAMEFIRST := 0 # print file name first, add uid and guid to detail view
|
||||
|
||||
ifeq ($(strip $(O_GITSTATUS)),1)
|
||||
LDLIBS += -lgit2
|
||||
endif
|
||||
|
||||
# convert targets to flags for backwards compatibility
|
||||
ifneq ($(filter debug,$(MAKECMDGOALS)),)
|
||||
|
@ -31,13 +41,13 @@ endif
|
|||
ifneq ($(filter norl,$(MAKECMDGOALS)),)
|
||||
O_NORL := 1
|
||||
endif
|
||||
ifneq ($(filter noloc,$(MAKECMDGOALS)),)
|
||||
ifneq ($(filter nolc,$(MAKECMDGOALS)),)
|
||||
O_NORL := 1
|
||||
O_NOLOC := 1
|
||||
O_NOLC := 1
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(O_DEBUG)),1)
|
||||
CPPFLAGS += -DDBGMODE
|
||||
CPPFLAGS += -DDEBUG
|
||||
CFLAGS += -g
|
||||
LDLIBS += -lrt
|
||||
endif
|
||||
|
@ -55,8 +65,14 @@ ifeq ($(strip $(O_PCRE)),1)
|
|||
LDLIBS += -lpcre
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(O_NOLOC)),1)
|
||||
CPPFLAGS += -DNOLOCALE
|
||||
ifeq ($(strip $(O_NOLC)),1)
|
||||
ifeq ($(strip $(O_ICONS)),1)
|
||||
$(info *** Ignoring O_NOLC since O_ICONS is set ***)
|
||||
else ifeq ($(strip $(O_NERD)),1)
|
||||
$(info *** Ignoring O_NOLC since O_NERD is set ***)
|
||||
else
|
||||
CPPFLAGS += -DNOLC
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(O_NOMOUSE)),1)
|
||||
|
@ -99,6 +115,14 @@ ifeq ($(strip $(O_NOUG)),1)
|
|||
CPPFLAGS += -DNOUG
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(O_NOX11)),1)
|
||||
CPPFLAGS += -DNOX11
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(O_MATCHFLTR)),1)
|
||||
CPPFLAGS += -DMATCHFLTR
|
||||
endif
|
||||
|
||||
ifeq ($(shell $(PKG_CONFIG) ncursesw && echo 1),1)
|
||||
CFLAGS_CURSES ?= $(shell $(PKG_CONFIG) --cflags ncursesw)
|
||||
LDLIBS_CURSES ?= $(shell $(PKG_CONFIG) --libs ncursesw)
|
||||
|
@ -110,7 +134,7 @@ else
|
|||
endif
|
||||
|
||||
ifeq ($(shell uname -s), Haiku)
|
||||
LDLIBS_HAIKU ?= -lstdc++ -lbe
|
||||
LDLIBS_HAIKU ?= -lstdc++ -lgnu -lbe
|
||||
SRC_HAIKU ?= misc/haiku/nm.cpp
|
||||
OBJS_HAIKU ?= misc/haiku/nm.o
|
||||
endif
|
||||
|
@ -119,8 +143,7 @@ CFLAGS += -std=c11 -Wall -Wextra -Wshadow
|
|||
CFLAGS += $(CFLAGS_OPTIMIZATION)
|
||||
CFLAGS += $(CFLAGS_CURSES)
|
||||
|
||||
LDLIBS += $(LDLIBS_CURSES) $(LDLIBS_HAIKU)
|
||||
|
||||
LDLIBS += $(LDLIBS_CURSES) -lpthread $(LDLIBS_HAIKU)
|
||||
# static compilation needs libgpm development package
|
||||
ifeq ($(strip $(O_STATIC)),1)
|
||||
LDFLAGS += -static
|
||||
|
@ -133,6 +156,9 @@ HEADERS = src/nnn.h
|
|||
BIN = nnn
|
||||
OBJS := nnn.o $(OBJS_HAIKU)
|
||||
|
||||
GITSTATUS = patches/gitstatus
|
||||
NAMEFIRST = patches/namefirst
|
||||
|
||||
all: $(BIN)
|
||||
|
||||
ifeq ($(shell uname -s), Haiku)
|
||||
|
@ -144,12 +170,14 @@ nnn.o: $(SRC) $(HEADERS)
|
|||
$(CC) -c $(CPPFLAGS) $(CFLAGS) -o $@ $<
|
||||
|
||||
$(BIN): $(OBJS)
|
||||
@$(MAKE) --silent prepatch
|
||||
$(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS)
|
||||
@$(MAKE) --silent postpatch
|
||||
|
||||
# targets for backwards compatibility
|
||||
debug: $(BIN)
|
||||
norl: $(BIN)
|
||||
noloc: $(BIN)
|
||||
nolc: $(BIN)
|
||||
|
||||
install: all
|
||||
$(INSTALL) -m 0755 -d $(DESTDIR)$(PREFIX)/bin
|
||||
|
@ -165,6 +193,7 @@ strip: $(BIN)
|
|||
$(STRIP) $^
|
||||
|
||||
static:
|
||||
# regular static binary
|
||||
make O_STATIC=1 strip
|
||||
mv $(BIN) $(BIN)-static
|
||||
|
||||
|
@ -196,6 +225,26 @@ upload-local: sign static
|
|||
clean:
|
||||
$(RM) -f $(BIN) nnn-$(VERSION).tar.gz *.sig $(BIN)-static $(BIN)-static-$(VERSION).x86_64.tar.gz
|
||||
|
||||
prepatch:
|
||||
ifeq ($(strip $(O_NAMEFIRST)),1)
|
||||
patch --forward --strip=1 --input=$(NAMEFIRST)/mainline.diff
|
||||
ifeq ($(strip $(O_GITSTATUS)),1)
|
||||
patch --forward --strip=1 --input=$(GITSTATUS)/namefirst.diff
|
||||
endif
|
||||
else ifeq ($(strip $(O_GITSTATUS)),1)
|
||||
patch --forward --strip=1 --input=$(GITSTATUS)/mainline.diff
|
||||
endif
|
||||
|
||||
postpatch:
|
||||
ifeq ($(strip $(O_NAMEFIRST)),1)
|
||||
ifeq ($(strip $(O_GITSTATUS)),1)
|
||||
patch --reverse --strip=1 --input=$(GITSTATUS)/namefirst.diff
|
||||
endif
|
||||
patch --reverse --strip=1 --input=$(NAMEFIRST)/mainline.diff
|
||||
else ifeq ($(strip $(O_GITSTATUS)),1)
|
||||
patch --reverse --strip=1 --input=$(GITSTATUS)/mainline.diff
|
||||
endif
|
||||
|
||||
skip: ;
|
||||
|
||||
.PHONY: all install uninstall strip static dist sign upload-local clean
|
||||
|
|
|
@ -12,7 +12,7 @@ Cygwin, WSL, Haiku and works seamlessly with DEs and GUI utilities.
|
|||
|
||||
Visit the Wiki for concepts, program usage, how-tos and troubleshooting."
|
||||
HOMEPAGE="https://github.com/jarun/nnn"
|
||||
COPYRIGHT="2016-2021 Arun Prakash Jana"
|
||||
COPYRIGHT="2016-2023 Arun Prakash Jana"
|
||||
LICENSE="BSD (2-clause)"
|
||||
REVISION="1"
|
||||
SOURCE_URI="git://github.com/jarun/nnn.git"
|
||||
|
|
|
@ -8,11 +8,11 @@
|
|||
resource app_signature "application/x-vnd.Jarun-nnn";
|
||||
|
||||
resource app_version {
|
||||
major = 3,
|
||||
middle = 6,
|
||||
major = 4,
|
||||
middle = 9,
|
||||
minor = 0,
|
||||
|
||||
variety = B_APPV_FINAL,
|
||||
variety = B_APPV_DEVELOPMENT,
|
||||
internal = 0,
|
||||
|
||||
short_info = "nnn",
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
#include "mach_gettime.h"
|
||||
#include <mach/mach_time.h>
|
||||
|
||||
#define MT_NANO (+1.0E-9)
|
||||
#define MT_GIGA UINT64_C(1000000000)
|
||||
|
||||
// TODO create a list of timers,
|
||||
static double mt_timebase = 0.0;
|
||||
static uint64_t mt_timestart = 0;
|
||||
|
||||
int clock_gettime(clockid_t clk_id, struct timespec *tp)
|
||||
{
|
||||
kern_return_t retval = KERN_SUCCESS;
|
||||
|
||||
if (clk_id == TIMER_ABSTIME) {
|
||||
if (!mt_timestart) { // only one timer, initialized on the first call to the TIMER
|
||||
mach_timebase_info_data_t tb;
|
||||
mach_timebase_info(&tb);
|
||||
mt_timebase = tb.numer;
|
||||
mt_timebase /= tb.denom;
|
||||
mt_timestart = mach_absolute_time();
|
||||
}
|
||||
|
||||
double diff = (mach_absolute_time() - mt_timestart) * mt_timebase;
|
||||
tp->tv_sec = diff * MT_NANO;
|
||||
tp->tv_nsec = diff - (tp->tv_sec * MT_GIGA);
|
||||
} else { // other clk_ids are mapped to the corresponding mach clock_service
|
||||
clock_serv_t cclock;
|
||||
mach_timespec_t mts;
|
||||
|
||||
host_get_clock_service(mach_host_self(), clk_id, &cclock);
|
||||
retval = clock_get_time(cclock, &mts);
|
||||
mach_port_deallocate(mach_task_self(), cclock);
|
||||
|
||||
tp->tv_sec = mts.tv_sec;
|
||||
tp->tv_nsec = mts.tv_nsec;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Copyright (c) 2015-2018 Alf Watt - Open Source - https://opensource.org/licenses/MIT */
|
|
@ -0,0 +1,28 @@
|
|||
#ifndef mach_time_h
|
||||
#define mach_time_h
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/_types/_timespec.h>
|
||||
#include <mach/mach.h>
|
||||
#include <mach/clock.h>
|
||||
|
||||
/* The opengroup spec isn't clear on the mapping from REALTIME to CALENDAR
|
||||
being appropriate or not.
|
||||
http://pubs.opengroup.org/onlinepubs/009695299/basedefs/time.h.html */
|
||||
|
||||
// XXX only supports a single timer
|
||||
#define TIMER_ABSTIME -1
|
||||
#define CLOCK_REALTIME CALENDAR_CLOCK
|
||||
#define CLOCK_MONOTONIC SYSTEM_CLOCK
|
||||
|
||||
typedef int clockid_t;
|
||||
|
||||
/* the mach kernel uses struct mach_timespec, so struct timespec
|
||||
is loaded from <sys/_types/_timespec.h> for compatibility */
|
||||
// struct timespec { time_t tv_sec; long tv_nsec; };
|
||||
|
||||
int clock_gettime(clockid_t clk_id, struct timespec *tp);
|
||||
|
||||
#endif
|
||||
|
||||
/* Copyright (c) 2015-2018 Alf Watt - Open Source - https://opensource.org/licenses/MIT */
|
|
@ -0,0 +1,67 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
# Statically compile nnn with netbsd-curses, musl-fts and musl libc on Ubuntu
|
||||
#
|
||||
# netbsd-curses: https://github.com/sabotage-linux/netbsd-curses
|
||||
# musl-fts: https://github.com/void-linux/musl-fts
|
||||
# musl libc: https://www.musl-libc.org/
|
||||
#
|
||||
# Dependencies: git
|
||||
#
|
||||
# Usage: musl-static-ubuntu.sh [no_run]
|
||||
# # optional argument - do not to execute the binary after compilation
|
||||
#
|
||||
# Notes:
|
||||
# - run the script within the top-level nnn directory
|
||||
# - installs musl & gits netbsd-curses, musl-fts libs
|
||||
#
|
||||
# Tested on Ubuntu 20.04 x86_64
|
||||
# Author: Arun Prakash Jana
|
||||
|
||||
# Exit on first failure
|
||||
set -e
|
||||
|
||||
# Output binary name
|
||||
BIN=nnn-musl-static
|
||||
|
||||
# Install musl
|
||||
sudo apt install -y --no-install-recommends musl musl-dev musl-tools
|
||||
|
||||
# Get netbsd-curses
|
||||
[ ! -d "./netbsd-curses" ] && git clone https://github.com/sabotage-linux/netbsd-curses
|
||||
|
||||
# Enter the library dir
|
||||
cd netbsd-curses
|
||||
|
||||
# Get the last known working version
|
||||
git checkout v0.3.2
|
||||
|
||||
# Compile the static netbsd-curses libraries
|
||||
if [ ! -d "./libs" ]; then
|
||||
mkdir libs
|
||||
else
|
||||
rm -vf -- libs/*
|
||||
fi
|
||||
make CC=musl-gcc CFLAGS=-O3 LDFLAGS=-static all-static -j$(($(nproc)+1))
|
||||
cp -v libcurses/libcurses.a libterminfo/libterminfo.a libs/
|
||||
|
||||
# Get musl-fts library
|
||||
cd ..
|
||||
[ ! -d "./musl-fts" ] && git clone https://github.com/void-linux/musl-fts --depth=1
|
||||
|
||||
# Compile the static musl-fts library
|
||||
cd musl-fts
|
||||
./bootstrap.sh
|
||||
./configure
|
||||
make CC=musl-gcc CFLAGS=-O3 LDFLAGS=-static -j$(($(nproc)+1))
|
||||
|
||||
# Compile nnn
|
||||
cd ..
|
||||
[ -e "./netbsd-curses" ] || rm -- "$BIN"
|
||||
musl-gcc -O3 -DNORL -DNOMOUSE -std=c11 -Wall -Wextra -Wshadow -I./netbsd-curses/libcurses -I./musl-fts -o "$BIN" src/nnn.c -Wl,-Bsymbolic-functions -lpthread -L./netbsd-curses/libs -lcurses -lterminfo -static -L./musl-fts/.libs -lfts
|
||||
strip "$BIN"
|
||||
|
||||
if [ -z "$1" ]; then
|
||||
# Run the binary with it selected
|
||||
./"$BIN" -d "$BIN"
|
||||
fi
|
|
@ -21,7 +21,7 @@
|
|||
# #############################################################################
|
||||
|
||||
import sys
|
||||
from subprocess import Popen, PIPE, DEVNULL
|
||||
from subprocess import Popen, PIPE
|
||||
|
||||
if len(sys.argv) < 3:
|
||||
print('usage: natool [-a] [-l] [-x] [archive] [file/dir]')
|
||||
|
|
|
@ -89,26 +89,26 @@ packages:
|
|||
deps:
|
||||
- ncurses
|
||||
- readline
|
||||
opensuse15.2:
|
||||
builddeps:
|
||||
- make
|
||||
- gcc
|
||||
- pkg-config
|
||||
- readline-devel
|
||||
- ncurses-devel
|
||||
deps:
|
||||
- libncurses6
|
||||
- libreadline7
|
||||
opensuse.tumbleweed:
|
||||
builddeps:
|
||||
- make
|
||||
- gcc
|
||||
- pkg-config
|
||||
- readline-devel
|
||||
- ncurses-devel
|
||||
deps:
|
||||
- libncurses6
|
||||
- libreadline8
|
||||
# opensuse15.2:
|
||||
# builddeps:
|
||||
# - make
|
||||
# - gcc
|
||||
# - pkg-config
|
||||
# - readline-devel
|
||||
# - ncurses-devel
|
||||
# deps:
|
||||
# - libncurses6
|
||||
# - libreadline7
|
||||
# opensuse.tumbleweed:
|
||||
# builddeps:
|
||||
# - make
|
||||
# - gcc
|
||||
# - pkg-config
|
||||
# - readline-devel
|
||||
# - ncurses-devel
|
||||
# deps:
|
||||
# - libncurses6
|
||||
# - libreadline8
|
||||
ubuntu16.04:
|
||||
builddeps:
|
||||
- make
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
n ()
|
||||
{
|
||||
# Block nesting of nnn in subshells
|
||||
[ "${NNNLVL:-0}" -eq 0 ] || {
|
||||
echo "nnn is already running"
|
||||
return
|
||||
}
|
||||
|
||||
# The behaviour is set to cd on quit (nnn checks if NNN_TMPFILE is set)
|
||||
# If NNN_TMPFILE is set to a custom path, it must be exported for nnn to
|
||||
# see. To cd on quit only on ^G, remove the "export" and make sure not to
|
||||
# use a custom path, i.e. set NNN_TMPFILE *exactly* as follows:
|
||||
# NNN_TMPFILE="${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.lastd"
|
||||
export NNN_TMPFILE="${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.lastd"
|
||||
|
||||
# Unmask ^Q (, ^V etc.) (if required, see `stty -a`) to Quit nnn
|
||||
# stty start undef
|
||||
# stty stop undef
|
||||
# stty lwrap undef
|
||||
# stty lnext undef
|
||||
|
||||
# The command builtin allows one to alias nnn to n, if desired, without
|
||||
# making an infinitely recursive alias
|
||||
command nnn "$@"
|
||||
|
||||
[ ! -f "$NNN_TMPFILE" ] || {
|
||||
. "$NNN_TMPFILE"
|
||||
rm -f -- "$NNN_TMPFILE" > /dev/null
|
||||
}
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
n ()
|
||||
{
|
||||
# Block nesting of nnn in subshells
|
||||
if [ -n $NNNLVL ] && [ "${NNNLVL:-0}" -ge 1 ]; then
|
||||
echo "nnn is already running"
|
||||
return
|
||||
fi
|
||||
|
||||
# The default behaviour is to cd on quit (nnn checks if NNN_TMPFILE is set)
|
||||
# To cd on quit only on ^G, remove the "export" as in:
|
||||
# NNN_TMPFILE="${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.lastd"
|
||||
# NOTE: NNN_TMPFILE is fixed, should not be modified
|
||||
export NNN_TMPFILE="${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.lastd"
|
||||
|
||||
# Unmask ^Q (, ^V etc.) (if required, see `stty -a`) to Quit nnn
|
||||
# stty start undef
|
||||
# stty stop undef
|
||||
# stty lwrap undef
|
||||
# stty lnext undef
|
||||
|
||||
nnn "$@"
|
||||
|
||||
if [ -f "$NNN_TMPFILE" ]; then
|
||||
. "$NNN_TMPFILE"
|
||||
rm -f "$NNN_TMPFILE" > /dev/null
|
||||
fi
|
||||
}
|
|
@ -1,8 +1,9 @@
|
|||
# NOTE: set NNN_TMPFILE correctly if you use 'XDG_CONFIG_HOME'
|
||||
|
||||
# The default behaviour is to cd on quit (nnn checks if NNN_TMPFILE is set)
|
||||
# To cd on quit only on ^G, export NNN_TMPFILE after the call to nnn
|
||||
# NOTE: NNN_TMPFILE is fixed, should not be modified
|
||||
# The behaviour is set to cd on quit (nnn checks if NNN_TMPFILE is set)
|
||||
# If NNN_TMPFILE is set to a custom path, it must be exported for nnn to see.
|
||||
# To cd on quit only on ^G, set NNN_TMPFILE after the nnn invocation, and make
|
||||
# sure not to use a custom path.
|
||||
set NNN_TMPFILE=~/.config/nnn/.lastd
|
||||
|
||||
# Unmask ^Q (, ^V etc.) (if required, see `stty -a`) to Quit nnn
|
||||
|
@ -11,4 +12,6 @@ set NNN_TMPFILE=~/.config/nnn/.lastd
|
|||
# stty lwrap undef
|
||||
# stty lnext undef
|
||||
|
||||
alias n 'nnn; source "$NNN_TMPFILE"; rm -f "$NNN_TMPFILE"'
|
||||
# The backslash allows one to alias n to nnn if desired without making an
|
||||
# infinitely recursive alias
|
||||
alias n '\nnn; source "$NNN_TMPFILE"; rm -f -- "$NNN_TMPFILE"'
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
# Append this file to ~/.elvish/rc.elv (Elvish > 0.17.0)
|
||||
|
||||
use path
|
||||
|
||||
fn n {|@a|
|
||||
# Block nesting of nnn in subshells
|
||||
if (has-env NNNLVL) {
|
||||
try {
|
||||
if (>= $E:NNNLVL 1) {
|
||||
echo "nnn is already running"
|
||||
return
|
||||
}
|
||||
} catch e {
|
||||
nop
|
||||
}
|
||||
}
|
||||
|
||||
# The behaviour is set to cd on quit (nnn checks if NNN_TMPFILE is set)
|
||||
# If NNN_TMPFILE is set to a custom path, it must be exported for nnn to
|
||||
# see.
|
||||
if (has-env XDG_CONFIG_HOME) {
|
||||
set-env NNN_TMPFILE $E:XDG_CONFIG_HOME/nnn/.lastd
|
||||
} else {
|
||||
set-env NNN_TMPFILE $E:HOME/.config/nnn/.lastd
|
||||
}
|
||||
|
||||
# Unmask ^Q (, ^V etc.) (if required, see `stty -a`) to Quit nnn
|
||||
# stty start undef
|
||||
# stty stop undef
|
||||
# stty lwrap undef
|
||||
# stty lnext undef
|
||||
|
||||
# The e: prefix allows one to alias n to nnn if desired without making an
|
||||
# infinitely recursive alias
|
||||
e:nnn $@a
|
||||
|
||||
if (path:is-regular $E:NNN_TMPFILE) {
|
||||
eval (slurp < $E:NNN_TMPFILE)
|
||||
rm -- $E:NNN_TMPFILE
|
||||
}
|
||||
}
|
|
@ -4,17 +4,15 @@
|
|||
|
||||
function n --wraps nnn --description 'support nnn quit and change directory'
|
||||
# Block nesting of nnn in subshells
|
||||
if test -n "$NNNLVL"
|
||||
if [ (expr $NNNLVL + 0) -ge 1 ]
|
||||
echo "nnn is already running"
|
||||
return
|
||||
end
|
||||
if test -n "$NNNLVL" -a "$NNNLVL" -ge 1
|
||||
echo "nnn is already running"
|
||||
return
|
||||
end
|
||||
|
||||
# The default behaviour is to cd on quit (nnn checks if NNN_TMPFILE is set)
|
||||
# To cd on quit only on ^G, remove the "-x" as in:
|
||||
# set NNN_TMPFILE "$XDG_CONFIG_HOME/nnn/.lastd"
|
||||
# NOTE: NNN_TMPFILE is fixed, should not be modified
|
||||
# The behaviour is set to cd on quit (nnn checks if NNN_TMPFILE is set)
|
||||
# If NNN_TMPFILE is set to a custom path, it must be exported for nnn to
|
||||
# see. To cd on quit only on ^G, remove the "-x" from both lines below,
|
||||
# without changing the paths.
|
||||
if test -n "$XDG_CONFIG_HOME"
|
||||
set -x NNN_TMPFILE "$XDG_CONFIG_HOME/nnn/.lastd"
|
||||
else
|
||||
|
@ -27,10 +25,12 @@ function n --wraps nnn --description 'support nnn quit and change directory'
|
|||
# stty lwrap undef
|
||||
# stty lnext undef
|
||||
|
||||
nnn $argv
|
||||
# The command function allows one to alias this function to `nnn` without
|
||||
# making an infinitely recursive alias
|
||||
command nnn $argv
|
||||
|
||||
if test -e $NNN_TMPFILE
|
||||
source $NNN_TMPFILE
|
||||
rm $NNN_TMPFILE
|
||||
rm -- $NNN_TMPFILE
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
# Run nnn with dynamic changing directory to the environment.
|
||||
#
|
||||
# $env.XDG_CONFIG_HOME sets the home folder for `nnn` folder and its $env.NNN_TMPFILE variable.
|
||||
# See manual NNN(1) for more information.
|
||||
#
|
||||
# Import module using `use quitcd.nu n` to have `n` command in your context.
|
||||
export def --env n [
|
||||
...args : string # Extra flags to launch nnn with.
|
||||
--selective = false # Change directory only when exiting via ^G.
|
||||
] -> nothing {
|
||||
|
||||
# The behaviour is set to cd on quit (nnn checks if $env.NNN_TMPFILE is set).
|
||||
# Hard-coded to its respective behaviour in `nnn` source-code.
|
||||
let nnn_tmpfile = $env
|
||||
| default '~/.config/' 'XDG_CONFIG_HOME'
|
||||
| get 'XDG_CONFIG_HOME'
|
||||
| path join 'nnn/.lastd'
|
||||
| path expand
|
||||
|
||||
# Launch nnn. Add desired flags after `^nnn`, ex: `^nnn -eda ...$args`,
|
||||
# or make an alias `alias n = n -eda`.
|
||||
if $selective {
|
||||
^nnn ...$args
|
||||
} else {
|
||||
NNN_TMPFILE=$nnn_tmpfile ^nnn ...$args
|
||||
}
|
||||
|
||||
if ($nnn_tmpfile | path exists) {
|
||||
# Remove <cd '> from the first part of the string and the last single quote <'>.
|
||||
# Fix post-processing of nnn's given path that escapes its single quotes with POSIX syntax.
|
||||
let path = open $nnn_tmpfile | str substring 4..-1 | str replace --all `'\''` `'`
|
||||
|
||||
^rm -- $nnn_tmpfile
|
||||
|
||||
cd $path
|
||||
}
|
||||
}
|
351
nnn.1
351
nnn.1
|
@ -1,4 +1,4 @@
|
|||
.Dd Mar 16, 2021
|
||||
.Dd Aug 27, 2023
|
||||
.Dt NNN 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -6,54 +6,51 @@
|
|||
.Nd The unorthodox terminal file manager.
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Ar -a
|
||||
.Op Ar -A
|
||||
.Op Ar -aAcCdDeEfgHJKnQrRSuUVxh
|
||||
.Op Ar -b key
|
||||
.Op Ar -c
|
||||
.Op Ar -C
|
||||
.Op Ar -d
|
||||
.Op Ar -D
|
||||
.Op Ar -e
|
||||
.Op Ar -E
|
||||
.Op Ar -f
|
||||
.Op Ar -F
|
||||
.Op Ar -g
|
||||
.Op Ar -H
|
||||
.Op Ar -J
|
||||
.Op Ar -K
|
||||
.Op Ar -l
|
||||
.Op Ar -n
|
||||
.Op Ar -F val
|
||||
.Op Ar -l val
|
||||
.Op Ar -p file
|
||||
.Op Ar -P key
|
||||
.Op Ar -Q
|
||||
.Op Ar -r
|
||||
.Op Ar -R
|
||||
.Op Ar -s name
|
||||
.Op Ar -S
|
||||
.Op Ar -t secs
|
||||
.Op Ar -T key
|
||||
.Op Ar -U
|
||||
.Op Ar -V
|
||||
.Op Ar -w
|
||||
.Op Ar -x
|
||||
.Op Ar -h
|
||||
.Op Ar PATH
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
(Nnn's Not Noice) is a performance-optimized, feature-packed fork of
|
||||
noice (http://git.2f30.org/noice/) with seamless desktop
|
||||
integration, simplified navigation, \fItype-to-nav\fR mode with
|
||||
auto select, disk usage analyzer mode, bookmarks, contexts, application
|
||||
launcher, familiar navigation shortcuts, subshell spawning and much
|
||||
more. It remains a simple and efficient file manager that stays out of your way.
|
||||
.Pq Nnn's Not Noice
|
||||
is a performance-optimized, feature-packed fork of noice
|
||||
.Em http://git.2f30.org/noice/
|
||||
with seamless desktop integration, simplified navigation,
|
||||
.Em type-to-nav
|
||||
mode with dir auto-enter, disk usage analyzer mode, bookmarks,
|
||||
contexts, application launcher, familiar navigation shortcuts,
|
||||
subshell spawning and much more. It remains a simple and
|
||||
efficient file manager that stays out of your way.
|
||||
.Pp
|
||||
.Nm
|
||||
opens the current working directory by default if
|
||||
opens the current working directory if
|
||||
.Ar PATH
|
||||
is not specified.
|
||||
is not specified. If
|
||||
.Ar PATH
|
||||
is specified and it exists,
|
||||
.Nm
|
||||
will open it. If the
|
||||
.Ar PATH
|
||||
doesn't exist and ends with a \fB/\fR,
|
||||
.Nm
|
||||
will attempt to create the directory tree and open it. Otherwise,
|
||||
.Ar PATH
|
||||
is considered a path to a regular file and
|
||||
.Nm
|
||||
attempts to create the complete directory tree to the file, open
|
||||
the parent directory and prompt to create the new file in it with
|
||||
the base filename.
|
||||
.Sh KEYBINDS
|
||||
.Pp
|
||||
Press \fB?\fR in
|
||||
Press
|
||||
.Ql \&?
|
||||
in
|
||||
.Nm
|
||||
to see the list of keybinds.
|
||||
.Sh OPTIONS
|
||||
|
@ -62,19 +59,22 @@ to see the list of keybinds.
|
|||
supports the following options:
|
||||
.Pp
|
||||
.Fl a
|
||||
auto-setup temporary NNN_FIFO (described in ENVIRONMENT section)
|
||||
auto-setup temporary \fBNNN_FIFO\fR (described in \fIENVIRONMENT\fR section)
|
||||
.Pp
|
||||
.Fl A
|
||||
disable directory auto-select in type-to-nav mode
|
||||
disable directory auto-enter on unique filter match
|
||||
.Pp
|
||||
.Fl "b key"
|
||||
specify bookmark key to open
|
||||
.Pp
|
||||
.Fl B
|
||||
use bsdtar for archives (default: atool)
|
||||
.Pp
|
||||
.Fl c
|
||||
indicates that the opener is a cli-only opener (overrides -e)
|
||||
.Pp
|
||||
.Fl C
|
||||
earlier colorscheme - color directories by context, disable file colors
|
||||
8-color scheme - color directories by context, disable file colors
|
||||
.Pp
|
||||
.Fl d
|
||||
detail mode
|
||||
|
@ -91,8 +91,9 @@ supports the following options:
|
|||
.Fl f
|
||||
use readline history file
|
||||
.Pp
|
||||
.Fl F
|
||||
show fortune in help and settings screen
|
||||
.Fl "F val"
|
||||
fifo notification mode
|
||||
0: notify as previewer, 1: notify as explorer
|
||||
.Pp
|
||||
.Fl g
|
||||
use regex filters instead of substring match
|
||||
|
@ -100,11 +101,15 @@ supports the following options:
|
|||
.Fl H
|
||||
show hidden files
|
||||
.Pp
|
||||
.Fl i
|
||||
show current file information in info bar (may be slow)
|
||||
.Pp
|
||||
.Fl J
|
||||
disable auto-proceed on select
|
||||
disable auto-advance on selection
|
||||
(eg. selecting an entry will no longer move cursor to the next entry)
|
||||
.Pp
|
||||
.Fl K
|
||||
test for keybind collision
|
||||
test for keybind collision and exit
|
||||
.Pp
|
||||
.Fl "l val"
|
||||
number of lines to move per mouse wheel scroll
|
||||
|
@ -126,10 +131,11 @@ supports the following options:
|
|||
.Pp
|
||||
.Fl r
|
||||
show cp, mv progress
|
||||
(Linux-only, needs advcpmv; '^T' shows the progress on BSD/macOS)
|
||||
(Linux-only, needs \fIadvcpmv\fR; '^T' shows the progress on BSD/macOS)
|
||||
.Pp
|
||||
.Fl R
|
||||
disable rollover at edges
|
||||
disable rollover at edges (eg. pressing \fIdown\fR while on the last
|
||||
entry will no longer move cursor to the first entry and vice\-versa)
|
||||
.Pp
|
||||
.Fl "s name"
|
||||
load a session by name
|
||||
|
@ -142,7 +148,11 @@ supports the following options:
|
|||
.Pp
|
||||
.Fl "T key"
|
||||
sort order
|
||||
keys: 'a'u / 'd'u / 'e'xtension / 'r'everse / 's'ize / 't'ime / 'v'ersion
|
||||
keys: 'a'pparent disk usage / 'd'isk usage / 'e'xtension / 'r'everse / 's'ize / 't'ime / 'v'ersion
|
||||
capitalize to reverse (except 'r')
|
||||
.Pp
|
||||
.Fl u
|
||||
use selection if available, don't prompt to choose between selection and hovered entry
|
||||
.Pp
|
||||
.Fl U
|
||||
show user and group names in status bar
|
||||
|
@ -150,19 +160,17 @@ supports the following options:
|
|||
.Fl V
|
||||
show version and exit
|
||||
.Pp
|
||||
.Fl w
|
||||
place hardware cursor on hovered entry
|
||||
.Pp
|
||||
.Fl x
|
||||
show notis on selection cp, mv, rm completion
|
||||
copy path to system clipboard on select
|
||||
show notifications on selection cp, mv, rm completion (requires \fI.ntfy\fR plugin)
|
||||
copy path to system clipboard on selection (requires \fI.cbcp\fR plugin)
|
||||
show xterm title (if non-picker mode)
|
||||
.Pp
|
||||
.Fl h
|
||||
show program help and exit
|
||||
.Sh CONFIGURATION
|
||||
There is no configuration file. Associated files are at
|
||||
.Pp
|
||||
\fB${XDG_CONFIG_HOME:-$HOME/.config}/nnn/\fR
|
||||
.Pa ${XDG_CONFIG_HOME:-$HOME/.config}/nnn/
|
||||
.Pp
|
||||
Configuration is done using a few optional (set if you need) environment
|
||||
variables. See ENVIRONMENT section.
|
||||
|
@ -185,28 +193,35 @@ A new context copies the state of the previous context. Each context can have
|
|||
its own color. See ENVIRONMENT section.
|
||||
.Sh SESSIONS
|
||||
Sessions are a way to save and restore states of work. A session stores the
|
||||
settings and contexts.
|
||||
settings and contexts. Sessions can be loaded at runtime or with a program
|
||||
option.
|
||||
.Pp
|
||||
Sessions can be loaded dynamically at runtime or with a program option.
|
||||
.Pp
|
||||
When a session is loaded dynamically, the last working session is saved
|
||||
automatically to a dedicated -- "last session" -- session file. The "last
|
||||
session" is also used in persistent session mode.
|
||||
.Pp
|
||||
Listing input stream has a higher priority to session options (-s/-S). Sessions
|
||||
can be loaded explicitly at runtime. Session option \fIrestore\fR would restore
|
||||
the persistent session at runtime.
|
||||
- When a session is loaded at runtime, the last working state is saved
|
||||
automatically to a dedicated "auto session" session file. Session option
|
||||
\fIrestore\fR would restore the "auto session".
|
||||
.br
|
||||
- The persistent session option is global. If it is used, the last active session
|
||||
will be updated with the final state at program quit.
|
||||
.br
|
||||
- The "auto session" is used in persistent session mode if no session is active.
|
||||
.br
|
||||
- Listing input stream and opening a bookmark by key have a higher priority to
|
||||
session options (-s/-S).
|
||||
.Pp
|
||||
All the session files are located by session name in the directory
|
||||
.Pp
|
||||
\fB${XDG_CONFIG_HOME:-$HOME/.config}/nnn/sessions\fR
|
||||
.Pp
|
||||
"@" is the "last session" file.
|
||||
"@" is the "auto session" file.
|
||||
.Sh FILTERS
|
||||
Filters are strings (or regex patterns) to find matching entries in the current
|
||||
directory instantly (\fIsearch-as-you-type\fR). Matches are case-insensitive by
|
||||
default. The last filter in each context is persisted at runtime or in saved
|
||||
sessions.
|
||||
.br
|
||||
When there's a unique match and it's a directory,
|
||||
.Nm
|
||||
auto enters the directory. Use the relevant program option to disable this.
|
||||
.Pp
|
||||
Special keys at filter prompt:
|
||||
.Bd -literal
|
||||
|
@ -215,7 +230,7 @@ Special keys at filter prompt:
|
|||
-------- + ---------------------------------------
|
||||
^char | Usual keybind functionality
|
||||
Esc | Exit filter prompt but skip dir refresh
|
||||
Alt+Esc | Exit filter prompt and refresh dir
|
||||
Alt+Esc | Unfilter, quit context
|
||||
-------- + ---------------------------------------
|
||||
.Ed
|
||||
.Pp
|
||||
|
@ -229,30 +244,11 @@ Special keys at \fBempty filter prompt\fR:
|
|||
: | Toggle case-sensitivity
|
||||
^L | Clear filter (\fIif prompt is non-empty\fR)
|
||||
| OR apply last filter
|
||||
Bksp | Stay at filter prompt and refresh dir
|
||||
Del | Stay at filter prompt and refresh dir
|
||||
------ + ---------------------------------------
|
||||
.Ed
|
||||
.Pp
|
||||
Additional special keys at \fBempty filter prompt\fR
|
||||
in \fBtype-to-nav\fR mode:
|
||||
.Bd -literal
|
||||
------ + ------------------------
|
||||
Key | Function
|
||||
------ + ------------------------
|
||||
' | Go to first non-dir file
|
||||
+ | Toggle auto-advance
|
||||
, | Mark CWD
|
||||
- | Go to last visited dir
|
||||
. | Show hidden files
|
||||
; | Run a plugin by its key
|
||||
= | Launch a GUI application
|
||||
> | Export file list
|
||||
@ | Visit start dir
|
||||
] | Show command prompt
|
||||
` | Visit /
|
||||
~ | Go HOME
|
||||
------ + ------------------------
|
||||
.Ed
|
||||
.Pp
|
||||
Common regex use cases:
|
||||
.Pp
|
||||
(1) To list all matches starting with the filter expression,
|
||||
|
@ -264,13 +260,29 @@ Common regex use cases:
|
|||
.br
|
||||
(4) Exclude filenames having 'nnn' (compiled with PCRE lib): '^(?!nnn)'
|
||||
.Pp
|
||||
In the \fItype-to-nav\fR mode directories are opened in filter
|
||||
In the \fBtype-to-nav\fR mode directories are opened in filter
|
||||
mode, allowing continuous navigation.
|
||||
.br
|
||||
When there's a unique match and it's a directory,
|
||||
.Nm
|
||||
auto selects the directory and enters it in this mode. Use the relevant
|
||||
program option to disable this behaviour.
|
||||
.Pp
|
||||
Additional special keys at \fBempty filter prompt\fR
|
||||
in \fBtype-to-nav\fR mode:
|
||||
.Bd -literal
|
||||
------ + ------------------------
|
||||
Key | Function
|
||||
------ + ------------------------
|
||||
' | Go to first non-dir file
|
||||
+ | Toggle file selection
|
||||
, | Mark CWD
|
||||
- | Go to last visited dir
|
||||
. | Show hidden files
|
||||
; | Run a plugin by its key
|
||||
= | Launch a GUI application
|
||||
> | Export file list
|
||||
@ | Visit start dir
|
||||
] | Show command prompt
|
||||
` | Visit /
|
||||
~ | Go HOME
|
||||
------ + ------------------------
|
||||
.Ed
|
||||
.Sh SELECTION
|
||||
.Nm
|
||||
allows file selection across directories and contexts!
|
||||
|
@ -289,23 +301,27 @@ A selection can be edited, copied, moved, removed, archived or linked.
|
|||
.Pp
|
||||
Absolute paths of the selected files are copied to \fB.selection\fR file in
|
||||
the config directory. The selection file is shared between multiple program
|
||||
instances. The most recent instance writing to the file overwrites the entries
|
||||
from earlier writes. If you have 2 instances if
|
||||
instances. Selection from multiple instances are not merged. The last instance
|
||||
writing to the file overwrites earlier contents. If you have 2 instances of
|
||||
.Nm
|
||||
\fIopen\fR in 2 panes of a terminal multiplexer, you can select in one pane and
|
||||
use the selection (e.g. to copy or move) in the other pane (if the instance
|
||||
doesn't have any local selection already).
|
||||
use the selection in the other pane. The selection gets cleared in the
|
||||
.Nm
|
||||
instance where the selection was made on mv/rm (but not on cp).
|
||||
.Pp
|
||||
.Nm
|
||||
clears the selection after file removal, batch-rename and link creation with
|
||||
selection. However, it is retained after archive creation with selection as
|
||||
the user may want to delete the archived files next.
|
||||
clears the selection after a successful operation with the selection. Plugins
|
||||
are allowed to define the behaviour individually.
|
||||
.Pp
|
||||
To edit the selection use the _edit selection_ key. Use this key to remove a
|
||||
file from selection after you navigate away from its directory. Editing doesn't
|
||||
end the selection mode. You can add more files to the selection and edit the
|
||||
list again. If no file is selected in the current session, this option attempts
|
||||
To edit the selection use the _edit selection_ key. Editing doesn't end the
|
||||
selection mode. You can add more files to the selection and edit the list
|
||||
again. If no file is selected in the current session, this option attempts
|
||||
to list the selection file.
|
||||
.Pp
|
||||
.Nm
|
||||
can show the total size of non-filtered selected files listed in a
|
||||
directory. For directories, only the size of the directory is added by
|
||||
default. To add the size of the contents of a directory, switch to du mode.
|
||||
.Sh FIND AND LIST
|
||||
There are two ways to search and list:
|
||||
.Pp
|
||||
|
@ -315,7 +331,7 @@ There are two ways to search and list:
|
|||
.Pp
|
||||
File paths must be NUL-separated ('\\0'). Paths and can be relative to the
|
||||
current directory or absolute. Invalid paths in the input are ignored. Input
|
||||
limit is 65,536 paths or 256 MiB of data.
|
||||
processing limit is 16,384 paths or 64 MiB (max_paths x max_path_len) of data.
|
||||
.Pp
|
||||
To list the input stream, start
|
||||
.Nm
|
||||
|
@ -337,7 +353,7 @@ Handy bash/zsh shell function to list files by mime-type in current directory:
|
|||
|
||||
list ()
|
||||
{
|
||||
find . -maxdepth 1 | file -if- | grep "$1" | awk -F: '{printf "%s\0", $1}' | nnn
|
||||
find . -maxdepth 1 | file -if- | grep "$1" | awk -F: '{printf "%s%c", $1, 0}' | nnn
|
||||
}
|
||||
.Ed
|
||||
.Pp
|
||||
|
@ -350,6 +366,24 @@ file. Press '-' to return to the listing dir. Press 'Enter' to open the symlink.
|
|||
.Pp
|
||||
Listing input stream can be scripted. It can be extended to pick (option -p)
|
||||
selected entries from the listed results.
|
||||
.Sh BOOKMARKS
|
||||
There are 2 ways (can be used together) to manage bookmarks.
|
||||
.Pp
|
||||
(1) Bookmark keys: See \fBNNN_BMS\fR under \fIENVIORNMENT\fR section on how to set
|
||||
bookmark keys.
|
||||
|
||||
The select bookmark key \fIb\fR lists all the bookmark keys set in \fBNNN_BMS\fR
|
||||
in the bookmarks prompt.
|
||||
.Pp
|
||||
(2) Symlinked bookmarks: A symlinked bookmark to the current directory can
|
||||
be created with the \fIB\fR key (or manually under ~/.config/nnn/bookmarks).
|
||||
|
||||
Pressing 'Enter' at the bookmarks prompt takes to this directory.
|
||||
If \fBNNN_BMS\fR is not set, the select bookmark key directly opens it.
|
||||
.Pp
|
||||
On entering a bookmark, the directory where the select bookmark key was
|
||||
pressed is set as the previous directory. Press '-' to return to it.
|
||||
.Pp
|
||||
.Sh UNITS
|
||||
The minimum file size unit is byte (B). The rest are K, M, G, T, P, E, Z, Y
|
||||
(powers of 1024), same as the default units in \fIls\fR.
|
||||
|
@ -373,9 +407,11 @@ used. A single combination of arguments is supported for SHELL and PAGER.
|
|||
\fBNNN_BMS:\fR bookmark string as \fIkey_char:location\fR pairs
|
||||
separated by \fI;\fR:
|
||||
.Bd -literal
|
||||
export NNN_BMS='d:~/Documents;u:/home/user/Cam Uploads;D:~/Downloads/'
|
||||
export NNN_BMS="d:$HOME/Docs;u:/home/user/Cam Uploads;D:$HOME/Downloads/"
|
||||
.Ed
|
||||
.Pp
|
||||
These bookmarks are listed in the help and config screen (key ?).
|
||||
.Pp
|
||||
\fBNNN_PLUG:\fR directly executable plugins as \fIkey_char:plugin\fR pairs
|
||||
separated by \fI;\fR:
|
||||
.Bd -literal
|
||||
|
@ -386,46 +422,70 @@ separated by \fI;\fR:
|
|||
2. Alternatively, combine with \fIAlt\fR (i.e. \fIAlt+key\fR).
|
||||
3. To skip directory refresh after running a plugin, prefix with \fB-\fR.
|
||||
|
||||
export NNN_PLUG='m:-mediainf'
|
||||
export NNN_PLUG='p:-plugin'
|
||||
.Ed
|
||||
.Pp
|
||||
To assign keys to arbitrary non-background non-shell-interpreted cli
|
||||
commands and invoke like plugins, add \fI_\fR (underscore) before the
|
||||
command.
|
||||
To assign keys to arbitrary non-background cli commands and invoke like
|
||||
plugins, add \fB!\fR before the command.
|
||||
.Bd -literal
|
||||
export NNN_PLUG='x:_chmod +x $nnn;g:_git log;s:_smplayer $nnn'
|
||||
export NNN_PLUG='x:!chmod +x "$nnn";g:!git log;s:!smplayer "$nnn"'
|
||||
|
||||
To pick and run an unassigned plugin, press \fBEnter\fR at the plugin prompt.
|
||||
To run a plugin at startup, use the option `-P` followed by the plugin key.
|
||||
|
||||
NOTES:
|
||||
1. Use single quotes for $NNN_PLUG so $nnn is not interpreted
|
||||
2. $nnn should be the last argument (IF used)
|
||||
3. (Again) add \fB_\fR before the command
|
||||
1. Place $nnn (or exported variables) in double quotes (\fB"$nnn"\fR)
|
||||
2. Use single quotes for $NNN_PLUG so "$nnn" is not interpreted
|
||||
3. (Again) add \fB!\fR before the command
|
||||
4. To disable directory refresh after running a \fIcommand as plugin\fR,
|
||||
prefix with \fB-_\fR
|
||||
prefix with \fB-!\fR
|
||||
5. To skip user confirmation after command execution, suffix with \fB*\fR
|
||||
Note: Do not use \fB*\fR with programs those run and exit e.g. cat
|
||||
|
||||
export NNN_PLUG='y:-_sync*'
|
||||
export NNN_PLUG='y:-!sync*'
|
||||
|
||||
6. To run a \fIGUI app as plugin\fR, add a \fB|\fR after \fB_\fR
|
||||
6. To run a \fIGUI app as plugin\fR, add a \fB&\fR after \fB!\fR.
|
||||
|
||||
export NNN_PLUG='m:-_|mousepad $nnn'
|
||||
export NNN_PLUG='m:-!&mousepad "$nnn"'
|
||||
|
||||
7. To show the output of run-and-exit commands which do not need user input,
|
||||
add \fB|\fR (pipe) after \fB!\fR
|
||||
Note: This option is incompatible with \fB&\fR (terminal output is masked
|
||||
for GUI programs) and ignores \fB*\fR (output is already paged for user).
|
||||
|
||||
export NNN_PLUG='m:-!|mediainfo "$nnn";t:-!|tree -ps;l:-!|ls -lah --group-directories-first'
|
||||
|
||||
EXAMPLES:
|
||||
----------------------------------- + -------------------------------------------------
|
||||
Key:Command | Description
|
||||
----------------------------------- + -------------------------------------------------
|
||||
g:-_git diff | Show git diff
|
||||
k:-_fuser -kiv $nnn* | Interactively kill process(es) using hovered file
|
||||
l:-_git log | Show git log
|
||||
n:-_vi /home/user/Dropbox/dir/note* | Take quick notes in a synced file/dir of notes
|
||||
p:-_less -iR $nnn* | Page through hovered file in less
|
||||
s:-_|smplayer -minigui $nnn | Play hovered media file, even unfinished download
|
||||
x:_chmod +x $nnn | Make the hovered file executable
|
||||
y:-_sync* | Flush cached writes
|
||||
----------------------------------- + -------------------------------------------------
|
||||
------------------------------------ + -------------------------------------------------
|
||||
Key:Command | Description
|
||||
------------------------------------ + -------------------------------------------------
|
||||
c:!convert "$nnn" png:- | xclip | Copy image to clipboard
|
||||
-sel clipboard -t image/png* |
|
||||
C:!cp -rv "$nnn" "$nnn".cp* | Create a copy of the hovered file
|
||||
e:-!sudo -E vim "$nnn"* | Edit file as root in vim
|
||||
g:-!git diff | Show git diff
|
||||
h:-!hx "$nnn"* | Open hovered file in hx hex editor
|
||||
k:-!fuser -kiv "$nnn"* | Interactively kill process(es) using hovered file
|
||||
l:-!git log | Show git log
|
||||
n:-!vi /home/user/Dropbox/dir/note* | Take quick notes in a synced file/dir of notes
|
||||
p:-!less -iR "$nnn"* | Page through hovered file in less
|
||||
s:-!&smplayer -minigui "$nnn" | Play hovered media file, even unfinished download
|
||||
x:!chmod +x "$nnn" | Make the hovered file executable
|
||||
y:-!sync* | Flush cached writes
|
||||
------------------------------------ + -------------------------------------------------
|
||||
|
||||
Online docs: https://github.com/jarun/nnn/tree/master/plugins
|
||||
.Ed
|
||||
.Pp
|
||||
\fBNNN_ORDER:\fR directory-specific sort key.
|
||||
.Bd -literal
|
||||
export NNN_ORDER='t:/home/user/Downloads;S:/tmp'
|
||||
|
||||
NOTE: Sort keys can be a/d/e/r/s/t/v (see program option -T).
|
||||
Capitalize to reverse (except 'r').
|
||||
Path must be absolute.
|
||||
|
||||
Timestamps for entries modified/created within 5 minutes are shown in reverse.
|
||||
.Ed
|
||||
.Pp
|
||||
\fBNNN_COLORS:\fR string of color numbers for each context, e.g.:
|
||||
|
@ -435,7 +495,7 @@ separated by \fI;\fR:
|
|||
export NNN_COLORS='1234'
|
||||
|
||||
# xterm 256 color numbers (converted to hex, 2 symbols per context):
|
||||
# see https://upload.wikimedia.org/wikipedia/commons/1/15/Xterm_256color_chart.svg
|
||||
# see https://user-images.githubusercontent.com/1482942/93023823-46a6ba80-f5e1-11ea-9ea3-6a3c757704f4.png
|
||||
export NNN_COLORS='#0a1b2c3d'
|
||||
|
||||
# both (256 followed by 8 as fallback, separated by ';')
|
||||
|
@ -448,8 +508,7 @@ separated by \fI;\fR:
|
|||
.Bd -literal
|
||||
export NNN_FCOLORS='c1e2272e006033f7c6d6abc4'
|
||||
|
||||
Specify file-specific colors with decimal xterm 256 color numbers converted
|
||||
to 2 hex symbols per color.
|
||||
Specify file-specific colors in xterm 256 color hex numbers (2 symbols per color).
|
||||
Order is strict, use 00 to omit/use default terminal color. Defaults:
|
||||
|
||||
------------------------- + --- + -------------
|
||||
|
@ -470,8 +529,8 @@ separated by \fI;\fR:
|
|||
------------------------- + --- + -------------
|
||||
|
||||
If the terminal supports xterm 256 colors or more, file-specific colors will be rendered.
|
||||
To force the earlier colorscheme use option -C.
|
||||
If xterm 256 colors aren't supported, earlier colorscheme will be used.
|
||||
To force the 8-color scheme use option -C.
|
||||
If xterm 256 colors aren't supported, 8-color scheme will be used.
|
||||
.Ed
|
||||
.Pp
|
||||
\fBNNN_ARCHIVE:\fR archive extensions to be handled silently (default: bzip2, (g)zip, tar).
|
||||
|
@ -481,6 +540,11 @@ separated by \fI;\fR:
|
|||
NOTE: Non-default formats may require a third-party utility.
|
||||
.Ed
|
||||
.Pp
|
||||
\fBNNN_ARCHMNT:\fR optional archive mounter utility (default: archivemount).
|
||||
.Bd -literal
|
||||
export NNN_ARCHIVE='fuse-archive'
|
||||
.Ed
|
||||
.Pp
|
||||
\fBNNN_SSHFS:\fR specify custom sshfs command with options:
|
||||
.Bd -literal
|
||||
export NNN_SSHFS='sshfs -o reconnect,idmap=user,cache_timeout=3600'
|
||||
|
@ -502,6 +566,9 @@ separated by \fI;\fR:
|
|||
.Ed
|
||||
.Pp
|
||||
\fBNNN_SEL:\fR absolute path to custom selection file.
|
||||
.Bd -literal
|
||||
export NNN_SEL='/tmp/.sel'
|
||||
.Ed
|
||||
.Pp
|
||||
\fBNNN_FIFO:\fR path of a named pipe to write the hovered file path:
|
||||
.Bd -literal
|
||||
|
@ -511,16 +578,26 @@ separated by \fI;\fR:
|
|||
1. Overridden by a temporary path with -a option.
|
||||
2. If the FIFO file doesn't exist it will be created,
|
||||
but not removed (unless it is generated by -a option).
|
||||
|
||||
Online docs: https://github.com/jarun/nnn/wiki/Live-previews
|
||||
.Ed
|
||||
.Pp
|
||||
.Em https://github.com/jarun/nnn/wiki/Live-previews
|
||||
.Pp
|
||||
\fBNNN_LOCKER:\fR terminal locker program.
|
||||
.Bd -literal
|
||||
export NNN_LOCKER='bmon -p wlp1s0'
|
||||
export NNN_LOCKER='cmatrix'
|
||||
.Ed
|
||||
.Pp
|
||||
\fBNNN_TMPFILE:\fR \fIalways\fR cd on quit and write the command in the file specified.
|
||||
.Bd -literal
|
||||
export NNN_TMPFILE='/tmp/.lastd'
|
||||
.Ed
|
||||
.Pp
|
||||
\fBNNN_HELP:\fR run a program and show the output on top of the program help page.
|
||||
.Bd -literal
|
||||
export NNN_HELP='fortune'
|
||||
.Ed
|
||||
.Pp
|
||||
\fBNNN_MCLICK:\fR key emulated by a middle mouse click.
|
||||
.Bd -literal
|
||||
export NNN_MCLICK='^R'
|
||||
|
@ -534,10 +611,6 @@ separated by \fI;\fR:
|
|||
.Ed
|
||||
.Pp
|
||||
\fBNO_COLOR:\fR disable ANSI color output (overridden by \fBNNN_COLORS\fR).
|
||||
.Sh KNOWN ISSUES
|
||||
.Nm
|
||||
may not handle keypresses correctly when used with tmux (see issue #104 for
|
||||
more details). Set \fBTERM=xterm-256color\fR to address it.
|
||||
.Sh AUTHORS
|
||||
.An Arun Prakash Jana Aq Mt engineerarun@gmail.com ,
|
||||
.An Lazaros Koromilas Aq Mt lostd@2f30.org ,
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
<h1 align="center">User Patch Framework</h1>
|
||||
|
||||
This directory contains sizable user submitted patches that were rejected from mainline as they tend to be more subjective in nature.
|
||||
|
||||
The patches will be adapted on each release when necessary (v4.1 onwards). Each patch can be applied through its respective make variable during compilation. In case inter-patch merge conflicts occur, a compatibility patch is provided and will automatically be applied.
|
||||
|
||||
## List of patches
|
||||
|
||||
| Patch (a-z) | Description | Make var |
|
||||
| --- | --- | --- |
|
||||
| colemak | Key bindings for Colemak keyboard layout | `O_COLEMAK` |
|
||||
| gitstatus | Add git status column to the detail view. Provides command line flag `-G` to show column in normal mode. | `O_GITSTATUS` |
|
||||
| namefirst | Print filenames first in the detail view. Print user/group columns when a directory contains different users/groups. | `O_NAMEFIRST` |
|
||||
| restorepreview | Add pipe to close and restore [`preview-tui`](https://github.com/jarun/nnn/blob/master/plugins/preview-tui) for internal undetached edits (<kbd>e</kbd> key)| `O_RESTOREPREVIEW` |
|
||||
|
||||
To apply a patch, use the corresponding make variable, e.g.:
|
||||
|
||||
make O_NAMEFIRST=1
|
||||
|
||||
When contributing/adding a new patch, make sure to add the make variable to the patches array in `./misc/test/check-patches.sh` as well so that patch failures can be easily tested.
|
||||
|
||||
## Resolving patch conflicts
|
||||
|
||||
Patch conflicts can be checked locally by running `make checkpatches` or by running `./patches/check-patches.sh` manually.
|
||||
|
||||
Whenever patch conflicts occur on the latest master, pull requests resolving them are welcome. Let's say a conflict occurs in the `restorepreview` patch. The best way to resolve this conflict would be something along the lines of:
|
||||
|
||||
- Ensure you're on latest master and run `PATCH_OPTS="--merge" make O_RESTOREPREVIEW=1`. This will generate the conflict markers in `src/nnn.c`.
|
||||
- Next edit `src/nnn.c`, resolve the conflicts around the conflict markers(`<<<<<<<`), and save.
|
||||
- Then run `git diff > patch.diff && sed -i -e "/^$/{r patch.diff" -e "q;}" patches/restorepreview/mainline.diff` to update the patch.
|
|
@ -0,0 +1,29 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Usage: ./misc/test/check-patches.sh
|
||||
#
|
||||
# Bash script that checks for any of the patches failing to apply.
|
||||
# Read patches/README.md for more information.
|
||||
|
||||
export PATCH_OPTS="--merge"
|
||||
patches=("O_COLEMAK" "O_GITSTATUS" "O_NAMEFIRST" "O_RESTOREPREVIEW")
|
||||
z=$(( 1 << ${#patches[@]} ))
|
||||
pid=$$
|
||||
ret=0
|
||||
trap 'ret=1' SIGUSR1
|
||||
|
||||
for ((n=1; n < z; ++n)); do
|
||||
for ((i=0; i < ${#patches[@]}; ++i)); do
|
||||
printf "%s=%d " "${patches[$i]}" "$(( (n & (1 << i)) != 0 ))"
|
||||
done | tee "/dev/stderr" | (
|
||||
make clean -s
|
||||
if ! xargs make 2>&1; then
|
||||
echo "[FAILED]" >&2
|
||||
kill -SIGUSR1 "$pid"
|
||||
else
|
||||
echo "[SUCCESS]" >&2
|
||||
fi
|
||||
git restore src
|
||||
) >/dev/null
|
||||
done
|
||||
exit "$ret"
|
|
@ -0,0 +1,134 @@
|
|||
diff --git a/src/nnn.c b/src/nnn.c
|
||||
index d7c53166..bb7ff3e8 100644
|
||||
--- a/src/nnn.c
|
||||
+++ b/src/nnn.c
|
||||
@@ -5149,12 +5149,12 @@ static void show_help(const char *path)
|
||||
"2(___n))\n"
|
||||
"0\n"
|
||||
"1NAVIGATION\n"
|
||||
- "9Up k Up%16PgUp ^U Page up\n"
|
||||
- "9Dn j Down%14PgDn ^D Page down\n"
|
||||
+ "9Up e Up%16PgUp ^U Page up\n"
|
||||
+ "9Dn n Down%14PgDn ^D Page down\n"
|
||||
"9Lt h Parent%12~ ` @ - ~, /, start, prev\n"
|
||||
- "5Ret Rt l Open%20' First file/match\n"
|
||||
- "9g ^A Top%21J Jump to entry/offset\n"
|
||||
- "9G ^E End%20^J Toggle auto-advance on open\n"
|
||||
+ "5Ret Rt i Open%20' First file/match\n"
|
||||
+ "9g ^E Top%21J Jump to entry/offset\n"
|
||||
+ "9G ^N End%20^J Toggle auto-advance on open\n"
|
||||
"8B (,) Book(mark)%11b ^/ Select bookmark\n"
|
||||
"a1-4 Context%11(Sh)Tab Cycle/new context\n"
|
||||
"62Esc ^Q Quit%19^y Next young\n"
|
||||
@@ -5162,27 +5162,27 @@ static void show_help(const char *path)
|
||||
"cq Quit context\n"
|
||||
"0\n"
|
||||
"1FILTER & PROMPT\n"
|
||||
- "c/ Filter%17^N Toggle type-to-nav\n"
|
||||
+ "c/ Filter%17^K Toggle type-to-nav\n"
|
||||
"aEsc Exit prompt%12^L Toggle last filter\n"
|
||||
"c. Toggle hidden%05Alt+Esc Unfilter, quit context\n"
|
||||
"0\n"
|
||||
"1FILES\n"
|
||||
- "9o ^O Open with%15n Create new/link\n"
|
||||
+ "9o ^O Open with%15c Create new/link\n"
|
||||
"9f ^F File stats%14d Detail mode toggle\n"
|
||||
"b^R Rename/dup%14r Batch rename\n"
|
||||
- "cz Archive%17e Edit file\n"
|
||||
+ "cz Archive%17y Edit file\n"
|
||||
"c* Toggle exe%14> Export list\n"
|
||||
"6Space + (Un)select%12m-m Select range/clear\n"
|
||||
"ca Select all%14A Invert sel\n"
|
||||
"9p ^P Copy here%12w ^W Cp/mv sel as\n"
|
||||
- "9v ^V Move here%15E Edit sel list\n"
|
||||
+ "9v ^V Move here%15l Edit sel list\n"
|
||||
"9x ^X Delete or trash%09S Listed sel size\n"
|
||||
"cX Delete (rm -rf)%07Esc Send to FIFO\n"
|
||||
"0\n"
|
||||
"1MISC\n"
|
||||
"8Alt ; Select plugin%11= Launch app\n"
|
||||
"9! ^] Shell%19] Cmd prompt\n"
|
||||
- "cc Connect remote%10u Unmount remote/archive\n"
|
||||
+ "cC Connect remote%10u Unmount remote/archive\n"
|
||||
"9t ^T Sort toggles%12s Manage session\n"
|
||||
"cT Set time type%110 Lock\n"
|
||||
"b^L Redraw%18? Help, conf\n"
|
||||
diff --git a/src/nnn.h b/src/nnn.h
|
||||
index bd500244..43b7fa22 100644
|
||||
--- a/src/nnn.h
|
||||
+++ b/src/nnn.h
|
||||
@@ -139,12 +139,12 @@ static struct key bindings[] = {
|
||||
{ '\r', SEL_OPEN },
|
||||
/* Pure navigate inside */
|
||||
{ KEY_RIGHT, SEL_NAV_IN },
|
||||
- { 'l', SEL_NAV_IN },
|
||||
+ { 'i', SEL_NAV_IN },
|
||||
/* Next */
|
||||
- { 'j', SEL_NEXT },
|
||||
+ { 'n', SEL_NEXT },
|
||||
{ KEY_DOWN, SEL_NEXT },
|
||||
/* Previous */
|
||||
- { 'k', SEL_PREV },
|
||||
+ { 'e', SEL_PREV },
|
||||
{ KEY_UP, SEL_PREV },
|
||||
/* Page down */
|
||||
{ KEY_NPAGE, SEL_PGDN },
|
||||
@@ -157,11 +157,11 @@ static struct key bindings[] = {
|
||||
/* First entry */
|
||||
{ KEY_HOME, SEL_HOME },
|
||||
{ 'g', SEL_HOME },
|
||||
- { CONTROL('A'), SEL_HOME },
|
||||
+ { CONTROL('E'), SEL_HOME },
|
||||
/* Last entry */
|
||||
{ KEY_END, SEL_END },
|
||||
{ 'G', SEL_END },
|
||||
- { CONTROL('E'), SEL_END },
|
||||
+ { CONTROL('N'), SEL_END },
|
||||
/* Go to first file */
|
||||
{ '\'', SEL_FIRST },
|
||||
/* Jump to an entry number/offset */
|
||||
@@ -179,7 +179,7 @@ static struct key bindings[] = {
|
||||
{ 'b', SEL_BMOPEN },
|
||||
{ CONTROL('_'), SEL_BMOPEN },
|
||||
/* Connect to server over SSHFS */
|
||||
- { 'c', SEL_REMOTE },
|
||||
+ { 'C', SEL_REMOTE },
|
||||
/* Cycle contexts in forward direction */
|
||||
{ '\t', SEL_CYCLE },
|
||||
/* Cycle contexts in reverse direction */
|
||||
@@ -202,7 +202,7 @@ static struct key bindings[] = {
|
||||
/* Filter */
|
||||
{ '/', SEL_FLTR },
|
||||
/* Toggle filter mode */
|
||||
- { CONTROL('N'), SEL_MFLTR },
|
||||
+ { CONTROL('K'), SEL_MFLTR },
|
||||
/* Toggle hide .dot files */
|
||||
{ '.', SEL_HIDDEN },
|
||||
/* Detailed listing */
|
||||
@@ -229,7 +229,7 @@ static struct key bindings[] = {
|
||||
/* Invert selection in current dir */
|
||||
{ 'A', SEL_SELINV },
|
||||
/* List, edit selection */
|
||||
- { 'E', SEL_SELEDIT },
|
||||
+ { 'l', SEL_SELEDIT },
|
||||
/* Copy from selection buffer */
|
||||
{ 'p', SEL_CP },
|
||||
{ CONTROL('P'), SEL_CP },
|
||||
@@ -247,7 +247,7 @@ static struct key bindings[] = {
|
||||
{ 'o', SEL_OPENWITH },
|
||||
{ CONTROL('O'), SEL_OPENWITH },
|
||||
/* Create a new file */
|
||||
- { 'n', SEL_NEW },
|
||||
+ { 'c', SEL_NEW },
|
||||
/* Show rename prompt */
|
||||
{ CONTROL('R'), SEL_RENAME },
|
||||
/* Rename contents of current dir */
|
||||
@@ -259,7 +259,7 @@ static struct key bindings[] = {
|
||||
/* Toggle auto-advance on file open */
|
||||
{ CONTROL('J'), SEL_AUTONEXT },
|
||||
/* Edit in EDITOR */
|
||||
- { 'e', SEL_EDIT },
|
||||
+ { 'y', SEL_EDIT },
|
||||
/* Run a plugin */
|
||||
{ ';', SEL_PLUGIN },
|
||||
/* Show total size of listed selection */
|
|
@ -0,0 +1,223 @@
|
|||
# Description: Add git status column to detail mode. Provides additional
|
||||
# command line flag -G which will render the git status
|
||||
# column also in normal mode. Vim plugin users may consider
|
||||
# adding the -G flag to their command override.
|
||||
#
|
||||
# Authors: Luuk van Baal
|
||||
|
||||
diff --git a/src/nnn.c b/src/nnn.c
|
||||
index 83ecdb90..4397944a 100644
|
||||
--- a/src/nnn.c
|
||||
+++ b/src/nnn.c
|
||||
@@ -270,6 +270,25 @@
|
||||
#define VFS_USED 1
|
||||
#define VFS_SIZE 2
|
||||
|
||||
+/* Git icons */
|
||||
+#ifdef NERD
|
||||
+#define GIT_ADD ""
|
||||
+#define GIT_DEL ""
|
||||
+#define GIT_IGN ""
|
||||
+#define GIT_MOD ""
|
||||
+#define GIT_NEW ""
|
||||
+#define GIT_NON "-"
|
||||
+#define GIT_UPD ""
|
||||
+#else
|
||||
+#define GIT_ADD "A"
|
||||
+#define GIT_DEL "D"
|
||||
+#define GIT_IGN "!"
|
||||
+#define GIT_MOD "M"
|
||||
+#define GIT_NEW "?"
|
||||
+#define GIT_NON "-"
|
||||
+#define GIT_UPD "U"
|
||||
+#endif
|
||||
+
|
||||
/* TYPE DEFINITIONS */
|
||||
typedef unsigned int uint_t;
|
||||
typedef unsigned char uchar_t;
|
||||
@@ -294,6 +313,7 @@ typedef struct entry {
|
||||
uid_t uid; /* 4 bytes */
|
||||
gid_t gid; /* 4 bytes */
|
||||
#endif
|
||||
+ char git_status[2][5];
|
||||
} *pEntry;
|
||||
|
||||
/* Selection marker */
|
||||
@@ -349,6 +369,7 @@ typedef struct {
|
||||
uint_t cliopener : 1; /* All-CLI app opener */
|
||||
uint_t waitedit : 1; /* For ops that can't be detached, used EDITOR */
|
||||
uint_t rollover : 1; /* Roll over at edges */
|
||||
+ uint_t normalgit : 1; /* Show git status in normal mode */
|
||||
} settings;
|
||||
|
||||
/* Non-persistent program-internal states (alphabeical order) */
|
||||
@@ -400,7 +421,17 @@ typedef struct {
|
||||
} session_header_t;
|
||||
#endif
|
||||
|
||||
+typedef struct {
|
||||
+ char status[2];
|
||||
+ char path[PATH_MAX];
|
||||
+} git_status_t;
|
||||
+
|
||||
/* GLOBALS */
|
||||
+struct {
|
||||
+ bool show;
|
||||
+ size_t len;
|
||||
+ git_status_t *statuses;
|
||||
+} git_statuses;
|
||||
|
||||
/* Configuration, contexts */
|
||||
static settings cfg = {
|
||||
@@ -3796,6 +3827,47 @@ static int get_kv_key(kv *kvarr, char *val, uchar_t max, uchar_t id)
|
||||
return -1;
|
||||
}
|
||||
|
||||
+static size_t get_git_statuses(const char *path)
|
||||
+{
|
||||
+ static char gst[] = "git -c core.quotePath= status -s --no-renames --ignored=matching -unormal . 2>/dev/null";
|
||||
+ FILE *fp = popen(gst, "r");
|
||||
+ char status[PATH_MAX];
|
||||
+ size_t pathindex, i = -1;
|
||||
+ git_statuses.show = FALSE;
|
||||
+
|
||||
+ while (fgets(status, PATH_MAX, fp)) {
|
||||
+ pathindex = (status[3] == '"') ? 4 : 3;
|
||||
+ if (!cfg.showhidden && status[pathindex] == '.')
|
||||
+ continue;
|
||||
+ status[xstrlen(status) - pathindex + 2] = '\0';
|
||||
+ git_statuses.statuses = xrealloc(git_statuses.statuses, sizeof(git_status_t) * (++i + 1));
|
||||
+ git_statuses.statuses[i].status[0] = status[0];
|
||||
+ git_statuses.statuses[i].status[1] = status[1];
|
||||
+ mkpath(path, status + pathindex, git_statuses.statuses[i].path);
|
||||
+ }
|
||||
+
|
||||
+ pclose(fp);
|
||||
+ return (i + 1);
|
||||
+}
|
||||
+
|
||||
+static void set_git_status(char status[][5], uint_t nr)
|
||||
+{
|
||||
+ for (int j = 0; j < 2; j++) {
|
||||
+ if (status[j][0] == '-')
|
||||
+ switch (git_statuses.statuses[nr].status[j]) {
|
||||
+ case ' ': xstrsncpy(status[j], GIT_NON, 4); break;
|
||||
+ case 'M': xstrsncpy(status[j], GIT_MOD, 4); break;
|
||||
+ case 'A': xstrsncpy(status[j], GIT_ADD, 4); break;
|
||||
+ case '?': xstrsncpy(status[j], GIT_NEW, 4); break;
|
||||
+ case '!': xstrsncpy(status[j], GIT_IGN, 4); break;
|
||||
+ case 'D': xstrsncpy(status[j], GIT_DEL, 4); break;
|
||||
+ case 'U': xstrsncpy(status[j], GIT_UPD, 4); break;
|
||||
+ }
|
||||
+ }
|
||||
+ if (git_statuses.statuses[nr].status[1] != '!')
|
||||
+ git_statuses.show = TRUE;
|
||||
+}
|
||||
+
|
||||
static void resetdircolor(int flags)
|
||||
{
|
||||
/* Directories are always shown on top, clear the color when moving to first file */
|
||||
@@ -4123,6 +4195,10 @@ static void printent(const struct entry *ent, uint_t namecols, bool sel)
|
||||
|
||||
uchar_t color_pair = get_color_pair_name_ind(ent, &ind, &attrs);
|
||||
|
||||
+ if (git_statuses.show && (cfg.showdetail || cfg.normalgit))
|
||||
+ printw("%*s%s%s", (cfg.normalgit && !cfg.showdetail) ? 1 : 0, "",
|
||||
+ ent->git_status[0], ent->git_status[1]);
|
||||
+
|
||||
addch((ent->flags & FILE_SELECTED) ? '+' | A_REVERSE | A_BOLD : ' ');
|
||||
|
||||
if (g_state.oldcolor)
|
||||
@@ -5592,6 +5668,11 @@ static int dentfill(char *path, struct entry **ppdents)
|
||||
attron(COLOR_PAIR(cfg.curctx + 1));
|
||||
}
|
||||
|
||||
+ char linkpath[PATH_MAX];
|
||||
+ if ((git_statuses.len = get_git_statuses(path)))
|
||||
+ if (!realpath(path, linkpath))
|
||||
+ printwarn(NULL);
|
||||
+
|
||||
#if _POSIX_C_SOURCE >= 200112L
|
||||
posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL);
|
||||
#endif
|
||||
@@ -5792,6 +5873,29 @@ static int dentfill(char *path, struct entry **ppdents)
|
||||
#endif
|
||||
}
|
||||
|
||||
+ if (git_statuses.len) {
|
||||
+ char dentpath[PATH_MAX];
|
||||
+ size_t pathlen = mkpath(linkpath, dentp->name, dentpath);
|
||||
+ dentp->git_status[0][0] = dentp->git_status[1][0] = '-';
|
||||
+ dentp->git_status[0][1] = dentp->git_status[1][1] = '\0';
|
||||
+
|
||||
+ if (dentp->flags & DIR_OR_DIRLNK) {
|
||||
+ char prefix[PATH_MAX];
|
||||
+ memccpy(prefix, dentpath, '\0', PATH_MAX);
|
||||
+ prefix[pathlen - 1] = '/';
|
||||
+
|
||||
+ for (size_t i = 0; i < git_statuses.len; ++i)
|
||||
+ if (is_prefix(git_statuses.statuses[i].path, prefix, pathlen))
|
||||
+ set_git_status(dentp->git_status, i);
|
||||
+ } else {
|
||||
+ for (size_t i = 0; i < git_statuses.len; ++i)
|
||||
+ if (!xstrcmp(git_statuses.statuses[i].path, dentpath)) {
|
||||
+ set_git_status(dentp->git_status, i);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
++ndents;
|
||||
} while ((dp = readdir(dirp)));
|
||||
|
||||
@@ -6361,11 +6465,12 @@ static int adjust_cols(int n)
|
||||
#endif
|
||||
if (cfg.showdetail) {
|
||||
/* Fallback to light mode if less than 35 columns */
|
||||
- if (n < 36)
|
||||
+ if (n < 38)
|
||||
cfg.showdetail ^= 1;
|
||||
else /* 2 more accounted for below */
|
||||
- n -= 32;
|
||||
- }
|
||||
+ n -= (git_statuses.show ? 34 : 32);
|
||||
+ } else if (cfg.normalgit && git_statuses.show)
|
||||
+ n -= 3;
|
||||
|
||||
/* 2 columns for preceding space and indicator */
|
||||
return (n - 2);
|
||||
@@ -8143,6 +8248,7 @@ static void usage(void)
|
||||
" -F val fifo mode [0:preview 1:explore]\n"
|
||||
#endif
|
||||
" -g regex filters\n"
|
||||
+ " -G always show git status\n"
|
||||
" -H show hidden files\n"
|
||||
" -i show current file info\n"
|
||||
" -J no auto-advance on selection\n"
|
||||
@@ -8282,6 +8388,7 @@ static void cleanup(void)
|
||||
fflush(stdout);
|
||||
}
|
||||
#endif
|
||||
+ free(git_statuses.statuses);
|
||||
free(selpath);
|
||||
free(plgpath);
|
||||
free(cfgpath);
|
||||
@@ -8326,7 +8433,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
while ((opt = (env_opts_id > 0
|
||||
? env_opts[--env_opts_id]
|
||||
- : getopt(argc, argv, "aAb:BcCdDeEfF:gHiJKl:nNop:P:QrRs:St:T:uUVxh"))) != -1) {
|
||||
+ : getopt(argc, argv, "aAb:BcCdDeEfF:gGHiJKl:nNop:P:QrRs:St:T:uUVxh"))) != -1) {
|
||||
switch (opt) {
|
||||
#ifndef NOFIFO
|
||||
case 'a':
|
||||
@@ -8380,6 +8487,9 @@ int main(int argc, char *argv[])
|
||||
cfg.regex = 1;
|
||||
filterfn = &visible_re;
|
||||
break;
|
||||
+ case 'G':
|
||||
+ cfg.normalgit = 1;
|
||||
+ break;
|
||||
case 'H':
|
||||
cfg.showhidden = 1;
|
||||
break;
|
|
@ -0,0 +1,226 @@
|
|||
# Description: Add git status column to detail mode. Provides additional
|
||||
# command line flag -G which will render the git status
|
||||
# column also in normal mode. Vim plugin users may consider
|
||||
# adding the -G flag to their command override.
|
||||
# Compatibility patch for the namefirst patch.
|
||||
#
|
||||
# Authors: Luuk van Baal
|
||||
|
||||
diff --git a/src/nnn.c b/src/nnn.c
|
||||
index 88538787..d4af7c43 100644
|
||||
--- a/src/nnn.c
|
||||
+++ b/src/nnn.c
|
||||
@@ -270,6 +270,25 @@
|
||||
#define VFS_USED 1
|
||||
#define VFS_SIZE 2
|
||||
|
||||
+/* Git icons */
|
||||
+#ifdef NERD
|
||||
+#define GIT_ADD ""
|
||||
+#define GIT_DEL ""
|
||||
+#define GIT_IGN ""
|
||||
+#define GIT_MOD ""
|
||||
+#define GIT_NEW ""
|
||||
+#define GIT_NON "-"
|
||||
+#define GIT_UPD ""
|
||||
+#else
|
||||
+#define GIT_ADD "A"
|
||||
+#define GIT_DEL "D"
|
||||
+#define GIT_IGN "!"
|
||||
+#define GIT_MOD "M"
|
||||
+#define GIT_NEW "?"
|
||||
+#define GIT_NON "-"
|
||||
+#define GIT_UPD "U"
|
||||
+#endif
|
||||
+
|
||||
/* TYPE DEFINITIONS */
|
||||
typedef unsigned int uint_t;
|
||||
typedef unsigned char uchar_t;
|
||||
@@ -294,6 +313,7 @@ typedef struct entry {
|
||||
uid_t uid; /* 4 bytes */
|
||||
gid_t gid; /* 4 bytes */
|
||||
#endif
|
||||
+ char git_status[2][5];
|
||||
} *pEntry;
|
||||
|
||||
/* Selection marker */
|
||||
@@ -349,6 +369,7 @@ typedef struct {
|
||||
uint_t cliopener : 1; /* All-CLI app opener */
|
||||
uint_t waitedit : 1; /* For ops that can't be detached, used EDITOR */
|
||||
uint_t rollover : 1; /* Roll over at edges */
|
||||
+ uint_t normalgit : 1; /* Show git status in normal mode */
|
||||
} settings;
|
||||
|
||||
/* Non-persistent program-internal states (alphabeical order) */
|
||||
@@ -404,7 +425,17 @@ static struct {
|
||||
ushort_t maxnameln, maxsizeln, maxuidln, maxgidln, maxentln, uidln, gidln, printguid;
|
||||
} dtls;
|
||||
|
||||
+typedef struct {
|
||||
+ char status[2];
|
||||
+ char path[PATH_MAX];
|
||||
+} git_status_t;
|
||||
+
|
||||
/* GLOBALS */
|
||||
+struct {
|
||||
+ bool show;
|
||||
+ size_t len;
|
||||
+ git_status_t *statuses;
|
||||
+} git_statuses;
|
||||
|
||||
/* Configuration, contexts */
|
||||
static settings cfg = {
|
||||
@@ -3804,6 +3835,47 @@ static int get_kv_key(kv *kvarr, char *val, uchar_t max, uchar_t id)
|
||||
return -1;
|
||||
}
|
||||
|
||||
+static size_t get_git_statuses(const char *path)
|
||||
+{
|
||||
+ static char gst[] = "git -c core.quotePath= status -s --no-renames --ignored=matching -unormal . 2>/dev/null";
|
||||
+ FILE *fp = popen(gst, "r");
|
||||
+ char status[PATH_MAX];
|
||||
+ size_t pathindex, i = -1;
|
||||
+ git_statuses.show = FALSE;
|
||||
+
|
||||
+ while (fgets(status, PATH_MAX, fp)) {
|
||||
+ pathindex = (status[3] == '"') ? 4 : 3;
|
||||
+ if (!cfg.showhidden && status[pathindex] == '.')
|
||||
+ continue;
|
||||
+ status[xstrlen(status) - pathindex + 2] = '\0';
|
||||
+ git_statuses.statuses = xrealloc(git_statuses.statuses, sizeof(git_status_t) * (++i + 1));
|
||||
+ git_statuses.statuses[i].status[0] = status[0];
|
||||
+ git_statuses.statuses[i].status[1] = status[1];
|
||||
+ mkpath(path, status + pathindex, git_statuses.statuses[i].path);
|
||||
+ }
|
||||
+
|
||||
+ pclose(fp);
|
||||
+ return (i + 1);
|
||||
+}
|
||||
+
|
||||
+static void set_git_status(char status[][5], uint_t nr)
|
||||
+{
|
||||
+ for (int j = 0; j < 2; j++) {
|
||||
+ if (status[j][0] == '-')
|
||||
+ switch (git_statuses.statuses[nr].status[j]) {
|
||||
+ case ' ': xstrsncpy(status[j], GIT_NON, 4); break;
|
||||
+ case 'M': xstrsncpy(status[j], GIT_MOD, 4); break;
|
||||
+ case 'A': xstrsncpy(status[j], GIT_ADD, 4); break;
|
||||
+ case '?': xstrsncpy(status[j], GIT_NEW, 4); break;
|
||||
+ case '!': xstrsncpy(status[j], GIT_IGN, 4); break;
|
||||
+ case 'D': xstrsncpy(status[j], GIT_DEL, 4); break;
|
||||
+ case 'U': xstrsncpy(status[j], GIT_UPD, 4); break;
|
||||
+ }
|
||||
+ }
|
||||
+ if (git_statuses.statuses[nr].status[1] != '!')
|
||||
+ git_statuses.show = TRUE;
|
||||
+}
|
||||
+
|
||||
static void resetdircolor(int flags)
|
||||
{
|
||||
/* Directories are always shown on top, clear the color when moving to first file */
|
||||
@@ -4104,6 +4176,9 @@ static void printent(const struct entry *ent, uint_t namecols, bool sel)
|
||||
int attrs = 0, namelen;
|
||||
uchar_t color_pair = get_color_pair_name_ind(ent, &ind, &attrs);
|
||||
|
||||
+ if (git_statuses.show && (cfg.showdetail || cfg.normalgit))
|
||||
+ printw(" %s%s", ent->git_status[0], ent->git_status[1]);
|
||||
+
|
||||
addch((ent->flags & FILE_SELECTED) ? '+' | A_REVERSE | A_BOLD : ' ');
|
||||
|
||||
if (g_state.oldcolor)
|
||||
@@ -5598,6 +5673,11 @@ static int dentfill(char *path, struct entry **ppdents)
|
||||
attron(COLOR_PAIR(cfg.curctx + 1));
|
||||
}
|
||||
|
||||
+ char linkpath[PATH_MAX];
|
||||
+ if ((git_statuses.len = get_git_statuses(path)))
|
||||
+ if (!realpath(path, linkpath))
|
||||
+ printwarn(NULL);
|
||||
+
|
||||
#if _POSIX_C_SOURCE >= 200112L
|
||||
posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL);
|
||||
#endif
|
||||
@@ -5798,6 +5878,29 @@ static int dentfill(char *path, struct entry **ppdents)
|
||||
#endif
|
||||
}
|
||||
|
||||
+ if (git_statuses.len) {
|
||||
+ char dentpath[PATH_MAX];
|
||||
+ size_t pathlen = mkpath(linkpath, dentp->name, dentpath);
|
||||
+ dentp->git_status[0][0] = dentp->git_status[1][0] = '-';
|
||||
+ dentp->git_status[0][1] = dentp->git_status[1][1] = '\0';
|
||||
+
|
||||
+ if (dentp->flags & DIR_OR_DIRLNK) {
|
||||
+ char prefix[PATH_MAX];
|
||||
+ memccpy(prefix, dentpath, '\0', PATH_MAX);
|
||||
+ prefix[pathlen - 1] = '/';
|
||||
+
|
||||
+ for (size_t i = 0; i < git_statuses.len; ++i)
|
||||
+ if (is_prefix(git_statuses.statuses[i].path, prefix, pathlen))
|
||||
+ set_git_status(dentp->git_status, i);
|
||||
+ } else {
|
||||
+ for (size_t i = 0; i < git_statuses.len; ++i)
|
||||
+ if (!xstrcmp(git_statuses.statuses[i].path, dentpath)) {
|
||||
+ set_git_status(dentp->git_status, i);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
++ndents;
|
||||
} while ((dp = readdir(dirp)));
|
||||
|
||||
@@ -6362,7 +6465,8 @@ static int adjust_cols(int n)
|
||||
cfg.showdetail ^= 1;
|
||||
else /* 2 more accounted for below */
|
||||
n -= (dtls.maxentln - 2 - dtls.maxnameln);
|
||||
- }
|
||||
+ } else if (cfg.normalgit && git_statuses.show)
|
||||
+ n -= 3;
|
||||
|
||||
/* 2 columns for preceding space and indicator */
|
||||
return (n - 2);
|
||||
@@ -6517,7 +6621,7 @@ static void redraw(char *path)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
- dtls.maxentln = dtls.maxnameln + dtls.maxsizeln + (dtls.printguid ? (dtls.maxuidln + dtls.maxgidln + 29) : 26);
|
||||
+ dtls.maxentln = dtls.maxnameln + dtls.maxsizeln + (dtls.printguid ? (dtls.maxuidln + dtls.maxgidln + 3) : 0) + (git_statuses.show ? 29 : 26);
|
||||
}
|
||||
|
||||
ncols = adjust_cols(ncols);
|
||||
@@ -8153,6 +8257,7 @@ static void usage(void)
|
||||
" -F val fifo mode [0:preview 1:explore]\n"
|
||||
#endif
|
||||
" -g regex filters\n"
|
||||
+ " -G always show git status\n"
|
||||
" -H show hidden files\n"
|
||||
" -i show current file info\n"
|
||||
" -J no auto-advance on selection\n"
|
||||
@@ -8292,6 +8397,7 @@ static void cleanup(void)
|
||||
fflush(stdout);
|
||||
}
|
||||
#endif
|
||||
+ free(git_statuses.statuses);
|
||||
free(selpath);
|
||||
free(plgpath);
|
||||
free(cfgpath);
|
||||
@@ -8336,7 +8442,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
while ((opt = (env_opts_id > 0
|
||||
? env_opts[--env_opts_id]
|
||||
- : getopt(argc, argv, "aAb:BcCdDeEfF:gHiJKl:nNop:P:QrRs:St:T:uUVxh"))) != -1) {
|
||||
+ : getopt(argc, argv, "aAb:BcCdDeEfF:gGHiJKl:nNop:P:QrRs:St:T:uUVxh"))) != -1) {
|
||||
switch (opt) {
|
||||
#ifndef NOFIFO
|
||||
case 'a':
|
||||
@@ -8390,6 +8496,9 @@ int main(int argc, char *argv[])
|
||||
cfg.regex = 1;
|
||||
filterfn = &visible_re;
|
||||
break;
|
||||
+ case 'G':
|
||||
+ cfg.normalgit = 1;
|
||||
+ break;
|
||||
case 'H':
|
||||
cfg.showhidden = 1;
|
||||
break;
|
|
@ -0,0 +1,227 @@
|
|||
# Description: Prints filenames first in the detail view. Prints user/group
|
||||
# columns when a directory contains different users/groups.
|
||||
#
|
||||
# Author: Luuk van Baal
|
||||
|
||||
diff --git a/src/nnn.c b/src/nnn.c
|
||||
index f8a2c58..9802a1f 100644
|
||||
--- a/src/nnn.c
|
||||
+++ b/src/nnn.c
|
||||
@@ -394,6 +394,10 @@ typedef struct {
|
||||
} session_header_t;
|
||||
#endif
|
||||
|
||||
+static struct {
|
||||
+ ushort_t maxnameln, maxsizeln, maxuidln, maxgidln, maxentln, uidln, gidln, printguid;
|
||||
+} dtls;
|
||||
+
|
||||
/* GLOBALS */
|
||||
|
||||
/* Configuration, contexts */
|
||||
@@ -1070,10 +1074,12 @@ static char *getpwname(uid_t uid)
|
||||
static char *namecache;
|
||||
|
||||
if (uidcache != uid) {
|
||||
+ if (dtls.maxuidln && !dtls.printguid) dtls.printguid = 1;
|
||||
struct passwd *pw = getpwuid(uid);
|
||||
|
||||
uidcache = uid;
|
||||
namecache = pw ? pw->pw_name : NULL;
|
||||
+ dtls.uidln = xstrlen(namecache ? namecache : xitoa(uid));
|
||||
}
|
||||
|
||||
return namecache ? namecache : xitoa(uid);
|
||||
@@ -1085,10 +1091,12 @@ static char *getgrname(gid_t gid)
|
||||
static char *grpcache;
|
||||
|
||||
if (gidcache != gid) {
|
||||
+ if (dtls.maxgidln && !dtls.printguid) dtls.printguid = 1;
|
||||
struct group *gr = getgrgid(gid);
|
||||
|
||||
gidcache = gid;
|
||||
grpcache = gr ? gr->gr_name : NULL;
|
||||
+ dtls.gidln = xstrlen(grpcache ? grpcache : xitoa(gid));
|
||||
}
|
||||
|
||||
return grpcache ? grpcache : xitoa(gid);
|
||||
@@ -3834,14 +3842,13 @@ static void resetdircolor(int flags)
|
||||
* Max supported str length: NAME_MAX;
|
||||
*/
|
||||
#ifdef NOLC
|
||||
-static char *unescape(const char *str, uint_t maxcols)
|
||||
+static size_t unescape(const char *str, uint_t maxcols)
|
||||
{
|
||||
char * const wbuf = g_buf;
|
||||
char *buf = wbuf;
|
||||
-
|
||||
- xstrsncpy(wbuf, str, maxcols);
|
||||
+ size_t len = xstrsncpy(wbuf, str, maxcols);
|
||||
#else
|
||||
-static wchar_t *unescape(const char *str, uint_t maxcols)
|
||||
+static size_t unescape(const char *str, uint_t maxcols)
|
||||
{
|
||||
wchar_t * const wbuf = (wchar_t *)g_buf;
|
||||
wchar_t *buf = wbuf;
|
||||
@@ -3866,7 +3873,7 @@ static wchar_t *unescape(const char *str, uint_t maxcols)
|
||||
++buf;
|
||||
}
|
||||
|
||||
- return wbuf;
|
||||
+ return len;
|
||||
}
|
||||
|
||||
static off_t get_size(off_t size, off_t *pval, int comp)
|
||||
@@ -4228,38 +4235,13 @@ static void printent(int pdents_index, uint_t namecols, bool sel)
|
||||
{
|
||||
const struct entry *ent = &pdents[pdents_index];
|
||||
char ind = '\0';
|
||||
- int attrs;
|
||||
-
|
||||
- if (cfg.showdetail) {
|
||||
- int type = ent->mode & S_IFMT;
|
||||
- char perms[6] = {' ', ' ', (char)('0' + ((ent->mode >> 6) & 7)),
|
||||
- (char)('0' + ((ent->mode >> 3) & 7)),
|
||||
- (char)('0' + (ent->mode & 7)), '\0'};
|
||||
-
|
||||
- addch(' ');
|
||||
- attrs = g_state.oldcolor ? (resetdircolor(ent->flags), A_DIM)
|
||||
- : (fcolors[C_MIS] ? COLOR_PAIR(C_MIS) : 0);
|
||||
- if (attrs)
|
||||
- attron(attrs);
|
||||
-
|
||||
- /* Print details */
|
||||
- print_time(&ent->sec, ent->flags);
|
||||
-
|
||||
- printw("%s%9s ", perms, (type == S_IFREG || type == S_IFDIR)
|
||||
- ? coolsize(cfg.blkorder ? (blkcnt_t)ent->blocks << blk_shift : ent->size)
|
||||
- : (type = (uchar_t)get_detail_ind(ent->mode), (char *)&type));
|
||||
-
|
||||
- if (attrs)
|
||||
- attroff(attrs);
|
||||
- }
|
||||
+ int attrs = 0, namelen;
|
||||
|
||||
if (g_state.showlines) {
|
||||
ptrdiff_t rel_num = pdents_index - cur;
|
||||
printw(rel_num == 0 ? "%4td" : "%+4td", rel_num);
|
||||
}
|
||||
|
||||
- attrs = 0;
|
||||
-
|
||||
uchar_t color_pair = get_color_pair_name_ind(ent, &ind, &attrs);
|
||||
|
||||
addch((ent->flags & FILE_SELECTED) ? '+' | A_REVERSE | A_BOLD : ' ');
|
||||
@@ -4284,15 +4266,40 @@ static void printent(int pdents_index, uint_t namecols, bool sel)
|
||||
++namecols;
|
||||
|
||||
#ifndef NOLC
|
||||
- addwstr(unescape(ent->name, namecols));
|
||||
+ addwstr((namelen = unescape(ent->name, namecols), (wchar_t *)g_buf));
|
||||
#else
|
||||
- addstr(unescape(ent->name, MIN(namecols, ent->nlen) + 1));
|
||||
+ addstr((namelen = unescape(ent->name, MIN(namecols, ent->nlen) + 1), (char *)g_buf));
|
||||
#endif
|
||||
|
||||
- if (attrs)
|
||||
+ if (!sel && attrs)
|
||||
attroff(attrs);
|
||||
if (ind)
|
||||
addch(ind);
|
||||
+ if (cfg.showdetail) {
|
||||
+ int type = ent->mode & S_IFMT;
|
||||
+ char perms[6] = {(char)('0' + ((ent->mode >> 6) & 7)),
|
||||
+ (char)('0' + ((ent->mode >> 3) & 7)),
|
||||
+ (char)('0' + (ent->mode & 7)), ' ', ' ', '\0'}, *size = NULL;
|
||||
+
|
||||
+ if (attrs)
|
||||
+ attron(attrs);
|
||||
+ if (!g_state.oldcolor && (type == S_IFDIR || (type == S_IFLNK && ent->flags & DIR_OR_DIRLNK)))
|
||||
+ attroff(A_BOLD);
|
||||
+ int sizelen = (type == S_IFREG || type == S_IFDIR) ? xstrlen(size = coolsize(cfg.blkorder ? ent->blocks << blk_shift : ent->size)) : 1;
|
||||
+ printw("%*c%*s%s%s", 1 + MIN(namecols, dtls.maxnameln + (uint_t)(ind ? 0 : 1)) - namelen, ' ',
|
||||
+ dtls.maxsizeln - sizelen, "", size ? size : (type = (uchar_t)get_detail_ind(ent->mode), (char *)&type), " ");
|
||||
+#ifndef NOUG
|
||||
+ if (g_state.uidgid && dtls.printguid) {
|
||||
+ addstr(getpwname(ent->uid));
|
||||
+ printw("%*c%s", dtls.maxuidln + 1 - dtls.uidln, ' ', getgrname(ent->gid));
|
||||
+ printw("%*c", dtls.maxgidln + 2 - dtls.gidln, ' ');
|
||||
+ }
|
||||
+#endif
|
||||
+ addstr(perms);
|
||||
+ print_time(&ent->sec, ent->flags);
|
||||
+ }
|
||||
+ if (attrs)
|
||||
+ attroff(attrs);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -6527,26 +6534,19 @@ static void statusbar(char *path)
|
||||
tocursor();
|
||||
}
|
||||
|
||||
-static inline void markhovered(void)
|
||||
-{
|
||||
- if (cfg.showdetail && ndents) { /* Bold forward arrowhead */
|
||||
- tocursor();
|
||||
- addch('>' | A_BOLD);
|
||||
- }
|
||||
-}
|
||||
-
|
||||
static int adjust_cols(int n)
|
||||
{
|
||||
/* Calculate the number of cols available to print entry name */
|
||||
#ifdef ICONS_ENABLED
|
||||
n -= (g_state.oldcolor ? 0 : ICON_SIZE + ICON_PADDING_LEFT_LEN + ICON_PADDING_RIGHT_LEN);
|
||||
#endif
|
||||
+
|
||||
if (cfg.showdetail) {
|
||||
/* Fallback to light mode if less than 35 columns */
|
||||
- if (n < 36)
|
||||
+ if (n < (dtls.maxentln + 1 - dtls.maxnameln))
|
||||
cfg.showdetail ^= 1;
|
||||
else /* 2 more accounted for below */
|
||||
- n -= 32;
|
||||
+ n -= (dtls.maxentln - 2 - dtls.maxnameln);
|
||||
}
|
||||
|
||||
/* 2 columns for preceding space and indicator */
|
||||
@@ -6412,8 +6411,6 @@ static void draw_line(int ncols)
|
||||
/* Must reset e.g. no files in dir */
|
||||
if (dir)
|
||||
attroff(COLOR_PAIR(cfg.curctx + 1) | A_BOLD);
|
||||
-
|
||||
- markhovered();
|
||||
}
|
||||
|
||||
static void redraw(char *path)
|
||||
@@ -6521,6 +6518,21 @@ static void redraw(char *path)
|
||||
|
||||
onscreen = MIN(onscreen + curscroll, ndents);
|
||||
|
||||
+ if (cfg.showdetail) {
|
||||
+ ushort_t lenbuf = dtls.maxnameln = dtls.maxsizeln = dtls.maxuidln = dtls.maxgidln = dtls.printguid = 0;
|
||||
+ for (i = curscroll; i < onscreen; ++i) {
|
||||
+ if ((lenbuf = pdents[i].nlen - 1) > dtls.maxnameln) dtls.maxnameln = lenbuf;
|
||||
+ if ((lenbuf = xstrlen(coolsize(cfg.blkorder ? pdents[i].blocks << blk_shift : pdents[i].size))) > dtls.maxsizeln) dtls.maxsizeln = lenbuf;
|
||||
+#ifndef NOUG
|
||||
+ if (g_state.uidgid) {
|
||||
+ if ((getpwname(pdents[i].uid), dtls.uidln) > dtls.maxuidln) dtls.maxuidln = dtls.uidln;
|
||||
+ if ((getgrname(pdents[i].gid), dtls.gidln) > dtls.maxgidln) dtls.maxgidln = dtls.gidln;
|
||||
+ }
|
||||
+#endif
|
||||
+ }
|
||||
+ dtls.maxentln = dtls.maxnameln + dtls.maxsizeln + (dtls.printguid ? (dtls.maxuidln + dtls.maxgidln + 29) : 26);
|
||||
+ }
|
||||
+
|
||||
ncols = adjust_cols(ncols);
|
||||
|
||||
int len = scanselforpath(path, FALSE);
|
||||
@@ -6551,7 +6563,7 @@ static void redraw(char *path)
|
||||
#endif
|
||||
}
|
||||
|
||||
- markhovered();
|
||||
+ statusbar(path);
|
||||
}
|
||||
|
||||
static bool cdprep(char *lastdir, char *lastname, char *path, char *newpath)
|
|
@ -0,0 +1,269 @@
|
|||
# Description: Adds preview pipe to enable closing and re-opening the preview
|
||||
# pane when running an undetached editor. If you are using vim
|
||||
# you might experience incorrectly resized window. Consider adding
|
||||
# the following to your vimrc:
|
||||
# autocmd VimEnter * :silent exec "!kill -s WINCH $PPID"
|
||||
#
|
||||
# Authors: Luuk van Baal
|
||||
|
||||
diff --git a/src/nnn.c b/src/nnn.c
|
||||
index 0388b23c..66d3316a 100644
|
||||
--- a/src/nnn.c
|
||||
+++ b/src/nnn.c
|
||||
@@ -391,7 +391,8 @@ typedef struct {
|
||||
uint_t usebsdtar : 1; /* Use bsdtar as default archive utility */
|
||||
uint_t xprompt : 1; /* Use native prompt instead of readline prompt */
|
||||
uint_t showlines : 1; /* Show line numbers */
|
||||
- uint_t reserved : 3; /* Adjust when adding/removing a field */
|
||||
+ uint_t previewer : 1; /* Run state of previewer */
|
||||
+ uint_t reserved : 2; /* Adjust when adding/removing a field */
|
||||
} runstate;
|
||||
|
||||
/* Contexts or workspaces */
|
||||
@@ -516,6 +517,9 @@ alignas(max_align_t) static char g_tmpfpath[TMP_LEN_MAX];
|
||||
/* Buffer to store plugins control pipe location */
|
||||
alignas(max_align_t) static char g_pipepath[TMP_LEN_MAX];
|
||||
|
||||
+/* Buffer to store preview plugins control pipe location */
|
||||
+static char g_ppipepath[TMP_LEN_MAX] __attribute__ ((aligned));
|
||||
+
|
||||
/* Non-persistent runtime states */
|
||||
static runstate g_state;
|
||||
|
||||
@@ -696,12 +700,13 @@ static const char * const messages[] = {
|
||||
#define NNN_FCOLORS 5
|
||||
#define NNNLVL 6
|
||||
#define NNN_PIPE 7
|
||||
-#define NNN_MCLICK 8
|
||||
-#define NNN_SEL 9
|
||||
-#define NNN_ARCHIVE 10
|
||||
-#define NNN_ORDER 11
|
||||
-#define NNN_HELP 12 /* strings end here */
|
||||
-#define NNN_TRASH 13 /* flags begin here */
|
||||
+#define NNN_PPIPE 8
|
||||
+#define NNN_MCLICK 9
|
||||
+#define NNN_SEL 10
|
||||
+#define NNN_ARCHIVE 11
|
||||
+#define NNN_ORDER 12
|
||||
+#define NNN_HELP 13 /* strings end here */
|
||||
+#define NNN_TRASH 14 /* flags begin here */
|
||||
|
||||
static const char * const env_cfg[] = {
|
||||
"NNN_OPTS",
|
||||
@@ -712,6 +717,7 @@ static const char * const env_cfg[] = {
|
||||
"NNN_FCOLORS",
|
||||
"NNNLVL",
|
||||
"NNN_PIPE",
|
||||
+ "NNN_PPIPE",
|
||||
"NNN_MCLICK",
|
||||
"NNN_SEL",
|
||||
"NNN_ARCHIVE",
|
||||
@@ -850,7 +856,7 @@ static int set_sort_flags(int r);
|
||||
static void statusbar(char *path);
|
||||
static bool get_output(char *file, char *arg1, char *arg2, int fdout, bool page);
|
||||
#ifndef NOFIFO
|
||||
-static void notify_fifo(bool force);
|
||||
+static void notify_fifo(bool force, bool closepreview);
|
||||
#endif
|
||||
|
||||
/* Functions */
|
||||
@@ -3140,7 +3146,7 @@ try_quit:
|
||||
} else {
|
||||
#ifndef NOFIFO
|
||||
if (!g_state.fifomode)
|
||||
- notify_fifo(TRUE); /* Send hovered path to NNN_FIFO */
|
||||
+ notify_fifo(TRUE, FALSE); /* Send hovered path to NNN_FIFO */
|
||||
#endif
|
||||
escaped = TRUE;
|
||||
settimeout();
|
||||
@@ -5258,15 +5264,20 @@ static void run_cmd_as_plugin(const char *file, uchar_t flags)
|
||||
|
||||
static bool plctrl_init(void)
|
||||
{
|
||||
- size_t len;
|
||||
+ size_t len, lenbuf;
|
||||
+ pid_t pid = getpid();
|
||||
|
||||
/* g_tmpfpath is used to generate tmp file names */
|
||||
g_tmpfpath[tmpfplen - 1] = '\0';
|
||||
- len = xstrsncpy(g_pipepath, g_tmpfpath, TMP_LEN_MAX);
|
||||
+ len = lenbuf = xstrsncpy(g_pipepath, g_tmpfpath, TMP_LEN_MAX);
|
||||
g_pipepath[len - 1] = '/';
|
||||
- len = xstrsncpy(g_pipepath + len, "nnn-pipe.", TMP_LEN_MAX - len) + len;
|
||||
- xstrsncpy(g_pipepath + len - 1, xitoa(getpid()), TMP_LEN_MAX - len);
|
||||
+ xstrsncpy(g_ppipepath, g_pipepath, TMP_LEN_MAX);
|
||||
+ len += xstrsncpy(g_pipepath + len, "nnn-pipe.", TMP_LEN_MAX - len);
|
||||
+ xstrsncpy(g_pipepath + len - 1, xitoa(pid), TMP_LEN_MAX - len);
|
||||
+ len = xstrsncpy(g_ppipepath + lenbuf, "nnn-ppipe.", TMP_LEN_MAX - lenbuf) + lenbuf;
|
||||
+ xstrsncpy(g_ppipepath + len - 1, xitoa(pid), TMP_LEN_MAX - len);
|
||||
setenv(env_cfg[NNN_PIPE], g_pipepath, TRUE);
|
||||
+ setenv(env_cfg[NNN_PPIPE], g_ppipepath, TRUE);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -5295,6 +5306,21 @@ static ssize_t read_nointr(int fd, void *buf, size_t count)
|
||||
return len;
|
||||
}
|
||||
|
||||
+void *previewpipe(void *arg __attribute__ ((unused)))
|
||||
+{
|
||||
+ int fd, buf;
|
||||
+
|
||||
+ mkfifo(g_ppipepath, 0600);
|
||||
+ fd = open(g_ppipepath, O_RDONLY);
|
||||
+
|
||||
+ if (read(fd, &buf, 1) == 1)
|
||||
+ g_state.previewer = buf;
|
||||
+
|
||||
+ close(fd);
|
||||
+ unlink(g_ppipepath);
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
static char *readpipe(int fd, char *ctxnum, char **path)
|
||||
{
|
||||
char ctx, *nextpath = NULL;
|
||||
@@ -5979,7 +6005,7 @@ static void populate(char *path, char *lastname)
|
||||
}
|
||||
|
||||
#ifndef NOFIFO
|
||||
-static void notify_fifo(bool force)
|
||||
+static void notify_fifo(bool force, bool closepreview)
|
||||
{
|
||||
if (!fifopath)
|
||||
return;
|
||||
@@ -5995,6 +6021,12 @@ static void notify_fifo(bool force)
|
||||
}
|
||||
}
|
||||
|
||||
+ if (closepreview) {
|
||||
+ if (write(fifofd, "close\n", 6) != 6)
|
||||
+ xerror();
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
static struct entry lastentry;
|
||||
|
||||
if (!force && !memcmp(&lastentry, &pdents[cur], sizeof(struct entry))) // NOLINT
|
||||
@@ -6027,7 +6059,7 @@ static void send_to_explorer(int *presel)
|
||||
if (fd > 1)
|
||||
close(fd);
|
||||
} else
|
||||
- notify_fifo(TRUE); /* Send opened path to NNN_FIFO */
|
||||
+ notify_fifo(TRUE, FALSE); /* Send opened path to NNN_FIFO */
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -6060,7 +6092,7 @@ static void move_cursor(int target, int ignore_scrolloff)
|
||||
|
||||
#ifndef NOFIFO
|
||||
if (!g_state.fifomode)
|
||||
- notify_fifo(FALSE); /* Send hovered path to NNN_FIFO */
|
||||
+ notify_fifo(FALSE, FALSE); /* Send hovered path to NNN_FIFO */
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -6733,7 +6765,7 @@ static bool browse(char *ipath, const char *session, int pkey)
|
||||
pEntry pent;
|
||||
enum action sel;
|
||||
struct stat sb;
|
||||
- int r = -1, presel, selstartid = 0, selendid = 0;
|
||||
+ int r = -1, presel, selstartid = 0, selendid = 0, previewkey = 0;
|
||||
const uchar_t opener_flags = (cfg.cliopener ? F_CLI : (F_NOTRACE | F_NOSTDIN | F_NOWAIT));
|
||||
bool watch = FALSE, cd = TRUE;
|
||||
ino_t inode = 0;
|
||||
@@ -6991,7 +7023,7 @@ nochange:
|
||||
move_cursor(r, 1);
|
||||
#ifndef NOFIFO
|
||||
else if ((event.bstate == BUTTON1_PRESSED) && !g_state.fifomode)
|
||||
- notify_fifo(TRUE); /* Send clicked path to NNN_FIFO */
|
||||
+ notify_fifo(TRUE, FALSE); /* Send clicked path to NNN_FIFO */
|
||||
#endif
|
||||
/* Handle right click selection */
|
||||
if (event.bstate == BUTTON3_PRESSED) {
|
||||
@@ -7153,7 +7185,14 @@ nochange:
|
||||
&& strstr(g_buf, "text")
|
||||
#endif
|
||||
) {
|
||||
+ if (g_state.previewer)
|
||||
+ notify_fifo(FALSE, TRUE);
|
||||
spawn(editor, newpath, NULL, NULL, F_CLI);
|
||||
+ if (g_state.previewer) {
|
||||
+ pkey = previewkey;
|
||||
+ goto run_plugin;
|
||||
+ }
|
||||
+
|
||||
if (cfg.filtermode) {
|
||||
presel = FILTER;
|
||||
clearfilter();
|
||||
@@ -7471,8 +7510,14 @@ nochange:
|
||||
copycurname();
|
||||
goto nochange;
|
||||
case SEL_EDIT:
|
||||
+ if (g_state.previewer)
|
||||
+ notify_fifo(FALSE, TRUE);
|
||||
if (!(g_state.picker || g_state.fifomode))
|
||||
spawn(editor, newpath, NULL, NULL, F_CLI);
|
||||
+ if (g_state.previewer) {
|
||||
+ pkey = previewkey;
|
||||
+ goto run_plugin;
|
||||
+ }
|
||||
continue;
|
||||
default: /* SEL_LOCK */
|
||||
lock_terminal();
|
||||
@@ -7860,6 +7905,7 @@ nochange:
|
||||
cd = FALSE;
|
||||
goto begin;
|
||||
}
|
||||
+run_plugin:
|
||||
case SEL_PLUGIN:
|
||||
/* Check if directory is accessible */
|
||||
if (!xdiraccess(plgpath)) {
|
||||
@@ -7885,6 +7931,12 @@ nochange:
|
||||
goto nochange;
|
||||
}
|
||||
|
||||
+ if (xstrcmp(tmp, "preview-tui") == 0) {
|
||||
+ previewkey = r;
|
||||
+ pthread_t tid;
|
||||
+ pthread_create(&tid, NULL, previewpipe, NULL);
|
||||
+ }
|
||||
+
|
||||
if (tmp[0] == '-' && tmp[1]) {
|
||||
++tmp;
|
||||
r = FALSE; /* Do not refresh dir after completion */
|
||||
@@ -7943,7 +7995,13 @@ nochange:
|
||||
case SEL_SHELL: // fallthrough
|
||||
case SEL_LAUNCH: // fallthrough
|
||||
case SEL_PROMPT:
|
||||
+ if (g_state.previewer)
|
||||
+ notify_fifo(FALSE, TRUE);
|
||||
r = handle_cmd(sel, path, newpath);
|
||||
+ if (g_state.previewer) {
|
||||
+ pkey = previewkey;
|
||||
+ goto run_plugin;
|
||||
+ }
|
||||
|
||||
/* Continue in type-to-nav mode, if enabled */
|
||||
if (cfg.filtermode)
|
||||
@@ -8492,8 +8550,10 @@ static void cleanup(void)
|
||||
if (g_state.autofifo)
|
||||
unlink(fifopath);
|
||||
#endif
|
||||
- if (g_state.pluginit)
|
||||
+ if (g_state.pluginit){
|
||||
unlink(g_pipepath);
|
||||
+ unlink(g_ppipepath);
|
||||
+ }
|
||||
#ifdef DEBUG
|
||||
disabledbg();
|
||||
#endif
|
||||
@@ -9020,7 +9080,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
#ifndef NOFIFO
|
||||
if (!g_state.fifomode)
|
||||
- notify_fifo(FALSE);
|
||||
+ notify_fifo(FALSE, TRUE);
|
||||
if (fifofd != -1)
|
||||
close(fifofd);
|
||||
#endif
|
|
@ -22,29 +22,30 @@
|
|||
IFS="$(printf '%b_' '\n')"; IFS="${IFS%_}" # protect trailing \n
|
||||
|
||||
selection=${NNN_SEL:-${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.selection}
|
||||
[ -s "$selection" ] || { echo "plugin .cbcp error: empty selection" >&2 ; exit 1; }
|
||||
|
||||
if which xsel >/dev/null 2>&1; then
|
||||
# Linux
|
||||
tr '\0' '\n' < "$selection" | xsel -bi
|
||||
elif which xclip >/dev/null 2>&1; then
|
||||
# Linux
|
||||
tr '\0' '\n' < "$selection" | xclip -sel clip
|
||||
elif which pbcopy >/dev/null 2>&1; then
|
||||
# macOS
|
||||
tr '\0' '\n' < "$selection" | pbcopy
|
||||
elif which termux-clipboard-set >/dev/null 2>&1; then
|
||||
# Termux
|
||||
tr '\0' '\n' < "$selection" | termux-clipboard-set
|
||||
elif which clip.exe >/dev/null 2>&1; then
|
||||
# WSL
|
||||
tr '\0' '\n' < "$selection" | clip.exe
|
||||
elif which clip >/dev/null 2>&1; then
|
||||
# Cygwin
|
||||
tr '\0' '\n' < "$selection" | clip
|
||||
elif which wl-copy >/dev/null 2>&1; then
|
||||
if [ "$XDG_SESSION_TYPE" = "wayland" ]; then
|
||||
# Wayland
|
||||
tr '\0' '\n' < "$selection" | wl-copy
|
||||
elif which clipboard >/dev/null 2>&1; then
|
||||
elif type xsel >/dev/null 2>&1; then
|
||||
# Linux
|
||||
tr '\0' '\n' < "$selection" | xsel -bi
|
||||
elif type xclip >/dev/null 2>&1; then
|
||||
# Linux
|
||||
tr '\0' '\n' < "$selection" | xclip -sel clip
|
||||
elif type pbcopy >/dev/null 2>&1; then
|
||||
# macOS
|
||||
tr '\0' '\n' < "$selection" | pbcopy
|
||||
elif type termux-clipboard-set >/dev/null 2>&1; then
|
||||
# Termux
|
||||
tr '\0' '\n' < "$selection" | termux-clipboard-set
|
||||
elif type clip.exe >/dev/null 2>&1; then
|
||||
# WSL
|
||||
tr '\0' '\n' < "$selection" | clip.exe
|
||||
elif type clip >/dev/null 2>&1; then
|
||||
# Cygwin
|
||||
tr '\0' '\n' < "$selection" | clip
|
||||
elif type clipboard >/dev/null 2>&1; then
|
||||
# Haiku
|
||||
tr '\0' '\n' < "$selection" | clipboard --stdin
|
||||
fi
|
||||
|
|
|
@ -0,0 +1,441 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
# Description: Print icons in front of list of directories/files
|
||||
|
||||
# Dependencies: awk
|
||||
|
||||
# Usage
|
||||
# 1. Set colors and/or icons to your liking
|
||||
# 2. Pipe any directory listing to iconlookup and it will output prepended icons
|
||||
# 3. preview-tui uses the script to prepend icon to directory listings
|
||||
# 4. Aditionally you can consider adding it to your PATH and/or FZF_DEFAULT_COMMAND to
|
||||
# make it work with various fzf plugins (make sure you also add --ansi to your FZF_DEFAULT_OPTS)
|
||||
|
||||
# Shell: POSIX compliant
|
||||
|
||||
# Author: Luuk van Baal (https://github.com/luukvbaal/iconlookup)
|
||||
|
||||
icon_lookup() {
|
||||
awk 'BEGIN {
|
||||
# Set your ANSI colorscheme below (https://en.wikipedia.org/wiki/ANSI_escape_code#Colors).
|
||||
# Default uses standard nnn icon colors, 8 and 24-bit nord themes are commented out.
|
||||
colordepth=8 #colordepth=8 #colordepth=24
|
||||
color_dirtxt=39 #color_dirtxt=111 #color_dirtxt="129;161;193"
|
||||
color_filetxt=15 #color_filetxt=111 #color_filetxt="129;161;193"
|
||||
color_default=39 #color_default=111 #color_default="129;161;193"
|
||||
color_video=93 #color_video=110 #color_video="136;192;208"
|
||||
color_audio=220 #color_audio=150 #color_audio="163;190;140"
|
||||
color_image=82 #color_image=150 #color_image="163;190;140"
|
||||
color_docs=202 #color_docs=173 #color_docs="208;135;112"
|
||||
color_archive=209 #color_archive=179 #color_archive="235;203;139"
|
||||
color_c=81 #color_c=150 #color_c="163;190;140"
|
||||
color_elixir=104 #color_elixir=109 #color_elixir="143;188;187"
|
||||
color_java=32 #color_java=139 #color_java="180;142;173"
|
||||
color_js=47 #color_js=109 #color_js="143;188;187"
|
||||
color_react=39 #color_react=111 #color_react="129;161;193"
|
||||
color_css=199 #color_css=110 #color_css="136;192;208"
|
||||
color_python=227 #color_python=68 #color_python="94;129;172"
|
||||
color_lua=19 #color_lua=167 #color_lua="191;97;106"
|
||||
color_document=15 #color_document=173 #color_document="208;135;112"
|
||||
color_fsharp=31 #color_fsharp=179 #color_fsharp="180;142;173"
|
||||
color_ruby=160 #color_ruby=150 #color_ruby="163;190;140"
|
||||
color_scala=196 #color_scala=139 #color_scala="143;188;187"
|
||||
color_shell=47 #color_shell=109 #color_shell="143;188;187"
|
||||
color_vim=28 #color_vim=109 #color_vim="143;188;187"
|
||||
|
||||
# icons[][1] contains icon and icons[][2] contains color
|
||||
icons["directory"][1] = ""; icons["directory"][2] = color_default
|
||||
icons["file"][1] = ""; icons["file"][2] = color_default
|
||||
icons["exec"][1] = ""; icons["exec"][2] = color_default
|
||||
icons["manual"][1] = ""; icons["manual"][2] = color_docs
|
||||
icons["pipe"][1] = ""; icons["pipe"][2] = color_default
|
||||
icons["socket"][1] = ""; icons["socket"][2] = color_default
|
||||
icons["door"][1] = "➡"; icons["door"][2] = color_default
|
||||
|
||||
# top level and common icons
|
||||
icons[".git"][1] = ""; icons[".git"][2] = color_default
|
||||
icons["desktop"][1] = ""; icons["desktop"][2] = color_default
|
||||
icons["briefcase"][1] = ""; icons["briefcase"][2] = color_default
|
||||
icons["document"][1] = ""; icons["document"][2] = color_default
|
||||
icons["downloads"][1] = ""; icons["downloads"][2] = color_default
|
||||
icons["music"][1] = ""; icons["music"][2] = color_default
|
||||
icons["musicfile"][1] = ""; icons["musicfile"][2] = color_audio
|
||||
icons["pictures"][1] = ""; icons["pictures"][2] = color_default
|
||||
icons["picturefile"][1] = ""; icons["picturefile"][2] = color_image
|
||||
icons["public"][1] = ""; icons["public"][2] = color_default
|
||||
icons["templates"][1] = ""; icons["templates"][2] = color_default
|
||||
icons["videos"][1] = ""; icons["videos"][2] = color_default
|
||||
icons["videofile"][1] = ""; icons["videofile"][2] = color_video
|
||||
icons["changelog"][1] = ""; icons["changelog"][2] = color_docs
|
||||
icons["configure"][1] = ""; icons["configure"][2] = color_default
|
||||
icons["license"][1] = ""; icons["license"][2] = color_docs
|
||||
icons["makefile"][1] = ""; icons["makefile"][2] = color_default
|
||||
icons["archive"][1] = ""; icons["archive"][2] = color_archive
|
||||
icons["rust"][1] = ""; icons["rust"][2] = color_default
|
||||
icons["script"][1] = ""; icons["script"][2] = color_shell
|
||||
icons["subtitle"][1] = ""; icons["subtitle"][2] = color_default
|
||||
icons["cplusplus"][1] = ""; icons["cplusplus"][2] = color_c
|
||||
icons["java"][1] = ""; icons["java"][2] = color_java
|
||||
icons["clojure"][1] = ""; icons["clojure"][2] = color_default
|
||||
icons["js"][1] = ""; icons["js"][2] = color_js
|
||||
icons["linux"][1] = ""; icons["linux"][2] = color_default
|
||||
icons["elixir"][1] = ""; icons["elixir"][2] = color_fsharp
|
||||
icons["fsharp"][1] = ""; icons["fsharp"][2] = color_fsharp
|
||||
icons["ruby"][1] = ""; icons["ruby"][2] = color_ruby
|
||||
icons["c"][1] = ""; icons["c"][2] = color_c
|
||||
icons["chess"][1] = ""; icons["chess"][2] = color_default
|
||||
icons["haskell"][1] = ""; icons["haskell"][2] = color_vim
|
||||
icons["font"][1] = ""; icons["font"][2] = color_default
|
||||
icons["html"][1] = ""; icons["html"][2] = color_default
|
||||
icons["react"][1] = ""; icons["react"][2] = color_react
|
||||
icons["python"][1] = ""; icons["python"][2] = color_python
|
||||
icons["database"][1] = ""; icons["database"][2] = color_default
|
||||
icons["worddoc"][1] = ""; icons["worddoc"][2] = color_document
|
||||
icons["playlist"][1] = ""; icons["playlist"][2] = color_audio
|
||||
icons["opticaldisk"][1] = ""; icons["opticaldisk"][2] = color_archive
|
||||
|
||||
# numbers
|
||||
icons["1"][1] = icons["manual"][1]; icons["1"][2] = icons["manual"][2]
|
||||
icons["7z"][1] = icons["archive"][1]; icons["7z"][2] = icons["archive"][2]
|
||||
|
||||
# a
|
||||
icons["a"][1] = icons["manual"][1]; icons["a"][2] = icons["manual"][2]
|
||||
icons["apk"][1] = icons["archive"][1]; icons["apk"][2] = icons["archive"][2]
|
||||
icons["asm"][1] = icons["file"][1]; icons["asm"][2] = icons["file"][2]
|
||||
icons["aup"][1] = icons["musicfile"][1]; icons["aup"][2] = icons["musicfile"][2]
|
||||
icons["avi"][1] = icons["videofile"][1]; icons["avi"][2] = icons["videofile"][2]
|
||||
|
||||
# b
|
||||
icons["bat"][1] = icons["script"][1]; icons["bat"][2] = icons["script"][2]
|
||||
icons["bin"][1] = ""; icons["bin"][2] = color_default
|
||||
icons["bmp"][1] = icons["picturefile"][1]; icons["bmp"][2] = icons["picturefile"][2]
|
||||
icons["bz2"][1] = icons["archive"][1]; icons["bz2"][2] = icons["archive"][2]
|
||||
|
||||
# c
|
||||
icons["cplusplus"][1] = icons["cplusplus"][1]; icons["cplusplus"][2] = icons["cplusplus"][2]
|
||||
icons["cabal"][1] = icons["haskell"][1]; icons["cab"][2] = icons["haskell"][2]
|
||||
icons["cab"][1] = icons["archive"][1]; icons["cab"][2] = icons["archive"][2]
|
||||
icons["cbr"][1] = icons["archive"][1]; icons["cbr"][2] = icons["archive"][2]
|
||||
icons["cbz"][1] = icons["archive"][1]; icons["cbz"][2] = icons["archive"][2]
|
||||
icons["cc"][1] = icons["cplusplus"][1]; icons["cc"][2] = icons["cplusplus"][2]
|
||||
icons["class"][1] = icons["java"][1]; icons["class"][2] = icons["java"][2]
|
||||
icons["clj"][1] = icons["clojure"][1]; icons["clj"][2] = icons["clojure"][2]
|
||||
icons["cljc"][1] = icons["clojure"][1]; icons["cljc"][2] = icons["clojure"][2]
|
||||
icons["cljs"][1] = icons["clojure"][1]; icons["cljs"][2] = icons["clojure"][2]
|
||||
icons["cmake"][1] = icons["makefile"][1]; icons["cmake"][2] = icons["makefile"][2]
|
||||
icons["coffee"][1] = ""; icons["coffee"][2] = color_default
|
||||
icons["conf"][1] = icons["configure"][1]; icons["conf"][2] = icons["configure"][2]
|
||||
icons["cpio"][1] = icons["archive"][1]; icons["cpio"][2] = icons["archive"][2]
|
||||
icons["cpp"][1] = icons["cplusplus"][1]; icons["cpp"][2] = icons["cplusplus"][2]
|
||||
icons["css"][1] = ""; icons["css"][2] = color_css
|
||||
icons["cue"][1] = icons["playlist"][1]; icons["cue"][2] = icons["playlist"][2]
|
||||
icons["cvs"][1] = icons["configure"][1]; icons["cvs"][2] = icons["configure"][2]
|
||||
icons["cxx"][1] = icons["cplusplus"][1]; icons["cxx"][2] = icons["cplusplus"][2]
|
||||
|
||||
# d
|
||||
icons["db"][1] = icons["database"][1]; icons["db"][2] = icons["database"][2]
|
||||
icons["deb"][1] = ""; icons["deb"][2] = color_archive
|
||||
icons["diff"][1] = ""; icons["diff"][2] = color_default
|
||||
icons["dll"][1] = icons["script"][1]; icons["dll"][2] = icons["script"][2]
|
||||
icons["doc"][1] = icons["worddoc"][1]; icons["doc"][2] = icons["worddoc"][2]
|
||||
icons["docx"][1] = icons["worddoc"][1]; icons["docx"][2] = icons["worddoc"][2]
|
||||
|
||||
# e
|
||||
icons["ejs"][1] = icons["js"][1]; icons["ejs"][2] = icons["js"][2]
|
||||
icons["elf"][1] = icons["linux"][1]; icons["elf"][2] = icons["linux"][2]
|
||||
icons["epub"][1] = icons["manual"][1]; icons["epub"][2] = icons["manual"][2]
|
||||
icons["exe"][1] = icons["exec"][1]; icons["exe"][2] = icons["exec"][2]
|
||||
icons["ex"][1] = icons["elixir"][1]; icons["ex"][2] = icons["elixir"][2]
|
||||
icons["eex"][1] = icons["elixir"][1]; icons["eex"][2] = icons["elixir"][2]
|
||||
icons["exs"][1] = icons["elixir"][1]; icons["exs"][2] = icons["elixir"][2]
|
||||
|
||||
# f
|
||||
icons["fsharp"][1] = icons["fsharp"][1]; icons["fsharp"][2] = icons["fsharp"][2]
|
||||
icons["flac"][1] = icons["musicfile"][1]; icons["flac"][2] = icons["musicfile"][2]
|
||||
icons["fen"][1] = icons["chess"][1]; icons["fen"][2] = icons["chess"][2]
|
||||
icons["flv"][1] = icons["videofile"][1]; icons["flv"][2] = icons["videofile"][2]
|
||||
icons["fs"][1] = icons["fsharp"][1]; icons["fs"][2] = icons["fsharp"][2]
|
||||
icons["fsi"][1] = icons["fsharp"][1]; icons["fsi"][2] = icons["fsharp"][2]
|
||||
icons["fsscript"][1] = icons["fsharp"][1]; icons["fsscript"][2] = icons["fsharp"][2]
|
||||
icons["fsx"][1] = icons["fsharp"][1]; icons["fsx"][2] = icons["fsharp"][2]
|
||||
|
||||
# g
|
||||
icons["gem"][1] = icons["ruby"][1]; icons["gem"][2] = icons["ruby"][2]
|
||||
icons["gif"][1] = icons["picturefile"][1]; icons["gif"][2] = icons["picturefile"][2]
|
||||
icons["go"][1] = ""; icons["go"][2] = color_default
|
||||
icons["gz"][1] = icons["archive"][1]; icons["gz"][2] = icons["archive"][2]
|
||||
icons["gzip"][1] = icons["archive"][1]; icons["gzip"][2] = icons["archive"][2]
|
||||
|
||||
# h
|
||||
icons["h"][1] = icons["c"][1]; icons["h"][2] = icons["c"][2]
|
||||
icons["hh"][1] = icons["cplusplus"][1]; icons["hh"][2] = icons["cplusplus"][2]
|
||||
icons["hpp"][1] = icons["cplusplus"][1]; icons["hpp"][2] = icons["cplusplus"][2]
|
||||
icons["hs"][1] = icons["haskell"][1]; icons["hs"][2] = icons["haskell"][2]
|
||||
icons["htaccess"][1] = icons["configure"][1]; icons["htaccess"][2] = icons["configure"][2]
|
||||
icons["htpasswd"][1] = icons["configure"][1]; icons["htpasswd"][2] = icons["configure"][2]
|
||||
icons["htm"][1] = icons["html"][1]; icons["htm"][2] = icons["html"][2]
|
||||
icons["hxx"][1] = icons["cplusplus"][1]; icons["hxx"][2] = icons["cplusplus"][2]
|
||||
icons["heex"][1] = icons["elixir"][1]; icons["heex"][2] = icons["elixir"][2]
|
||||
|
||||
# i
|
||||
icons["ico"][1] = icons["picturefile"][1]; icons["ico"][2] = icons["picturefile"][2]
|
||||
icons["img"][1] = icons["opticaldisk"][1]; icons["img"][2] = icons["opticaldisk"][2]
|
||||
icons["ini"][1] = icons["configure"][1]; icons["ini"][2] = icons["configure"][2]
|
||||
icons["iso"][1] = icons["opticaldisk"][1]; icons["iso"][2] = icons["opticaldisk"][2]
|
||||
icons["isub"][1] = icons["subtitle"][1]; icons["isub"][2] = icons["subtitle"][2]
|
||||
|
||||
# j
|
||||
icons["jar"][1] = icons["java"][1]; icons["jar"][2] = icons["java"][2]
|
||||
icons["java"][1] = icons["java"][1]; icons["java"][2] = icons["java"][2]
|
||||
icons["jl"][1] = icons["configure"][1]; icons["jl"][2] = icons["configure"][2]
|
||||
icons["jpeg"][1] = icons["picturefile"][1]; icons["jpeg"][2] = icons["picturefile"][2]
|
||||
icons["jpg"][1] = icons["picturefile"][1]; icons["jpg"][2] = icons["picturefile"][2]
|
||||
icons["json"][1] = ""; icons["json"][2] = color_js
|
||||
icons["jsx"][1] = icons["react"][1]; icons["jsx"][2] = icons["react"][2]
|
||||
icons["jxl"][1] = icons["picturefile"][1]; icons["jxl"][2] = icons["picturefile"][2]
|
||||
|
||||
# k
|
||||
icons["ksh"][1] = icons["font"][1]; icons["ksf"][2] = icons["font"][2]
|
||||
|
||||
# l
|
||||
icons["lha"][1] = icons["archive"][1]; icons["lha"][2] = icons["archive"][2]
|
||||
icons["lhs"][1] = icons["haskell"][1]; icons["lhs"][2] = icons["haskell"][2]
|
||||
icons["ilog"][1] = icons["document"][1]; icons["ilog"][2] = icons["document"][2]
|
||||
icons["lua"][1] = ""; icons["lua"][2] = color_lua
|
||||
icons["lzh"][1] = icons["archive"][1]; icons["lzh"][2] = icons["archive"][2]
|
||||
icons["lzma"][1] = icons["archive"][1]; icons["lzma"][2] = icons["archive"][2]
|
||||
|
||||
# m
|
||||
icons["m"][1] = ""; icons["mat"][2] = color_c
|
||||
icons["m4a"][1] = icons["musicfile"][1]; icons["m4a"][2] = icons["musicfile"][2]
|
||||
icons["m4v"][1] = icons["videofile"][1]; icons["m4v"][2] = icons["videofile"][2]
|
||||
icons["mat"][1] = ""; icons["mat"][2] = color_c
|
||||
icons["markdown"][1] = ""; icons["markdown"][2] = color_docs
|
||||
icons["md"][1] = ""; icons["md"][2] = color_docs
|
||||
icons["mk"][1] = icons["makefile"][1]; icons["mk"][2] = icons["makefile"][2]
|
||||
icons["mkv"][1] = icons["videofile"][1]; icons["mkv"][2] = icons["videofile"][2]
|
||||
icons["mov"][1] = icons["videofile"][1]; icons["mov"][2] = icons["videofile"][2]
|
||||
icons["mp3"][1] = icons["musicfile"][1]; icons["mp3"][2] = icons["musicfile"][2]
|
||||
icons["mp4"][1] = icons["videofile"][1]; icons["mp4"][2] = icons["videofile"][2]
|
||||
icons["mpeg"][1] = icons["videofile"][1]; icons["mpeg"][2] = icons["videofile"][2]
|
||||
icons["mpg"][1] = icons["videofile"][1]; icons["mpg"][2] = icons["videofile"][2]
|
||||
icons["msi"][1] = ""; icons["msi"][2] = color_default
|
||||
|
||||
# n
|
||||
icons["nix"][1] = ""; icons["nix"][2] = color_fsharp
|
||||
|
||||
# o
|
||||
icons["o"][1] = icons["manual"][1]; icons["o"][2] = icons["manual"][2]
|
||||
icons["ogg"][1] = icons["musicfile"][1]; icons["ogg"][2] = icons["musicfile"][2]
|
||||
icons["odownload"][1] = icons["download"][1]; icons["odownload"][2] = icons["download"][2]
|
||||
icons["otf"][1] = icons["font"][1]; icons["otf"][2] = icons["font"][2]
|
||||
icons["out"][1] = icons["linux"][1]; icons["out"][2] = icons["linux"][2]
|
||||
|
||||
# p
|
||||
icons["part"][1] = icons["download"][1]; icons["part"][2] = icons["download"][2]
|
||||
icons["patch"][1] = icons["diff"][1]; icons["patch"][2] = icons["diff"][2]
|
||||
icons["pdf"][1] = ""; icons["pdf"][2] = color_docs
|
||||
icons["pgn"][1] = icons["chess"][1]; icons["pgn"][2] = icons["chess"][2]
|
||||
icons["php"][1] = ""; icons["php"][2] = color_default
|
||||
icons["png"][1] = icons["picturefile"][1]; icons["png"][2] = icons["picturefile"][2]
|
||||
icons["ppt"][1] = ""; icons["ppt"][2] = color_default
|
||||
icons["pptx"][1] = ""; icons["pptx"][2] = color_default
|
||||
icons["psb"][1] = ""; icons["psb"][2] = color_default
|
||||
icons["psd"][1] = ""; icons["psd"][2] = color_default
|
||||
icons["py"][1] = icons["python"][1]; icons["py"][2] = icons["python"][2]
|
||||
icons["pyc"][1] = icons["python"][1]; icons["pyc"][2] = icons["python"][2]
|
||||
icons["pyd"][1] = icons["python"][1]; icons["pyd"][2] = icons["python"][2]
|
||||
icons["pyo"][1] = icons["python"][1]; icons["pyo"][2] = icons["python"][2]
|
||||
|
||||
# q
|
||||
|
||||
# r
|
||||
icons["rar"][1] = icons["archive"][1]; icons["rar"][2] = icons["archive"][2]
|
||||
icons["rc"][1] = icons["configure"][1]; icons["rc"][2] = icons["configure"][2]
|
||||
icons["rom"][1] = ""; icons["rom"][2] = color_default
|
||||
icons["rpm"][1] = icons["archive"][1]; icons["rpm"][2] = icons["archive"][2]
|
||||
icons["rss"][1] = ""; icons["rss"][2] = color_default
|
||||
icons["rtf"][1] = ""; icons["rtf"][2] = color_default
|
||||
|
||||
# s
|
||||
icons["sass"][1] = ""; icons["sass"][2] = color_css
|
||||
icons["scss"][1] = ""; icons["scss"][2] = color_css
|
||||
icons["so"][1] = icons["manual"][1]; icons["so"][2] = icons["manual"][2]
|
||||
icons["scala"][1] = ""; icons["scala"][2] = color_scala
|
||||
icons["sh"][1] = icons["script"][1]; icons["sh"][2] = icons["script"][2]
|
||||
icons["slim"][1] = icons["script"][1]; icons["slim"][2] = icons["script"][2]
|
||||
icons["sln"][1] = ""; icons["sln"][2] = color_default
|
||||
icons["sql"][1] = icons["database"][1]; icons["sql"][2] = icons["database"][2]
|
||||
icons["srt"][1] = icons["subtitle"][1]; icons["srt"][2] = icons["subtitle"][2]
|
||||
icons["svg"][1] = icons["picturefile"][1]; icons["svg"][2] = icons["picturefile"][2]
|
||||
|
||||
# t
|
||||
icons["tar"][1] = icons["archive"][1]; icons["tar"][2] = icons["archive"][2]
|
||||
icons["tex"][1] = ""; icons["tex"][2] = color_default
|
||||
icons["tgz"][1] = icons["archive"][1]; icons["tgz"][2] = icons["archive"][2]
|
||||
icons["ts"][1] = ""; icons["ts"][2] = color_js
|
||||
icons["tsx"][1] = icons["react"][1]; icons["tsx"][2] = icons["react"][2]
|
||||
icons["txt"][1] = icons["document"][1]; icons["txt"][2] = icons["document"][2]
|
||||
icons["txz"][1] = icons["archive"][1]; icons["txz"][2] = icons["archive"][2]
|
||||
icons["ttf"][1] = icons["font"][1]; icons["ttf"][2] = icons["font"][2]
|
||||
|
||||
# u
|
||||
|
||||
# v
|
||||
icons["vid"][1] = icons["videofile"][1]; icons["vid"][2] = icons["videofile"][2]
|
||||
icons["vim"][1] = ""; icons["vim"][2] = color_vim
|
||||
icons["vimrc"][1] = ""; icons["vimrc"][2] = color_vim
|
||||
icons["vtt"][1] = icons["subtitle"][1]; icons["vtt"][2] = icons["subtitle"][2]
|
||||
# w
|
||||
icons["wav"][1] = icons["musicfile"][1]; icons["wav"][2] = icons["musicfile"][2]
|
||||
icons["webm"][1] = icons["videofile"][1]; icons["webm"][2] = icons["videofile"][2]
|
||||
icons["wma"][1] = icons["videofile"][1]; icons["wma"][2] = icons["videofile"][2]
|
||||
icons["wmv"][1] = icons["videofile"][1]; icons["wmv"][2] = icons["videofile"][2]
|
||||
|
||||
# x
|
||||
icons["xbps"][1] = icons["archive"][1]; icons["xbps"][2] = color_archive
|
||||
icons["xcf"][1] = icons["picturefile"][1]; icons["xcf"][2] = color_image
|
||||
icons["xhtml"][1] = icons["html"][1]; icons["xhtml"][2] = icons["html"][2]
|
||||
icons["xls"][1] = ""; icons["xls"][2] = color_default
|
||||
icons["xlsx"][1] = ""; icons["xlsx"][2] = color_default
|
||||
icons["xml"][1] = icons["html"][1]; icons["xml"][2] = icons["html"][2]
|
||||
icons["xz"][1] = icons["archive"][1]; icons["xz"][2] = icons["archive"][2]
|
||||
|
||||
# y
|
||||
icons["yaml"][1] = icons["configure"][1]; icons["yaml"][2] = icons["configure"][2]
|
||||
icons["yml"][1] = icons["configure"][1]; icons["yml"][2] = icons["configure"][2]
|
||||
# z
|
||||
icons["zip"][1] = icons["archive"][1]; icons["zip"][2] = icons["archive"][2]
|
||||
icons["zsh"][1] = icons["script"][1]; icons["zsh"][2] = icons["script"][2]
|
||||
icons["zst"][1] = icons["archive"][1]; icons["zst"][2] = icons["archive"][2]
|
||||
|
||||
FS = "."
|
||||
limit = ENVIRON["limit"]
|
||||
switch (colordepth) {
|
||||
case "4":
|
||||
escape="\033["
|
||||
break;
|
||||
case "8":
|
||||
escape="\033[38;5;"
|
||||
break;
|
||||
case "24":
|
||||
escape="\033[38;2;"
|
||||
break;
|
||||
}
|
||||
bstr = ENVIRON["beforestr"]
|
||||
}
|
||||
{
|
||||
# dont print cwd . and leading ./ from tree -f
|
||||
if ($0 ~/^\.$/)
|
||||
next
|
||||
ent = ($0 ~/^\.\//) ? substr($0, 3, length($0) - 2) : $0
|
||||
ext = $NF
|
||||
|
||||
# Print icons, set color and bold directories by using ansi escape codes
|
||||
if (ext in icons)
|
||||
printcolor(icons[ext][1], icons[ext][2], color_filetxt, ent, "10")
|
||||
else
|
||||
switch (substr(ent, length(ent), 1)) {
|
||||
case "/":
|
||||
printcolor(icons["directory"][1], color_default, color_dirtxt, ent, "1")
|
||||
break;
|
||||
case "*":
|
||||
printcolor(icons["exe"][1], color_default, color_filetxt, ent, "10")
|
||||
break;
|
||||
case "|":
|
||||
printcolor(icons["pipe"][1], color_default, color_filetxt, ent, "10")
|
||||
break;
|
||||
case "=":
|
||||
printcolor(icons["socket"][1], color_default, color_filetxt, ent, "10")
|
||||
break;
|
||||
case ">":
|
||||
printcolor(icons["door"][1], color_default, color_filetxt, ent, "10")
|
||||
break;
|
||||
default:
|
||||
printcolor(icons["file"][1], color_default, color_filetxt, ent, "10")
|
||||
}
|
||||
}
|
||||
function printcolor(i, c, d, n, b) {
|
||||
if (limit != "" && length(n) + 2 > limit)
|
||||
n = substr(n, 1, limit - 2)
|
||||
printf "\033[0m"
|
||||
printf "%s%s%s;%sm%s %s%sm%s\n", bstr, escape, c, b, i, escape, d, n
|
||||
}'
|
||||
printf '\033[0m'
|
||||
}
|
||||
|
||||
print_begin() {
|
||||
printf '%s\n' "$1" | sed 's/\\n/\n/g'
|
||||
}
|
||||
|
||||
print_end() {
|
||||
printf '%s\n' "$1" | sed 's/\\n/\n/g'
|
||||
}
|
||||
|
||||
print_help() {
|
||||
printf 'Icon Lookup\n
|
||||
Usage:
|
||||
iconlookup [options]
|
||||
iconlookup [-bBe] [string]
|
||||
iconlookup -l [number]
|
||||
iconlookup (-h | --help)
|
||||
|
||||
Prepend icons to list of files based on extension or appended indicator by ls/tree "-F" flag ("/" for directory, "*" for executable etc.)
|
||||
|
||||
Options:
|
||||
-h --help -? Show this screen.
|
||||
-b --before Prepend str before icon.
|
||||
-B --begin Prepend str before output.
|
||||
-e --end Append str after output.
|
||||
-l --limit Limit line length to [number] characters.'
|
||||
}
|
||||
|
||||
while :; do
|
||||
case $1 in
|
||||
-h|-\?|--help)
|
||||
print_help
|
||||
exit ;;
|
||||
-B|--begin)
|
||||
if [ -n "$2" ]; then
|
||||
print_begin "$2"
|
||||
fi
|
||||
shift ;;
|
||||
-e|--end)
|
||||
if [ -n "$2" ]; then
|
||||
end=1
|
||||
endstr="$2"
|
||||
fi
|
||||
shift ;;
|
||||
-b|--before)
|
||||
if [ -n "$2" ]; then
|
||||
export beforestr="$2"
|
||||
fi
|
||||
shift ;;
|
||||
-l|--limit)
|
||||
if [ -n "$2" ]; then
|
||||
export limit="$2"
|
||||
shift
|
||||
else
|
||||
printf 'ERROR: "--limit" requires a non-empty option argument.\n'
|
||||
exit
|
||||
fi ;;
|
||||
--)
|
||||
shift
|
||||
break ;;
|
||||
-?*)
|
||||
printf 'WARNING: Unknown option ignored: %s\n' "$1" ;;
|
||||
*) break ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if [ ! -t 0 ]; then
|
||||
[ -n "$beforestr" ] && limit="$((limit - ${#beforestr}))"
|
||||
icon_lookup
|
||||
else
|
||||
printf 'ERROR: no data provided...\nExpecting a directory listing in stdin\n'
|
||||
fi
|
||||
|
||||
if [ -n "$end" ]; then
|
||||
print_end "$endstr"
|
||||
fi
|
62
plugins/.nmv
62
plugins/.nmv
|
@ -5,6 +5,7 @@
|
|||
# Note: nnn auto-detects and invokes this plugin if available
|
||||
# Whitespace is used as delimiter for read.
|
||||
# The plugin doesn't support filenames with leading or trailing whitespace
|
||||
# To use NNN_LIST your shell must support readlink(1)
|
||||
#
|
||||
# Capabilities:
|
||||
# 1. Basic file rename
|
||||
|
@ -16,39 +17,63 @@
|
|||
# Shell: bash
|
||||
# Author: KlzXS
|
||||
|
||||
# shellcheck disable=SC1090,SC1091
|
||||
. "$(dirname "$0")"/.nnn-plugin-helper
|
||||
|
||||
EDITOR="${EDITOR:-vi}"
|
||||
TMPDIR="${TMPDIR:-/tmp}"
|
||||
INCLUDE_HIDDEN="${INCLUDE_HIDDEN:-0}"
|
||||
NNN_INCLUDE_HIDDEN="${NNN_INCLUDE_HIDDEN:-0}"
|
||||
VERBOSE="${VERBOSE:-0}"
|
||||
RECURSIVE="${RECURSIVE:-0}"
|
||||
|
||||
case "$NNN_TRASH" in
|
||||
1)
|
||||
RM_UTIL="trash-put" ;;
|
||||
2)
|
||||
RM_UTIL="gio trash" ;;
|
||||
*)
|
||||
RM_UTIL="rm -ri --" ;;
|
||||
esac
|
||||
|
||||
selection=${NNN_SEL:-${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.selection}
|
||||
exit_status=0
|
||||
|
||||
dst_file=$(mktemp "$TMPDIR/.nnnXXXXXX")
|
||||
|
||||
if [ -s "$selection" ]; then
|
||||
resp="s"
|
||||
else
|
||||
resp="c"
|
||||
fi
|
||||
|
||||
if [ "$resp" = "s" ]; then
|
||||
if nnn_use_selection "Rename"; then
|
||||
# shellcheck disable=SC2154
|
||||
arr=$(tr '\0' '\n' < "$selection")
|
||||
else
|
||||
if [ "$INCLUDE_HIDDEN" -eq 0 ]; then
|
||||
arr=$(find . ! -name . -prune ! -name ".*" -print | sort)
|
||||
else
|
||||
arr=$(find . ! -name . -prune -print | sort)
|
||||
findcmd="find . ! -name ."
|
||||
|
||||
if [ "$RECURSIVE" -eq 0 ]; then
|
||||
findcmd="$findcmd -prune"
|
||||
fi
|
||||
|
||||
if [ "$NNN_INCLUDE_HIDDEN" -eq 0 ]; then
|
||||
findcmd="$findcmd ! -name \".*\""
|
||||
fi
|
||||
|
||||
if [ -z "$NNN_LIST" ]; then
|
||||
findcmd="$findcmd -print"
|
||||
else
|
||||
findcmd="$findcmd -printf "'"'"$NNN_LIST/%P\n"'"'
|
||||
fi
|
||||
|
||||
arr=$(eval "$findcmd" | sort)
|
||||
fi
|
||||
|
||||
lines=$(printf "%s\n" "$arr" | wc -l)
|
||||
width=${#lines}
|
||||
|
||||
dst_file=$(mktemp "$TMPDIR/.nnnXXXXXX")
|
||||
trap 'rm -f -- "$dst_file"' EXIT
|
||||
|
||||
printf "%s" "$arr" | awk '{printf("%'"${width}"'d %s\n", NR, $0)}' > "$dst_file"
|
||||
|
||||
items=("~")
|
||||
while IFS='' read -r line; do
|
||||
if [ -n "$NNN_LIST" ]; then
|
||||
line=$(readlink "$line" || printf "%s" "$line")
|
||||
fi
|
||||
|
||||
items+=("$line");
|
||||
done < <(printf "%s\n" "$arr")
|
||||
|
||||
|
@ -97,7 +122,7 @@ while read -r num name; do
|
|||
tmp="$tmp~$c"
|
||||
done
|
||||
|
||||
if mv "$name" "$tmp"; then
|
||||
if mv -- "$name" "$tmp"; then
|
||||
if [ "$VERBOSE" -ne 0 ]; then
|
||||
printf "'%s' -> '%s'\n" "$name" "$tmp"
|
||||
fi
|
||||
|
@ -117,7 +142,7 @@ while read -r num name; do
|
|||
if [ ! -d "$dir" ] && ! mkdir -p "$dir"; then
|
||||
printf "%s: failed to create directory tree %s\n" "$0" "$dir" > /dev/stderr
|
||||
exit_status=1
|
||||
elif ! mv "$src" "$name"; then
|
||||
elif ! mv -i -- "$src" "$name"; then
|
||||
printf "%s: failed to rename %s to %s: %s\n" "$0" "$name" "$tmp" "$!" > /dev/stderr
|
||||
exit_status=1
|
||||
else
|
||||
|
@ -143,8 +168,7 @@ done <"$dst_file"
|
|||
|
||||
unset "items[0]"
|
||||
for item in "${items[@]}"; do
|
||||
rm -ri "$item"
|
||||
$RM_UTIL "$item"
|
||||
done
|
||||
|
||||
rm "$dst_file"
|
||||
exit $exit_status
|
||||
|
|
|
@ -12,6 +12,9 @@ export selection
|
|||
CUR_CTX=0
|
||||
export CUR_CTX
|
||||
|
||||
NNN_PREFER_SELECTION="${NNN_PREFER_SELECTION:-0}"
|
||||
export NNN_PREFER_SELECTION
|
||||
|
||||
## Ask nnn to switch to directory $1 in context $2.
|
||||
## If $2 is not provided, the function asks explicitly.
|
||||
nnn_cd () {
|
||||
|
@ -33,6 +36,26 @@ nnn_cd () {
|
|||
}
|
||||
|
||||
cmd_exists () {
|
||||
which "$1" > /dev/null 2>&1
|
||||
echo $?
|
||||
type "$1" > /dev/null 2>&1
|
||||
echo $?
|
||||
}
|
||||
|
||||
nnn_use_selection() {
|
||||
if ! [ -s "$selection" ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ "$NNN_PREFER_SELECTION" -eq 1 ]; then
|
||||
return 0
|
||||
else
|
||||
[ -n "$1" ] && printf "%s " "$1"
|
||||
printf "(s)election/(c)urrent? [default=c] "
|
||||
read -r resp__
|
||||
|
||||
if [ "$resp__" = "s" ]; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
|
|
@ -11,11 +11,11 @@
|
|||
|
||||
OS="$(uname)"
|
||||
|
||||
if which notify-send >/dev/null 2>&1; then
|
||||
if type notify-send >/dev/null 2>&1; then
|
||||
notify-send nnn "Done!"
|
||||
elif [ "$OS" = "Darwin" ]; then
|
||||
osascript -e 'display notification "Done!" with title "nnn"'
|
||||
elif which ntfy >/dev/null 2>&1; then
|
||||
elif type ntfy >/dev/null 2>&1; then
|
||||
ntfy -t nnn send "Done!"
|
||||
elif [ "$OS" = "Haiku" ]; then
|
||||
notify --title "nnn" "Done!"
|
||||
|
|
|
@ -3,9 +3,6 @@
|
|||
<p align="center"><img src="https://i.imgur.com/SpT0L2W.png" /></p>
|
||||
<p align="center"><i>read ebooks with plugin gutenread (Android)</i></p>
|
||||
|
||||
<p align="center"><a href="https://asciinema.org/a/336443"><img src="https://asciinema.org/a/336443.svg" width="734"/></a></p>
|
||||
<p align="center"><i>Live Previews</i></p>
|
||||
|
||||
## Introduction
|
||||
|
||||
Plugins extend the capabilities of `nnn`. They are _executable_ scripts (or binaries) `nnn` can communicate with and trigger. This mechanism fits perfectly with the fundamental design to keep the core file manager lean and fast, by delegating repetitive (but not necessarily file manager-specific) tasks to the plugins which can be run with custom hotkeys.
|
||||
|
@ -14,67 +11,91 @@ Plugins extend the capabilities of `nnn`. They are _executable_ scripts (or bina
|
|||
|
||||
## List of plugins
|
||||
|
||||
| Plugin (a-z) | Description | Lang | Dependencies |
|
||||
| Plugin (a-z) | Description [Clears selection<sup>1</sup>] | Lang | Dependencies |
|
||||
| --- | --- | --- | --- |
|
||||
| [autojump](autojump) | Navigate to dir/path | sh | [jump](https://github.com/gsamokovarov/jump)/autojump/zoxide |
|
||||
| [bookmarks](bookmarks) | Use named bookmarks managed with symlinks | sh | fzf |
|
||||
| [autojump](autojump) | Navigate to dir/path | sh | [jump](https://github.com/gsamokovarov/jump)/autojump/<br>zoxide/z/[z.lua](https://github.com/skywind3000/z.lua) |
|
||||
| [boom](boom) | Play random music from dir | sh | [moc](http://moc.daper.net/) |
|
||||
| [bulknew](bulknew) | Create multiple files/dirs at once | bash | sed, xargs, mktemp |
|
||||
| [dups](dups) | List non-empty duplicate files in current dir | bash | find, md5sum,<br>sort uniq xargs |
|
||||
| [chksum](chksum) | Create and verify checksums | sh | md5sum,<br>sha256sum |
|
||||
| [diffs](diffs) | Diff for selection (limited to 2 for directories) | sh | vimdiff, mktemp |
|
||||
| [cbcopy-mac](cbcopy-mac) | Copy the hovered file to MacOS clipboard | applescript | macos |
|
||||
| [cbpaste-mac](cbpaste-mac) | Pastes files from MacOS clipboard into currect directory | macos |
|
||||
| [cdpath](cdpath) | `cd` to the directory from `CDPATH` | sh | fzf |
|
||||
| [chksum](chksum) | Create and verify checksums [✓] | sh | md5sum,<br>sha256sum |
|
||||
| [cmusq](cmusq) | Queue/play files/dirs in cmus player [✓] | sh | cmus, pgrep |
|
||||
| [diffs](diffs) | Diff for selection (limited to 2 for directories) [✓] | sh | vimdiff, mktemp |
|
||||
| [dragdrop](dragdrop) | Drag/drop files from/into nnn | sh | [dragon](https://github.com/mwh/dragon) |
|
||||
| [finder](finder) | Run custom find command and list | sh | - |
|
||||
| [fzcd](fzcd) | Change to the directory of a fuzzy-selected file/dir | sh | fzf |
|
||||
| [dups](dups) | List non-empty duplicate files in current dir | bash | find, md5sum,<br>sort uniq xargs |
|
||||
| [finder](finder) | Run custom find command (**stored in histfile**) and list | sh | - |
|
||||
| [fixname](fixname) | Clean filename to be more shell-friendly [✓] | bash | sed |
|
||||
| [fzcd](fzcd) | Fuzzy search multiple dirs (or `$PWD`) and visit file | sh | fzf, (find) |
|
||||
| [fzhist](fzhist) | Fuzzy-select a cmd from history, edit in `$EDITOR` and run | sh | fzf, mktemp |
|
||||
| [fzopen](fzopen) | Fuzzy find a file in dir subtree and edit or open | sh | fzf, xdg-open |
|
||||
| [fzz](fzz) | Change to any directory in the z database with fzf | sh | fzf, z |
|
||||
| [fzopen](fzopen) | Fuzzy find file(s) in subtree to edit/open/pick | sh | fzf, xdg-open/open |
|
||||
| [fzplug](fzplug) | Fuzzy find, preview and run other plugins | sh | fzf |
|
||||
| [getplugs](getplugs) | Update plugins to installed `nnn` version | sh | curl |
|
||||
| [gitroot](gitroot) | Cd to the root of current git repo | sh | git |
|
||||
| [gpge](gpge) | Encrypt/decrypt files using GPG [✓] | sh | gpg |
|
||||
| [gutenread](gutenread) | Browse, download, read from Project Gutenberg | sh | curl, unzip, w3m<br>[epr](https://github.com/wustho/epr) (optional) |
|
||||
| [gpg\*](gpg\*) | Encrypt/decrypt files using GPG | sh | gpg |
|
||||
| [hexview](hexview) | View a file in hex in `$PAGER` | sh | [hx](https://github.com/krpors/hx)/xxd |
|
||||
| [imgresize](imgresize) | Resize images in dir to screen resolution | sh | [imgp](https://github.com/jarun/imgp) |
|
||||
| [imgthumb](imgthumb) | View thumbnail of an image or dir of images | sh | [lsix](https://github.com/hackerb9/lsix) |
|
||||
| [gsconnect](gsconnect) | GNOME's implementation of kdeconnect [✓] | sh | gsconnect |
|
||||
| [imgresize](imgresize) | Batch resize images in dir to screen resolution | sh | [imgp](https://github.com/jarun/imgp) |
|
||||
| [imgur](imgur) | Upload an image to imgur (from [imgur-screenshot](https://github.com/jomo/imgur-screenshot)) | bash | - |
|
||||
| [imgview](imgview) | Browse images, set wallpaper, copy path ([config](https://wiki.archlinux.org/index.php/Sxiv#Assigning_keyboard_shortcuts)), [rename](https://github.com/jarun/nnn/wiki/Basic-use-cases#browse-rename-images)| sh | [imv](https://github.com/eXeC64/imv)/[sxiv](https://github.com/muennich/sxiv)/[viu](https://github.com/atanunq/viu), less|
|
||||
| [imgview](imgview) | View (thumbnail)images, set wallpaper, [rename](https://github.com/jarun/nnn/wiki/Basic-use-cases#browse-rename-images) and [more](https://wiki.archlinux.org/index.php/Sxiv#Assigning_keyboard_shortcuts)| sh | _see in-file docs_ |
|
||||
| [ipinfo](ipinfo) | Fetch external IP address and whois information | sh | curl, whois |
|
||||
| [kdeconnect](kdeconnect) | Send selected files to an Android device | sh | kdeconnect-cli |
|
||||
| [kdeconnect](kdeconnect) | Send selected files to an Android device [✓] | sh | kdeconnect-cli |
|
||||
| [launch](launch) | GUI application launcher | sh | fzf |
|
||||
| [mediainf](mediainf) | Show media information | sh | mediainfo |
|
||||
| [mimelist](mimelist) | List files by mime in subtree | sh | - |
|
||||
| [mimelist](mimelist) | List files by mime in subtree | sh | file/mimetype |
|
||||
| [moclyrics](moclyrics) | Show lyrics of the track playing in moc | sh | [ddgr](https://github.com/jarun/ddgr), [moc](http://moc.daper.net/) |
|
||||
| [mocplay](mocplay) | Append (and/or play) selection/dir/file in moc | sh | [moc](http://moc.daper.net/) |
|
||||
| [mocq](mocq) | Queue/play selection/dir/file in moc [✓] | sh | [moc](http://moc.daper.net/) |
|
||||
| [mp3conv](mp3conv) | Extract audio from multimedia as mp3 | sh | ffmpeg |
|
||||
| [mtpmount](mtpmount) | Toggle mount of MTP device (eg. Android) | sh | gvfs-mtp |
|
||||
| [nbak](nbak) | Backs up `nnn` config | sh | tar, awk, mktemp |
|
||||
| [nmount](nmount) | Toggle mount status of a device as normal user | sh | pmount, udisks2 |
|
||||
| [nmount](nmount) | Toggle mount status of a device as normal user | sh | pmount (optional), udisks2 |
|
||||
| [nuke](nuke) | Sample file opener (CLI-only by default) | sh | _see in-file docs_ |
|
||||
| [oldbigfile](oldbigfile) | List large files by access time | sh | find, sort |
|
||||
| [organize](organize) | Auto-organize files in directories by file type | sh | file |
|
||||
| [openall](openall) | Open selected files together or one by one [✓] | bash | - |
|
||||
| [organize](organize) | Auto-organize files in directories by file type [✓] | sh | file |
|
||||
| [pdfread](pdfread) | Read a PDF or text file aloud | sh | pdftotext, mpv,<br>pico2wave |
|
||||
| [pdfview](pdfview) | View PDF file in `$PAGER` | sh | pdftotext/<br>mupdf-tools |
|
||||
| [picker](picker) | Pick files and list one per line (to pipe) | sh | nnn |
|
||||
| [preview-tabbed](preview-tabbed) | Tabbed/xembed based file previewer | bash | _see in-file docs_ |
|
||||
| [preview-tui](preview-tui) | Tmux/kitty/xterm/`$TERMINAL` based file previewer | sh | _see in-file docs_ |
|
||||
| [preview-tabbed](preview-tabbed) | Preview files with Tabbed/xembed | bash | _see in-file docs_ |
|
||||
| [preview-tui](preview-tui) | Preview with Tmux/kitty/[QuickLook](https://github.com/QL-Win/QuickLook)/xterm/`$TERMINAL` | sh | _see in-file docs_ |
|
||||
| [pskill](pskill) | Fuzzy list by name and kill process or zombie | sh | fzf, ps, sudo/doas |
|
||||
| [renamer](renamer) | Batch rename selection or files in dir | sh | [qmv](https://www.nongnu.org/renameutils/)/[vidir](https://joeyh.name/code/moreutils/) |
|
||||
| [renamer](renamer) | Batch rename selection or files in dir [✓] | sh | [qmv](https://www.nongnu.org/renameutils/)/[vidir](https://joeyh.name/code/moreutils/) |
|
||||
| [ringtone](ringtone) | Create a variable bitrate mp3 ringtone from file | sh | date, ffmpeg |
|
||||
| [splitjoin](splitjoin) | Split file or join selection | sh | split, cat |
|
||||
| [rsynccp](rsynccp) | Gives copy-paste verbose progress percentage [✓] | sh | rsync |
|
||||
| [splitjoin](splitjoin) | Split file or join selection [✓] | sh | split, cat |
|
||||
| [suedit](suedit) | Edit file using superuser permissions | sh | sudoedit/sudo/doas |
|
||||
| [togglex](togglex) | Toggle executable mode for selection | sh | chmod |
|
||||
| [treeview](treeview) | Informative tree output in `$EDITOR` | sh | tree |
|
||||
| [uidgid](uidgid) | List user and group of all files in dir | sh | ls, less |
|
||||
| [upgrade](upgrade) | Upgrade nnn manually on Debian 9 Stretch | sh | curl |
|
||||
| [togglex](togglex) | Toggle executable mode for selection [✓] | sh | chmod |
|
||||
| [umounttree](umounttree) | Unmount a remote mountpoint from within | sh | fusermount |
|
||||
| [upload](upload) | Upload to Firefox Send or ix.io (text) or file.io (bin) | sh | [ffsend](https://github.com/timvisee/ffsend), curl, jq, tr |
|
||||
| [vidthumb](vidthumb) | Show video thumbnails in terminal | sh | [ffmpegthumbnailer](https://github.com/dirkvdb/ffmpegthumbnailer),<br>[lsix](https://github.com/hackerb9/lsix) |
|
||||
| [wall](wall) | Set wallpaper or change colorscheme | sh | nitrogen/pywal |
|
||||
| [x2sel](x2sel) | Copy `\n`-separated file list from system clipboard to sel | sh | _see in-file docs_ |
|
||||
| [wallpaper](wallpaper) | Set wallpaper or change colorscheme | sh | nitrogen/pywal |
|
||||
| [x2sel](x2sel) | Copy file list from system clipboard to selection | sh | _see in-file docs_ |
|
||||
| [xdgdefault](xdgdefault) | Set the default app for the hovered file type | sh | xdg-utils, fzf/dmenu |
|
||||
|
||||
Notes:
|
||||
|
||||
1. A plugin has to explicitly request `nnn` to clear the selection e.g. after operating on the selected files.
|
||||
2. Files starting with a dot in the `plugins` directory are internal files and should not be used as plugins.
|
||||
|
||||
### Table of contents
|
||||
|
||||
- [Installation](#installation)
|
||||
- [Configuration](#configuration)
|
||||
- [Skip directory refresh after running a plugin](#skip-directory-refresh-after-running-a-plugin--)
|
||||
- [Running commands as plugin](#running-commands-as-plugin-)
|
||||
- [Skip user confirmation after command execution](#skip-user-confirmation-after-command-execution-)
|
||||
- [Run a GUI app as plugin](#run-a-gui-app-as-plugin-)
|
||||
- [Page non-interactive command output](#page-non-interactive-command-output-)
|
||||
- [Some useful key-command examples](#some-useful-key-command-examples)
|
||||
- [Access level of plugins](#access-level-of-plugins)
|
||||
- [Create your own plugins](#create-your-own-plugins)
|
||||
- [Send data to `nnn`](#send-data-to-nnn)
|
||||
- [Get notified on file hover](#get-notified-on-file-hover)
|
||||
- [Examples](#examples)
|
||||
- [Contributing plugins](#contributing-plugins)
|
||||
|
||||
## Installation
|
||||
|
||||
The following command installs or updates (after backup) all plugins:
|
||||
|
||||
```sh
|
||||
curl -Ls https://raw.githubusercontent.com/jarun/nnn/master/plugins/getplugs | sh
|
||||
sh -c "$(curl -Ls https://raw.githubusercontent.com/jarun/nnn/master/plugins/getplugs)"
|
||||
```
|
||||
|
||||
Plugins are installed to `${XDG_CONFIG_HOME:-$HOME/.config}/nnn/plugins`.
|
||||
|
@ -84,7 +105,7 @@ Plugins are installed to `${XDG_CONFIG_HOME:-$HOME/.config}/nnn/plugins`.
|
|||
Set environment variable `NNN_PLUG` to assign keybinds and invoke plugins directly using the plugin shortcut (<kbd>;</kbd>) followed by the assigned key character. E.g., with the below config:
|
||||
|
||||
```sh
|
||||
export NNN_PLUG='f:finder;o:fzopen;p:mocplay;d:diffs;t:nmount;v:imgview'
|
||||
export NNN_PLUG='f:finder;o:fzopen;p:mocq;d:diffs;t:nmount;v:imgview'
|
||||
```
|
||||
|
||||
plugin `finder` can be invoked with the keybind <kbd>;f</kbd>, `fzopen` can be run with <kbd>;o</kbd> and so on... The key vs. plugin pairs are shown in the help and config screen.
|
||||
|
@ -100,88 +121,101 @@ If the plugins list gets too long, try breaking them up into sections:
|
|||
```
|
||||
NNN_PLUG_PERSONAL='g:personal/convert2zoom;p:personal/echo'
|
||||
NNN_PLUG_WORK='j:work/prettyjson;d:work/foobar'
|
||||
NNN_PLUG_INLINE='e:_go run $nnn*'
|
||||
NNN_PLUG_DEFAULT='1:bookmarks;2:ipinfo;p:preview-tui;o:fzz;b:nbak'
|
||||
NNN_PLUG_INLINE='e:!go run "$nnn"*'
|
||||
NNN_PLUG_DEFAULT='1:ipinfo;p:preview-tui;o:fzz;b:nbak'
|
||||
NNN_PLUG="$NNN_PLUG_PERSONAL;$NNN_PLUG_WORK;$NNN_PLUG_DEFAULT;$NNN_PLUG_INLINE"
|
||||
export NNN_PLUG
|
||||
```
|
||||
|
||||
Note:
|
||||
- `'g:personal/convert2zoom'` will look in the personal sub-folder inside the plugin folder.
|
||||
- `'b:boom;b:bookmarks` will result in only the first definition of *b* (`b:boom`) being used.
|
||||
- `'b:boom;b:bulknew` will result in only the first definition of *b* (`b:boom`) being used.
|
||||
- A keybinding definition of more than 1 character will prevent nnn from starting.
|
||||
|
||||
|
||||
#### Skip directory refresh after running a plugin
|
||||
#### Skip directory refresh after running a plugin [`-`]
|
||||
|
||||
`nnn` refreshes the directory after running a plugin to reflect any changes by the plugin. To disable this (say while running the `mediainf` plugin on some filtered files), add a `-` before the plugin name:
|
||||
`nnn` refreshes the directory after running a plugin to reflect any changes by the plugin. To disable this add a `-` before the plugin name:
|
||||
|
||||
```sh
|
||||
export NNN_PLUG='m:-mediainf'
|
||||
export NNN_PLUG='p:-plugin'
|
||||
```
|
||||
|
||||
Now `nnn` will not refresh the directory after running the `mediainf` plugin.
|
||||
## Running commands as plugin [`!`]
|
||||
|
||||
## Running commands as plugin
|
||||
|
||||
To assign keys to arbitrary non-background, non-shell-interpreted cli commands and invoke like plugins, add `_` (underscore) before the command.
|
||||
|
||||
For example:
|
||||
To assign keys to arbitrary non-background cli commands and invoke like plugins, add `!` before the command.
|
||||
|
||||
```sh
|
||||
export NNN_PLUG='x:_chmod +x $nnn;g:_git log;s:_smplayer $nnn'
|
||||
export NNN_PLUG='x:!chmod +x "$nnn";g:!git log;s:!smplayer "$nnn"'
|
||||
```
|
||||
|
||||
Now <kbd>;x</kbd> can be used to make a file executable, <kbd>;g</kbd> can be used to the git log of a git project directory, <kbd>;s</kbd> can be used to preview a partially downloaded media file.
|
||||
|
||||
#### Skip user confirmation after command execution
|
||||
#### Skip user confirmation after command execution [`*`]
|
||||
|
||||
`nnn` waits for user confirmation (the prompt `Press Enter to continue`) after it executes a command as plugin (unlike plugins which can add a `read` to wait). To skip this, add a `*` after the command. For example:
|
||||
`nnn` waits for user confirmation (the prompt `Press Enter to continue`) after it executes a command as plugin (unlike plugins which can add a `read` to wait). To skip this, add a `*` after the command.
|
||||
|
||||
```sh
|
||||
export NNN_PLUG='s:_smplayer $nnn*;n:-_vim /home/vaio/Dropbox/Public/synced_note*'
|
||||
export NNN_PLUG='s:!smplayer "$nnn"*;n:-!vim /home/vaio/Dropbox/Public/synced_note*'
|
||||
```
|
||||
|
||||
Now there will be no prompt after <kbd>;s</kbd> and <kbd>;n</kbd>.
|
||||
|
||||
Note: Do not use `*` with programs those run and exit e.g. cat.
|
||||
Note: Do not use `*` with programs that run and exit e.g. cat.
|
||||
|
||||
#### Run GUI app as plugin
|
||||
#### Run a GUI app as plugin [`&`]
|
||||
|
||||
To run a GUI app as plugin, add a `|` after `_`. For example:
|
||||
To run a GUI app as plugin, add a `&` after `!`.
|
||||
|
||||
```sh
|
||||
export NNN_PLUG='m:-_|mousepad $nnn'
|
||||
export NNN_PLUG='m:-!&mousepad "$nnn"'
|
||||
```
|
||||
|
||||
Notes:
|
||||
#### Page non-interactive command output [`|`]
|
||||
|
||||
1. Use single quotes for `$NNN_PLUG` so `$nnn` is not interpreted
|
||||
2. `$nnn` should be the last argument (IF used)
|
||||
3. (_Again_) add `_` before the command
|
||||
4. To disable directory refresh after running a _command as plugin_, prefix with `-_`
|
||||
To show the output of run-and-exit commands which do not need user input, add `|` (pipe) after `!`.
|
||||
|
||||
```sh
|
||||
export NNN_PLUG='m:-!|mediainfo "$nnn";t:-!|tree -ps;l:-!|ls -lah --group-directories-first'
|
||||
```
|
||||
|
||||
This option is incompatible with `&` (terminal output is masked for GUI programs) and ignores `*` (output is already paged for user).
|
||||
|
||||
Notes:
|
||||
1. Place `$nnn` (or exported variables) in double quotes (**`"$nnn"`**)
|
||||
2. Use single quotes for `$NNN_PLUG` so `"$nnn"` is not interpreted
|
||||
3. (_Again_) add `!` before the command
|
||||
4. To disable directory refresh after running a _command as plugin_, prefix with `-!`
|
||||
|
||||
#### Some useful key-command examples
|
||||
|
||||
| Key:Command | Description |
|
||||
|---|---|
|
||||
| `g:-_git diff` | Show git diff |
|
||||
| `k:-_fuser -kiv $nnn*` | Interactively kill process(es) using hovered file |
|
||||
| `l:-_git log` | Show git log |
|
||||
| `n:-_vi /home/user/Dropbox/dir/note*` | Take quick notes in a synced file/dir of notes |
|
||||
| `p:-_less -iR $nnn*` | Page through hovered file in less |
|
||||
| `s:-_\|smplayer -minigui $nnn` | Play hovered media file, even unfinished download |
|
||||
| `x:_chmod +x $nnn` | Make the hovered file executable |
|
||||
| `y:-_sync*` | Flush cached writes |
|
||||
| `c:!convert "$nnn" png:- \| xclip -sel clipboard -t image/png*` | Copy image to clipboard |
|
||||
| `C:!cp -rv "$nnn" "$nnn".cp` | Create a copy of the hovered file |
|
||||
| `e:-!sudo -E vim "$nnn"*` | Edit file as root in vim |
|
||||
| `g:-!git diff` | Show git diff |
|
||||
| `h:-!hx "$nnn"*` | Open hovered file in [hx](https://github.com/krpors/hx) hex editor |
|
||||
| `k:-!fuser -kiv "$nnn"*` | Interactively kill process(es) using hovered file |
|
||||
| `l:-!git log` | Show git log |
|
||||
| `n:-!vi /home/user/Dropbox/dir/note*` | Take quick notes in a synced file/dir of notes |
|
||||
| `p:-!less -iR "$nnn"*` | Page through hovered file in less |
|
||||
| `s:-!&smplayer -minigui "$nnn"` | Play hovered media file, even unfinished download |
|
||||
| `x:!chmod +x "$nnn"` | Make the hovered file executable |
|
||||
| `y:-!sync*` | Flush cached writes |
|
||||
|
||||
## Access level of plugins
|
||||
|
||||
When `nnn` executes a plugin, it does the following:
|
||||
- Changes to the directory where the plugin is to be run (`$PWD` pointing to the active directory)
|
||||
- Passes two arguments to the script:
|
||||
1. The hovered file's name.
|
||||
2. The working directory (might differ from `$PWD` in case of symlinked paths; non-canonical).
|
||||
- Passes three arguments to the script:
|
||||
1. `$1`: The hovered file's name.
|
||||
2. `$2`: The working directory (might differ from `$PWD` in case of symlinked paths; non-canonical).
|
||||
3. `$3`: The picker mode output file (`-` for stdout) if `nnn` is executed as a file picker.
|
||||
- Sets the environment variable `NNN_PIPE` used to control `nnn` active directory.
|
||||
- Sets the environment variable `NNN_INCLUDE_HIDDEN` to `1` if hidden files are active, `0` otherwise.
|
||||
- Sets the environment variable `NNN_PREFER_SELECTION` to `1` if user prefers to use selection (see nnn's `-u` flag), `0` otherwise.
|
||||
- Exports the [special variables](https://github.com/jarun/nnn/wiki/Concepts#special-variables).
|
||||
|
||||
Plugins can also read the `.selection` file in the config directory.
|
||||
|
||||
|
@ -189,20 +223,25 @@ Plugins can also read the `.selection` file in the config directory.
|
|||
|
||||
Plugins can be written in any scripting language. However, POSIX-compliant shell scripts runnable in `sh` are preferred.
|
||||
|
||||
Drop the plugin in `${XDG_CONFIG_HOME:-$HOME/.config}/nnn/plugins` and make it executable. Optionally add a hotkey in `$NNN_PLUG` for frequent usage.
|
||||
**Make the file executable**. Drop it in the plugin directory. Optionally add a hotkey in `$NNN_PLUG` for frequent usage.
|
||||
|
||||
#### Send data to `nnn`
|
||||
`nnn` provides a mechanism for plugins to send data to `nnn` to control its active directory or invoke the list mode.
|
||||
The way to do so is by writing to the pipe pointed by the environment variable `NNN_PIPE`.
|
||||
The plugin should write a single string in the format `<ctxcode><opcode><data>` without a newline at the end. For example, `1c/etc`.
|
||||
The plugin should write a single string in the format `(<->)<ctxcode><opcode><data>` without a newline at the end. For example, `1c/etc`.
|
||||
|
||||
The optional `-` at the **beginning of the stream** instructs `nnn` to clear the selection.
|
||||
In cases where the data transfer to `nnn` has to happen while the selection file is being read (e.g. in a loop), the plugin should
|
||||
create a tmp copy of the selection file, inform `nnn` to clear the selection and then do the subsequent processing with the tmp file.
|
||||
A paged [`|`] or GUI [`&`] cmd run as plugin cannot clear selection.
|
||||
|
||||
The `ctxcode` indicates the context to change the active directory of.
|
||||
|
||||
| Context code | Meaning |
|
||||
|:---:| --- |
|
||||
| `1`-`4` | context number |
|
||||
| `0` | current context |
|
||||
| `+` | smart context (next inactive else current) |
|
||||
| `0` | current context |
|
||||
| `1`-`4` | context number |
|
||||
|
||||
The `opcode` indicates the operation type.
|
||||
|
||||
|
@ -210,6 +249,7 @@ The `opcode` indicates the operation type.
|
|||
|:---:| --- |
|
||||
| `c` | change directory |
|
||||
| `l` | list files in list mode |
|
||||
| `p` | picker file overwritten |
|
||||
|
||||
For convenience, we provided a helper script named `.nnn-plugin-helper` and a function named `nnn_cd` to ease this process. `nnn_cd` receives the path to change to as the first argument, and the context as an optional second argument.
|
||||
If a context is not provided, it is asked for explicitly. To skip this and choose the current context, set the `CUR_CTX` variable in `.nnn-plugin-helper` (or in the specific plugin after sourcing `.nnn-plugin-helper`) to 1.
|
||||
|
@ -223,87 +263,121 @@ Don't forget to fork in the background to avoid blocking `nnn`.
|
|||
|
||||
For more details on configuration and usage of the preview plugins, visit [Live Previews](https://github.com/jarun/nnn/wiki/Live-previews).
|
||||
|
||||
#### Examples
|
||||
## Examples
|
||||
|
||||
There are many plugins provided by `nnn` which can be used as examples. Here are a few simple selected examples.
|
||||
|
||||
- Show the git log of changes to the particular file along with the code for a quick and easy review.
|
||||
```sh
|
||||
#!/usr/bin/env sh
|
||||
git log -p -- "$1"
|
||||
```
|
||||
#### Show the git log of changes to the particular file along with the code for a quick and easy review.
|
||||
|
||||
- Change to directory in clipboard using helper script
|
||||
```sh
|
||||
#!/usr/bin/env sh
|
||||
. $(dirname $0)/.nnn-plugin-helper
|
||||
```sh
|
||||
#!/usr/bin/env sh
|
||||
|
||||
nnn_cd "$(xsel -ob)"
|
||||
```
|
||||
git log -p -- "$1"
|
||||
```
|
||||
|
||||
- Change directory to the location of a link using helper script with specific context (current)
|
||||
```sh
|
||||
#!/usr/bin/env sh
|
||||
. $(dirname $0)/.nnn-plugin-helper
|
||||
#### Change to directory in clipboard using helper script
|
||||
|
||||
nnn_cd "$(dirname $(readlink -fn $1))" 0
|
||||
```
|
||||
```sh
|
||||
#!/usr/bin/env sh
|
||||
|
||||
- Change to arbitrary directory without helper script
|
||||
```sh
|
||||
#!/usr/bin/env sh
|
||||
printf "cd to: "
|
||||
read -r dir
|
||||
. $(dirname $0)/.nnn-plugin-helper
|
||||
|
||||
printf "%s" "0c$dir" > "$NNN_PIPE"
|
||||
```
|
||||
nnn_cd "$(xsel -ob)"
|
||||
```
|
||||
|
||||
- Send every hovered file to X selection
|
||||
```sh
|
||||
#!/usr/bin/env sh
|
||||
if [ -z "$NNN_FIFO" ] ; then
|
||||
exit 1
|
||||
fi
|
||||
#### Change directory to the location of a link using helper script with specific context (current)
|
||||
|
||||
while read FILE ; do
|
||||
printf "%s" "$FILE" | xsel
|
||||
done < "$NNN_FIFO" &
|
||||
disown
|
||||
```
|
||||
```sh
|
||||
#!/usr/bin/env sh
|
||||
|
||||
- Quick find (using `fd`)
|
||||
```sh
|
||||
#!/usr/bin/env sh
|
||||
. $(dirname $0)/.nnn-plugin-helper
|
||||
|
||||
. "$(dirname "$0")"/.nnn-plugin-helper
|
||||
nnn_cd "$(dirname $(readlink -fn $1))" 0
|
||||
```
|
||||
|
||||
printf "pattern: "
|
||||
read -r pattern
|
||||
#### Change to arbitrary directory without helper script
|
||||
|
||||
if ! [ -z "$pattern" ]; then
|
||||
printf "%s" "+l" > "$NNN_PIPE"
|
||||
eval "fd -HI $pattern -0" > "$NNN_PIPE"
|
||||
fi
|
||||
```
|
||||
```sh
|
||||
#!/usr/bin/env sh
|
||||
|
||||
- Quick grep (using `rg`)
|
||||
```sh
|
||||
#!/usr/bin/env sh
|
||||
printf "cd to: "
|
||||
read -r dir
|
||||
|
||||
. "$(dirname "$0")"/.nnn-plugin-helper
|
||||
printf "%s" "0c$dir" > "$NNN_PIPE"
|
||||
```
|
||||
|
||||
printf "pattern: "
|
||||
read -r pattern
|
||||
#### Send every hovered file to X selection
|
||||
|
||||
if ! [ -z "$pattern" ]; then
|
||||
printf "%s" "+l" > "$NNN_PIPE"
|
||||
eval "rg -l0 --hidden -S $pattern" > "$NNN_PIPE"
|
||||
fi
|
||||
```
|
||||
```sh
|
||||
#!/usr/bin/env sh
|
||||
|
||||
if [ -z "$NNN_FIFO" ] ; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
while read FILE ; do
|
||||
printf "%s" "$FILE" | xsel
|
||||
done < "$NNN_FIFO" &
|
||||
disown
|
||||
```
|
||||
|
||||
#### Quick `find` the first match in subtree and open in `nuke`
|
||||
|
||||
```sh
|
||||
#!/usr/bin/env sh
|
||||
|
||||
NUKE="${XDG_CONFIG_HOME:-$HOME/.config}/nnn/plugins/nuke"
|
||||
|
||||
printf "file name: "
|
||||
read -r pattern
|
||||
|
||||
entry=$(find . -type f -iname "$pattern" -print -quit 2>/dev/null)
|
||||
|
||||
if [ -n "$entry" ]; then
|
||||
"$NUKE" "$entry"
|
||||
fi
|
||||
```
|
||||
|
||||
#### Quick find (using `fd`)
|
||||
|
||||
```sh
|
||||
#!/usr/bin/env sh
|
||||
|
||||
. "$(dirname "$0")"/.nnn-plugin-helper
|
||||
|
||||
printf "pattern: "
|
||||
read -r pattern
|
||||
|
||||
if [ -n "$pattern" ]; then
|
||||
printf "%s" "+l" > "$NNN_PIPE"
|
||||
eval "fd -HI $pattern -0" > "$NNN_PIPE"
|
||||
fi
|
||||
```
|
||||
|
||||
#### Quick grep (using `rg`)
|
||||
|
||||
```sh
|
||||
#!/usr/bin/env sh
|
||||
|
||||
. "$(dirname "$0")"/.nnn-plugin-helper
|
||||
|
||||
printf "pattern: "
|
||||
read -r pattern
|
||||
|
||||
if [ -n "$pattern" ]; then
|
||||
printf "%s" "+l" > "$NNN_PIPE"
|
||||
eval "rg -l0 --hidden -S $pattern" > "$NNN_PIPE"
|
||||
fi
|
||||
```
|
||||
|
||||
#### Change directory
|
||||
|
||||
NNN_PLUG='c:!read -r to && [ -n "$to" ] && printf "0c%s" "${to}" > "$NNN_PIPE"*'
|
||||
|
||||
## Contributing plugins
|
||||
|
||||
1. Add informative sections like _Description_, _Notes_, _Dependencies_, _Shell_, _Author_ etc. in the plugin.
|
||||
2. Add an entry in the table above.
|
||||
2. Add an entry in the table above. Note that the list is alphabetically ordered by plugin name.
|
||||
3. Keep non-portable commands (like `notify-send`) commented so users from any other OS/DE aren't surprised.
|
||||
4. The plugin file should be executable.
|
||||
5. If your plugin stores data, use `${XDG_CACHE_HOME:-$HOME/.cache}/nnn`. Document it _in-file_.
|
||||
|
|
|
@ -1,33 +1,41 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
# Description: Navigate to directory using jump/autojump/zoxide
|
||||
# Description: Navigate to directory using jump/autojump/zoxide/z
|
||||
#
|
||||
# Dependencies: jump - https://github.com/gsamokovarov/jump
|
||||
# OR autojump - https://github.com/wting/autojump
|
||||
# OR zoxide - https://github.com/ajeetdsouza/zoxide
|
||||
# Dependencies:
|
||||
# - jump - https://github.com/gsamokovarov/jump
|
||||
# - OR autojump - https://github.com/wting/autojump
|
||||
# - OR zoxide - https://github.com/ajeetdsouza/zoxide
|
||||
# - OR z - https://github.com/rupa/z (z requires fzf)
|
||||
# - OR z (fish) - https://github.com/jethrokuan/z (z requires fzf)
|
||||
# - OR z.lua - https://github.com/skywind3000/z.lua (z.lua can enhanced with fzf)
|
||||
#
|
||||
# Note: The dependencies STORE NAVIGATION PATTERNS
|
||||
#
|
||||
# to make z.lua work, you need to set $NNN_ZLUA to the path of script z.lua
|
||||
#
|
||||
# Shell: POSIX compliant
|
||||
# Authors: Marty Buchaus, Dave Snider, Tim Adler
|
||||
# Authors: Marty Buchaus, Dave Snider, Tim Adler, Nick Waywood
|
||||
|
||||
if [ -z "$NNN_PIPE" ]; then
|
||||
echo 'ERROR: NNN_PIPE is not set' | ${PAGER:-less}
|
||||
if [ ! -p "$NNN_PIPE" ]; then
|
||||
printf 'ERROR: NNN_PIPE is not set!'
|
||||
read -r _
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if which jump >/dev/null 2>&1; then
|
||||
if type jump >/dev/null 2>&1; then
|
||||
printf "jump to : "
|
||||
read -r dir
|
||||
odir="$(jump cd "$dir")"
|
||||
IFS= read -r line
|
||||
# shellcheck disable=SC2086
|
||||
odir="$(jump cd ${line})"
|
||||
printf "%s" "0c$odir" > "$NNN_PIPE"
|
||||
elif which autojump >/dev/null 2>&1; then
|
||||
elif type autojump >/dev/null 2>&1; then
|
||||
printf "jump to : "
|
||||
read -r dir
|
||||
odir="$(autojump "$dir")"
|
||||
printf "%s" "0c$odir" > "$NNN_PIPE"
|
||||
elif which zoxide >/dev/null 2>&1; then
|
||||
if which fzf >/dev/null 2>&1; then
|
||||
elif type zoxide >/dev/null 2>&1; then
|
||||
if type fzf >/dev/null 2>&1; then
|
||||
odir="$(zoxide query -i --)"
|
||||
printf "%s" "0c$odir" > "$NNN_PIPE"
|
||||
else
|
||||
|
@ -36,7 +44,31 @@ elif which zoxide >/dev/null 2>&1; then
|
|||
odir="$(zoxide query -- "$dir")"
|
||||
printf "%s" "0c$odir" > "$NNN_PIPE"
|
||||
fi
|
||||
elif type lua >/dev/null 2>&1 && [ -n "$NNN_ZLUA" ]; then
|
||||
printf "jump to : "
|
||||
read -r line
|
||||
if type fzf >/dev/null 2>&1; then
|
||||
odir="$(lua "$NNN_ZLUA" -l "$line" | fzf --nth 2.. --reverse --inline-info --tac +s -e --height 35%)"
|
||||
printf "%s" "0c$(echo "$odir" | awk '{print $2}')" > "$NNN_PIPE"
|
||||
else
|
||||
odir="$(lua "$NNN_ZLUA" -e "$line")"
|
||||
printf "%s" "0c$odir" > "$NNN_PIPE"
|
||||
fi
|
||||
else
|
||||
printf "No supported autojump script found. (jump/autojump/zoxide are supported)"
|
||||
read -r _
|
||||
# rupa/z uses $_Z_DATA, jethrokuan/z (=port of z for fish) uses $Z_DATA
|
||||
datafile="${_Z_DATA:-${Z_DATA:-$HOME/.z}}"
|
||||
if type fzf >/dev/null 2>&1 && [ -f "$datafile" ]; then
|
||||
# Read the data from z's file instead of calling
|
||||
# z so the data doesn't need to be processed twice
|
||||
sel=$(awk -F "|" '{print $1}' "$datafile" | fzf | awk '{$1=$1};1')
|
||||
|
||||
# NOTE: Uncomment this line and comment out the line above if
|
||||
# you want to see the weightings of the dir's in the fzf pane
|
||||
# sel=$(awk -F "|" '{printf "%s %s\n", $2, $1}' "$datafile" | fzf | sed 's/^[0-9,.]* *//' | awk '{$1=$1};1')
|
||||
|
||||
printf "%s" "0c$sel" > "$NNN_PIPE"
|
||||
else
|
||||
printf "No supported autojump script [jump/autojump/zoxide/z (needs fzf)] found"
|
||||
read -r _
|
||||
fi
|
||||
fi
|
||||
|
|
|
@ -1,60 +0,0 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
# Description: Use named bookmarks using symlinks
|
||||
#
|
||||
# Dependencies: fzf
|
||||
#
|
||||
# Usage:
|
||||
# 1. Create a $BOOKMARKS_DIR directory
|
||||
# By default, $BOOKMARKS_DIR is set to: ${XDG_CACHE_HOME:-$HOME/.cache}/nnn/bookmarks
|
||||
#
|
||||
# 2. Create symlinks to directories
|
||||
# `cd $BOOKMARKS_DIR`
|
||||
# `ln -s /path/to/useful/directory bookmark_name`
|
||||
# `ln -s $XDG_CONFIG_HOME/nnn/plugins nnn_plugins"
|
||||
# `ln -s /path/to/documents docs`
|
||||
# `ln -s /path/to/media media`
|
||||
# `ln -s /path/to/movies movies`
|
||||
#
|
||||
# Bonus tip: Add `$BOOKMARKS_DIR` to your `$CDPATH`
|
||||
# https://linux.101hacks.com/cd-command/cdpath/
|
||||
#
|
||||
# TODO:
|
||||
# 1. Remove `fzf` dependency
|
||||
#
|
||||
# Shell: POSIX compliant
|
||||
# Author: Todd Yamakawa
|
||||
|
||||
if [ -z "$BOOKMARKS_DIR" ]; then
|
||||
BOOKMARKS_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/nnn/bookmarks"
|
||||
fi
|
||||
|
||||
# Check if NNN_PIPE is set
|
||||
if [ -z "$NNN_PIPE" ]; then
|
||||
echo 'ERROR: NNN_PIPE is not set' | ${PAGER:-less}
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Get all directory symlinks
|
||||
get_links() {
|
||||
for entry in "$1"/*; do
|
||||
|
||||
# Skip unless directory symlink
|
||||
[ -h "$entry" ] || continue
|
||||
[ -d "$entry" ] || continue
|
||||
|
||||
printf "%20s -> %s\n" "$(basename "$entry")" "$(readlink -f "$entry")"
|
||||
done | fzf |
|
||||
awk 'END {
|
||||
if (length($1) == 0) { print "'"$PWD"'" }
|
||||
else { print "'"$BOOKMARKS_DIR"'/"$1 }
|
||||
}'
|
||||
}
|
||||
|
||||
# Choose symlink with fzf
|
||||
cddir="$(get_links "$BOOKMARKS_DIR")"
|
||||
|
||||
# Writing result to NNN_PIPE will change nnn's active directory
|
||||
# https://github.com/jarun/nnn/tree/master/plugins#send-data-to-nnn
|
||||
context=0
|
||||
printf "%s" "${context}c$(readlink -f "$cddir")" > "$NNN_PIPE"
|
11
plugins/boom
11
plugins/boom
|
@ -1,12 +1,15 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
# Description: Play random music from current directory. Identifies MP3, FLAC, M4A, WEBM, WMA.
|
||||
# You may want to set GUIPLAYER.
|
||||
# Description: Play random music (MP3, FLAC, M4A, WEBM, WMA) from current dir.
|
||||
#
|
||||
# Dependencies: mocp (or custom)
|
||||
#
|
||||
# Note: You may want to set GUIPLAYER.
|
||||
#
|
||||
# Shell: POSIX compliant
|
||||
# Author: Arun Prakash Jana
|
||||
|
||||
GUIPLAYER="${GUIPLAYER}"
|
||||
GUIPLAYER="${GUIPLAYER:-""}"
|
||||
NUMTRACKS="${NUMTRACKS:-100}"
|
||||
|
||||
if [ -n "$GUIPLAYER" ]; then
|
||||
|
@ -14,7 +17,7 @@ if [ -n "$GUIPLAYER" ]; then
|
|||
|
||||
# detach the player
|
||||
sleep 1
|
||||
elif which mocp >/dev/null 2>&1; then
|
||||
elif type mocp >/dev/null 2>&1; then
|
||||
cmd=$(pgrep -x mocp 2>/dev/null)
|
||||
ret=$cmd
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
# Description: Allows for creation of multiple files/directories at the same time.
|
||||
# Plugin opens a temp file where each entry is to be written on a separate line
|
||||
# Description: Allows for creation of multiple files/dirs simultaneously
|
||||
# Creates a tmp file to write each entry in a separate line
|
||||
#
|
||||
# Note: Only relative paths are supported. Absolute paths are ignored
|
||||
# Leading and trailing whitespace in path names is also ignored
|
||||
|
@ -29,4 +29,4 @@ $EDITOR "$tmpfile"
|
|||
|
||||
sed "/^\//d" "$tmpfile" | xargs -n1 -I{} sh -c "$cmd"
|
||||
|
||||
rm "$tmpfile"
|
||||
rm -- "$tmpfile"
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/osascript
|
||||
|
||||
# Description: Copy the hovered file to MacOS clipboard.
|
||||
#
|
||||
# Note: Supports only MacOS
|
||||
#
|
||||
# Shell: POSIX compliant
|
||||
# Author: Syed Umar Anis
|
||||
|
||||
|
||||
on run args
|
||||
set filePath to (second item of args & "/" & first item of args)
|
||||
tell application "Finder"
|
||||
set the clipboard to (filePath as POSIX file)
|
||||
end tell
|
||||
end
|
|
@ -0,0 +1,24 @@
|
|||
#!/usr/bin/env sh
|
||||
# shellcheck disable=all
|
||||
|
||||
# Description: Paste the clipboard files into the current directory.
|
||||
# Only works if clipboard contents are files.
|
||||
#
|
||||
# Note: Supports only MacOS
|
||||
#
|
||||
# Shell: POSIX compliant
|
||||
# Author: Syed Umar Anis
|
||||
|
||||
|
||||
fs=($( osascript -e "use framework \"Foundation\"
|
||||
property this : a reference to the current application
|
||||
property NSPasteboard : a reference to NSPasteboard of this
|
||||
property NSURL : a reference to NSURL of this
|
||||
property pb : a reference to NSPasteboard's generalPasteboard
|
||||
|
||||
property text item delimiters : linefeed
|
||||
|
||||
pb's readObjectsForClasses:[NSURL] options:[]
|
||||
(result's valueForKey:\"path\") as list as text" ))
|
||||
|
||||
cp -R -- "${fs[@]}" "$2/"
|
|
@ -0,0 +1,56 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
# Description: 'cd' to the directory from CDPATH
|
||||
#
|
||||
# Details: If the CDPATH environment variable is not set, the default value of
|
||||
# ${XDG_CONFIG_HOME:-$HOME/.config}/nnn/bookmarks will be used.
|
||||
# You can create this directory and fill it with symbolic links to your
|
||||
# favorite directories. It's a good idea to add it to CDPATH so that it
|
||||
# could also be used from the command line outside of nnn.
|
||||
# The fzf search is done on the directory basename (the first column).
|
||||
#
|
||||
# This plugin is an extended version of the bookmarks plugin.
|
||||
# If you set your CDPATH to ${XDG_CACHE_HOME:-$HOME/.cache}/nnn/bookmarks
|
||||
# or to the value of BOOKMARKS_DIR, you can use it as a bookmarks replacement.
|
||||
#
|
||||
# Shell: POSIX compliant
|
||||
# Author: Yuri Kloubakov
|
||||
|
||||
# shellcheck disable=SC1090,SC1091
|
||||
. "$(dirname "$0")"/.nnn-plugin-helper
|
||||
|
||||
# Get a list of (symbolic links to) directories for every element of CDPATH
|
||||
get_dirs() {
|
||||
IFS=':'
|
||||
for path in $CDPATH; do
|
||||
for entry in "$path"/*; do
|
||||
if [ -d "$entry" ]; then
|
||||
name=$(basename "$entry" | grep -o '^.\{1,24\}')
|
||||
if [ -h "$entry" ]; then
|
||||
slink=$(ls -dl -- "$entry")
|
||||
entry=${slink#*" $entry -> "}
|
||||
fi
|
||||
printf "%-24s :%s\n" "${name}" "$entry"
|
||||
fi
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
abort() {
|
||||
echo "$1"
|
||||
read -r _
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [ -z "$CDPATH" ]; then
|
||||
CDPATH="${XDG_CONFIG_HOME:-$HOME/.config}/nnn/bookmarks"
|
||||
[ -d "$CDPATH" ] || abort "CDPATH is not set and there is no \"$CDPATH\" directory"
|
||||
fi
|
||||
|
||||
dir_list=$(get_dirs)
|
||||
[ -n "$dir_list" ] || abort "There are no directories to choose from. Check your \"$CDPATH\"."
|
||||
|
||||
dir=$(echo "$dir_list" | fzf --nth=1 --delimiter=':' | awk -F: 'END { print $2 }')
|
||||
if [ -n "$dir" ]; then
|
||||
nnn_cd "$dir" 0
|
||||
fi
|
|
@ -2,13 +2,17 @@
|
|||
|
||||
# Description: Create and verify checksums
|
||||
#
|
||||
# For selection: it will generate one file containing the checksums with file names
|
||||
# [and with paths if they are in another directory]
|
||||
# the output checksum filename will be checksum_timestamp.checksum_type
|
||||
# For file: if the file is a checksum, the plugin does the verification
|
||||
# Note: On macOS, install the relevant checksum packages from Homebrew with:
|
||||
# brew install coreutils
|
||||
#
|
||||
# Details:
|
||||
# - selection: it will generate one file with the checksums and filenames
|
||||
# (and with paths if they are in another directory)
|
||||
# output checksum filename format: checksum_timestamp.checksum_type
|
||||
# - file: if the file is a checksum, the plugin does the verification
|
||||
# if the file is not a checksum, checksum will be generated for it
|
||||
# the output checksum filename will be filename.checksum_type
|
||||
# For directory: recursively calculates checksum for all the files in the directory
|
||||
# - directory: recursively calculates checksum for all the files in the dir
|
||||
# the output checksum filename will be directory.checksum_type
|
||||
#
|
||||
# Shell: POSIX compliant
|
||||
|
@ -45,6 +49,11 @@ fi
|
|||
if [ "$resp" = "s" ]; then
|
||||
checksum_type
|
||||
sed 's|'"$PWD/"'||g' < "$selection" | xargs -0 -I{} ${chsum}sum {} > "checksum_$(date '+%Y%m%d%H%M').$chsum"
|
||||
|
||||
# Clear selection
|
||||
if [ -p "$NNN_PIPE" ]; then
|
||||
printf "-" > "$NNN_PIPE"
|
||||
fi
|
||||
elif [ -n "$1" ]; then
|
||||
if [ -f "$1" ]; then
|
||||
for chks in md5 sha1 sha224 sha256 sha384 sha512
|
||||
|
@ -52,7 +61,7 @@ elif [ -n "$1" ]; then
|
|||
if echo "$1" | grep -q \.${chks}$; then
|
||||
${chks}sum -c < "$1"
|
||||
read -r _
|
||||
return
|
||||
exit
|
||||
fi
|
||||
done
|
||||
checksum_type
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
# Description: Add selection or hovered file/directory to cmus queue
|
||||
#
|
||||
# Dependencies: cmus, pgrep, xdotool (optional)
|
||||
#
|
||||
# Notes:
|
||||
# 1. If adding selection, files/dirs are added in the same order they were selected in nnn
|
||||
# 2. A new window will be opened if cmus is not running already, playback will start immediately
|
||||
# 3. If cmus is already running, files will be appended to the queue with no forced playback
|
||||
#
|
||||
# TODO:
|
||||
# 1. Add cava and cmus-lyrics as optional dependencies
|
||||
# 2. Start cava and/or cmus-lyrics in tmux or kitty panes next to cmus
|
||||
#
|
||||
# Shell: POSIX compliant
|
||||
# Author: Kabouik
|
||||
|
||||
# (Optional) Set preferred terminal emulator for cmus if not set in your env,
|
||||
# or leave commented out to use OS default
|
||||
#TERMINAL="kitty"
|
||||
|
||||
if ! type cmus >/dev/null; then
|
||||
printf "cmus missing"
|
||||
read -r _
|
||||
exit 1
|
||||
fi
|
||||
|
||||
selection=${NNN_SEL:-${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.selection}
|
||||
|
||||
start_cmus() {
|
||||
type xdotool >/dev/null && nnnwindow="$(xdotool getactivewindow)"
|
||||
case "$TERMINAL" in
|
||||
kitty | gnome-terminal | st)
|
||||
nohup "$TERMINAL" -- cmus & ;;
|
||||
havoc)
|
||||
nohup "$TERMINAL" cmus & ;;
|
||||
"")
|
||||
nohup x-terminal-emulator -e cmus & ;;
|
||||
*)
|
||||
nohup "$TERMINAL" -e cmus & ;;
|
||||
esac
|
||||
# Give the new terminal some time to open
|
||||
until cmus-remote -C; do sleep 0.1; done
|
||||
[ -n "$nnnwindow" ] && xdotool windowactivate "$nnnwindow"
|
||||
} >/dev/null 2>&1
|
||||
|
||||
fill_queue() {
|
||||
if [ "$REPLY" = "s" ]; then
|
||||
xargs < "$selection" -0 cmus-remote -q
|
||||
elif [ -n "$1" ]; then
|
||||
cmus-remote -q "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
# If active selection,then ask what to do
|
||||
if [ -s "$selection" ]; then
|
||||
printf "Queue [s]election or [c]urrently hovered? [default=c]: "
|
||||
read -r REPLY
|
||||
fi
|
||||
|
||||
# If cmus is not running, start and play queue
|
||||
if ! pgrep cmus >/dev/null; then
|
||||
printf "cmus is not running, starting it in a new %s window.\n" "$TERMINAL"
|
||||
start_cmus
|
||||
fill_queue "$1"
|
||||
cmus-remote -p
|
||||
printf "Files added to cmus queue.\n"
|
||||
else # Append to existing queue if cmus is already running
|
||||
fill_queue "$1"
|
||||
printf "Files appended to current cmus queue.\n"
|
||||
fi
|
||||
|
||||
# Change view
|
||||
cmus-remote -C "view 4"
|
||||
|
||||
# Clear selection
|
||||
if [ -p "$NNN_PIPE" ]; then
|
||||
printf "-" > "$NNN_PIPE"
|
||||
fi
|
|
@ -2,17 +2,18 @@
|
|||
|
||||
# Description: Show diff of 2 directories or multiple files in vimdiff
|
||||
#
|
||||
# Note: 1. vim may show the warning: 'Vim: Warning: Input is not from a terminal'
|
||||
# press 'Enter' to ignore and proceed.
|
||||
# 2. if only one file is in selection, the hovered file is considered as the
|
||||
# second file to diff with
|
||||
# Notes:
|
||||
# 1. vim may show the warning: 'Vim: Warning: Input is not from a terminal'
|
||||
# press 'Enter' to ignore and proceed.
|
||||
# 2. if only one file is in selection, the hovered file is considered as the
|
||||
# second file to diff with
|
||||
#
|
||||
# Shell: POSIX compliant
|
||||
# Authors: Arun Prakash Jana, ath3
|
||||
|
||||
selection=${NNN_SEL:-${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.selection}
|
||||
|
||||
if which nvim >/dev/null 2>&1; then
|
||||
if type nvim >/dev/null 2>&1; then
|
||||
diffcmd="nvim -d"
|
||||
else
|
||||
diffcmd="vimdiff +0"
|
||||
|
@ -24,7 +25,7 @@ dirdiff() {
|
|||
ls -A1 "$1" > "$dir1"
|
||||
ls -A1 "$2" > "$dir2"
|
||||
$diffcmd "$dir1" "$dir2"
|
||||
rm "$dir1" "$dir2"
|
||||
rm -- "$dir1" "$dir2"
|
||||
}
|
||||
|
||||
if [ -s "$selection" ]; then
|
||||
|
@ -54,3 +55,8 @@ if [ -s "$selection" ]; then
|
|||
echo "needs at least 2 files or directories selected for comparison"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Clear selection
|
||||
if [ -p "$NNN_PIPE" ]; then
|
||||
printf "-" > "$NNN_PIPE"
|
||||
fi
|
||||
|
|
|
@ -3,13 +3,13 @@
|
|||
# Description: Open a Drag and drop window, to drop files onto other programs.
|
||||
# Also provides drag and drop window for files.
|
||||
#
|
||||
# Dependencies: https://github.com/mwh/dragon
|
||||
# Dependencies: dragon - https://github.com/mwh/dragon
|
||||
#
|
||||
# Notes:
|
||||
# - Files that are dropped will be added to nnn's selection
|
||||
# Some webbased files will be downloaded to current directory with curl
|
||||
# and it may overwrite some existing files
|
||||
# - The user has to mm to clear nnn's selection first
|
||||
# 1. Files that are dropped will be added to nnn's selection
|
||||
# Some web-based files will be downloaded to current dir
|
||||
# with curl and it may overwrite some existing files
|
||||
# 2. The user has to mm to clear nnn's selection first
|
||||
#
|
||||
# Shell: POSIX compliant
|
||||
# Author: 0xACE
|
||||
|
@ -17,8 +17,10 @@
|
|||
selection=${NNN_SEL:-${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.selection}
|
||||
resp=f
|
||||
all=
|
||||
if which dragon-drag-and-drop >/dev/null 2>&1; then
|
||||
if type dragon-drag-and-drop >/dev/null 2>&1; then
|
||||
dnd="dragon-drag-and-drop"
|
||||
elif type dragon-drop >/dev/null 2>&1; then
|
||||
dnd="dragon-drop"
|
||||
else
|
||||
dnd="dragon"
|
||||
fi
|
||||
|
|
30
plugins/dups
30
plugins/dups
|
@ -1,19 +1,19 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
# Description: List non-empty duplicate files in the current directory (based on size followed by MD5)
|
||||
# Description: List non-empty duplicates in the current dir (based on size followed by MD5)
|
||||
#
|
||||
# Source: https://www.commandlinefu.com/commands/view/3555/find-duplicate-files-based-on-size-first-then-md5-hash
|
||||
#
|
||||
# Dependencies: find md5sum sort uniq xargs gsed
|
||||
#
|
||||
# Note: bash compatible required for mktemp
|
||||
# Notes:
|
||||
# 1. If the file size exceeds $size_digits digits the file will be misplaced
|
||||
# 12 digits fit files up to 931GiB
|
||||
# 2. Bash compatible required for mktemp
|
||||
#
|
||||
# Shell: bash
|
||||
# Shell: Bash
|
||||
# Authors: syssyphus, KlzXS
|
||||
|
||||
# If the size of a file has more that $size_digits digits the file will be misplaced
|
||||
# 12 digits fit files up to 931GiB
|
||||
|
||||
EDITOR="${EDITOR:-vi}"
|
||||
TMPDIR="${TMPDIR:-/tmp}"
|
||||
|
||||
|
@ -28,17 +28,17 @@ printf "\
|
|||
" > "$tmpfile"
|
||||
|
||||
# shellcheck disable=SC2016
|
||||
find . -size +0 -type f -printf "%${size_digits}s %p\n" | sort -rn | uniq -w"${size_digits}" -D | sed -E '
|
||||
s/^ {,12}([0-9]{,12}) (.*)$/printf "%s %s\\n" "$(md5sum "\2")" "d\1"/
|
||||
' | tr '\n' '\0' | xargs -0 -n1 sh -c | sort | { uniq -w32 --all-repeated=separate; echo; } | sed -nE '
|
||||
find . -size +0 -type f -printf "%${size_digits}s %p\n" | sort -rn | uniq -w"${size_digits}" -D | sed -e '
|
||||
s/^ \{0,12\}\([0-9]\{0,12\}\) \(.*\)$/printf "%s %s\\n" "$(md5sum "\2")" "d\1"/
|
||||
' | tr '\n' '\0' | xargs -0 -n1 sh -c | sort | { uniq -w32 --all-repeated=separate; echo; } | sed -ne '
|
||||
h
|
||||
s/^(.{32}).* d([0-9]*)$/## md5sum: \1 size: \2 bytes/p
|
||||
s/^\(.\{32\}\).* d\([0-9]*\)$/## md5sum: \1 size: \2 bytes/p
|
||||
g
|
||||
|
||||
:loop
|
||||
N
|
||||
/.*\n$/!b loop
|
||||
p' | sed -E 's/^.{32} (.*) d[0-9]*$/\1/' >> "$tmpfile"
|
||||
p' | sed -e 's/^.\{32\} \(.*\) d[0-9]*$/\1/' >> "$tmpfile"
|
||||
|
||||
"$EDITOR" "$tmpfile"
|
||||
|
||||
|
@ -46,7 +46,7 @@ printf "Remove commented files? (yes/no) [default=n]: "
|
|||
read -r commented
|
||||
|
||||
if [ "$commented" = "y" ]; then
|
||||
sedcmd="/^(##|[^#]).*/d; /^$/d; s/^# *(.*)$/\1/"
|
||||
sedcmd="/^##.*/d; /^[^#].*/d; /^$/d; s/^# *\(.*\)$/\1/"
|
||||
else
|
||||
printf "Press any key to exit"
|
||||
read -r _
|
||||
|
@ -58,13 +58,13 @@ read -r force
|
|||
|
||||
if [ "$force" = "f" ]; then
|
||||
#shellcheck disable=SC2016
|
||||
sed -E "$sedcmd" "$tmpfile" | tr '\n' '\0' | xargs -0 -r sh -c 'rm -f "$0" "$@" </dev/tty'
|
||||
sed -e "$sedcmd" "$tmpfile" | tr '\n' '\0' | xargs -0 -r sh -c 'rm -f -- "$0" "$@" </dev/tty'
|
||||
else
|
||||
#shellcheck disable=SC2016
|
||||
sed -E "$sedcmd" "$tmpfile" | tr '\n' '\0' | xargs -0 -r sh -c 'rm -i "$0" "$@" </dev/tty'
|
||||
sed -e "$sedcmd" "$tmpfile" | tr '\n' '\0' | xargs -0 -r sh -c 'rm -i -- "$0" "$@" </dev/tty'
|
||||
fi
|
||||
|
||||
rm "$tmpfile"
|
||||
rm -- "$tmpfile"
|
||||
|
||||
printf "Press any key to exit"
|
||||
read -r _
|
||||
|
|
|
@ -1,28 +1,89 @@
|
|||
#!/usr/bin/env sh
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Description: Run custom search and list results in smart context
|
||||
#
|
||||
# Note: To enable multi select in fzf, export the following:
|
||||
# - export FZF_DEFAULT_OPTS='--bind ctrl-a:select-all,ctrl-d:deselect-all,ctrl-t:toggle'
|
||||
# Note: This plugin retains search history
|
||||
#
|
||||
# Shell: POSIX compliant
|
||||
# Author: Arun Prakash Jana
|
||||
# Usage:
|
||||
# Run plugin and enter e.g. "-size +10M" to list files in current
|
||||
# directory larger than 10M. By default entered expressions are
|
||||
# interpreted as arguments to find. Results have to be NUL
|
||||
# terminated which is done by default for find. Alternatively one
|
||||
# can prepend a '$' to run a custom search program such as fd or
|
||||
# ripgrep. Entered expressions will be saved in history file to
|
||||
# be listed as bookmarks and and can be entered by index and edited.
|
||||
#
|
||||
# Shell: Bash
|
||||
# Author: Arun Prakash Jana, Luuk van Baal
|
||||
TMPDIR="${TMPDIR:-/tmp}"
|
||||
NNN_FINDHIST="${NNN_FINDHIST:-${XDG_CONFIG_HOME:-$HOME/.config}/nnn/finderbms}"
|
||||
NNN_FINDHISTLEN="${NNN_FINDHISTLEN:-10000}"
|
||||
|
||||
. "$(dirname "$0")"/.nnn-plugin-helper
|
||||
printexamples() {
|
||||
printf -- "-maxdepth 1 -name pattern
|
||||
-maxdepth 1 -size +100M
|
||||
\$fd -0 pattern
|
||||
\$fd -0 -d 2 -S +100M
|
||||
\$grep -rlZ pattern
|
||||
\$rg -l0 pattern
|
||||
\$fzf -m | tr '\\\n' '\\\0'\n"
|
||||
}
|
||||
|
||||
printf "Examples:\n"
|
||||
printf " find . -name \"pattern*\" -print0\n"
|
||||
printf " fd pattern -0\n"
|
||||
printf " find -maxdepth 1 -size +100M -print0\n"
|
||||
printf " fd -d 2 -S +100M -0\n"
|
||||
printf " grep -rlZ pattern\n"
|
||||
printf " rg -l0 pattern\n"
|
||||
printf " fzf -m | tr %s %s\n\n" "'\n'" "'\0'"
|
||||
printexprs() {
|
||||
for ((i = "$1"; i < ${#fexprs[@]}; i++)); do
|
||||
printf '%s\t%s\n' "$((i + 1))" "${fexprs[$i]}"
|
||||
done
|
||||
}
|
||||
|
||||
printf "cmd: "
|
||||
read -r cmd
|
||||
mapexpr() {
|
||||
if [ "$fexpr" -eq "$fexpr" ] 2>/dev/null; then
|
||||
fexpr=${fexprs[$((fexpr - 1))]}
|
||||
read -r -e -p "Search expression: " -i "$fexpr" fexpr
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
if [ -n "$cmd" ]; then
|
||||
printf "%s" "+l" > "$NNN_PIPE"
|
||||
eval "$cmd" > "$NNN_PIPE"
|
||||
readexpr() {
|
||||
case "$fexpr" in
|
||||
h) clear
|
||||
printf "Examples:\n"
|
||||
mapfile -t fexprs < <(printexamples)
|
||||
printexprs 0
|
||||
read -r -p "Search expression or index: " fexpr
|
||||
mapexpr
|
||||
[ -n "$fexpr" ] && readexpr ;;
|
||||
\$*) cmd="${fexpr:1}" ;;
|
||||
*) mapexpr && readexpr
|
||||
cmd="find . $fexpr -print0" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
clear
|
||||
[ -f "$NNN_FINDHIST" ] || printexamples > "$NNN_FINDHIST"
|
||||
|
||||
mapfile -t fexprs < <(sort "$NNN_FINDHIST" | uniq -c | sort -nr | head -n5 |\
|
||||
awk '{for (i=2; i<NF; i++) printf $i " "; print $NF}')
|
||||
printf "Most used search expressions:\n"
|
||||
printexprs 0
|
||||
|
||||
mapfile -t -O"$i" fexprs < <(tac "$NNN_FINDHIST" | awk '!a[$0]++' | head -n5)
|
||||
printf "Most recently used search expressions:\n"
|
||||
printexprs "$i"
|
||||
read -r -p "Search expression or index (h for help): " fexpr
|
||||
|
||||
mapexpr
|
||||
|
||||
if [ -n "$fexpr" ]; then
|
||||
printf "+l" > "$NNN_PIPE"
|
||||
while :; do
|
||||
readexpr
|
||||
eval "$cmd" > "$NNN_PIPE" && break
|
||||
read -r -e -p "Search expression: " -i "$fexpr" fexpr
|
||||
done
|
||||
if [ -n "$fexpr" ]; then
|
||||
tail -n"$NNN_FINDHISTLEN" "$NNN_FINDHIST" > "$TMPDIR/finderbms"
|
||||
printf "%s\n" "$fexpr" >> "$TMPDIR/finderbms"
|
||||
mv -- "$TMPDIR/finderbms" "$NNN_FINDHIST"
|
||||
fi
|
||||
fi
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Description: Clean filename or dirname (either hovered or selections)
|
||||
# to be more shell-friendly. This script cleans
|
||||
# non A-Za-z0-9._- characters.
|
||||
# and replaces it with underscore (_).
|
||||
#
|
||||
# It supports cleaning single/double quote, newline,
|
||||
# leading, trailing spaces.
|
||||
#
|
||||
# eg.
|
||||
# to be continued (つづく).mp4 -> to_be_continued______.mp4
|
||||
# [work] stuff.txt -> _work__stuff.txt
|
||||
# home's server -> home_s_server
|
||||
# qwe\trty -> __qwe_rty
|
||||
#
|
||||
# And if there are two almost similar filenames
|
||||
# like: 'asd]f' and 'asd f' both will be renamed to 'asd_f',
|
||||
# to avoid overwriting, the last file will be prepended by _.
|
||||
# So they will be: 'asd_f' and '_asd_f'
|
||||
#
|
||||
# Dependencies: sed
|
||||
#
|
||||
# Shell: Bash
|
||||
# Author: Benawi Adha
|
||||
|
||||
prompt=true
|
||||
sel=${NNN_SEL:-${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.selection}
|
||||
|
||||
cleanup() {
|
||||
# printf "%s" "$1" | sed -e 's/[^A-Za-z0-9._-]/_/g'
|
||||
printf "%s" "$1" | sed 's/[^A-Za-z0-9._-]/_/g' | sed ':a;N;$!ba;s/\n/_/g'
|
||||
}
|
||||
|
||||
if [ -s "$sel" ]; then
|
||||
targets=()
|
||||
while IFS= read -r -d '' i || [ -n "$i" ]; do
|
||||
targets+=( "$(basename "$i")" )
|
||||
done < "$sel"
|
||||
else
|
||||
targets=("$1")
|
||||
fi
|
||||
|
||||
for i in "${targets[@]}"; do
|
||||
printf "%s -> %s\n" "$i" "$(cleanup "$i")";
|
||||
done
|
||||
|
||||
if $prompt; then
|
||||
echo
|
||||
printf "Proceed [Yn]? "
|
||||
read -r input
|
||||
case "$input" in
|
||||
y|Y|'')
|
||||
;;
|
||||
*)
|
||||
echo "Canceled"
|
||||
exit
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
for i in "${targets[@]}"; do
|
||||
if [ "$i" != "$(cleanup "$i")" ]; then
|
||||
tmp=''
|
||||
if [ -e "$(cleanup "$i")" ]; then
|
||||
tmp='_'
|
||||
fi
|
||||
mv -- "$i" "$tmp$(cleanup "$i")";
|
||||
fi
|
||||
done
|
||||
|
||||
# Clear selection
|
||||
if [ -s "$sel" ] && [ -p "$NNN_PIPE" ]; then
|
||||
printf "-" > "$NNN_PIPE"
|
||||
fi
|
76
plugins/fzcd
76
plugins/fzcd
|
@ -1,16 +1,71 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
# Description: Run fzf and go to the directory of the file selected
|
||||
# Description: Fuzzy search multiple locations read-in from a path-list file
|
||||
# (or $PWD) and open the selected file's dir in a smart context.
|
||||
# Dependencies: fzf, find (only for multi-location search)
|
||||
#
|
||||
# Details: Paths in list file should be newline-separated absolute paths.
|
||||
# Paths can be file paths; the script will scan the parent dirs.
|
||||
#
|
||||
# The path-list file precedence is:
|
||||
# - "$1" (the hovered file) if it exists, is plain-text and the
|
||||
# first line points to an existing file
|
||||
# - "$LIST" if set below
|
||||
# - "$2" (the current directory) [mimics plugin fzcd behaviour]
|
||||
#
|
||||
# The path-list file can be generated easily:
|
||||
# - pick the (file)paths in picker mode to path-list file
|
||||
# - OR, edit selection in nnn and save as path-list file
|
||||
#
|
||||
# Shell: POSIX compliant
|
||||
# Author: Anna Arad
|
||||
# Author: Anna Arad, Arun Prakash Jana, KlzXS
|
||||
|
||||
IFS="$(printf '\n\r')"
|
||||
|
||||
# shellcheck disable=SC1090,SC1091
|
||||
. "$(dirname "$0")"/.nnn-plugin-helper
|
||||
|
||||
if [ "$(cmd_exists fzf)" -eq "0" ]; then
|
||||
sel=$(fzf)
|
||||
else
|
||||
exit 1
|
||||
CTX=+
|
||||
LIST="${LIST:-""}"
|
||||
|
||||
if ! type fzf >/dev/null 2>&1; then
|
||||
printf "fzf missing"
|
||||
read -r _
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -n "$1" ] && [ "$(file -b --mime-type "$1")" = 'text/plain' ] && [ -e "$(head -1 "$1")" ]; then
|
||||
LIST="$1"
|
||||
elif ! [ -s "$LIST" ]; then
|
||||
sel=$(fzf)
|
||||
# Show only the file and parent dir
|
||||
# sel=$(fzf --delimiter / --with-nth=-2,-1 --tiebreak=begin --info=hidden)
|
||||
|
||||
LIST=''
|
||||
fi
|
||||
|
||||
if [ -n "$LIST" ]; then
|
||||
if type find >/dev/null 2>&1; then
|
||||
tmpfile=$(mktemp /tmp/abc-script.XXXXXX)
|
||||
|
||||
while IFS= read -r path; do
|
||||
if [ -d "$path" ]; then
|
||||
printf "%s\n" "$path" >> "$tmpfile"
|
||||
elif [ -f "$path" ]; then
|
||||
printf "%s\n" "$(dirname "$path")" >> "$tmpfile"
|
||||
fi
|
||||
done < "$LIST"
|
||||
|
||||
sel=$(xargs -d '\n' < "$tmpfile" -I{} find {} -type f -printf "%H//%P\n" | sed '/.*\/\/\(\..*\|.*\/\..*\)/d; s:/\+:/:g' | fzf --delimiter / --tiebreak=begin --info=hidden)
|
||||
# Alternative for 'fd'
|
||||
# sel=$(xargs -d '\n' < "$tmpfile" fd . | fzf --delimiter / --tiebreak=begin --info=hidden)
|
||||
|
||||
rm -- "$tmpfile"
|
||||
else
|
||||
printf "find missing"
|
||||
read -r _
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "$sel" ]; then
|
||||
|
@ -18,18 +73,17 @@ if [ -n "$sel" ]; then
|
|||
exit 0
|
||||
fi
|
||||
|
||||
# Check if selected path returned
|
||||
# by fzf command is absolute
|
||||
# Check if the selected path returned by fzf command is absolute
|
||||
case $sel in
|
||||
/*) nnn_cd "$sel" ;;
|
||||
/*) nnn_cd "$sel" "$CTX" ;;
|
||||
*)
|
||||
# Remove "./" prefix if it exists
|
||||
sel="${sel#./}"
|
||||
|
||||
if [ "$PWD" = "/" ]; then
|
||||
nnn_cd "/$sel"
|
||||
nnn_cd "/$sel" "$CTX"
|
||||
else
|
||||
nnn_cd "$PWD/$sel"
|
||||
nnn_cd "$PWD/$sel" "$CTX"
|
||||
fi;;
|
||||
esac
|
||||
fi
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
# Description: Fuzzy find a command from history, edit in $EDITOR and run as a command
|
||||
# Currently supports only bash and fish history
|
||||
# Description: Fuzzy find a command from history,
|
||||
# edit in $EDITOR and run as a command
|
||||
#
|
||||
# Note: Supports only bash, zsh and fish history
|
||||
#
|
||||
# TODO: For zsh there's also $ZDOTDIR which might need to be checked as well for the -z $HISTFILE && -n $ZDOTDIR case.
|
||||
#
|
||||
# Shell: POSIX compliant
|
||||
# Author: Arun Prakash Jana
|
||||
|
||||
if which fzf >/dev/null 2>&1; then
|
||||
if type fzf >/dev/null 2>&1; then
|
||||
fuzzy=fzf
|
||||
else
|
||||
exit 1
|
||||
|
@ -15,10 +19,21 @@ fi
|
|||
shellname="$(basename "$SHELL")"
|
||||
|
||||
if [ "$shellname" = "bash" ]; then
|
||||
hist_file="$HOME/.bash_history"
|
||||
if [ -f "$HISTFILE" ]; then
|
||||
hist_file="$HISTFILE"
|
||||
else
|
||||
hist_file="$HOME/.bash_history"
|
||||
fi
|
||||
entry="$("$fuzzy" < "$hist_file")"
|
||||
elif [ "$shellname" = "zsh" ]; then
|
||||
if [ -f "$HISTFILE" ]; then
|
||||
hist_file="$HISTFILE"
|
||||
else
|
||||
hist_file="$HOME/.zsh_history"
|
||||
fi
|
||||
entry="$("$fuzzy" < "$hist_file")"
|
||||
elif [ "$shellname" = "fish" ]; then
|
||||
hist_file="$HOME/.config/fish/fish_history"
|
||||
hist_file="$HOME/.local/share/fish/fish_history"
|
||||
entry="$(grep "\- cmd: " "$hist_file" | cut -c 8- | "$fuzzy")"
|
||||
fi
|
||||
|
||||
|
@ -31,7 +46,7 @@ if [ -n "$entry" ]; then
|
|||
$SHELL -c "$(cat "$tmpfile")"
|
||||
fi
|
||||
|
||||
rm "$tmpfile"
|
||||
rm -- "$tmpfile"
|
||||
|
||||
printf "Press any key to exit"
|
||||
read -r _
|
||||
|
|
|
@ -1,38 +1,85 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
# Description: Fuzzy find a file in directory subtree
|
||||
# Opens in $VISUAL or $EDITOR if text
|
||||
# Opens other type of files with xdg-open
|
||||
# Description: Regular mode:
|
||||
# Fuzzy find a file in directory subtree.
|
||||
# Opens in $VISUAL or $EDITOR if text.
|
||||
# Opens other type of files with xdg-open.
|
||||
# Work only with a single file selected.
|
||||
#
|
||||
# Dependencies: fd/find, fzf/skim, xdg-open
|
||||
# Picker mode:
|
||||
# If picker mode output file is passed, it
|
||||
# will be overwritten with any picked files.
|
||||
# Leaves untouched if no file is picked.
|
||||
# Works with single/multiple files selected.
|
||||
#
|
||||
# Dependencies: fd/find, fzf/skim, xdg-open/open (on macOS)
|
||||
#
|
||||
# Shell: POSIX compliant
|
||||
# Author: Arun Prakash Jana
|
||||
|
||||
if which fzf >/dev/null 2>&1; then
|
||||
NUKE="${XDG_CONFIG_HOME:-$HOME/.config}/nnn/plugins/nuke"
|
||||
USE_NUKE=0
|
||||
|
||||
# shellcheck disable=SC1090,SC1091
|
||||
. "$(dirname "$0")"/.nnn-plugin-helper
|
||||
|
||||
if type fzf >/dev/null 2>&1; then
|
||||
cmd="$FZF_DEFAULT_COMMAND"
|
||||
if which fd >/dev/null 2>&1; then
|
||||
if type fd >/dev/null 2>&1; then
|
||||
[ -z "$cmd" ] && cmd="fd -t f 2>/dev/null"
|
||||
else
|
||||
[ -z "$cmd" ] && cmd="find . -type f 2>/dev/null"
|
||||
fi
|
||||
entry="$(eval "$cmd" | fzf --delimiter / --nth=-1 --tiebreak=begin --info=hidden)"
|
||||
entry="$(eval "$cmd" | fzf -m)"
|
||||
# To show only the file name
|
||||
# entry=$(find . -type f 2>/dev/null | fzf --delimiter / --with-nth=-1 --tiebreak=begin --info=hidden)
|
||||
elif which sk >/dev/null 2>&1; then
|
||||
elif type sk >/dev/null 2>&1; then
|
||||
entry=$(find . -type f 2>/dev/null | sk)
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
case "$(file -biL "$entry")" in
|
||||
*text*)
|
||||
"${VISUAL:-$EDITOR}" "$entry" ;;
|
||||
*)
|
||||
if uname | grep -q "Darwin"; then
|
||||
open "$entry" >/dev/null 2>&1
|
||||
# Check for picker mode
|
||||
if [ "$3" ]; then
|
||||
if [ "$entry" ]; then
|
||||
case "$entry" in
|
||||
/*) fullpath="$entry" ;;
|
||||
*) fullpath="$PWD/$entry" ;;
|
||||
esac
|
||||
if [ "-" = "$3" ]; then
|
||||
printf "%s\n" "$fullpath"
|
||||
else
|
||||
xdg-open "$entry" >/dev/null 2>&1
|
||||
printf "%s\n" "$fullpath" > "$3"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# Tell `nnn` to clear its internal selection
|
||||
printf "%s" "0p" > "$NNN_PIPE"
|
||||
fi
|
||||
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$entry" ]; then
|
||||
if [ "$USE_NUKE" -ne 0 ]; then
|
||||
"$NUKE" "$entry"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Open the file (works for a single file only)
|
||||
cmd_file=""
|
||||
cmd_open=""
|
||||
if uname | grep -q "Darwin"; then
|
||||
cmd_file="file -bIL"
|
||||
cmd_open="open"
|
||||
else
|
||||
cmd_file="file -biL"
|
||||
cmd_open="xdg-open"
|
||||
fi
|
||||
|
||||
case "$($cmd_file "$entry")" in
|
||||
*text*)
|
||||
"${VISUAL:-$EDITOR}" "$entry" ;;
|
||||
*)
|
||||
$cmd_open "$entry" >/dev/null 2>&1 ;;
|
||||
esac
|
||||
fi
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
# Description: Fuzzy find and execute nnn plugins (and optionally,
|
||||
# custom scripts located elsewhere).
|
||||
# Description and details of plugins can be previewed
|
||||
# from the fzf interface. Use `?` to toggle preview
|
||||
# pane on and off, ^Up/^Dn to scroll.
|
||||
#
|
||||
# Dependencies: find, fzf, cat (or bat, if installed)
|
||||
#
|
||||
# Note: For better compatibility with as many nnn plugins as possible,
|
||||
# fzplug will first execute the chosen script on the file hovered
|
||||
# in nnn, and upon failure, try to run it with no target (i.e on
|
||||
# an active selection, if present).
|
||||
#
|
||||
# Shell: POSIX compliant
|
||||
# Author: Kabouik
|
||||
|
||||
# Optional scripts sources
|
||||
|
||||
# Leave blank or fill with the absolute path of a folder containing executable
|
||||
# scripts other than nnn plugins (e.g., "$HOME/.local/share/nautilus/scripts",
|
||||
# since there are numerous Nautilus script git repositories).
|
||||
# Add extra variables if needed, make sure you call them in the find command.
|
||||
|
||||
#CUSTOMDIR1="$HOME/.local/share/nautilus/scripts"
|
||||
CUSTOMDIR1=""
|
||||
CUSTOMDIR2=""
|
||||
|
||||
nnnpluginsdir="$HOME/.config/nnn/plugins"
|
||||
|
||||
# Preview with bat if installed
|
||||
if type bat >/dev/null; then
|
||||
BAT="bat --terminal-width='$(tput cols)' --decorations=always --color=always --style='${BAT_STYLE:-header,numbers}'"
|
||||
fi
|
||||
|
||||
plugin=$(find "$nnnpluginsdir" "$CUSTOMDIR1" "$CUSTOMDIR2" \
|
||||
-maxdepth 3 -perm -111 -type f 2>/dev/null | fzf --ansi --preview \
|
||||
"${BAT:-cat} {}" --preview-window="right:66%:wrap" --delimiter / \
|
||||
--with-nth -1 --bind="?:toggle-preview")
|
||||
|
||||
# Try running the script on the hovered file, and abort
|
||||
# abort if no plugin was selected (ESC or ^C pressed).
|
||||
err=0
|
||||
if ! [ "$plugin" = "" ]; then
|
||||
"$plugin" "$1" || err=1
|
||||
fi
|
||||
|
||||
# If attempt with hovered file fails, try without any target
|
||||
# (nnn selections should still be passed to the script in that case)
|
||||
if [ "$err" -eq "1" ]; then
|
||||
clear && "$plugin" || err=2
|
||||
fi
|
||||
|
||||
# Abort and show error if both fail
|
||||
if [ "$err" -eq "2" ]; then
|
||||
sep="\n---\n"
|
||||
printf "$sep""Failed to execute '%s'. See error above or try without fzfplug. Press return to continue. " "$plugin" && read -r _ && clear
|
||||
fi
|
26
plugins/fzz
26
plugins/fzz
|
@ -1,26 +0,0 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
# Description: cd to any dir in the z database using an fzf pane
|
||||
#
|
||||
# Shell: POSIX compliant
|
||||
# Author: Nick Waywood
|
||||
|
||||
. "$(dirname "$0")"/.nnn-plugin-helper
|
||||
|
||||
if which fzf >/dev/null 2>&1; then
|
||||
fuzzy=fzf
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
datafile="${_Z_DATA:-$HOME/.z}"
|
||||
if [ -f "$datafile" ]; then
|
||||
# I read the data from z's file instead of calling the z command so that the data doesn't need to be processed twice
|
||||
sel=$(awk -F "|" '{print $1}' "$datafile" | "$fuzzy" | awk '{$1=$1};1')
|
||||
# NOTE: Uncomment this line and comment out the line above if you want to see the weightings of the dir's in the fzf pane
|
||||
# sel=$(awk -F "|" '{printf "%s %s\n", $2, $1}' "$datafile" | "$fuzzy" | sed 's/^[0-9,.]* *//' | awk '{$1=$1};1')
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
printf "%s" "0c$sel" > "$NNN_PIPE"
|
|
@ -8,13 +8,8 @@
|
|||
CONFIG_DIR=${XDG_CONFIG_HOME:-$HOME/.config}/nnn/
|
||||
PLUGIN_DIR=${XDG_CONFIG_HOME:-$HOME/.config}/nnn/plugins
|
||||
|
||||
# is_cmd_exists () {
|
||||
# which "$1" > /dev/null 2>&1
|
||||
# echo $?
|
||||
# }
|
||||
|
||||
merge () {
|
||||
if which nvim >/dev/null 2>&1; then
|
||||
if type nvim >/dev/null 2>&1; then
|
||||
nvim -d "$1" "$2"
|
||||
else
|
||||
vimdiff +0 "$1" "$2"
|
||||
|
@ -29,24 +24,16 @@ prompt () {
|
|||
if [ "$operation" = "m" ]; then
|
||||
op="merge"
|
||||
elif [ "$operation" = "o" ]; then
|
||||
op="cp -vRf"
|
||||
op="cp -vRf --"
|
||||
else
|
||||
op="true"
|
||||
fi
|
||||
}
|
||||
|
||||
# if [ "$(is_cmd_exists sudo)" -eq "0" ]; then
|
||||
# sucmd=sudo
|
||||
# elif [ "$(is_cmd_exists doas)" -eq "0" ]; then
|
||||
# sucmd=doas
|
||||
# else
|
||||
# sucmd=: # noop
|
||||
# fi
|
||||
|
||||
if [ "$1" = "master" ] ; then
|
||||
VER="master"
|
||||
ARCHIVE_URL=https://github.com/jarun/nnn/archive/master.tar.gz
|
||||
elif which nnn >/dev/null 2>&1; then
|
||||
elif type nnn >/dev/null 2>&1; then
|
||||
VER=$(nnn -V)
|
||||
ARCHIVE_URL=https://github.com/jarun/nnn/releases/download/v"$VER"/nnn-v"$VER".tar.gz
|
||||
else
|
||||
|
@ -75,7 +62,7 @@ for f in $(find . -maxdepth 1 \( ! -iname "." ! -iname "*.md" \)); do
|
|||
$op "$f" ../../plugins/
|
||||
fi
|
||||
else
|
||||
cp -vRf "$f" ../../plugins/
|
||||
cp -vRf -- "$f" ../../plugins/
|
||||
fi
|
||||
done
|
||||
cd ../.. || exit 1
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
# Description: cd to the top level of the current git repository in the current context
|
||||
# Dependencies: git
|
||||
# Shell: sh
|
||||
# Author: https://github.com/PatrickF1
|
||||
|
||||
root="$(git rev-parse --show-toplevel 2>/dev/null)"
|
||||
if [ -n "$root" ]; then
|
||||
printf "%s" "0c$root" > "$NNN_PIPE"
|
||||
else
|
||||
printf "Not in a git repository"
|
||||
read -r _
|
||||
exit 1
|
||||
fi
|
11
plugins/gpgd
11
plugins/gpgd
|
@ -1,8 +1,10 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
# Description: Decrypts selected files using gpg. The contents of the decrypted file are stored in a file with extension .dec
|
||||
# Description: Decrypts selected files using gpg. The contents of the
|
||||
# decrypted file are stored in a file with extension .dec
|
||||
#
|
||||
# Note: If an appropriate private key cannot be found gpg silently prints a message in the background and no files are written.
|
||||
# Note: If an appropriate private key cannot be found gpg silently
|
||||
# prints a message in the background and no files are written.
|
||||
#
|
||||
# Shell: POSIX compliant
|
||||
# Author: KlzXS
|
||||
|
@ -19,3 +21,8 @@ else
|
|||
fi
|
||||
|
||||
printf "%s" "$files" | xargs -n1 -I{} gpg --decrypt --output "{}.dec" {}
|
||||
|
||||
# Clear selection
|
||||
if [ "$resp" = "s" ] && [ -p "$NNN_PIPE" ]; then
|
||||
printf "-" > "$NNN_PIPE"
|
||||
fi
|
||||
|
|
24
plugins/gpge
24
plugins/gpge
|
@ -1,14 +1,17 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
# Description: Encrypts selected files using gpg. Can encrypt either asymmetrically (key) or symmetrically (passphrase).
|
||||
# If asymmetric encryption is chosen a key can be chosen from the list of capable public keys using fzf.
|
||||
# Description: Encrypts selected files using gpg. Can encrypt
|
||||
# asymmetrically (key) or symmetrically (passphrase).
|
||||
# If asymmetric encryption is chosen a key can be
|
||||
# chosen from the list of capable public keys using fzf.
|
||||
#
|
||||
# Note: symmetric encryption only works for a single (current) file as per gpg limitations
|
||||
# Note: Symmetric encryption only works for a single (current) file as per gpg limitations
|
||||
#
|
||||
# Shell: POSIX compliant
|
||||
# Author: KlzXS
|
||||
|
||||
selection=${NNN_SEL:-${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.selection}
|
||||
# shellcheck disable=SC1090,SC1091
|
||||
. "$(dirname "$0")"/.nnn-plugin-helper
|
||||
|
||||
printf "(s)ymmetric, (a)symmetric? [default=a] "
|
||||
read -r symmetry
|
||||
|
@ -16,12 +19,12 @@ read -r symmetry
|
|||
if [ "$symmetry" = "s" ]; then
|
||||
gpg --symmetric "$1"
|
||||
else
|
||||
printf "(s)election/(c)urrent? [default=c] "
|
||||
read -r resp
|
||||
|
||||
if [ "$resp" = "s" ]; then
|
||||
if nnn_use_selection; then
|
||||
clear_sel=1
|
||||
# shellcheck disable=SC2154
|
||||
files=$(tr '\0' '\n' < "$selection")
|
||||
else
|
||||
clear_sel=0
|
||||
files=$1
|
||||
fi
|
||||
|
||||
|
@ -34,4 +37,9 @@ else
|
|||
recipient=$(printf "%s" "$keyuids" | fzf | awk '{print $1}')
|
||||
|
||||
printf "%s" "$files" | xargs -n1 gpg --encrypt --recipient "$recipient"
|
||||
|
||||
# Clear selection
|
||||
if [ "$clear_sel" -eq 1 ] && [ -p "$NNN_PIPE" ]; then
|
||||
printf "-" > "$NNN_PIPE"
|
||||
fi
|
||||
fi
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
#set -x
|
||||
# Description: Send the selected (or hovered) files to your Android device using gsconnect daemon.js.
|
||||
# GSConnect must be configured on the Android device and the PC.
|
||||
#
|
||||
# Shell: POSIX compliant
|
||||
# Author: Darukutsu
|
||||
selection=${NNN_SEL:-${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.selection}
|
||||
gsconnect=$HOME/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/service/daemon.js
|
||||
ids=$($gsconnect -l)
|
||||
|
||||
for id in $ids; do
|
||||
if [ -s "$selection" ]; then
|
||||
xargs -0 < "$selection" -I{} "$gsconnect" -d "$id" --share-file="{}"
|
||||
# Clear selection
|
||||
printf "-" > "$NNN_PIPE"
|
||||
else
|
||||
"$gsconnect" -d "$id" --share-file="$2/$1"
|
||||
fi
|
||||
done
|
|
@ -18,11 +18,11 @@
|
|||
# Shell: POSIX compliant
|
||||
# Author: Arun Prakash Jana
|
||||
|
||||
EBOOK_ID="${EBOOK_ID}"
|
||||
EBOOK_ID="${EBOOK_ID:-""}"
|
||||
DIR="${XDG_CACHE_HOME:-$HOME/.cache}/nnn/gutenbooks/$EBOOK_ID"
|
||||
BROWSE_LINK="https://www.gutenberg.org/ebooks/search/?sort_order=downloads"
|
||||
BROWSER="${BROWSER:-w3m}"
|
||||
READER="${READER}"
|
||||
READER="${READER:-""}"
|
||||
|
||||
if [ -n "$EBOOK_ID" ]; then
|
||||
if [ ! -e "$DIR" ]; then
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
# Description: View a file in hex
|
||||
# Dependencies: hx (https://github.com/krpors/hx)/xxd and $PAGER
|
||||
#
|
||||
# Shell: POSIX compliant
|
||||
# Author: Arun Prakash Jana
|
||||
|
||||
if [ -n "$1" ]; then
|
||||
if which hx >/dev/null 2>&1; then
|
||||
hx "$1"
|
||||
else
|
||||
xxd "$1" | $PAGER
|
||||
fi
|
||||
fi
|
|
@ -1,15 +1,16 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
# Description: Resize images in a directory to screen resolution with imgp
|
||||
# imgp homepage: https://github.com/jarun/imgp
|
||||
#
|
||||
# Dependencipes: imgp - https://github.com/jarun/imgp
|
||||
#
|
||||
# Notes:
|
||||
# 1. Set res if you don't want to be prompted for desktop resolution every time
|
||||
# 2. MINSIZE is set to 1MB by default, adjust it if you want
|
||||
# 3. imgp options used:
|
||||
# a - adaptive mode
|
||||
# c - convert PNG to JPG
|
||||
# k - skip images matching specified hres/vres
|
||||
# 1. Set res to avoid the desktop resolution prompt each time
|
||||
# 2. MINSIZE is set to 1MB by default, adjust it if you want
|
||||
# 3. imgp options used:
|
||||
# a - adaptive mode
|
||||
# c - convert PNG to JPG
|
||||
# k - skip images matching specified hres/vres
|
||||
#
|
||||
# Shell: POSIX compliant
|
||||
# Author: Arun Prakash Jana
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
# Description: View thumbnail of an image or a directory of images with lsix
|
||||
#
|
||||
# Shell: POSIX compliant
|
||||
# Author: Arun Prakash Jana
|
||||
|
||||
if [ -n "$1" ]; then
|
||||
if [ -d "$1" ]; then
|
||||
lsix "$1"/*
|
||||
else
|
||||
lsix "$1"
|
||||
fi
|
||||
|
||||
printf "Press any key to exit..."
|
||||
read -r _
|
||||
fi
|
|
@ -28,11 +28,11 @@
|
|||
##########################################################################
|
||||
|
||||
# https://github.com/jomo/imgur-screenshot
|
||||
# https://imgur.com/tools
|
||||
# https://help.imgur.com/hc/en-us/articles/209592766-Tools-for-Imgur
|
||||
#
|
||||
# Slightly modified for `nnn` integration
|
||||
#
|
||||
# Shell: bash
|
||||
# Shell: Bash
|
||||
# Description: Upload an image file to imgur
|
||||
|
||||
if [ "${1}" = "--debug" ]; then
|
||||
|
@ -112,28 +112,29 @@ check_update="true"
|
|||
|
||||
settings_path="${HOME}/.config/imgur-screenshot/settings.conf"
|
||||
if [ -f "${settings_path}" ]; then
|
||||
# shellcheck disable=SC1090
|
||||
source "${settings_path}"
|
||||
fi
|
||||
|
||||
# dependency check
|
||||
if [ "${1}" = "--check" ]; then
|
||||
(which grep &>/dev/null && echo "OK: found grep") || echo "ERROR: grep not found"
|
||||
(type grep &>/dev/null && echo "OK: found grep") || echo "ERROR: grep not found"
|
||||
if is_mac; then
|
||||
if which growlnotify &>/dev/null; then
|
||||
if type growlnotify &>/dev/null; then
|
||||
echo "OK: found growlnotify"
|
||||
elif which terminal-notifier &>/dev/null; then
|
||||
elif type terminal-notifier &>/dev/null; then
|
||||
echo "OK: found terminal-notifier"
|
||||
else
|
||||
echo "ERROR: growlnotify nor terminal-notifier found"
|
||||
fi
|
||||
(which screencapture &>/dev/null && echo "OK: found screencapture") || echo "ERROR: screencapture not found"
|
||||
(which pbcopy &>/dev/null && echo "OK: found pbcopy") || echo "ERROR: pbcopy not found"
|
||||
(type screencapture &>/dev/null && echo "OK: found screencapture") || echo "ERROR: screencapture not found"
|
||||
(type pbcopy &>/dev/null && echo "OK: found pbcopy") || echo "ERROR: pbcopy not found"
|
||||
else
|
||||
(which notify-send &>/dev/null && echo "OK: found notify-send") || echo "ERROR: notify-send (from libnotify-bin) not found"
|
||||
(which scrot &>/dev/null && echo "OK: found scrot") || echo "ERROR: scrot not found"
|
||||
(which xclip &>/dev/null && echo "OK: found xclip") || echo "ERROR: xclip not found"
|
||||
(type notify-send &>/dev/null && echo "OK: found notify-send") || echo "ERROR: notify-send (from libnotify-bin) not found"
|
||||
(type scrot &>/dev/null && echo "OK: found scrot") || echo "ERROR: scrot not found"
|
||||
(type xclip &>/dev/null && echo "OK: found xclip") || echo "ERROR: xclip not found"
|
||||
fi
|
||||
(which curl &>/dev/null && echo "OK: found curl") || echo "ERROR: curl not found"
|
||||
(type curl &>/dev/null && echo "OK: found curl") || echo "ERROR: curl not found"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
@ -141,7 +142,7 @@ fi
|
|||
# notify <'ok'|'error'> <title> <text>
|
||||
function notify() {
|
||||
if is_mac; then
|
||||
if which growlnotify &>/dev/null; then
|
||||
if type growlnotify &>/dev/null; then
|
||||
growlnotify --icon "${imgur_icon_path}" --iconpath "${imgur_icon_path}" --title "${2}" --message "${3}"
|
||||
else
|
||||
terminal-notifier -appIcon "${imgur_icon_path}" -contentImage "${imgur_icon_path}" -title "imgur: ${2}" -message "${3}"
|
||||
|
@ -204,6 +205,7 @@ function load_access_token() {
|
|||
token_expire_time=0
|
||||
# check for saved access_token and its expiration date
|
||||
if [ -f "${credentials_file}" ]; then
|
||||
# shellcheck disable=SC1090
|
||||
source "${credentials_file}"
|
||||
fi
|
||||
current_time="$(date +%s)"
|
||||
|
@ -581,7 +583,7 @@ for upload_file in "${upload_files[@]}"; do
|
|||
# delete file if configured
|
||||
if [ "${keep_file}" = "false" ] && [ -z "${1}" ]; then
|
||||
echo "Deleting temp file ${file_dir}/${img_file}"
|
||||
rm -rf "${img_file}"
|
||||
rm -rf -- "${img_file}"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
|
151
plugins/imgview
151
plugins/imgview
|
@ -1,70 +1,113 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
# Description: Open images in hovered directory and thumbnails
|
||||
# open hovered image in sxiv or viu and browse other images in the directory
|
||||
# Dependencies: imv (https://github.com/eXeC64/imv) or,
|
||||
# sxiv (https://github.com/muennich/sxiv) or,
|
||||
# viu (https://github.com/atanunq/viu), less
|
||||
# Description: Open hovered or current directory in image viewer.
|
||||
# Generates media thumbnails with optional dependencies.
|
||||
#
|
||||
# Dependencies:
|
||||
# - imv (https://github.com/eXeC64/imv) or,
|
||||
# - sxiv (https://github.com/muennich/sxiv) or,
|
||||
# - nsxiv (https://codeberg.org/nsxiv/nsxiv) or,
|
||||
# - ucollage (https://github.com/ckardaris/ucollage) or,
|
||||
# - lsix (https://github.com/hackerb9/lsix), or
|
||||
# - viu (https://github.com/atanunq/viu), or
|
||||
# - catimg (https://github.com/posva/catimg), or
|
||||
# - optional: ffmpeg for audio thumbnails (album art)
|
||||
# - optional: ffmpegthumbnailer for video thumbnails
|
||||
#
|
||||
# Shell: POSIX compliant
|
||||
# Author: Arun Prakash Jana
|
||||
# Author: Arun Prakash Jana, Luuk van Baal
|
||||
#
|
||||
# Consider setting NNN_PREVIEWDIR to $XDG_CACHE_HOME/nnn/previews
|
||||
# if you want to keep media thumbnails on disk between reboots.
|
||||
NNN_PREVIEWDIR="${NNN_PREVIEWDIR:-${TMPDIR:-/tmp}/nnn/previews}"
|
||||
|
||||
abspath() {
|
||||
case "$1" in
|
||||
/*) printf "%s\n" "$1";;
|
||||
*) printf "%s\n" "$PWD/$1";;
|
||||
esac
|
||||
exit_prompt() {
|
||||
[ -n "$1" ] && printf "%s\n" "$1"
|
||||
printf "%s" "Press any key to exit..."
|
||||
cfg=$(stty -g); stty raw -echo; head -c 1; stty "$cfg"
|
||||
clear
|
||||
exit
|
||||
}
|
||||
|
||||
make_thumbs() {
|
||||
mkdir -p "$NNN_PREVIEWDIR$dir" || return
|
||||
if [ "$1" = "viu" ] || [ "$1" = "catimg" ]; then
|
||||
[ -d "$target" ] && exit_prompt "$1 can only display a single image"
|
||||
mime="$(file -bL --mime-type -- "$target")"
|
||||
case "$mime" in
|
||||
audio/*) ffmpeg -i "$target" "$NNN_PREVIEWDIR$target.jpg" -y >/dev/null 2>&1
|
||||
ret="$NNN_PREVIEWDIR/$target.jpg" ;;
|
||||
video/*) ffmpegthumbnailer -i "$target" -o "$NNN_PREVIEWDIR$target.jpg" 2> /dev/null
|
||||
ret="$NNN_PREVIEWDIR/$target.jpg" ;;
|
||||
*) ret="$target" ;;
|
||||
esac
|
||||
fi
|
||||
for file in "$dir"/*; do
|
||||
if [ ! -f "$NNN_PREVIEWDIR$file.jpg" ]; then
|
||||
case "$(file -bL --mime-type -- "$file")" in
|
||||
audio/*) [ "$1" != "sxiv" ] &&
|
||||
ffmpeg -i "$file" "$NNN_PREVIEWDIR$file.jpg" -y >/dev/null 2>&1 ;;
|
||||
video/*) [ "$1" != "ucollage" ] &&
|
||||
ffmpegthumbnailer -i "$file" -o "$NNN_PREVIEWDIR$file.jpg" 2> /dev/null ;;
|
||||
esac
|
||||
fi
|
||||
done
|
||||
for file in "$NNN_PREVIEWDIR$dir"/*; do
|
||||
filename="$(basename "$file" .jpg)"
|
||||
[ ! -e "$dir/$filename" ] && rm -- "$file" 2>/dev/null
|
||||
done
|
||||
}
|
||||
|
||||
listimages() {
|
||||
find -L "$(dirname "$target")" -maxdepth 1 -type f -iregex \
|
||||
'.*\(jpe?g\|bmp\|webp\|png\|gif\)$' -print0 | sort -z
|
||||
find -L "$dir" "$NNN_PREVIEWDIR$dir" -maxdepth 1 -type f -print0 2>/dev/null | sort -z
|
||||
}
|
||||
|
||||
view_dir() {
|
||||
target="$(abspath "$2")"
|
||||
count="$(listimages | grep -a -m 1 -ZznF "$target" | cut -d: -f1)"
|
||||
|
||||
if [ -n "$count" ]; then
|
||||
if [ "$1" = 'sxiv' ]; then
|
||||
listimages | xargs -0 "$1" -an "$count" --
|
||||
else
|
||||
listimages | xargs -0 "$1" -n "$count" --
|
||||
fi
|
||||
else
|
||||
shift
|
||||
"$1" -- "$@" # fallback
|
||||
fi
|
||||
view_files() {
|
||||
[ -f "$target" ] && count="-n $(listimages | grep -a -m 1 -ZznF "$target" | cut -d: -f1)"
|
||||
case "$1" in
|
||||
nsxiv) listimages | xargs -0 nsxiv -a "${count:--t}" -- ;;
|
||||
sxiv) listimages | xargs -0 sxiv -a "${count:--t}" -- ;;
|
||||
imv*) listimages | xargs -0 "$1" "${count:-}" -- ;;
|
||||
esac
|
||||
}
|
||||
|
||||
if [ -z "$1" ] || ! [ -s "$1" ]; then
|
||||
printf "empty file"
|
||||
read -r _
|
||||
exit 1
|
||||
fi
|
||||
|
||||
target="$(readlink -f "$1")"
|
||||
[ -d "$target" ] && dir="$target" || dir="${target%/*}"
|
||||
if uname | grep -q "Darwin"; then
|
||||
if [ -f "$1" ]; then
|
||||
open "$1" >/dev/null 2>&1 &
|
||||
[ -f "$1" ] && open "$1" >/dev/null 2>&1 &
|
||||
elif type lsix >/dev/null 2>&1; then
|
||||
if [ -d "$target" ]; then
|
||||
cd "$target" || exit_prompt
|
||||
fi
|
||||
# `imvr` is often callable as `imv` on Linux distros
|
||||
# You might need to change the reference below
|
||||
elif which imvr >/dev/null 2>&1; then
|
||||
if [ -f "$1" ]; then
|
||||
view_dir imvr "$1" >/dev/null 2>&1 &
|
||||
elif [ -d "$1" ] || [ -h "$1" ]; then
|
||||
imvr "$1" >/dev/null 2>&1 &
|
||||
fi
|
||||
elif which sxiv >/dev/null 2>&1; then
|
||||
if [ -f "$1" ]; then
|
||||
view_dir sxiv "$1" >/dev/null 2>&1 &
|
||||
elif [ -d "$1" ] || [ -h "$1" ]; then
|
||||
sxiv -aqt "$1" >/dev/null 2>&1 &
|
||||
fi
|
||||
elif which viu >/dev/null 2>&1; then
|
||||
viu -n "$1" | less -R
|
||||
make_thumbs lsix
|
||||
clear
|
||||
lsix
|
||||
cd "$NNN_PREVIEWDIR$dir" && lsix
|
||||
exit_prompt
|
||||
elif type ucollage >/dev/null 2>&1; then
|
||||
type ffmpeg >/dev/null 2>&1 && make_thumbs ucollage
|
||||
UCOLLAGE_EXPAND_DIRS=1 ucollage "$dir" "$NNN_PREVIEWDIR$dir" || exit_prompt
|
||||
elif type sxiv >/dev/null 2>&1; then
|
||||
type ffmpegthumbnailer >/dev/null 2>&1 && make_thumbs sxiv
|
||||
view_files sxiv >/dev/null 2>&1 &
|
||||
elif type nsxiv >/dev/null 2>&1; then
|
||||
type ffmpegthumbnailer >/dev/null 2>&1 && make_thumbs sxiv
|
||||
view_files nsxiv >/dev/null 2>&1 &
|
||||
elif type imv >/dev/null 2>&1; then
|
||||
make_thumbs imv
|
||||
view_files imv >/dev/null 2>&1 &
|
||||
elif type imvr >/dev/null 2>&1; then
|
||||
make_thumbs imv
|
||||
view_files imvr >/dev/null 2>&1 &
|
||||
elif type viu >/dev/null 2>&1; then
|
||||
clear
|
||||
make_thumbs viu
|
||||
viu -n "$ret"
|
||||
exit_prompt
|
||||
elif type catimg >/dev/null 2>&1; then
|
||||
make_thumbs catimg
|
||||
catimg "$ret"
|
||||
exit_prompt
|
||||
else
|
||||
printf "Please install imv/sxiv/viu and check their callable names match the plugin source"
|
||||
read -r _
|
||||
exit 2
|
||||
exit_prompt "Please install sxiv/nsxiv/imv/viu/catimg/lsix."
|
||||
fi
|
||||
|
|
|
@ -1,18 +1,66 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
# Description: Send the selected files to your Android device using kdeconnect-cli. You must have installed and configured kdeconnect both on the Android device and on the PC.
|
||||
# Description: Send files or folders to your Android device using kdeconnect-cli.
|
||||
# kdeconnect must be configured on the Android device and the PC.
|
||||
#
|
||||
# Usage:
|
||||
# - Hover over a file or a folder and call the plugin.
|
||||
# - Alternatively, select the files and folders you would like to send, and activate the plugin.
|
||||
#
|
||||
# Shell: POSIX compliant
|
||||
# Author: juacq97
|
||||
# Author: juacq97, raffaem, N-R-K
|
||||
|
||||
# If you want system notification, put this equal to 1
|
||||
notify=0
|
||||
|
||||
note() {
|
||||
if [ $notify = 1 ]; then
|
||||
notify-send -a "Kdeconnect" "$1"
|
||||
else
|
||||
echo "[Kdeconnect] $1"
|
||||
fi
|
||||
}
|
||||
|
||||
# kdeconnect doesn't cope with non-files
|
||||
filter_files() {
|
||||
xargs -0 -I{} sh -c '
|
||||
if [ -f "{}" ]; then
|
||||
printf "%s\0" "{}";
|
||||
else
|
||||
printf "Error: not a regular file: %s\n" "{}" >&2;
|
||||
fi;'
|
||||
}
|
||||
|
||||
send() {
|
||||
filter_files | xargs -0 -I{} kdeconnect-cli --name "$devname" --share {}
|
||||
note "Files sent"
|
||||
}
|
||||
|
||||
# Select paired device
|
||||
names=$(kdeconnect-cli --list-available --name-only 2>/dev/null)
|
||||
if [ -z "$names" ]; then
|
||||
note "No devices paired and available"
|
||||
exit
|
||||
fi
|
||||
|
||||
ndevs=$(printf "%s" "$names" | awk 'END{print NR}')
|
||||
if [ "$ndevs" -eq 1 ]; then
|
||||
devname="$names"
|
||||
else
|
||||
printf "%s" "$names" | awk '{ print NR ". " $0 }'
|
||||
printf "Pick a device: "
|
||||
read -r pick
|
||||
if [ -n "$pick" ] && [ "$pick" -eq "$pick" ]; then
|
||||
devname=$(printf '%s' "$names" | awk "NR==$pick")
|
||||
fi
|
||||
fi
|
||||
|
||||
selection=${NNN_SEL:-${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.selection}
|
||||
|
||||
id=$(kdeconnect-cli -a --id-only | awk '{print $1}')
|
||||
if [ "$(find "$selection")" ]; then
|
||||
kdeconnect-cli -d "$id" --share "$(cat "$selection")"
|
||||
|
||||
# If you want a system notification, uncomment the next 3 lines.
|
||||
#notify-send -a "Kdeconnect" "Sending $(cat "$selection")"
|
||||
#else
|
||||
#notify-send -a "Kdeconnect" "No file selected"
|
||||
if [ -s "$selection" ]; then
|
||||
send < "$selection"
|
||||
[ -p "$NNN_PIPE" ] && printf "-" > "$NNN_PIPE" # clear selection
|
||||
elif [ -n "$1" ]; then
|
||||
printf "%s" "$1" | send
|
||||
else
|
||||
note "No selection and no hovered file"
|
||||
fi
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
IFS=':'
|
||||
|
||||
get_selection() {
|
||||
if which fzf >/dev/null 2>&1; then
|
||||
if type fzf >/dev/null 2>&1; then
|
||||
{ IFS=':'; ls -H $PATH; } | sort | fzf
|
||||
else
|
||||
exit 1
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
# Description: Show media information of a file in pager
|
||||
#
|
||||
# Dependencies: mediainfo
|
||||
#
|
||||
# Shell: POSIX compliant
|
||||
# Author: Arun Prakash Jana
|
||||
|
||||
if [ -n "$1" ] && [ -f "$1" ]; then
|
||||
mediainfo "$1" | $PAGER
|
||||
# exiftool "$1" | $PAGER
|
||||
fi
|
|
@ -2,13 +2,22 @@
|
|||
|
||||
# Description: Find and list files by mime type in smart context
|
||||
#
|
||||
# Dependencies:
|
||||
# - file
|
||||
# - mimetype (optional, PERL File MimeInfo)
|
||||
#
|
||||
# Shell: POSIX compliant
|
||||
# Author: Arun Prakash Jana
|
||||
# Author: Arun Prakash Jana, Michel DHOOGE
|
||||
|
||||
# shellcheck disable=SC1090,SC1091
|
||||
. "$(dirname "$0")"/.nnn-plugin-helper
|
||||
|
||||
printf "mime (e.g., video/audio/image): "
|
||||
read -r mime
|
||||
|
||||
printf "%s" "+l" > "$NNN_PIPE"
|
||||
find . | file -if- | grep "$mime" | awk -F: '{printf "%s\0", $1}' > "$NNN_PIPE"
|
||||
if type mimetype >/dev/null 2>&1; then
|
||||
find . | mimetype -f - | grep "$mime" | awk -F: '{printf "%s%c", $1, 0}' > "$NNN_PIPE"
|
||||
else
|
||||
find . | file -if- | grep "$mime" | awk -F: '{printf "%s%c", $1, 0}' > "$NNN_PIPE"
|
||||
fi
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
# Description: Fetches the lyrics of the track currently playing in MOC
|
||||
#
|
||||
# Dependencies: ddgr (https://github.com/jarun/ddgr)
|
||||
#
|
||||
# Shell: POSIX compliant
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
# Description: Appends and optionally plays music in MOC
|
||||
#
|
||||
# Notes:
|
||||
# - if selection is available, plays it, else plays the current file or directory
|
||||
# - appends tracks and exits is MOC is running, else clears playlist and adds tracks
|
||||
# - to let mocp shuffle tracks, set SHUFFLE=1
|
||||
# - if selection is available, plays it, else plays the current file or directory
|
||||
# - appends tracks and exits is MOC is running, else clears playlist and adds tracks
|
||||
# - to let mocp shuffle tracks, set SHUFFLE=1
|
||||
#
|
||||
# Shell: POSIX compliant
|
||||
# Authors: Arun Prakash Jana, ath3
|
||||
|
@ -82,3 +82,8 @@ mocp -p
|
|||
|
||||
# uncomment the line below to show mocp interface after appending
|
||||
# mocp
|
||||
|
||||
# Clear selection
|
||||
if [ "$resp" = "y" ] && [ -p "$NNN_PIPE" ]; then
|
||||
printf "-" > "$NNN_PIPE"
|
||||
fi
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
# Description: Extract audio from multimedia files and convert to mp3
|
||||
#
|
||||
# Dependency: ffmpeg compiled with libmp3lame audio codec support
|
||||
# Dependencies: ffmpeg compiled with libmp3lame audio codec support
|
||||
#
|
||||
# Shell: POSIX compliant
|
||||
# Author: Arun Prakash Jana
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
# Description: Toggle mount of MTP device (eg. Android device)
|
||||
# 'l' to list mountable devices
|
||||
# 'n' integer associated to device to mount
|
||||
# 'q'/'Return' exit
|
||||
#
|
||||
# Dependencies: gvfs-mtp
|
||||
#
|
||||
# Notes: The MTP device should be mounted at /run/user/$UID/gvfs.
|
||||
# Put /run/user/$UID/gvfs to bookmark entries (NNN_BMS) for faster access.
|
||||
# Make sure the device is unlocked when mounting.
|
||||
#
|
||||
# When doing copy-paste into MTP device, you will get an error like this:
|
||||
# cp: preserving times for './gambar1.png': Operation not supported
|
||||
# That just means the file is copied but timestamp won't be preserved.
|
||||
# It's like doing `cp -p localfile.txt file-to-SMB.txt`.
|
||||
#
|
||||
# Shell: POSIX compliant
|
||||
# Author: Benawi Adha
|
||||
|
||||
prompt="Device number ('l' to list): "
|
||||
|
||||
IFS='
|
||||
'
|
||||
|
||||
lsmtp () {
|
||||
devs=$(gio mount -li | grep -e 'activation_root' | sed 's/\s*activation_root=//g')
|
||||
c=1
|
||||
printf "Devices list:\n"
|
||||
for i in $devs; do
|
||||
printf "%s %s\\n" "$c" "$i"
|
||||
c=$(( c + 1 ))
|
||||
done
|
||||
echo
|
||||
}
|
||||
|
||||
lsmtp
|
||||
printf "%s" "$prompt"
|
||||
read -r input
|
||||
|
||||
while [ -n "$input" ]
|
||||
do
|
||||
if [ "$input" = "l" ]; then
|
||||
lsmtp
|
||||
elif [ "$input" = "q" ] || [ "$input" -eq 0 ]; then
|
||||
exit
|
||||
elif [ "$input" -le "$(printf '%s\n' "${devs}" | grep -c '^')" ]; then
|
||||
# dev=$(printf "%s\n" "$devs" | cut -d$'\n' -f${input})
|
||||
c=1
|
||||
for i in $devs; do
|
||||
dev=$i
|
||||
if [ "$input" -eq $c ]; then
|
||||
break
|
||||
fi
|
||||
c=$(( c + 1 ))
|
||||
done
|
||||
|
||||
if (gio mount -l | grep '^Mount([1-9]).*'"$dev" ) 1>/dev/null; then
|
||||
if gio mount -u "${dev}"; then
|
||||
printf "%s unmounted\n" "$dev"
|
||||
fi
|
||||
else
|
||||
if gio mount "${dev}"; then
|
||||
printf "%s mounted to /run/user/\$UID/gvfs\n" "$dev"
|
||||
fi
|
||||
fi
|
||||
echo
|
||||
else
|
||||
printf "Invalid input\n"
|
||||
fi
|
||||
|
||||
printf "%s" "$prompt"
|
||||
read -r input
|
||||
done
|
||||
|
|
@ -34,7 +34,7 @@ fi
|
|||
cd "$tempdir/$outdir" || exit 1
|
||||
|
||||
# Backing up config dir content
|
||||
cp -r "$configdir" . || exit 1
|
||||
cp -r -- "$configdir" . || exit 1
|
||||
|
||||
# Environment config
|
||||
env | sed "s/'/'\\\\''/" |\
|
||||
|
@ -72,4 +72,4 @@ printf "Saving as '%s' ... " "$workdir/$outfile"
|
|||
|
||||
tar caf "$workdir/$outfile" "$outdir" && echo "Done" || echo "Failed"
|
||||
|
||||
cd "$workdir" && rm -rf "$tempdir"
|
||||
cd "$workdir" && rm -rf -- "$tempdir"
|
||||
|
|
|
@ -4,19 +4,21 @@
|
|||
# If the device is not mounted, it will be mounted.
|
||||
# If the device is mounted, it will be unmounted and powered down.
|
||||
#
|
||||
# Runs `lsblk` if 'l' is entered, exits on 'Return`.
|
||||
# Dependencies: lsblk, pmount (optional), udisks2
|
||||
#
|
||||
# Note:
|
||||
# - The script uses Linux-specific lsblk to list block devices. Alternatives:
|
||||
# Usage: Runs `lsblk` on 'l', exits on 'Return`.
|
||||
#
|
||||
# Notes:
|
||||
# - The script uses Linux-specific lsblk to list block devices. Alternatives:
|
||||
# macOS: "diskutil list"
|
||||
# BSD: "geom disk list"
|
||||
# - The script uses udisksctl (from udisks2) to power down devices. This is also Linux-specific.
|
||||
# Users on non-Linux platforms can comment it and use an alterntive to power-down disks.
|
||||
# - The script uses udisksctl (from udisks2) to power down devices. This is also Linux-specific.
|
||||
# Users on non-Linux platforms can comment it and use an alternative to power-down disks.
|
||||
#
|
||||
# Shell: POSIX compliant
|
||||
# Author: Arun Prakash Jana
|
||||
|
||||
prompt="device name ['l' lists]: "
|
||||
prompt="device name [e.g. sdXn] ('l'ist, 'q'uit): "
|
||||
|
||||
lsblk
|
||||
|
||||
|
@ -24,26 +26,59 @@ printf "\nEnsure you aren't still in the mounted device.\n"
|
|||
printf "%s" "$prompt"
|
||||
read -r dev
|
||||
|
||||
while [ -n "$dev" ]
|
||||
do
|
||||
while [ -n "$dev" ]; do
|
||||
if [ "$dev" = "l" ]; then
|
||||
lsblk
|
||||
elif [ "$dev" = "q" ]; then
|
||||
exit
|
||||
else
|
||||
if grep -qs "$dev " /proc/mounts; then
|
||||
sync
|
||||
if pumount "$dev"
|
||||
then
|
||||
echo "$dev" unmounted.
|
||||
if udisksctl power-off -b /dev/"$dev"
|
||||
then
|
||||
echo "$dev" ejected.
|
||||
# LUKS volumes mounted with udisksctl appear differently than with pmount
|
||||
if grep -qs "$dev " /proc/mounts || [ -n "$(lsblk -n "/dev/$dev" -o MOUNTPOINT)" ]; then
|
||||
sync "$(lsblk -n "/dev/$dev" -o MOUNTPOINT | sed "/^$/d")"
|
||||
if type pumount >/dev/null 2>&1; then
|
||||
pumount "/dev/$dev"
|
||||
exit_code="$?"
|
||||
else
|
||||
# Unlike pmount, udisksctl does not transparently handle LUKS volumes
|
||||
# We need to manually get the unlocked device, unmount it, and then lock the volume
|
||||
if lsblk -n "/dev/$dev" -o FSTYPE | grep "crypto_LUKS" >/dev/null; then
|
||||
dev_map="$(udisksctl info -b /dev/"$dev" | grep "CleartextDevice" | grep -o "dm_2d[[:digit:]]*" | sed "s/_2d/-/")"
|
||||
udisksctl unmount -b "/dev/$dev_map" --no-user-interaction >/dev/null
|
||||
exit_code="$?"
|
||||
udisksctl lock -b "/dev/$dev" --no-user-interaction >/dev/null
|
||||
else
|
||||
udisksctl unmount -b "/dev/$dev" --no-user-interaction >/dev/null
|
||||
exit_code="$?"
|
||||
fi
|
||||
fi
|
||||
if [ $exit_code -eq 0 ]; then
|
||||
echo "/dev/$dev unmounted."
|
||||
if udisksctl power-off -b "/dev/$dev" --no-user-interaction; then
|
||||
echo "/dev/$dev ejected."
|
||||
fi
|
||||
fi
|
||||
elif [ -b "/dev/$dev" ]; then
|
||||
if type pmount >/dev/null 2>&1; then
|
||||
pmount "/dev/$dev"
|
||||
exit_code="$?"
|
||||
else
|
||||
# Unlike pmount, udisksctl does not transparently handle LUKS volumes
|
||||
# We need to manually get the unlocked device and mount that instead of the volume itself
|
||||
if [ "$(lsblk "/dev/$dev" -n -o FSTYPE)" = "crypto_LUKS" ]; then
|
||||
dev_map=$(udisksctl unlock -b "/dev/$dev" --no-user-interaction | grep -o "dm-[[:digit:]]*")
|
||||
udisksctl mount -b "/dev/$dev_map" --no-user-interaction >/dev/null
|
||||
exit_code="$?"
|
||||
else
|
||||
udisksctl mount -b "/dev/$dev" --no-user-interaction >/dev/null
|
||||
exit_code="$?"
|
||||
fi
|
||||
fi
|
||||
if [ $exit_code -eq 0 ]; then
|
||||
sleep 1
|
||||
echo "/dev/$dev mounted to $(lsblk -n "/dev/$dev" -o MOUNTPOINT | sed "/^$/d")."
|
||||
fi
|
||||
else
|
||||
pmount "$dev"
|
||||
echo "$dev" mounted to "$(lsblk -n /dev/"$dev" | rev | cut -d' ' -f1 | rev)".
|
||||
echo "/dev/$dev does not exist or is not a block device."
|
||||
fi
|
||||
fi
|
||||
|
||||
|
|
221
plugins/nuke
221
plugins/nuke
|
@ -1,6 +1,5 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
# #############################################################################
|
||||
# Description: Sample script to play files in apps by file type or mime
|
||||
#
|
||||
# Shell: POSIX compliant
|
||||
|
@ -14,7 +13,7 @@
|
|||
# 2. Run nnn with the program option to indicate a CLI opener
|
||||
# nnn -c
|
||||
# # The -c program option overrides option -e
|
||||
# 3. nuke can use nnn plugins (e.g. mocplay is used for audio), $PATH is updated.
|
||||
# 3. nuke can use nnn plugins (e.g. mocq is used for audio), $PATH is updated.
|
||||
#
|
||||
# Details:
|
||||
# Inspired by ranger's scope.sh, modified for usage with nnn.
|
||||
|
@ -22,9 +21,10 @@
|
|||
# Guards against accidentally opening mime types like executables, shared libs etc.
|
||||
#
|
||||
# Tries to play 'file' (1st argument) in the following order:
|
||||
# i. by extension
|
||||
# ii. by mime (image, video, audio, pdf)
|
||||
# iii. by mime (other file types)
|
||||
# 1. by extension
|
||||
# 2. by mime (image, video, audio, pdf)
|
||||
# 3. by mime (other file types)
|
||||
# 4. by mime (prompt and run executables)
|
||||
#
|
||||
# Modification tips:
|
||||
# 1. Invokes CLI utilities by default. Set GUI to 1 to enable GUI apps.
|
||||
|
@ -42,7 +42,7 @@
|
|||
# rar: list with unrar
|
||||
# 7-zip: list with 7z
|
||||
# pdf: zathura (GUI), pdftotext, mutool, exiftool
|
||||
# audio: mocplay (nnn plugin using MOC), mpv, media_client (Haiku), mediainfo, exiftool
|
||||
# audio: mocq (nnn plugin using MOC), mpv, media_client (Haiku), mediainfo, exiftool
|
||||
# avi|mkv|mp4: smplayer, mpv (GUI), ffmpegthumbnailer, mediainfo, exiftool
|
||||
# log: vi
|
||||
# torrent: rtorrent, transmission-show
|
||||
|
@ -51,22 +51,22 @@
|
|||
# htm|html|xhtml: w3m, lynx, elinks
|
||||
# json: jq, python (json.tool module)
|
||||
# Multimedia by mime:
|
||||
# image/*: imv/sxiv (GUI), viu (https://github.com/atanunq/viu), img2txt, exiftool
|
||||
# image/*: imv/sxiv/nsxiv (GUI), viu (https://github.com/atanunq/viu), img2txt, exiftool
|
||||
# video/*: smplayer, mpv (GUI), ffmpegthumbnailer, mediainfo, exiftool
|
||||
# audio/*: mocplay (nnn plugin using MOC), mpv, media_client (Haiku), mediainfo, exiftool
|
||||
# audio/*: mocq (nnn plugin using MOC), mpv, media_client (Haiku), mediainfo, exiftool
|
||||
# application/pdf: zathura (GUI), pdftotext, mutool, exiftool
|
||||
# Other mimes:
|
||||
# text/troff: man -l
|
||||
# text/* | */xml: vi
|
||||
# image/vnd.djvu): djvutxt, exiftool
|
||||
#
|
||||
# ToDo:
|
||||
# TODO:
|
||||
# 1. Adapt, test and enable all mimes
|
||||
# 2. Clean-up the unnecessary exit codes
|
||||
# #############################################################################
|
||||
|
||||
# set to 1 to enable GUI apps
|
||||
# set to 1 to enable GUI apps and/or BIN execution
|
||||
GUI="${GUI:-0}"
|
||||
BIN="${BIN:-0}"
|
||||
|
||||
set -euf -o noclobber -o noglob -o nounset
|
||||
IFS="$(printf '%b_' '\n')"; IFS="${IFS%_}" # protect trailing \n
|
||||
|
@ -88,67 +88,68 @@ is_mac() {
|
|||
}
|
||||
|
||||
handle_pdf() {
|
||||
if [ "$GUI" -ne 0 ] && is_mac; then
|
||||
nohup open "${FPATH}" >/dev/null 2>&1 &
|
||||
exit 0
|
||||
elif [ "$GUI" -ne 0 ] && which zathura >/dev/null 2>&1; then
|
||||
nohup zathura "${FPATH}" >/dev/null 2>&1 &
|
||||
exit 0
|
||||
elif which pdftotext >/dev/null 2>&1; then
|
||||
if [ "$GUI" -ne 0 ]; then
|
||||
if is_mac; then
|
||||
nohup open "${FPATH}" >/dev/null 2>&1 &
|
||||
elif type zathura >/dev/null 2>&1; then
|
||||
nohup zathura "${FPATH}" >/dev/null 2>&1 &
|
||||
else
|
||||
return
|
||||
fi
|
||||
elif type pdftotext >/dev/null 2>&1; then
|
||||
## Preview as text conversion
|
||||
pdftotext -l 10 -nopgbrk -q -- "${FPATH}" - | eval "$PAGER"
|
||||
exit 0
|
||||
elif which mutool >/dev/null 2>&1; then
|
||||
elif type mutool >/dev/null 2>&1; then
|
||||
mutool draw -F txt -i -- "${FPATH}" 1-10 | eval "$PAGER"
|
||||
exit 0
|
||||
elif which exiftool >/dev/null 2>&1; then
|
||||
elif type exiftool >/dev/null 2>&1; then
|
||||
exiftool "${FPATH}" | eval "$PAGER"
|
||||
exit 0
|
||||
else
|
||||
return
|
||||
fi
|
||||
exit 0
|
||||
}
|
||||
|
||||
handle_audio() {
|
||||
if which mocp >/dev/null 2>&1 && which mocplay >/dev/null 2>&1; then
|
||||
mocplay "${FPATH}" "opener" >/dev/null 2>&1
|
||||
exit 0
|
||||
elif which mpv >/dev/null 2>&1; then
|
||||
if type mocp >/dev/null 2>&1 && type mocq >/dev/null 2>&1; then
|
||||
mocq "${FPATH}" "opener" >/dev/null 2>&1
|
||||
elif type mpv >/dev/null 2>&1; then
|
||||
mpv "${FPATH}" >/dev/null 2>&1 &
|
||||
exit 0
|
||||
elif which media_client >/dev/null 2>&1; then
|
||||
elif type media_client >/dev/null 2>&1; then
|
||||
media_client play "${FPATH}" >/dev/null 2>&1 &
|
||||
exit 0
|
||||
elif which mediainfo >/dev/null 2>&1; then
|
||||
elif type mediainfo >/dev/null 2>&1; then
|
||||
mediainfo "${FPATH}" | eval "$PAGER"
|
||||
exit 0
|
||||
elif which exiftool >/dev/null 2>&1; then
|
||||
elif type exiftool >/dev/null 2>&1; then
|
||||
exiftool "${FPATH}"| eval "$PAGER"
|
||||
exit 0
|
||||
else
|
||||
return
|
||||
fi
|
||||
exit 0
|
||||
}
|
||||
|
||||
handle_video() {
|
||||
if [ "$GUI" -ne 0 ] && is_mac; then
|
||||
nohup open "${FPATH}" >/dev/null 2>&1 &
|
||||
exit 0
|
||||
elif [ "$GUI" -ne 0 ] && which smplayer >/dev/null 2>&1; then
|
||||
nohup smplayer "${FPATH}" >/dev/null 2>&1 &
|
||||
exit 0
|
||||
elif [ "$GUI" -ne 0 ] && which mpv >/dev/null 2>&1; then
|
||||
nohup mpv "${FPATH}" >/dev/null 2>&1 &
|
||||
exit 0
|
||||
elif which ffmpegthumbnailer >/dev/null 2>&1; then
|
||||
if [ "$GUI" -ne 0 ]; then
|
||||
if is_mac; then
|
||||
nohup open "${FPATH}" >/dev/null 2>&1 &
|
||||
elif type smplayer >/dev/null 2>&1; then
|
||||
nohup smplayer "${FPATH}" >/dev/null 2>&1 &
|
||||
elif type mpv >/dev/null 2>&1; then
|
||||
nohup mpv "${FPATH}" >/dev/null 2>&1 &
|
||||
else
|
||||
return
|
||||
fi
|
||||
elif type ffmpegthumbnailer >/dev/null 2>&1; then
|
||||
# Thumbnail
|
||||
[ -d "${IMAGE_CACHE_PATH}" ] || mkdir "${IMAGE_CACHE_PATH}"
|
||||
ffmpegthumbnailer -i "${FPATH}" -o "${IMAGE_CACHE_PATH}/${FNAME}.jpg" -s 0
|
||||
viu -n "${IMAGE_CACHE_PATH}/${FNAME}.jpg" | eval "$PAGER"
|
||||
exit 0
|
||||
elif which mediainfo >/dev/null 2>&1; then
|
||||
elif type mediainfo >/dev/null 2>&1; then
|
||||
mediainfo "${FPATH}" | eval "$PAGER"
|
||||
exit 0
|
||||
elif which exiftool >/dev/null 2>&1; then
|
||||
elif type exiftool >/dev/null 2>&1; then
|
||||
exiftool "${FPATH}"| eval "$PAGER"
|
||||
exit 0
|
||||
else
|
||||
return
|
||||
fi
|
||||
exit 0
|
||||
}
|
||||
|
||||
# handle this extension and exit
|
||||
|
@ -157,22 +158,22 @@ handle_extension() {
|
|||
## Archive
|
||||
a|ace|alz|arc|arj|bz|bz2|cab|cpio|deb|gz|jar|lha|lz|lzh|lzma|lzo|\
|
||||
rpm|rz|t7z|tar|tbz|tbz2|tgz|tlz|txz|tZ|tzo|war|xpi|xz|Z|zip)
|
||||
if which atool >/dev/null 2>&1; then
|
||||
if type atool >/dev/null 2>&1; then
|
||||
atool --list -- "${FPATH}" | eval "$PAGER"
|
||||
exit 0
|
||||
elif which bsdtar >/dev/null 2>&1; then
|
||||
elif type bsdtar >/dev/null 2>&1; then
|
||||
bsdtar --list --file "${FPATH}" | eval "$PAGER"
|
||||
exit 0
|
||||
fi
|
||||
exit 1;;
|
||||
rar)
|
||||
if which unrar >/dev/null 2>&1; then
|
||||
if type unrar >/dev/null 2>&1; then
|
||||
## Avoid password prompt by providing empty password
|
||||
unrar lt -p- -- "${FPATH}" | eval "$PAGER"
|
||||
fi
|
||||
exit 1;;
|
||||
7z)
|
||||
if which 7z >/dev/null 2>&1; then
|
||||
if type 7z >/dev/null 2>&1; then
|
||||
## Avoid password prompt by providing empty password
|
||||
7z l -p -- "${FPATH}" | eval "$PAGER"
|
||||
exit 0
|
||||
|
@ -201,10 +202,10 @@ handle_extension() {
|
|||
|
||||
## BitTorrent
|
||||
torrent)
|
||||
if which rtorrent >/dev/null 2>&1; then
|
||||
if type rtorrent >/dev/null 2>&1; then
|
||||
rtorrent "${FPATH}"
|
||||
exit 0
|
||||
elif which transmission-show >/dev/null 2>&1; then
|
||||
elif type transmission-show >/dev/null 2>&1; then
|
||||
transmission-show -- "${FPATH}"
|
||||
exit 0
|
||||
fi
|
||||
|
@ -212,7 +213,7 @@ handle_extension() {
|
|||
|
||||
## OpenDocument
|
||||
odt|ods|odp|sxw)
|
||||
if which odt2txt >/dev/null 2>&1; then
|
||||
if type odt2txt >/dev/null 2>&1; then
|
||||
## Preview as text conversion
|
||||
odt2txt "${FPATH}" | eval "$PAGER"
|
||||
exit 0
|
||||
|
@ -221,10 +222,10 @@ handle_extension() {
|
|||
|
||||
## Markdown
|
||||
md)
|
||||
if which glow >/dev/null 2>&1; then
|
||||
if type glow >/dev/null 2>&1; then
|
||||
glow -sdark "${FPATH}" | eval "$PAGER"
|
||||
exit 0
|
||||
elif which lowdown >/dev/null 2>&1; then
|
||||
elif type lowdown >/dev/null 2>&1; then
|
||||
lowdown -Tterm "${FPATH}" | eval "$PAGER"
|
||||
exit 0
|
||||
fi
|
||||
|
@ -233,13 +234,13 @@ handle_extension() {
|
|||
## HTML
|
||||
htm|html|xhtml)
|
||||
## Preview as text conversion
|
||||
if which w3m >/dev/null 2>&1; then
|
||||
if type w3m >/dev/null 2>&1; then
|
||||
w3m -dump "${FPATH}" | eval "$PAGER"
|
||||
exit 0
|
||||
elif which lynx >/dev/null 2>&1; then
|
||||
elif type lynx >/dev/null 2>&1; then
|
||||
lynx -dump -- "${FPATH}" | eval "$PAGER"
|
||||
exit 0
|
||||
elif which elinks >/dev/null 2>&1; then
|
||||
elif type elinks >/dev/null 2>&1; then
|
||||
elinks -dump "${FPATH}" | eval "$PAGER"
|
||||
exit 0
|
||||
fi
|
||||
|
@ -247,10 +248,10 @@ handle_extension() {
|
|||
|
||||
## JSON
|
||||
json)
|
||||
if which jq >/dev/null 2>&1; then
|
||||
if type jq >/dev/null 2>&1; then
|
||||
jq --color-output . "${FPATH}" | eval "$PAGER"
|
||||
exit 0
|
||||
elif which python >/dev/null 2>&1; then
|
||||
elif type python >/dev/null 2>&1; then
|
||||
python -m json.tool -- "${FPATH}" | eval "$PAGER"
|
||||
exit 0
|
||||
fi
|
||||
|
@ -258,27 +259,32 @@ handle_extension() {
|
|||
esac
|
||||
}
|
||||
|
||||
# sets the variable abs_target, this should be faster than calling printf
|
||||
abspath() {
|
||||
case "$1" in
|
||||
/*) printf "%s\n" "$1";;
|
||||
*) printf "%s\n" "$PWD/$1";;
|
||||
/*) abs_target="$1";;
|
||||
*) abs_target="$PWD/$1";;
|
||||
esac
|
||||
}
|
||||
|
||||
# storing the result to a tmp file is faster than calling listimages twice
|
||||
listimages() {
|
||||
find -L "$(dirname "$target")" -maxdepth 1 -type f -iregex \
|
||||
'.*\(jpe?g\|bmp\|webp\|png\|gif\)$' -print0 | sort -z
|
||||
find -L "///${1%/*}" -maxdepth 1 -type f -print0 |
|
||||
grep -izZE '\.(jpe?g|png|gif|webp|tiff|bmp|ico|svg)$' |
|
||||
sort -zV | tee "$tmp"
|
||||
}
|
||||
|
||||
load_dir() {
|
||||
target="$(abspath "$2")"
|
||||
count="$(listimages | grep -a -m 1 -ZznF "$target" | cut -d: -f1)"
|
||||
abspath "$2"
|
||||
tmp="${TMPDIR:-/tmp}/nuke_$$"
|
||||
trap 'rm -f -- "$tmp"' EXIT
|
||||
count="$(listimages "$abs_target" | grep -a -m 1 -ZznF "$abs_target" | cut -d: -f1)"
|
||||
|
||||
if [ -n "$count" ]; then
|
||||
if [ "$GUI" -ne 0 ]; then
|
||||
listimages | xargs -0 nohup "$1" -n "$count" --
|
||||
xargs -0 nohup "$1" -n "$count" -- < "$tmp"
|
||||
else
|
||||
listimages | xargs -0 "$1" -n "$count" --
|
||||
xargs -0 "$1" -n "$count" -- < "$tmp"
|
||||
fi
|
||||
else
|
||||
shift
|
||||
|
@ -308,22 +314,30 @@ handle_multimedia() {
|
|||
|
||||
## Image
|
||||
image/*)
|
||||
if [ "$GUI" -ne 0 ] && is_mac; then
|
||||
nohup open "${FPATH}" >/dev/null 2>&1 &
|
||||
exit 0
|
||||
elif [ "$GUI" -ne 0 ] && which imvr >/dev/null 2>&1; then
|
||||
load_dir imvr "${FPATH}" >/dev/null 2>&1 &
|
||||
exit 0
|
||||
elif [ "$GUI" -ne 0 ] && which sxiv >/dev/null 2>&1; then
|
||||
load_dir sxiv "${FPATH}" >/dev/null 2>&1 &
|
||||
exit 0
|
||||
elif which viu >/dev/null 2>&1; then
|
||||
if [ "$GUI" -ne 0 ]; then
|
||||
if is_mac; then
|
||||
nohup open "${FPATH}" >/dev/null 2>&1 &
|
||||
exit 0
|
||||
elif type imv >/dev/null 2>&1; then
|
||||
load_dir imv "${FPATH}" >/dev/null 2>&1 &
|
||||
exit 0
|
||||
elif type imvr >/dev/null 2>&1; then
|
||||
load_dir imvr "${FPATH}" >/dev/null 2>&1 &
|
||||
exit 0
|
||||
elif type sxiv >/dev/null 2>&1; then
|
||||
load_dir sxiv "${FPATH}" >/dev/null 2>&1 &
|
||||
exit 0
|
||||
elif type nsxiv >/dev/null 2>&1; then
|
||||
load_dir nsxiv "${FPATH}" >/dev/null 2>&1 &
|
||||
exit 0
|
||||
fi
|
||||
elif type viu >/dev/null 2>&1; then
|
||||
viu -n "${FPATH}" | eval "$PAGER"
|
||||
exit 0
|
||||
elif which img2txt >/dev/null 2>&1; then
|
||||
elif type img2txt >/dev/null 2>&1; then
|
||||
img2txt --gamma=0.6 -- "${FPATH}" | eval "$PAGER"
|
||||
exit 0
|
||||
elif which exiftool >/dev/null 2>&1; then
|
||||
elif type exiftool >/dev/null 2>&1; then
|
||||
exiftool "${FPATH}" | eval "$PAGER"
|
||||
exit 0
|
||||
fi
|
||||
|
@ -388,7 +402,7 @@ handle_multimedia() {
|
|||
# "${FPATH}";
|
||||
# then
|
||||
# convert -- "${preview_png}" "${IMAGE_CACHE_PATH}" \
|
||||
# && rm "${preview_png}" \
|
||||
# && rm -- "${preview_png}" \
|
||||
# && exit 6
|
||||
# else
|
||||
# exit 1
|
||||
|
@ -466,11 +480,11 @@ handle_mime() {
|
|||
|
||||
## DjVu
|
||||
image/vnd.djvu)
|
||||
if which djvutxt >/dev/null 2>&1; then
|
||||
if type djvutxt >/dev/null 2>&1; then
|
||||
## Preview as text conversion (requires djvulibre)
|
||||
djvutxt "${FPATH}" | eval "$PAGER"
|
||||
exit 0
|
||||
elif which exiftool >/dev/null 2>&1; then
|
||||
elif type exiftool >/dev/null 2>&1; then
|
||||
exiftool "${FPATH}" | eval "$PAGER"
|
||||
exit 0
|
||||
fi
|
||||
|
@ -479,12 +493,14 @@ handle_mime() {
|
|||
}
|
||||
|
||||
handle_fallback() {
|
||||
if [ "$GUI" -ne 0 ] && which xdg-open >/dev/null 2>&1; then
|
||||
nohup xdg-open "${FPATH}" >/dev/null 2>&1 &
|
||||
exit 0
|
||||
elif [ "$GUI" -ne 0 ] && which open >/dev/null 2>&1; then
|
||||
nohup open "${FPATH}" >/dev/null 2>&1 &
|
||||
exit 0
|
||||
if [ "$GUI" -ne 0 ]; then
|
||||
if type xdg-open >/dev/null 2>&1; then
|
||||
nohup xdg-open "${FPATH}" >/dev/null 2>&1 &
|
||||
exit 0
|
||||
elif type open >/dev/null 2>&1; then
|
||||
nohup open "${FPATH}" >/dev/null 2>&1 &
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
echo '----- File details -----' && file --dereference --brief -- "${FPATH}"
|
||||
|
@ -510,10 +526,29 @@ handle_blocked() {
|
|||
esac
|
||||
}
|
||||
|
||||
MIMETYPE="$( file --dereference --brief --mime-type -- "${FPATH}" )"
|
||||
handle_bin() {
|
||||
case "${MIMETYPE}" in
|
||||
application/x-executable|application/x-shellscript)
|
||||
clear
|
||||
echo '-------- Executable File --------' && file --dereference --brief -- "${FPATH}"
|
||||
printf "Run executable (y/N/'a'rgs)? "
|
||||
read -r answer
|
||||
case "$answer" in
|
||||
[Yy]* ) exec "${FPATH}";;
|
||||
[Aa]* )
|
||||
printf "args: "
|
||||
read -r args
|
||||
exec "${FPATH}" "$args";;
|
||||
[Nn]* ) exit;;
|
||||
esac
|
||||
esac
|
||||
}
|
||||
|
||||
MIMETYPE="$( file -bL --mime-type -- "${FPATH}" )"
|
||||
handle_extension
|
||||
handle_multimedia "${MIMETYPE}"
|
||||
handle_mime "${MIMETYPE}"
|
||||
[ "$BIN" -ne 0 ] && [ -x "${FPATH}" ] && handle_bin
|
||||
handle_blocked "${MIMETYPE}"
|
||||
handle_fallback
|
||||
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Description: Open selected files in nuke one by one or in oneshot
|
||||
#
|
||||
# Notes: 1. Opens the hovered file if the selection is empty
|
||||
# 2. nuke is the default, set OPENER below for custom
|
||||
# 3. Opener is invoked once for each file in a loop
|
||||
# 4. Keep pressing "Enter" to open files one by one
|
||||
#
|
||||
# Shell: bash
|
||||
# Author: Arun Prakash Jana
|
||||
|
||||
sel=${NNN_SEL:-${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.selection}
|
||||
OPENER="${XDG_CONFIG_HOME:-$HOME/.config}/nnn/plugins/nuke"
|
||||
|
||||
if [ -s "$sel" ]; then
|
||||
targets=()
|
||||
while IFS= read -r -d '' entry || [ -n "$entry" ]; do
|
||||
targets+=( "$entry" )
|
||||
done < "$sel"
|
||||
|
||||
elements=${#targets[@]}
|
||||
|
||||
if (( elements == 1 )); then
|
||||
# If there's only one file selected, open without prompts
|
||||
"$OPENER" "${targets[0]}"
|
||||
else
|
||||
printf "open [A]ll? "
|
||||
read -r all
|
||||
|
||||
for ((index=0; index <= ${#targets[@]}; index++)); do
|
||||
"$OPENER" "${targets[index]}"
|
||||
if [ "$all" != "A" ] && (( index+1 < elements )); then
|
||||
printf "press Enter to open '%s'\n" "${targets[index+1]}"
|
||||
read -r -s -n 1 key
|
||||
if [[ $key != "" ]]; then
|
||||
break
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# Clear selection
|
||||
if [ -s "$sel" ] && [ -p "$NNN_PIPE" ]; then
|
||||
printf "-" > "$NNN_PIPE"
|
||||
fi
|
||||
elif [ -n "$1" ]; then
|
||||
"$OPENER" "$1"
|
||||
fi
|
|
@ -2,43 +2,47 @@
|
|||
|
||||
# Description: Organize files in directories by category
|
||||
#
|
||||
# Note: This plugin clears the selection as it changes the contents of the current dir
|
||||
#
|
||||
# Shell: POSIX compliant
|
||||
# Author: th3lusive
|
||||
|
||||
sel=${NNN_SEL:-${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.selection}
|
||||
|
||||
organize() {
|
||||
case "$(file -biL "$1")" in
|
||||
*video*)
|
||||
[ ! -d "Videos" ] && mkdir "Videos"
|
||||
mv "$1" "Videos/$1"
|
||||
mv -- "$1" "Videos/$1"
|
||||
printf "Moved %s to Videos\n" "$1" ;;
|
||||
|
||||
*audio*) [ ! -d "Audio" ] && mkdir "Audio"
|
||||
mv "$1" "Audio/$1"
|
||||
mv -- "$1" "Audio/$1"
|
||||
printf "Moved %s to Audio\n" "$1" ;;
|
||||
|
||||
*image*)
|
||||
[ ! -d "Images" ] && mkdir "Images"
|
||||
mv "$1" "Images/$1"
|
||||
mv -- "$1" "Images/$1"
|
||||
printf "Moved %s to Images\n" "$1" ;;
|
||||
|
||||
*pdf*|*document*|*epub*|*djvu*|*cb*)
|
||||
[ ! -d "Documents" ] && mkdir "Documents"
|
||||
mv "$1" "Documents/$1"
|
||||
mv -- "$1" "Documents/$1"
|
||||
printf "Moved %s to Documents\n" "$1" ;;
|
||||
|
||||
*text*)
|
||||
[ ! -d "Plaintext" ] && mkdir "Plaintext"
|
||||
mv "$1" "Plaintext/$1"
|
||||
mv -- "$1" "Plaintext/$1"
|
||||
printf "Moved %s to Plaintext\n" "$1" ;;
|
||||
|
||||
*tar*|*xz*|*compress*|*7z*|*rar*|*zip*)
|
||||
[ ! -d "Archives" ] && mkdir "Archives"
|
||||
mv "$1" "Archives/$1"
|
||||
mv -- "$1" "Archives/$1"
|
||||
printf "Moved %s to Archives\n" "$1" ;;
|
||||
|
||||
*binary*)
|
||||
[ ! -d "Binaries" ] && mkdir "Binaries"
|
||||
mv "$1" "Binaries/$1"
|
||||
mv -- "$1" "Binaries/$1"
|
||||
printf "Moved %s to Binaries\n" "$1" ;;
|
||||
esac
|
||||
}
|
||||
|
@ -48,6 +52,11 @@ main() {
|
|||
do
|
||||
[ -f "$file" ] && organize "$file"
|
||||
done
|
||||
|
||||
# Clear selection
|
||||
if [ -s "$sel" ] && [ -p "$NNN_PIPE" ]; then
|
||||
printf "-" > "$NNN_PIPE"
|
||||
fi
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
|
|
@ -15,7 +15,7 @@ if [ -n "$1" ]; then
|
|||
|
||||
pico2wave -w "$tmpf".wav -l en-GB "$(tr '\n' ' ' < "$tmpf".txt)"
|
||||
|
||||
rm "$tmpf".txt
|
||||
rm -- "$tmpf".txt
|
||||
else
|
||||
pico2wave -w "$tmpf".wav -l en-GB "$(tr '\n' ' ' < "$1")"
|
||||
fi
|
||||
|
@ -26,5 +26,5 @@ if [ -n "$1" ]; then
|
|||
# flat read but better quality
|
||||
# play -qV0 "$tmpf".wav treble 2 gain -l 2
|
||||
|
||||
rm "$tmpf".wav
|
||||
rm -- "$tmpf".wav
|
||||
fi
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
# Description: View a PDF file in pager
|
||||
#
|
||||
# Notes:
|
||||
# - $PAGER must be 'less -R' or 'most'
|
||||
# - To use mutool, uncomment the relevant lines and comment the pdftotext line
|
||||
#
|
||||
# Shell: POSIX compliant
|
||||
# Author: Arun Prakash Jana
|
||||
|
||||
if [ -n "$1" ]; then
|
||||
if [ "$(head -c 4 "$1")" = "%PDF" ]; then
|
||||
# Convert using pdftotext
|
||||
pdftotext -nopgbrk -layout "$1" - | sed 's/\xe2\x80\x8b//g' | $PAGER
|
||||
|
||||
# Convert using mutool
|
||||
# file=`basename "$1"`
|
||||
# txt=/tmp/"$file".txt
|
||||
# mutool convert -o "$txt" "$1"
|
||||
# eval $PAGER $txt
|
||||
# rm "$txt"
|
||||
fi
|
||||
fi
|
|
@ -1,26 +0,0 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
# Description: Pick files and pipe the newline-separated list to another utility
|
||||
#
|
||||
# Usage:
|
||||
# Copy this file in your $PATH, make it executable and preferably name it to picker.
|
||||
# Run commands like:
|
||||
# ls -l `picker`
|
||||
# cd `picker`
|
||||
# vimdiff `picker`
|
||||
# or, in fish shell:
|
||||
# ls -l (picker)
|
||||
# cd (picker)
|
||||
# vimdiff (picker)
|
||||
#
|
||||
# Note: This use case is limited to picking files, other functionality may not work as expected.
|
||||
#
|
||||
# Shell: POSIX compliant
|
||||
# Author: Arun Prakash Jana
|
||||
|
||||
nnn -p /tmp/picked
|
||||
|
||||
if [ -f /tmp/picked ]; then
|
||||
tr '\0' '\n' < /tmp/picked
|
||||
rm /tmp/picked
|
||||
fi
|
|
@ -2,33 +2,32 @@
|
|||
|
||||
# Description: tabbed/xembed based file previewer
|
||||
#
|
||||
# Note: This plugin needs a "NNN_FIFO" to work. See man.
|
||||
#
|
||||
# Dependencies:
|
||||
# - tabbed (https://tools.suckless.org/tabbed): xembed host
|
||||
# - xterm (or urxvt or st) : xembed client for text-based preview
|
||||
# - mpv (https://mpv.io): xembed client for video/audio
|
||||
# - sxiv (https://github.com/muennich/sxiv): xembed client for images
|
||||
# - zathura (https://pwmt.org/projects/zathura): xembed client for PDF documents
|
||||
# - nnn's nuke plugin for text preview and fallback (should be in plugins directory)
|
||||
# nuke is a fallback for 'mpv', 'sxiv', and 'zathura', but it has has its own
|
||||
# dependencies, see the script itself
|
||||
# - vim (or any editor/pager really)
|
||||
# - file
|
||||
# - mktemp
|
||||
# - xdotool (optional, to keep main window focused)
|
||||
# - tabbed (https://tools.suckless.org/tabbed): xembed host
|
||||
# - xterm (or urxvt or st or alacritty) : xembed client for text-based preview
|
||||
# - mpv (https://mpv.io): xembed client for video/audio
|
||||
# - sxiv (https://github.com/muennich/sxiv) or,
|
||||
# - nsxiv (https://codeberg.org/nsxiv/nsxiv) : xembed client for images
|
||||
# - zathura (https://pwmt.org/projects/zathura): xembed client for PDF
|
||||
# - nnn's nuke plugin for text preview and fallback
|
||||
# nuke is a fallback for 'mpv', 'sxiv'/'nsxiv', and 'zathura', but has its
|
||||
# own dependencies, see the script for more information
|
||||
# - vim (or any editor/pager really)
|
||||
# - file
|
||||
# - mktemp
|
||||
# - xdotool (optional, to keep main window focused)
|
||||
#
|
||||
# How to use:
|
||||
# First, install the dependencies. Then you need to set a NNN_FIFO path
|
||||
# and set a key for the plugin, then start `nnn`:
|
||||
# Usage:
|
||||
# - Install the dependencies. Then set a NNN_FIFO
|
||||
# and set a key for the plugin, then start `nnn`:
|
||||
# $ NNN_FIFO=/tmp/nnn.fifo nnn
|
||||
# - Launch the plugin with the designated key from nnn
|
||||
#
|
||||
# $ NNN_FIFO=/tmp/nnn.fifo nnn
|
||||
#
|
||||
# Then in `nnn`, launch the `preview-tabbed` plugin.
|
||||
#
|
||||
# If you provide the same NNN_FIFO to all nnn instances, there will be a
|
||||
# single common preview window. I you provide different FIFO path, they
|
||||
# will be independent.
|
||||
# Notes:
|
||||
# 1. This plugin needs a "NNN_FIFO" to work. See man.
|
||||
# 2. If the same NNN_FIFO is used in multiple nnn instances, there will be one
|
||||
# common preview window. With different FIFO paths, they will be independent.
|
||||
# 3. This plugin only works on X, not on Wayland.
|
||||
#
|
||||
# How it works:
|
||||
# We use `tabbed` [1] as a xembed [2] host, to have a single window
|
||||
|
@ -38,14 +37,14 @@
|
|||
# provided for `urxvt` and `st`). For graphic preview this can be trickier,
|
||||
# but a few popular viewers are xembed-able, we use:
|
||||
# - `mpv`: multimedia player, for video/audio preview
|
||||
# - `sxiv`: image viewer
|
||||
# - `sxiv`/`nsxiv`: image viewer
|
||||
# - `zathura`: PDF viewer
|
||||
# - but we always fallback to `nuke` plugin
|
||||
#
|
||||
# [1]: https://tools.suckless.org/tabbed/
|
||||
# [2]: https://specifications.freedesktop.org/xembed-spec/xembed-spec-latest.html
|
||||
#
|
||||
# Shell: bash (job control is weakly specified in POSIX)
|
||||
# Shell: Bash (job control is weakly specified in POSIX)
|
||||
# Author: Léo Villeveygoux
|
||||
|
||||
|
||||
|
@ -53,17 +52,26 @@ XDOTOOL_TIMEOUT=2
|
|||
PAGER=${PAGER:-"vim -R"}
|
||||
NUKE="${XDG_CONFIG_HOME:-$HOME/.config}/nnn/plugins/nuke"
|
||||
|
||||
if [ -n "$WAYLAND_DISPLAY" ] ; then
|
||||
echo "Wayland is not supported in preview-tabbed, this plugin could freeze your session!" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if which xterm >/dev/null 2>&1 ; then
|
||||
if type xterm >/dev/null 2>&1 ; then
|
||||
TERMINAL="xterm -into"
|
||||
elif which urxvt >/dev/null 2>&1 ; then
|
||||
elif type urxvt >/dev/null 2>&1 ; then
|
||||
TERMINAL="urxvt -embed"
|
||||
elif which st >/dev/null 2>&1 ; then
|
||||
elif type st >/dev/null 2>&1 ; then
|
||||
TERMINAL="st -w"
|
||||
elif type alacritty >/dev/null 2>&1 ; then
|
||||
TERMINAL="alacritty --embed"
|
||||
else
|
||||
echo "No xembed term found" >&2
|
||||
fi
|
||||
|
||||
if type xdg-user-dir >/dev/null 2>&1 ; then
|
||||
PICTURES_DIR=$(xdg-user-dir PICTURES)
|
||||
fi
|
||||
|
||||
term_nuke () {
|
||||
# $1 -> $XID, $2 -> $FILE
|
||||
|
@ -87,7 +95,7 @@ start_tabbed () {
|
|||
|
||||
read -r XID < "$FIFO"
|
||||
|
||||
rm "$FIFO"
|
||||
rm -- "$FIFO"
|
||||
}
|
||||
|
||||
get_viewer_pid () {
|
||||
|
@ -138,39 +146,51 @@ previewer_loop () {
|
|||
|
||||
kill_viewer
|
||||
|
||||
MIME="$(file -b --mime-type "$FILE")"
|
||||
MIME="$(file -bL --mime-type "$FILE")"
|
||||
|
||||
case "$MIME" in
|
||||
video/*)
|
||||
if which mpv >/dev/null 2>&1 ; then
|
||||
if type mpv >/dev/null 2>&1 ; then
|
||||
mpv --force-window=immediate --loop-file --wid="$XID" "$FILE" &
|
||||
else
|
||||
term_nuke "$XID" "$FILE"
|
||||
fi
|
||||
;;
|
||||
audio/*)
|
||||
if which mpv >/dev/null 2>&1 ; then
|
||||
if type mpv >/dev/null 2>&1 ; then
|
||||
mpv --force-window=immediate --loop-file --wid="$XID" "$FILE" &
|
||||
else
|
||||
term_nuke "$XID" "$FILE"
|
||||
fi
|
||||
;;
|
||||
image/*)
|
||||
if which sxiv >/dev/null 2>&1 ; then
|
||||
sxiv -e "$XID" "$FILE" &
|
||||
if type sxiv >/dev/null 2>&1 ; then
|
||||
sxiv -ae "$XID" "$FILE" &
|
||||
elif type nsxiv >/dev/null 2>&1 ; then
|
||||
nsxiv -ae "$XID" "$FILE" &
|
||||
else
|
||||
term_nuke "$XID" "$FILE"
|
||||
fi
|
||||
;;
|
||||
application/pdf)
|
||||
if which zathura >/dev/null 2>&1 ; then
|
||||
if type zathura >/dev/null 2>&1 ; then
|
||||
zathura -e "$XID" "$FILE" &
|
||||
else
|
||||
term_nuke "$XID" "$FILE"
|
||||
fi
|
||||
;;
|
||||
inode/directory)
|
||||
$TERMINAL "$XID" -e nnn "$FILE" &
|
||||
if [[ -n $PICTURES_DIR && "$FILE" == "$PICTURES_DIR"* ]] ; then
|
||||
if type sxiv >/dev/null 2>&1 ; then
|
||||
sxiv -te "$XID" "$FILE" &
|
||||
elif type nsxiv >/dev/null 2>&1 ; then
|
||||
nsxiv -te "$XID" "$FILE" &
|
||||
else
|
||||
$TERMINAL "$XID" -e nnn "$FILE" &
|
||||
fi
|
||||
else
|
||||
$TERMINAL "$XID" -e nnn "$FILE" &
|
||||
fi
|
||||
;;
|
||||
text/*)
|
||||
if [ -x "$NUKE" ] ; then
|
||||
|
|
|
@ -1,32 +1,50 @@
|
|||
#!/usr/bin/env sh
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Description: Terminal based file previewer
|
||||
#
|
||||
# Note: This plugin needs a "NNN_FIFO" to work. See man.
|
||||
# For a more extended version of this script, including ueberzug support, see preview-tui-ext.
|
||||
#
|
||||
# Dependencies:
|
||||
# - Supports 3 independent methods to preview with:
|
||||
# - tmux (>=3.0), or
|
||||
# - kitty with allow_remote_control on, or
|
||||
# - $TERMINAL set to a terminal (it's xterm by default).
|
||||
# - less or $PAGER
|
||||
# - tree or exa or ls
|
||||
# - mediainfo or file
|
||||
# - mktemp
|
||||
# - unzip
|
||||
# - tar
|
||||
# - man
|
||||
# - optional: bat for code syntax highlighting
|
||||
# - optional: ueberzug, kitty terminal, viu or catimg for images.
|
||||
# - optional: scope.sh file viewer from ranger.
|
||||
# To use:
|
||||
# 1. drop scope.sh executable in $PATH
|
||||
# 2. set/export $USE_SCOPE as 1
|
||||
# - optional: pistol file viewer (https://github.com/doronbehar/pistol).
|
||||
# To use:
|
||||
# 1. install pistol
|
||||
# 2. set/export $USE_PISTOL as 1
|
||||
# - Supports 6 independent methods to preview with:
|
||||
# - tmux (>=3.0), or
|
||||
# - kitty with allow_remote_control and listen_on set in kitty.conf, or
|
||||
# - wezterm (https://wezfurlong.org/wezterm), or
|
||||
# - QuickLook on WSL (https://github.com/QL-Win/QuickLook), or
|
||||
# - Windows Terminal (https://github.com/Microsoft/Terminal | https://aka.ms/terminal) with WSL, or
|
||||
# - $NNN_TERMINAL set to a terminal (it's xterm by default).
|
||||
# - less or $NNN_PAGER
|
||||
# - tree or exa/eza or (GNU) ls
|
||||
# - mediainfo or file
|
||||
# - mktemp
|
||||
# - unzip
|
||||
# - tar
|
||||
# - man
|
||||
# - optional: bsdtar or atool for additional archive preview
|
||||
# - optional: bat for code syntax highlighting
|
||||
# - optional: ueberzug, kitty terminal, wezterm terminal, img2sixel, viu, catimg or chafa for images
|
||||
# - optional: convert(ImageMagick) for playing gif preview (mandatory for kitty image previews)
|
||||
# - optional: mpv for gif and video
|
||||
# Also requires a terminal supporting the sixel (https://www.arewesixelyet.com/)
|
||||
# or kitty (https://sw.kovidgoyal.net/kitty/graphics-protocol) video_output backends.
|
||||
# Requires tmux compiled with `./configure --enable-sixel` if used.
|
||||
# - optional: ffmpegthumbnailer for video thumbnails (https://github.com/dirkvdb/ffmpegthumbnailer)
|
||||
# - optional: ffmpeg for audio thumbnails
|
||||
# - optional: libreoffce for opendocument/officedocument preview
|
||||
# - optional: pdftoppm(poppler) for pdf thumbnails
|
||||
# - optional: gnome-epub-thumbnailer for epub thumbnails (https://gitlab.gnome.org/GNOME/gnome-epub-thumbnailer)
|
||||
# - optional: fontpreview for font preview (https://github.com/sdushantha/fontpreview)
|
||||
# - optional: djvulibre for djvu
|
||||
# - optional: glow or lowdown for markdown
|
||||
# - optional: w3m or lynx or elinks for html
|
||||
# - optional: set/export NNN_ICONLOOKUP as 1 to enable file icons in front of directory previews with .iconlookup
|
||||
# Icons and colors are configurable in .iconlookup
|
||||
# - optional: scope.sh file viewer from ranger.
|
||||
# 1. drop scope.sh executable in $PATH
|
||||
# 2. set/export $NNN_SCOPE as 1
|
||||
# - optional: pistol file viewer (https://github.com/doronbehar/pistol).
|
||||
# 1. install pistol
|
||||
# 2. set/export $NNN_PISTOL as 1
|
||||
# - optional: librsvg for rsvg-convert
|
||||
#
|
||||
# Usage:
|
||||
# You need to set a NNN_FIFO path and a key for the plugin with NNN_PLUG,
|
||||
|
@ -38,7 +56,7 @@
|
|||
#
|
||||
# $ NNN_FIFO=/tmp/nnn.fifo nnn
|
||||
#
|
||||
# Then in `nnn`, launch the `preview-tui` plugin.
|
||||
# Then launch the `preview-tui` plugin in `nnn`.
|
||||
#
|
||||
# If you provide the same NNN_FIFO to all nnn instances, there will be a
|
||||
# single common preview window. If you provide different FIFO path (e.g.
|
||||
|
@ -46,231 +64,475 @@
|
|||
#
|
||||
# The previews will be shown in a tmux split. If that isn't possible, it
|
||||
# will try to use a kitty terminal split. And as a final fallback, a
|
||||
# different terminal window will be used ($TERMINAL).
|
||||
# different terminal window will be used ($NNN_TERMINAL).
|
||||
#
|
||||
# Tmux and kitty users can configure $SPLIT to either "h" or "v" to set a
|
||||
# 'h'orizontal split or a 'v'ertical split (as in, the line that splits the
|
||||
# windows will be horizontal or vertical).
|
||||
# Kitty users need something similar to the following in their kitty.conf:
|
||||
# - `allow_remote_control yes`
|
||||
# - `listen_on unix:$TMPDIR/kitty`
|
||||
# - `enabled_layouts splits` (optional)
|
||||
# With ImageMagick installed, this terminal can use the icat kitten to display images.
|
||||
# Refer to kitty documentation for further details.
|
||||
#
|
||||
# Kitty users need `allow_remote_control` set to `yes`. To customize the
|
||||
# window split, `enabled_layouts` has to be set to `all` or `splits` (the
|
||||
# former is the default value). This terminal is also able to show images
|
||||
# without extra dependencies.
|
||||
# Users with both tmux and kitty can leverage image previews inside tmux with kitty's icat kitten
|
||||
# - setup kitty as stated above
|
||||
# - tmux >= v3.3a required
|
||||
# - add the following to your tmux.conf:
|
||||
# - `set -g allow-passthrough on`
|
||||
#
|
||||
# Shell: POSIX compliant
|
||||
# Authors: Todd Yamakawa, Léo Villeveygoux, @Recidiviste, Mario Ortiz Manero
|
||||
# Wezterm should work out of the box. If `NNN_PREVIEWIMGPROG` is not specified it will use
|
||||
# built in iTerm2 image protocol.
|
||||
#
|
||||
# Note that GNU ls is used for its `--group-directories-first` flag.
|
||||
# On MacOS this may be installed with `brew install coreutils`, or the flag can be removed.
|
||||
# iTerm2 users are recommended to use viu to view images without getting pixelated.
|
||||
#
|
||||
# Windows Terminal users can set "Profile termination behavior" under "Profile > Advanced" settings
|
||||
# to automatically close pane on quit when exit code is 0.
|
||||
#
|
||||
# When specifying a different terminal, additional arguments are supported. In particular, you can
|
||||
# append a specific title to the terminal and set it to "nofocus" in your WM config.
|
||||
# E.g for alacritty and i3, you can set $NNN_TERMINAL to 'alacritty --title preview-tui' and add
|
||||
# 'no_focus [title="preview-tui"]' to your i3 config file.
|
||||
#
|
||||
# Shell: Bash (for environment manipulation through arrays)
|
||||
# Authors: Todd Yamakawa, Léo Villeveygoux, @Recidiviste, Mario Ortiz Manero, Luuk van Baal, @WanderLanz, @flipflop133
|
||||
|
||||
SPLIT="$SPLIT" # you can set a permanent split here
|
||||
TERMINAL="$TERMINAL" # same goes for the terminal
|
||||
USE_SCOPE="${USE_SCOPE:-0}"
|
||||
USE_PISTOL="${USE_PISTOL:-0}"
|
||||
PAGER="${PAGER:-less -R}"
|
||||
TMPDIR="${TMPDIR:-/tmp}"
|
||||
[ "$PAGER" = "most" ] && PAGER="less -R"
|
||||
# Configurable environment variables:
|
||||
NNN_SPLIT=${NNN_SPLIT:-} # permanent split direction
|
||||
NNN_TERMINAL=${NNN_TERMINAL:-} # external terminal to be used
|
||||
NNN_SPLITSIZE=${NNN_SPLITSIZE:-50} # previewer split size percentage
|
||||
TMPDIR=${TMPDIR:-/tmp} # location of temporary files
|
||||
ENVVARS=(
|
||||
"NNN_SCOPE=${NNN_SCOPE:-0}" # use scope
|
||||
"NNN_PISTOL=${NNN_PISTOL:-0}" # use pistol
|
||||
"NNN_ICONLOOKUP=${NNN_ICONLOOKUP:-0}" # use .iconlookup
|
||||
"NNN_PAGER=${NNN_PAGER:-less -P?n -R -C}" # pager options
|
||||
"NNN_BATTHEME=${NNN_BATTHEME:-ansi}" # bat theme
|
||||
"NNN_BATSTYLE=${NNN_BATSTYLE:-numbers}" # bat style
|
||||
"NNN_PREVIEWWIDTH=${NNN_PREVIEWWIDTH:-1920}" # width of generated preview images
|
||||
"NNN_PREVIEWHEIGHT=${NNN_PREVIEWHEIGHT:-1080}" # height of generated preview images
|
||||
"NNN_PREVIEWDIR=${NNN_PREVIEWDIR:-$TMPDIR/nnn/previews}" # location of generated preview images
|
||||
"NNN_PREVIEWIMGPROG=${NNN_PREVIEWIMGPROG:-}" # program used to preview images
|
||||
"NNN_PREVIEWVIDEO=${NNN_PREVIEWVIDEO:-}" # mpv backend used to preview video
|
||||
)
|
||||
# Non-configurable environment variables
|
||||
NNN_PARENT=${NNN_FIFO#*.}
|
||||
[ "$NNN_PARENT" -eq "$NNN_PARENT" ] 2>/dev/null || NNN_PARENT="" # Make empty if non-numeric
|
||||
ENVVARS+=(
|
||||
"PWD=$PWD"
|
||||
"PATH=$PATH"
|
||||
"NNN_FIFO=$NNN_FIFO"
|
||||
"FIFOPID=$TMPDIR/nnn-preview-tui-fifopid.$NNN_PARENT"
|
||||
"FIFOPATH=$TMPDIR/nnn-preview-tui-fifo.$NNN_PARENT"
|
||||
"PREVIEWPID=$TMPDIR/nnn-preview-tui-previewpid.$NNN_PARENT"
|
||||
"CURSEL=$TMPDIR/nnn-preview-tui-selection.$NNN_PARENT"
|
||||
"FIFO_UEBERZUG=$TMPDIR/nnn-preview-tui-ueberzug-fifo.$NNN_PARENT"
|
||||
"POSOFFSET=$TMPDIR/nnn-preview-tui-posoffset"
|
||||
)
|
||||
|
||||
if [ -e "${TMUX%%,*}" ] && tmux -V | grep -q '[ -][3456789]\.'; then
|
||||
TERMINAL=tmux
|
||||
elif [ -n "$KITTY_WINDOW_ID" ] && kitty @ ls >/dev/null 2>&1; then
|
||||
TERMINAL=kitty
|
||||
else
|
||||
TERMINAL="${TERMINAL:-xterm}"
|
||||
fi
|
||||
trap '' PIPE
|
||||
exists() { type "$1" >/dev/null 2>&1 ;}
|
||||
pkill() { command pkill "$@" >/dev/null 2>&1 ;}
|
||||
prompt() { clear; printf "%b" "$@"; cfg=$(stty -g); stty raw -echo; head -c 1; stty "$cfg" ;}
|
||||
pidkill() {
|
||||
if [ -f "$1" ]; then
|
||||
PID="$(cat "$1" 2>/dev/null)" || return 1
|
||||
kill "$PID" >/dev/null 2>&1
|
||||
RET=$?
|
||||
wait "$PID" 2>/dev/null
|
||||
return $RET
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
if [ -z "$SPLIT" ] && [ $(($(tput lines) * 2)) -gt "$(tput cols)" ]; then
|
||||
SPLIT='h'
|
||||
elif [ "$SPLIT" != 'h' ]; then
|
||||
SPLIT='v'
|
||||
fi
|
||||
start_preview() {
|
||||
if [ -e "${TMUX%%,*}" ] && tmux -V | grep -q '[ -][3456789]\.'; then
|
||||
NNN_TERMINAL=tmux
|
||||
exists mpv && tmux display -p '#{client_termfeatures}' | grep -q 'sixel' && ENVVARS+=("NNN_PREVIEWVIDEO=sixel")
|
||||
elif [ -n "$KITTY_LISTEN_ON" ]; then
|
||||
NNN_TERMINAL=kitty
|
||||
exists mpv && ENVVARS+=("NNN_PREVIEWVIDEO=kitty")
|
||||
elif [ -n "$WEZTERM_PANE" ]; then
|
||||
NNN_TERMINAL=wezterm
|
||||
exists mpv && ENVVARS+=("NNN_PREVIEWVIDEO=kitty")
|
||||
elif [ -z "$NNN_TERMINAL" ] && [ "$TERM_PROGRAM" = "iTerm.app" ]; then
|
||||
NNN_TERMINAL=iterm
|
||||
exists mpv && ENVVARS+=("NNN_PREVIEWVIDEO=sixel")
|
||||
elif [ -n "$WT_SESSION" ]; then
|
||||
NNN_TERMINAL=winterm
|
||||
else
|
||||
NNN_TERMINAL="${NNN_TERMINAL:-xterm}"
|
||||
fi
|
||||
|
||||
exists() {
|
||||
which "$1" >/dev/null 2>&1
|
||||
if [ -z "$NNN_SPLIT" ] && [ $(($(tput lines) * 2)) -gt "$(tput cols)" ]; then
|
||||
NNN_SPLIT='h'
|
||||
elif [ "$NNN_SPLIT" != 'h' ]; then
|
||||
NNN_SPLIT='v'
|
||||
fi
|
||||
|
||||
ENVVARS+=("NNN_TERMINAL=$NNN_TERMINAL" "NNN_SPLIT=$NNN_SPLIT" "QLPATH=$2" "PREVIEW_MODE=1")
|
||||
case "$NNN_TERMINAL" in
|
||||
iterm|winterm) # has to run in separate shell command: escape
|
||||
ENVVARS=("${ENVVARS[@]/#/\\\"}")
|
||||
ENVVARS=("${ENVVARS[@]/%/\\\"}")
|
||||
command="$SHELL -c 'env ${ENVVARS[*]} \\\"$0\\\" \\\"$1\\\"'" ;;
|
||||
esac
|
||||
|
||||
case "$NNN_TERMINAL" in
|
||||
tmux) # tmux splits are inverted
|
||||
ENVVARS=("${ENVVARS[@]/#/-e}")
|
||||
if [ "$NNN_SPLIT" = "v" ]; then split="h"; else split="v"; fi
|
||||
tmux split-window -l"$NNN_SPLITSIZE"% "${ENVVARS[@]}" -d"$split" -p"$NNN_SPLITSIZE" "$0" "$1" ;;
|
||||
kitty) # Setting the layout for the new window. It will be restored after the script ends.
|
||||
ENVVARS=("${ENVVARS[@]/#/--env=}")
|
||||
kitty @ goto-layout splits
|
||||
# Trying to use kitty's integrated window management as the split window.
|
||||
kitty @ launch --no-response --title "preview-tui" --keep-focus \
|
||||
--cwd "$PWD" "${ENVVARS[@]}" --location "${NNN_SPLIT}split" "$0" "$1" ;;
|
||||
wezterm)
|
||||
export "${ENVVARS[@]}"
|
||||
if [ "$NNN_SPLIT" = "v" ]; then split="--horizontal"; else split="--bottom"; fi
|
||||
wezterm cli split-pane --cwd "$PWD" $split --percent "$NNN_SPLITSIZE" "$0" "$1" >/dev/null
|
||||
wezterm cli activate-pane-direction Prev ;;
|
||||
iterm)
|
||||
if [ "$NNN_SPLIT" = "h" ]; then split="horizontally"; else split="vertically"; fi
|
||||
osascript <<-EOF
|
||||
tell application "iTerm"
|
||||
tell current session of current window
|
||||
split $split with default profile command "$command"
|
||||
end tell
|
||||
end tell
|
||||
EOF
|
||||
;;
|
||||
winterm)
|
||||
if [ "$NNN_SPLIT" = "h" ]; then split="H"; else split="V"; fi
|
||||
wt -w 0 sp -$split -s"0.$NNN_SPLITSIZE" "$command" \; -w 0 mf previous 2>/dev/null ;;
|
||||
*) if [ -n "$2" ]; then
|
||||
env "${ENVVARS[@]}" QUICKLOOK=1 "$0" "$1" &
|
||||
else
|
||||
# shellcheck disable=SC2086 # (allow arguments)
|
||||
env "${ENVVARS[@]}" $NNN_TERMINAL -e "$0" "$1" &
|
||||
fi ;;
|
||||
esac
|
||||
}
|
||||
|
||||
toggle_preview() {
|
||||
export "${ENVVARS[@]}"
|
||||
if exists QuickLook.exe; then
|
||||
QLPATH="QuickLook.exe"
|
||||
elif exists Bridge.exe; then
|
||||
QLPATH="Bridge.exe"
|
||||
fi
|
||||
if pidkill "$FIFOPID"; then
|
||||
[ -p "$NNN_PPIPE" ] && printf "0" > "$NNN_PPIPE"
|
||||
pidkill "$PREVIEWPID"
|
||||
pkill -f "tail --follow $FIFO_UEBERZUG"
|
||||
if [ -n "$QLPATH" ] && stat "$1"; then
|
||||
f="$(wslpath -w "$1")" && "$QLPATH" "$f" &
|
||||
fi
|
||||
else
|
||||
[ -p "$NNN_PPIPE" ] && printf "1" > "$NNN_PPIPE"
|
||||
start_preview "$1" "$QLPATH"
|
||||
fi
|
||||
}
|
||||
|
||||
fifo_pager() {
|
||||
cmd="$1"
|
||||
shift
|
||||
|
||||
# We use a FIFO to access $PAGER PID in jobs control
|
||||
tmpfifopath="${TMPDIR:-/tmp}/nnn-preview-tui-fifo.$$"
|
||||
mkfifo "$tmpfifopath" || return
|
||||
# We use a FIFO to access $NNN_PAGER PID in jobs control
|
||||
mkfifo "$FIFOPATH" || return
|
||||
|
||||
$PAGER < "$tmpfifopath" &
|
||||
$NNN_PAGER < "$FIFOPATH" &
|
||||
printf "%s" "$!" > "$PREVIEWPID"
|
||||
|
||||
(
|
||||
exec > "$tmpfifopath"
|
||||
"$cmd" "$@" &
|
||||
exec > "$FIFOPATH"
|
||||
if [ "$cmd" = "pager" ]; then
|
||||
if exists bat; then
|
||||
bat --terminal-width="$cols" --decorations=always --color=always \
|
||||
--paging=never --style="$NNN_BATSTYLE" --theme="$NNN_BATTHEME" "$@" &
|
||||
else
|
||||
$NNN_PAGER "$@" &
|
||||
fi
|
||||
else
|
||||
"$cmd" "$@" &
|
||||
fi
|
||||
)
|
||||
|
||||
rm "$tmpfifopath"
|
||||
rm -- "$FIFOPATH"
|
||||
}
|
||||
|
||||
# Binary file: show file info inside the pager
|
||||
print_bin_info() {
|
||||
printf -- "-------- \033[1;31mBinary file\033[0m --------\n"
|
||||
if exists mediainfo; then
|
||||
mediainfo "$1" 2>/dev/null
|
||||
mediainfo "$1"
|
||||
else
|
||||
file -b "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
preview_file () {
|
||||
kill %- %+ 2>/dev/null && wait %- %+ 2>/dev/null
|
||||
clear
|
||||
handle_mime() {
|
||||
case "$2" in
|
||||
image/jpeg) image_preview "$cols" "$lines" "$1" ;;
|
||||
image/gif) generate_preview "$cols" "$lines" "$1" "gif" ;;
|
||||
image/vnd.djvu) generate_preview "$cols" "$lines" "$1" "djvu" ;;
|
||||
image/*) generate_preview "$cols" "$lines" "$1" "image" ;;
|
||||
video/*) generate_preview "$cols" "$lines" "$1" "video" ;;
|
||||
audio/*) generate_preview "$cols" "$lines" "$1" "audio" ;;
|
||||
application/font*|application/*opentype|font/*) generate_preview "$cols" "$lines" "$1" "font" ;;
|
||||
*/*office*|*/*document*|*/*msword|*/*ms-excel) generate_preview "$cols" "$lines" "$1" "office" ;;
|
||||
application/zip) fifo_pager unzip -l "$1" ;;
|
||||
text/troff)
|
||||
if exists man; then
|
||||
fifo_pager man -Pcat -l "$1"
|
||||
else
|
||||
fifo_pager pager "$1"
|
||||
fi ;;
|
||||
*) handle_ext "$1" "$3" "$4" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
handle_ext() {
|
||||
case "$2" in
|
||||
epub) generate_preview "$cols" "$lines" "$1" "epub" ;;
|
||||
pdf) generate_preview "$cols" "$lines" "$1" "pdf" ;;
|
||||
gz|bz2) fifo_pager tar -tvf "$1" ;;
|
||||
md) if exists glow; then
|
||||
fifo_pager glow -s dark "$1"
|
||||
elif exists lowdown; then
|
||||
fifo_pager lowdown -Tterm "$1"
|
||||
else
|
||||
fifo_pager pager "$1"
|
||||
fi ;;
|
||||
htm|html|xhtml)
|
||||
if exists w3m; then
|
||||
fifo_pager w3m "$1"
|
||||
elif exists lynx; then
|
||||
fifo_pager lynx "$1"
|
||||
elif exists elinks; then
|
||||
fifo_pager elinks "$1"
|
||||
else
|
||||
fifo_pager pager "$1"
|
||||
fi ;;
|
||||
7z|a|ace|alz|arc|arj|bz|cab|cpio|deb|jar|lha|lz|lzh|lzma|lzo\
|
||||
|rar|rpm|rz|t7z|tar|tbz|tbz2|tgz|tlz|txz|tZ|tzo|war|xpi|xz|Z)
|
||||
if exists atool; then
|
||||
fifo_pager atool -l "$1"
|
||||
elif exists bsdtar; then
|
||||
fifo_pager bsdtar -tvf "$1"
|
||||
fi ;;
|
||||
*) if [ "$3" = "bin" ]; then
|
||||
fifo_pager print_bin_info "$1"
|
||||
else
|
||||
fifo_pager pager "$1"
|
||||
fi ;;
|
||||
esac
|
||||
}
|
||||
|
||||
preview_file() {
|
||||
clear
|
||||
# Trying to use pistol if it's available.
|
||||
if [ "$USE_PISTOL" -ne 0 ] && exists pistol; then
|
||||
if [ "$NNN_PISTOL" -ne 0 ] && exists pistol; then
|
||||
fifo_pager pistol "$1"
|
||||
return
|
||||
fi
|
||||
|
||||
# Trying to use scope.sh if it's available.
|
||||
if [ "$USE_SCOPE" -ne 0 ] && exists scope.sh; then
|
||||
fifo_pager scope.sh "$1" "$cols" "$lines" "$(mktemp -d)" \
|
||||
"True" 2>/dev/null
|
||||
if [ "$NNN_SCOPE" -ne 0 ] && exists scope.sh; then
|
||||
fifo_pager scope.sh "$1" "$cols" "$lines" "$(mktemp -d)" "True"
|
||||
return
|
||||
fi
|
||||
|
||||
# Detecting the exact type of the file: the encoding, mime type, and
|
||||
# extension in lowercase.
|
||||
encoding="$(file -Lb --mime-encoding -- "$1")"
|
||||
mimetype="$(file -Lb --mime-type -- "$1")"
|
||||
ext="${1##*.}"
|
||||
if [ -n "$ext" ]; then
|
||||
ext="$(printf "%s" "${ext}" | tr '[:upper:]' '[:lower:]')"
|
||||
# Use QuickLook if it's available.
|
||||
if [ -n "$QUICKLOOK" ]; then
|
||||
stat "$1" && f="$(wslpath -w "$1")" && "$QLPATH" "$f" &
|
||||
return
|
||||
fi
|
||||
lines=$(($(tput lines)-1))
|
||||
|
||||
# Detecting the exact type of the file: the encoding, mime type, and extension in lowercase.
|
||||
encoding="$(file -bL --mime-encoding -- "$1")"
|
||||
mimetype="$(file -bL --mime-type -- "$1")"
|
||||
ext="${1##*.}"
|
||||
[ -n "$ext" ] && ext="$(printf "%s" "${ext}" | tr '[:upper:]' '[:lower:]')"
|
||||
lines=$(tput lines)
|
||||
cols=$(tput cols)
|
||||
|
||||
# Otherwise, falling back to the defaults.
|
||||
if [ -d "$1" ]; then
|
||||
cd "$1" || return
|
||||
if exists tree; then
|
||||
fifo_pager tree -L 3 -F
|
||||
if [ "$NNN_ICONLOOKUP" -ne 0 ] && [ -f "$(dirname "$0")"/.iconlookup ]; then
|
||||
[ "$NNN_SPLIT" = v ] && BSTR="\n"
|
||||
# shellcheck disable=SC2012
|
||||
ls -F --group-directories-first | head -n "$((lines - 3))" | "$(dirname "$0")"/.iconlookup -l "$cols" -B "$BSTR" -b " "
|
||||
elif exists tree; then
|
||||
fifo_pager tree --filelimit "$(find . -maxdepth 1 | wc -l)" -L 3 -C -F --dirsfirst --noreport
|
||||
elif exists exa; then
|
||||
fifo_pager exa -G --colour=always 2>/dev/null
|
||||
fifo_pager exa -T --group-directories-first --colour=always -L 3
|
||||
elif exists eza; then # eza is a community fork of exa (exa is unmaintained)
|
||||
fifo_pager eza -T --group-directories-first --colour=always -L 3
|
||||
else
|
||||
fifo_pager ls --color=always
|
||||
fifo_pager ls -F --group-directories-first --color=always
|
||||
fi
|
||||
elif [ "$encoding" = "binary" ]; then
|
||||
if [ "${mimetype%%/*}" = "image" ]; then
|
||||
image_preview "$cols" "$lines" "$1"
|
||||
elif [ "$mimetype" = "application/zip" ]; then
|
||||
fifo_pager unzip -l "$1"
|
||||
elif [ "$ext" = "gz" ] || [ "$ext" = "bz2" ]; then
|
||||
fifo_pager tar -tvf "$1"
|
||||
else
|
||||
fifo_pager print_bin_info "$1"
|
||||
fi
|
||||
elif [ "$mimetype" = "text/troff" ]; then
|
||||
fifo_pager man -Pcat -l "$1"
|
||||
cd ..
|
||||
elif [ "${encoding#*)}" = "binary" ]; then
|
||||
handle_mime "$1" "$mimetype" "$ext" "bin"
|
||||
else
|
||||
if exists bat; then
|
||||
fifo_pager bat --terminal-width="$cols" --paging=never --decorations=always --color=always \
|
||||
"$1" 2>/dev/null
|
||||
else
|
||||
$PAGER "$1" &
|
||||
fi
|
||||
handle_mime "$1" "$mimetype" "$ext"
|
||||
fi
|
||||
}
|
||||
|
||||
image_preview() {
|
||||
if [ "$TERMINAL" = "kitty" ]; then
|
||||
# Kitty terminal users can use the native image preview method.
|
||||
kitty +kitten icat --silent --place "$1"x"$2"@0x0 --transfer-mode=stream --stdin=no \
|
||||
"$3"
|
||||
elif exists ueberzug; then
|
||||
ueberzug_layer "$1" "$2" "$3"
|
||||
elif exists catimg; then
|
||||
catimg "$3" &
|
||||
gifpid="$!"
|
||||
elif exists viu; then
|
||||
viu -t "$3" &
|
||||
gifpid="$!"
|
||||
else
|
||||
fifo_pager print_bin_info "$1"
|
||||
generate_preview() {
|
||||
if [ -n "$QLPATH" ] && stat "$3"; then
|
||||
f="$(wslpath -w "$3")" && "$QLPATH" "$f" &
|
||||
elif [ -n "$NNN_PREVIEWVIDEO" ] && [[ "$4" == +(gif|video) ]]; then
|
||||
[ "$4" = "video" ] && args=(--start=10% --length=4) || args=()
|
||||
video_preview "$1" "$2" "$3" "${args[@]}" && return
|
||||
elif [ ! -f "$NNN_PREVIEWDIR/$3.jpg" ] || [ -n "$(find -L "$3" -newer "$NNN_PREVIEWDIR/$3.jpg")" ]; then
|
||||
mkdir -p "$NNN_PREVIEWDIR/${3%/*}"
|
||||
case $4 in
|
||||
audio) ffmpeg -i "$3" -filter_complex "scale=iw*min(1\,min($NNN_PREVIEWWIDTH/iw\,ih)):-1" "$NNN_PREVIEWDIR/$3.jpg" -y ;;
|
||||
epub) gnome-epub-thumbnailer "$3" "$NNN_PREVIEWDIR/$3.jpg" ;;
|
||||
font) fontpreview -i "$3" -o "$NNN_PREVIEWDIR/$3.jpg" ;;
|
||||
gif) if [ -p "$FIFO_UEBERZUG" ] && exists convert; then
|
||||
frameprefix="$NNN_PREVIEWDIR/$3/${3##*/}"
|
||||
if [ ! -d "$NNN_PREVIEWDIR/$3" ]; then
|
||||
mkdir -p "$NNN_PREVIEWDIR/$3"
|
||||
convert -coalesce -resize "$NNN_PREVIEWWIDTH"x"$NNN_PREVIEWHEIGHT"\> "$3" "$frameprefix.jpg" ||
|
||||
MAGICK_TMPDIR="/tmp" convert -coalesce -resize "$NNN_PREVIEWWIDTH"x"$NNN_PREVIEWHEIGHT"\> "$3" "$frameprefix.jpg"
|
||||
fi
|
||||
frames=$(($(find "$NNN_PREVIEWDIR/$3" | wc -l) - 2))
|
||||
[ $frames -lt 0 ] && return
|
||||
while true; do
|
||||
for i in $(seq 0 $frames); do
|
||||
image_preview "$1" "$2" "$frameprefix-$i.jpg"
|
||||
sleep 0.1
|
||||
done
|
||||
done &
|
||||
printf "%s" "$!" > "$PREVIEWPID"
|
||||
return
|
||||
elif [ -n "$NNN_PREVIEWVIDEO" ]; then
|
||||
video_preview "$1" "$2" "$3" && return
|
||||
else
|
||||
image_preview "$1" "$2" "$3" && return
|
||||
fi ;;
|
||||
image) if exists rsvg-convert && [[ "${3##*.}" == "svg" ]]; then
|
||||
rsvg-convert -a -w "$NNN_PREVIEWWIDTH" -h "$NNN_PREVIEWHEIGHT" -f png -o "$NNN_PREVIEWDIR/$3.png" "$3"
|
||||
elif exists convert; then
|
||||
convert "$3" -flatten -resize "$NNN_PREVIEWWIDTH"x"$NNN_PREVIEWHEIGHT"\> "$NNN_PREVIEWDIR/$3.jpg"
|
||||
else
|
||||
image_preview "$1" "$2" "$3" && return
|
||||
fi ;;
|
||||
office) libreoffice --convert-to jpg "$3" --outdir "$NNN_PREVIEWDIR/${3%/*}"
|
||||
filename="$(printf "%s" "${3##*/}" | cut -d. -f1)"
|
||||
mv -- "$NNN_PREVIEWDIR/${3%/*}/$filename.jpg" "$NNN_PREVIEWDIR/$3.jpg" ;;
|
||||
pdf) pdftoppm -jpeg -f 1 -singlefile "$3" "$NNN_PREVIEWDIR/$3" ;;
|
||||
djvu) ddjvu -format=ppm -page=1 "$3" "$NNN_PREVIEWDIR/$3.jpg" ;;
|
||||
video) video_preview "$1" "$2" "$3" && return ;;
|
||||
esac
|
||||
fi
|
||||
if [ -f "$NNN_PREVIEWDIR/$3.jpg" ]; then
|
||||
image_preview "$1" "$2" "$NNN_PREVIEWDIR/$3.jpg"
|
||||
elif [[ "${3##*.}" == "svg" ]] && [ -f "$NNN_PREVIEWDIR/$3.png" ]; then
|
||||
image_preview "$1" "$2" "$NNN_PREVIEWDIR/$3.png"
|
||||
else
|
||||
fifo_pager print_bin_info "$3"
|
||||
fi
|
||||
} >/dev/null 2>&1
|
||||
|
||||
image_preview() {
|
||||
clear
|
||||
exec >/dev/tty
|
||||
if [ "$NNN_TERMINAL" = "kitty" ] && [[ "$NNN_PREVIEWIMGPROG" == +(|icat) ]]; then
|
||||
kitty +kitten icat --silent --scale-up --place "$1"x"$2"@0x0 --transfer-mode=stream --stdin=no "$3" &
|
||||
elif [ "$NNN_TERMINAL" = "tmux" ] && [[ -n "$KITTY_LISTEN_ON" ]] && [[ "$NNN_PREVIEWIMGPROG" == +(|icat) ]]; then
|
||||
kitty +kitten icat --silent --scale-up --place "$(($1 - 1))x$(($2 - 1))"@0x0 --transfer-mode=memory --stdin=no "$3" &
|
||||
elif [ "$NNN_TERMINAL" = "wezterm" ] && [[ "$NNN_PREVIEWIMGPROG" == +(|imgcat) ]]; then
|
||||
wezterm imgcat "$3" &
|
||||
elif exists ueberzug && [[ "$NNN_PREVIEWIMGPROG" == +(|ueberzug) ]]; then
|
||||
ueberzug_layer "$1" "$2" "$3" && return
|
||||
elif exists catimg && [[ "$NNN_PREVIEWIMGPROG" == +(|catimg) ]]; then
|
||||
catimg "$3" &
|
||||
elif exists viu && [[ "$NNN_PREVIEWIMGPROG" == +(|viu) ]]; then
|
||||
viu -t "$3" &
|
||||
elif exists chafa && [[ "$NNN_PREVIEWIMGPROG" == +(|chafa) ]]; then
|
||||
chafa "$3" &
|
||||
elif exists img2sixel && [[ "$NNN_PREVIEWIMGPROG" == +(|img2sixel) ]]; then
|
||||
img2sixel -g "$3" &
|
||||
else
|
||||
fifo_pager print_bin_info "$3" && return
|
||||
fi
|
||||
printf "%s" "$!" > "$PREVIEWPID"
|
||||
}
|
||||
|
||||
video_preview() {
|
||||
clear
|
||||
exec >/dev/tty
|
||||
if [ -n "$NNN_PREVIEWVIDEO" ]; then
|
||||
mpv --no-config --really-quiet --vo="$NNN_PREVIEWVIDEO" --profile=sw-fast --loop-file --no-audio "$4" "$3" &
|
||||
else
|
||||
ffmpegthumbnailer -m -s0 -i "$3" -o "$NNN_PREVIEWDIR/$3.jpg" || rm -- "$NNN_PREVIEWDIR/$3.jpg" &
|
||||
fi
|
||||
printf "%s" "$!" > "$PREVIEWPID"
|
||||
}
|
||||
|
||||
ueberzug_layer() {
|
||||
printf '{"action": "add", "identifier": "nnn_ueberzug", "x": 0, "y": 0, "width": "%s", "height": "%s", "path": "%s"}\n' "$1" "$2" "$3" > "$FIFO_UEBERZUG"
|
||||
[ -f "$POSOFFSET" ] && read -r x y < "$POSOFFSET"
|
||||
printf '{"action": "add", "identifier": "nnn_ueberzug", "x": %d, "y": %d, "width": "%d", "height": "%d", "scaler": "fit_contain", "path": "%s"}\n'\
|
||||
"${x:-0}" "${y:-0}" "$1" "$2" "$3" > "$FIFO_UEBERZUG"
|
||||
}
|
||||
|
||||
ueberzug_remove() {
|
||||
printf '{"action": "remove", "identifier": "nnn_ueberzug"}\n' > "$FIFO_UEBERZUG"
|
||||
}
|
||||
|
||||
ueberzug_refresh() {
|
||||
winch_handler() {
|
||||
clear
|
||||
pkill -P "$$"
|
||||
pkill -f -n preview-tui
|
||||
echo > "$NNN_FIFO"
|
||||
tail --follow "$FIFO_UEBERZUG" | ueberzug layer --silent --parser json &
|
||||
preview_fifo &
|
||||
wait
|
||||
pidkill "$PREVIEWPID"
|
||||
if [ -p "$FIFO_UEBERZUG" ]; then
|
||||
pkill -f "tail --follow $FIFO_UEBERZUG"
|
||||
tail --follow "$FIFO_UEBERZUG" | ueberzug layer --silent --parser json &
|
||||
fi
|
||||
preview_file "$(cat "$CURSEL")"
|
||||
}
|
||||
if [ "$TERMINAL" != "kitty" ] && [ "$PREVIEW_MODE" ] && exists ueberzug; then
|
||||
trap 'ueberzug_refresh' WINCH
|
||||
trap 'rm "$FIFO_UEBERZUG"' INT HUP EXIT
|
||||
fi
|
||||
|
||||
preview_fifo() {
|
||||
# use cat instead of 'exec <' to avoid issues with dash shell
|
||||
# shellcheck disable=SC2002
|
||||
cat "$NNN_FIFO" |\
|
||||
while read -r selection; do
|
||||
[ "$gifpid" -ne 0 ] && kill "$gifpid"
|
||||
[ "$TERMINAL" != "kitty" ] && exists ueberzug && ueberzug_remove
|
||||
preview_file "$selection"
|
||||
done
|
||||
[ "$TERMINAL" != "kitty" ] && exists ueberzug && rm "$FIFO_UEBERZUG"
|
||||
if [ -n "$selection" ]; then
|
||||
pidkill "$PREVIEWPID"
|
||||
[ -p "$FIFO_UEBERZUG" ] && ueberzug_remove
|
||||
[ "$selection" = "close" ] && break
|
||||
preview_file "$selection"
|
||||
printf "%s" "$selection" > "$CURSEL"
|
||||
fi
|
||||
done < "$NNN_FIFO"
|
||||
sleep 0.1 # make sure potential preview by winch_handler is killed
|
||||
pkill -P "$$"
|
||||
}
|
||||
|
||||
if [ "$PREVIEW_MODE" ]; then
|
||||
if [ ! -r "$NNN_FIFO" ]; then
|
||||
echo "No FIFO available! (\$NNN_FIFO='$NNN_FIFO')" >&2
|
||||
read -r
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$TERMINAL" != "kitty" ] && exists ueberzug; then
|
||||
FIFO_UEBERZUG="$TMPDIR/nnn-ueberzug-fifo.$$"
|
||||
if [ "$PREVIEW_MODE" -eq 1 ] 2>/dev/null; then
|
||||
if exists ueberzug && [ "$NNN_TERMINAL" != "kitty" ] && [[ "$NNN_PREVIEWIMGPROG" == +(|ueberzug) ]]; then
|
||||
mkfifo "$FIFO_UEBERZUG"
|
||||
tail --follow "$FIFO_UEBERZUG" | ueberzug layer --silent --parser json &
|
||||
fi
|
||||
|
||||
preview_file "$1"
|
||||
preview_fifo &
|
||||
wait
|
||||
|
||||
# Restoring the previous layout for kitty users. This will only work for
|
||||
# kitty >= 0.18.0.
|
||||
if [ "$TERMINAL" = "kitty" ]; then
|
||||
kitty @ last-used-layout --no-response >/dev/null 2>&1
|
||||
fi
|
||||
|
||||
preview_file "$PWD/$1"
|
||||
preview_fifo & WAITPID=$!
|
||||
printf "%s" "$!" > "$FIFOPID"
|
||||
printf "%s" "$PWD/$1" > "$CURSEL"
|
||||
trap 'winch_handler' WINCH
|
||||
trap 'rm -- "$PREVIEWPID" "$CURSEL" "$FIFO_UEBERZUG" "$FIFOPID" "$POSOFFSET" 2>/dev/null' INT HUP EXIT
|
||||
while kill -s 0 $WAITPID; do
|
||||
wait $WAITPID 2>/dev/null
|
||||
done
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$TERMINAL" = "tmux" ]; then
|
||||
# tmux splits are inverted
|
||||
if [ "$SPLIT" = "v" ]; then SPLIT="h"; else SPLIT="v"; fi
|
||||
|
||||
tmux split-window -e "NNN_FIFO=$NNN_FIFO" -e "PREVIEW_MODE=1" -d"$SPLIT" "$0" "$1"
|
||||
elif [ "$TERMINAL" = "kitty" ]; then
|
||||
# Setting the layout for the new window. It will be restored after the
|
||||
# script ends.
|
||||
kitty @ goto-layout splits >/dev/null
|
||||
|
||||
# Trying to use kitty's integrated window management as the split window.
|
||||
# All environmental variables that will be used in the new window must
|
||||
# be explicitly passed.
|
||||
kitty @ launch --no-response --title "nnn preview" --keep-focus \
|
||||
--cwd "$PWD" --env "PATH=$PATH" --env "NNN_FIFO=$NNN_FIFO" \
|
||||
--env "PREVIEW_MODE=1" --env "PAGER=$PAGER" \
|
||||
--env "USE_SCOPE=$USE_SCOPE" --env "SPLIT=$SPLIT" \
|
||||
--env "USE_PISTOL=$USE_PISTOL" \
|
||||
--location "${SPLIT}split" "$0" "$1" >/dev/null
|
||||
else
|
||||
PREVIEW_MODE=1 $TERMINAL -e "$0" "$1" &
|
||||
if [ ! -r "$NNN_FIFO" ]; then
|
||||
prompt "No FIFO available! (\$NNN_FIFO='$NNN_FIFO')\nPlease read Usage in '$0'."
|
||||
elif [ "$KITTY_WINDOW_ID" ] && [ -z "$TMUX" ] && [ -z "$KITTY_LISTEN_ON" ]; then
|
||||
prompt "\$KITTY_LISTEN_ON not set!\nPlease read Usage in '$0'."
|
||||
else
|
||||
toggle_preview "$1" &
|
||||
fi
|
||||
fi
|
||||
|
|
|
@ -1,340 +0,0 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
# Description: Terminal based file previewer
|
||||
#
|
||||
# Note: This plugin needs a "NNN_FIFO" to work. See man.
|
||||
#
|
||||
# Dependencies:
|
||||
# - Supports 3 independent methods to preview with:
|
||||
# - tmux (>=3.0), or
|
||||
# - kitty with allow_remote_control on, or
|
||||
# - $TERMINAL set to a terminal (it's xterm by default).
|
||||
# - less or $PAGER
|
||||
# - tree or exa or ls
|
||||
# - mediainfo or file
|
||||
# - mktemp
|
||||
# - unzip
|
||||
# - tar
|
||||
# - man
|
||||
# - optional: atool for additional archive preview
|
||||
# - optional: bat for code syntax highlighting
|
||||
# - optional: ueberzug, kitty terminal, viu or catimg for images.
|
||||
# - optional: convert(ImageMagick) for playing gif preview
|
||||
# - optional: ffmpegthumbnailer for video thumbnails (https://github.com/dirkvdb/ffmpegthumbnailer).
|
||||
# - optional: ffmpeg for audio thumbnails
|
||||
# - optional: libreoffce for opendocument/officedocument preview
|
||||
# - optional: pdftoppm(poppler) for pdf thumbnails
|
||||
# - optional: gnome-epub-thumbnailer for epub thumbnails (https://gitlab.gnome.org/GNOME/gnome-epub-thumbnailer)
|
||||
# - optional: fontpreview for font preview (https://github.com/sdushantha/fontpreview)
|
||||
# - optional: scope.sh file viewer from ranger.
|
||||
# To use:
|
||||
# 1. drop scope.sh executable in $PATH
|
||||
# 2. set/export $USE_SCOPE as 1
|
||||
# - optional: pistol file viewer (https://github.com/doronbehar/pistol).
|
||||
# To use:
|
||||
# 1. install pistol
|
||||
# 2. set/export $USE_PISTOL as 1
|
||||
#
|
||||
# Usage:
|
||||
# You need to set a NNN_FIFO path and a key for the plugin with NNN_PLUG,
|
||||
# then start `nnn`:
|
||||
#
|
||||
# $ nnn -a
|
||||
#
|
||||
# or
|
||||
#
|
||||
# $ NNN_FIFO=/tmp/nnn.fifo nnn
|
||||
#
|
||||
# Then in `nnn`, launch the `preview-tui` plugin.
|
||||
#
|
||||
# If you provide the same NNN_FIFO to all nnn instances, there will be a
|
||||
# single common preview window. If you provide different FIFO path (e.g.
|
||||
# with -a), they will be independent.
|
||||
#
|
||||
# The previews will be shown in a tmux split. If that isn't possible, it
|
||||
# will try to use a kitty terminal split. And as a final fallback, a
|
||||
# different terminal window will be used ($TERMINAL).
|
||||
#
|
||||
# Tmux and kitty users can configure $SPLIT to either "h" or "v" to set a
|
||||
# 'h'orizontal split or a 'v'ertical split (as in, the line that splits the
|
||||
# windows will be horizontal or vertical).
|
||||
#
|
||||
# Kitty users need `allow_remote_control` set to `yes`. To customize the
|
||||
# window split, `enabled_layouts` has to be set to `all` or `splits` (the
|
||||
# former is the default value). This terminal is also able to show images
|
||||
# without extra dependencies.
|
||||
#
|
||||
# Shell: POSIX compliant
|
||||
# Authors: Todd Yamakawa, Léo Villeveygoux, @Recidiviste, Mario Ortiz Manero
|
||||
|
||||
SPLIT="$SPLIT" # you can set a permanent split here
|
||||
TERMINAL="$TERMINAL" # same goes for the terminal
|
||||
USE_SCOPE="${USE_SCOPE:-0}"
|
||||
USE_PISTOL="${USE_PISTOL:-0}"
|
||||
PAGER="${PAGER:-less -P?n -R}"
|
||||
ARCHIVES="$(echo "$NNN_ARCHIVE" | sed 's/.*(\(.*\)).*/\1/;s/|/ /g')"
|
||||
TMPDIR="${TMPDIR:-/tmp}"
|
||||
|
||||
[ "$PAGER" = "most" ] && PAGER="less -R"
|
||||
|
||||
if [ -e "${TMUX%%,*}" ] && tmux -V | grep -q '[ -][3456789]\.'; then
|
||||
TERMINAL=tmux
|
||||
elif [ -n "$KITTY_WINDOW_ID" ] && kitty @ ls >/dev/null 2>&1; then
|
||||
TERMINAL=kitty
|
||||
else
|
||||
TERMINAL="${TERMINAL:-xterm}"
|
||||
fi
|
||||
|
||||
if [ -z "$SPLIT" ] && [ $(($(tput lines) * 2)) -gt "$(tput cols)" ]; then
|
||||
SPLIT='h'
|
||||
elif [ "$SPLIT" != 'h' ]; then
|
||||
SPLIT='v'
|
||||
fi
|
||||
|
||||
exists() {
|
||||
which "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
fifo_pager() {
|
||||
cmd="$1"
|
||||
shift
|
||||
|
||||
# We use a FIFO to access $PAGER PID in jobs control
|
||||
tmpfifopath="$TMPDIR/nnn-preview-tui-fifo.$$"
|
||||
mkfifo "$tmpfifopath" || return
|
||||
|
||||
$PAGER < "$tmpfifopath" &
|
||||
pagerpid="$!"
|
||||
|
||||
(
|
||||
exec > "$tmpfifopath"
|
||||
"$cmd" "$@" &
|
||||
)
|
||||
|
||||
rm "$tmpfifopath"
|
||||
}
|
||||
|
||||
# Binary file: show file info inside the pager
|
||||
print_bin_info() {
|
||||
printf -- "-------- \033[1;31mBinary file\033[0m --------\n"
|
||||
if exists mediainfo; then
|
||||
mediainfo "$1" 2>/dev/null
|
||||
else
|
||||
file -b "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
preview_file () {
|
||||
kill %- %+ 2>/dev/null && wait %- %+ 2>/dev/null
|
||||
clear
|
||||
|
||||
# Trying to use pistol if it's available.
|
||||
if [ "$USE_PISTOL" -ne 0 ] && exists pistol; then
|
||||
fifo_pager pistol "$1"
|
||||
return
|
||||
fi
|
||||
|
||||
# Trying to use scope.sh if it's available.
|
||||
if [ "$USE_SCOPE" -ne 0 ] && exists scope.sh; then
|
||||
fifo_pager scope.sh "$1" "$cols" "$lines" "$(mktemp -d)" \
|
||||
"True" 2>/dev/null
|
||||
return
|
||||
fi
|
||||
|
||||
# Detecting the exact type of the file: the encoding, mime type, and
|
||||
# extension in lowercase.
|
||||
encoding="$(file -Lb --mime-encoding -- "$1")"
|
||||
mimetype="$(file -Lb --mime-type -- "$1")"
|
||||
ext="${1##*.}"
|
||||
if [ -n "$ext" ]; then
|
||||
ext="$(printf "%s" "${ext}" | tr '[:upper:]' '[:lower:]')"
|
||||
fi
|
||||
lines=$(($(tput lines)-1))
|
||||
cols=$(tput cols)
|
||||
|
||||
# Otherwise, falling back to the defaults.
|
||||
if [ -d "$1" ]; then
|
||||
cd "$1" || return
|
||||
if exists tree; then
|
||||
fifo_pager tree -L 1 --dirsfirst -F -C
|
||||
elif exists exa; then
|
||||
fifo_pager exa -G --colour=always 2>/dev/null
|
||||
else
|
||||
fifo_pager ls --color=always
|
||||
fi
|
||||
elif [ "$encoding" = "binary" ]; then
|
||||
if [ "$ext" = "gif" ]; then
|
||||
generate_preview "$cols" "$lines" "$1" "gif"
|
||||
elif [ "${mimetype%%/*}" = "image" ]; then
|
||||
image_preview "$cols" "$lines" "$1"
|
||||
elif [ "${mimetype%%/*}" = "audio" ] && exists ffmpeg; then
|
||||
generate_preview "$cols" "$lines" "$1" "audio"
|
||||
elif [ "${mimetype%%/*}" = "video" ] && exists ffmpegthumbnailer; then
|
||||
generate_preview "$cols" "$lines" "$1" "video"
|
||||
elif [ "$ext" = "pdf" ] && exists pdftoppm; then
|
||||
generate_preview "$cols" "$lines" "$1" "pdf"
|
||||
elif [ "$ext" = "epub" ] && exists gnome-epub-thumbnailer; then
|
||||
generate_preview "$cols" "$lines" "$1" "epub"
|
||||
elif [ "${mimetype%%/*}" = "font" ] && exists fontpreview; then
|
||||
generate_preview "$cols" "$lines" "$1" "font"
|
||||
elif [ "${mimetype#*office}" != "$mimetype" ] || [ "${mimetype#*document}" != "$mimetype" ] && exists libreoffice; then
|
||||
generate_preview "$cols" "$lines" "$1" "office"
|
||||
elif [ "${ARCHIVES#*$ext}" != "$ARCHIVES" ] && exists atool; then
|
||||
fifo_pager atool -l "$1"
|
||||
elif [ "$mimetype" = "application/zip" ]; then
|
||||
fifo_pager unzip -l "$1"
|
||||
elif [ "$ext" = "gz" ] || [ "$ext" = "bz2" ]; then
|
||||
fifo_pager tar -tvf "$1"
|
||||
else
|
||||
fifo_pager print_bin_info "$1"
|
||||
fi
|
||||
elif [ "$mimetype" = "text/troff" ]; then
|
||||
fifo_pager man -Pcat -l "$1"
|
||||
else
|
||||
if exists bat; then
|
||||
fifo_pager bat --terminal-width="$cols" --paging=never --decorations=always --color=always \
|
||||
"$1" 2>/dev/null
|
||||
else
|
||||
$PAGER "$1" &
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
generate_preview() {
|
||||
if [ ! -f "$TMPDIR/$3.png" ]; then
|
||||
fifo_pager print_bin_info "$3"
|
||||
mkdir -p "$TMPDIR/${3%/*}"
|
||||
case $4 in
|
||||
audio) ffmpeg -i "$3" "$TMPDIR/$3.png" -y >/dev/null 2>&1 ;;
|
||||
epub) gnome-epub-thumbnailer "$3" "$TMPDIR/$3.png" >/dev/null 2>&1 ;;
|
||||
font) fontpreview -i "$3" -o "$TMPDIR/$3.png" >/dev/null 2>&1 ;;
|
||||
gif) if exists ueberzug || [ "$TERMINAL" = "kitty" ]; then
|
||||
if [ ! -d "$TMPDIR/$3" ]; then
|
||||
mkdir -p "$TMPDIR/$3"
|
||||
convert -coalesce "$3" "$TMPDIR/$3/${3##*/}.png"
|
||||
fi
|
||||
while true; do
|
||||
for frame in $(find "$TMPDIR/$3"/*.png | sort -V); do
|
||||
image_preview "$1" "$2" "$frame"
|
||||
sleep 0.1
|
||||
done
|
||||
[ "$LOOP_GIFS" -eq 0 ] && return
|
||||
done &
|
||||
gifpid="$!"
|
||||
return
|
||||
else
|
||||
image_preview "$1" "$2" "$3"
|
||||
return
|
||||
fi ;;
|
||||
office) libreoffice --convert-to png "$3" --outdir "$TMPDIR/${3%/*}" > /dev/null 2>&1
|
||||
filename="$(echo "${3##*/}" | cut -d. -f1)"
|
||||
mv "$TMPDIR/${3%/*}/$filename.png" "$TMPDIR/$3.png" ;;
|
||||
pdf) pdftoppm -png -f 1 -singlefile "$3" "$TMPDIR/$3" >/dev/null 2>&1 ;;
|
||||
video) ffmpegthumbnailer -i "$3" -o "$TMPDIR/$3.png" -s 0 -q 10 >/dev/null 2>&1 ;;
|
||||
esac
|
||||
kill "$pagerpid"
|
||||
fi
|
||||
image_preview "$1" "$2" "$TMPDIR/$3.png"
|
||||
}
|
||||
|
||||
image_preview() {
|
||||
if [ "$TERMINAL" = "kitty" ]; then
|
||||
# Kitty terminal users can use the native image preview method.
|
||||
kitty +kitten icat --silent --place "$1"x"$2"@0x0 --transfer-mode=stream --stdin=no \
|
||||
"$3"
|
||||
elif exists ueberzug; then
|
||||
ueberzug_layer "$1" "$2" "$3"
|
||||
elif exists catimg; then
|
||||
catimg "$3" &
|
||||
gifpid="$!"
|
||||
elif exists viu; then
|
||||
viu -t "$3" &
|
||||
gifpid="$!"
|
||||
else
|
||||
fifo_pager print_bin_info "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
ueberzug_layer() {
|
||||
printf '{"action": "add", "identifier": "nnn_ueberzug", "x": 0, "y": 0, "width": "%s", "height": "%s", "path": "%s"}\n' "$1" "$2" "$3" > "$FIFO_UEBERZUG"
|
||||
}
|
||||
|
||||
ueberzug_remove() {
|
||||
printf '{"action": "remove", "identifier": "nnn_ueberzug"}\n' > "$FIFO_UEBERZUG"
|
||||
}
|
||||
|
||||
ueberzug_refresh() {
|
||||
clear
|
||||
pkill -P "$$"
|
||||
pkill -f -n preview-tui-ext
|
||||
echo > "$NNN_FIFO"
|
||||
tail --follow "$FIFO_UEBERZUG" | ueberzug layer --silent --parser json &
|
||||
preview_fifo &
|
||||
wait
|
||||
}
|
||||
if [ "$TERMINAL" != "kitty" ] && [ "$PREVIEW_MODE" ] && exists ueberzug; then
|
||||
trap 'ueberzug_refresh' WINCH
|
||||
trap 'rm "$FIFO_UEBERZUG"' INT HUP EXIT
|
||||
fi
|
||||
|
||||
preview_fifo() {
|
||||
# use cat instead of 'exec <' to avoid issues with dash shell
|
||||
# shellcheck disable=SC2002
|
||||
cat "$NNN_FIFO" |\
|
||||
while read -r selection ; do
|
||||
[ "$gifpid" -ne 0 ] && kill "$gifpid"
|
||||
[ "$TERMINAL" != "kitty" ] && exists ueberzug && ueberzug_remove
|
||||
preview_file "$selection"
|
||||
done
|
||||
[ "$TERMINAL" != "kitty" ] && exists ueberzug && rm "$FIFO_UEBERZUG"
|
||||
}
|
||||
|
||||
|
||||
if [ "$PREVIEW_MODE" ]; then
|
||||
if [ ! -r "$NNN_FIFO" ]; then
|
||||
echo "No FIFO available! (\$NNN_FIFO='$NNN_FIFO')" >&2
|
||||
read -r
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$TERMINAL" != "kitty" ] && exists ueberzug; then
|
||||
FIFO_UEBERZUG="$TMPDIR/nnn-ueberzug-fifo.$$"
|
||||
mkfifo "$FIFO_UEBERZUG"
|
||||
tail --follow "$FIFO_UEBERZUG" | ueberzug layer --silent --parser json &
|
||||
fi
|
||||
|
||||
preview_file "$1"
|
||||
preview_fifo &
|
||||
wait
|
||||
|
||||
# Restoring the previous layout for kitty users. This will only work for
|
||||
# kitty >= 0.18.0.
|
||||
if [ "$TERMINAL" = "kitty" ]; then
|
||||
kitty @ last-used-layout --no-response >/dev/null 2>&1
|
||||
fi
|
||||
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$TERMINAL" = "tmux" ]; then
|
||||
# tmux splits are inverted
|
||||
if [ "$SPLIT" = "v" ]; then SPLIT="h"; else SPLIT="v"; fi
|
||||
|
||||
tmux split-window -e "NNN_FIFO=$NNN_FIFO" -e "PREVIEW_MODE=1" -d"$SPLIT" "$0" "$1"
|
||||
elif [ "$TERMINAL" = "kitty" ]; then
|
||||
# Setting the layout for the new window. It will be restored after the
|
||||
# script ends.
|
||||
kitty @ goto-layout splits >/dev/null
|
||||
|
||||
# Trying to use kitty's integrated window management as the split window.
|
||||
# All environmental variables that will be used in the new window must
|
||||
# be explicitly passed.
|
||||
kitty @ launch --no-response --title "nnn preview" --keep-focus \
|
||||
--cwd "$PWD" --env "PATH=$PATH" --env "NNN_FIFO=$NNN_FIFO" \
|
||||
--env "PREVIEW_MODE=1" --env "PAGER=$PAGER" \
|
||||
--env "USE_SCOPE=$USE_SCOPE" --env "SPLIT=$SPLIT" \
|
||||
--env "USE_PISTOL=$USE_PISTOL" \
|
||||
--location "${SPLIT}split" "$0" "$1" >/dev/null
|
||||
else
|
||||
PREVIEW_MODE=1 $TERMINAL -e "$0" "$1" &
|
||||
fi
|
|
@ -14,15 +14,15 @@ read -r psname
|
|||
|
||||
# shellcheck disable=SC2009
|
||||
if [ -n "$psname" ]; then
|
||||
if which sudo >/dev/null 2>&1; then
|
||||
if type sudo >/dev/null 2>&1; then
|
||||
sucmd=sudo
|
||||
elif which doas >/dev/null 2>&1; then
|
||||
elif type doas >/dev/null 2>&1; then
|
||||
sucmd=doas
|
||||
else
|
||||
sucmd=: # noop
|
||||
fi
|
||||
|
||||
if which fzf >/dev/null 2>&1; then
|
||||
if type fzf >/dev/null 2>&1; then
|
||||
fuzzy=fzf
|
||||
else
|
||||
exit 1
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
# Description: Batch rename selection or current directory with qmv
|
||||
# Description: Batch rename selection or current directory with qmv or vidir
|
||||
#
|
||||
# Notes:
|
||||
# - Try to mimic current batch rename functionality but with correct
|
||||
# handling of edge cases by qmv or vidir.
|
||||
# Qmv opens with hidden files if no selection is used. Selected
|
||||
# directories are shown.
|
||||
# Vidir don't show directories nor hidden files.
|
||||
# - Try to mimic current batch rename functionality but with correct
|
||||
# handling of edge cases by qmv or vidir.
|
||||
# - Qmv opens with hidden files if no selection is used. Selected
|
||||
# directories are shown.
|
||||
# - Vidir don't show directories nor hidden files.
|
||||
#
|
||||
# Shell: POSIX compliant
|
||||
# Author: José Neder
|
||||
|
||||
selection=${NNN_SEL:-${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.selection}
|
||||
|
||||
if which qmv >/dev/null 2>&1; then
|
||||
if type qmv >/dev/null 2>&1; then
|
||||
batchrenamesel="qmv -fdo -da"
|
||||
batchrename="qmv -fdo -a"
|
||||
elif which vidir >/dev/null 2>&1; then
|
||||
elif type vidir >/dev/null 2>&1; then
|
||||
batchrenamesel="vidir"
|
||||
batchrename="vidir"
|
||||
else
|
||||
|
@ -33,6 +33,11 @@ fi
|
|||
if [ "$resp" = "y" ]; then
|
||||
# -o flag is necessary for interactive editors
|
||||
xargs -o -0 $batchrenamesel < "$selection"
|
||||
|
||||
# Clear selection
|
||||
if [ -p "$NNN_PIPE" ]; then
|
||||
printf "-" > "$NNN_PIPE"
|
||||
fi
|
||||
elif [ ! "$(LC_ALL=C ls -a)" = ".
|
||||
.." ]; then
|
||||
# On older systems that don't have ls -A
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
# Description: Simple script to give copy-paste a progress percentage
|
||||
# by utilizing rsync.
|
||||
#
|
||||
# LIMITATION: this won't work when pasting to MTP device.
|
||||
#
|
||||
# Dependencies: rsync
|
||||
#
|
||||
# Shell: POSIX compliant
|
||||
# Author: Benawi Adha
|
||||
|
||||
sel=${NNN_SEL:-${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.selection}
|
||||
|
||||
# Choose one of these two schemes by commenting
|
||||
|
||||
# more verbose
|
||||
xargs -0 -I % rsync -ah --progress % "$PWD" < "$sel"
|
||||
|
||||
# less verbose
|
||||
# xargs -0 -I % rsync -ah --info=progress2 % "$PWD" < "$sel"
|
||||
|
||||
# Clear selection
|
||||
if [ -p "$NNN_PIPE" ]; then
|
||||
printf "-" > "$NNN_PIPE"
|
||||
fi
|
|
@ -26,13 +26,18 @@ if [ "$resp" = "j" ]; then
|
|||
for entry in $arr
|
||||
do
|
||||
if [ -d "$entry" ]; then
|
||||
echo "cant join directories"
|
||||
echo "can't join directories"
|
||||
exit
|
||||
fi
|
||||
done
|
||||
|
||||
file="$(basename "$(echo "$arr" | sed -n '1p' | sed -e 's/[0-9][0-9]$//')")"
|
||||
sort -z < "$selection" | xargs -0 -I{} cat {} > "${file}.out"
|
||||
|
||||
# Clear selection
|
||||
if [ -p "$NNN_PIPE" ]; then
|
||||
printf "-" > "$NNN_PIPE"
|
||||
fi
|
||||
fi
|
||||
elif [ "$resp" = "s" ]; then
|
||||
if [ -n "$1" ] && [ -f "$1" ]; then
|
||||
|
|
|
@ -7,15 +7,10 @@
|
|||
|
||||
EDITOR="${EDITOR:-vim}"
|
||||
|
||||
is_cmd_exists () {
|
||||
which "$1" > /dev/null 2>&1
|
||||
echo $?
|
||||
}
|
||||
|
||||
if [ "$(is_cmd_exists sudo)" -eq "0" ]; then
|
||||
sudo "$EDITOR" "$1"
|
||||
elif [ "$(is_cmd_exists sudoedit)" -eq "0" ]; then
|
||||
sudoedit "$1"
|
||||
elif [ "$(is_cmd_exists doas)" -eq "0" ]; then
|
||||
if type sudo >/dev/null 2>&1; then
|
||||
sudo -E "$EDITOR" "$1"
|
||||
elif type sudoedit >/dev/null 2>&1; then
|
||||
sudoedit -E "$1"
|
||||
elif type doas >/dev/null 2>&1; then
|
||||
doas "$EDITOR" "$1"
|
||||
fi
|
||||
|
|
|
@ -11,10 +11,11 @@
|
|||
|
||||
selection=${NNN_SEL:-${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.selection}
|
||||
|
||||
if [ ! -s "$selection" ]; then
|
||||
printf "0 selected "
|
||||
read -r _
|
||||
exit
|
||||
fi
|
||||
if [ -s "$selection" ]; then
|
||||
xargs -0 -I {} sh -c 'if [ -x "{}" ] ; then chmod -x "{}" ; else chmod +x "{}" ; fi' < "$selection"
|
||||
|
||||
xargs -0 -I {} sh -c 'if [ -x "{}" ] ; then chmod -x "{}" ; else chmod +x "{}" ; fi' < "$selection"
|
||||
# Clear selection
|
||||
if [ -p "$NNN_PIPE" ]; then
|
||||
printf "-" > "$NNN_PIPE"
|
||||
fi
|
||||
fi
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue