Compare commits
652 Commits
neofetch-7.3.9
...
2.0.2
| Author | SHA1 | Date | |
|---|---|---|---|
| a463f4234c | |||
| beb04101db | |||
| bf60e4265b | |||
| 42421bc57d | |||
| f64ee7b7e9 | |||
| 1fa29cf831 | |||
| 4861dd5d4a | |||
| 5614b723fd | |||
| 5e1e13b091 | |||
| 79ddb3ca92 | |||
| 684929edea | |||
| f02ec8c4ba | |||
| 5fd4ed9b0c | |||
| 003c295084 | |||
| d4560e3edb | |||
| 62b4c27404 | |||
| 169368a784 | |||
| 3e47640c1a | |||
| 6ddd762b35 | |||
| 713bcce0ec | |||
| fdfd9816f5 | |||
| d6f9d1f569 | |||
| b28aa0ddf2 | |||
| a5e784c528 | |||
| 93b4dd3471 | |||
| d15afe579f | |||
| f79aca3c65 | |||
| fa3fc59a5f | |||
| afa3c1dfb9 | |||
| cf6b77a1b7 | |||
| b58425badd | |||
| 8c1713c37d | |||
| 3c7c449da4 | |||
| 2fe4b3f287 | |||
| 6a80928f10 | |||
| 4ac698817d | |||
| 13acc0b6b6 | |||
| 455f0382e7 | |||
| 0c9e4db742 | |||
| aee058e591 | |||
| b74787768f | |||
| 218c535d06 | |||
| 76ae5e507a | |||
| d2dfd950a3 | |||
| 45ee7e199e | |||
| 2cfea54a88 | |||
| 0cc6ddbca8 | |||
| 8a536c30f0 | |||
| 5c24bd443a | |||
| e691b2d9da | |||
| 5ec7b4f01a | |||
| f38b754783 | |||
| 211beb7b6a | |||
| 02c64ef281 | |||
| 4e9c510240 | |||
| d6b559fb40 | |||
| 9806ced8b2 | |||
| 982ac52c69 | |||
| f9c9a92048 | |||
| b8e5dadd78 | |||
| 287921439d | |||
| e8e0a58e4b | |||
| 3a80670491 | |||
| 8cc06c02b5 | |||
| 48f52be2d3 | |||
| b009342d78 | |||
| 8e4b57e33a | |||
| 9a9101a9a3 | |||
| 90d12d9385 | |||
| ca74acbafb | |||
| afd9ad33d4 | |||
| cafa3ff752 | |||
| a0db219ba3 | |||
| 89cced9950 | |||
| 1ff4b12f19 | |||
| 4f8ddd1c22 | |||
| 7a42824883 | |||
| 916f7274df | |||
| 79fc190013 | |||
| e78d95e573 | |||
| 943503004d | |||
| deb2bddbe1 | |||
| 15fabbdb1a | |||
| df71b0132a | |||
| 191995c0fe | |||
| 6558cf39f1 | |||
| 99d652383a | |||
| e78ae3233c | |||
| a60dd35169 | |||
| ccc8121550 | |||
| bb260890c5 | |||
| 057b3b53e2 | |||
| 3a96fe8561 | |||
| 1b3b5ca883 | |||
| 53f7e3fcdb | |||
| e630b7837f | |||
| aa065fe910 | |||
| 28b365d418 | |||
| 4ea0a4a9dc | |||
| b5b49ecbc0 | |||
| cf56c60006 | |||
| a6225d698f | |||
| d5621877d5 | |||
| d5b93829fc | |||
| f3fc92dc7d | |||
| 36fc38c7a9 | |||
| 6af128fb05 | |||
| 8b3e4bba76 | |||
| 1211dc6978 | |||
| d0f911922a | |||
| c68dd7fe5b | |||
| 49b26dc7ea | |||
| f815d2bdd6 | |||
| b0b8c51d35 | |||
| 87e6092446 | |||
| fb52256729 | |||
| 5e11110c66 | |||
| a8b94f9187 | |||
| 3754aada04 | |||
| f94e788547 | |||
| a5f648a3fa | |||
| e184ed613a | |||
| f4d6b75f56 | |||
| 865850da59 | |||
| 54e0f55a08 | |||
| c969ce3a21 | |||
| afc646c679 | |||
| 6ac7f70c51 | |||
| c1fbd137a0 | |||
| 6f913b6d4a | |||
| 1077ee5142 | |||
| cec24f6bd0 | |||
| 9636c980e7 | |||
| 3866ad0249 | |||
| 0ca67a5608 | |||
| b2f7a3cee9 | |||
| b33b26625a | |||
| 1e67d65cec | |||
| e04ef3b0fd | |||
| a51a19658a | |||
| a65a229b0e | |||
| 5c0662142e | |||
| 88d835f511 | |||
| ce358fc155 | |||
| d5b283e64d | |||
| a609edc505 | |||
| 753d35b56e | |||
| d309f2d8a8 | |||
| e59a0556ed | |||
| afa18885ee | |||
| 69f07aec8f | |||
| 95a6cc7f4b | |||
| 896ba8fc7d | |||
| 319afd2aa9 | |||
| 3df77e0042 | |||
| 729e81a3e2 | |||
| 3dafba3554 | |||
| 36d87c2c35 | |||
| 0f744ff815 | |||
| 0dea6eb11b | |||
| 05685de193 | |||
| 03a6802b8f | |||
| d6341d241a | |||
| 32dd56dc63 | |||
| 6732945af8 | |||
| bb6b9b1d37 | |||
| 474f744bc6 | |||
| 7c139595a6 | |||
| ebd253523b | |||
| 13e29325b9 | |||
| 00369355e6 | |||
| 2865ee7131 | |||
| faa7ab240f | |||
| bcdc720d8a | |||
| 52844b55ad | |||
| 6ccf0d9c31 | |||
| e46e78ecd5 | |||
| 2f18cc2826 | |||
| 4c72ed6d79 | |||
| 55b0eed88d | |||
| 28f98a40fb | |||
| bbe40930c2 | |||
| a5913cc3d7 | |||
| f976781997 | |||
| cbe176ff4e | |||
| fe7ed923ea | |||
| c2795125d2 | |||
| 370b56c1db | |||
| f47561c947 | |||
| 89e5342614 | |||
| 4e3ec2604a | |||
| 279311fea0 | |||
| a7c277cb76 | |||
| c2586212d6 | |||
| 632296dbb4 | |||
| fe7d902dac | |||
| c7295ebed8 | |||
| bdd03a34af | |||
| 683d1fc2ec | |||
| c80a6185fc | |||
| 6564ca72c2 | |||
| 2a8cd48674 | |||
| 13ead437ec | |||
| 8edb50c4d8 | |||
| 14ff66b836 | |||
| 0c7c43d71c | |||
| 2613471978 | |||
| a558cf7ac9 | |||
| cd1858134c | |||
| 0a31cd0817 | |||
| e25684cfd8 | |||
| de43bf74a9 | |||
| d8f3302b89 | |||
| 5517283fb2 | |||
| 66b08f7a2e | |||
| 19e3b382b4 | |||
| e10bdac351 | |||
| 6e28482706 | |||
| 198742e15b | |||
| a5de091883 | |||
| da5f6ef655 | |||
| dbecd3d705 | |||
| e2d538df1f | |||
| 8514629960 | |||
| d11f6f0a9f | |||
| 45347e0714 | |||
| d79196a7fc | |||
| 114de9be12 | |||
| 4861744b50 | |||
| 66b57cfea6 | |||
| ca583bddcb | |||
| 965b009bc7 | |||
| 5b759e0986 | |||
| 3cc26d7dd9 | |||
| 85a85ad4d3 | |||
| f3b1840e92 | |||
| d773c69918 | |||
| 290da7c363 | |||
| fa66bb486b | |||
| 1239e86d1a | |||
| 66491a4e73 | |||
| c100ca52a6 | |||
| 46b618252f | |||
| be70233b03 | |||
| b5588d8259 | |||
| ff46c8f4ca | |||
| 59213687fb | |||
| 475b10ba07 | |||
| b0737a33ba | |||
| 3e4e679b11 | |||
| 3c355f54f2 | |||
| 86e442b8a4 | |||
| a0856aa4f5 | |||
| d1d99daa87 | |||
| 4f1efbc699 | |||
| c1b30918e9 | |||
| 517dde43cc | |||
| 955046c959 | |||
| 274440e9db | |||
| fd413caba4 | |||
| 474c339599 | |||
| 927803549e | |||
| 11601933f9 | |||
| b7f2992ecd | |||
| 1f1362a0b5 | |||
| 7c874a8e9a | |||
| 6e0e3fd18a | |||
| 974c4514b2 | |||
| e3b220a248 | |||
| ae1f6a2b3f | |||
| 290445110d | |||
| 4f9e6deb90 | |||
| 3b94b94528 | |||
| 39b44ad041 | |||
| bf2c3c51d4 | |||
| 2a01c50aa6 | |||
| 7f18d0e042 | |||
| 2307f9de20 | |||
| c185f018a4 | |||
| 9b159c7472 | |||
| ca77102be1 | |||
| 5ee89eb148 | |||
| ced109f0ea | |||
| 5051b692f0 | |||
| 07e23e2a5b | |||
| 270334a385 | |||
| df7884c2ac | |||
| a8f02e94b6 | |||
| 881833d3c9 | |||
| 207c608cd6 | |||
| ccab992c7b | |||
| e385eef74a | |||
| 820b78fb3b | |||
| 09c823d8c8 | |||
| aef326ae07 | |||
| 1139abd9c6 | |||
| 4517efc07e | |||
| 3b5b3a556b | |||
| 7534371b05 | |||
| fc98d61109 | |||
| 359226c26b | |||
| 109d7d2f01 | |||
| 33fd55e6ad | |||
| e08e864be0 | |||
| 07da5d5f4b | |||
| c2a26cf0ae | |||
| 1c1483822c | |||
| 46d38d4851 | |||
| a8c2cfb921 | |||
| d8affa54cd | |||
| 4707704330 | |||
| 882dafd11b | |||
| 9a867c6819 | |||
| bfeca1535b | |||
| b2afcb8a64 | |||
| 6e7ac1839d | |||
| 515afa90c3 | |||
| 1a3e6a8e29 | |||
| cff0fdf6d8 | |||
| 896658d5e1 | |||
| cdc0071e28 | |||
| 4ed4f19196 | |||
| 38b8173be4 | |||
| d70baebbf0 | |||
| a2abe13b86 | |||
| cd6f74931c | |||
| 1b1c90ec44 | |||
| d942de0b88 | |||
| d41a302e44 | |||
| 566011efff | |||
| 96ba35b0bf | |||
| 4c06a53c68 | |||
| 30d1e67b53 | |||
| 22c8d76193 | |||
| 36cdc6da2a | |||
| 293889b9ad | |||
| e21f9bef26 | |||
| bbe141557e | |||
| f06c3fda31 | |||
| dbe67789d8 | |||
| 6a1ba72df9 | |||
| 413a7d3681 | |||
| 18107d9601 | |||
| 5ded23e8dd | |||
| 09506aaa3c | |||
| 770ffb01a5 | |||
| 41d767fa4e | |||
| e5169705b3 | |||
| 73bb634326 | |||
| 8eadfec466 | |||
| 6816679ad9 | |||
| 2a87f1d3b4 | |||
| 6dec8c4a58 | |||
| e466389ae9 | |||
| bb5f45a71c | |||
| 3a415600d5 | |||
| 5bafa5128b | |||
| 51f0ebf3ea | |||
| c7d6c753d9 | |||
| d8bb0097c1 | |||
| 9292a602df | |||
| dbe657a05f | |||
| bb156173b5 | |||
| 9cebc9df35 | |||
| 25a64b6ce3 | |||
| 5c34876c53 | |||
| 1e30a7701f | |||
| 1c9480b764 | |||
| a385480d89 | |||
| 81f4dc90e8 | |||
| 2b6d17c559 | |||
| 6f9155fe83 | |||
| f32df6e6d0 | |||
| ece02c5d44 | |||
| d47a63d237 | |||
| be8f75df01 | |||
| bd9c0b30cf | |||
| b835eea039 | |||
| 01a01fb21b | |||
| 1bcf46aa42 | |||
| 811ec5d2d2 | |||
| dc359abe45 | |||
| be05f6984d | |||
| e6d94bf20d | |||
| f9a43fba5f | |||
| bc8499e2fb | |||
| 3ba7830824 | |||
| d914d3ea2b | |||
| 7eb4102417 | |||
| 7da1531d34 | |||
| b283b0d11d | |||
| b8115e97ae | |||
| 7c41025c55 | |||
| 98d3d9f629 | |||
| d374354cb6 | |||
| eeffb35944 | |||
| 048e2d93fd | |||
| b9db6d2cc5 | |||
| d5e3b07c1c | |||
| fd5ff6a821 | |||
| a33f85d45a | |||
| 1b89fc9531 | |||
| 2aa368ee9e | |||
| 3d6be24e9f | |||
| f2ed3e7155 | |||
| 98efa7a44d | |||
| 25ec6bbac5 | |||
| eef4153c5b | |||
| 17e02a384f | |||
| e50ec9e366 | |||
| 057f075a0e | |||
| a410eb0646 | |||
| 56796a331f | |||
| 2c33e7e37d | |||
| 8edddeaf8b | |||
| caa1547e8c | |||
| 807eed022d | |||
| b69c400fa4 | |||
| 5f266a3f16 | |||
| b740ddc3e5 | |||
| dfc3f59323 | |||
| 0c1ac93a4d | |||
| f449cfadc3 | |||
| bdb222f9f8 | |||
| 985f32e5a6 | |||
| da48f1d32c | |||
| 98a3befd4b | |||
| 09c62956a3 | |||
| 9945075de5 | |||
| 5f079cec46 | |||
| 97a31aba52 | |||
| 76f3ce2608 | |||
| 3a5ce4eb58 | |||
| 44c9a5491b | |||
| 2cbd8e440d | |||
| 4516747954 | |||
| 813b6f7173 | |||
| 937e5041c4 | |||
| f59f6f55d2 | |||
| 2ce3bb6a11 | |||
| a2fb43bfca | |||
| 9a5d8fb971 | |||
| 8ee497ad97 | |||
| 5072baf1cf | |||
| b407bc0ea4 | |||
| 78bcf1e5cc | |||
| e080924040 | |||
| c2f69d64f4 | |||
| 620bc2ca88 | |||
| ea61ca96b7 | |||
| 979e3950e9 | |||
| ce1423bfbd | |||
| f66b128caf | |||
| e63e2693c2 | |||
| 5e109afceb | |||
| 524baf9cf7 | |||
| deac271585 | |||
| b027dc4cb5 | |||
| 5b93e00b63 | |||
| d7e9ee8499 | |||
| 48da56a78e | |||
| a1e42b4f89 | |||
| 0f62374205 | |||
| 953001537f | |||
| 05bdef915a | |||
| 91ced42151 | |||
| 5d076fcea6 | |||
| ec8693322a | |||
| a6e184bd4a | |||
| d16806cb16 | |||
| bfcd8b1f67 | |||
| 81cdaa980c | |||
| 2af4aa9adc | |||
| ae4e484d65 | |||
| 1e736ae011 | |||
| f316b2b5cb | |||
| b87bb47502 | |||
| 797199dd05 | |||
| 42a275b27b | |||
| d267aaa90c | |||
| f06dea80fc | |||
| 1114fe53d4 | |||
| a214e65b08 | |||
| b24f6663ba | |||
| d91db75b4a | |||
| 294805f045 | |||
| 47dea65fa8 | |||
| 8e367e41a4 | |||
| 81134bbb34 | |||
| 0729e40e00 | |||
| 598731bf89 | |||
| afcf53f01f | |||
| c505323826 | |||
| 10b227a780 | |||
| a9d76846a9 | |||
| 73d305ac69 | |||
| d3577a8878 | |||
| 5519dd16a0 | |||
| 20e93689b6 | |||
| fca42c0390 | |||
| ce9c4aa432 | |||
| 3ebfcfd474 | |||
| d7c3475726 | |||
| 8d0393d654 | |||
| 54d82ff557 | |||
| fd96030436 | |||
| b1df896e44 | |||
| 4a053f942c | |||
| 025dff4c30 | |||
| c33c897724 | |||
| ff8f9b2879 | |||
| 6b84920587 | |||
| a5f2653675 | |||
| 5f527960e9 | |||
| d312ca97cc | |||
| c77a05809e | |||
| 74d1bb5622 | |||
| d9d9998d99 | |||
| a8f26f9e36 | |||
| 1e8fade4be | |||
| ace0245097 | |||
| 5122d08ff6 | |||
| 179fa567a3 | |||
| 1acfe273e8 | |||
| 1ff772a01b | |||
| 8182224dc7 | |||
| 57a28da23b | |||
| 4536dafa09 | |||
| c8185944dc | |||
| 4a90533097 | |||
| b353cb7247 | |||
| 4d9bbbae9c | |||
| edf2a697d9 | |||
| c7a516247a | |||
| 29cbbae974 | |||
| 98863df16d | |||
| 922a91ebb1 | |||
| e7938ea4c3 | |||
| 7491081946 | |||
| 14bde2e49b | |||
| 242eae6de0 | |||
| 53bbd3fdf8 | |||
| 5c785f0819 | |||
| 75750f12a5 | |||
| 73b39252df | |||
| b313d39366 | |||
| 116c83b513 | |||
| e33ccd3484 | |||
| 1e68f174cd | |||
| d164d4c8f6 | |||
| 445f97093a | |||
| e81f2aa6d7 | |||
| 53dec09f88 | |||
| 3d7dfc0220 | |||
| 62710fa00e | |||
| 63f37d28e3 | |||
| 8c4cbf656f | |||
| 526c97fde6 | |||
| 391ff75cd1 | |||
| df0c2be57a | |||
| 59ef6434d7 | |||
| 01821a8d7a | |||
| 65d82be06e | |||
| b5e9edfae7 | |||
| 98feca03f9 | |||
| 6167ba885b | |||
| ce2a49e9a0 | |||
| d025ece2c3 | |||
| c547ccb3c3 | |||
| 6251cb5e43 | |||
| ea42a29bbd | |||
| 0305e269e0 | |||
| cf17522d50 | |||
| 1bf2281912 | |||
| 4d39bd750f | |||
| 6db170e825 | |||
| 25df70367a | |||
| a9602f5619 | |||
| 2f69013177 | |||
| 434f5aeda8 | |||
| 988ca7993e | |||
| 1efafdfb81 | |||
| 75fd94fa61 | |||
| 08029959f3 | |||
| 9c59dc2791 | |||
| e9ae4dbb6f | |||
| 26453ea3d7 | |||
| 0385fd836d | |||
| cec8152f3d | |||
| 407387eb0b | |||
| 484f13fa39 | |||
| cf83073200 | |||
| 8e63a77335 | |||
| 05c60fddfd | |||
| 04a6744e6d | |||
| 68cf96e24a | |||
| 576facfd69 | |||
| bec385d02f | |||
| a32028755a | |||
| ebd6acd004 | |||
| 0694c10537 | |||
| 2dea4d54e0 | |||
| 5bbaf0a658 | |||
| 2f753325ae | |||
| 0d018248e5 | |||
| aa5bfe060c | |||
| 407fcd4987 | |||
| bf16e1cd47 | |||
| 9f808b99ab | |||
| dc778c3078 | |||
| 0634893733 | |||
| 0aa0a76151 | |||
| 511af9031c | |||
| db54e8990d | |||
| 673de9bb53 | |||
| 41d1446476 | |||
| 02b8e6bd5f | |||
| 356c83f057 | |||
| 38cf9502c5 | |||
| ae70359fca | |||
| ed377261a2 | |||
| a97d2805b1 | |||
| 7bfac43dd9 | |||
| 8bf694c7ba | |||
| 176f08ad0b | |||
| 2ce7a59a59 | |||
| 698afafa26 | |||
| 4b1546ccd6 | |||
| 6a023d4c91 | |||
| 40ea204223 | |||
| 31af137e97 | |||
| 914890b4b0 | |||
| 5ab2f2dcc5 | |||
| 01aed343a6 | |||
| 8389a1dee9 | |||
| a2cf60bc4c | |||
| 2577462649 | |||
| 3edca64629 | |||
| 2edf9c1304 | |||
| 50abc68f0d | |||
| 60b4b925d3 | |||
| 717b74c30b | |||
| 506f345a9d | |||
| 42d8b0d860 | |||
| cdae93479f | |||
| 82c949e5a1 | |||
| a8bcbfce09 | |||
| 43bea54532 | |||
| df11c756dd | |||
| 2cda9e9b2c | |||
| 0033e31388 | |||
| c02d375d71 |
@@ -0,0 +1,2 @@
|
||||
[env]
|
||||
CARGO_WORKSPACE_DIR = { value = "", relative = true }
|
||||
@@ -0,0 +1,71 @@
|
||||
# EditorConfig helps developers define and maintain consistent
|
||||
# coding styles between different editors and IDEs
|
||||
# editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
# Change these settings to your own preference
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
# We recommend you to keep these unchanged
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.csv]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.js]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[*.json]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.py]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[*.rs]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[*.sh]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[*.toml]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[*.{yaml,yml}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[.github/{actions,workflows}/**/*.yml]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[Cargo.toml]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[Makefile]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
|
||||
[neofetch]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[package.json]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
+17
-2
@@ -1,2 +1,17 @@
|
||||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
||||
* text=auto eol=lf
|
||||
|
||||
*.csv text eol=lf
|
||||
*.js text eol=lf
|
||||
*.json text eol=lf
|
||||
*.md text eol=lf
|
||||
*.py text eol=lf
|
||||
*.rs text eol=lf
|
||||
*.sh text eol=lf
|
||||
*.toml text eol=lf
|
||||
*.txt text eol=lf
|
||||
*.yaml text eol=lf
|
||||
*.yml text eol=lf
|
||||
Cargo.lock text eol=lf merge=binary
|
||||
Makefile text eol=lf
|
||||
MANIFEST.in text eol=lf
|
||||
neofetch text eol=lf
|
||||
|
||||
+12
@@ -120,3 +120,15 @@ webhook-log
|
||||
start_moderation.sh
|
||||
gh_moderator.toml
|
||||
moderator-data
|
||||
hyfetch/git
|
||||
build
|
||||
dist
|
||||
target
|
||||
.vscode
|
||||
.idea
|
||||
*.iml
|
||||
*.egg-info
|
||||
__pycache__
|
||||
*.pyc
|
||||
*.pyo
|
||||
*.pyd
|
||||
|
||||
Generated
+1216
File diff suppressed because it is too large
Load Diff
+51
@@ -0,0 +1,51 @@
|
||||
[workspace]
|
||||
resolver = "2"
|
||||
members = ["crates/*"]
|
||||
|
||||
[workspace.package]
|
||||
version = "2.0.2"
|
||||
authors = ["Azalea Gui <azalea@hydev.org>"]
|
||||
edition = "2021"
|
||||
rust-version = "1.75.0"
|
||||
description = "Neofetch with LGBTQ+ pride flags!"
|
||||
repository = "https://github.com/hykilpikonna/hyfetch"
|
||||
license = "MIT"
|
||||
|
||||
[workspace.dependencies]
|
||||
aho-corasick = { version = "1.1.3", default-features = false }
|
||||
ansi_colours = { version = "1.2.2", default-features = false }
|
||||
anstream = { version = "0.6.14", default-features = false }
|
||||
anyhow = { version = "1.0.86", default-features = false }
|
||||
bpaf = { version = "0.9.12", default-features = false }
|
||||
crossterm = { version = "0.27.0", default-features = false }
|
||||
deranged = { version = "0.3.11", default-features = false }
|
||||
directories = { version = "5.0.1", default-features = false }
|
||||
enable-ansi-support = { version = "0.2.1", default-features = false }
|
||||
enterpolation = { version = "0.2.1", default-features = false }
|
||||
fastrand = { version = "2.1.0", default-features = false }
|
||||
indexmap = { version = "2.2.6", default-features = false }
|
||||
itertools = { version = "0.13.0", default-features = false }
|
||||
normpath = { version = "1.2.0", default-features = false }
|
||||
palette = { version = "0.7.6", default-features = false }
|
||||
regex = { version = "1.10.5", default-features = false }
|
||||
same-file = { version = "1.0.6", default-features = false }
|
||||
serde = { version = "1.0.203", default-features = false }
|
||||
serde_json = { version = "1.0.118", default-features = false }
|
||||
serde_path_to_error = { version = "0.1.16", default-features = false }
|
||||
shell-words = { version = "1.1.0", default-features = false }
|
||||
strum = { version = "0.26.3", default-features = false }
|
||||
supports-color = { version = "3.0.0", default-features = false }
|
||||
tempfile = { version = "3.10.1", default-features = false }
|
||||
terminal-colorsaurus = { version = "0.4.3", default-features = false }
|
||||
terminal_size = { version = "0.3.0", default-features = false }
|
||||
thiserror = { version = "1.0.61", default-features = false }
|
||||
time = { version = "0.3.36", default-features = false }
|
||||
toml_edit = { version = "0.22.16", default-features = false }
|
||||
tracing = { version = "0.1.40", default-features = false }
|
||||
tracing-subscriber = { version = "0.3.18", default-features = false }
|
||||
unicode-normalization = { version = "0.1.23", default-features = false }
|
||||
unicode-segmentation = { version = "1.11.0", default-features = false }
|
||||
which = { version = "7.0.1", default-features = false }
|
||||
|
||||
[workspace.lints.clippy]
|
||||
arithmetic_side_effects = "warn"
|
||||
@@ -1 +1,9 @@
|
||||
include hyfetch/scripts/*
|
||||
|
||||
recursive-exclude tools *
|
||||
recursive-exclude .github *
|
||||
recursive-exclude .vscode *
|
||||
exclude .gitignore
|
||||
exclude .gitattributes
|
||||
exclude package.json
|
||||
exclude CONTRIBUTING.md
|
||||
@@ -1,16 +0,0 @@
|
||||
PREFIX = /usr
|
||||
MANDIR = $(PREFIX)/share/man
|
||||
|
||||
all:
|
||||
@echo Run \'make install\' to install Neofetch.
|
||||
|
||||
install:
|
||||
@mkdir -p $(DESTDIR)$(PREFIX)/bin
|
||||
@mkdir -p $(DESTDIR)$(MANDIR)/man1
|
||||
@cp -p neofetch $(DESTDIR)$(PREFIX)/bin/neofetch
|
||||
@cp -p neofetch.1 $(DESTDIR)$(MANDIR)/man1
|
||||
@chmod 755 $(DESTDIR)$(PREFIX)/bin/neofetch
|
||||
|
||||
uninstall:
|
||||
@rm -rf $(DESTDIR)$(PREFIX)/bin/neofetch
|
||||
@rm -rf $(DESTDIR)$(MANDIR)/man1/neofetch.1*
|
||||
@@ -6,45 +6,57 @@ neofetch with pride flags <3
|
||||
|
||||
### Running Updated Original Neofetch
|
||||
|
||||
This repo also serves as an updated version of the original `neofetch` since the upstream [dylanaraps/neofetch](https://github.com/dylanaraps/neofetch) doesn't seem to be maintained anymore (as of Jul 30, 2022, the original repo hasn't merged a pull request for 6 months). If you only want to use the updated neofetch without pride flags, you can use the `neofetch` script from this repo. To prevent command name conflict, I call it `neowofetch` :)
|
||||
This repo also serves as an updated version of the original `neofetch` since the upstream [dylanaraps/neofetch](https://github.com/dylanaraps/neofetch) isn't maintained anymore and has been archived. If you only want to use the updated neofetch without pride flags, you can use the `neofetch` script from this repo. To prevent command name conflict, I call it `neowofetch` :)
|
||||
|
||||
* Method 1: `pip install hyfetch` then run `neowofetch`
|
||||
* Method 1: `pip install -U hyfetch` then run `neowofetch`
|
||||
* Method 2: `npx neowofetch`
|
||||
* Method 3: `P="$HOME/.local/bin/neowofetch" curl -L nf.hydev.org -o $P && chmod +x $P`
|
||||
* Method 3: `P="$HOME/.local/bin/neowofetch" && curl -L nf.hydev.org -o "$P" && chmod +x "$P"`
|
||||
* Method 4: Run without install `bash <(curl -sL nf.hydev.org)`
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
### Method 1: Install using Python pip (Recommended)
|
||||
### Method 1: Install using pip (Recommended)
|
||||
|
||||
Install Python >= 3.7 first. Then, just do:
|
||||
Even though hyfetch has been rewritten in Rust since 2.0.0, we also published PyPI packages with prebuilt rust binaries to allow seamless transition from the Python version. You can install the rust binaries using pip:
|
||||
|
||||
```sh
|
||||
pip install hyfetch
|
||||
pip install wheel
|
||||
pip install -U hyfetch
|
||||
```
|
||||
|
||||
If a rust binary is not available for your platform (e.g. riscv64), it will automatically fall back to the v1.99.0 Python version.
|
||||
|
||||
### Method 2: Install using system package manager
|
||||
|
||||
Currently, these distributions have existing packages for HyFetch:
|
||||
|
||||
* Universal [Lure.sh](https://lure.sh/): `lure in hyfetch` (Thanks to [@Elara6331](https://github.com/Elara6331))
|
||||
* Arch Linux: `sudo pacman -S hyfetch` (Thanks to [@Aleksana](https://github.com/Aleksanaa) and [@Antiz96](https://github.com/Antiz96))
|
||||
* Fedora Linux: `sudo dnf install hyfetch` (packaged by [@topazus](http://github.com/topazus))
|
||||
* Nix: `nix-env -i hyfetch` (Thanks to [@YisuiDenghua](https://github.com/YisuiDenghua))
|
||||
* Nix Profile: `nix profile install nixpkgs#hyfetch`
|
||||
* Guix: `guix install hyfetch` (Thanks to [@WammKD](https://github.com/WammKD))
|
||||
* Slackware `sbopkg -b hyfetch` Slackware [Slackbuild](https://slackbuilds.org/repository/15.0/desktop/hyfetch/?search=hyfetch) (Thanks to [@bittin](https://github.com/bittin) and Urchlay)
|
||||
* Nix Profile `nix profile install nixpkgs#hyfetch`
|
||||
* Slackware: `sbopkg -b hyfetch` [Slackbuild](https://slackbuilds.org/repository/15.0/desktop/hyfetch/?search=hyfetch) (Thanks to [@bittin](https://github.com/bittin) , willysr (https://github.com/willysr), jebrhansen and Urchlay)
|
||||
* Homebrew: `brew install hyfetch` (Thanks to [@catumin](https://github.com/catumin) and [@osalbahr](https://github.com/osalbahr))
|
||||
* openSUSE Tumbleweed: `zypper in python311-hyfetch` (Thanks to [@catumin](https://github.com/catumin))
|
||||
* Gentoo: `emerge --ask app-misc/hyfetch` (Thanks to [@catumin](https://github.com/catumin))
|
||||
* Debian and Ubuntu `apt install hyfetch` (for Debian flavor >= [Trixie](https://packages.debian.org/trixie/hyfetch), Ubuntu flavor >= [Noble](https://packages.ubuntu.com/noble/hyfetch)) (Thanks to [@catumin](https://github.com/catumin))
|
||||
|
||||
[](https://repology.org/project/hyfetch/versions)
|
||||
|
||||
### Method 3: Install the latest developmental version using git
|
||||
### Method 3: Install using Cargo
|
||||
|
||||
Install Python >= 3.7 first. Then run the following commands:
|
||||
Since hyfetch has been rewritten in Rust since 2.0.0, you can now install it using Cargo:
|
||||
|
||||
```sh
|
||||
git clone https://github.com/hykilpikonna/hyfetch.git
|
||||
cd hyfetch
|
||||
pip install .
|
||||
cargo install hyfetch
|
||||
```
|
||||
|
||||
> [!WARNING]
|
||||
> If you install using Cargo, you would need to manually install dependencies like fastfetch if you want to use it as the backend, and Git Bash if you're on Windows.
|
||||
>
|
||||
> The PyPI package has all the dependencies bundled, so it's recommended to use that instead.
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -67,6 +79,22 @@ Feel free to experiment with it!
|
||||
|
||||

|
||||
|
||||
#### Q: Why do you use pride flag's coloring? I don't think it looks nice at all.
|
||||
|
||||
A: The core idea behind HyFetch coloring isn't just to make logos look nicer, it's about representation and identity. While it's okay to assess the visual appeal, you also need to understand that the LGBTQ+ flag colors serves a much deeper purpose than just aesthetics.
|
||||
|
||||
For many in the LGBTQ+ community, these flags symbolize their identity, struggles, and pride. Integrating these symbols into a showcase of the tech specs they share can provide a sense of empowerment. It's combining their enthusiasm for their favorite distro / hardware with their LGBTQ+ identity.
|
||||
|
||||
Also, by including flag coloring along with the updated neofetch, we're also broadcasting a wider message about the importance of inclusivity and representation. It's not just a design choice, it's a statement that promotes awareness and understanding toward the LGBTQ+ community.
|
||||
|
||||
#### Q: When I use `hyfetch` or `neowofetch` in my MotD, no art displays. How do I get the art back?
|
||||
|
||||
A: Most likely, the `stdout` detection is set to auto and is removing the ascii art and colors. To change this, you can: set `args` in your hyfetch.json to `"--stdout=off"`, add `--stdout=off` to the `neowofetch` command in your motd script, or set the option in $HOME/.config/(neofetch|neowofetch)/config.conf to off.
|
||||
|
||||
#### Q: How can I run HyFetch on Windows?
|
||||
|
||||
A: Install Python > 3.7 and Git > 2.42.0 first. Then, either open Git Bash terminal or install a terminal emulator that can display RGB colors (the default Windows cmd.exe cannot, but the new [Windows Terminal](https://apps.microsoft.com/detail/9N0DX20HK701?hl=en-US&gl=US) can). Then, run `pip install hyfetch` and run `hyfetch`.
|
||||
|
||||
|
||||
## Contributing
|
||||
|
||||
@@ -96,11 +124,209 @@ Updates to `neowofetch` begins with the emoji 🖼️
|
||||
Note: You can install the latest nightly version by using:
|
||||
|
||||
```sh
|
||||
pip install git+https://github.com/hykilpikonna/hyfetch.git@master
|
||||
cargo install --git https://github.com/hykilpikonna/hyfetch
|
||||
```
|
||||
|
||||
<!-- CHANGELOG STARTS HERE --->
|
||||
|
||||
### 2.0.2
|
||||
|
||||
This is a small patch release that adds more flags and fixes some bugs from the recent Rust rewrite.
|
||||
|
||||
* 🏳️🌈 **New Flags**: Added new pride flags for Nullflux ([#397](https://github.com/hykilpikonna/hyfetch/pull/397)), Hypergender ([#422](https://github.com/hykilpikonna/hyfetch/pull/422)), Fictosexual ([#394](https://github.com/hykilpikonna/hyfetch/pull/394)), and Adipophilia ([#424](https://github.com/hykilpikonna/hyfetch/pull/424)).
|
||||
* 🐛 **Bug Fixes**:
|
||||
* Fixed a critical bug where custom `fastfetch` configurations could break hyfetch ([#420](https://github.com/hykilpikonna/hyfetch/pull/420)).
|
||||
* Corrected the `nixos_small` ASCII logo to display properly ([#421](https://github.com/hykilpikonna/hyfetch/pull/421)).
|
||||
* 🔧 **Improvements**:
|
||||
* Improved a warning message for better clarity ([#419](https://github.com/hykilpikonna/hyfetch/issues/419)).
|
||||
|
||||
### 2.0.1
|
||||
|
||||
(changelog is generated by Gemini from commit history)
|
||||
|
||||
**🦀 The Rust Rewrite!**
|
||||
|
||||
This is a massive update, rewriting the entire hyfetch core from Python to Rust for significantly improved performance, reliability, and maintainability. A huge thank you to **@teohhanhui** and all the contributors who made this possible!
|
||||
|
||||
* 🚀 **Complete Rewrite in Rust**: The entire codebase has been ported to Rust, resulting in major performance improvements and a smaller binary size.
|
||||
* ⚙️ **New Backends**: In addition to neofetch and fastfetch, hyfetch now supports **macchina** as a backend option.
|
||||
* 🌈 **Improved June Animation**: The `--june` pride month animation is now smoother, flicker-free ([#408](https://github.com/hykilpikonna/hyfetch/pull/408)).
|
||||
* 🪟 **Native Windows Support**: The Rust version provides much-improved support for Windows.
|
||||
|
||||
**✨ Features & Enhancements**
|
||||
|
||||
* 🎨 **Automatic Theme Detection**: Hyfetch can now automatically detect your terminal's light/dark mode (when auto_detect_light_dark is true) ([#380](https://github.com/hykilpikonna/hyfetch/pull/380)).
|
||||
* ✍️ **Font Logos**: Added a new feature to display a logo created from your system's font.
|
||||
* 🌐 **Cloudflare for Public IP**: Now uses Cloudflare to fetch the public IP address, with a fallback option ([#416](https://github.com/hykilpikonna/hyfetch/pull/416)).
|
||||
* 🖼️ **Interactive Logo Selection**: An interactive setup step now allows you to choose between default and small logo variants for your distro ([#392](https://github.com/hykilpikonna/hyfetch/pull/392)).
|
||||
* 🏳️🌈 **New Pride Flags**: Added flags for Cisgender ([#386](https://github.com/hykilpikonna/hyfetch/pull/386)), Kessoku Band ([#384](https://github.com/hykilpikonna/hyfetch/pull/384)), and Watermelon Cream Lozenges ([#369](https://github.com/hykilpikonna/hyfetch/pull/369)) for memes.
|
||||
* 📄 **Page Navigation**: Added `n` and `p` as shorthands for next/previous page selection and implemented page number roll-over ([#372](https://github.com/hykilpikonna/hyfetch/pull/372)).
|
||||
|
||||
**🖼️ New & Updated Distro Support**
|
||||
|
||||
* **Added Bazzite** ([#406](https://github.com/hykilpikonna/hyfetch/pull/406))
|
||||
* **Added Rhino Linux Logo** ([#407](https://github.com/hykilpikonna/hyfetch/pull/407))
|
||||
* **Updated openSUSE Logos & Added Slowroll**
|
||||
* **Updated KSLinux Detection** ([#395](https://github.com/hykilpikonna/hyfetch/pull/395))
|
||||
|
||||
**🐛 Bug Fixes**
|
||||
|
||||
* **macOS**: Fixed CPU and memory fetching on older macOS versions like Leopard and Tiger ([#387](https://github.com/hykilpikonna/hyfetch/pull/387), [#389](https://github.com/hykilpikonna/hyfetch/pull/389)).
|
||||
* **Packaging**: Resolved several issues with `cargo publish` to ensure reliable package deployment ([#405](https://github.com/hykilpikonna/hyfetch/pull/405)).
|
||||
* **Performance**: Sped up RPM package counting by skipping digest and signature verification ([#371](https://github.com/hykilpikonna/hyfetch/pull/371)).
|
||||
* **Animation**: Updated logic to ensure the pride month animation is always shown when `--june` is explicitly used ([#411](https://github.com/hykilpikonna/hyfetch/pull/411)).
|
||||
* **General**: Fixed numerous bugs related to builds, path detection, cache handling, and distro name detection.
|
||||
* **Formatting**: Fixed an unwanted space in the Python version output ([#401](https://github.com/hykilpikonna/hyfetch/pull/401)).
|
||||
|
||||
**🔧 Maintenance**
|
||||
|
||||
* **Documentation**: Updated the README with additional credits for Slackware contributors ([#365](https://github.com/hykilpikonna/hyfetch/pull/365)).
|
||||
* **Build System**: Overhauled the build scripts for Rust, including support for `musl` static builds and cross-compilation for macOS and Windows.
|
||||
|
||||
### 1.99.0
|
||||
|
||||
This version would be the last version of HyFetch on Python as we migrate to Rust (Huge thanks to everyone on [#317](https://github.com/hykilpikonna/hyfetch/pull/317)!). It will also be an effort to start a transition that phases out the neowofetch/neofetch backend in favor of FastFetch, since the time needed to maintain the NF backend currently exceed our capacity. If you are willing to help maintaining it, please let us know!
|
||||
|
||||
* 🌈 **Improve Windows support**
|
||||
* 🌈 **Include FastFetch into HyFetch PyPI package**
|
||||
* 🌈 Detached our fork from neofetch
|
||||
* 🌈 Build architecture-specific wheels for PyPI
|
||||
* 🌈 Add plural flag (bc8499e2)
|
||||
* 🌈 Add genderflux and girlflux flags ([#263](https://github.com/hykilpikonna/hyfetch/pull/263))
|
||||
* 🌈 Add Fraysexual flag ([#277](https://github.com/hykilpikonna/hyfetch/pull/277))
|
||||
* 🌈 Add Xenogender flag ([#309](https://github.com/hykilpikonna/hyfetch/pull/309))
|
||||
* 🌈 Add Caninekin flag ([#318](https://github.com/hykilpikonna/hyfetch/pull/318))
|
||||
* 🌈 Add Kenochoric, veldian, solian, lunian flags ([#331](https://github.com/hykilpikonna/hyfetch/pull/331))
|
||||
* 🌈 Add Polyamorous, sapphic, androgyne, interprogress, progress, intersex, equal-rights, drag, neofluid, genderqueer, and pronoun flags ([#342](https://github.com/hykilpikonna/hyfetch/pull/342))
|
||||
* 🌈 Add Gilbert Baker's original rainbow flag ([#284](https://github.com/hykilpikonna/hyfetch/pull/284))
|
||||
* 🌈 Add Queer subculture flags ([#302](https://github.com/hykilpikonna/hyfetch/pull/302))
|
||||
* 🌈 Add random flag option ([#334](https://github.com/hykilpikonna/hyfetch/pull/334))
|
||||
* 🌈 Fix distro logo triple-quotation mark escaping ([#222](https://github.com/hykilpikonna/hyfetch/pull/222))
|
||||
* 🌈 Fix Windows encoding issue on non-English systems ([#294](https://github.com/hykilpikonna/hyfetch/pull/294))
|
||||
* 🌈 Fix termux compatibility ([#286](https://github.com/hykilpikonna/hyfetch/pull/286))
|
||||
* 🌈 Fix term background detection not resetting properly ([#298](https://github.com/hykilpikonna/hyfetch/pull/298))
|
||||
* 🌈 Make typing-extensions optional ([#299](https://github.com/hykilpikonna/hyfetch/pull/299))
|
||||
* 🌈 Remove setuptools dependency ([#325](https://github.com/hykilpikonna/hyfetch/pull/325))
|
||||
* 🌈 Allow lightness value without a '%' sign in config prompt ([#307](https://github.com/hykilpikonna/hyfetch/pull/307))
|
||||
* 🌈 Fix Windows 7 and Python 3.7.0 support.
|
||||
* 🖼 OS - Update Apple hardware ID list ([#256](https://github.com/hykilpikonna/hyfetch/pull/256))
|
||||
* 🖼 OS - Remove Lilu detection for hackintosh ([#310](https://github.com/hykilpikonna/hyfetch/pull/310))
|
||||
* 🖼 OS - Support host info on PowerPC Macs ([#341](https://github.com/hykilpikonna/hyfetch/pull/341))
|
||||
* 🖼 DE - Show Kinfo for Plasma 6 ([#269](https://github.com/hykilpikonna/hyfetch/pull/269))
|
||||
* 🖼 GPU - Fix GPU not displaying in Haiku (dylanaraps#2448)
|
||||
* 🖼 GPU - List all intel GPU as detected ([#348](https://github.com/hykilpikonna/hyfetch/pull/348))
|
||||
* 🖼 Distro - Add eweOS ([#252](https://github.com/hykilpikonna/hyfetch/pull/252))
|
||||
* 🖼 Distro - Add Fedora Immutable distros (dylanaraps#2434)
|
||||
* 🖼 Distro - Add Macaroni OS (dylanaraps#2424)
|
||||
* 🖼 Distro - Add Ironclad OS ([#219](https://github.com/hykilpikonna/hyfetch/pull/219))
|
||||
* 🖼 Distro - Add Chimera Linux ([#285](https://github.com/hykilpikonna/hyfetch/pull/285))
|
||||
* 🖼 Distro - Add Tatra (dylanaraps#2439)
|
||||
* 🖼 Distro - Add Furreto Linux ([#290](https://github.com/hykilpikonna/hyfetch/pull/290))
|
||||
* 🖼 Distro - Add BlackMesa ([#316](https://github.com/hykilpikonna/hyfetch/pull/316))
|
||||
* 🖼 Distro - Add Magix ([#338](https://github.com/hykilpikonna/hyfetch/pull/338))
|
||||
* 🖼 Distro - Add Mauna ([#343](https://github.com/hykilpikonna/hyfetch/pull/343))
|
||||
* 🖼 Distro - Add Arkane Linux ([#321](https://github.com/hykilpikonna/hyfetch/pull/321))
|
||||
* 🖼 Distro - Add Linux From Scratch ([#336](https://github.com/hykilpikonna/hyfetch/pull/336))
|
||||
* 🖼 Distro - Fix debian version on Ubuntu ([#195](https://github.com/hykilpikonna/hyfetch/pull/195))
|
||||
* 🖼 Ascii - Update PikaOS logo ([#231](https://github.com/hykilpikonna/hyfetch/pull/231))
|
||||
* 🖼 Ascii - Add Fedora unicode logo ([#238](https://github.com/hykilpikonna/hyfetch/pull/238))
|
||||
* 🖼 Ascii - Fix colors not reverting properly ([#314](https://github.com/hykilpikonna/hyfetch/pull/314))
|
||||
* 🖼 Ascii - Fix AmogOS backslash escape ([#339](https://github.com/hykilpikonna/hyfetch/pull/339))
|
||||
* 🖼 Ascii - Add colorful NixOS logo ([#311](https://github.com/hykilpikonna/hyfetch/pull/311))
|
||||
* 🖼 Terminal - Fix terminal emulator selection ([#220](https://github.com/hykilpikonna/hyfetch/pull/220))
|
||||
* 🖼 Terminal - Fix terminal font info for yakuake ([#235](https://github.com/hykilpikonna/hyfetch/pull/235))
|
||||
* 🖼 Terminal - Add Apple Terminal ([#272](https://github.com/hykilpikonna/hyfetch/pull/272))
|
||||
* 🖼 Editor - Display neovim version ([#267](https://github.com/hykilpikonna/hyfetch/pull/267))
|
||||
* 🖼 Package - Add an option to hide some package managers ([#257](https://github.com/hykilpikonna/hyfetch/pull/257))
|
||||
* 🖼 Package - Add "AM" application manager ([#234](https://github.com/hykilpikonna/hyfetch/pull/234))
|
||||
* 🖼 Package - Fix npm list count mismatch ([#240](https://github.com/hykilpikonna/hyfetch/pull/240))
|
||||
* 🖼 Package - Add pnpm ([#288](https://github.com/hykilpikonna/hyfetch/pull/288))
|
||||
* 🖼 Package - Add pkgx.sh ([#265](https://github.com/hykilpikonna/hyfetch/pull/265))
|
||||
* 🖼 Package - Add pip, bonsai, rad, radula, birb ([#337](https://github.com/hykilpikonna/hyfetch/pull/337))
|
||||
* 🖼 Package - Add MacPorts for Linux support ([#340](https://github.com/hykilpikonna/hyfetch/pull/340))
|
||||
* 🖼 Package - Use XDG path for Nix package counting ([#255](https://github.com/hykilpikonna/hyfetch/pull/255))
|
||||
* 🖼 Package - Fix short package count ([#305](https://github.com/hykilpikonna/hyfetch/pull/305))
|
||||
* 🖼 Song - Add Cider player ([#245](https://github.com/hykilpikonna/hyfetch/pull/245))
|
||||
* 🖼 Network - Fix network speed detection on macOS ([#360](https://github.com/hykilpikonna/hyfetch/pull/360))
|
||||
|
||||
### 1.4.11
|
||||
|
||||
* 🌈 Add ability to set backend args in hyfetch config file ([#181](https://github.com/hykilpikonna/hyfetch/pull/181))
|
||||
* 🌈 Update makefile to be able to install hyfetch ([#174](https://github.com/hykilpikonna/hyfetch/pull/174))
|
||||
* 🌈 Fix config file argument ([#177](https://github.com/hykilpikonna/hyfetch/pull/177))
|
||||
* 🌈 Support pipx installation ([#188](https://github.com/hykilpikonna/hyfetch/pull/188), [#192](https://github.com/hykilpikonna/hyfetch/pull/192))
|
||||
* 🌈 Create package for Debian, OpenSUSE, Homebrew, Gentoo, and lure.sh
|
||||
([#184](https://github.com/hykilpikonna/hyfetch/pull/184), [#194](https://github.com/hykilpikonna/hyfetch/pull/194), [#207](https://github.com/hykilpikonna/hyfetch/pull/207), [#206](https://github.com/hykilpikonna/hyfetch/pull/206)) Huge thanks to @catumin!
|
||||
* 🖼 DE - Fix DE empty bracket in macOS ([#172](https://github.com/hykilpikonna/hyfetch/pull/172))
|
||||
* 🖼 OS - Disable Hackintosh check on arm64 processors ([dylanaraps#2396](https://github.com/dylanaraps/neofetch/pull/2396))
|
||||
* 🖼 OS - Add Windows NT ([#217](https://github.com/hykilpikonna/hyfetch/pull/217))
|
||||
* 🖼 Distro - Fixed Kubuntu recognized as Ubuntu ([dylanaraps#2411](https://github.com/dylanaraps/neofetch/pull/2411))
|
||||
* 🖼 Distro - Use /etc/debian_version to get .x on Debian ([#191](https://github.com/hykilpikonna/hyfetch/pull/191))
|
||||
* 🖼 Distro - Add LainOS ([#190](https://github.com/hykilpikonna/hyfetch/pull/190))
|
||||
* 🖼 Distro - Add aerOS ([dylanaraps#2360](https://github.com/dylanaraps/neofetch/pull/2360))
|
||||
* 🖼 Distro - Add Xenia ([#197](https://github.com/hykilpikonna/hyfetch/pull/197))
|
||||
* 🖼 Distro - Add EndeavourOS Small Option ([dylanaraps#2391](https://github.com/dylanaraps/neofetch/pull/2391))
|
||||
* 🖼 Distro - Add AZOS ([dylanaraps#2339](https://github.com/dylanaraps/neofetch/pull/2339))
|
||||
* 🖼 Distro - Add MainsailOS ([dylanaraps#2407](https://github.com/dylanaraps/neofetch/pull/2407))
|
||||
* 🖼 Distro - Add Interix ([dylanaraps#2409](https://github.com/dylanaraps/neofetch/pull/2409))
|
||||
* 🖼 Distro - Add Peropesis Linux ([dylanaraps#2414](https://github.com/dylanaraps/neofetch/pull/2414))
|
||||
* 🖼 Distro - Add Adélie Linux ([#218](https://github.com/hykilpikonna/hyfetch/pull/218))
|
||||
* 🖼 Distro - Add Xray_OS ([dylanaraps#2413](https://github.com/dylanaraps/neofetch/pull/2413))
|
||||
* 🖼 Ascii - Update AOSC logo ([#185](https://github.com/hykilpikonna/hyfetch/pull/185))
|
||||
* 🖼 Ascii - Update phyOS logo ([#211](https://github.com/hykilpikonna/hyfetch/pull/211))
|
||||
* 🖼 Ascii - Update Parch logo ([dylanaraps#2045](https://github.com/dylanaraps/neofetch/pull/2045))
|
||||
* 🖼 Ascii - Add linux_small ([dylanaraps#2417](https://github.com/dylanaraps/neofetch/pull/2417))
|
||||
* 🖼 Bug Fix - Fix color blocks for bash !=3 & <5 ([#170](https://github.com/hykilpikonna/hyfetch/pull/170))
|
||||
* 🖼 Bug Fix - Use sed -r instead of -E when using GNU sed ([#171](https://github.com/hykilpikonna/hyfetch/pull/171))
|
||||
* 🖼 Resolution - Improved MacOS resolution detection ([dylanaraps#2356](https://github.com/dylanaraps/neofetch/pull/2356))
|
||||
* 🖼 Terminal - Add support for alacritty's new config format ([#202](https://github.com/hykilpikonna/hyfetch/pull/202))
|
||||
* 🖼 Terminal - Check for newer xfce4-term config ([#214](https://github.com/hykilpikonna/hyfetch/pull/214))
|
||||
* 🖼 Package - Add support for npm global packages ([#215](https://github.com/hykilpikonna/hyfetch/pull/215))
|
||||
|
||||
### 1.4.10
|
||||
|
||||
* 🌈 Add support for qwqfetch backend ([#148](https://github.com/hykilpikonna/hyfetch/pull/148))
|
||||
* 🌈 Add nonhuman-unity flag ([#139](https://github.com/hykilpikonna/hyfetch/pull/139))
|
||||
* 🌈 Add gynesexual, androsexual flags ([#157](https://github.com/hykilpikonna/hyfetch/pull/157))
|
||||
* 🌈 Add option to disable pride month animation ([#134](https://github.com/hykilpikonna/hyfetch/pull/134))
|
||||
* 🌈 Make ^C error message less aggressive (?)
|
||||
* 🌈 Fix: Should not assume ~/.config is writable ([#136](https://github.com/hykilpikonna/hyfetch/pull/136))
|
||||
* 🌈 Fix: Foreground-background arrangement not detected ([#154](https://github.com/hykilpikonna/hyfetch/pull/154))
|
||||
* 🖼 OS - Update macOS version name list ([#140](https://github.com/hykilpikonna/hyfetch/pull/140))
|
||||
* 🖼 Ascii - Improve color removal ([#161](https://github.com/hykilpikonna/hyfetch/pull/161))
|
||||
* 🖼 Ascii - Fix reset character performance ([#158](https://github.com/hykilpikonna/hyfetch/pull/158))
|
||||
* 🖼 Distro - Smoothen the Tumbleweed logo ([dylanaraps#2342](https://github.com/dylanaraps/neofetch/pull/2342))
|
||||
* 🖼 Distro - Update RebornOS logo ([dylanaraps#2358](https://github.com/dylanaraps/neofetch/pull/2358))
|
||||
* 🖼 Distro - Update Venom Linux logo ([#166](https://github.com/hykilpikonna/hyfetch/pull/166))
|
||||
* 🖼 Distro - Add Windows 95 ASCII logo ([dylanaraps#2346](https://github.com/dylanaraps/neofetch/pull/2346))
|
||||
* 🖼 Distro - Add ParchLinux ([dylanaraps#2045](https://github.com/dylanaraps/neofetch/pull/2045))
|
||||
* 🖼 Distro - Add OpenKylin ([dylanaraps#2341](https://github.com/dylanaraps/neofetch/pull/2341))
|
||||
* 🖼 Distro - Add EvolutionOS ([dylanaraps#2350](https://github.com/dylanaraps/neofetch/pull/2350))
|
||||
* 🖼 Distro - Add Salix ([dylanaraps#2357](https://github.com/dylanaraps/neofetch/pull/2357))
|
||||
* 🖼 Distro - Add Panwah ([dylanaraps#2355](https://github.com/dylanaraps/neofetch/pull/2355))
|
||||
* 🖼 Distro - Add PhyOS ([#142](https://github.com/hykilpikonna/hyfetch/pull/142))
|
||||
* 🖼 Distro - Add Athena OS ([#130](https://github.com/hykilpikonna/hyfetch/pull/130))
|
||||
* 🖼 Distro - Add Meowix ([#159](https://github.com/hykilpikonna/hyfetch/pull/159))
|
||||
* 🖼 Distro - Add Slackel ([#167](https://github.com/hykilpikonna/hyfetch/pull/167))
|
||||
* 🖼 Distro - Support *Wrt variants ([dylanaraps#2352](https://github.com/dylanaraps/neofetch/pull/2352))
|
||||
* 🖼 Version - Fix a typo that broke OS detection on WSL ([#155](https://github.com/hykilpikonna/hyfetch/pull/155))
|
||||
* 🖼 Packages - Implement --package_separate flag ([#135](https://github.com/hykilpikonna/hyfetch/pull/135))
|
||||
* 🖼 Packages - Separate flatpak-system and flatpak-user ([#135](https://github.com/hykilpikonna/hyfetch/pull/135))
|
||||
* 🖼 Packages - Add steam as a package manager ([#152](https://github.com/hykilpikonna/hyfetch/pull/152))
|
||||
* 🖼 Packages - Add squirrel package manager ([#153](https://github.com/hykilpikonna/hyfetch/pull/153))
|
||||
* 🖼 Packages - Make cargo run on all systems ([#146](https://github.com/hykilpikonna/hyfetch/pull/146))
|
||||
* 🖼 Packages - Fix cargo package count ([#144](https://github.com/hykilpikonna/hyfetch/pull/144))
|
||||
* 🖼 Packages - Add Devbox package manager ([#137](https://github.com/hykilpikonna/hyfetch/pull/137))
|
||||
* 🖼 Packages - Fix phantom package when pm command fails ([#145](https://github.com/hykilpikonna/hyfetch/pull/145))
|
||||
* 🖼 Packages - Update scratch package manager ([#165](https://github.com/hykilpikonna/hyfetch/pull/165))
|
||||
* 🖼 Editor - Better version detection
|
||||
* 🖼 Resolution - Improve macOS resolution detection ([dylanaraps#2356](https://github.com/dylanaraps/neofetch/pull/2356))
|
||||
* 🖼 Resolution - Add resolution lookup for iOS ([#164](https://github.com/hykilpikonna/hyfetch/pull/164))
|
||||
* 🖼 Desktop - Display global KDE Plasma theme ([#163](https://github.com/hykilpikonna/hyfetch/pull/163))
|
||||
* 🖼 IP - Improve macOS local IP detection ([dylanaraps#2362](https://github.com/dylanaraps/neofetch/pull/2362))
|
||||
* 🖼 IP - Fix macOS route hangs on reverse DNS lookup
|
||||
* 🖼 Config - Allow specifying default config to copy to ~/.config ([#133](https://github.com/hykilpikonna/hyfetch/pull/133))
|
||||
|
||||
### 1.4.9
|
||||
|
||||
* 🌈 Add pride month easter-egg animation! ⭐️
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
[package]
|
||||
name = "hyfetch"
|
||||
version = { workspace = true }
|
||||
authors = { workspace = true }
|
||||
edition = { workspace = true }
|
||||
rust-version = { workspace = true }
|
||||
description = { workspace = true }
|
||||
repository = { workspace = true }
|
||||
license = { workspace = true }
|
||||
default-run = "hyfetch"
|
||||
|
||||
[dependencies]
|
||||
aho-corasick = { workspace = true, features = ["perf-literal", "std"] }
|
||||
ansi_colours = { workspace = true, features = [] }
|
||||
anstream = { workspace = true, features = [], optional = true }
|
||||
anyhow = { workspace = true, features = ["std"] }
|
||||
bpaf = { workspace = true, features = [] }
|
||||
crossterm = { workspace = true, features = [] }
|
||||
deranged = { workspace = true, features = ["serde", "std"] }
|
||||
directories = { workspace = true, features = [] }
|
||||
enterpolation = { workspace = true, features = ["bspline", "std"] }
|
||||
fastrand = { workspace = true, features = ["std"] }
|
||||
indexmap = { workspace = true, features = ["serde", "std"] }
|
||||
itertools = { workspace = true, features = ["use_std"] }
|
||||
palette = { workspace = true, features = ["std"] }
|
||||
serde = { workspace = true, features = ["derive", "std"] }
|
||||
serde_json = { workspace = true, features = ["std"] }
|
||||
serde_path_to_error = { workspace = true, features = [] }
|
||||
shell-words = { workspace = true, features = ["std"] }
|
||||
strum = { workspace = true, features = ["derive", "std"] }
|
||||
supports-color = { workspace = true, features = [] }
|
||||
tempfile = { workspace = true, features = [] }
|
||||
terminal-colorsaurus = { workspace = true, features = [] }
|
||||
terminal_size = { workspace = true, features = [] }
|
||||
thiserror = { workspace = true, features = [] }
|
||||
time = { workspace = true, features = ["local-offset", "std"] }
|
||||
toml_edit = { workspace = true, features = [], optional = true }
|
||||
tracing = { workspace = true, features = ["attributes", "std"] }
|
||||
tracing-subscriber = { workspace = true, features = ["ansi", "fmt", "smallvec", "std", "tracing-log"] }
|
||||
unicode-segmentation = { workspace = true, features = [] }
|
||||
which = { workspace = true, features = [] }
|
||||
|
||||
[build-dependencies]
|
||||
indexmap = { workspace = true, features = ["std"] }
|
||||
regex = { workspace = true, features = ["perf", "std", "unicode"] }
|
||||
unicode-normalization = { workspace = true, features = ["std"] }
|
||||
fs_extra = "1.3.0"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
enable-ansi-support = { workspace = true, features = [] }
|
||||
normpath = { workspace = true, features = [] }
|
||||
same-file = { workspace = true, features = [] }
|
||||
crossterm = { workspace = true, features = ["windows"] }
|
||||
|
||||
[features]
|
||||
default = ["autocomplete", "color", "macchina"]
|
||||
autocomplete = ["bpaf/autocomplete"]
|
||||
color = ["bpaf/dull-color"]
|
||||
macchina = ["dep:anstream", "dep:toml_edit", "toml_edit/display"]
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
@@ -0,0 +1,273 @@
|
||||
use std::env;
|
||||
use std::fmt::Write as _;
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use fs_extra::dir::{CopyOptions};
|
||||
use indexmap::IndexMap;
|
||||
use regex::Regex;
|
||||
use unicode_normalization::UnicodeNormalization as _;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct AsciiDistro {
|
||||
pattern: String,
|
||||
art: String,
|
||||
}
|
||||
|
||||
impl AsciiDistro {
|
||||
fn friendly_name(&self) -> String {
|
||||
self.pattern
|
||||
.split('|')
|
||||
.next()
|
||||
.expect("invalid distro pattern")
|
||||
.trim_matches(|c: char| c.is_ascii_punctuation() || c == ' ')
|
||||
.replace(['"', '*'], "")
|
||||
}
|
||||
}
|
||||
|
||||
fn anything_that_exist(paths: &[&Path]) -> Option<PathBuf> {
|
||||
paths.iter().copied().find(|p| p.exists()).map(Path::to_path_buf)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// Path hack to make file paths work in both workspace and manifest directory
|
||||
let dir = PathBuf::from(env::var_os("CARGO_WORKSPACE_DIR").unwrap_or_else(|| env::var_os("CARGO_MANIFEST_DIR").unwrap()));
|
||||
let o = PathBuf::from(env::var_os("OUT_DIR").unwrap());
|
||||
|
||||
for file in &["neofetch", "hyfetch"] {
|
||||
let src = anything_that_exist(&[
|
||||
&dir.join(file),
|
||||
&dir.join("../../").join(file),
|
||||
]).expect("couldn't find neofetch");
|
||||
let dst = o.join(file);
|
||||
println!("cargo:rerun-if-changed={}", src.display());
|
||||
|
||||
// Copy either file or directory
|
||||
if src.is_dir() {
|
||||
let opt = CopyOptions { overwrite: true, copy_inside: true, ..CopyOptions::default() };
|
||||
fs_extra::dir::copy(&src, &dst, &opt).expect("Failed to copy directory to OUT_DIR");
|
||||
}
|
||||
else { fs::copy(&src, &dst).expect("Failed to copy file to OUT_DIR"); }
|
||||
}
|
||||
|
||||
export_distros(&o.join("neofetch"), &o);
|
||||
}
|
||||
|
||||
fn export_distros<P>(neofetch_path: P, out_path: &Path)
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
let distros = parse_ascii_distros(neofetch_path);
|
||||
let mut variants = IndexMap::with_capacity(distros.len());
|
||||
|
||||
for distro in &distros {
|
||||
let variant = distro
|
||||
.friendly_name()
|
||||
.replace(|c: char| c.is_ascii_punctuation() || c == ' ', "_")
|
||||
.nfc()
|
||||
.collect::<String>();
|
||||
if variants.contains_key(&variant) {
|
||||
let variant_fallback = format!("{variant}_fallback");
|
||||
if variants.contains_key(&variant_fallback) {
|
||||
todo!("too many name clashes in ascii distro patterns: {variant}");
|
||||
}
|
||||
variants.insert(variant_fallback, distro);
|
||||
continue;
|
||||
}
|
||||
variants.insert(variant, distro);
|
||||
}
|
||||
|
||||
let mut buf = r###"
|
||||
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub enum Distro {
|
||||
"###
|
||||
.to_owned();
|
||||
|
||||
for (variant, AsciiDistro { pattern, .. }) in &variants {
|
||||
write!(
|
||||
buf,
|
||||
r###"
|
||||
// {pattern})
|
||||
{variant},
|
||||
"###,
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
buf.push_str(
|
||||
r###"
|
||||
}
|
||||
|
||||
impl Distro {
|
||||
pub fn detect<S>(name: S) -> Option<Self>
|
||||
where
|
||||
S: AsRef<str>,
|
||||
{
|
||||
let name = name.as_ref().to_lowercase();
|
||||
"###,
|
||||
);
|
||||
|
||||
for (variant, AsciiDistro { pattern, .. }) in &variants {
|
||||
let patterns = pattern.split('|').map(|s| s.trim());
|
||||
let mut conds = Vec::new();
|
||||
|
||||
for m in patterns {
|
||||
let stripped = m.trim_matches(['*', '\'', '"']).to_lowercase();
|
||||
|
||||
if stripped.contains(['*', '"']) {
|
||||
if let Some((prefix, suffix)) = stripped.split_once(r#""*""#) {
|
||||
conds.push(format!(
|
||||
r#"name.starts_with("{prefix}") && name.ends_with("{suffix}")"#
|
||||
));
|
||||
continue;
|
||||
}
|
||||
todo!("cannot properly parse: {m}");
|
||||
}
|
||||
|
||||
// Exact matches
|
||||
if m.trim_matches('*') == m {
|
||||
conds.push(format!(r#"name == "{stripped}""#));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Both sides are *
|
||||
if m.starts_with('*') && m.ends_with('*') {
|
||||
conds.push(format!(
|
||||
r#"name.starts_with("{stripped}") || name.ends_with("{stripped}")"#
|
||||
));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ends with *
|
||||
if m.ends_with('*') {
|
||||
conds.push(format!(r#"name.starts_with("{stripped}")"#));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Starts with *
|
||||
if m.starts_with('*') {
|
||||
conds.push(format!(r#"name.ends_with("{stripped}")"#));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let condition = conds.join(" || ");
|
||||
|
||||
write!(
|
||||
buf,
|
||||
r###"
|
||||
if {condition} {{
|
||||
return Some(Self::{variant});
|
||||
}}
|
||||
"###
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
buf.push_str(
|
||||
r###"
|
||||
None
|
||||
}
|
||||
|
||||
pub fn ascii_art(&self) -> &str {
|
||||
let art = match self {
|
||||
"###,
|
||||
);
|
||||
|
||||
let quotes = "#".repeat(80);
|
||||
for (variant, AsciiDistro { art, .. }) in &variants {
|
||||
write!(
|
||||
buf,
|
||||
r###"
|
||||
Self::{variant} => r{quotes}"
|
||||
{art}
|
||||
"{quotes},
|
||||
"###,
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
buf.push_str(
|
||||
r###"
|
||||
};
|
||||
&art[1..art.len().checked_sub(1).unwrap()]
|
||||
}
|
||||
}
|
||||
"###,
|
||||
);
|
||||
|
||||
fs::write(out_path.join("distros.rs"), buf).expect("couldn't write distros.rs");
|
||||
}
|
||||
|
||||
/// Parses ascii distros from neofetch script.
|
||||
fn parse_ascii_distros<P>(neofetch_path: P) -> Vec<AsciiDistro>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
let neofetch_path = neofetch_path.as_ref();
|
||||
|
||||
let nf = {
|
||||
let nf = fs::read_to_string(neofetch_path).expect("couldn't read neofetch script");
|
||||
|
||||
// Get the content of "get_distro_ascii" function
|
||||
let (_, nf) = nf
|
||||
.split_once("get_distro_ascii() {\n")
|
||||
.expect("couldn't find get_distro_ascii function");
|
||||
let (nf, _) = nf
|
||||
.split_once("\n}\n")
|
||||
.expect("couldn't find end of get_distro_ascii function");
|
||||
|
||||
let mut nf = nf.replace('\t', &" ".repeat(4));
|
||||
|
||||
// Remove trailing spaces
|
||||
while nf.contains(" \n") {
|
||||
nf = nf.replace(" \n", "\n");
|
||||
}
|
||||
nf
|
||||
};
|
||||
|
||||
let case_re = Regex::new(r"case .*? in\n").expect("couldn't compile case regex");
|
||||
let eof_re = Regex::new(r"EOF[ \n]*?;;").expect("couldn't compile eof regex");
|
||||
|
||||
// Split by blocks
|
||||
let mut blocks = Vec::new();
|
||||
for b in case_re.split(&nf) {
|
||||
blocks.extend(eof_re.split(b).map(|sub| sub.trim()));
|
||||
}
|
||||
|
||||
// Parse blocks
|
||||
fn parse_block(block: &str) -> Option<AsciiDistro> {
|
||||
let (block, art) = block.split_once("'EOF'\n")?;
|
||||
|
||||
// Join \
|
||||
//
|
||||
// > A <backslash> that is not quoted shall preserve the literal value of the
|
||||
// > following character, with the exception of a <newline>. If a <newline>
|
||||
// > follows the <backslash>, the shell shall interpret this as line
|
||||
// > continuation. The <backslash> and <newline> shall be removed before
|
||||
// > splitting the input into tokens. Since the escaped <newline> is removed
|
||||
// > entirely from the input and is not replaced by any white space, it cannot
|
||||
// > serve as a token separator.
|
||||
// See https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_02_01
|
||||
let block = block.replace("\\\n", "");
|
||||
|
||||
// Get case pattern
|
||||
let pattern = block
|
||||
.split('\n')
|
||||
.next()
|
||||
.and_then(|pattern| pattern.trim().strip_suffix(')'))?;
|
||||
|
||||
// Unescape backslashes here because backslashes are escaped in neofetch
|
||||
// for printf
|
||||
let art = art.replace(r"\\", r"\");
|
||||
|
||||
Some(AsciiDistro {
|
||||
pattern: pattern.to_owned(),
|
||||
art,
|
||||
})
|
||||
}
|
||||
blocks
|
||||
.iter()
|
||||
.filter_map(|block| parse_block(block))
|
||||
.collect()
|
||||
}
|
||||
@@ -0,0 +1,402 @@
|
||||
use std::borrow::Cow;
|
||||
use std::fmt::Write as _;
|
||||
use std::ops::Range;
|
||||
|
||||
use aho_corasick::AhoCorasick;
|
||||
use anyhow::{Context as _, Result};
|
||||
use indexmap::IndexMap;
|
||||
use tracing::debug;
|
||||
use unicode_segmentation::UnicodeSegmentation;
|
||||
|
||||
use crate::color_util::{
|
||||
color, ForegroundBackground, NeofetchAsciiIndexedColor, ToAnsiString as _,
|
||||
};
|
||||
use crate::neofetch_util::{
|
||||
ascii_size, ColorAlignment, NEOFETCH_COLORS_AC, NEOFETCH_COLOR_PATTERNS,
|
||||
};
|
||||
use crate::presets::ColorProfile;
|
||||
use crate::types::{AnsiMode, TerminalTheme};
|
||||
|
||||
/// Raw ascii art before any processing.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct RawAsciiArt {
|
||||
pub asc: String,
|
||||
pub fg: Vec<NeofetchAsciiIndexedColor>,
|
||||
}
|
||||
|
||||
/// Normalized ascii art where every line has the same width.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct NormalizedAsciiArt {
|
||||
pub lines: Vec<String>,
|
||||
pub w: u8,
|
||||
pub h: u8,
|
||||
pub fg: Vec<NeofetchAsciiIndexedColor>,
|
||||
}
|
||||
|
||||
/// Recolored ascii art with all color codes replaced.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct RecoloredAsciiArt {
|
||||
pub lines: Vec<String>,
|
||||
pub w: u8,
|
||||
pub h: u8,
|
||||
}
|
||||
|
||||
impl RawAsciiArt {
|
||||
/// Makes sure every line is the same width.
|
||||
#[tracing::instrument(level = "debug", skip(self))]
|
||||
pub fn to_normalized(&self) -> Result<NormalizedAsciiArt> {
|
||||
debug!("normalize ascii");
|
||||
|
||||
let (w, h) = ascii_size(&self.asc).context("failed to get ascii size")?;
|
||||
|
||||
let lines = self
|
||||
.asc
|
||||
.lines()
|
||||
.map(|line| {
|
||||
let (line_w, _) = ascii_size(line).unwrap();
|
||||
let pad = " ".repeat(usize::from(w.checked_sub(line_w).unwrap()));
|
||||
format!("{line}{pad}")
|
||||
})
|
||||
.collect();
|
||||
|
||||
Ok(NormalizedAsciiArt {
|
||||
lines,
|
||||
w,
|
||||
h,
|
||||
fg: self.fg.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl NormalizedAsciiArt {
|
||||
/// Uses a color alignment to recolor the ascii art.
|
||||
#[tracing::instrument(level = "debug", skip(self), fields(self.w = self.w, self.h = self.h))]
|
||||
pub fn to_recolored(
|
||||
&self,
|
||||
color_align: &ColorAlignment,
|
||||
color_profile: &ColorProfile,
|
||||
color_mode: AnsiMode,
|
||||
theme: TerminalTheme,
|
||||
) -> Result<RecoloredAsciiArt> {
|
||||
debug!("recolor ascii");
|
||||
|
||||
if self.lines.is_empty() {
|
||||
return Ok(RecoloredAsciiArt {
|
||||
lines: self.lines.clone(),
|
||||
w: 0,
|
||||
h: 0,
|
||||
});
|
||||
}
|
||||
|
||||
let reset = color("&~&*", color_mode).expect("color reset should not be invalid");
|
||||
|
||||
let lines = match (color_align, self) {
|
||||
(ColorAlignment::Horizontal, Self { fg, .. }) => {
|
||||
let Self { lines, .. } = self
|
||||
.fill_starting()
|
||||
.context("failed to fill in starting neofetch color codes")?;
|
||||
|
||||
let ac = NEOFETCH_COLORS_AC
|
||||
.get_or_init(|| AhoCorasick::new(NEOFETCH_COLOR_PATTERNS).unwrap());
|
||||
|
||||
// Replace foreground colors
|
||||
let asc = {
|
||||
let asc = lines.join("\n");
|
||||
let mut replacements = NEOFETCH_COLOR_PATTERNS;
|
||||
let fg_color = color(
|
||||
match theme {
|
||||
TerminalTheme::Light => "&0",
|
||||
TerminalTheme::Dark => "&f",
|
||||
},
|
||||
color_mode,
|
||||
)
|
||||
.expect("foreground color should not be invalid");
|
||||
for &fore in fg {
|
||||
replacements[usize::from(u8::from(fore)).checked_sub(1).unwrap()] =
|
||||
&fg_color;
|
||||
}
|
||||
ac.replace_all(&asc, &replacements)
|
||||
};
|
||||
let lines = asc.lines();
|
||||
|
||||
// Add new colors
|
||||
let lines = {
|
||||
let ColorProfile { colors } = color_profile
|
||||
.with_length(self.h.try_into().expect("`h` should not be 0"))
|
||||
.with_context(|| {
|
||||
format!("failed to spread color profile to length {h}", h = self.h)
|
||||
})?;
|
||||
lines.enumerate().map(move |(i, line)| {
|
||||
let bg_color =
|
||||
colors[i].to_ansi_string(color_mode, ForegroundBackground::Foreground);
|
||||
const N: usize = NEOFETCH_COLOR_PATTERNS.len();
|
||||
let replacements = [&bg_color; N];
|
||||
ac.replace_all(line, &replacements)
|
||||
})
|
||||
};
|
||||
|
||||
// Reset colors at end of each line to prevent color bleeding
|
||||
lines.map(|line| format!("{line}{reset}")).collect()
|
||||
},
|
||||
(ColorAlignment::Vertical, Self { fg, .. }) if !fg.is_empty() => {
|
||||
if self.w == 0 {
|
||||
return Ok(RecoloredAsciiArt {
|
||||
lines: self.lines.clone(),
|
||||
w: 0,
|
||||
h: self.h,
|
||||
});
|
||||
}
|
||||
|
||||
let Self { lines, .. } = self
|
||||
.fill_starting()
|
||||
.context("failed to fill in starting neofetch color codes")?;
|
||||
|
||||
let color_profile = color_profile
|
||||
.with_length(self.w.try_into().expect("`w` should not be 0"))
|
||||
.with_context(|| {
|
||||
format!("failed to spread color profile to length {w}", w = self.w)
|
||||
})?;
|
||||
|
||||
// Apply colors
|
||||
let ac = NEOFETCH_COLORS_AC
|
||||
.get_or_init(|| AhoCorasick::new(NEOFETCH_COLOR_PATTERNS).unwrap());
|
||||
lines
|
||||
.into_iter()
|
||||
.map(|line| {
|
||||
let line: &str = line.as_ref();
|
||||
|
||||
// `AhoCorasick` operates on bytes; we need to map that back to grapheme
|
||||
// clusters (i.e. a character as seen on the terminal)
|
||||
// See https://github.com/BurntSushi/aho-corasick/issues/72#issuecomment-821128859
|
||||
let byte_idx_to_grapheme_idx: IndexMap<usize, usize> = {
|
||||
let mut m: IndexMap<_, _> = line
|
||||
.grapheme_indices(true)
|
||||
.enumerate()
|
||||
.map(|(gr_idx, (byte_idx, _))| (byte_idx, gr_idx))
|
||||
.collect();
|
||||
// Add an extra entry at the end, to support lookup using exclusive
|
||||
// range end
|
||||
m.insert(line.len(), m.len());
|
||||
m
|
||||
};
|
||||
|
||||
let mut matches = ac.find_iter(line).peekable();
|
||||
let mut dst = String::new();
|
||||
let mut offset: u8 = 0;
|
||||
loop {
|
||||
let current = matches.next();
|
||||
let next = matches.peek();
|
||||
let (neofetch_color_idx, span, done) = match (current, next) {
|
||||
(Some(m), Some(m_next)) => {
|
||||
let ai_start = m.start().checked_add(3).unwrap();
|
||||
let ai_end = m.end().checked_sub(1).unwrap();
|
||||
let neofetch_color_idx: NeofetchAsciiIndexedColor = line
|
||||
[ai_start..ai_end]
|
||||
.parse()
|
||||
.expect("neofetch color index should be valid");
|
||||
if offset == 0 && m.start() > 0 {
|
||||
dst.push_str(&line[..m.start()]);
|
||||
}
|
||||
offset =
|
||||
offset.checked_add(u8::try_from(m.len()).unwrap()).unwrap();
|
||||
let mut span = m.span();
|
||||
span.start = m.end();
|
||||
span.end = m_next.start();
|
||||
(neofetch_color_idx, span, false)
|
||||
},
|
||||
(Some(m), None) => {
|
||||
// Last color code
|
||||
let ai_start = m.start().checked_add(3).unwrap();
|
||||
let ai_end = m.end().checked_sub(1).unwrap();
|
||||
let neofetch_color_idx: NeofetchAsciiIndexedColor = line
|
||||
[ai_start..ai_end]
|
||||
.parse()
|
||||
.expect("neofetch color index should be valid");
|
||||
if offset == 0 && m.start() > 0 {
|
||||
dst.push_str(&line[..m.start()]);
|
||||
}
|
||||
offset =
|
||||
offset.checked_add(u8::try_from(m.len()).unwrap()).unwrap();
|
||||
let mut span = m.span();
|
||||
span.start = m.end();
|
||||
span.end = line.len();
|
||||
(neofetch_color_idx, span, true)
|
||||
},
|
||||
(None, _) => {
|
||||
// No color code in the entire line
|
||||
unreachable!(
|
||||
"`fill_starting` ensured each line of ascii art starts \
|
||||
with neofetch color code"
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
if span.is_empty() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let txt = &line[span];
|
||||
|
||||
if fg.contains(&neofetch_color_idx) {
|
||||
let fore = color(
|
||||
match theme {
|
||||
TerminalTheme::Light => "&0",
|
||||
TerminalTheme::Dark => "&f",
|
||||
},
|
||||
color_mode,
|
||||
)
|
||||
.expect("foreground color should not be invalid");
|
||||
write!(dst, "{fore}{txt}{reset}").unwrap();
|
||||
} else {
|
||||
let mut c_range: Range<usize> = span.into();
|
||||
c_range.start = byte_idx_to_grapheme_idx
|
||||
.get(&c_range.start)
|
||||
.unwrap()
|
||||
.checked_sub(usize::from(offset))
|
||||
.unwrap();
|
||||
c_range.end = byte_idx_to_grapheme_idx
|
||||
.get(&c_range.end)
|
||||
.unwrap()
|
||||
.checked_sub(usize::from(offset))
|
||||
.unwrap();
|
||||
dst.push_str(
|
||||
&ColorProfile::new(Vec::from(&color_profile.colors[c_range]))
|
||||
.color_text(
|
||||
txt,
|
||||
color_mode,
|
||||
ForegroundBackground::Foreground,
|
||||
false,
|
||||
)
|
||||
.context("failed to color text using color profile")?,
|
||||
);
|
||||
}
|
||||
|
||||
if done {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Ok(dst)
|
||||
})
|
||||
.collect::<Result<_>>()?
|
||||
},
|
||||
(ColorAlignment::Vertical, Self { fg, .. }) if fg.is_empty() => {
|
||||
// Remove existing colors
|
||||
let asc = {
|
||||
let asc = self.lines.join("\n");
|
||||
let ac = NEOFETCH_COLORS_AC
|
||||
.get_or_init(|| AhoCorasick::new(NEOFETCH_COLOR_PATTERNS).unwrap());
|
||||
const N: usize = NEOFETCH_COLOR_PATTERNS.len();
|
||||
const REPLACEMENTS: [&str; N] = [""; N];
|
||||
ac.replace_all(&asc, &REPLACEMENTS)
|
||||
};
|
||||
let lines = asc.lines();
|
||||
|
||||
// Add new colors
|
||||
lines
|
||||
.map(|line| {
|
||||
let line = color_profile
|
||||
.color_text(line, color_mode, ForegroundBackground::Foreground, false)
|
||||
.context("failed to color text using color profile")?;
|
||||
Ok(line)
|
||||
})
|
||||
.collect::<Result<_>>()?
|
||||
},
|
||||
(
|
||||
ColorAlignment::Custom {
|
||||
colors: custom_colors,
|
||||
},
|
||||
_,
|
||||
) => {
|
||||
let Self { lines, .. } = self
|
||||
.fill_starting()
|
||||
.context("failed to fill in starting neofetch color codes")?;
|
||||
|
||||
let ColorProfile { colors } = color_profile.unique_colors();
|
||||
|
||||
// Apply colors
|
||||
let asc = {
|
||||
let asc = lines.join("\n");
|
||||
let ac = NEOFETCH_COLORS_AC
|
||||
.get_or_init(|| AhoCorasick::new(NEOFETCH_COLOR_PATTERNS).unwrap());
|
||||
const N: usize = NEOFETCH_COLOR_PATTERNS.len();
|
||||
let mut replacements = vec![Cow::from(""); N];
|
||||
for (&ai, &pi) in custom_colors {
|
||||
let ai: u8 = ai.into();
|
||||
let pi: u8 = pi.into();
|
||||
replacements[usize::from(ai.checked_sub(1).unwrap())] = colors
|
||||
[usize::from(pi)]
|
||||
.to_ansi_string(color_mode, ForegroundBackground::Foreground)
|
||||
.into();
|
||||
}
|
||||
ac.replace_all(&asc, &replacements)
|
||||
};
|
||||
let lines = asc.lines();
|
||||
|
||||
// Reset colors at end of each line to prevent color bleeding
|
||||
lines.map(|line| format!("{line}{reset}")).collect()
|
||||
},
|
||||
_ => {
|
||||
unreachable!()
|
||||
},
|
||||
};
|
||||
|
||||
Ok(RecoloredAsciiArt {
|
||||
lines,
|
||||
w: self.w,
|
||||
h: self.h,
|
||||
})
|
||||
}
|
||||
|
||||
/// Fills the missing starting placeholders.
|
||||
///
|
||||
/// e.g. `"${c1}...\n..."` -> `"${c1}...\n${c1}..."`
|
||||
fn fill_starting(&self) -> Result<Self> {
|
||||
let ac =
|
||||
NEOFETCH_COLORS_AC.get_or_init(|| AhoCorasick::new(NEOFETCH_COLOR_PATTERNS).unwrap());
|
||||
|
||||
let mut last = None;
|
||||
let lines =
|
||||
self.lines
|
||||
.iter()
|
||||
.map(|line| {
|
||||
let line: &str = line.as_ref();
|
||||
|
||||
let mut new = String::new();
|
||||
let mut matches = ac.find_iter(line).peekable();
|
||||
|
||||
match matches.peek() {
|
||||
Some(m)
|
||||
if m.start() == 0
|
||||
|| line[0..m.start()].trim_end_matches(' ').is_empty() =>
|
||||
{
|
||||
// Line starts with neofetch color code
|
||||
last = Some(&line[m.span()]);
|
||||
},
|
||||
Some(_) => {
|
||||
new.push_str(last.context(
|
||||
"failed to find neofetch color code from a previous line",
|
||||
)?);
|
||||
},
|
||||
None => {
|
||||
new.push_str(last.unwrap_or(NEOFETCH_COLOR_PATTERNS[0]));
|
||||
},
|
||||
}
|
||||
new.push_str(line);
|
||||
|
||||
// Get the last placeholder for the next line
|
||||
if let Some(m) = matches.last() {
|
||||
last.context("non-space character seen before first color code")?;
|
||||
last = Some(&line[m.span()]);
|
||||
}
|
||||
|
||||
Ok(new)
|
||||
})
|
||||
.collect::<Result<_>>()?;
|
||||
|
||||
Ok(Self {
|
||||
lines,
|
||||
fg: self.fg.clone(),
|
||||
..*self
|
||||
})
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,260 @@
|
||||
use std::iter;
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr as _;
|
||||
|
||||
use anyhow::Context as _;
|
||||
#[cfg(feature = "autocomplete")]
|
||||
use bpaf::ShellComp;
|
||||
use bpaf::{construct, long, OptionParser, Parser as _};
|
||||
use directories::BaseDirs;
|
||||
use itertools::Itertools as _;
|
||||
use strum::{VariantArray, VariantNames};
|
||||
|
||||
use crate::color_util::{color, Lightness};
|
||||
use crate::presets::Preset;
|
||||
use crate::types::{AnsiMode, Backend};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Options {
|
||||
pub config: bool,
|
||||
pub config_file: PathBuf,
|
||||
pub preset: Option<Preset>,
|
||||
pub mode: Option<AnsiMode>,
|
||||
pub backend: Option<Backend>,
|
||||
pub args: Option<Vec<String>>,
|
||||
pub scale: Option<f32>,
|
||||
pub lightness: Option<Lightness>,
|
||||
pub june: bool,
|
||||
pub debug: bool,
|
||||
pub distro: Option<String>,
|
||||
pub ascii_file: Option<PathBuf>,
|
||||
pub print_font_logo: bool,
|
||||
pub test_print: bool,
|
||||
pub ask_exit: bool,
|
||||
pub auto_detect_light_dark: Option<bool>,
|
||||
}
|
||||
|
||||
pub fn options() -> OptionParser<Options> {
|
||||
let config = long("config").short('c').help("Configure hyfetch").switch();
|
||||
let config_file = long("config-file")
|
||||
.short('C')
|
||||
.help("Use another config file")
|
||||
.argument("CONFIG_FILE");
|
||||
#[cfg(feature = "autocomplete")]
|
||||
let config_file = config_file.complete_shell(ShellComp::Nothing);
|
||||
let config_file = config_file
|
||||
.fallback_with(|| {
|
||||
Ok::<_, anyhow::Error>(
|
||||
BaseDirs::new()
|
||||
.context("failed to get base dirs")?
|
||||
.config_dir()
|
||||
.join("hyfetch.json"),
|
||||
)
|
||||
})
|
||||
.debug_fallback();
|
||||
let preset = long("preset")
|
||||
.short('p')
|
||||
.help(&*format!(
|
||||
"Use preset
|
||||
PRESET={{{presets}}}",
|
||||
presets = <Preset as VariantNames>::VARIANTS
|
||||
.iter()
|
||||
.chain(iter::once(&"random"))
|
||||
.join(",")
|
||||
))
|
||||
.argument::<String>("PRESET");
|
||||
#[cfg(feature = "autocomplete")]
|
||||
let preset = preset.complete(complete_preset);
|
||||
let preset = preset
|
||||
.parse(|s| {
|
||||
Preset::from_str(&s)
|
||||
.or_else(|e| {
|
||||
if s == "random" {
|
||||
let mut rng = fastrand::Rng::new();
|
||||
Ok(*rng
|
||||
.choice(<Preset as VariantArray>::VARIANTS)
|
||||
.expect("preset iterator should not be empty"))
|
||||
} else {
|
||||
Err(e)
|
||||
}
|
||||
})
|
||||
.with_context(|| {
|
||||
format!(
|
||||
"PRESET should be one of {{{presets}}}",
|
||||
presets = <Preset as VariantNames>::VARIANTS
|
||||
.iter()
|
||||
.chain(iter::once(&"random"))
|
||||
.join(",")
|
||||
)
|
||||
})
|
||||
})
|
||||
.optional();
|
||||
let mode = long("mode")
|
||||
.short('m')
|
||||
.help(&*format!(
|
||||
"Color mode
|
||||
MODE={{{modes}}}",
|
||||
modes = AnsiMode::VARIANTS.join(",")
|
||||
))
|
||||
.argument::<String>("MODE");
|
||||
#[cfg(feature = "autocomplete")]
|
||||
let mode = mode.complete(complete_mode);
|
||||
let mode = mode
|
||||
.parse(|s| {
|
||||
AnsiMode::from_str(&s).with_context(|| {
|
||||
format!(
|
||||
"MODE should be one of {{{modes}}}",
|
||||
modes = AnsiMode::VARIANTS.join(",")
|
||||
)
|
||||
})
|
||||
})
|
||||
.optional();
|
||||
let backend = long("backend")
|
||||
.short('b')
|
||||
.help(&*format!(
|
||||
"Choose a *fetch backend
|
||||
BACKEND={{{backends}}}",
|
||||
backends = Backend::VARIANTS.join(",")
|
||||
))
|
||||
.argument::<String>("BACKEND");
|
||||
#[cfg(feature = "autocomplete")]
|
||||
let backend = backend.complete(complete_backend);
|
||||
let backend = backend
|
||||
.parse(|s| {
|
||||
Backend::from_str(&s).with_context(|| {
|
||||
format!(
|
||||
"BACKEND should be one of {{{backends}}}",
|
||||
backends = Backend::VARIANTS.join(",")
|
||||
)
|
||||
})
|
||||
})
|
||||
.optional();
|
||||
let args = long("args")
|
||||
.help("Additional arguments pass-through to backend")
|
||||
.argument::<String>("ARGS")
|
||||
.parse(|s| shell_words::split(&s).context("ARGS should be valid command-line arguments"))
|
||||
.optional();
|
||||
let scale = long("c-scale")
|
||||
.help("Lighten colors by a multiplier")
|
||||
.argument("SCALE")
|
||||
.optional();
|
||||
let lightness = long("c-set-l")
|
||||
.help("Set lightness value of the colors")
|
||||
.argument("LIGHTNESS")
|
||||
.optional();
|
||||
let june = long("june").help("Show pride month easter egg").switch();
|
||||
let debug = long("debug").help("Debug mode").switch();
|
||||
let distro = long("distro")
|
||||
.help("Test for a specific distro")
|
||||
.argument("DISTRO")
|
||||
.optional();
|
||||
let test_distro = long("test-distro")
|
||||
.help("Test for a specific distro")
|
||||
.argument("DISTRO")
|
||||
.optional();
|
||||
let distro = construct!([distro, test_distro]);
|
||||
let ascii_file = long("ascii-file")
|
||||
.help("Use a specific file for the ascii art")
|
||||
.argument("ASCII_FILE");
|
||||
#[cfg(feature = "autocomplete")]
|
||||
let ascii_file = ascii_file.complete_shell(ShellComp::Nothing);
|
||||
let ascii_file = ascii_file.optional();
|
||||
let print_font_logo = long("print-font-logo")
|
||||
.help("Print the Font Logo / Nerd Font icon of your distro and exit")
|
||||
.switch();
|
||||
// hidden
|
||||
let test_print = long("test-print")
|
||||
.help("Print the ascii distro and exit")
|
||||
.switch()
|
||||
.hide();
|
||||
let ask_exit = long("ask-exit")
|
||||
.help("Ask for input before exiting")
|
||||
.switch()
|
||||
.hide();
|
||||
let auto_detect_light_dark = long("auto-detect-light-dark")
|
||||
.help("Enables hyfetch to detect light/dark terminal background in runtime")
|
||||
.argument("BOOL")
|
||||
.optional();
|
||||
|
||||
construct!(Options {
|
||||
config,
|
||||
config_file,
|
||||
preset,
|
||||
mode,
|
||||
backend,
|
||||
args,
|
||||
scale,
|
||||
lightness,
|
||||
june,
|
||||
debug,
|
||||
distro,
|
||||
ascii_file,
|
||||
print_font_logo,
|
||||
// hidden
|
||||
test_print,
|
||||
ask_exit,
|
||||
auto_detect_light_dark,
|
||||
})
|
||||
.to_options()
|
||||
.header(
|
||||
&*color(
|
||||
"&l&bhyfetch&~&L - neofetch with flags <3",
|
||||
AnsiMode::Ansi256,
|
||||
)
|
||||
.expect("header should not contain invalid color codes"),
|
||||
)
|
||||
.version(env!("CARGO_PKG_VERSION"))
|
||||
}
|
||||
|
||||
#[cfg(feature = "autocomplete")]
|
||||
fn complete_preset(input: &String) -> Vec<(String, Option<String>)> {
|
||||
<Preset as VariantNames>::VARIANTS
|
||||
.iter()
|
||||
.chain(iter::once(&"random"))
|
||||
.filter_map(|&name| {
|
||||
if name.starts_with(input) {
|
||||
Some((name.to_owned(), None))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
#[cfg(feature = "autocomplete")]
|
||||
fn complete_mode(input: &String) -> Vec<(String, Option<String>)> {
|
||||
AnsiMode::VARIANTS
|
||||
.iter()
|
||||
.filter_map(|&name| {
|
||||
if name.starts_with(input) {
|
||||
Some((name.to_owned(), None))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
#[cfg(feature = "autocomplete")]
|
||||
fn complete_backend(input: &String) -> Vec<(String, Option<String>)> {
|
||||
Backend::VARIANTS
|
||||
.iter()
|
||||
.filter_map(|&name| {
|
||||
if name.starts_with(input) {
|
||||
Some((name.to_owned(), None))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn check_options() {
|
||||
options().check_invariants(false)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,433 @@
|
||||
use std::io::{self, Write as _};
|
||||
use std::num::{ParseFloatError, ParseIntError};
|
||||
use std::str::FromStr;
|
||||
use std::sync::OnceLock;
|
||||
|
||||
use aho_corasick::AhoCorasick;
|
||||
use ansi_colours::{ansi256_from_grey, rgb_from_ansi256, AsRGB as _};
|
||||
use anyhow::{anyhow, Context as _, Result};
|
||||
use deranged::RangedU8;
|
||||
use palette::color_difference::ImprovedCiede2000 as _;
|
||||
use palette::{
|
||||
FromColor as _, IntoColor as _, IntoColorMut as _, Lab, LinSrgb, Okhsl, Srgb, SrgbLuma,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::types::{AnsiMode, TerminalTheme};
|
||||
|
||||
const MINECRAFT_COLORS: [(&str, &str); 30] = [
|
||||
// Minecraft formatting codes
|
||||
// ==========================
|
||||
("&0", "\x1b[38;5;0m"),
|
||||
("&1", "\x1b[38;5;4m"),
|
||||
("&2", "\x1b[38;5;2m"),
|
||||
("&3", "\x1b[38;5;6m"),
|
||||
("&4", "\x1b[38;5;1m"),
|
||||
("&5", "\x1b[38;5;5m"),
|
||||
("&6", "\x1b[38;5;3m"),
|
||||
("&7", "\x1b[38;5;7m"),
|
||||
("&8", "\x1b[38;5;8m"),
|
||||
("&9", "\x1b[38;5;12m"),
|
||||
("&a", "\x1b[38;5;10m"),
|
||||
("&b", "\x1b[38;5;14m"),
|
||||
("&c", "\x1b[38;5;9m"),
|
||||
("&d", "\x1b[38;5;13m"),
|
||||
("&e", "\x1b[38;5;11m"),
|
||||
("&f", "\x1b[38;5;15m"),
|
||||
("&l", "\x1b[1m"), // Enable bold text
|
||||
("&o", "\x1b[3m"), // Enable italic text
|
||||
("&n", "\x1b[4m"), // Enable underlined text
|
||||
("&k", "\x1b[8m"), // Enable hidden text
|
||||
("&m", "\x1b[9m"), // Enable strikethrough text
|
||||
("&r", "\x1b[0m"), // Reset everything
|
||||
// Extended codes (not officially in Minecraft)
|
||||
// ============================================
|
||||
("&-", "\n"), // Line break
|
||||
("&~", "\x1b[39m"), // Reset text color
|
||||
("&*", "\x1b[49m"), // Reset background color
|
||||
("&L", "\x1b[22m"), // Disable bold text
|
||||
("&O", "\x1b[23m"), // Disable italic text
|
||||
("&N", "\x1b[24m"), // Disable underlined text
|
||||
("&K", "\x1b[28m"), // Disable hidden text
|
||||
("&M", "\x1b[29m"), // Disable strikethrough text
|
||||
];
|
||||
const RGB_COLOR_PATTERNS: [&str; 2] = ["&gf(", "&gb("];
|
||||
|
||||
/// See https://github.com/mina86/ansi_colours/blob/b9feefce10def2ac632b215ecd20830a4fca7836/src/ansi256.rs#L109
|
||||
const ANSI256_GRAYSCALE_COLORS: [u8; 30] = [
|
||||
16, 59, 102, 145, 188, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244,
|
||||
245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255,
|
||||
];
|
||||
|
||||
static MINECRAFT_COLORS_AC: OnceLock<(AhoCorasick, Box<[&str; 30]>)> = OnceLock::new();
|
||||
static RGB_COLORS_AC: OnceLock<AhoCorasick> = OnceLock::new();
|
||||
|
||||
/// Represents the lightness component in [`Okhsl`].
|
||||
///
|
||||
/// The range of valid values is
|
||||
/// [`Lightness::MIN`]`..=`[`Lightness::MAX`]
|
||||
///
|
||||
/// [`Okhsl`]: palette::Okhsl
|
||||
#[derive(Copy, Clone, PartialEq, PartialOrd, Debug, Deserialize, Serialize)]
|
||||
pub struct Lightness(f32);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum LightnessError {
|
||||
#[error(
|
||||
"invalid lightness {0}, expected value between {min} and {max}",
|
||||
min = Lightness::MIN,
|
||||
max = Lightness::MAX
|
||||
)]
|
||||
OutOfRange(f32),
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ParseLightnessError {
|
||||
#[error("invalid float")]
|
||||
InvalidFloat(#[from] ParseFloatError),
|
||||
#[error("invalid lightness")]
|
||||
InvalidLightness(#[from] LightnessError),
|
||||
}
|
||||
|
||||
/// An indexed color where the color palette is the set of colors used in
|
||||
/// neofetch ascii art.
|
||||
///
|
||||
/// The range of valid values as supported in neofetch is
|
||||
/// [`NeofetchAsciiIndexedColor::MIN`]`..=`[`NeofetchAsciiIndexedColor::MAX`]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Deserialize, Serialize)]
|
||||
pub struct NeofetchAsciiIndexedColor(
|
||||
RangedU8<{ NeofetchAsciiIndexedColor::MIN }, { NeofetchAsciiIndexedColor::MAX }>,
|
||||
);
|
||||
|
||||
/// An indexed color where the color palette is the set of unique colors in a
|
||||
/// preset.
|
||||
///
|
||||
/// The range of valid values depends on the number of unique colors in a
|
||||
/// certain preset.
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Deserialize, Serialize)]
|
||||
pub struct PresetIndexedColor(u8);
|
||||
|
||||
/// Whether the color is for foreground text or background color.
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub enum ForegroundBackground {
|
||||
Foreground,
|
||||
Background,
|
||||
}
|
||||
|
||||
pub trait ToAnsiString {
|
||||
/// Converts RGB to ANSI escape code.
|
||||
fn to_ansi_string(&self, mode: AnsiMode, foreground_background: ForegroundBackground)
|
||||
-> String;
|
||||
}
|
||||
|
||||
pub trait Theme {
|
||||
fn theme(&self) -> TerminalTheme;
|
||||
}
|
||||
|
||||
pub trait ContrastGrayscale {
|
||||
/// Calculates the grayscale foreground color which provides the highest
|
||||
/// contrast against this background color.
|
||||
///
|
||||
/// The returned color is one of the ANSI 256 (8-bit) grayscale colors.
|
||||
///
|
||||
/// See <https://upload.wikimedia.org/wikipedia/commons/1/15/Xterm_256color_chart.svg>
|
||||
fn contrast_grayscale(&self) -> SrgbLuma<u8>;
|
||||
}
|
||||
|
||||
impl Lightness {
|
||||
pub const MAX: f32 = 1.0f32;
|
||||
pub const MIN: f32 = 0.0f32;
|
||||
|
||||
pub fn new(value: f32) -> Result<Self, LightnessError> {
|
||||
if !(Self::MIN..=Self::MAX).contains(&value) {
|
||||
return Err(LightnessError::OutOfRange(value));
|
||||
}
|
||||
|
||||
Ok(Self(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<f32> for Lightness {
|
||||
type Error = LightnessError;
|
||||
|
||||
fn try_from(value: f32) -> Result<Self, Self::Error> {
|
||||
Lightness::new(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Lightness {
|
||||
type Err = ParseLightnessError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
Ok(Lightness::new(s.parse()?)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Lightness> for f32 {
|
||||
fn from(value: Lightness) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
impl NeofetchAsciiIndexedColor {
|
||||
pub const MAX: u8 = 6;
|
||||
pub const MIN: u8 = 1;
|
||||
}
|
||||
|
||||
impl TryFrom<u8> for NeofetchAsciiIndexedColor {
|
||||
type Error = deranged::TryFromIntError;
|
||||
|
||||
fn try_from(value: u8) -> Result<Self, Self::Error> {
|
||||
Ok(Self(value.try_into()?))
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for NeofetchAsciiIndexedColor {
|
||||
type Err = deranged::ParseIntError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
Ok(Self(s.parse()?))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<NeofetchAsciiIndexedColor> for u8 {
|
||||
fn from(value: NeofetchAsciiIndexedColor) -> Self {
|
||||
value.0.get()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u8> for PresetIndexedColor {
|
||||
fn from(value: u8) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for PresetIndexedColor {
|
||||
type Err = ParseIntError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
Ok(Self(s.parse()?))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PresetIndexedColor> for u8 {
|
||||
fn from(value: PresetIndexedColor) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
impl ToAnsiString for Srgb<u8> {
|
||||
fn to_ansi_string(
|
||||
&self,
|
||||
mode: AnsiMode,
|
||||
foreground_background: ForegroundBackground,
|
||||
) -> String {
|
||||
let c: u8 = match foreground_background {
|
||||
ForegroundBackground::Foreground => 38,
|
||||
ForegroundBackground::Background => 48,
|
||||
};
|
||||
match mode {
|
||||
AnsiMode::Rgb => {
|
||||
let [r, g, b]: [u8; 3] = (*self).into();
|
||||
format!("\x1b[{c};2;{r};{g};{b}m")
|
||||
},
|
||||
AnsiMode::Ansi256 => {
|
||||
let rgb: [u8; 3] = (*self).into();
|
||||
let indexed = rgb.to_ansi256();
|
||||
format!("\x1b[{c};5;{indexed}m")
|
||||
},
|
||||
AnsiMode::Ansi16 => {
|
||||
unimplemented!();
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToAnsiString for SrgbLuma<u8> {
|
||||
fn to_ansi_string(
|
||||
&self,
|
||||
mode: AnsiMode,
|
||||
foreground_background: ForegroundBackground,
|
||||
) -> String {
|
||||
let c: u8 = match foreground_background {
|
||||
ForegroundBackground::Foreground => 38,
|
||||
ForegroundBackground::Background => 48,
|
||||
};
|
||||
match mode {
|
||||
AnsiMode::Rgb => {
|
||||
let rgb_f32_color: LinSrgb = self.into_linear().into_color();
|
||||
let [r, g, b]: [u8; 3] = Srgb::<u8>::from_linear(rgb_f32_color).into();
|
||||
format!("\x1b[{c};2;{r};{g};{b}m")
|
||||
},
|
||||
AnsiMode::Ansi256 => {
|
||||
let indexed = ansi256_from_grey(self.luma);
|
||||
format!("\x1b[{c};5;{indexed}m")
|
||||
},
|
||||
AnsiMode::Ansi16 => {
|
||||
unimplemented!();
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Theme for Srgb<u8> {
|
||||
fn theme(&self) -> TerminalTheme {
|
||||
let mut rgb_f32_color: LinSrgb = self.into_linear();
|
||||
|
||||
{
|
||||
let okhsl_f32_color: &mut Okhsl = &mut rgb_f32_color.into_color_mut();
|
||||
|
||||
if okhsl_f32_color.lightness > 0.5 {
|
||||
TerminalTheme::Light
|
||||
} else {
|
||||
TerminalTheme::Dark
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ContrastGrayscale for Srgb<u8> {
|
||||
fn contrast_grayscale(&self) -> SrgbLuma<u8> {
|
||||
let self_lab_f32: Lab = self.into_linear().into_color();
|
||||
|
||||
let mut best_contrast = None;
|
||||
for indexed in ANSI256_GRAYSCALE_COLORS {
|
||||
let rgb_u8_color: Srgb<u8> = rgb_from_ansi256(indexed).into();
|
||||
let lab_f32_color: Lab = rgb_u8_color.into_linear().into_color();
|
||||
let diff = lab_f32_color.improved_difference(self_lab_f32);
|
||||
best_contrast = match best_contrast {
|
||||
Some((_, best_diff)) if diff > best_diff => Some((lab_f32_color, diff)),
|
||||
None => Some((lab_f32_color, diff)),
|
||||
best => best,
|
||||
};
|
||||
}
|
||||
let (best_lab_f32, _) = best_contrast.expect("`best_contrast` should not be `None`");
|
||||
SrgbLuma::from_color(best_lab_f32).into_format()
|
||||
}
|
||||
}
|
||||
|
||||
/// Replaces extended minecraft color codes in message.
|
||||
///
|
||||
/// Returns message with escape codes.
|
||||
pub fn color<S>(msg: S, mode: AnsiMode) -> Result<String>
|
||||
where
|
||||
S: AsRef<str>,
|
||||
{
|
||||
let msg = msg.as_ref();
|
||||
|
||||
let msg = {
|
||||
let (ac, escape_codes) = MINECRAFT_COLORS_AC.get_or_init(|| {
|
||||
let (color_codes, escape_codes): (Vec<_>, Vec<_>) =
|
||||
MINECRAFT_COLORS.into_iter().unzip();
|
||||
let ac = AhoCorasick::new(color_codes).unwrap();
|
||||
(
|
||||
ac,
|
||||
escape_codes.try_into().expect(
|
||||
"`MINECRAFT_COLORS` should have the same number of elements as \
|
||||
`MINECRAFT_COLORS_AC.get_or_init(...).1`",
|
||||
),
|
||||
)
|
||||
});
|
||||
ac.replace_all(msg, &escape_codes[..])
|
||||
};
|
||||
|
||||
let ac = RGB_COLORS_AC.get_or_init(|| AhoCorasick::new(RGB_COLOR_PATTERNS).unwrap());
|
||||
let mut dst = String::new();
|
||||
let mut ret_err = None;
|
||||
ac.replace_all_with(&msg, &mut dst, |m, _, dst| {
|
||||
let start = m.end();
|
||||
let end = msg[start..]
|
||||
.find(')')
|
||||
.context("missing closing brace for color code");
|
||||
let end = match end {
|
||||
Ok(end) => end,
|
||||
Err(err) => {
|
||||
ret_err = Some(err);
|
||||
return false;
|
||||
},
|
||||
};
|
||||
let code = &msg[start..end];
|
||||
let foreground_background = if m.pattern().as_usize() == 0 {
|
||||
ForegroundBackground::Foreground
|
||||
} else {
|
||||
ForegroundBackground::Background
|
||||
};
|
||||
|
||||
let rgb: Srgb<u8> = if code.starts_with('#') {
|
||||
let rgb = code.parse().context("failed to parse hex color");
|
||||
match rgb {
|
||||
Ok(rgb) => rgb,
|
||||
Err(err) => {
|
||||
ret_err = Some(err);
|
||||
return false;
|
||||
},
|
||||
}
|
||||
} else {
|
||||
let rgb: Result<[&str; 3], _> = code
|
||||
.split(&[',', ';', ' '])
|
||||
.filter(|x| x.is_empty())
|
||||
.collect::<Vec<_>>()
|
||||
.try_into()
|
||||
.map_err(|_| anyhow!("wrong number of rgb components"));
|
||||
let rgb = match rgb {
|
||||
Ok(rgb) => rgb,
|
||||
Err(err) => {
|
||||
ret_err = Some(err);
|
||||
return false;
|
||||
},
|
||||
};
|
||||
let rgb = rgb
|
||||
.into_iter()
|
||||
.map(u8::from_str)
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
.context("failed to parse rgb components");
|
||||
let rgb: [u8; 3] = match rgb {
|
||||
Ok(rgb) => rgb.try_into().unwrap(),
|
||||
Err(err) => {
|
||||
ret_err = Some(err);
|
||||
return false;
|
||||
},
|
||||
};
|
||||
rgb.into()
|
||||
};
|
||||
|
||||
dst.push_str(&rgb.to_ansi_string(mode, foreground_background));
|
||||
|
||||
true
|
||||
});
|
||||
if let Some(err) = ret_err {
|
||||
return Err(err);
|
||||
}
|
||||
|
||||
Ok(dst)
|
||||
}
|
||||
|
||||
/// Prints with color.
|
||||
pub fn printc<S>(msg: S, mode: AnsiMode) -> Result<()>
|
||||
where
|
||||
S: AsRef<str>,
|
||||
{
|
||||
writeln!(
|
||||
io::stdout(),
|
||||
"{msg}",
|
||||
msg = color(format!("{msg}&r", msg = msg.as_ref()), mode)
|
||||
.context("failed to color message")?
|
||||
)
|
||||
.context("failed to write message to stdout")
|
||||
}
|
||||
|
||||
/// Clears screen using ANSI escape codes.
|
||||
pub fn clear_screen(title: Option<&str>, mode: AnsiMode, debug_mode: bool) -> Result<()> {
|
||||
if !debug_mode {
|
||||
write!(io::stdout(), "\x1b[2J\x1b[H")
|
||||
.and_then(|_| io::stdout().flush())
|
||||
.context("failed to write clear screen sequence to stdout")?;
|
||||
}
|
||||
|
||||
if let Some(title) = title {
|
||||
printc(format!("\n{title}\n"), mode).context("failed to print title")?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/distros.rs"));
|
||||
@@ -0,0 +1,42 @@
|
||||
use crate::neofetch_util::get_distro_name;
|
||||
use crate::types::Backend;
|
||||
use crate::utils::get_cache_path;
|
||||
use anyhow::{Context, Result};
|
||||
use std::collections::HashMap;
|
||||
use std::fs::{File};
|
||||
use std::io::{Read, Write};
|
||||
|
||||
const FONT_LOGOS: &str = include_str!(concat!(env!("OUT_DIR"), "/hyfetch/data/font_logos.json"));
|
||||
|
||||
pub fn get_font_logo(backend: Backend) -> Result<String> {
|
||||
// Check if the cache file exists and return its contents if it does
|
||||
let cache_path = get_cache_path().context("Failed to get cache path")?.join("font_logo");
|
||||
if cache_path.exists() {
|
||||
let mut cached_logo = String::new();
|
||||
File::open(cache_path).context("Failed to open cache file")?
|
||||
.read_to_string(&mut cached_logo).context("Failed to read from cache file")?;
|
||||
return Ok(cached_logo);
|
||||
}
|
||||
|
||||
// Deserialize the JSON into a HashMap
|
||||
let font_logos: HashMap<String, String> = serde_json::from_str::<HashMap<String, String>>(FONT_LOGOS)
|
||||
.context("Failed to deserialize font logos JSON file")?
|
||||
.into_iter().map(|(k, v)| (k.to_lowercase(), v)).collect();
|
||||
|
||||
// Get the distro name
|
||||
let distro = get_distro_name(backend).context("Failed to get distro name")?.to_lowercase();
|
||||
|
||||
// Find the most likely matching distro from font_logos
|
||||
let matched_distro = font_logos.keys().find(|&k| distro.contains(k))
|
||||
.or_else(|| font_logos.keys().find(|k| k.contains(&distro)))
|
||||
.or_else(|| font_logos.keys().find(|k| k.split_whitespace().any(|part| distro.contains(part))))
|
||||
.ok_or_else(|| anyhow::anyhow!("No font logo found for distro: {distro}. The supported logos are in https://github.com/Lukas-W/font-logos"))?;
|
||||
|
||||
let logo = font_logos.get(matched_distro).unwrap();
|
||||
|
||||
// Write the logo to the cache file
|
||||
let mut cache_file = File::create(cache_path).context("Failed to create cache file")?;
|
||||
cache_file.write_all(logo.as_bytes()).context("Failed to write logo to cache file")?;
|
||||
|
||||
Ok(logo.clone())
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
pub mod ascii;
|
||||
pub mod cli_options;
|
||||
pub mod color_util;
|
||||
pub mod distros;
|
||||
pub mod font_logo;
|
||||
pub mod models;
|
||||
pub mod neofetch_util;
|
||||
pub mod presets;
|
||||
pub mod pride_month;
|
||||
pub mod types;
|
||||
pub mod utils;
|
||||
@@ -0,0 +1,119 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::color_util::Lightness;
|
||||
use crate::neofetch_util::ColorAlignment;
|
||||
use crate::presets::Preset;
|
||||
use crate::types::{AnsiMode, Backend, TerminalTheme};
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct Config {
|
||||
pub preset: Preset,
|
||||
pub mode: AnsiMode,
|
||||
pub auto_detect_light_dark: Option<bool>,
|
||||
pub light_dark: Option<TerminalTheme>,
|
||||
pub lightness: Option<Lightness>,
|
||||
pub color_align: ColorAlignment,
|
||||
pub backend: Backend,
|
||||
#[serde(default)]
|
||||
#[serde(with = "self::args_serde")]
|
||||
pub args: Option<Vec<String>>,
|
||||
pub distro: Option<String>,
|
||||
pub pride_month_disable: bool,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn default_lightness(theme: TerminalTheme) -> Lightness {
|
||||
match theme {
|
||||
TerminalTheme::Dark => {
|
||||
Lightness::new(0.65).expect("default lightness should not be invalid")
|
||||
},
|
||||
TerminalTheme::Light => {
|
||||
Lightness::new(0.4).expect("default lightness should not be invalid")
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod args_serde {
|
||||
use std::fmt;
|
||||
|
||||
use serde::de::{self, value, Deserialize, Deserializer, SeqAccess, Visitor};
|
||||
use serde::ser::Serializer;
|
||||
|
||||
type Value = Option<Vec<String>>;
|
||||
|
||||
pub(super) fn serialize<S>(value: &Value, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
match value {
|
||||
Some(value) => serializer.serialize_some(&shell_words::join(value)),
|
||||
None => serializer.serialize_none(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn deserialize<'de, D>(deserializer: D) -> Result<Value, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct StringOrVec;
|
||||
|
||||
struct OptionVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for StringOrVec {
|
||||
type Value = Vec<String>;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("string or list of strings")
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
shell_words::split(s).map_err(de::Error::custom)
|
||||
}
|
||||
|
||||
fn visit_seq<S>(self, seq: S) -> Result<Self::Value, S::Error>
|
||||
where
|
||||
S: SeqAccess<'de>,
|
||||
{
|
||||
Deserialize::deserialize(value::SeqAccessDeserializer::new(seq))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Visitor<'de> for OptionVisitor {
|
||||
type Value = Value;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("option")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_unit<E>(self) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_none<E>(self) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
deserializer.deserialize_any(StringOrVec).map(Some)
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_option(OptionVisitor)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,776 @@
|
||||
use std::borrow::Cow;
|
||||
use std::ffi::OsStr;
|
||||
#[cfg(feature = "macchina")]
|
||||
use std::fs;
|
||||
use std::io::{self, Write as _};
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
use std::sync::OnceLock;
|
||||
use std::{env, fmt};
|
||||
|
||||
use aho_corasick::AhoCorasick;
|
||||
use anyhow::{Context as _, Result};
|
||||
use indexmap::IndexMap;
|
||||
use itertools::Itertools as _;
|
||||
#[cfg(windows)]
|
||||
use anyhow::anyhow;
|
||||
#[cfg(windows)]
|
||||
use crate::utils::find_file;
|
||||
#[cfg(windows)]
|
||||
use std::path::Path;
|
||||
#[cfg(windows)]
|
||||
use normpath::PathExt as _;
|
||||
#[cfg(windows)]
|
||||
use same_file::is_same_file;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use strum::AsRefStr;
|
||||
#[cfg(feature = "macchina")]
|
||||
use toml_edit::{value, DocumentMut, Item, Table};
|
||||
use tracing::debug;
|
||||
use unicode_segmentation::UnicodeSegmentation as _;
|
||||
use which::which;
|
||||
use crate::ascii::{RawAsciiArt, RecoloredAsciiArt};
|
||||
use crate::color_util::{printc, NeofetchAsciiIndexedColor, PresetIndexedColor};
|
||||
use crate::distros::Distro;
|
||||
use crate::types::{AnsiMode, Backend};
|
||||
use crate::utils::{find_in_path, get_cache_path, input, process_command_status};
|
||||
|
||||
pub const TEST_ASCII: &str = r####################"
|
||||
### |\___/| ###
|
||||
### ) ( ###
|
||||
## =\ /= ##
|
||||
#### )===( ####
|
||||
### / \ ###
|
||||
### | | ###
|
||||
## / {txt} \ ##
|
||||
## \ / ##
|
||||
_/\_\_ _/_/\_
|
||||
|##| ( ( |##|
|
||||
|##| ) ) |##|
|
||||
|##| (_( |##|
|
||||
"####################;
|
||||
|
||||
pub const NEOFETCH_COLOR_PATTERNS: [&str; 6] =
|
||||
["${c1}", "${c2}", "${c3}", "${c4}", "${c5}", "${c6}"];
|
||||
pub static NEOFETCH_COLORS_AC: OnceLock<AhoCorasick> = OnceLock::new();
|
||||
pub const NEOFETCH_SCRIPT: &str = include_str!(concat!(env!("OUT_DIR"), "/neofetch"));
|
||||
|
||||
#[derive(Clone, Eq, PartialEq, Debug, AsRefStr, Deserialize, Serialize)]
|
||||
#[serde(tag = "mode")]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
#[strum(serialize_all = "lowercase")]
|
||||
pub enum ColorAlignment {
|
||||
Horizontal,
|
||||
Vertical,
|
||||
Custom {
|
||||
#[serde(rename = "custom_colors")]
|
||||
#[serde(deserialize_with = "crate::utils::index_map_serde::deserialize")]
|
||||
colors: IndexMap<NeofetchAsciiIndexedColor, PresetIndexedColor>,
|
||||
},
|
||||
}
|
||||
|
||||
/// Asks the user to provide an input among a list of options.
|
||||
pub fn literal_input<'a, S1, S2>(
|
||||
prompt: S1,
|
||||
options: &'a [S2],
|
||||
default: &str,
|
||||
show_options: bool,
|
||||
color_mode: AnsiMode,
|
||||
) -> Result<&'a str>
|
||||
where
|
||||
S1: AsRef<str>,
|
||||
S2: AsRef<str>,
|
||||
{
|
||||
let prompt = prompt.as_ref();
|
||||
|
||||
if show_options {
|
||||
let options_text = options
|
||||
.iter()
|
||||
.map(|o| {
|
||||
let o = o.as_ref();
|
||||
|
||||
if o == default {
|
||||
format!("&l&n{o}&L&N")
|
||||
} else {
|
||||
o.to_owned()
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join("|");
|
||||
printc(format!("{prompt} ({options_text})"), color_mode)
|
||||
.context("failed to print input prompt")?;
|
||||
} else {
|
||||
printc(format!("{prompt} (default: {default})"), color_mode)
|
||||
.context("failed to print input prompt")?;
|
||||
}
|
||||
|
||||
loop {
|
||||
let selection = input(Some("> ")).context("failed to read input")?;
|
||||
let selection = if selection.is_empty() {
|
||||
default.to_owned()
|
||||
} else {
|
||||
selection.to_lowercase()
|
||||
};
|
||||
|
||||
if let Some(selected) = find_selection(&selection, options) {
|
||||
writeln!(io::stdout()).context("failed to write to stdout")?;
|
||||
|
||||
return Ok(selected);
|
||||
} else {
|
||||
let options_text = options.iter().map(AsRef::as_ref).join("|");
|
||||
writeln!(
|
||||
io::stdout(),
|
||||
"Invalid selection! {selection} is not one of {options_text}"
|
||||
)
|
||||
.context("failed to write message to stdout")?;
|
||||
}
|
||||
}
|
||||
|
||||
fn find_selection<'a, S>(sel: &str, options: &'a [S]) -> Option<&'a str>
|
||||
where
|
||||
S: AsRef<str>,
|
||||
{
|
||||
if sel.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Find exact match
|
||||
if let Some(selected) = options.iter().find(|&o| o.as_ref().to_lowercase() == sel) {
|
||||
return Some(selected.as_ref());
|
||||
}
|
||||
|
||||
// Find starting abbreviation
|
||||
if let Some(selected) = options
|
||||
.iter()
|
||||
.find(|&o| o.as_ref().to_lowercase().starts_with(sel))
|
||||
{
|
||||
return Some(selected.as_ref());
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Add the PyPI pacakge path to the PATH environment variable (for this local process only).
|
||||
/// This is done so that `which` can find the commands inside the PyPI package.
|
||||
pub fn add_pkg_path() -> Result<()> {
|
||||
// Get PATH
|
||||
let pv = &env::var_os("PATH").context("`PATH` env var is not set or invalid")?;
|
||||
let mut path = env::split_paths(pv).collect::<Vec<_>>();
|
||||
let exe = env::current_exe().context("failed to get path of current running executable")?;
|
||||
let base = exe.parent().unwrap();
|
||||
|
||||
// Add from bin: ../git, ../fastfetch, ../scripts
|
||||
let to_add = ["git", "fastfetch", "scripts", "fastfetch/usr/bin"];
|
||||
if let Some(parent) = base.parent() {
|
||||
path.extend(to_add.iter().map(|d| parent.join(d)));
|
||||
}
|
||||
|
||||
// Add from cwd: ./hyfetch/git, ./hyfetch/fastfetch, ./hyfetch/scripts
|
||||
path.extend(to_add.iter().map(|d| PathBuf::from("hyfetch").join(d)));
|
||||
|
||||
// Set PATH
|
||||
env::set_var("PATH", env::join_paths(path).context("failed to join paths")?);
|
||||
debug!("Added PyPI package path to PATH, PATH={}", env::var("PATH")?);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Gets the absolute path of the [neofetch] command.
|
||||
///
|
||||
/// [neofetch]: https://github.com/hykilpikonna/hyfetch#running-updated-original-neofetch
|
||||
pub fn neofetch_path() -> Result<PathBuf> {
|
||||
if let Ok(p) = which("neowofetch") {
|
||||
return Ok(p);
|
||||
}
|
||||
|
||||
// Instead of doing that, let's write the neofetch script to a temp file
|
||||
let f: PathBuf = get_cache_path().context("Failed to get cache path")?.join("nf_script.sh");
|
||||
let mut file = fs::File::create(&f).context("Failed to create neofetch script file")?;
|
||||
file.write_all(NEOFETCH_SCRIPT.as_bytes())
|
||||
.context("Failed to write neofetch script to file")?;
|
||||
|
||||
Ok(f)
|
||||
}
|
||||
|
||||
/// Gets the absolute path of the [macchina] command.
|
||||
///
|
||||
/// [macchina]: https://github.com/Macchina-CLI/macchina
|
||||
#[cfg(feature = "macchina")]
|
||||
pub fn macchina_path() -> Result<Option<PathBuf>> {
|
||||
let macchina_path = {
|
||||
#[cfg(not(windows))]
|
||||
{
|
||||
find_in_path("macchina").context("failed to check existence of `macchina` in `PATH`")?
|
||||
}
|
||||
#[cfg(windows)]
|
||||
{
|
||||
find_in_path("macchina.exe")
|
||||
.context("failed to check existence of `macchina.exe` in `PATH`")?
|
||||
}
|
||||
};
|
||||
|
||||
// Fall back to `macchina.exe` in directory of current executable
|
||||
#[cfg(windows)]
|
||||
let macchina_path = macchina_path.map_or_else(
|
||||
|| {
|
||||
let current_exe_path: PathBuf = env::current_exe()
|
||||
.and_then(|p| p.normalize().map(|p| p.into()))
|
||||
.context("failed to get path of current running executable")?;
|
||||
let current_exe_dir_path = current_exe_path
|
||||
.parent()
|
||||
.expect("parent should not be `None`");
|
||||
let macchina_path = current_exe_dir_path.join("macchina.exe");
|
||||
find_file(&macchina_path)
|
||||
.with_context(|| format!("failed to check existence of file {macchina_path:?}"))
|
||||
},
|
||||
|path| Ok(Some(path)),
|
||||
)?;
|
||||
|
||||
Ok(macchina_path)
|
||||
}
|
||||
|
||||
/// Gets the distro ascii of the current distro. Or if distro is specified, get
|
||||
/// the specific distro's ascii art instead.
|
||||
#[tracing::instrument(level = "debug")]
|
||||
pub fn get_distro_ascii<S>(distro: Option<S>, backend: Backend) -> Result<RawAsciiArt>
|
||||
where
|
||||
S: AsRef<str> + fmt::Debug,
|
||||
{
|
||||
let distro: Cow<_> = if let Some(distro) = distro.as_ref() {
|
||||
distro.as_ref().into()
|
||||
} else {
|
||||
get_distro_name(backend)
|
||||
.context("failed to get distro name")?
|
||||
.into()
|
||||
};
|
||||
debug!(%distro, "distro name");
|
||||
|
||||
// Try new codegen-based detection method
|
||||
if let Some(distro) = Distro::detect(&distro) {
|
||||
let asc = distro.ascii_art().to_owned();
|
||||
let fg = ascii_foreground(&distro);
|
||||
|
||||
return Ok(RawAsciiArt { asc, fg });
|
||||
}
|
||||
|
||||
debug!(%distro, "could not find a match for distro; falling back to neofetch");
|
||||
|
||||
// Old detection method that calls neofetch
|
||||
let asc = run_neofetch_command_piped(&["print_ascii", "--ascii_distro", distro.as_ref()])
|
||||
.context("failed to get ascii art from neofetch")?;
|
||||
|
||||
// Unescape backslashes here because backslashes are escaped in neofetch for
|
||||
// printf
|
||||
let asc = asc.replace(r"\\", r"\");
|
||||
|
||||
Ok(RawAsciiArt {
|
||||
asc,
|
||||
fg: Vec::new(),
|
||||
})
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(asc), fields(asc.w = asc.w, asc.h = asc.h))]
|
||||
pub fn run(asc: RecoloredAsciiArt, backend: Backend, args: Option<&Vec<String>>) -> Result<()> {
|
||||
let asc = asc.lines.join("\n");
|
||||
|
||||
match backend {
|
||||
Backend::Neofetch => run_neofetch(asc, args).context("failed to run neofetch")?,
|
||||
Backend::Fastfetch => run_fastfetch(asc, args).context("failed to run fastfetch")?,
|
||||
#[cfg(feature = "macchina")]
|
||||
Backend::Macchina => run_macchina(asc, args).context("failed to run macchina")?,
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Gets distro ascii width and height, ignoring color code.
|
||||
pub fn ascii_size<S>(asc: S) -> Result<(u8, u8)>
|
||||
where
|
||||
S: AsRef<str>,
|
||||
{
|
||||
let asc = asc.as_ref();
|
||||
|
||||
if asc.is_empty() {
|
||||
return Ok((0, 0));
|
||||
}
|
||||
|
||||
let asc = {
|
||||
let ac =
|
||||
NEOFETCH_COLORS_AC.get_or_init(|| AhoCorasick::new(NEOFETCH_COLOR_PATTERNS).unwrap());
|
||||
const N: usize = NEOFETCH_COLOR_PATTERNS.len();
|
||||
const REPLACEMENTS: [&str; N] = [""; N];
|
||||
ac.replace_all(asc, &REPLACEMENTS)
|
||||
};
|
||||
|
||||
if asc.is_empty() {
|
||||
return Ok((0, 0));
|
||||
}
|
||||
|
||||
let width = asc
|
||||
.lines()
|
||||
.map(|line| line.graphemes(true).count())
|
||||
.max()
|
||||
.expect("line iterator should not be empty");
|
||||
let width: u8 = width.try_into().with_context(|| {
|
||||
format!(
|
||||
"`asc` should not have more than {limit} characters per line",
|
||||
limit = u8::MAX
|
||||
)
|
||||
})?;
|
||||
let height = asc.lines().count();
|
||||
let height: u8 = height.try_into().with_context(|| {
|
||||
format!(
|
||||
"`asc` should not have more than {limit} lines",
|
||||
limit = u8::MAX
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok((width, height))
|
||||
}
|
||||
|
||||
/// Gets the absolute path of the bash command.
|
||||
#[cfg(windows)]
|
||||
fn bash_path() -> Result<PathBuf> {
|
||||
// Find `bash.exe` in `PATH`, but exclude the known bad paths
|
||||
if let Some(bash_path) = find_in_path("bash.exe").context("bash.exe not found")? {
|
||||
// Check if it's not MSYS bash https://stackoverflow.com/a/58418686/1529493
|
||||
if !bash_path.ends_with(r"Git\usr\bin\bash.exe") {
|
||||
// Check if it's not WSL bash
|
||||
// See https://github.com/hykilpikonna/hyfetch/issues/233
|
||||
let windir = env::var_os("windir").context("`windir` environ not found")?;
|
||||
match is_same_file(&bash_path, Path::new(&windir).join(r"System32\bash.exe")) {
|
||||
Ok(false) => return Ok(bash_path),
|
||||
Err(err) if err.kind() == io::ErrorKind::NotFound => return Ok(bash_path),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(bash_path) = find_in_path("git.exe").context("failed to find `git.exe` in `PATH`")? {
|
||||
if bash_path.ends_with(r"Git\cmd\git.exe") {
|
||||
let pth = bash_path.parent().unwrap().parent().unwrap().join(r"bin\bash.exe");
|
||||
if pth.is_file() {
|
||||
return Ok(pth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Err(anyhow!("bash.exe not found"))
|
||||
}
|
||||
|
||||
/// Runs neofetch command, returning the piped stdout output.
|
||||
fn run_neofetch_command_piped<S>(args: &[S]) -> Result<String>
|
||||
where
|
||||
S: AsRef<OsStr> + fmt::Debug,
|
||||
{
|
||||
let mut command = make_neofetch_command(args)?;
|
||||
|
||||
let output = command
|
||||
.output()
|
||||
.context("failed to execute neofetch as child process")?;
|
||||
debug!(?output, "neofetch output");
|
||||
process_command_status(&output.status).context("neofetch command exited with error")?;
|
||||
|
||||
let out = String::from_utf8(output.stdout)
|
||||
.context("failed to process neofetch output as it contains invalid UTF-8")?
|
||||
.trim()
|
||||
.to_owned();
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
fn make_neofetch_command<S>(args: &[S]) -> Result<Command>
|
||||
where
|
||||
S: AsRef<OsStr>,
|
||||
{
|
||||
// Find neofetch script
|
||||
let neofetch_path = neofetch_path().context("neofetch command not found")?;
|
||||
|
||||
debug!(?neofetch_path, "neofetch path");
|
||||
|
||||
#[cfg(not(windows))]
|
||||
{
|
||||
let mut command = Command::new("bash");
|
||||
command.arg(neofetch_path);
|
||||
command.args(args);
|
||||
Ok(command)
|
||||
}
|
||||
#[cfg(windows)]
|
||||
{
|
||||
let bash_path = bash_path().context("failed to get bash path")?;
|
||||
let mut command = Command::new(bash_path);
|
||||
command.arg(neofetch_path);
|
||||
command.args(args);
|
||||
Ok(command)
|
||||
}
|
||||
}
|
||||
|
||||
/// Runs fastfetch command, returning the piped stdout output.
|
||||
fn run_fastfetch_command_piped<S>(args: &[S]) -> Result<String>
|
||||
where
|
||||
S: AsRef<OsStr> + fmt::Debug,
|
||||
{
|
||||
let mut command = make_fastfetch_command(args)?;
|
||||
|
||||
let output = command
|
||||
.output()
|
||||
.context("failed to execute fastfetch as child process")?;
|
||||
debug!(?output, "fastfetch output");
|
||||
process_command_status(&output.status).context("fastfetch command exited with error")?;
|
||||
|
||||
let out = String::from_utf8(output.stdout)
|
||||
.context("failed to process fastfetch output as it contains invalid UTF-8")?
|
||||
.trim()
|
||||
.to_owned();
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
pub fn fastfetch_path() -> Result<PathBuf> {
|
||||
which("fastfetch").context("fastfetch command not found")
|
||||
}
|
||||
|
||||
fn make_fastfetch_command<S>(args: &[S]) -> Result<Command>
|
||||
where
|
||||
S: AsRef<OsStr>,
|
||||
{
|
||||
// Find fastfetch executable
|
||||
let ff_path = fastfetch_path()?;
|
||||
debug!(?ff_path, "fastfetch path");
|
||||
|
||||
let mut command = Command::new(ff_path);
|
||||
command.env("FFTS_IGNORE_PARENT", "1");
|
||||
command.args(args);
|
||||
Ok(command)
|
||||
}
|
||||
|
||||
/// Runs macchina command, returning the piped stdout output.
|
||||
#[cfg(feature = "macchina")]
|
||||
fn run_macchina_command_piped<S>(args: &[S]) -> Result<String>
|
||||
where
|
||||
S: AsRef<OsStr> + fmt::Debug,
|
||||
{
|
||||
let mut command = make_macchina_command(args)?;
|
||||
|
||||
let output = command
|
||||
.output()
|
||||
.context("failed to execute macchina as child process")?;
|
||||
debug!(?output, "macchina output");
|
||||
process_command_status(&output.status).context("macchina command exited with error")?;
|
||||
|
||||
let out = String::from_utf8(output.stdout)
|
||||
.context("failed to process macchina output as it contains invalid UTF-8")?
|
||||
.trim()
|
||||
.to_owned();
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
#[cfg(feature = "macchina")]
|
||||
fn make_macchina_command<S>(args: &[S]) -> Result<Command>
|
||||
where
|
||||
S: AsRef<OsStr>,
|
||||
{
|
||||
// Find macchina executable
|
||||
let macchina_path = macchina_path()
|
||||
.context("failed to get macchina path")?
|
||||
.context("macchina command not found")?;
|
||||
|
||||
debug!(?macchina_path, "macchina path");
|
||||
|
||||
let mut command = Command::new(macchina_path);
|
||||
command.args(args);
|
||||
Ok(command)
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug")]
|
||||
pub fn get_distro_name(backend: Backend) -> Result<String> {
|
||||
match backend {
|
||||
Backend::Neofetch => run_neofetch_command_piped(&["ascii_distro_name"])
|
||||
.context("failed to get distro name from neofetch"),
|
||||
Backend::Fastfetch => Ok(run_fastfetch_command_piped(&["--logo", "none", "-c", "none", "-s", "OS",])
|
||||
.context("failed to get distro name from fastfetch")?.replace("OS: ", "")),
|
||||
#[cfg(feature = "macchina")]
|
||||
Backend::Macchina => {
|
||||
// Write ascii art to temp file
|
||||
let asc_file_path = {
|
||||
let mut temp_file = tempfile::Builder::new()
|
||||
.suffix("ascii.txt")
|
||||
.tempfile()
|
||||
.context("failed to create temp file for ascii art")?;
|
||||
temp_file
|
||||
.write_all(b"\t\n\t\n")
|
||||
.context("failed to write ascii art to temp file")?;
|
||||
temp_file.into_temp_path()
|
||||
};
|
||||
|
||||
// Write macchina theme to temp file
|
||||
let theme_file_path = {
|
||||
let project_dirs = directories::ProjectDirs::from("", "", "macchina")
|
||||
.context("failed to get base dirs")?;
|
||||
let themes_path = project_dirs.config_dir().join("themes");
|
||||
fs::create_dir_all(&themes_path).with_context(|| {
|
||||
format!("failed to create macchina themes dir {themes_path:?}")
|
||||
})?;
|
||||
let mut temp_file = tempfile::Builder::new()
|
||||
.suffix("theme.toml")
|
||||
.tempfile_in(themes_path)
|
||||
.context("failed to create temp file for macchina theme")?;
|
||||
let theme_doc = {
|
||||
let mut doc = DocumentMut::new();
|
||||
doc["spacing"] = value(0);
|
||||
doc["padding"] = value(0);
|
||||
// See https://github.com/Macchina-CLI/macchina/issues/319
|
||||
// doc["hide_ascii"] = value(true);
|
||||
doc["separator"] = value("");
|
||||
doc["custom_ascii"] = Item::Table(Table::from_iter([(
|
||||
"path",
|
||||
&*asc_file_path.to_string_lossy(),
|
||||
)]));
|
||||
doc["keys"] = Item::Table(Table::from_iter([("os", ""), ("distro", "")]));
|
||||
doc
|
||||
};
|
||||
debug!(%theme_doc, "macchina theme");
|
||||
temp_file
|
||||
.write_all(theme_doc.to_string().as_bytes())
|
||||
.context("failed to write macchina theme to temp file")?;
|
||||
temp_file.into_temp_path()
|
||||
};
|
||||
|
||||
let args: [&OsStr; 4] = [
|
||||
"--show".as_ref(),
|
||||
if cfg!(target_os = "linux") {
|
||||
"distribution"
|
||||
} else {
|
||||
"operating-system"
|
||||
}
|
||||
.as_ref(),
|
||||
"--theme".as_ref(),
|
||||
theme_file_path
|
||||
.file_stem()
|
||||
.expect("file name should not be `None`"),
|
||||
];
|
||||
run_macchina_command_piped(&args[..])
|
||||
.map(|s| {
|
||||
anstream::adapter::strip_str(&s)
|
||||
.to_string()
|
||||
.trim()
|
||||
.to_owned()
|
||||
})
|
||||
.context("failed to get distro name from macchina")
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Runs neofetch with custom ascii art.
|
||||
#[tracing::instrument(level = "debug", skip(asc))]
|
||||
fn run_neofetch(asc: String, args: Option<&Vec<String>>) -> Result<()> {
|
||||
// Escape backslashes here because backslashes are escaped in neofetch for
|
||||
// printf
|
||||
let asc = asc.replace('\\', r"\\");
|
||||
|
||||
// Write ascii art to temp file
|
||||
let asc_file_path = {
|
||||
let mut temp_file = tempfile::Builder::new()
|
||||
.suffix("ascii.txt")
|
||||
.tempfile()
|
||||
.context("failed to create temp file for ascii art")?;
|
||||
temp_file
|
||||
.write_all(asc.as_bytes())
|
||||
.context("failed to write ascii art to temp file")?;
|
||||
temp_file.into_temp_path()
|
||||
};
|
||||
|
||||
// Call neofetch
|
||||
let args = {
|
||||
let mut v: Vec<Cow<OsStr>> = vec![
|
||||
OsStr::new("--ascii").into(),
|
||||
OsStr::new("--source").into(),
|
||||
OsStr::new(&asc_file_path).into(),
|
||||
OsStr::new("--ascii_colors").into(),
|
||||
];
|
||||
if let Some(args) = args {
|
||||
v.extend(args.iter().map(|arg| OsStr::new(arg).into()));
|
||||
}
|
||||
v
|
||||
};
|
||||
let mut command = make_neofetch_command(&args[..])?;
|
||||
|
||||
debug!(?command, "neofetch command");
|
||||
|
||||
let status = command
|
||||
.status()
|
||||
.context("failed to execute neofetch command as child process")?;
|
||||
process_command_status(&status).context("neofetch command exited with error")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Runs fastfetch with custom ascii art.
|
||||
#[tracing::instrument(level = "debug", skip(asc))]
|
||||
fn run_fastfetch(asc: String, args: Option<&Vec<String>>) -> Result<()> {
|
||||
// Write ascii art to temp file
|
||||
let asc_file_path = {
|
||||
let mut temp_file = tempfile::Builder::new()
|
||||
.suffix("ascii.txt")
|
||||
.tempfile()
|
||||
.context("failed to create temp file for ascii art")?;
|
||||
temp_file
|
||||
.write_all(asc.as_bytes())
|
||||
.context("failed to write ascii art to temp file")?;
|
||||
temp_file.into_temp_path()
|
||||
};
|
||||
|
||||
// Call fastfetch
|
||||
let args = {
|
||||
let mut v: Vec<Cow<OsStr>> = vec![
|
||||
OsStr::new("--file-raw").into(),
|
||||
OsStr::new(&asc_file_path).into(),
|
||||
];
|
||||
if let Some(args) = args {
|
||||
v.extend(args.iter().map(|arg| OsStr::new(arg).into()));
|
||||
}
|
||||
v
|
||||
};
|
||||
let mut command = make_fastfetch_command(&args[..])?;
|
||||
|
||||
debug!(?command, "fastfetch command");
|
||||
|
||||
let status = command
|
||||
.status()
|
||||
.context("failed to execute fastfetch command as child process")?;
|
||||
process_command_status(&status).context("fastfetch command exited with error")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Runs macchina with custom ascii art.
|
||||
#[cfg(feature = "macchina")]
|
||||
#[tracing::instrument(level = "debug", skip(asc))]
|
||||
fn run_macchina(asc: String, args: Option<&Vec<String>>) -> Result<()> {
|
||||
// Write ascii art to temp file
|
||||
let asc_file_path = {
|
||||
let mut temp_file = tempfile::Builder::new()
|
||||
.suffix("ascii.txt")
|
||||
.tempfile()
|
||||
.context("failed to create temp file for ascii art")?;
|
||||
temp_file
|
||||
.write_all(asc.as_bytes())
|
||||
.context("failed to write ascii art to temp file")?;
|
||||
temp_file.into_temp_path()
|
||||
};
|
||||
|
||||
// Write macchina theme to temp file
|
||||
let theme_file_path = {
|
||||
let project_dirs = directories::ProjectDirs::from("", "", "macchina")
|
||||
.context("failed to get base dirs")?;
|
||||
let themes_path = project_dirs.config_dir().join("themes");
|
||||
fs::create_dir_all(&themes_path)
|
||||
.with_context(|| format!("failed to create macchina themes dir {themes_path:?}"))?;
|
||||
let mut temp_file = tempfile::Builder::new()
|
||||
.suffix("theme.toml")
|
||||
.tempfile_in(themes_path)
|
||||
.context("failed to create temp file for macchina theme")?;
|
||||
let theme_doc = {
|
||||
let mut doc = DocumentMut::new();
|
||||
doc["custom_ascii"] = Item::Table(Table::from_iter([(
|
||||
"path",
|
||||
&*asc_file_path.to_string_lossy(),
|
||||
)]));
|
||||
doc
|
||||
};
|
||||
debug!(%theme_doc, "macchina theme");
|
||||
temp_file
|
||||
.write_all(theme_doc.to_string().as_bytes())
|
||||
.context("failed to write macchina theme to temp file")?;
|
||||
temp_file.into_temp_path()
|
||||
};
|
||||
|
||||
let args = {
|
||||
let mut v: Vec<Cow<OsStr>> = vec![
|
||||
OsStr::new("--theme").into(),
|
||||
theme_file_path
|
||||
.file_stem()
|
||||
.expect("file name should not be `None`")
|
||||
.into(),
|
||||
];
|
||||
if let Some(args) = args {
|
||||
v.extend(args.iter().map(|arg| OsStr::new(arg).into()));
|
||||
}
|
||||
v
|
||||
};
|
||||
let mut command = make_macchina_command(&args[..])?;
|
||||
|
||||
debug!(?command, "macchina command");
|
||||
|
||||
let status = command
|
||||
.status()
|
||||
.context("failed to execute macchina command as child process")?;
|
||||
process_command_status(&status).context("macchina command exited with error")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Gets the color indices that should be considered as foreground, for a
|
||||
/// particular distro's ascii art.
|
||||
fn ascii_foreground(distro: &Distro) -> Vec<NeofetchAsciiIndexedColor> {
|
||||
let fg: Vec<u8> = match distro {
|
||||
Distro::Anarchy => vec![2],
|
||||
Distro::Android => vec![2],
|
||||
Distro::Antergos => vec![1],
|
||||
Distro::ArchStrike => vec![2],
|
||||
Distro::Arkane => vec![1],
|
||||
Distro::Asahi => vec![5],
|
||||
Distro::Astra_Linux => vec![2],
|
||||
Distro::BlackArch => vec![3],
|
||||
Distro::CelOS => vec![3],
|
||||
Distro::Chapeau => vec![2],
|
||||
Distro::Chrom => vec![5],
|
||||
Distro::Clear_Linux_OS => vec![2],
|
||||
Distro::Container_Linux_by_CoreOS => vec![3],
|
||||
Distro::CRUX => vec![3],
|
||||
Distro::EuroLinux => vec![2],
|
||||
Distro::eweOS => vec![3],
|
||||
Distro::Fedora => vec![2],
|
||||
Distro::Fedora_Sericea => vec![2],
|
||||
Distro::Fedora_Silverblue => vec![2],
|
||||
Distro::GalliumOS => vec![2],
|
||||
Distro::Gentoo => vec![1],
|
||||
Distro::HarDClanZ => vec![2],
|
||||
Distro::Kibojoe => vec![3],
|
||||
Distro::KrassOS => vec![2],
|
||||
Distro::Kubuntu => vec![2],
|
||||
Distro::Linux => vec![1],
|
||||
Distro::LinuxFromScratch => vec![1, 3],
|
||||
Distro::Lubuntu => vec![2],
|
||||
Distro::openEuler => vec![2],
|
||||
Distro::orchid => vec![1],
|
||||
Distro::Panwah => vec![1],
|
||||
Distro::Peppermint => vec![2],
|
||||
Distro::PNM_Linux => vec![2],
|
||||
Distro::Pop__OS => vec![2],
|
||||
Distro::Reborn_OS => vec![1],
|
||||
Distro::SalentOS => vec![4],
|
||||
Distro::Septor => vec![2],
|
||||
Distro::Ubuntu_Cinnamon => vec![2],
|
||||
Distro::Ubuntu_Kylin => vec![2],
|
||||
Distro::Ubuntu_MATE => vec![2],
|
||||
Distro::Ubuntu_old => vec![2],
|
||||
Distro::Ubuntu_Studio => vec![2],
|
||||
Distro::Ubuntu_Sway => vec![2],
|
||||
Distro::Ultramarine_Linux => vec![2],
|
||||
Distro::Univention => vec![2],
|
||||
Distro::uwuntu => vec![2],
|
||||
Distro::Vanilla => vec![2],
|
||||
Distro::VNux => vec![3, 5],
|
||||
Distro::Void => vec![2],
|
||||
Distro::Xray_OS => vec![2, 3],
|
||||
Distro::Xubuntu => vec![2],
|
||||
_ => Vec::new(),
|
||||
};
|
||||
|
||||
fg.into_iter()
|
||||
.map(|fore| {
|
||||
fore.try_into()
|
||||
.expect("`fore` should be a valid neofetch color index")
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
@@ -0,0 +1,901 @@
|
||||
use std::iter;
|
||||
use std::num::{NonZeroU8, NonZeroUsize};
|
||||
|
||||
use anyhow::{anyhow, Context as _, Result};
|
||||
use indexmap::IndexSet;
|
||||
use palette::num::ClampAssign as _;
|
||||
use palette::{IntoColorMut as _, LinSrgb, Okhsl, Srgb};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use strum::{AsRefStr, EnumCount, EnumString, VariantArray, VariantNames};
|
||||
use tracing::debug;
|
||||
use unicode_segmentation::UnicodeSegmentation as _;
|
||||
|
||||
use crate::color_util::{ForegroundBackground, Lightness, ToAnsiString as _};
|
||||
use crate::types::{AnsiMode, TerminalTheme};
|
||||
|
||||
#[derive(
|
||||
Copy,
|
||||
Clone,
|
||||
Hash,
|
||||
Debug,
|
||||
AsRefStr,
|
||||
Deserialize,
|
||||
EnumCount,
|
||||
EnumString,
|
||||
Serialize,
|
||||
VariantArray,
|
||||
VariantNames,
|
||||
)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
#[strum(serialize_all = "kebab-case")]
|
||||
pub enum Preset {
|
||||
Rainbow,
|
||||
|
||||
Transgender,
|
||||
|
||||
Nonbinary,
|
||||
|
||||
Xenogender,
|
||||
|
||||
Agender,
|
||||
|
||||
Queer,
|
||||
|
||||
Genderfluid,
|
||||
|
||||
Bisexual,
|
||||
|
||||
Pansexual,
|
||||
|
||||
Polysexual,
|
||||
|
||||
Omnisexual,
|
||||
|
||||
Omniromantic,
|
||||
|
||||
GayMen,
|
||||
|
||||
Lesbian,
|
||||
|
||||
Abrosexual,
|
||||
|
||||
Asexual,
|
||||
|
||||
Aromantic,
|
||||
|
||||
Fictosexual,
|
||||
|
||||
Aroace1,
|
||||
|
||||
Aroace2,
|
||||
|
||||
Aroace3,
|
||||
|
||||
Greysexual,
|
||||
|
||||
Autosexual,
|
||||
|
||||
Intergender,
|
||||
|
||||
Greygender,
|
||||
|
||||
Akiosexual,
|
||||
|
||||
Bigender,
|
||||
|
||||
Demigender,
|
||||
|
||||
Demiboy,
|
||||
|
||||
Demigirl,
|
||||
|
||||
Transmasculine,
|
||||
|
||||
Transfeminine,
|
||||
|
||||
Genderfaun,
|
||||
|
||||
Demifaun,
|
||||
|
||||
Genderfae,
|
||||
|
||||
Demifae,
|
||||
|
||||
Neutrois,
|
||||
|
||||
Biromantic1,
|
||||
|
||||
Autoromantic,
|
||||
|
||||
Boyflux2,
|
||||
|
||||
Girlflux,
|
||||
|
||||
Genderflux,
|
||||
|
||||
Nullflux,
|
||||
|
||||
Hypergender, Hyperboy, Hypergirl, Hyperandrogyne, Hyperneutrois,
|
||||
|
||||
Finsexual,
|
||||
|
||||
Unlabeled1,
|
||||
|
||||
Unlabeled2,
|
||||
|
||||
Pangender,
|
||||
|
||||
/// High-contrast version of pangender flag
|
||||
#[serde(rename = "pangender.contrast")]
|
||||
#[strum(serialize = "pangender.contrast")]
|
||||
PangenderContrast,
|
||||
|
||||
#[serde(rename = "gendernonconforming1")]
|
||||
#[strum(serialize = "gendernonconforming1")]
|
||||
GenderNonconforming1,
|
||||
|
||||
#[serde(rename = "gendernonconforming2")]
|
||||
#[strum(serialize = "gendernonconforming2")]
|
||||
GenderNonconforming2,
|
||||
|
||||
Femboy,
|
||||
|
||||
Tomboy,
|
||||
|
||||
Gynesexual,
|
||||
|
||||
Androsexual,
|
||||
|
||||
Gendervoid,
|
||||
|
||||
Voidgirl,
|
||||
|
||||
Voidboy,
|
||||
|
||||
NonhumanUnity,
|
||||
|
||||
/// For all the dogs
|
||||
Caninekin,
|
||||
|
||||
Plural,
|
||||
|
||||
Fraysexual,
|
||||
|
||||
Bear,
|
||||
|
||||
Butch,
|
||||
|
||||
Leather,
|
||||
|
||||
Otter,
|
||||
|
||||
Twink,
|
||||
|
||||
Adipophilia,
|
||||
|
||||
Kenochoric,
|
||||
|
||||
Veldian,
|
||||
|
||||
Solian,
|
||||
|
||||
Lunian,
|
||||
|
||||
Polyam,
|
||||
|
||||
Sapphic,
|
||||
|
||||
Androgyne,
|
||||
|
||||
Interprogress,
|
||||
|
||||
Progress,
|
||||
|
||||
Intersex,
|
||||
|
||||
OldPolyam,
|
||||
|
||||
EqualRights,
|
||||
|
||||
Drag,
|
||||
|
||||
Pronounfluid,
|
||||
|
||||
Pronounflux,
|
||||
|
||||
Exipronoun,
|
||||
|
||||
Neopronoun,
|
||||
|
||||
Neofluid,
|
||||
|
||||
Genderqueer,
|
||||
|
||||
Cisgender,
|
||||
|
||||
/// Colors from Gilbert Baker's original 1978 flag design
|
||||
Baker,
|
||||
|
||||
/// Meme flag
|
||||
Beiyang,
|
||||
|
||||
/// Meme flag
|
||||
Burger,
|
||||
|
||||
/// Meme flag
|
||||
#[serde(rename = "throatlozenges")]
|
||||
#[strum(serialize = "throatlozenges")]
|
||||
ThroatLozenges,
|
||||
|
||||
/// Meme flag
|
||||
Band,
|
||||
}
|
||||
|
||||
#[derive(Clone, Eq, PartialEq, Debug)]
|
||||
pub struct ColorProfile {
|
||||
pub colors: Vec<Srgb<u8>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
pub enum AssignLightness {
|
||||
Replace(Lightness),
|
||||
ClampMax(Lightness),
|
||||
ClampMin(Lightness),
|
||||
}
|
||||
|
||||
impl Preset {
|
||||
pub fn color_profile(&self) -> ColorProfile {
|
||||
(match self {
|
||||
Self::Rainbow => ColorProfile::from_hex_colors(vec![
|
||||
"#E50000", "#FF8D00", "#FFEE00", "#028121", "#004CFF", "#770088",
|
||||
]),
|
||||
|
||||
Self::Transgender => ColorProfile::from_hex_colors(vec![
|
||||
"#55CDFD", "#F6AAB7", "#FFFFFF", "#F6AAB7", "#55CDFD",
|
||||
]),
|
||||
|
||||
Self::Nonbinary => {
|
||||
ColorProfile::from_hex_colors(vec!["#FCF431", "#FCFCFC", "#9D59D2", "#282828"])
|
||||
},
|
||||
|
||||
// sourced from https://commons.wikimedia.org/wiki/File:Xenogender_pride_flag.svg
|
||||
Self::Xenogender => ColorProfile::from_hex_colors(vec![
|
||||
"#FF6692", "#FF9A98", "#FFB883", "#FBFFA8", "#85BCFF", "#9D85FF", "#A510FF",
|
||||
]),
|
||||
|
||||
Self::Agender => ColorProfile::from_hex_colors(vec![
|
||||
"#000000", "#BABABA", "#FFFFFF", "#BAF484", "#FFFFFF", "#BABABA", "#000000",
|
||||
]),
|
||||
|
||||
Self::Queer => ColorProfile::from_hex_colors(vec!["#B57FDD", "#FFFFFF", "#49821E"]),
|
||||
|
||||
Self::Genderfluid => ColorProfile::from_hex_colors(vec![
|
||||
"#FE76A2", "#FFFFFF", "#BF12D7", "#000000", "#303CBE",
|
||||
]),
|
||||
|
||||
Self::Bisexual => ColorProfile::from_hex_colors(vec!["#D60270", "#9B4F96", "#0038A8"]),
|
||||
|
||||
Self::Pansexual => ColorProfile::from_hex_colors(vec!["#FF1C8D", "#FFD700", "#1AB3FF"]),
|
||||
|
||||
Self::Polysexual => {
|
||||
ColorProfile::from_hex_colors(vec!["#F714BA", "#01D66A", "#1594F6"])
|
||||
},
|
||||
|
||||
// sourced from https://www.flagcolorcodes.com/omnisexual
|
||||
Self::Omnisexual => ColorProfile::from_hex_colors(vec![
|
||||
"#FE9ACE", "#FF53BF", "#200044", "#6760FE", "#8EA6FF",
|
||||
]),
|
||||
|
||||
Self::Omniromantic => ColorProfile::from_hex_colors(vec![
|
||||
"#FEC8E4", "#FDA1DB", "#89739A", "#ABA7FE", "#BFCEFF",
|
||||
]),
|
||||
|
||||
// sourced from https://www.flagcolorcodes.com/gay-men
|
||||
Self::GayMen => ColorProfile::from_hex_colors(vec![
|
||||
"#078D70", "#98E8C1", "#FFFFFF", "#7BADE2", "#3D1A78",
|
||||
]),
|
||||
|
||||
Self::Lesbian => ColorProfile::from_hex_colors(vec![
|
||||
"#D62800", "#FF9B56", "#FFFFFF", "#D462A6", "#A40062",
|
||||
]),
|
||||
|
||||
// used colorpicker to source from https://fyeahaltpride.tumblr.com/post/151704251345/could-you-guys-possibly-make-an-abrosexual-pride
|
||||
Self::Abrosexual => ColorProfile::from_hex_colors(vec![
|
||||
"#46D294", "#A3E9CA", "#FFFFFF", "#F78BB3", "#EE1766",
|
||||
]),
|
||||
|
||||
Self::Asexual => {
|
||||
ColorProfile::from_hex_colors(vec!["#000000", "#A4A4A4", "#FFFFFF", "#810081"])
|
||||
},
|
||||
|
||||
Self::Aromantic => ColorProfile::from_hex_colors(vec![
|
||||
"#3BA740", "#A8D47A", "#FFFFFF", "#ABABAB", "#000000",
|
||||
]),
|
||||
|
||||
// https://orientation.fandom.com/wiki/Fictosexual
|
||||
Self::Fictosexual => ColorProfile::from_hex_colors(vec![
|
||||
"#000000", "#C4C4C4", "#A349A5", "#C4C4C4", "#000000",
|
||||
]),
|
||||
|
||||
// sourced from https://flag.library.lgbt/flags/aroace/
|
||||
Self::Aroace1 => ColorProfile::from_hex_colors(vec![
|
||||
"#E28C00", "#ECCD00", "#FFFFFF", "#62AEDC", "#203856",
|
||||
]),
|
||||
|
||||
// sourced from https://flag.library.lgbt/flags/aroace/
|
||||
Self::Aroace2 => ColorProfile::from_hex_colors(vec![
|
||||
"#000000", "#810081", "#A4A4A4", "#FFFFFF", "#A8D47A", "#3BA740",
|
||||
]),
|
||||
|
||||
// sourced from https://flag.library.lgbt/flags/aroace/
|
||||
Self::Aroace3 => ColorProfile::from_hex_colors(vec![
|
||||
"#3BA740", "#A8D47A", "#FFFFFF", "#ABABAB", "#000000", "#A4A4A4", "#FFFFFF",
|
||||
"#810081",
|
||||
]),
|
||||
|
||||
// sourced from https://www.flagcolorcodes.com/greysexual
|
||||
Self::Greysexual => ColorProfile::from_hex_colors(vec![
|
||||
"#740194", "#AEB1AA", "#FFFFFF", "#AEB1AA", "#740194",
|
||||
]),
|
||||
|
||||
// sourced from https://www.flagcolorcodes.com/autosexual
|
||||
Self::Autosexual => ColorProfile::from_hex_colors(vec!["#99D9EA", "#7F7F7F"]),
|
||||
|
||||
// sourced from https://www.flagcolorcodes.com/intergender
|
||||
Self::Intergender => {
|
||||
ColorProfile::from_hex_colors(vec!["#900DC2", "#FFE54F", "#900DC2"])
|
||||
.and_then(|c| c.with_weights(vec![2, 1, 2]))
|
||||
},
|
||||
|
||||
// sourced from https://www.flagcolorcodes.com/greygender
|
||||
Self::Greygender => ColorProfile::from_hex_colors(vec![
|
||||
"#B3B3B3", "#FFFFFF", "#062383", "#FFFFFF", "#535353",
|
||||
])
|
||||
.and_then(|c| c.with_weights(vec![2, 1, 2, 1, 2])),
|
||||
|
||||
// sourced from https://www.flagcolorcodes.com/akiosexual
|
||||
Self::Akiosexual => ColorProfile::from_hex_colors(vec![
|
||||
"#F9485E", "#FEA06A", "#FEF44C", "#FFFFFF", "#000000",
|
||||
]),
|
||||
|
||||
// sourced from https://www.flagcolorcodes.com/bigender
|
||||
Self::Bigender => ColorProfile::from_hex_colors(vec![
|
||||
"#C479A2", "#EDA5CD", "#D6C7E8", "#FFFFFF", "#D6C7E8", "#9AC7E8", "#6D82D1",
|
||||
]),
|
||||
|
||||
// yellow sourced from https://lgbtqia.fandom.com/f/p/4400000000000041031
|
||||
// other colors sourced from demiboy and demigirl flags
|
||||
Self::Demigender => ColorProfile::from_hex_colors(vec![
|
||||
"#7F7F7F", "#C4C4C4", "#FBFF75", "#FFFFFF", "#FBFF75", "#C4C4C4", "#7F7F7F",
|
||||
]),
|
||||
|
||||
// sourced from https://www.flagcolorcodes.com/demiboy
|
||||
Self::Demiboy => ColorProfile::from_hex_colors(vec![
|
||||
"#7F7F7F", "#C4C4C4", "#9DD7EA", "#FFFFFF", "#9DD7EA", "#C4C4C4", "#7F7F7F",
|
||||
]),
|
||||
|
||||
// sourced from https://www.flagcolorcodes.com/demigirl
|
||||
Self::Demigirl => ColorProfile::from_hex_colors(vec![
|
||||
"#7F7F7F", "#C4C4C4", "#FDADC8", "#FFFFFF", "#FDADC8", "#C4C4C4", "#7F7F7F",
|
||||
]),
|
||||
|
||||
// sourced from https://www.flagcolorcodes.com/transmasculine
|
||||
Self::Transmasculine => ColorProfile::from_hex_colors(vec![
|
||||
"#FF8ABD", "#CDF5FE", "#9AEBFF", "#74DFFF", "#9AEBFF", "#CDF5FE", "#FF8ABD",
|
||||
]),
|
||||
|
||||
// used colorpicker to source from https://www.deviantart.com/pride-flags/art/Trans-Woman-Transfeminine-1-543925985
|
||||
// linked from https://gender.fandom.com/wiki/Transfeminine
|
||||
Self::Transfeminine => ColorProfile::from_hex_colors(vec![
|
||||
"#73DEFF", "#FFE2EE", "#FFB5D6", "#FF8DC0", "#FFB5D6", "#FFE2EE", "#73DEFF",
|
||||
]),
|
||||
|
||||
// sourced from https://www.flagcolorcodes.com/genderfaun
|
||||
Self::Genderfaun => ColorProfile::from_hex_colors(vec![
|
||||
"#FCD689", "#FFF09B", "#FAF9CD", "#FFFFFF", "#8EDED9", "#8CACDE", "#9782EC",
|
||||
]),
|
||||
|
||||
// sourced from https://www.flagcolorcodes.com/demifaun
|
||||
Self::Demifaun => ColorProfile::from_hex_colors(vec![
|
||||
"#7F7F7F", "#C6C6C6", "#FCC688", "#FFF19C", "#FFFFFF", "#8DE0D5", "#9682EC",
|
||||
"#C6C6C6", "#7F7F7F",
|
||||
])
|
||||
.and_then(|c| c.with_weights(vec![2, 2, 1, 1, 1, 1, 1, 2, 2])),
|
||||
|
||||
// sourced from https://www.flagcolorcodes.com/genderfae
|
||||
Self::Genderfae => ColorProfile::from_hex_colors(vec![
|
||||
"#97C3A5", "#C3DEAE", "#F9FACD", "#FFFFFF", "#FCA2C4", "#DB8AE4", "#A97EDD",
|
||||
]),
|
||||
|
||||
// used colorpicker to source form https://www.deviantart.com/pride-flags/art/Demifae-870194777
|
||||
Self::Demifae => ColorProfile::from_hex_colors(vec![
|
||||
"#7F7F7F", "#C5C5C5", "#97C3A4", "#C4DEAE", "#FFFFFF", "#FCA2C5", "#AB7EDF",
|
||||
"#C5C5C5", "#7F7F7F",
|
||||
])
|
||||
.and_then(|c| c.with_weights(vec![2, 2, 1, 1, 1, 1, 1, 2, 2])),
|
||||
|
||||
// sourced from https://www.flagcolorcodes.com/neutrois
|
||||
Self::Neutrois => ColorProfile::from_hex_colors(vec!["#FFFFFF", "#1F9F00", "#000000"]),
|
||||
|
||||
// sourced from https://www.flagcolorcodes.com/biromantic-alternate-2
|
||||
Self::Biromantic1 => ColorProfile::from_hex_colors(vec![
|
||||
"#8869A5", "#D8A7D8", "#FFFFFF", "#FDB18D", "#151638",
|
||||
]),
|
||||
|
||||
// sourced from https://www.flagcolorcodes.com/autoromantic
|
||||
Self::Autoromantic => ColorProfile::from_hex_colors(
|
||||
// symbol interpreted
|
||||
vec!["#99D9EA", "#3DA542", "#7F7F7F"],
|
||||
)
|
||||
.and_then(|c| c.with_weights(vec![2, 1, 2])),
|
||||
|
||||
// sourced from https://www.flagcolorcodes.com/boyflux-alternate-2
|
||||
Self::Boyflux2 => ColorProfile::from_hex_colors(vec![
|
||||
"#E48AE4", "#9A81B4", "#55BFAB", "#FFFFFF", "#A8A8A8", "#81D5EF", "#69ABE5",
|
||||
"#5276D4",
|
||||
])
|
||||
.and_then(|c| c.with_weights(vec![1, 1, 1, 1, 1, 5, 5, 5])),
|
||||
|
||||
// sourced from https://commons.wikimedia.org/wiki/File:Girlflux_Pride_Flag.jpg
|
||||
Self::Girlflux => ColorProfile::from_hex_colors(vec![
|
||||
"f9e6d7", "f2526c", "bf0311", "e9c587", "bf0311", "f2526c", "f9e6d7",
|
||||
]),
|
||||
|
||||
// sourced from https://www.deviantart.com/pride-flags/art/Genderflux-1-543925589
|
||||
Self::Genderflux => ColorProfile::from_hex_colors(vec![
|
||||
"f47694", "f2a2b9", "cecece", "7ce0f7", "3ecdf9", "fff48d",
|
||||
]),
|
||||
|
||||
Self::Nullflux => ColorProfile::from_hex_colors(vec![
|
||||
"#0B0C0E", "#A28DB9", "#E1D4EF", "#F0E6DD", "#665858",
|
||||
]),
|
||||
|
||||
Self::Hypergender => ColorProfile::from_hex_colors(vec![
|
||||
"#EFEFEF", "#FFFFFF", "#FBFF75", "#000000", "#FBFF75", "#FFFFFF", "#EFEFEF",
|
||||
]),
|
||||
|
||||
Self::Hyperboy => ColorProfile::from_hex_colors(vec![
|
||||
"#EFEFEF", "#FFFFFF", "#74D7FE", "#000000", "#74D7FE", "#FFFFFF", "#EFEFEF",
|
||||
]),
|
||||
|
||||
Self::Hypergirl => ColorProfile::from_hex_colors(vec![
|
||||
"#EFEFEF", "#FFFFFF", "#FC76D3", "#000000", "#FC76D3", "#FFFFFF", "#EFEFEF",
|
||||
]),
|
||||
|
||||
Self::Hyperandrogyne => ColorProfile::from_hex_colors(vec![
|
||||
"#EFEFEF", "#FFFFFF", "#BB83FF", "#000000", "#BB83FF", "#FFFFFF", "#EFEFEF",
|
||||
]),
|
||||
|
||||
Self::Hyperneutrois => ColorProfile::from_hex_colors(vec![
|
||||
"#EFEFEF", "#FFFFFF", "#BAFA74", "#000000", "#BAFA74", "#FFFFFF", "#EFEFEF",
|
||||
]),
|
||||
|
||||
// sourced from https://lgbtqia.wiki/wiki/Finsexual
|
||||
Self::Finsexual => ColorProfile::from_hex_colors(vec![
|
||||
"#B18EDF", "#D7B1E2", "#F7CDE9", "#F39FCE", "#EA7BB3",
|
||||
]),
|
||||
|
||||
// sourced from https://web.archive.org/web/20221002181913/https://unlabeledinfo.carrd.co/#flags
|
||||
Self::Unlabeled1 => {
|
||||
ColorProfile::from_hex_colors(vec!["#EAF8E4", "#FDFDFB", "#E1EFF7", "#F4E2C4"])
|
||||
},
|
||||
|
||||
// sourced from https://web.archive.org/web/20221002181913/https://unlabeledinfo.carrd.co/#flags
|
||||
Self::Unlabeled2 => ColorProfile::from_hex_colors(vec![
|
||||
"#250548", "#FFFFFF", "#F7DCDA", "#EC9BEE", "#9541FA", "#7D2557",
|
||||
]),
|
||||
|
||||
Self::Pangender => ColorProfile::from_hex_colors(vec![
|
||||
"#FFF798", "#FEDDCD", "#FFEBFB", "#FFFFFF", "#FFEBFB", "#FEDDCD", "#FFF798",
|
||||
]),
|
||||
|
||||
// high-contrast version of pangender flag
|
||||
Self::PangenderContrast => ColorProfile::from_hex_colors(vec![
|
||||
"#ffe87f", "#fcbaa6", "#fbc9f3", "#FFFFFF", "#fbc9f3", "#fcbaa6", "#ffe87f",
|
||||
]),
|
||||
|
||||
Self::GenderNonconforming1 => ColorProfile::from_hex_colors(vec![
|
||||
"#50284d", "#96467b", "#5c96f7", "#ffe6f7", "#5c96f7", "#96467b", "#50284d",
|
||||
])
|
||||
.and_then(|c| c.with_weights(vec![4, 1, 1, 1, 1, 1, 4])),
|
||||
|
||||
Self::GenderNonconforming2 => ColorProfile::from_hex_colors(vec![
|
||||
"#50284d", "#96467b", "#5c96f7", "#ffe6f7", "#5c96f7", "#96467b", "#50284d",
|
||||
]),
|
||||
|
||||
Self::Femboy => ColorProfile::from_hex_colors(vec![
|
||||
"#d260a5", "#e4afcd", "#fefefe", "#57cef8", "#fefefe", "#e4afcd", "#d260a5",
|
||||
]),
|
||||
|
||||
Self::Tomboy => ColorProfile::from_hex_colors(vec![
|
||||
"#2f3fb9", "#613a03", "#fefefe", "#f1a9b7", "#fefefe", "#613a03", "#2f3fb9",
|
||||
]),
|
||||
|
||||
// sourced from https://lgbtqia.fandom.com/wiki/Gynesexual
|
||||
Self::Gynesexual => {
|
||||
ColorProfile::from_hex_colors(vec!["#F4A9B7", "#903F2B", "#5B953B"])
|
||||
},
|
||||
|
||||
// sourced from https://lgbtqia.fandom.com/wiki/Androsexual
|
||||
Self::Androsexual => {
|
||||
ColorProfile::from_hex_colors(vec!["#01CCFF", "#603524", "#B799DE"])
|
||||
},
|
||||
|
||||
// sourced from: https://gender.fandom.com/wiki/Gendervoid
|
||||
Self::Gendervoid => ColorProfile::from_hex_colors(vec![
|
||||
"#081149", "#4B484B", "#000000", "#4B484B", "#081149",
|
||||
]),
|
||||
|
||||
// sourced from: https://gender.fandom.com/wiki/Gendervoid
|
||||
Self::Voidgirl => ColorProfile::from_hex_colors(vec![
|
||||
"#180827", "#7A5A8B", "#E09BED", "#7A5A8B", "#180827",
|
||||
]),
|
||||
|
||||
// sourced from: https://gender.fandom.com/wiki/Gendervoid
|
||||
Self::Voidboy => ColorProfile::from_hex_colors(vec![
|
||||
"#0B130C", "#547655", "#66B969", "#547655", "#0B130C",
|
||||
]),
|
||||
|
||||
// used https://twitter.com/foxbrained/status/1667621855518236674/photo/1 as source and colorpicked
|
||||
Self::NonhumanUnity => {
|
||||
ColorProfile::from_hex_colors(vec!["#177B49", "#FFFFFF", "#593C90"])
|
||||
},
|
||||
|
||||
// used https://www.tumblr.com/zombpawcoins/745062851267493888/caninekin-canine-therian-flag
|
||||
Self::Caninekin => ColorProfile::from_hex_colors(vec![
|
||||
"#2d2822", "#543d25", "#9c754d", "#e8dac2", "#cfad8c", "#b77b55", "#954e31",
|
||||
]),
|
||||
|
||||
// used https://pluralpedia.org/w/Plurality#/media/File:Plural-Flag-1.jpg as source and colorpicked
|
||||
Self::Plural => ColorProfile::from_hex_colors(vec![
|
||||
"#2D0625", "#543475", "#7675C3", "#89C7B0", "#F3EDBD",
|
||||
]),
|
||||
|
||||
// sampled from https://es.m.wikipedia.org/wiki/Archivo:Fraysexual_flag.jpg
|
||||
Self::Fraysexual => {
|
||||
ColorProfile::from_hex_colors(vec!["#226CB5", "#94E7DD", "#FFFFFF", "#636363"])
|
||||
},
|
||||
|
||||
// sourced from https://commons.wikimedia.org/wiki/File:Bear_Brotherhood_flag.svg
|
||||
Self::Bear => ColorProfile::from_hex_colors(vec![
|
||||
"#623804", "#D56300", "#FEDD63", "#FEE6B8", "#FFFFFF", "#555555",
|
||||
]),
|
||||
|
||||
// colorpicked from https://commons.wikimedia.org/wiki/File:Butch_Flag.png
|
||||
Self::Butch => ColorProfile::from_hex_colors(vec![
|
||||
"#D72800", "#F17623", "#FF9C56", "#FFFDF6", "#FFCE89", "#FEAF02", "#A37000",
|
||||
]),
|
||||
|
||||
// colorpicked from https://commons.wikimedia.org/wiki/File:Leather,_Latex,_and_BDSM_pride_-_Light.svg
|
||||
Self::Leather => ColorProfile::from_hex_colors(vec![
|
||||
"#000000", "#252580", "#000000", "#252580", "#FFFFFF", "#252580", "#000000",
|
||||
"#252580", "#000000",
|
||||
]),
|
||||
|
||||
// colorpicked from https://commons.wikimedia.org/wiki/File:Official_Otter_Pride_Flag_by_Bearbackgear.jpg
|
||||
Self::Otter => ColorProfile::from_hex_colors(vec![
|
||||
"#263881", "#5C9DC9", "#FFFFFF", "#3A291D", "#5C9DC9", "#263881",
|
||||
]),
|
||||
|
||||
// colorpicked from https://commons.wikimedia.org/wiki/File:Twink_Pride_Flag_(proposed).svg
|
||||
Self::Twink => ColorProfile::from_hex_colors(vec!["#FFB2FF", "#FFFFFF", "#FFFF81"]),
|
||||
|
||||
// https://en.wikipedia.org/wiki/File:FatFetishFlag.png
|
||||
Self::Adipophilia => ColorProfile::from_hex_colors(vec![
|
||||
"#000000", "#E16180", "#FFF9BE", "#603E41", "#000000",
|
||||
]),
|
||||
|
||||
Self::Kenochoric => {
|
||||
ColorProfile::from_hex_colors(vec!["#000000", "#2E1569", "#824DB7", "#C7A1D6"])
|
||||
},
|
||||
|
||||
Self::Veldian => ColorProfile::from_hex_colors(vec![
|
||||
"#D182A8", "#FAF6E0", "#69ACBE", "#5D448F", "#3A113E",
|
||||
]),
|
||||
|
||||
Self::Solian => ColorProfile::from_hex_colors(vec![
|
||||
"#FFF8ED", "#FFE7A8", "#F1B870", "#A56058", "#46281E",
|
||||
]),
|
||||
|
||||
Self::Lunian => ColorProfile::from_hex_colors(vec![
|
||||
"#2F0E62", "#6F41B1", "#889FDF", "#7DDFD5", "#D2F2E2",
|
||||
]),
|
||||
|
||||
// pulled from https://polyamproud.com/flag
|
||||
Self::Polyam => ColorProfile::from_hex_colors(vec![
|
||||
"#FFFFFF", "#FCBF00", "#009FE3", "#E50051", "#340C46",
|
||||
]),
|
||||
|
||||
Self::Sapphic => ColorProfile::from_hex_colors(vec![
|
||||
"#FD8BA8", "#FBF2FF", "#C76BC5", "#FDD768", "#C76BC5", "#FBF2FF", "#FD8BA8",
|
||||
]),
|
||||
|
||||
Self::Androgyne => ColorProfile::from_hex_colors(vec!["#FE007F", "#9832FF", "#00B8E7"]),
|
||||
|
||||
Self::Interprogress => ColorProfile::from_hex_colors(vec![
|
||||
"#FFD800", "#7902AA", "#FFFFFF", "#FFAFC8", "#74D7EE", "#613915", "#000000",
|
||||
"#E50000", "#FF8D00", "#FFEE00", "#028121", "#004CFF", "#770088",
|
||||
]),
|
||||
|
||||
Self::Progress => ColorProfile::from_hex_colors(vec![
|
||||
"#FFFFFF", "#FFAFC8", "#74D7EE", "#613915", "#000000", "#E50000", "#FF8D00",
|
||||
"#FFEE00", "#028121", "#004CFF", "#770088",
|
||||
]),
|
||||
|
||||
Self::Intersex => ColorProfile::from_hex_colors(vec!["#FFD800", "#7902AA", "#FFD800"])
|
||||
.and_then(|c| c.with_weights(vec![2, 1, 2])),
|
||||
|
||||
Self::OldPolyam => ColorProfile::from_hex_colors(vec![
|
||||
"#0000FF", "#FF0000", "#FFFF00", "#FF0000", "#000000",
|
||||
]),
|
||||
|
||||
Self::EqualRights => ColorProfile::from_hex_colors(vec![
|
||||
"#0000FF", "#FFFF00", "#0000FF", "#FFFF00", "#0000FF",
|
||||
])
|
||||
.and_then(|c| c.with_weights(vec![2, 1, 2, 1, 2])),
|
||||
|
||||
Self::Drag => ColorProfile::from_hex_colors(vec![
|
||||
"#CC67FF", "#FFFFFF", "#FFA3E3", "#FFFFFF", "#3366FF",
|
||||
]),
|
||||
|
||||
Self::Pronounfluid => ColorProfile::from_hex_colors(vec![
|
||||
"#FFB3F9", "#FFFFFF", "#D1FDCB", "#C7B0FF", "#000000", "#B8CCFF",
|
||||
]),
|
||||
|
||||
Self::Pronounflux => ColorProfile::from_hex_colors(vec![
|
||||
"#FDB3F8", "#B6CCFA", "#18DDD3", "#64FF89", "#FF7690", "#FFFFFF",
|
||||
]),
|
||||
|
||||
Self::Exipronoun => {
|
||||
ColorProfile::from_hex_colors(vec!["#1C3D34", "#FFFFFF", "#321848", "#000000"])
|
||||
},
|
||||
|
||||
Self::Neopronoun => {
|
||||
ColorProfile::from_hex_colors(vec!["#BCEC64", "#FFFFFF", "#38077A"])
|
||||
},
|
||||
|
||||
Self::Neofluid => ColorProfile::from_hex_colors(vec![
|
||||
"#FFECA0", "#FFFFFF", "#FFECA0", "#38087A", "#BCEC64",
|
||||
]),
|
||||
|
||||
Self::Genderqueer => ColorProfile::from_hex_colors(vec![
|
||||
"#B57EDC", "#FFFFFF", "#4A8123"
|
||||
]),
|
||||
|
||||
Self::Cisgender => ColorProfile::from_hex_colors(vec![
|
||||
"#D70270", "#0038A7"
|
||||
]),
|
||||
|
||||
// used https://gilbertbaker.com/rainbow-flag-color-meanings/ as source and colorpicked
|
||||
Self::Baker => ColorProfile::from_hex_colors(vec![
|
||||
"#F23D9E", "#F80A24", "#F78022", "#F9E81F", "#1E972E", "#1B86BC", "#243897", "#6F0A82",
|
||||
]),
|
||||
|
||||
Self::Beiyang => ColorProfile::from_hex_colors(vec![
|
||||
"#DF1B12", "#FFC600", "#01639D", "#FFFFFF", "#000000",
|
||||
]),
|
||||
|
||||
Self::Burger => ColorProfile::from_hex_colors(vec![
|
||||
"#F3A26A", "#498701", "#FD1C13", "#7D3829", "#F3A26A",
|
||||
]),
|
||||
|
||||
Self::ThroatLozenges => ColorProfile::from_hex_colors(vec![
|
||||
"#2759DA", "#03940D", "#F5F100", "#F59B00", "#B71212",
|
||||
]),
|
||||
|
||||
Self::Band => ColorProfile::from_hex_colors(vec![
|
||||
"#2670C0", "#F5BD00", "#DC0045", "#E0608E"
|
||||
]),
|
||||
|
||||
})
|
||||
.expect("preset color profiles should be valid")
|
||||
}
|
||||
}
|
||||
|
||||
impl ColorProfile {
|
||||
pub fn new(colors: Vec<Srgb<u8>>) -> Self {
|
||||
Self { colors }
|
||||
}
|
||||
|
||||
pub fn from_hex_colors<S>(hex_colors: Vec<S>) -> Result<Self>
|
||||
where
|
||||
S: AsRef<str>,
|
||||
{
|
||||
let colors = hex_colors
|
||||
.into_iter()
|
||||
.map(|s| s.as_ref().parse())
|
||||
.collect::<Result<_, _>>()
|
||||
.context("failed to parse hex colors")?;
|
||||
Ok(Self::new(colors))
|
||||
}
|
||||
|
||||
/// Maps colors based on weights.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `weights` - Weights of each color (`weights[i]` = how many times
|
||||
/// `colors[i]` appears)
|
||||
pub fn with_weights(&self, weights: Vec<u8>) -> Result<Self> {
|
||||
if weights.len() != self.colors.len() {
|
||||
debug!(?weights, ?self.colors, "length mismatch between `weights` and `colors`");
|
||||
return Err(anyhow!(
|
||||
"`weights` should have the same number of elements as `colors`"
|
||||
));
|
||||
}
|
||||
|
||||
let mut weighted_colors = Vec::new();
|
||||
|
||||
for (i, w) in weights.into_iter().enumerate() {
|
||||
weighted_colors.extend(iter::repeat(self.colors[i]).take(usize::from(w)));
|
||||
}
|
||||
|
||||
Ok(Self::new(weighted_colors))
|
||||
}
|
||||
|
||||
/// Creates a new color profile, with the colors spread to the specified
|
||||
/// length.
|
||||
pub fn with_length(&self, length: NonZeroU8) -> Result<Self> {
|
||||
let orig_len = self.colors.len();
|
||||
let orig_len: NonZeroUsize = orig_len.try_into().expect("`colors` should not be empty");
|
||||
let orig_len: NonZeroU8 = orig_len
|
||||
.try_into()
|
||||
.expect("`colors` should not have more than 255 elements");
|
||||
// TODO: I believe weird things can happen because of this...
|
||||
// if length < orig_len {
|
||||
// unimplemented!("compressing length of color profile not implemented");
|
||||
// }
|
||||
let center_i = usize::from(orig_len.get() / 2);
|
||||
|
||||
// How many copies of each color should be displayed at least?
|
||||
let repeats = length.get().div_euclid(orig_len.get());
|
||||
let mut weights = vec![repeats; NonZeroUsize::from(orig_len).get()];
|
||||
|
||||
// How many extra spaces left?
|
||||
let mut extras = length.get().rem_euclid(orig_len.get());
|
||||
|
||||
// If there is an odd space left, extend the center by one space
|
||||
if extras % 2 == 1 {
|
||||
weights[center_i] = weights[center_i].checked_add(1).unwrap();
|
||||
extras = extras.checked_sub(1).unwrap();
|
||||
}
|
||||
|
||||
// Add weight to border until there's no space left (extras must be even at this
|
||||
// point)
|
||||
let weights_len = weights.len();
|
||||
for border_i in 0..usize::from(extras / 2) {
|
||||
weights[border_i] = weights[border_i].checked_add(1).unwrap();
|
||||
let border_opp = weights_len
|
||||
.checked_sub(border_i)
|
||||
.unwrap()
|
||||
.checked_sub(1)
|
||||
.unwrap();
|
||||
weights[border_opp] = weights[border_opp].checked_add(1).unwrap();
|
||||
}
|
||||
|
||||
self.with_weights(weights)
|
||||
}
|
||||
|
||||
/// Colors a text.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `foreground_background` - Whether the color is shown on the foreground
|
||||
/// text or the background block
|
||||
/// * `space_only` - Whether to only color spaces
|
||||
pub fn color_text<S>(
|
||||
&self,
|
||||
txt: S,
|
||||
color_mode: AnsiMode,
|
||||
foreground_background: ForegroundBackground,
|
||||
space_only: bool,
|
||||
) -> Result<String>
|
||||
where
|
||||
S: AsRef<str>,
|
||||
{
|
||||
let txt = txt.as_ref();
|
||||
|
||||
let txt: Vec<&str> = txt.graphemes(true).collect();
|
||||
|
||||
let ColorProfile { colors } = {
|
||||
let length = txt.len();
|
||||
let length: NonZeroUsize = length.try_into().context("`txt` should not be empty")?;
|
||||
let length: NonZeroU8 = length.try_into().with_context(|| {
|
||||
format!(
|
||||
"`txt` should not have more than {limit} characters",
|
||||
limit = u8::MAX
|
||||
)
|
||||
})?;
|
||||
self.with_length(length)
|
||||
.with_context(|| format!("failed to spread color profile to length {length}"))?
|
||||
};
|
||||
|
||||
let mut buf = String::new();
|
||||
for (i, &gr) in txt.iter().enumerate() {
|
||||
if space_only && gr != " " {
|
||||
if i > 0 && txt[i.checked_sub(1).unwrap()] == " " {
|
||||
buf.push_str("\x1b[39;49m");
|
||||
}
|
||||
buf.push_str(gr);
|
||||
} else {
|
||||
buf.push_str(&colors[i].to_ansi_string(color_mode, foreground_background));
|
||||
buf.push_str(gr);
|
||||
}
|
||||
}
|
||||
|
||||
buf.push_str("\x1b[39;49m");
|
||||
Ok(buf)
|
||||
}
|
||||
|
||||
/// Creates a new color profile, with the colors lightened by a multiplier.
|
||||
pub fn lighten(&self, multiplier: f32) -> Self {
|
||||
let mut rgb_f32_colors: Vec<LinSrgb> =
|
||||
self.colors.iter().map(|c| c.into_linear()).collect();
|
||||
|
||||
{
|
||||
let okhsl_f32_colors: &mut [Okhsl] = &mut rgb_f32_colors.into_color_mut();
|
||||
|
||||
for okhsl_f32_color in okhsl_f32_colors {
|
||||
okhsl_f32_color.lightness *= multiplier;
|
||||
}
|
||||
}
|
||||
|
||||
let rgb_u8_colors: Vec<_> = rgb_f32_colors
|
||||
.into_iter()
|
||||
.map(Srgb::<u8>::from_linear)
|
||||
.collect();
|
||||
|
||||
Self {
|
||||
colors: rgb_u8_colors,
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new color profile, with the colors set to the specified
|
||||
/// [`Okhsl`] lightness value.
|
||||
pub fn with_lightness(&self, assign_lightness: AssignLightness) -> Self {
|
||||
let mut rgb_f32_colors: Vec<LinSrgb> =
|
||||
self.colors.iter().map(|c| c.into_linear()).collect();
|
||||
|
||||
{
|
||||
let okhsl_f32_colors: &mut [Okhsl] = &mut rgb_f32_colors.into_color_mut();
|
||||
|
||||
for okhsl_f32_color in okhsl_f32_colors {
|
||||
match assign_lightness {
|
||||
AssignLightness::Replace(lightness) => {
|
||||
okhsl_f32_color.lightness = lightness.into();
|
||||
},
|
||||
AssignLightness::ClampMax(lightness) => {
|
||||
okhsl_f32_color.lightness.clamp_max_assign(lightness.into());
|
||||
},
|
||||
AssignLightness::ClampMin(lightness) => {
|
||||
okhsl_f32_color.lightness.clamp_min_assign(lightness.into());
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let rgb_u8_colors: Vec<Srgb<u8>> = rgb_f32_colors
|
||||
.into_iter()
|
||||
.map(Srgb::<u8>::from_linear)
|
||||
.collect();
|
||||
|
||||
Self {
|
||||
colors: rgb_u8_colors,
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new color profile, with the colors set to the specified
|
||||
/// [`Okhsl`] lightness value, adapted to the terminal theme.
|
||||
pub fn with_lightness_adaptive(&self, lightness: Lightness, theme: TerminalTheme) -> Self {
|
||||
match theme {
|
||||
TerminalTheme::Dark => self.with_lightness(AssignLightness::ClampMin(lightness)),
|
||||
TerminalTheme::Light => self.with_lightness(AssignLightness::ClampMax(lightness)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates another color profile with only the unique colors.
|
||||
pub fn unique_colors(&self) -> Self {
|
||||
let unique_colors: IndexSet<[u8; 3]> = self.colors.iter().map(|&c| c.into()).collect();
|
||||
let unique_colors: Vec<Srgb<u8>> = unique_colors.into_iter().map(|c| c.into()).collect();
|
||||
Self::new(unique_colors)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,329 @@
|
||||
use std::fmt::Write as _;
|
||||
use std::io::{self, Write as _};
|
||||
use std::num::{NonZeroU16, NonZeroUsize, Wrapping};
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use std::{cmp, thread};
|
||||
|
||||
use anyhow::{anyhow, Context as _, Result};
|
||||
use crossterm::execute;
|
||||
use crossterm::terminal::{
|
||||
BeginSynchronizedUpdate, EndSynchronizedUpdate, EnterAlternateScreen, LeaveAlternateScreen,
|
||||
};
|
||||
use palette::blend::Blend as _;
|
||||
use palette::{LinSrgba, Srgb, WithAlpha as _};
|
||||
use strum::VariantArray as _;
|
||||
use terminal_size::{terminal_size, Height, Width};
|
||||
|
||||
use crate::color_util::{color, ForegroundBackground, ToAnsiString as _};
|
||||
use crate::neofetch_util::ascii_size;
|
||||
use crate::presets::Preset;
|
||||
use crate::types::AnsiMode;
|
||||
|
||||
const TEXT_ASCII: &str = r"
|
||||
.======================================================.
|
||||
| . . .__ . . . , . | |
|
||||
| |__| _.._ ._ . [__)._.* _| _ |\/| _ ._ -+-|_ | |
|
||||
| | |(_][_)[_)\_| | [ |(_](/, | |(_)[ ) | [ ) * |
|
||||
| | | ._| |
|
||||
'======================================================'
|
||||
";
|
||||
|
||||
const TEXT_ASCII_SMALL: &str = r"
|
||||
.====================.
|
||||
| Happy Pride Month! |
|
||||
'===================='
|
||||
";
|
||||
|
||||
const NOTICE: &str = "Press enter to continue";
|
||||
|
||||
pub fn start_animation(color_mode: AnsiMode) -> Result<()> {
|
||||
let (w, h) = {
|
||||
let (Width(w), Height(h)) = terminal_size().context("failed to get terminal size")?;
|
||||
let w: NonZeroU16 = w.try_into().context("terminal width should not be 0")?;
|
||||
let h: NonZeroU16 = h.try_into().context("terminal height should not be 0")?;
|
||||
(w, h)
|
||||
};
|
||||
|
||||
let text = &TEXT_ASCII[1..TEXT_ASCII.len().checked_sub(1).unwrap()];
|
||||
let (text_width, text_height) =
|
||||
ascii_size(text).expect("text ascii should have valid width and height");
|
||||
let (text, text_width, text_height) = {
|
||||
const TEXT_BORDER_WIDTH: u16 = 2;
|
||||
const NOTICE_BORDER_WIDTH: u16 = 1;
|
||||
const VERTICAL_MARGIN: u16 = 1;
|
||||
let notice_w = NOTICE.len();
|
||||
let notice_w: u8 = notice_w
|
||||
.try_into()
|
||||
.expect("`NOTICE` width should fit in `u8`");
|
||||
let notice_h = NOTICE.lines().count();
|
||||
let notice_h: u8 = notice_h
|
||||
.try_into()
|
||||
.expect("`NOTICE` height should fit in `u8`");
|
||||
let term_w_min = cmp::max(
|
||||
u16::from(text_width)
|
||||
.checked_add(TEXT_BORDER_WIDTH.checked_mul(2).unwrap())
|
||||
.unwrap(),
|
||||
u16::from(notice_w)
|
||||
.checked_add(NOTICE_BORDER_WIDTH.checked_mul(2).unwrap())
|
||||
.unwrap(),
|
||||
);
|
||||
let term_h_min = u16::from(text_height)
|
||||
.checked_add(notice_h.into())
|
||||
.unwrap()
|
||||
.checked_add(VERTICAL_MARGIN.checked_mul(2).unwrap())
|
||||
.unwrap();
|
||||
if w.get() >= term_w_min && h.get() >= term_h_min {
|
||||
(text, text_width, text_height)
|
||||
} else {
|
||||
let text = &TEXT_ASCII_SMALL[1..TEXT_ASCII_SMALL.len().checked_sub(1).unwrap()];
|
||||
let (text_width, text_height) =
|
||||
ascii_size(text).expect("text ascii should have valid width and height");
|
||||
let term_w_min = cmp::max(
|
||||
u16::from(text_width)
|
||||
.checked_add(TEXT_BORDER_WIDTH.checked_mul(2).unwrap())
|
||||
.unwrap(),
|
||||
u16::from(notice_w)
|
||||
.checked_add(NOTICE_BORDER_WIDTH.checked_mul(2).unwrap())
|
||||
.unwrap(),
|
||||
);
|
||||
let term_h_min = u16::from(text_height)
|
||||
.checked_add(notice_h.into())
|
||||
.unwrap()
|
||||
.checked_add(VERTICAL_MARGIN.checked_mul(2).unwrap())
|
||||
.unwrap();
|
||||
if w.get() < term_w_min || h.get() < term_h_min {
|
||||
return Err(anyhow!(
|
||||
"terminal size should be at least ({term_w_min} * {term_h_min})"
|
||||
));
|
||||
}
|
||||
(text, text_width, text_height)
|
||||
}
|
||||
};
|
||||
let text_lines: Vec<&str> = text.lines().collect();
|
||||
|
||||
const BLOCKS: u8 = 9;
|
||||
let block_width: NonZeroU16 = w
|
||||
.get()
|
||||
.div_euclid(u16::from(BLOCKS))
|
||||
.try_into()
|
||||
.with_context(|| format!("terminal width should be at least {BLOCKS}"))?;
|
||||
|
||||
let text_start_y = h
|
||||
.get()
|
||||
.div_euclid(2)
|
||||
.checked_sub((text_height / 2).into())
|
||||
.unwrap();
|
||||
let text_end_y = text_start_y.checked_add(text_height.into()).unwrap();
|
||||
let text_start_x = w
|
||||
.get()
|
||||
.div_euclid(2)
|
||||
.checked_sub((text_width / 2).into())
|
||||
.unwrap();
|
||||
let text_end_x = text_start_x.checked_add(text_width.into()).unwrap();
|
||||
|
||||
let notice_start_x = w
|
||||
.get()
|
||||
.checked_sub(
|
||||
u8::try_from(NOTICE.len())
|
||||
.expect("`NOTICE` length should fit in `u8`")
|
||||
.into(),
|
||||
)
|
||||
.unwrap()
|
||||
.checked_sub(1)
|
||||
.unwrap();
|
||||
let notice_end_x = w.get().checked_sub(1).unwrap();
|
||||
let notice_y = h.get().checked_sub(1).unwrap();
|
||||
|
||||
// Add every preset to colors
|
||||
let colors: Vec<Srgb<u8>> = Preset::VARIANTS
|
||||
.iter()
|
||||
.flat_map(|p| p.color_profile().colors)
|
||||
.collect();
|
||||
|
||||
let fg: Srgb<u8> = "#FFE09B"
|
||||
.parse()
|
||||
.expect("foreground color hex should be valid");
|
||||
let black = LinSrgba::new(0.0, 0.0, 0.0, 0.5);
|
||||
|
||||
let draw_frame = |frame: usize| -> Result<()> {
|
||||
execute!(io::stdout(), BeginSynchronizedUpdate)
|
||||
.context("failed to begin synchronized update")?;
|
||||
|
||||
let mut buf = String::new();
|
||||
|
||||
// Loop over the height
|
||||
for y in 0..h.get() {
|
||||
// Print the starting color
|
||||
write!(
|
||||
buf,
|
||||
"{bg}{fg}",
|
||||
bg = colors[frame
|
||||
.wrapping_add(y.into())
|
||||
.div_euclid(block_width.get().into())
|
||||
.rem_euclid(colors.len())]
|
||||
.to_ansi_string(color_mode, ForegroundBackground::Background),
|
||||
fg = fg.to_ansi_string(color_mode, ForegroundBackground::Foreground)
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Loop over the width
|
||||
for x in 0..w.get() {
|
||||
let idx = frame
|
||||
.wrapping_add(x.into())
|
||||
.wrapping_add(y.into())
|
||||
.wrapping_add_signed((2.0 * (y as f64 + 0.5 * frame as f64).sin()) as isize);
|
||||
let y_text = text_start_y <= y && y < text_end_y;
|
||||
|
||||
let border = 1u16
|
||||
.checked_add(
|
||||
if y == text_start_y || y == text_end_y.checked_sub(1).unwrap() {
|
||||
0
|
||||
} else {
|
||||
1
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
let text_bounds_x1 = text_start_x
|
||||
.checked_sub(border)
|
||||
.expect("`text_start_x - border` should not underflow `u16`");
|
||||
let text_bounds_x2 = text_end_x
|
||||
.checked_add(border)
|
||||
.expect("`text_end_x + border` should not overflow `u16`");
|
||||
let notice_bounds_x1 = notice_start_x
|
||||
.checked_sub(1)
|
||||
.expect("`notice_start_x - 1` should not underflow `u16`");
|
||||
let notice_bounds_x2 = notice_end_x
|
||||
.checked_add(1)
|
||||
.expect("`notice_end_x + 1` should not overflow `u16`");
|
||||
|
||||
// If it's a switching point
|
||||
if idx.rem_euclid(NonZeroUsize::from(block_width).get()) == 0
|
||||
|| x == text_bounds_x1
|
||||
|| x == text_bounds_x2
|
||||
|| x == notice_bounds_x1
|
||||
|| x == notice_bounds_x2
|
||||
{
|
||||
// Print the color at the current frame
|
||||
let ci = idx
|
||||
.div_euclid(NonZeroUsize::from(block_width).get())
|
||||
.rem_euclid(colors.len());
|
||||
let c = colors[ci];
|
||||
if (y_text && (text_bounds_x1 <= x) && (x < text_bounds_x2))
|
||||
|| (y == notice_y && notice_bounds_x1 <= x && x < notice_bounds_x2)
|
||||
{
|
||||
let c: LinSrgba = c.with_alpha(1.0).into_linear();
|
||||
let c = Srgb::<u8>::from_linear(c.overlay(black).without_alpha());
|
||||
write!(
|
||||
buf,
|
||||
"{bg}",
|
||||
bg = c.to_ansi_string(color_mode, ForegroundBackground::Background),
|
||||
)
|
||||
.unwrap();
|
||||
} else {
|
||||
write!(
|
||||
buf,
|
||||
"{bg}",
|
||||
bg = c.to_ansi_string(color_mode, ForegroundBackground::Background),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
// If text should be printed, print text
|
||||
if y_text && text_start_x <= x && x < text_end_x {
|
||||
write!(
|
||||
buf,
|
||||
"{text_char}",
|
||||
text_char = text_lines[usize::from(y.checked_sub(text_start_y).unwrap())]
|
||||
.chars()
|
||||
.nth(usize::from(x.checked_sub(text_start_x).unwrap()))
|
||||
.unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
} else if y == notice_y && notice_start_x <= x && x < notice_end_x {
|
||||
write!(
|
||||
buf,
|
||||
"{notice_char}",
|
||||
notice_char = NOTICE
|
||||
.chars()
|
||||
.nth(usize::from(x.checked_sub(notice_start_x).unwrap()))
|
||||
.unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
} else {
|
||||
write!(buf, " ").unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
// New line if it isn't the last line
|
||||
if y != h.get().checked_sub(1).unwrap() {
|
||||
writeln!(
|
||||
buf,
|
||||
"{reset}",
|
||||
reset = color("&r", color_mode).expect("reset should be valid"),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let mut stdout = io::stdout().lock();
|
||||
write!(stdout, "{buf}")
|
||||
.and_then(|_| stdout.flush())
|
||||
.context("failed to write to stdout")?;
|
||||
}
|
||||
|
||||
execute!(io::stdout(), EndSynchronizedUpdate)
|
||||
.context("failed to end synchronized update")?;
|
||||
|
||||
Ok(())
|
||||
};
|
||||
|
||||
let key_pressed = Arc::new(AtomicBool::new(false));
|
||||
|
||||
// TODO: use non-blocking I/O; no need for another thread
|
||||
let _handle = thread::spawn({
|
||||
let key_pressed = Arc::clone(&key_pressed);
|
||||
move || {
|
||||
loop {
|
||||
match io::stdin().lines().next() {
|
||||
Some(Ok(_)) => {
|
||||
key_pressed.store(true, Ordering::Release);
|
||||
break;
|
||||
},
|
||||
Some(Err(err)) => {
|
||||
eprintln!("failed to read line from stdin: {err}");
|
||||
},
|
||||
None => {
|
||||
// EOF
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let mut frame: Wrapping<usize> = Wrapping(0);
|
||||
|
||||
const SPEED: u8 = 2;
|
||||
let frame_delay = Duration::from_secs_f32(2.0 / 25.0);
|
||||
|
||||
execute!(io::stdout(), EnterAlternateScreen).context("failed to enter alternate screen")?;
|
||||
|
||||
loop {
|
||||
// Move cursor to the top left corner
|
||||
print!("\x1B[H");
|
||||
draw_frame(frame.0)?;
|
||||
frame += usize::from(SPEED);
|
||||
thread::sleep(frame_delay);
|
||||
|
||||
if key_pressed.load(Ordering::Acquire) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
execute!(io::stdout(), LeaveAlternateScreen).context("failed to leave alternate screen")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use strum::{AsRefStr, EnumString, VariantNames};
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, AsRefStr, Deserialize, EnumString, Serialize)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
#[strum(serialize_all = "lowercase")]
|
||||
pub enum AnsiMode {
|
||||
#[serde(rename = "ansi")]
|
||||
#[serde(skip)]
|
||||
#[strum(serialize = "ansi")]
|
||||
#[strum(disabled)]
|
||||
Ansi16,
|
||||
#[serde(rename = "8bit")]
|
||||
#[strum(serialize = "8bit")]
|
||||
Ansi256,
|
||||
Rgb,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Copy,
|
||||
Clone,
|
||||
Eq,
|
||||
PartialEq,
|
||||
Hash,
|
||||
Debug,
|
||||
AsRefStr,
|
||||
Deserialize,
|
||||
EnumString,
|
||||
Serialize,
|
||||
VariantNames,
|
||||
)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
#[strum(serialize_all = "lowercase")]
|
||||
pub enum TerminalTheme {
|
||||
Light,
|
||||
Dark,
|
||||
}
|
||||
|
||||
impl Default for TerminalTheme {
|
||||
fn default() -> Self {
|
||||
Self::Dark
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Copy,
|
||||
Clone,
|
||||
Eq,
|
||||
PartialEq,
|
||||
Hash,
|
||||
Debug,
|
||||
AsRefStr,
|
||||
Deserialize,
|
||||
EnumString,
|
||||
Serialize,
|
||||
VariantNames,
|
||||
)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
#[strum(serialize_all = "kebab-case")]
|
||||
pub enum Backend {
|
||||
Neofetch,
|
||||
Fastfetch,
|
||||
#[cfg(feature = "macchina")]
|
||||
Macchina,
|
||||
}
|
||||
|
||||
// See https://github.com/Peternator7/strum/issues/244
|
||||
impl VariantNames for AnsiMode {
|
||||
const VARIANTS: &'static [&'static str] = &["8bit", "rgb"];
|
||||
}
|
||||
@@ -0,0 +1,231 @@
|
||||
use std::io::Write as _;
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::process::ExitStatusExt as _;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::ExitStatus;
|
||||
use std::{env, fs, io};
|
||||
|
||||
use anyhow::{anyhow, Context as _, Result};
|
||||
use directories::ProjectDirs;
|
||||
#[cfg(windows)]
|
||||
use normpath::PathExt as _;
|
||||
use tracing::debug;
|
||||
|
||||
pub fn get_cache_path() -> Result<PathBuf> {
|
||||
let path = ProjectDirs::from("", "", "hyfetch")
|
||||
.context("failed to get base dirs")?
|
||||
.cache_dir()
|
||||
.to_owned();
|
||||
|
||||
// Make sure the cache directory exists
|
||||
if !path.exists() {
|
||||
fs::create_dir_all(&path).with_context(|| format!("failed to create cache dir {path:?}"))?;
|
||||
}
|
||||
|
||||
Ok(path)
|
||||
}
|
||||
|
||||
/// Reads a string from standard input. The trailing newline is stripped.
|
||||
///
|
||||
/// The prompt string, if given, is printed to standard output without a
|
||||
/// trailing newline before reading input.
|
||||
pub fn input<S>(prompt: Option<S>) -> Result<String>
|
||||
where
|
||||
S: AsRef<str>,
|
||||
{
|
||||
if let Some(prompt) = prompt {
|
||||
write!(io::stdout(), "{prompt}", prompt = prompt.as_ref())
|
||||
.and_then(|_| io::stdout().flush())
|
||||
.context("failed to write prompt to stdout")?;
|
||||
}
|
||||
|
||||
io::stdin()
|
||||
.lines()
|
||||
.next()
|
||||
.unwrap_or_else(|| Ok(String::new()))
|
||||
.context("failed to read line from stdin")
|
||||
}
|
||||
|
||||
/// Finds a command in `PATH`.
|
||||
///
|
||||
/// Returns the canonicalized / normalized absolute path of the command.
|
||||
pub fn find_in_path<P>(program: P) -> Result<Option<PathBuf>>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
let program = program.as_ref();
|
||||
|
||||
// Only accept program name, i.e. a relative path with one component
|
||||
if program.parent() != Some(Path::new("")) {
|
||||
return Err(anyhow!("invalid command name {program:?}"));
|
||||
};
|
||||
|
||||
let path_env = env::var_os("PATH").context("`PATH` env var is not set or invalid")?;
|
||||
|
||||
for search_path in env::split_paths(&path_env) {
|
||||
let path = search_path.join(program);
|
||||
let path = find_file(&path)
|
||||
.with_context(|| format!("failed to check existence of file {path:?}"))?;
|
||||
if path.is_some() {
|
||||
return Ok(path);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
/// Finds a file.
|
||||
///
|
||||
/// Returns the canonicalized / normalized absolute path of the file.
|
||||
pub fn find_file<P>(path: P) -> Result<Option<PathBuf>>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
let path = path.as_ref();
|
||||
|
||||
let metadata = match fs::metadata(path) {
|
||||
Ok(metadata) => metadata,
|
||||
Err(err) if err.kind() == io::ErrorKind::NotFound => {
|
||||
return Ok(None);
|
||||
},
|
||||
Err(err) => {
|
||||
return Err(err).with_context(|| format!("failed to get metadata for {path:?}"));
|
||||
},
|
||||
};
|
||||
|
||||
if !metadata.is_file() {
|
||||
debug!(?path, "path exists but is not a file");
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
{
|
||||
path.canonicalize()
|
||||
.with_context(|| format!("failed to canonicalize path {path:?}"))
|
||||
.map(Some)
|
||||
}
|
||||
#[cfg(windows)]
|
||||
{
|
||||
path.normalize()
|
||||
.with_context(|| format!("failed to normalize path {path:?}"))
|
||||
.map(|p| Some(p.into()))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn process_command_status(status: &ExitStatus) -> Result<()> {
|
||||
if status.success() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let err = if let Some(code) = status.code() {
|
||||
anyhow!("child process exited with status code: {code}")
|
||||
} else {
|
||||
#[cfg(unix)]
|
||||
{
|
||||
anyhow!(
|
||||
"child process terminated by signal: {signal}",
|
||||
signal = status
|
||||
.signal()
|
||||
.expect("either one of status code or signal should be set")
|
||||
)
|
||||
}
|
||||
#[cfg(not(unix))]
|
||||
{
|
||||
unimplemented!("status code not expected to be `None` on non-Unix platforms")
|
||||
}
|
||||
};
|
||||
Err(err)
|
||||
}
|
||||
|
||||
pub(crate) mod index_map_serde {
|
||||
use std::fmt;
|
||||
use std::hash::Hash;
|
||||
use std::marker::PhantomData;
|
||||
use std::str::FromStr;
|
||||
|
||||
use indexmap::IndexMap;
|
||||
use serde::de::{self, DeserializeSeed, MapAccess, Visitor};
|
||||
use serde::{Deserialize, Deserializer};
|
||||
|
||||
pub(crate) fn deserialize<'de, D, K, V>(deserializer: D) -> Result<IndexMap<K, V>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
K: Eq + Hash + FromStr,
|
||||
K::Err: fmt::Display,
|
||||
V: Deserialize<'de>,
|
||||
{
|
||||
struct KeySeed<K> {
|
||||
k: PhantomData<K>,
|
||||
}
|
||||
|
||||
impl<'de, K> DeserializeSeed<'de> for KeySeed<K>
|
||||
where
|
||||
K: FromStr,
|
||||
K::Err: fmt::Display,
|
||||
{
|
||||
type Value = K;
|
||||
|
||||
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
deserializer.deserialize_str(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<K> Visitor<'_> for KeySeed<K>
|
||||
where
|
||||
K: FromStr,
|
||||
K::Err: fmt::Display,
|
||||
{
|
||||
type Value = K;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("a string")
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
K::from_str(s).map_err(de::Error::custom)
|
||||
}
|
||||
}
|
||||
|
||||
struct MapVisitor<K, V> {
|
||||
k: PhantomData<K>,
|
||||
v: PhantomData<V>,
|
||||
}
|
||||
|
||||
impl<'de, K, V> Visitor<'de> for MapVisitor<K, V>
|
||||
where
|
||||
K: Eq + Hash + FromStr,
|
||||
K::Err: fmt::Display,
|
||||
V: Deserialize<'de>,
|
||||
{
|
||||
type Value = IndexMap<K, V>;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("a map")
|
||||
}
|
||||
|
||||
fn visit_map<A>(self, mut input: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: MapAccess<'de>,
|
||||
{
|
||||
let mut map = IndexMap::new();
|
||||
while let Some((k, v)) =
|
||||
input.next_entry_seed(KeySeed { k: PhantomData }, PhantomData)?
|
||||
{
|
||||
map.insert(k, v);
|
||||
}
|
||||
Ok(map)
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_map(MapVisitor {
|
||||
k: PhantomData,
|
||||
v: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
-36
@@ -1,36 +0,0 @@
|
||||
with import <nixpkgs> {};
|
||||
|
||||
rec {
|
||||
hyfetch = python3Packages.buildPythonPackage rec {
|
||||
pname = "HyFetch";
|
||||
version = "1.0.7";
|
||||
|
||||
src = pythonPackages.fetchPypi {
|
||||
inherit pname version;
|
||||
hash = "sha256-3/6/3EtTqHXTMuRIo2nclIxYSzOFvQegR29OJsKMQU4=";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = with python3Packages; [
|
||||
typing-extensions
|
||||
setuptools
|
||||
];
|
||||
|
||||
doCheck = false;
|
||||
|
||||
meta = with lib; {
|
||||
description = "neofetch with pride flags <3";
|
||||
longDescription = ''
|
||||
HyFetch is a command-line system information tool fork of neofetch.
|
||||
HyFetch displays information about your system next to your OS logo
|
||||
in ASCII representation. The ASCII representation is then colored in
|
||||
the pattern of the pride flag of your choice. The main purpose of
|
||||
HyFetch is to be used in screenshots to show other users what
|
||||
operating system or distribution you are running, what theme or
|
||||
icon set you are using, etc.
|
||||
'';
|
||||
homepage = "https://github.com/hykilpikonna/HyFetch";
|
||||
license = licenses.mit;
|
||||
mainProgram = "hyfetch";
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
|
||||
.TH VERSION: "1" "September 2025" "Version: 2.0.2" "User Commands"
|
||||
.SH NAME
|
||||
Version: \- manual page for Version: 2.0.2
|
||||
.SH SYNOPSIS
|
||||
.B hyfetch
|
||||
[\fI\,-c\/\fR] [\fI\,-C=CONFIG_FILE\/\fR] [\fI\,-p=PRESET\/\fR] [\fI\,-m=MODE\/\fR] [\fI\,-b=BACKEND\/\fR] [\fI\,--args=ARGS\/\fR] [\fI\,--c-scale=\/\fR
|
||||
.SH DESCRIPTION
|
||||
SCALE] [\-\-c\-set\-l=LIGHTNESS] [\-\-june] [\-\-debug] ([\-\-distro=DISTRO] | [\-\-test\-distro=DISTRO]) [
|
||||
\fB\-\-ascii\-file\fR=\fI\,ASCII_FILE]\/\fR [\-\-print\-font\-logo] [\-\-auto\-detect\-light\-dark=BOOL]
|
||||
.PP
|
||||
[1m[38;5;14mhyfetch[39m[22m \- neofetch with flags <3
|
||||
.SS "Available options:"
|
||||
.TP
|
||||
\fB\-c\fR, \fB\-\-config\fR
|
||||
Configure hyfetch
|
||||
.TP
|
||||
\fB\-C\fR, \fB\-\-config\-file\fR=\fI\,CONFIG_FILE\/\fR
|
||||
Use another config file
|
||||
[default: "/home/azalea/.config/hyfetch.json"]
|
||||
.TP
|
||||
\fB\-p\fR, \fB\-\-preset\fR=\fI\,PRESET\/\fR
|
||||
Use preset
|
||||
PRESET={rainbow,transgender,nonbinary,xenogender,agender,queer,genderfluid,bisexual,pansexual,polysexual,omnisexual,omniromantic,gay\-men,lesbian,abrosexual,asexual,aromantic,fictosexual,aroace1,aroace2,aroace3,greysexual,autosexual,intergender,greygender,akiosexual,bigender,demigender,demiboy,demigirl,transmasculine,transfeminine,genderfaun,demifaun,genderfae,demifae,neutrois,biromantic1,autoromantic,boyflux2,girlflux,genderflux,nullflux,hypergender,hyperboy,hypergirl,hyperandrogyne,hyperneutrois,finsexual,unlabeled1,unlabeled2,pangender,pangender.contrast,gendernonconforming1,gendernonconforming2,femboy,tomboy,gynesexual,androsexual,gendervoid,voidgirl,voidboy,nonhuman\-unity,caninekin,plural,fraysexual,bear,butch,leather,otter,twink,adipophilia,kenochoric,veldian,solian,lunian,polyam,sapphic,androgyne,interprogress,progress,intersex,old\-polyam,equal\-rights,drag,pronounfluid,pronounflux,exipronoun,neopronoun,neofluid,genderqueer,cisgender,baker,beiyang,burger,throatlozenges,band,random}
|
||||
.TP
|
||||
\fB\-m\fR, \fB\-\-mode\fR=\fI\,MODE\/\fR
|
||||
Color mode MODE={8bit,rgb}
|
||||
.TP
|
||||
\fB\-b\fR, \fB\-\-backend\fR=\fI\,BACKEND\/\fR
|
||||
Choose a *fetch backend BACKEND={neofetch,fastfetch,macchina}
|
||||
.TP
|
||||
\fB\-\-args\fR=\fI\,ARGS\/\fR
|
||||
Additional arguments pass\-through to backend
|
||||
.TP
|
||||
\fB\-\-c\-scale\fR=\fI\,SCALE\/\fR
|
||||
Lighten colors by a multiplier
|
||||
.TP
|
||||
\fB\-\-c\-set\-l\fR=\fI\,LIGHTNESS\/\fR
|
||||
Set lightness value of the colors
|
||||
.TP
|
||||
\fB\-\-june\fR
|
||||
Show pride month easter egg
|
||||
.TP
|
||||
\fB\-\-debug\fR
|
||||
Debug mode
|
||||
.TP
|
||||
\fB\-\-distro\fR=\fI\,DISTRO\/\fR
|
||||
Test for a specific distro
|
||||
.TP
|
||||
\fB\-\-test\-distro\fR=\fI\,DISTRO\/\fR
|
||||
Test for a specific distro
|
||||
.TP
|
||||
\fB\-\-ascii\-file\fR=\fI\,ASCII_FILE\/\fR
|
||||
Use a specific file for the ascii art
|
||||
.TP
|
||||
\fB\-\-print\-font\-logo\fR
|
||||
Print the Font Logo / Nerd Font icon of your distro and exit
|
||||
.TP
|
||||
\fB\-\-auto\-detect\-light\-dark\fR=\fI\,BOOL\/\fR
|
||||
Enables hyfetch to detect light/dark terminal background in
|
||||
runtime
|
||||
.TP
|
||||
\fB\-h\fR, \fB\-\-help\fR
|
||||
Prints help information
|
||||
.TP
|
||||
\fB\-V\fR, \fB\-\-version\fR
|
||||
Prints version information
|
||||
.SH "SEE ALSO"
|
||||
The full documentation for
|
||||
.B Version:
|
||||
is maintained as a Texinfo manual. If the
|
||||
.B info
|
||||
and
|
||||
.B Version:
|
||||
programs are properly installed at your site, the command
|
||||
.IP
|
||||
.B info Version:
|
||||
.PP
|
||||
should give you access to the complete manual.
|
||||
@@ -1,7 +1,7 @@
|
||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
|
||||
.TH NEOFETCH "1" "June 2023" "Neofetch 7.3.9" "User Commands"
|
||||
.TH NEOFETCH "1" "September 2025" "Neofetch 8.0.2" "User Commands"
|
||||
.SH NAME
|
||||
Neofetch \- manual page for Neofetch 7.3.9
|
||||
Neofetch \- manual page for Neofetch 8.0.2
|
||||
.SH SYNOPSIS
|
||||
.B neofetch
|
||||
\fI\,func_name --option "value" --option "value"\/\fR
|
||||
@@ -46,6 +46,12 @@ Hide/Show Fully Qualified Domain Name in title.
|
||||
\fB\-\-package_managers\fR on/off
|
||||
Hide/Show Package Manager names. (on, tiny, off)
|
||||
.TP
|
||||
\fB\-\-package_separate\fR on/off
|
||||
Whether to separate system/user modes for supported package managers
|
||||
.TP
|
||||
\fB\-\-package_minimal\fR
|
||||
Reduce output of packages list by not showing programming language package managers or Steam games
|
||||
.TP
|
||||
\fB\-\-os_arch\fR on/off
|
||||
Hide/Show OS architecture.
|
||||
.TP
|
||||
@@ -310,61 +316,71 @@ Colors to print the ascii art
|
||||
\fB\-\-ascii_distro\fR distro
|
||||
Which Distro's ascii art to print
|
||||
.TP
|
||||
NOTE: AIX, AlmaLinux, Alpine, Alter, Amazon, AmogOS, Anarchy,
|
||||
Android, Antergos, antiX, AOSC OS, AOSC OS/Retro, Aperio GNU/Linux,
|
||||
Aperture, Apricity, Arch, ArchBox, Archcraft, archcraft_ascii,
|
||||
archcraft_minimal, ARCHlabs, ArchMerge, ArchStrike, ArcoLinux,
|
||||
ArseLinux, Artix, Arya, Asahi, Aster, AsteroidOS, astOS, Astra
|
||||
Linux, Bedrock, BigLinux, Bitrig, BlackArch, blackPanther, BLAG,
|
||||
NOTE: Ad??lie, aerOS, Afterglow, AIX, AlmaLinux, Alpine, Alter,
|
||||
Amazon, AmogOS, Anarchy, Android, Antergos, antiX, AOSC OS, Aperio
|
||||
GNU/Linux, Aperture, Apricity, Arch, ArchBox, Archcraft,
|
||||
archcraft_ascii, archcraft_minimal, ARCHlabs, ArchMerge, ArchStrike,
|
||||
ArcoLinux, Arkane, ArseLinux, Artix, Arya, Asahi, AsteroidOS, astOS,
|
||||
Astra Linux, Athena, azos, Bazzite, Bedrock, BigLinux,
|
||||
BigLinux_large, Bitrig, BlackArch, BlackMesa, blackPanther, BLAG,
|
||||
BlankOn, BlueLight, Bodhi, bonsai, BSD, BunsenLabs, CachyOS,
|
||||
Calculate, CalinixOS, Carbs, CBL\-Mariner, CelOS, Center, CentOS,
|
||||
Chakra, ChaletOS, Chapeau, ChonkySealOS, Chrom, Cleanjaro, Clear
|
||||
Linux OS, ClearOS, Clover, Cobalt, Condres, Container Linux by
|
||||
Chakra, ChaletOS, Chapeau, Chimera, ChonkySealOS, Chrom, Cleanjaro,
|
||||
Clear Linux OS, ClearOS, Clover, Cobalt, Condres, Container Linux by
|
||||
CoreOS, CRUX, Crystal Linux, Cucumber, CutefishOS, CuteOS, CyberOS,
|
||||
dahlia, DarkOs, Darwin, Debian, Deepin, DesaOS, Devuan, DietPi,
|
||||
DracOS, DragonFly, Drauger, Droidian, Elementary, Elive, EncryptOS,
|
||||
EndeavourOS, Endless, Enso, EuroLinux, Exherbo, Exodia Predator OS,
|
||||
Fedora, FemboyOS, Feren, Finnix, Floflis, FreeBSD, FreeMiNT,
|
||||
Frugalware, Funtoo, GalliumOS, Garuda, Gentoo, GhostBSD, glaucus,
|
||||
gNewSense, GNOME, GNU, GoboLinux, GrapheneOS, Grombyang, Guix,
|
||||
Haiku, HamoniKR, HarDClanZ, Hash, Huayra, Hybrid, HydroOS,
|
||||
Hyperbola, iglunix, instantOS, IRIX, Itc, januslinux, Kaisen, Kali,
|
||||
KaOS, KDE, Kibojoe, Kogaion, Korora, KrassOS, KSLinux, Kubuntu,
|
||||
LangitKetujuh, LaxerOS, LEDE, LibreELEC, Linspire, Linux, Linux
|
||||
Lite, Linux Mint, Linux Mint Old, Live Raizo, LMDE, Lubuntu, Lunar,
|
||||
mac, Mageia, MagpieOS, Mandriva, Manjaro, MassOS, MatuusOS, Maui,
|
||||
Mer, Minix, MIRACLE LINUX, MX, Namib, NekOS, Neptune, NetBSD,
|
||||
Netrunner, Nitrux, NixOS, Nobara, NomadBSD, Nurunner, NuTyX, Obarun,
|
||||
OBRevenge, OmniOS, Open Source Media Center, OpenBSD, openEuler,
|
||||
OpenIndiana, openmamba, OpenMandriva, OpenStage, openSUSE, openSUSE
|
||||
Leap, openSUSE Tumbleweed, OpenWrt, OPNsense, Oracle, orchid, OS
|
||||
Elbrus, PacBSD, Parabola, parch, Pardus, Parrot, Parsix, PCBSD,
|
||||
PCLinuxOS, pearOS, Pengwin, Pentoo, Peppermint, PikaOS, Pisi, PNM
|
||||
Linux, Pop!_OS, Porteus, PostMarketOS, Profelis SambaBOX, Proxmox,
|
||||
PuffOS, Puppy, PureOS, Q4OS, Qubes, Qubyt, Quibian, Radix, Raspbian,
|
||||
ravynOS, Reborn OS, Red Star, Redcore, Redhat, Refracted Devuan,
|
||||
Regata, Regolith, RhaymOS, rocky, Rosa, Sabayon, sabotage, Sailfish,
|
||||
SalentOS, Salient OS, Sasanqua, Scientific, semc, Septor, Serene,
|
||||
SharkLinux, ShastraOS, Siduction, SkiffOS, Slackware, SliTaz,
|
||||
SmartOS, Soda, Solus, Source Mage, Sparky, Star, SteamOS, Stock
|
||||
Linux, Sulin, SunOS, SwagArch, t2, Tails, TeArch, TorizonCore,
|
||||
Trisquel, Twister, Ubuntu, Ubuntu Budgie, Ubuntu Cinnamon, Ubuntu
|
||||
Kylin, Ubuntu MATE, Ubuntu Studio, Ubuntu Sway, Ubuntu Touch,
|
||||
Ubuntu\-GNOME, ubuntu_old02, Ultramarine Linux, Univalent,
|
||||
Univention, Uos, UrukOS, uwuntu, Vanilla, Venom, VNux, Void,
|
||||
VzLinux, wii\-linux\-ngx, Windows, Windows 10, Windows 11, XFerience,
|
||||
Xubuntu, yiffOS, Zorin have ascii logos.
|
||||
digital UNIX, DracOS, DragonFly, Drauger, Droidian, Elementary,
|
||||
Elive, EncryptOS, EndeavourOS, Endless, Enso, EuroLinux,
|
||||
EvolutionOS, eweOS, Exherbo, Exodia Predator OS, Fedora, Fedora
|
||||
Kinoite, Fedora Sericea, Fedora Silverblue, Fedora_unicode,
|
||||
FemboyOS, Feren, Finnix, Floflis, FreeBSD, FreeMiNT, Frugalware,
|
||||
Funtoo, Furreto, GalliumOS, Garuda, Gentoo, GhostBSD, glaucus,
|
||||
Gloire, gNewSense, GNOME, GNU, GoboLinux, GrapheneOS, Grombyang,
|
||||
Guix, Haiku, HamoniKR, HarDClanZ, Hash, Huayra, Hybrid, HydroOS,
|
||||
Hyperbola, iglunix, instantOS, Interix, IRIX, Itc, januslinux,
|
||||
Kaisen, Kali, KaOS, KDE, Kibojoe, Kogaion, Korora, KrassOS, KSLinux,
|
||||
Kubuntu, LainOS, LangitKetujuh, LaxerOS, LEDE, LibreELEC, Linspire,
|
||||
Linux, Linux Lite, Linux Mint, Linux Mint Old, LinuxFromScratch,
|
||||
Live Raizo, LMDE, Lubuntu, Lunar, mac, MacaroniOS, Mageia, Magix,
|
||||
MagpieOS, MainsailOS, Mandriva, Manjaro, MassOS, MatuusOS, Maui,
|
||||
Mauna, Meowix, Mer, Minix, MIRACLE LINUX, MX, Namib, NekOS, Neptune,
|
||||
NetBSD, Netrunner, Nitrux, NixOS, nixos_colorful, Nobara, NomadBSD,
|
||||
Nurunner, NuTyX, Obarun, OBRevenge, OmniOS, Open Source Media
|
||||
Center, OpenBSD, openEuler, OpenIndiana, openKylin, openmamba,
|
||||
OpenMandriva, OpenStage, openSUSE, openSUSE Leap, openSUSE
|
||||
Tumbleweed, openSUSE Tumbleweed\-Slowroll, OPNsense, Oracle, orchid,
|
||||
OS Elbrus, PacBSD, Panwah, Parabola, parch, Pardus, Parrot, Parsix,
|
||||
PCBSD, PCLinuxOS, pearOS, Pengwin, Pentoo, Peppermint, Peropesis,
|
||||
phyOS, PikaOS, Pisi, PNM Linux, Pop!_OS, Porteus, PostMarketOS,
|
||||
Profelis SambaBOX, Proxmox, PuffOS, Puppy, PureOS, Q4OS, Qubes,
|
||||
Qubyt, Quibian, Radix, Raspbian, ravynOS, Reborn OS, Red Star,
|
||||
Redcore, Redhat, Refracted Devuan, Regata, Regolith, RhaymOS, Rhino
|
||||
Linux, rocky, Rosa, Sabayon, sabotage, Sailfish, SalentOS, Salient
|
||||
OS, Salix, Sasanqua, Scientific, semc, Septor, Serene, SharkLinux,
|
||||
ShastraOS, Siduction, SkiffOS, Slackel, Slackware, SliTaz, SmartOS,
|
||||
Soda, Solus, Source Mage, Sparky, Star, SteamOS, Stock Linux, Sulin,
|
||||
SunOS, SwagArch, t2, Tails, Tatra, TeArch, TorizonCore, Trisquel,
|
||||
Twister, Ubuntu, Ubuntu Budgie, Ubuntu Cinnamon, Ubuntu Kylin,
|
||||
Ubuntu MATE, Ubuntu Studio, Ubuntu Sway, Ubuntu Touch, Ubuntu\-GNOME,
|
||||
ubuntu_old02, Ultramarine Linux, unicodearch, Univalent, Univention,
|
||||
Uos, UrukOS, uwuntu, Vanilla, Venom, VNux, Void, VzLinux, wii\-linuxngx, Windows, Windows 10, Windows 11, Windows95, Wrt, Xenia, Xenia2,
|
||||
XFerience, Xray_OS, Xubuntu, yiffOS, Zorin have ascii logos.
|
||||
.TP
|
||||
NOTE: arch, dragonfly, Fedora, LangitKetujuh, nixos, redhat, Ubuntu
|
||||
have 'old' logo variants, use {distro}_old to use them.
|
||||
.TP
|
||||
NOTE: alpine, android, aoscosretro, arch, arcolinux, artix,
|
||||
CalinixOS, centos, cleanjaro, crux, debian, dragonfly, elementary,
|
||||
fedora, freebsd, garuda, gentoo, guix, haiku, hyperbola, kali,
|
||||
linuxlite, linuxmint, mac, mageia, manjaro, mx, netbsd, nixos,
|
||||
openbsd, opensuse, orchid, parabola, popos, postmarketos, pureos,
|
||||
Raspbian, rocky, slackware, sunos, ubuntu, void have 'small' logo
|
||||
variants, use {distro}_small to use them.
|
||||
NOTE: alpine, android, arch, arcolinux, artix, CalinixOS, centos,
|
||||
cleanjaro, crux, debian, dragonfly, elementary, endeavouros, fedora,
|
||||
freebsd, garuda, gentoo, guix, haiku, hyperbola, kali, Linux,
|
||||
linuxlite, linuxmint, mac, mageia, MainsailOS, manjaro, mx, netbsd,
|
||||
nixos, openbsd, opensuse, orchid, parabola, popos, postmarketos,
|
||||
pureos, Raspbian, rocky, slackware, sunos, ubuntu, venom, void have
|
||||
\&'small' logo variants, use {distro}_small to use them.
|
||||
.IP
|
||||
NOTE: Fedora has immutable spins with unique logos (except Onyx).
|
||||
.TP
|
||||
NOTE: Change this to Silverblue, Kinoite, Sericea, or CoreOS to use
|
||||
the spins.
|
||||
.TP
|
||||
\fB\-\-ascii_bold\fR on/off
|
||||
Whether or not to bold the ascii logo.
|
||||
Executable
+3
@@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env bash
|
||||
cd /ws/Others/hyfetch
|
||||
python3 -m hyfetch --print-font-logo
|
||||
+8
-2
@@ -1,4 +1,10 @@
|
||||
from hyfetch import main
|
||||
import os
|
||||
|
||||
from .py import run_py
|
||||
from .rs import run_rust
|
||||
|
||||
if __name__ == '__main__':
|
||||
main.run()
|
||||
if os.environ.get('HYFETCH_PY', False):
|
||||
run_py()
|
||||
else:
|
||||
run_rust()
|
||||
|
||||
@@ -1 +1 @@
|
||||
VERSION = '1.4.9'
|
||||
VERSION = '2.0.2'
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import platform
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
@@ -28,6 +29,9 @@ TEST_ASCII_WIDTH = max(len(line) for line in TEST_ASCII.split('\n'))
|
||||
DEFAULT_DARK_L = 0.
|
||||
IS_WINDOWS = platform.system() == 'Windows'
|
||||
|
||||
CACHE_PATH = Path(os.getenv("LOCALAPPDATA") or os.getenv("XDG_CACHE_HOME") or Path.home() / '.cache') / 'hyfetch'
|
||||
|
||||
|
||||
@dataclass
|
||||
class GlobalConfig:
|
||||
# Global color mode default to 8-bit for compatibility
|
||||
@@ -46,6 +50,4 @@ class GlobalConfig:
|
||||
return 0.65 if term.lower() == 'dark' else 0.4
|
||||
|
||||
|
||||
GLOBAL_CFG = GlobalConfig(color_mode='8bit', override_distro=None, debug=False, is_light=False, use_overlay=False)
|
||||
|
||||
MINGIT_URL = 'https://github.com/git-for-windows/git/releases/download/v2.37.2.windows.2/MinGit-2.37.2.2-busybox-32-bit.zip'
|
||||
GLOBAL_CFG = GlobalConfig(color_mode='8bit', override_distro=None, debug=False, is_light=False, use_overlay=True)
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
{
|
||||
"Alma": "",
|
||||
"Alpine": "",
|
||||
"AOSC OS": "",
|
||||
"Apple": "",
|
||||
"macOS": "",
|
||||
"iOS": "",
|
||||
"Archcraft": "",
|
||||
"ArchLabs": "",
|
||||
"Arch": "",
|
||||
"Arco": "",
|
||||
"Arduino": "",
|
||||
"Artix": "",
|
||||
"Awesome WM": "",
|
||||
"Big": "",
|
||||
"bspwm": "",
|
||||
"Budgie": "",
|
||||
"CentOS": "",
|
||||
"Cinnamon": "",
|
||||
"Codeberg": "",
|
||||
"CoreOS": "",
|
||||
"Crystal": "",
|
||||
"Debian": "",
|
||||
"Deepin": "",
|
||||
"Devuan": "",
|
||||
"Docker": "",
|
||||
"dwm": "",
|
||||
"elementary OS": "",
|
||||
"Endeavour OS": "",
|
||||
"Enlightenment": "",
|
||||
"F-droid": "",
|
||||
"Fedora": "",
|
||||
"Fedora (inverse)": "",
|
||||
"Ferris": "",
|
||||
"Flathub": "",
|
||||
"Fluxbox": "",
|
||||
"Forgejo": "",
|
||||
"FOSDEM": "",
|
||||
"FreeBSD": "",
|
||||
"FreeCAD": "",
|
||||
"freedesktop.org": "",
|
||||
"Garuda": "",
|
||||
"Gentoo": "",
|
||||
"GIMP": "",
|
||||
"Gitea": "",
|
||||
"GNOME": "",
|
||||
"GNU Guix": "",
|
||||
"GTK": "",
|
||||
"Hyperbola -libre": "",
|
||||
"Hyprland": "",
|
||||
"i3": "",
|
||||
"illumos": "",
|
||||
"Inkscape": "",
|
||||
"JWM": "",
|
||||
"Kali": "",
|
||||
"KDE": "",
|
||||
"KDE Neon": "",
|
||||
"KDE Plasma": "",
|
||||
"Kdenlive": "",
|
||||
"KiCad": "",
|
||||
"Krita": "",
|
||||
"Kubuntu": "",
|
||||
"Kubuntu (inverse)": "",
|
||||
"Mint": "",
|
||||
"Mint (inverse)": "",
|
||||
"Loc-OS": "",
|
||||
"LXDE": "",
|
||||
"LXLE": "",
|
||||
"LXQt": "",
|
||||
"Mageia": "",
|
||||
"Mandriva": "",
|
||||
"Manjaro": "",
|
||||
"MATE": "",
|
||||
"mpv": "",
|
||||
"MX": "",
|
||||
"Neovim": "",
|
||||
"NixOS": "",
|
||||
"Octoprint": "",
|
||||
"OpenBSD": "",
|
||||
"OpenSCAD": "",
|
||||
"OpenSUSE": "",
|
||||
"OSH": "",
|
||||
"OSHWA": "",
|
||||
"OSI": "",
|
||||
"Parabola -libre": "",
|
||||
"Parrot OS": "",
|
||||
"Pop!_OS": "",
|
||||
"PostmarketOS": "",
|
||||
"Prusa Slicer": "",
|
||||
"Puppy": "",
|
||||
"Qt": "",
|
||||
"Qtile": "",
|
||||
"QubesOS": "",
|
||||
"Raspberry pi": "",
|
||||
"Red Hat": "",
|
||||
"RepRap": "",
|
||||
"RISC-V": "",
|
||||
"Rocky": "",
|
||||
"Sabayon": "",
|
||||
"Slackware": "",
|
||||
"Slackware (inverse)": "",
|
||||
"Snappy": "",
|
||||
"Solus": "",
|
||||
"Sway": "",
|
||||
"Tails": "",
|
||||
"Thunderbird": "",
|
||||
"Tor Browser": "",
|
||||
"Trisquel": "",
|
||||
"Tux": "",
|
||||
"Ubuntu": "",
|
||||
"Ubuntu (inverse)": "",
|
||||
"Vanilla OS": "",
|
||||
"Void": "",
|
||||
"VS Codium": "",
|
||||
"Wayland": "",
|
||||
"Wikimedia": "",
|
||||
"Xero": "",
|
||||
"XFCE": "",
|
||||
"Xmonad": "",
|
||||
"Xorg": "",
|
||||
"Zorin OS": "",
|
||||
"Windows": "\uE62A"
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
adelie = AsciiArt(match=r'''"Adélie"* | "Adelie"*''', color='4 7 6', ascii=r"""
|
||||
${c1} ${c3} ,-^-___
|
||||
${c3} /\\\///
|
||||
${c2}refined.${c1} /\\\\//
|
||||
${c2}reliable.${c1} /\\\///
|
||||
${c2}ready.${c1} /\\/////\
|
||||
__///\\\\/////\
|
||||
${c3} _//////\\\\\\\////
|
||||
${c1} ///////${c3}\\\\\\\\\\//
|
||||
//////${c1}\\\\\/
|
||||
/////\\\\\/
|
||||
/////${c3}\\\\/
|
||||
/\\///\\\/
|
||||
/\\\/${c1}\\/
|
||||
/\\\\//
|
||||
//////
|
||||
/// ${c3}\\\\\
|
||||
""")
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
aeros = AsciiArt(match=r'''"aerOS"*''', color='fg 0 0 0', ascii=r"""
|
||||
${c1}
|
||||
ooo OOO OOO ooo
|
||||
oOO OOo
|
||||
oOO OOo
|
||||
oOO OOo
|
||||
oOO OOo
|
||||
oOO OOo
|
||||
oOO OOo
|
||||
OOo
|
||||
OOo
|
||||
OOo
|
||||
OOo
|
||||
OOo
|
||||
OOo
|
||||
oOO OOo
|
||||
oOO OOo
|
||||
oOO OOo
|
||||
oOO OOo
|
||||
oO OOo
|
||||
oOO OOo
|
||||
oOO OOo
|
||||
ooo OOO OOO ooo
|
||||
""")
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
afterglow = AsciiArt(match=r'''"Afterglow"*''', color='5 1 3 4', ascii=r"""
|
||||
${c2} .
|
||||
${c1}. ${c2}.{!
|
||||
${c1}.L! ${c2}J@||*
|
||||
${c1}gJJJJL` ${c2}g@FFS"
|
||||
${c1},@FFFJF`${c2}_g@@LLP`
|
||||
${c1}_@FFFFF`${c2}_@@@@@P` ${c4}.
|
||||
${c1}J@@@LLF ${c2}_@@@@@P` ${c4}.J!
|
||||
${c1}g@@@@@" ${c2}_@@@@@P`${c3}. ${c4}.L|||*
|
||||
${c1}g@@@@M" ${c2}"VP`${c3}.L! ${c4}<@JJJJ`
|
||||
${c1}"@N" ${c3}:||||! ${c4}JFFFFS"
|
||||
${c3}.{JJ||F`${c4}_gFFFF@'
|
||||
${c3}.@FJJJF`${c4},@LFFFF`
|
||||
${c3}_@FFFFF ${c4}VLLLP`
|
||||
${c3}J@@LL@" ${c4}`"
|
||||
${c3}V@@"
|
||||
""")
|
||||
|
||||
+19
-22
@@ -2,26 +2,23 @@
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
aosc_os = AsciiArt(match=r'''"AOSC OS"*''', color='4 7 1', ascii=r"""
|
||||
${c2} .:+syhhhhys+:.
|
||||
.ohNMMMMMMMMMMMMMMNho.
|
||||
`+mMMMMMMMMMMmdmNMMMMMMMMm+`
|
||||
+NMMMMMMMMMMMM/ `./smMMMMMN+
|
||||
.mMMMMMMMMMMMMMMo -yMMMMMm.
|
||||
:NMMMMMMMMMMMMMMMs .hMMMMN:
|
||||
.NMMMMhmMMMMMMMMMMm+/- oMMMMN.
|
||||
dMMMMs ./ymMMMMMMMMMMNy. sMMMMd
|
||||
-MMMMN` oMMMMMMMMMMMN: `NMMMM-
|
||||
/MMMMh NMMMMMMMMMMMMm hMMMM/
|
||||
/MMMMh NMMMMMMMMMMMMm hMMMM/
|
||||
-MMMMN` :MMMMMMMMMMMMy. `NMMMM-
|
||||
dMMMMs .yNMMMMMMMMMMMNy/. sMMMMd
|
||||
.NMMMMo -/+sMMMMMMMMMMMmMMMMN.
|
||||
:NMMMMh. .MMMMMMMMMMMMMMMN:
|
||||
.mMMMMMy- NMMMMMMMMMMMMMm.
|
||||
+NMMMMMms/.` mMMMMMMMMMMMN+
|
||||
`+mMMMMMMMMNmddMMMMMMMMMMm+`
|
||||
.ohNMMMMMMMMMMMMMMNho.
|
||||
.:+syhhhhys+:.
|
||||
""")
|
||||
aosc_os = AsciiArt(match=r'''"AOSC OS"*''', color='4 0 1 3', ascii=r'''
|
||||
${c2} __
|
||||
${c2}gpBBBBBBBBBP
|
||||
${c2}_gBBBBBBBBBRP
|
||||
${c2}4BBBBBBBBRP ${c4},_____
|
||||
${c2}`"" ${c4}_g@@@@@@@@@@@@@%g>
|
||||
${c4}__@@@@@@@@@@@@@@@@P" ${c1}___
|
||||
${c4}_g@@@@@@@@@@@@@@@N"` ${c1}_gN@@@@@N^
|
||||
${c4}_w@@@@@@@@@@@@@@@@P" ${c1}_g@@@@@@@P"
|
||||
${c4}_g@@@@@@@@@@@@@@@N"` ${c1}VMNN@NNNM^`
|
||||
${c4}^MMM@@@@@@@@@@@MP" ${c3},ggppww__
|
||||
${c4}`""""" ${c3}_wNNNNNNNNNNNNNNNNNNN
|
||||
${c3}_gBNNNNNNNNNNNNNNNNNP"
|
||||
${c3}_wNNNNNNNNNNNNNNNNNNMP`
|
||||
${c3}_gBNNNNNNNNNNNNNNNNNP"
|
||||
${c3}_wNNNNNNNNNNNNNNNNNNNM^
|
||||
${c3}""Y^^MNNNNNNNNNNNNP`
|
||||
${c3}`"""""""
|
||||
''')
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
aosc_os_retro = AsciiArt(match=r'''"AOSC OS/Retro"*''', color='4 7 1 3', ascii=r"""
|
||||
${c2} .........
|
||||
...................
|
||||
.....................${c1}################${c2}
|
||||
.............. ....${c1}################${c2}
|
||||
.............. ...${c1}################${c2}
|
||||
............. ..${c1}****************${c2}
|
||||
............ . .${c1}****************${c2}
|
||||
........... ... ${c1}................${c2}
|
||||
.......... ..... ${c1}...............${c2}
|
||||
......... ....... ...
|
||||
.${c3}...... ${c2}.
|
||||
${c3}..... .....${c2}.... ${c4}...........
|
||||
${c3}.... ......${c2}. ${c4}...........
|
||||
${c3}... ....... ${c4}...........
|
||||
${c3}................ ${c4}***********
|
||||
${c3}................ ${c4}###########
|
||||
${c3}****************
|
||||
${c3}################
|
||||
""")
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
aoscosretro_small = AsciiArt(match=r'''"aoscosretro_small"''', color='4 7 1 3', ascii=r"""
|
||||
${c2} _____ ${c1}_____${c2}
|
||||
-' '-${c1}| |${c2}
|
||||
/ ___ ${c1}| |${c2}
|
||||
| / _ \${c1}|_____|${c2}
|
||||
' / /_\ \
|
||||
\ / _____ \${c4}___
|
||||
${c3}|${c2}/_/ ${c3}| ${c4}| |
|
||||
${c3}| | ${c4}|___|
|
||||
${c3}|_____|
|
||||
""")
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
arkane = AsciiArt(match=r'''"Arkane"*''', color='7 130 237', ascii=r"""
|
||||
${c3} .:..
|
||||
..:::......
|
||||
${c2}.${c3} .${c2}.${c3}.....
|
||||
${c2}+=${c3}...${c2}==${c3}....
|
||||
......:.${c1}:-${c2}:${c3}..${c1}+*${c2}=${c3}....
|
||||
${c2}:----::${c3}......
|
||||
${c2}.=***##*+=: ${c3}..
|
||||
${c2}=${c1}***######*${c2}=
|
||||
${c2}.${c1}-*######+
|
||||
${c2}:+${c1}###%%%###${c3}:
|
||||
${c2}-+*${c1}########+${c3}.
|
||||
${c2}=++*${c1}#######${c3}-
|
||||
${c2}-+=+**${c1}*####${c3}=
|
||||
${c3}.${c2}-=++==***${c1}##*${c1}-
|
||||
${c2}-++++++==++++=
|
||||
.-+++**+++=+===${c3}.
|
||||
${c2}:---===++++=-=--${c3}.
|
||||
${c2}-===============${c3}-==--:
|
||||
${c2}.-==+++***++*${c1}*#########${c3}=:::.
|
||||
${c2}.-=++++*++++**${c1}#######%%###${c3}=
|
||||
${c2}.:==++++++**${c1}#############${c3}:
|
||||
${c2}.${c3}-+*++*+++==${c1}###${c3}+
|
||||
-${c1}*+${c3}:
|
||||
""")
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
aster = AsciiArt(match=r'''"Aster"*''', color='6 6', ascii=r"""
|
||||
${c1} ...''...
|
||||
${c1} .;oOXWMWNXXXNMMN0d:.
|
||||
${c1} .oXMWOo;.. ..:oO;
|
||||
${c1} ;KMWx, co,
|
||||
${c1} 'KMNl dMMW.
|
||||
${c1} oMMx xMMMMk
|
||||
${c1} xMM: dMMMMMM;
|
||||
${c1} cMMl dMMMMMMMW
|
||||
${c1} NMK xMMMx::dXMx
|
||||
${c1} ,MMl xMMN' .o.
|
||||
${c1} cMM; dMMW'
|
||||
${c1} ;MMc oMMW,
|
||||
${c1} WMK dMMW, ccccccc.
|
||||
${c1} lMMl oMMM; ooooooo.
|
||||
${c1} OMMc ...
|
||||
${c1} xMMx
|
||||
${c1} ;XMN:
|
||||
${c1} ,.
|
||||
""")
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
athena = AsciiArt(match=r'''"Athena"*''', color='7 3', ascii=r"""
|
||||
${c1} . ..
|
||||
${c1} :####: ####.
|
||||
${c1} .################
|
||||
${c1} :##################
|
||||
${c1}.###################.
|
||||
${c1}######## #######
|
||||
${c1}####### ${c2}####${c1} #####
|
||||
${c1}:#######. ####
|
||||
${c1} ######### ${c2}#${c1} ## #
|
||||
${c1} ####### ${c2}##${c1} ####
|
||||
${c1}######## ${c2}####${c1} #######
|
||||
${c1}######## ${c2}#####${c1} ########
|
||||
${c1}######## ${c2}#######${c1} #######
|
||||
${c1} ####### ${c2}########${c1} #######
|
||||
${c1} ######## ${c2}#########${c1} ######
|
||||
${c1} ######## ${c2}#########${c1} #####
|
||||
${c1} ####### ${c2}#########${c1} ####
|
||||
${c1} ####### ${c2}#########${c1} ##
|
||||
${c1} ####### ${c2}########${c1} ##
|
||||
${c1} ###### ${c2}########${c1} #
|
||||
${c1} ### ${c2}#######${c1}
|
||||
${c1} ${c2}######${c1}
|
||||
${c1} ${c2}####${c1}
|
||||
${c1} ${c2}##${c1}
|
||||
""")
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
azos = AsciiArt(match=r'''"azos"*''', color='6 1', ascii=r"""
|
||||
${c1} ////. ${c2} (((((
|
||||
${c1} //////// ${c2} @((((((((
|
||||
${c1} //////// ${c2} @((((((((
|
||||
${c1} //////// /////// ${c2} ((((((( @((((((((
|
||||
${c1} //////// ///////// ${c2} ((((((((( @((((((((
|
||||
${c1} //////// ///////// ${c2} ((((((((( @((((((((
|
||||
${c1} //////// ///////// ////// ${c2} (((((( ((((((((( @((((((((
|
||||
${c1} //////// ///////// //////// ${c2} (((((((( ((((((((( @((((((((
|
||||
${c1} //////// ///////// //////// ${c2} (((((((( ((((((((( @((((((((
|
||||
${c1} //////// ///////// //////// ${c2} ((((((( ((((((((( @((((((((
|
||||
${c1} //////// ///////// /// ${c2} ( ((((((((( @((((((((
|
||||
${c1} //////// ///////// ${c2} ((((((((( @((((((((
|
||||
${c1} //////// ///////// ${c2} &(((((((( @((((((((
|
||||
${c1} //////// ////// ${c2} @(((( @((((((((
|
||||
${c1} //////// ${c2} @((((((((
|
||||
${c1} //////// ${c2} @((((((((
|
||||
${c1} ///// ${c2} (((((
|
||||
""")
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
bazzite = AsciiArt(match=r'''"Bazzite"*''', color='5 5', ascii=r"""
|
||||
${c1} %%%%%%====%%%%%%%%%%
|
||||
%%%%%%%% %%%%%%%%%%%%%%
|
||||
%%%%%%%%% %%%%%%%%%%%%%%%%
|
||||
%%%%%%%%% %%%%%%%%%%%%%%%###
|
||||
%%%%%%%%% %%%%%%%%%%%%%######
|
||||
== =======######
|
||||
== =========#####
|
||||
%%%%%%%%% %%%%%%%####======#####
|
||||
%%%%%%%%% %%%%%#######=====#####
|
||||
%%%%%%%%% %%%#########=====#####
|
||||
%%%%%%%%% %%##########=====#####
|
||||
%%%%%%%%%====###########=====######
|
||||
%%%%%%%%====#########======######
|
||||
%%%%%%%=====#####========######
|
||||
%%%%###===============#######
|
||||
%#######==========#########
|
||||
#######################
|
||||
###################
|
||||
###########
|
||||
""")
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
biglinux_large = AsciiArt(match=r'''"BigLinux_large"*''', color='2 3 4 7', ascii=r"""
|
||||
${c4}
|
||||
${c3}.cd0KXXX${c4}0${c3}x;
|
||||
${c3}.oXM${c4}M${c3}MMMMMMMMMWo
|
||||
${c2}... ${c3}dWMMMM${c4}M${c3}MMMMMMMMMMN,
|
||||
${c2}c0WMMMW0: ${c3}.XMMMM${c4}M${c3}MMMKdc;,;cxNMM:
|
||||
${c1}x, ${c2}.XMMMMMMMMM: ${c3}'W${c3}MMMMMMWo. ;KW.
|
||||
${c1}dM. ${c2}.WMMMMMMMM0 ${c3}N${c3}MMMM${c4}M${c3}Mk. dd
|
||||
${c1}.MM. ${c2}.lOKXKOl. ${c3}oMMMMMMd .l${c4}x${c3}kd: .
|
||||
${c1}kMM: .'.. ${c2}:xOOxc. ${c3}O${c4}M${c3}MMMM0 lXMMMMM${c4}M${c3}N;
|
||||
${c1}WMM0 lKMMMMMW0o. ${c2}KMMMMMMN. ${c3}xMM${c4}M${c3}M, .dWMMMMMMMMMM;
|
||||
${c1}.MMMMx .oWMMMMMMOl0MMX; ${c2}NMMMMMMM; ${c3}.NMMMM. .dWMMMM${c4}M${c3}MMMMMMMN
|
||||
${c1}.MMMMMNOKMMMMMMMk. 'MMMMx ${c2};MMMMMMMO ${c3}.KMMMl .oWMMMMMWk:,lWMMMM.
|
||||
${c1}xMMMMMMMMMMMMk. .MMMMMc ${c2}'XMMMMMMx ${c3}:0MMNMMMM${c4}M${c3}MWx. .WM${c4}M${c3}M.
|
||||
${c1}0MMMMMMMMWx. :MMMMMK ${c2}cKMMMMMX: ${c3},ok0K0x:. oMMN
|
||||
${c1}oNMMMM0c. .NMMMMMO ${c2}.lOWMMMX: ${c3}.M${c4}M${c3}o
|
||||
${c1}c. .'. .KMMMMMM: ${c2}.';clc. ${c3}MN
|
||||
${c1}:N; cWMMMMMMO ${c3}.W;
|
||||
${c1}0M0: 'dNMMMMMMM0 ${c3}',
|
||||
${c1}0MMMX0O0XMMMMMMMMMMo
|
||||
${c1}oWMMMMMMMMMMMMMMk.
|
||||
${c1}.oXMMMMMMMMW0c.
|
||||
${c1}.;ccc:,.
|
||||
""")
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
blackmesa = AsciiArt(match=r'''"BlackMesa"''', color='1', ascii=r"""
|
||||
${c1}
|
||||
.-;+$XHHHHHHX$+;-.
|
||||
,;X@@X%/;=----=:/%X@@X/,
|
||||
=$@@%=. .=+H@X:
|
||||
-XMX: =XMX=
|
||||
/@@: =H@+
|
||||
%@X, .$@$
|
||||
+@X. $@%
|
||||
-@@, .@@=
|
||||
%@% +@$
|
||||
H@: :@H
|
||||
H@: :HHHHHHHHHHHHHHHHHHX, =@H
|
||||
%@% ;@M@@@@@@@@@@@@@@@@@H- +@$
|
||||
=@@, :@@@@@@@@@@@@@@@@@@@@@= .@@:
|
||||
+@X :@@@@@@@@@@@@@@@M@@@@@@:%@%
|
||||
$@$, ;@@@@@@@@@@@@@@@@@M@@@@@@$.
|
||||
+@@HHHHHHH@@@@@@@@@@@@@@@@@@@@@@@+
|
||||
=X@@@@@@@@@@@@@@@@@@@@@@@@@@@@X=
|
||||
:$@@@@@@@@@@@@@@@@@@@M@@@@$:
|
||||
,;$@@@@@@@@@@@@@@@@@@X/-
|
||||
.-;+$XXHHHHHX$+;-.
|
||||
""")
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
chimera = AsciiArt(match=r'''"Chimera"*''', color='1 5 4 1', ascii=r"""
|
||||
${c3}ddddddddddddddc ${c1},cc:
|
||||
${c3}ddddddddddddddc ${c1},cc:
|
||||
${c3}ddddddddddddddd ${c1},cc:
|
||||
${c3}ddddddddddddl:' ${c1},cc:
|
||||
${c3}dddddddddl' ${c1}..;cc:
|
||||
${c3}dddddddo. ${c1},:cccccc:
|
||||
${c3}ddddddl ${c1},ccc:'''''
|
||||
${c3}dddddo. ${c1};ccc. ............
|
||||
.ccc. cccccccccccc
|
||||
${c2}...... ${c1}.ccc. .ccc'''''''''
|
||||
${c2}OOOOOk. ${c1};ccc. .ccc; ......
|
||||
${c2}OOOOOOd ${c1}'ccc:,....,:ccc' ${c4}coooooo
|
||||
${c2}OOOOOOOx. ${c1}':cccccccc:' ${c4}.looooooo
|
||||
${c2}OOOOOOOOOd, ${c1}`'''` ${c4}.coooooooo
|
||||
${c2}OOOOOOOOOOOOdc,. ${c4}..,coooooooooooo
|
||||
${c2}OOOOOOOOOOOOOOOO' ${c4}.oooooooooooooooo
|
||||
${c2}OOOOOOOOOOOOOOOO' ${c4}.oooooooooooooooo
|
||||
${c2}OOOOOOOOOOOOOOOO' ${c4}.oooooooooooooooo
|
||||
""")
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
container_linux_by_coreos = AsciiArt(match=r'''"Container Linux by CoreOS"* | "Container_Linux"*''', color='4 7 1', ascii=r"""
|
||||
container_linux_by_coreos = AsciiArt(match=r'''"Container Linux by CoreOS"* | "Container_Linux"* | "Fedora CoreOS" | "CoreOS"*''', color='4 7 1', ascii=r"""
|
||||
${c1} .....
|
||||
.';:cccccccc:;'.
|
||||
':ccccclc${c3}lllllllll${c1}cc:.
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
debian = AsciiArt(match=r'''"Debian"*''', color='1 7 3', ascii=r"""
|
||||
debian = AsciiArt(match=r'''"Debian"*''', color='1 7 3', ascii=r'''
|
||||
${c2} _,met$$$$$gg.
|
||||
,g$$$$$$$$$$$$$$$P.
|
||||
,g$$P" "\""Y$$.".
|
||||
,g$$P" """Y$$.".
|
||||
,$$P' `$$$.
|
||||
',$$P ,ggs. `$$b:
|
||||
`d$$' ,$P"' ${c1}.${c2} $$$
|
||||
@@ -19,6 +19,6 @@ ${c2} `Y$$
|
||||
`$$b.
|
||||
`Y$$b.
|
||||
`"Y$b._
|
||||
`"\""
|
||||
""")
|
||||
`"""
|
||||
''')
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
digital_unix = AsciiArt(match=r'''"digital UNIX"*''', color='1 6 7', ascii=r"""
|
||||
${c1} +-+-+-+-+-+-+-+
|
||||
|${c3}d${c1}|${c3}i${c1}|${c3}g${c1}|${c3}i${c1}|${c3}t${c1}|${c3}a${c1}|${c3}l${c1}|
|
||||
+-+-+-+-+-+-+-+
|
||||
${c2} _ _ _ _ _______ __
|
||||
| | | | \ | |_ _\ \ / /
|
||||
| | | | \| | | | \ V /
|
||||
| | | | . ` | | | > <
|
||||
| |__| | |\ |_| |_ / . \
|
||||
\____/|_| \_|_____/_/ \_\
|
||||
""")
|
||||
|
||||
@@ -8,6 +8,10 @@ def detect(name: str) -> AsciiArt | None:
|
||||
if not name:
|
||||
return None
|
||||
name = name.lower()
|
||||
if name.startswith('adélie') or name.startswith('adelie'):
|
||||
from .adelie import adelie
|
||||
return adelie
|
||||
|
||||
if name.startswith('aix'):
|
||||
from .aix import aix
|
||||
return aix
|
||||
@@ -88,13 +92,9 @@ def detect(name: str) -> AsciiArt | None:
|
||||
from .antix import antix
|
||||
return antix
|
||||
|
||||
if name.startswith('aosc os/retro'):
|
||||
from .aosc_os_retro import aosc_os_retro
|
||||
return aosc_os_retro
|
||||
|
||||
if name == 'aoscosretro_small':
|
||||
from .aoscosretro_small import aoscosretro_small
|
||||
return aoscosretro_small
|
||||
if name.startswith('afterglow'):
|
||||
from .afterglow import afterglow
|
||||
return afterglow
|
||||
|
||||
if name.startswith('aosc os'):
|
||||
from .aosc_os import aosc_os
|
||||
@@ -124,6 +124,10 @@ def detect(name: str) -> AsciiArt | None:
|
||||
from .arcolinux import arcolinux
|
||||
return arcolinux
|
||||
|
||||
if name.startswith('arkane'):
|
||||
from .arkane import arkane
|
||||
return arkane
|
||||
|
||||
if name == 'arch_small':
|
||||
from .arch_small import arch_small
|
||||
return arch_small
|
||||
@@ -160,10 +164,18 @@ def detect(name: str) -> AsciiArt | None:
|
||||
from .archmerge import archmerge
|
||||
return archmerge
|
||||
|
||||
if name.startswith('aeros'):
|
||||
from .aeros import aeros
|
||||
return aeros
|
||||
|
||||
if name.startswith('arch'):
|
||||
from .arch import arch
|
||||
return arch
|
||||
|
||||
if name.startswith('unicodearch'):
|
||||
from .unicodearch import unicodearch
|
||||
return unicodearch
|
||||
|
||||
if name.startswith('artix_small'):
|
||||
from .artix_small import artix_small
|
||||
return artix_small
|
||||
@@ -184,14 +196,26 @@ def detect(name: str) -> AsciiArt | None:
|
||||
from .asteroidos import asteroidos
|
||||
return asteroidos
|
||||
|
||||
if name.startswith('aster'):
|
||||
from .aster import aster
|
||||
return aster
|
||||
if name.startswith('athena'):
|
||||
from .athena import athena
|
||||
return athena
|
||||
|
||||
if name.startswith('azos'):
|
||||
from .azos import azos
|
||||
return azos
|
||||
|
||||
if name.startswith('bedrock'):
|
||||
from .bedrock import bedrock
|
||||
return bedrock
|
||||
|
||||
if name.startswith('bazzite'):
|
||||
from .bazzite import bazzite
|
||||
return bazzite
|
||||
|
||||
if name.startswith('biglinux_large'):
|
||||
from .biglinux_large import biglinux_large
|
||||
return biglinux_large
|
||||
|
||||
if name.startswith('biglinux'):
|
||||
from .biglinux import biglinux
|
||||
return biglinux
|
||||
@@ -204,6 +228,10 @@ def detect(name: str) -> AsciiArt | None:
|
||||
from .blackarch import blackarch
|
||||
return blackarch
|
||||
|
||||
if name == 'blackmesa':
|
||||
from .blackmesa import blackmesa
|
||||
return blackmesa
|
||||
|
||||
if name.startswith('blackpanther') or name.startswith('blackpanther'):
|
||||
from .blackpanther import blackpanther
|
||||
return blackpanther
|
||||
@@ -292,6 +320,10 @@ def detect(name: str) -> AsciiArt | None:
|
||||
from .chapeau import chapeau
|
||||
return chapeau
|
||||
|
||||
if name.startswith('chimera'):
|
||||
from .chimera import chimera
|
||||
return chimera
|
||||
|
||||
if name.startswith('chonkysealos'):
|
||||
from .chonkysealos import chonkysealos
|
||||
return chonkysealos
|
||||
@@ -324,7 +356,7 @@ def detect(name: str) -> AsciiArt | None:
|
||||
from .condres import condres
|
||||
return condres
|
||||
|
||||
if name.startswith('container linux by coreos') or name.startswith('container_linux'):
|
||||
if name.startswith('container linux by coreos') or name.startswith('container_linux') or name == 'fedora coreos' or name.startswith('coreos'):
|
||||
from .container_linux_by_coreos import container_linux_by_coreos
|
||||
return container_linux_by_coreos
|
||||
|
||||
@@ -368,6 +400,10 @@ def detect(name: str) -> AsciiArt | None:
|
||||
from .debian import debian
|
||||
return debian
|
||||
|
||||
if name.startswith('digital unix'):
|
||||
from .digital_unix import digital_unix
|
||||
return digital_unix
|
||||
|
||||
if name.startswith('droidian'):
|
||||
from .droidian import droidian
|
||||
return droidian
|
||||
@@ -376,6 +412,10 @@ def detect(name: str) -> AsciiArt | None:
|
||||
from .deepin import deepin
|
||||
return deepin
|
||||
|
||||
if name.startswith('openkylin'):
|
||||
from .openkylin import openkylin
|
||||
return openkylin
|
||||
|
||||
if name == 'desaos':
|
||||
from .desaos import desaos
|
||||
return desaos
|
||||
@@ -428,6 +468,10 @@ def detect(name: str) -> AsciiArt | None:
|
||||
from .elive import elive
|
||||
return elive
|
||||
|
||||
if name.startswith('endeavouros_small'):
|
||||
from .endeavouros_small import endeavouros_small
|
||||
return endeavouros_small
|
||||
|
||||
if name.startswith('endeavouros'):
|
||||
from .endeavouros import endeavouros
|
||||
return endeavouros
|
||||
@@ -448,6 +492,14 @@ def detect(name: str) -> AsciiArt | None:
|
||||
from .eurolinux import eurolinux
|
||||
return eurolinux
|
||||
|
||||
if name.startswith('evolutionos'):
|
||||
from .evolutionos import evolutionos
|
||||
return evolutionos
|
||||
|
||||
if name.startswith('eweos'):
|
||||
from .eweos import eweos
|
||||
return eweos
|
||||
|
||||
if name.startswith('exherbo'):
|
||||
from .exherbo import exherbo
|
||||
return exherbo
|
||||
@@ -460,6 +512,22 @@ def detect(name: str) -> AsciiArt | None:
|
||||
from .fedora_old import fedora_old
|
||||
return fedora_old
|
||||
|
||||
if name == 'fedora_unicode':
|
||||
from .fedora_unicode import fedora_unicode
|
||||
return fedora_unicode
|
||||
|
||||
if name == 'fedora silverblue' or name.startswith('silverblue'):
|
||||
from .fedora_silverblue import fedora_silverblue
|
||||
return fedora_silverblue
|
||||
|
||||
if name.startswith('fedora kinoite') or name.startswith('kinoite'):
|
||||
from .fedora_kinoite import fedora_kinoite
|
||||
return fedora_kinoite
|
||||
|
||||
if name.startswith('fedora sericea') or name.startswith('sericea'):
|
||||
from .fedora_sericea import fedora_sericea
|
||||
return fedora_sericea
|
||||
|
||||
if name.startswith('fedora'):
|
||||
from .fedora import fedora
|
||||
return fedora
|
||||
@@ -476,6 +544,10 @@ def detect(name: str) -> AsciiArt | None:
|
||||
from .finnix import finnix
|
||||
return finnix
|
||||
|
||||
if name.startswith('furreto'):
|
||||
from .furreto import furreto
|
||||
return furreto
|
||||
|
||||
if name == 'freebsd_small':
|
||||
from .freebsd_small import freebsd_small
|
||||
return freebsd_small
|
||||
@@ -592,6 +664,14 @@ def detect(name: str) -> AsciiArt | None:
|
||||
from .iglunix import iglunix
|
||||
return iglunix
|
||||
|
||||
if name.startswith('interix'):
|
||||
from .interix import interix
|
||||
return interix
|
||||
|
||||
if name.startswith('gloire'):
|
||||
from .gloire import gloire
|
||||
return gloire
|
||||
|
||||
if name.startswith('januslinux') or name.startswith('janus') or name.startswith('ataraxia linux') or name.startswith('ataraxia'):
|
||||
from .januslinux import januslinux
|
||||
return januslinux
|
||||
@@ -636,6 +716,10 @@ def detect(name: str) -> AsciiArt | None:
|
||||
from .kubuntu import kubuntu
|
||||
return kubuntu
|
||||
|
||||
if name.startswith('lainos'):
|
||||
from .lainos import lainos
|
||||
return lainos
|
||||
|
||||
if name.startswith('lede'):
|
||||
from .lede import lede
|
||||
return lede
|
||||
@@ -660,6 +744,14 @@ def detect(name: str) -> AsciiArt | None:
|
||||
from .linux import linux
|
||||
return linux
|
||||
|
||||
if name == 'linuxfromscratch' or name.endswith('lfs') or name == 'linux-from-scratch' or name == 'linux_from_scratch':
|
||||
from .linuxfromscratch import linuxfromscratch
|
||||
return linuxfromscratch
|
||||
|
||||
if name == 'linux_small':
|
||||
from .linux_small import linux_small
|
||||
return linux_small
|
||||
|
||||
if name.startswith('linuxlite_small'):
|
||||
from .linuxlite_small import linuxlite_small
|
||||
return linuxlite_small
|
||||
@@ -680,6 +772,10 @@ def detect(name: str) -> AsciiArt | None:
|
||||
from .lunar import lunar
|
||||
return lunar
|
||||
|
||||
if name.startswith('macaronios') or name.startswith('macaroni os'):
|
||||
from .macaronios import macaronios
|
||||
return macaronios
|
||||
|
||||
if name == 'mac"*"_small':
|
||||
from .mac_small import mac_small
|
||||
return mac_small
|
||||
@@ -696,10 +792,22 @@ def detect(name: str) -> AsciiArt | None:
|
||||
from .mageia import mageia
|
||||
return mageia
|
||||
|
||||
if name.startswith('magix'):
|
||||
from .magix import magix
|
||||
return magix
|
||||
|
||||
if name.startswith('magpieos'):
|
||||
from .magpieos import magpieos
|
||||
return magpieos
|
||||
|
||||
if name.startswith('mainsailos_small'):
|
||||
from .mainsailos_small import mainsailos_small
|
||||
return mainsailos_small
|
||||
|
||||
if name.startswith('mainsailos'):
|
||||
from .mainsailos import mainsailos
|
||||
return mainsailos
|
||||
|
||||
if name.startswith('mandriva') or name.startswith('mandrake'):
|
||||
from .mandriva import mandriva
|
||||
return mandriva
|
||||
@@ -724,6 +832,14 @@ def detect(name: str) -> AsciiArt | None:
|
||||
from .maui import maui
|
||||
return maui
|
||||
|
||||
if name.startswith('mauna'):
|
||||
from .mauna import mauna
|
||||
return mauna
|
||||
|
||||
if name.startswith('meowix'):
|
||||
from .meowix import meowix
|
||||
return meowix
|
||||
|
||||
if name.startswith('mer'):
|
||||
from .mer import mer
|
||||
return mer
|
||||
@@ -800,6 +916,10 @@ def detect(name: str) -> AsciiArt | None:
|
||||
from .nixos_old import nixos_old
|
||||
return nixos_old
|
||||
|
||||
if name.startswith('nixos_colorful'):
|
||||
from .nixos_colorful import nixos_colorful
|
||||
return nixos_colorful
|
||||
|
||||
if name.startswith('nixos'):
|
||||
from .nixos import nixos
|
||||
return nixos
|
||||
@@ -860,9 +980,9 @@ def detect(name: str) -> AsciiArt | None:
|
||||
from .openstage import openstage
|
||||
return openstage
|
||||
|
||||
if name.startswith('openwrt'):
|
||||
from .openwrt import openwrt
|
||||
return openwrt
|
||||
if (name.startswith('wrt') or name.endswith('wrt')):
|
||||
from .wrt import wrt
|
||||
return wrt
|
||||
|
||||
if name.startswith('open source media center') or name == 'osmc':
|
||||
from .open_source_media_center import open_source_media_center
|
||||
@@ -892,6 +1012,10 @@ def detect(name: str) -> AsciiArt | None:
|
||||
from .pacbsd import pacbsd
|
||||
return pacbsd
|
||||
|
||||
if name.startswith('panwah'):
|
||||
from .panwah import panwah
|
||||
return panwah
|
||||
|
||||
if name.startswith('parabola_small'):
|
||||
from .parabola_small import parabola_small
|
||||
return parabola_small
|
||||
@@ -940,6 +1064,10 @@ def detect(name: str) -> AsciiArt | None:
|
||||
from .pikaos import pikaos
|
||||
return pikaos
|
||||
|
||||
if name.startswith('phyos'):
|
||||
from .phyos import phyos
|
||||
return phyos
|
||||
|
||||
if name.startswith('pnm linux') or name.startswith('whpnm linux'):
|
||||
from .pnm_linux import pnm_linux
|
||||
return pnm_linux
|
||||
@@ -984,6 +1112,10 @@ def detect(name: str) -> AsciiArt | None:
|
||||
from .pureos import pureos
|
||||
return pureos
|
||||
|
||||
if name.startswith('peropesis'):
|
||||
from .peropesis import peropesis
|
||||
return peropesis
|
||||
|
||||
if name.startswith('q4os'):
|
||||
from .q4os import q4os
|
||||
return q4os
|
||||
@@ -1052,6 +1184,10 @@ def detect(name: str) -> AsciiArt | None:
|
||||
from .rhaymos import rhaymos
|
||||
return rhaymos
|
||||
|
||||
if name.startswith('rhino linux'):
|
||||
from .rhino_linux import rhino_linux
|
||||
return rhino_linux
|
||||
|
||||
if name.startswith('rocky_small'):
|
||||
from .rocky_small import rocky_small
|
||||
return rocky_small
|
||||
@@ -1096,6 +1232,10 @@ def detect(name: str) -> AsciiArt | None:
|
||||
from .salient_os import salient_os
|
||||
return salient_os
|
||||
|
||||
if name.startswith('salix'):
|
||||
from .salix import salix
|
||||
return salix
|
||||
|
||||
if name.startswith('scientific'):
|
||||
from .scientific import scientific
|
||||
return scientific
|
||||
@@ -1116,6 +1256,10 @@ def detect(name: str) -> AsciiArt | None:
|
||||
from .siduction import siduction
|
||||
return siduction
|
||||
|
||||
if name.startswith('slackel'):
|
||||
from .slackel import slackel
|
||||
return slackel
|
||||
|
||||
if name.startswith('slackware_small'):
|
||||
from .slackware_small import slackware_small
|
||||
return slackware_small
|
||||
@@ -1176,6 +1320,10 @@ def detect(name: str) -> AsciiArt | None:
|
||||
from .t2 import t2
|
||||
return t2
|
||||
|
||||
if name.startswith('opensuse tumbleweed-slowroll') or name.startswith('opensuse_slowroll'):
|
||||
from .opensuse_tumbleweed_slowroll import opensuse_tumbleweed_slowroll
|
||||
return opensuse_tumbleweed_slowroll
|
||||
|
||||
if name.startswith('opensuse tumbleweed') or name.startswith('opensuse_tumbleweed'):
|
||||
from .opensuse_tumbleweed import opensuse_tumbleweed
|
||||
return opensuse_tumbleweed
|
||||
@@ -1288,6 +1436,10 @@ def detect(name: str) -> AsciiArt | None:
|
||||
from .urukos import urukos
|
||||
return urukos
|
||||
|
||||
if name.startswith('venom_small'):
|
||||
from .venom_small import venom_small
|
||||
return venom_small
|
||||
|
||||
if name.startswith('venom'):
|
||||
from .venom import venom
|
||||
return venom
|
||||
@@ -1336,10 +1488,18 @@ def detect(name: str) -> AsciiArt | None:
|
||||
from .windows_10 import windows_10
|
||||
return windows_10
|
||||
|
||||
if name == 'windows95':
|
||||
from .windows95 import windows95
|
||||
return windows95
|
||||
|
||||
if name.startswith('windows'):
|
||||
from .windows import windows
|
||||
return windows
|
||||
|
||||
if name.startswith('xray_os'):
|
||||
from .xray_os import xray_os
|
||||
return xray_os
|
||||
|
||||
if name.startswith('xubuntu'):
|
||||
from .xubuntu import xubuntu
|
||||
return xubuntu
|
||||
@@ -1356,6 +1516,18 @@ def detect(name: str) -> AsciiArt | None:
|
||||
from .irix import irix
|
||||
return irix
|
||||
|
||||
if name.startswith('xenia2'):
|
||||
from .xenia2 import xenia2
|
||||
return xenia2
|
||||
|
||||
if name.startswith('xenia'):
|
||||
from .xenia import xenia
|
||||
return xenia
|
||||
|
||||
if name.startswith('tatra'):
|
||||
from .tatra import tatra
|
||||
return tatra
|
||||
|
||||
if name.startswith('zorin'):
|
||||
from .zorin import zorin
|
||||
return zorin
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
endeavouros_small = AsciiArt(match=r'''"endeavouros_small"*''', color='1 5 4', ascii=r"""
|
||||
${c1} /${c2}o${c3}.
|
||||
${c1} :${c2}sssso${c3}-
|
||||
${c1} :${c2}ossssssso${c3}:
|
||||
${c1} /${c2}ssssssssssso${c3}+
|
||||
${c1} -+${c2}ssssssssssssssso${c3}+
|
||||
${c1} //${c2}osssssssssssssso${c3}+-
|
||||
`+++++++++++++++-`
|
||||
""")
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
evolutionos = AsciiArt(match=r'''"EvolutionOS"*''', color='4 7', ascii=r"""
|
||||
${c1}\e[1;32m dddddddddddddddddddddddd
|
||||
.dddd''''''''''''''''''''''dddd.
|
||||
dd: dddddddddddddddddddd; dd:
|
||||
dd: ldl:'''''''''''''''' dd:
|
||||
dd: ldl: dd:
|
||||
dd: ldl: dd:
|
||||
dd: ldl: dd:
|
||||
dd: ldl: dd:
|
||||
dd: ldl: ddddddd; ddddd; dd:
|
||||
dd: ldl: ''''''' ''''' dd:
|
||||
dd: ldl: dd:
|
||||
dd: ldl: dd:
|
||||
dd: ldl: dd:
|
||||
dd: ldl: dd:
|
||||
dd: ldl: ddddddddddddddd; dd:
|
||||
dddd:.''' ''''''''''''''' dddd:
|
||||
dddddddddddddddddddddddddd;;'
|
||||
'''''''''''''''''''''''''\e[0m
|
||||
""")
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
eweos = AsciiArt(match=r'''"eweOS"*''', color='7 11 9 8 1', ascii=r"""
|
||||
${c2} #####%%%
|
||||
${c2} ##%%${c3}////${c2}%%%%%${c3}///
|
||||
${c2} #%%%%${c3}////((((////${c2}%
|
||||
${c1} *@@@@@@@${c3}/${c5},,,${c3}/////${c5},,,${c2}%${c1}@@@@@@@
|
||||
${c1} .@@@@@@@@@@@${c3}////////${c2}%%%${c1}@@@@@@@@@@@@
|
||||
${c1} @@@${c4}...${c1}@@@@@@${c3}////${c2}%%${c3}////${c1}@@@@@@@@@@@@@@@@
|
||||
${c1} @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
||||
${c1} @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
||||
${c1} @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
||||
${c1} @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
||||
${c1} @@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
||||
${c1} @@@@@@@@@@@@@@@@@@@@@@@@@@@
|
||||
${c1} @@@@@@@@@@@@@@@@@@@@@@@
|
||||
${c1} @@@@@@ @@@@@@
|
||||
${c1} @@@ @@@
|
||||
""")
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
fedora_kinoite = AsciiArt(match=r'''"Fedora Kinoite"* | "Kinoite"*''', color='12 7', ascii=r"""
|
||||
${c1} ,clll:.${c2} .,::::::::::::'
|
||||
${c1}:ooooooo${c2} .;::::::::::::::
|
||||
${c1}looooooo${c2} ,:::::::::::::::'
|
||||
${c1}looooooo${c2} .::::::::::::::::
|
||||
${c1}looooooo${c2} ;:::::::::::::::.
|
||||
${c1}looooooo${c2} .::::::::::::::::
|
||||
${c1}looooool${c2};;;;,::::::::::::::::
|
||||
${c1}looool${c2}::, .::::::::::::::
|
||||
${c1}looooc${c2}:: ;::
|
||||
${c1}looooc${c2}::;. .::;
|
||||
${c1}loooool${c2}:::::::::::.
|
||||
${c1}looooooo${c2}. .::::::'
|
||||
${c1}looooooo${c2} .::::::,;,..
|
||||
${c1}looooooo${c2} :::;' ';:;.
|
||||
${c1}looooooo${c2} ::: :::
|
||||
${c1}cooooooo${c2} .::' '::.
|
||||
${c1}.ooooc ${c2} ::, ,::
|
||||
''''
|
||||
""")
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
fedora_sericea = AsciiArt(match=r'''"Fedora Sericea"* | "Sericea"*''', color='12 7', ascii=r"""
|
||||
${c1} :oooo, .','
|
||||
.';;;.;oooooooolooooo'
|
||||
coooooooooooooooooooooooolc'
|
||||
.':oooooooooooo${c2}ll${c1}ooooooooooooool
|
||||
.oooooooooooooooo${c2}ll${c1}oooooooooooo${c2}l${c1}ool
|
||||
ooooooooooooooooo${c2}ll${c1}ooooooooooo${c2}ll${c1}oo'
|
||||
oooo${c2}l${c1}oooooooooo${c2}lll${c1}ooooooooo${c2}lll${c1}oo
|
||||
.ooooo${c2}lll${c1}ooooo${c2}lll${c1}ooooooooo${c2}lll${c1}ool
|
||||
.ooooooo${c2}lll${c1}oo${c2}llll${c1}oooo${c2}lllll${c1}ooooo:
|
||||
'oooooooo${c2}llllllllllll${c1}oooooooo'
|
||||
.c,.oo${c2}lllll${c1}oooooooo.${c2}
|
||||
'll;
|
||||
'll.
|
||||
lll
|
||||
lll
|
||||
;ll,
|
||||
.l:
|
||||
""")
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
fedora_silverblue = AsciiArt(match=r'''"Fedora Silverblue" | "Silverblue"*''', color='4 7 12', ascii=r"""
|
||||
${c1} .;ooooooooooooooooooooooooooo.
|
||||
${c1} ,dddddddddddddddddddddddddddddd'${c3};
|
||||
${c1} lddddddddddddddddddddddddddddd'${c3};;;
|
||||
${c1}ddddd${c2},XXX.${c1}ddddd${c2},XXX.${c1}dddd'${c2},XXX.${c3};;;;;
|
||||
${c1}ddddd${c2}XX${c1}x${c2}XX${c1}ddddd${c2}XX${c1}x${c2}XX${c1}ddd'${c2},XX${c3}x${c2}XX${c3};;;;;
|
||||
${c1}ddddd${c2}'XXX'${c1}ddddd${c2}'XXX'${c1}dd'${c2}XXXXXX'${c3};;;;;
|
||||
${c1}dddddd${c2};X;${c1}ddddddd${c2};X:${c1}d'${c2}XXX${c3};;;;;;;;;;;
|
||||
${c1}dddddd${c2};X;${c1}ddddddd${c2};X:${c2}XXX${c3};;;;;;;;;;;;;
|
||||
${c1}dddddd${c2};X;${c1}dddddd'${c2};XXX,,,,,,XXX.${c3};;;;;
|
||||
${c1}dddddd${c2};X;${c1}dddd'${c2}XXXX${c2}XXXXXXXXX${c3}x${c2}XX${c3};;;;;
|
||||
${c1}dddddd${c2};X;${c1}dd'${c2}XXX${c3};;;;;;;;;;;${c2}XXX${c3};;;;;;
|
||||
${c1}dddddd${c2};X;${c1}'${c2}XXX${c3};;;;;;;;;;;;;;;;;;;;;;
|
||||
${c1}dddddd${c2};XXXXX,,,,,,,,,,,,,;XXX:${c3};;;;;
|
||||
${c1}dddddd${c2}:XXXXXXXXXXXXXXXXXXXX${c3}x${c2}XX${c3};;;;;
|
||||
${c1}ddddd'${c3};;;;;;;;;;;;;;;;;;;${c2}'XXX'${c3};;;;'
|
||||
${c1}ddd'${c3};;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
${c1}o'${c3};;;;;;;;;;;;;;;;;;;;;;;;;;;;'
|
||||
""")
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
fedora_unicode = AsciiArt(match=r'''"Fedora_unicode"''', color='12 7', ascii=r"""
|
||||
${c1} ▄████████████████████▄
|
||||
▄████████████████████████▄
|
||||
▄████████████████████████████▄
|
||||
▄███████████████${c2} ${c1}█████████▄
|
||||
▄████████████████${c2} ${c1}██████████▄
|
||||
████████████████${c2} ${c1}████${c2} ${c1}██████████
|
||||
████████████████${c2} ${c1}████${c2} ${c1}██████████
|
||||
████████████████${c2} ${c1}██████████████████
|
||||
█████████${c2} ${c1}▀█${c2} ${c1}██████████████
|
||||
███████${c2} ${c1}█${c2} ${c1}██████████████
|
||||
██████${c2} ${c1}██████${c2} ${c1}██████████████████
|
||||
██████${c2} ${c1}███████${c2} ${c1}██████████████████
|
||||
██████${c2} ${c1}███${c2} ${c1}███████████████████
|
||||
███████${c2} ${c1}██████████████████▀
|
||||
█████████${c2} ${c1}██████████████████▀
|
||||
████████████████████████████████▀
|
||||
▀█████████████████████████████▀
|
||||
▀█████████████████████████▀
|
||||
""")
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
furreto = AsciiArt(match=r'''"Furreto"*''', color='211 255 225 199', ascii=r"""
|
||||
${c1}
|
||||
${c1}.xOOko .odd,
|
||||
o${c3}X${c2}WWK${c3}O${c1}OOO. 'O${c3}N${c2}WW${c3}0${c1}kkk.
|
||||
.k0${c3}XKO${c1}OOOOOcOO${c2}NWN${c1}OOOOO.
|
||||
xOOOOOOOOOkkOOOOOOOOO;
|
||||
.O0OkkocxO000000kcdk0OO0OOkx
|
||||
k${c3}W${c2}MX${c1}kkkkloxkkkx; :dxxxxddc...
|
||||
'kO0OOOOOkc .cl:..kk0KK0Okc
|
||||
;kOOO0000xd. dO00000Oo .xkO${c3}N${c2}MM${c3}X${c1}OOOO
|
||||
.dddxkOOOkddc.k${c3}K${c2}NWW${c3}N${c1}000000l.ddk${c2}00${c1}00OOOO.
|
||||
'dd:;ddddd;.d${c3}K${c2}MMM${c3}W${c1}K00KKK0O::ddxkO00Oko
|
||||
.okxkOKK0kkOO00KKOxxlodddddddl
|
||||
.00OOkkkkkkkkOOO00OOOO0O; .dddl
|
||||
'kkkkkxxkkkkkkkOOkxdxkxxddd.
|
||||
cddddddddxxkkkkk${c4}xddddddddddo
|
||||
'ddddddodddddddddddddddddddc
|
||||
.ddddddodddddddddodddddddc
|
||||
.odddo.
|
||||
|
||||
.kOOkkk;
|
||||
lkKWNkkkxc
|
||||
kkxkkkkkkx.
|
||||
,,..xxx.
|
||||
""")
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
gloire = AsciiArt(match=r'''"Gloire"*''', color='5 7 0', ascii=r"""
|
||||
${c3}
|
||||
&#BGPPPPPG#&
|
||||
B5?77!!?YJJ7!7YBB&
|
||||
&G5YJ77!7JYYYYYBPJ&PY#
|
||||
#PYYYYYY?!?YYYYY7?7JP5JJ
|
||||
B?YYYYYY7!!7JYYYYJ!!?JJJ5
|
||||
&& B7?J?77?7!!!!!77777!7Y5YYBBPGGG&
|
||||
G77?YBB!!!!!!!!!!!!!JYJ??7JYJJY# PYPPG&
|
||||
J777JB?!7JJ???!!!7?JYYYYYPJ!7JB
|
||||
GYYG #JJJJJ??7!!!JYYY5PGB&GB&
|
||||
#Y!?GB5YYJY5PG###&
|
||||
GJJP
|
||||
""")
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
haiku = AsciiArt(match=r'''"Haiku"*''', color='1 3 7 2', ascii=r"""
|
||||
haiku = AsciiArt(match=r'''"Haiku"*''', color='1 3 7 2', ascii=r'''
|
||||
${c3}
|
||||
|
||||
MMMM MMMM
|
||||
@@ -16,6 +16,6 @@ ${c3} MMMM${c4} .cOMMMMM|/MMMMM/`
|
||||
MM${c4}MMMMMMM/`:MMM/ ${c3}MMMM
|
||||
MMMM MMMM
|
||||
MMMM MMMM
|
||||
"\"\"" "\"\""
|
||||
""")
|
||||
"""" """"
|
||||
''')
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
interix = AsciiArt(match=r'''"Interix"*''', color='1 7 4 0 3', ascii=r"""
|
||||
${c1} .${c3}.
|
||||
${c1} 75${c3}G!
|
||||
${c1} ^?PG${c3}&&J.
|
||||
${c1} :!5GPP${c3}&&&B!
|
||||
${c1} :YPPPPP${c3}&&&&&Y:
|
||||
${c1} !5PPPPPP${c3}&&&&&&B!
|
||||
${c1} :?PPPPPPPP${c3}&&&&&&&&Y~
|
||||
${c1} !5PPPPPPPPP${c3}###&&&&&&B7
|
||||
${c1} :?PPPP5555555${c3}B####&&&&&&5:
|
||||
${c1} ~5PPPP555YJ${c5}7!~7?${c3}5B###&&&&&B?.
|
||||
${c1} .:JPPPP5555Y${c5}?^....:^?${c3}G####&&&&&5:
|
||||
${c1} 75PPP555555Y${c5}7:....:^!${c3}5#####&&&&&B7.
|
||||
${c1} :JPPPP${c2}555555YY?${c5}~::::^~${c2}7YPGBB###${c3}&&&&&5^
|
||||
${c1}75${c2}GGPPPPPP555555YJ?77??YYYYYY55PPGGB#${c3}&B?
|
||||
${c2}~!!7JY5PGGBBBBBBBBGGGGGGGBGGGGGP5YJ?7~~~
|
||||
.::^~7?JYPGBB#BGPYJ?7!7^:.
|
||||
..:^...
|
||||
""")
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
ironclad = AsciiArt(match=r'''"Ironclad"*''', color='5 7 0', ascii=r"""
|
||||
${c3}
|
||||
&#BGPPPPPG#&
|
||||
B5?77!!?YJJ7!7YBB&
|
||||
&G5YJ77!7JYYYYYBPJ&PY#
|
||||
#PYYYYYY?!?YYYYY7?7JP5JJ
|
||||
B?YYYYYY7!!7JYYYYJ!!?JJJ5
|
||||
&& B7?J?77?7!!!!!77777!7Y5YYBBPGGG&
|
||||
G77?YBB!!!!!!!!!!!!!JYJ??7JYJJY# PYPPG&
|
||||
J777JB?!7JJ???!!!7?JYYYYYPJ!7JB
|
||||
GYYG #JJJJJ??7!!!JYYY5PGB&GB&
|
||||
#Y!?GB5YYJY5PG###&
|
||||
GJJP
|
||||
""")
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
lainos = AsciiArt(match=r'''"LainOS"*''', color='4 14 7 2 3 5', ascii=r"""
|
||||
${c2} /==\
|
||||
\==/
|
||||
${c1} · · · · · · ·
|
||||
· · · · · · · · · ·
|
||||
· · · ${c2}.-======-.${c1}· · · ·
|
||||
${c2} .::.${c1} ·${c2}.-============-.${c1}· ${c2}.::.
|
||||
.:==:${c1}· ${c2}.:===:'${c1}. ·· .${c2}':===:.${c1} ·${c2}:==:.
|
||||
.:===:${c1} · ${c2}:===.${c1} · ${c3}.--.${c1} · ${c2}.===:${c1} · ${c2}:===:.
|
||||
:===:${c1}· · ${c2}:===.${c1} · ${c3}.:====:.${c1} · ${c2}.===:${c1} · ·${c2}:===:
|
||||
(===:${c1}· · ${c2}:===-${c1} · ${c3}:======:${c1} · ${c2}-===:${c1} · ·${c2}:===)
|
||||
:===:${c1}· · ${c2}:===.${c1} · ${c3}':====:'${c1} · ${c2}.===:${c1} · ·${c2}:===:
|
||||
':===:${c1} · ${c2}:===.${c1} · ${c3}'--'${c1} · ${c2}.===:${c1} · ${c2}:===:'
|
||||
':==:${c1}· ${c2}':===:.${c1}' ·· '${c2}.:===:'${c1} ·${c2}:==:'
|
||||
'::'${c1} · ${c2}'===-. .-==='${c1} · ${c2}'::'
|
||||
${c2}/==\${c1} · · · ${c2}:=== ===:${c1} · · · ${c2}/==\
|
||||
\==/${c1} · · ·${c2}:===${c1} ·${c2}===:${c1}· · · ${c2}\==/${c2}
|
||||
.-. ${c1}· ${c2}:===${c1}· ${c2}===:${c1} ·${c2} ${c2}.-.
|
||||
.===. .=== ===. .===.
|
||||
.======== ========.
|
||||
''''' '''''
|
||||
""")
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
linux_small = AsciiArt(match=r'''"Linux_small"''', color='fg 8 3', ascii=r"""
|
||||
${c2} ___
|
||||
${c2} (${c1}.. ${c2}|
|
||||
${c2} (${c3}<> ${c2}|
|
||||
${c2} / ${c1}__ ${c2}\
|
||||
${c2} ( ${c1}/ \ ${c2}/|
|
||||
${c3}_${c2}/\ ${c1}__)${c2}/${c3}_${c2})
|
||||
${c3}\/${c2}-____${c3}\/
|
||||
""")
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
linuxfromscratch = AsciiArt(match=r'''"LinuxFromScratch" | *"LFS" | "linux-from-scratch" | "linux_from_scratch"''', color='fg 8 3', ascii=r"""
|
||||
${c2} .:@:.
|
||||
${c2} :@@@@@@@:
|
||||
${c2} @@@@@@@@@-
|
||||
${c2} .:%. @@@@@@@@@+. @%
|
||||
${c2} *@@@%+: :@@@@@@@%=: .=%@@@@@@=
|
||||
${c2} :@@@@@@##@@@@@@@@@%*+%@%+@@@@@@@+
|
||||
${c2} @@#${c1}####${c2}+@@@@@@@%:${c1}######${c2}=@@@@@@@@@-
|
||||
${c2} *@%${c1}######${c2}.@@@@@#${c1}#########${c2}-@@@@@@@@#.
|
||||
${c2} %@-${c1}#${c2}.@${c1}=${c2}:${c1}##${c2}+@@@@-${c1}###${c2}%@${c1}:${c2}=${c1}###${c2}*@#*+=-+#:
|
||||
${c2} @@.${c1}#${c2}@@*${c1}=${c2}:${c1}#${c2}-%%**-${c1}##${c2}%@@%${c1}*${c2}*${c1}###${c2}#=-
|
||||
${c2} @@-${c1}#${c2}@@@@+.-${c3}...${c2}:=.${c1}#${c2}%@@@@%${c1}###${c2}#-
|
||||
${c2} %@%${c1}##${c2}*#:${c3}.o.....o...${c2}-%@+${c1}###${c2}#@+ -:
|
||||
${c2} +@@*${c1}#${c3}....................${c2}+@@@@@@@@+
|
||||
${c2} @%:${c3}....................._:${c2}@@@@@@@=.
|
||||
${c2} .=:${c3}...............__*-=`.${c2}=@@@@@@#=.
|
||||
${c2} :+:${c3}....:==*__*-=`:..==-:${c2}#@@@@@%+:
|
||||
${c2} .--=-: ${c3}+..::.....-: ${c2}=%@*=:
|
||||
${c2} :........-
|
||||
${c2} .:...--.
|
||||
""")
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
macaronios = AsciiArt(match=r'''"MacaroniOS"* | "Macaroni OS"*''', color='2 3 15 14', ascii=r"""
|
||||
${c2}
|
||||
-=+++==--::.. .-+++==-:.
|
||||
.:--:-=++==-:. :=*+=--==+***######**+-:
|
||||
.---:-===-----===+++==-:.. :=+=--=+*****+++*****#%%%#-
|
||||
.=*********+++========+++++=--:. .:-=+++++++=-:.. .=*=::.
|
||||
:-=-. .:::---===+++++++++++*******++====+**+++=-:. :+*-..
|
||||
.. -++ ..:--==+***********=:. -*=
|
||||
. :+. . ${c3}...${c2} .:--===:. .++
|
||||
.*: . ${c3}:+#%%@@%%#=: ${c2}--
|
||||
${c2}-= ${c3}-#@@@@@@@@@@@@#: ${c2}.
|
||||
${c3}:*%@%%@@@@@@@@@@@%+ .:--====-:.
|
||||
:*%%%%%%%%%@@@@@@@@@*. :=*#%%%%@@@@@%#+-
|
||||
.*%%%%%%%%%%%%%@@#+--=- -*%%%%%%%%%%%@@@@@%#=
|
||||
-#%%%%%%%%%%%%%#: :+: :+%*#%%%%%%%%%%%%%%%%%*.
|
||||
+%%%%%%%%%%%%%%: .#*: *+-*%%%%%%%%%%%%%%%%%+
|
||||
+%%%%%%%%%%%%%# . . . :%%%%%%%%%%%%%%%%%#.
|
||||
=#%%%%%%%%%%%%# . . =%%%%%%%%%%%%%%%%%*.
|
||||
.*%%%%%%%%%%%%%* : =%%%%%%%%%%%%%%%%%#-
|
||||
:#%%%%%%%%%%%%%#=.... .=*%%%%%%%%%%%%%%%%%%*:
|
||||
:*%@@%%%%%%%%%%%%#+. :+#%%%%%%%%%%%%%#*-
|
||||
=*%%@@%%%%%%%#*- .-=+**##**+=:
|
||||
:=*######+=:
|
||||
""")
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
magix = AsciiArt(match=r'''"Magix"*''', color='206 39', ascii=r"""
|
||||
${c2} @
|
||||
@@--=====@@
|
||||
@@--==@@ @@====+@
|
||||
@-@@ @==@
|
||||
@=@
|
||||
@=@${c1} @=@ @-==== @=@${c2}
|
||||
@=@${c1} @-===@==++@===+@${c2}
|
||||
@=@${c1} @--====@@=====+@${c2}
|
||||
-=@${c1} @--==========++@${c2}
|
||||
==${c1} @--==========++@${c2} @=@
|
||||
@==${c1} @--=======@==++@${c2} @=+@
|
||||
@==${c1} @-==========++${c2} @=@
|
||||
@==${c1} @-=======@=%${c2} @=@
|
||||
@==${c1} @@@@@@${c2} @=@
|
||||
@====@@@ @@===+%
|
||||
@@=====@@==++++@@
|
||||
=#@=@
|
||||
@==@++@
|
||||
@@@
|
||||
""")
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
mainsailos = AsciiArt(match=r'''"MainsailOS"*''', color='1', ascii=r"""
|
||||
${c1} -
|
||||
*%:
|
||||
:%%%#
|
||||
=%%%%%-
|
||||
*%%%%%%#
|
||||
:#%%%%%%%#.
|
||||
-%%%%%%%%+
|
||||
*%%%%%%%%- :
|
||||
.#%%%%%%%#. *%=
|
||||
-%%%%%%%%+ :#%%%*
|
||||
+%%%%%%%%- =%%%%%%#.
|
||||
.#%%%%%%%#. *%%%%%%%%:
|
||||
-%%%%%%%%* :#%%%%%%%#.
|
||||
+%%%%%%%%- =%%%%%%%%+ :%*.
|
||||
.#%%%%%%%#: *%%%%%%%%- +%%%%*:
|
||||
:%%%%%%%%* :#%%%%%%%#. .*%%%%%%%*
|
||||
+%%%%%%%%= -%%%%%%%%+ :%%%%%%%%*
|
||||
.#%%%%%%%%: *%%%%%%%%- =%%%%%%%%=
|
||||
""")
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
mainsailos_small = AsciiArt(match=r'''"MainsailOS_small"*''', color='1', ascii=r"""
|
||||
${c1} -:
|
||||
+%*
|
||||
.#%%+
|
||||
-%%%: +=
|
||||
+%%#..#%%-
|
||||
.#%%+ -%%%- +=
|
||||
-%%%- +%%#..#%%+
|
||||
""")
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
mauna = AsciiArt(match=r'''"Mauna"*''', color='4 6', ascii=r"""
|
||||
${c1} .. :-=++++=-:
|
||||
.-+*+ -********* **=
|
||||
=***= +******+ =---=+*.
|
||||
+**** +****+ :-=++*++=--
|
||||
=****= **** :+***********+:
|
||||
+****+ *** ${c2}.-- ${c1}+******-
|
||||
=*****: *- ${c2}:+=: ${c1}=*****:
|
||||
${c2}. ${c1}+*****: : ${c2}-+++ ${c1}:****=
|
||||
${c2}-+ ${c1}:*****+ ${c2}- ++++ ${c1}:***-
|
||||
${c2}-++=: ${c1}=+****: ${c2}:++ +++++ ${c1}**+
|
||||
${c2} +++++= ${c1}-====-${c2}++++: +++++ ${c1}*+
|
||||
${c2} .=++++++++++++++: ${c2}+++++= ${c1}.
|
||||
${c2} .=+++++++++= :=+++++=
|
||||
.:::--- -+++++++-
|
||||
:-==++==-.
|
||||
""")
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
meowix = AsciiArt(match=r'''"Meowix"*''', color='1 3 3 4', ascii=r"""
|
||||
${c1} #${c2}% ${c3}&${c4}*
|
||||
${c1} ##${c2}%% ${c3}&&${c4}**
|
||||
${c1} ## ${c2}%% ${c3}&& ${c4}**
|
||||
${c1} ## ${c2}%% ${c3}&& ${c4}**
|
||||
${c1} ## ${c2}%% ${c3}&& ${c4}**
|
||||
${c1} ## ${c2}%% ${c3}&& ${c4}**
|
||||
${c1} ## ${c2}%%${c3}&& ${c4}**
|
||||
${c1} ## ${c2}%% ${c4}**
|
||||
${c1} ## ${c4}**
|
||||
${c1}## ${c4}**
|
||||
""")
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
nixos_colorful = AsciiArt(match=r'''"nixos_colorful"*''', color='4 6 4 6 4 6', ascii=r"""
|
||||
${c1} ▗▄▄▄ ${c2}▗▄▄▄▄ ▄▄▄▖
|
||||
${c1} ▜███▙ ${c2}▜███▙ ▟███▛
|
||||
${c1} ▜███▙ ${c2}▜███▙▟███▛
|
||||
${c1} ▜███▙ ${c2}▜██████▛
|
||||
${c1} ▟█████████████████▙ ${c2}▜████▛ ${c3}▟▙
|
||||
${c1} ▟███████████████████▙ ${c2}▜███▙ ${c3}▟██▙
|
||||
${c6} ▄▄▄▄▖ ${c2}▜███▙ ${c3}▟███▛
|
||||
${c6} ▟███▛ ${c2}▜██▛ ${c3}▟███▛
|
||||
${c6} ▟███▛ ${c2}▜▛ ${c3}▟███▛
|
||||
${c6}▟███████████▛ ${c3}▟██████████▙
|
||||
${c6}▜██████████▛ ${c3}▟███████████▛
|
||||
${c6} ▟███▛ ${c5}▟▙ ${c3}▟███▛
|
||||
${c6} ▟███▛ ${c5}▟██▙ ${c3}▟███▛
|
||||
${c6} ▟███▛ ${c5}▜███▙ ${c3}▝▀▀▀▀
|
||||
${c6} ▜██▛ ${c5}▜███▙ ${c4}▜██████████████████▛
|
||||
${c6} ▜▛ ${c5}▟████▙ ${c4}▜████████████████▛
|
||||
${c5} ▟██████▙ ${c4}▜███▙
|
||||
${c5} ▟███▛▜███▙ ${c4}▜███▙
|
||||
${c5} ▟███▛ ▜███▙ ${c4}▜███▙
|
||||
${c5} ▝▀▀▀ ▀▀▀▀▘ ${c4}▀▀▀▘
|
||||
""")
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
from . import AsciiArt
|
||||
|
||||
nixos_small = AsciiArt(match=r'''"nixos_small"''', color='4 6', ascii=r"""
|
||||
${c1} \\ \\ //
|
||||
${c1} \\ \\ //
|
||||
==\\__\\/ //
|
||||
// \\//
|
||||
==// //==
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
openkylin = AsciiArt(match=r'''"openKylin"*''', color='2 7', ascii=r"""
|
||||
${c1}
|
||||
/KKK]
|
||||
KKKKKKK` ]KKKK\
|
||||
KKKKK/ /KKKKKKKKK\
|
||||
KKKK/ ,KKKKKKKKKKKK^
|
||||
,]KKK =KKK` /KKKKKKOOOOOO`
|
||||
,KKKKKK =KK /` [\OOOOOOO\
|
||||
\KKKKK =K ,OOOOOOO`
|
||||
,KKKKK =^ \OOOOOO
|
||||
,KKKK ^ OOOOOO^
|
||||
*KKK^ =OOOOO^
|
||||
OOKK^ OOOOOO^
|
||||
\OOOK\ /OOOOOO`
|
||||
OOOOOO] ,OOOOOOO^
|
||||
,OOOOOOOO\] ,[OOOOOOOOO/
|
||||
\OOOOOOOOOOOOOOOOOOOOO`
|
||||
[OOOOOOOOOOOOOOOO/`
|
||||
,[OOOOOOOOO]
|
||||
""")
|
||||
|
||||
@@ -3,21 +3,23 @@
|
||||
from . import AsciiArt
|
||||
|
||||
opensuse_leap = AsciiArt(match=r'''"openSUSE Leap"* | "openSUSE_Leap"*''', color='2 7', ascii=r"""
|
||||
${c2} `-++:`
|
||||
./oooooo/-
|
||||
`:oooooooooooo:.
|
||||
-+oooooooooooooooo+-`
|
||||
./oooooooooooooooooooooo/-
|
||||
:oooooooooooooooooooooooooo:
|
||||
` `-+oooooooooooooooooooo/- `
|
||||
`:oo/- .:ooooooooooooooo+:` `-+oo/.
|
||||
`/oooooo:. -/oooooooooo/. ./oooooo/.
|
||||
`:+ooooo+-` `:+oooo+- `:oooooo+:`
|
||||
.:oooooo/. .::` -+oooooo/.
|
||||
-/oooooo:. ./oooooo+-
|
||||
`:+ooooo+-:+oooooo:`
|
||||
./oooooooooo/.
|
||||
-/oooo+:`
|
||||
`:/.
|
||||
${c2} ====
|
||||
======
|
||||
==== ====+
|
||||
+==== +====
|
||||
+===+ ====
|
||||
==== ====
|
||||
+=== +====
|
||||
==== +====
|
||||
===== ====
|
||||
+===+ =====
|
||||
==+ ===== +===+ ===
|
||||
==== ==== ===== =====
|
||||
==== ======= ====
|
||||
==== === ====
|
||||
====+ ====
|
||||
==== =====
|
||||
======
|
||||
==
|
||||
""")
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
opensuse_slowroll = AsciiArt(match=r'''"openSUSE Slowroll"* | "openSUSE_Slowroll"*''', color='2 7', ascii=r"""
|
||||
${c2} _aaaymQQmwaaa,
|
||||
,wWQQQD????????$QQQQa,.
|
||||
_wQQB?" ??QQQa,
|
||||
sQQD^ ?QQ6\
|
||||
yWW' 4QQg
|
||||
,QQD .aaaaaaaa ^4Q6
|
||||
,mQP _wWQW?????YWWQa, 4Qm
|
||||
jQ@ wWW?' ^4QQc ^$QL
|
||||
,QQ' jWW' )QW\ ]QQ
|
||||
|QQ ,QW' ]QQ ^QQ|
|
||||
|QQ |QQ ]QQ QQ|
|
||||
|QQ 4Qg ]QQ .QQ|
|
||||
'QQ6 '$WQac. _QQ( jQQ
|
||||
]QQw "?QWQQf _mQP ,QQ(
|
||||
4QQga wQQP ,mQ?
|
||||
4QQQga, saQWP' jQQf
|
||||
?QQQQQQwaaaaaaaayWWW?' _mQ@'
|
||||
?WQQQP?9VWUV???^ _amQP^
|
||||
"4QQQaa, ,awQQQ?^
|
||||
"?VQQQQQQQQQQQQQQP?'
|
||||
""")
|
||||
|
||||
@@ -3,18 +3,27 @@
|
||||
from . import AsciiArt
|
||||
|
||||
opensuse_tumbleweed = AsciiArt(match=r'''"openSUSE Tumbleweed"* | "openSUSE_Tumbleweed"*''', color='2 7', ascii=r"""
|
||||
${c2} ......
|
||||
.,cdxxxoc,. .:kKMMMNWMMMNk:.
|
||||
cKMMN0OOOKWMMXo. ; ;0MWk:. .:OMMk.
|
||||
;WMK;. .lKMMNM, :NMK, .OMW;
|
||||
cMW; 'WMMMN ,XMK, oMM'
|
||||
.MMc ..;l. xMN: KM0
|
||||
'MM. 'NMO oMM
|
||||
.MM, .kMMl xMN
|
||||
KM0 .kMM0. .dl:,.. .WMd
|
||||
.XM0. ,OMMK, OMMMK. .XMK
|
||||
oWMO:. .;xNMMk, NNNMKl. .xWMx
|
||||
:ONMMNXMMMKx; . ,xNMWKkxllox0NMWk,
|
||||
..... .:dOOXXKOxl,
|
||||
${c2} JJJJJJJJ
|
||||
JJJJJJJJJJJJJJ
|
||||
JJJJJJ =JJJJJJJ
|
||||
JJJJ =JJJ JJJJ
|
||||
JJJ =JJJ JJJ
|
||||
JJJJ =JJJ JJJ
|
||||
JJJJJJJJJJJJJJJ JJJJ
|
||||
JJJJJJJJJJJJJJ JJJJ
|
||||
JJJJ JJJJ
|
||||
JJJJJ= JJJJ
|
||||
JJJJJJJJJJJJJJJJJJJJJJJJJJJJJ=
|
||||
=JJJJJJJJJJJJJJJJJJJJJJJJJJJJJ
|
||||
JJJJ =JJJJJJ
|
||||
JJJJ =JJJJ
|
||||
JJJJ JJJJJJJJJJJJJJ
|
||||
JJJJ JJJJJJJJJJJJJJJ
|
||||
JJJJ JJJJ JJJJ
|
||||
JJJ JJJJ JJJ
|
||||
JJJJJ JJJJ JJJJ
|
||||
=JJJJJJJJ JJJJJJ
|
||||
JJJJJJJJJJJJJJ
|
||||
JJJJJJJ=
|
||||
""")
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
opensuse_tumbleweed_slowroll = AsciiArt(match=r'''"openSUSE Tumbleweed-Slowroll"* | "openSUSE_Slowroll"*''', color='2 7', ascii=r"""
|
||||
${c2} _aaaymQQmwaaa,
|
||||
,wWQQQD????????$QQQQa,.
|
||||
_wQQB?" ??QQQa,
|
||||
sQQD^ ?QQ6\
|
||||
yWW' 4QQg
|
||||
,QQD .aaaaaaaa ^4Q6
|
||||
,mQP _wWQW?????YWWQa, 4Qm
|
||||
jQ@ wWW?' ^4QQc ^$QL
|
||||
,QQ' jWW' )QW\ ]QQ
|
||||
|QQ ,QW' ]QQ ^QQ|
|
||||
|QQ |QQ ]QQ QQ|
|
||||
|QQ 4Qg ]QQ .QQ|
|
||||
'QQ6 '$WQac. _QQ( jQQ
|
||||
]QQw "?QWQQf _mQP ,QQ(
|
||||
4QQga wQQP ,mQ?
|
||||
4QQQga, saQWP' jQQf
|
||||
?QQQQQQwaaaaaaaayWWW?' _mQ@'
|
||||
?WQQQP?9VWUV???^ _amQP^
|
||||
"4QQQaa, ,awQQQ?^
|
||||
"?VQQQQQQQQQQQQQQP?'
|
||||
""")
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
panwah = AsciiArt(match=r'''"Panwah"*''', color='7 1 0', ascii=r"""
|
||||
${c1}
|
||||
HHH
|
||||
HAAAH HHH
|
||||
HAAAAH HAAAH
|
||||
HAAAAAAH HAAAAH
|
||||
HAAAAAAH HAAAAAH
|
||||
HAAAAAAAAH${c2}WWWWWWWWWWWWWWWW ${c1}HAAAAAH$
|
||||
HAAAAAAAAH${c2}WWWWWWWWWWWWWWWWWWWW${c1} HAAAAAH
|
||||
HAA${c2}WWWWWWWWWWWWWWWWWWWWWWWWWWWWW${c1}AAAAAH${c2}
|
||||
WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW${c1}WAH${c2}
|
||||
WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
|
||||
WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
|
||||
WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
|
||||
WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
|
||||
WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
|
||||
WWWWWWW${c1}AAA${c2}WWWW WWWWWWWWWWWWWWWWWWWWWWWWWWW
|
||||
WWWW${c1}AAA${c2}WWWWW WWWWWWW WWWWWWWWWWWWWWW
|
||||
WW${c1}AAA${c2}WWWWWWWWWWWWWWWWW WWWWW${c1}AAA${c2}WWWWWWWW
|
||||
${c1}AAA${c2}WWWWW${c1}OOOOOOOOOOO${C2}WWWWWWWWWWW${c1}AAA${c2}WWWWWW
|
||||
${c1}OOOO${c3}GGGGGGG${c1}OOOO${c2}WWWWWWWWWW${c1}AAA${c2}WWWW
|
||||
${c1}OOO${c3}GGGGGGG${c1}OOO${c2}WWWWWWWWWWWW${c1}AAA${c2}W
|
||||
${c1}OOOOOOOOO
|
||||
""")
|
||||
|
||||
+26
-30
@@ -2,35 +2,31 @@
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
parch = AsciiArt(match=r'''"parch"* | "Parch"* | "PARCH"*''', color='4 6', ascii=r"""
|
||||
|
||||
${c1} ,#/*%*
|
||||
${c1} #. ..,..,*,,
|
||||
${c1} ,/,,... ,. (/ ...
|
||||
${c1} ,/,........ .,. ./(/%/ .* #*
|
||||
${c1} .**,..... ...,%&. .,
|
||||
${c1} ,%,.... ., ,
|
||||
${c1} ,&,... .,, &. .
|
||||
${c1} (%,... ..,& *.
|
||||
${c1} *&*..... &,,,,,,,#& ..,&/ *. /
|
||||
${c1} *&*,..... &***%&&**,& ...,&* / /
|
||||
${c1} *&,.... &,**,,,**,# ..,&/ .
|
||||
${c1} (/,... &***%%%(, ..,%( #
|
||||
${c1} %*... #,,,% ..*% . *
|
||||
${c1} %,.. .,% . /
|
||||
${c1} %,. ..,,. .%
|
||||
${c1} /,. ${c1} ..# .%
|
||||
${c1} .,. ${c2} @@@@@# ${c1} ./ ./.
|
||||
${c1} ,.. ${c2} #&%.%%@ ${c1} .#%&*
|
||||
${c1} .,.. ${c2} @//(*(@, ${c1} ..
|
||||
${c1} ,.. ${c2} #@ /@@, ${c1}
|
||||
${c1} ... ${c2} &@ @@@ ${c1}
|
||||
${c1} ,,. ${c2} (# .@@#, ${c1} ,
|
||||
${c1} /,.. ${c2} *****@% #****/ ${c1} .
|
||||
${c1} ((*....${c2} /***% %*** ${c1} .,.*
|
||||
${c1} /&&&**,.., ${c2}* **,*,,. ${c1} ...,(&%*
|
||||
${c1} %&&&#*(**,,,,,,,,,,,,,,,*//(&&&&#
|
||||
${c1} /, .,....... .,,***/(/,,/
|
||||
${c1} ./*/#*,,***,,***///(#%%*.
|
||||
parch = AsciiArt(match=r'''"parch"* | "Parch"* | "PARCH"*''', color='4 7 1', ascii=r"""
|
||||
${c1} ,:lodddd.
|
||||
.:clooood.
|
||||
;clllooooc
|
||||
;cclllllloo
|
||||
.cccccllllll
|
||||
. ,cccclllll
|
||||
':::;; ccccclll;
|
||||
.:::cccccccccccll;
|
||||
;::::ccccllllllcll:
|
||||
.;::::cccclllloool::;
|
||||
;;;::::cccclllolc::::;.
|
||||
;;;::::cccclllccc:::::;.
|
||||
;;;::::cccclccccc::::::;.
|
||||
;;;;::::::llcccccc:::::'
|
||||
;;;;:; ,clllccccccc::
|
||||
.;; .cllllllcccccc::;::::'
|
||||
.'''''''''',:lddoooolll
|
||||
'.....'''',cdddooooollll
|
||||
........':oddddoooolllllc
|
||||
....';ldddddooooolllllc:
|
||||
,cdddddddooooollllccc
|
||||
:ddddddoooolllllccc
|
||||
;ddooooolllllcc.
|
||||
:ooollllc.
|
||||
c'
|
||||
""")
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
peropesis = AsciiArt(match=r'''"Peropesis"*''', color='4 7 1', ascii=r"""
|
||||
${c1}#### #### #### ### #### #### #### # ####
|
||||
# # # # # # # # # # # # #
|
||||
#### ### #### # # #### ### # # #
|
||||
# # # # # # # # # # #
|
||||
# #### # # ### # #### #### # ####
|
||||
""")
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
phyos = AsciiArt(match=r'''"phyOS"*''', color='33 33 7 1', ascii=r"""
|
||||
${c1}.^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^.^^^^^.
|
||||
:777777777777777777777777777777^~7777:
|
||||
.~~~~~~~~~~~~~~~~~~~~~^~7777!:!777!.
|
||||
~7!!!!!!!!!!!!!!!!!^:!777~^!777~
|
||||
^77777!!!!!!!!!7!^^7777^^7777^
|
||||
^7777~.~~~~^. .~7777^~7777:
|
||||
:!777~^!777~. !777!:~777!:
|
||||
.!777!:~777!:~77~:!777!.
|
||||
~777!^~7777:^~^!777~
|
||||
^7777^^7777^^7777^
|
||||
:7777~^!7777777:
|
||||
.!777!:!7777!.
|
||||
.~777!:~77~.
|
||||
~7777^~~
|
||||
^7777.
|
||||
:77:
|
||||
..
|
||||
""")
|
||||
|
||||
@@ -3,13 +3,34 @@
|
||||
from . import AsciiArt
|
||||
|
||||
pikaos = AsciiArt(match=r'''"PikaOS"*''', color='11', ascii=r"""
|
||||
${c1} /🐦🐦🐦$ /🐦/🐦 /🐦🐦🐦 /🐦🐦🐦
|
||||
| 🐦__ $|__| 🐦 /🐦__ 🐦/🐦__ 🐦
|
||||
| 🐦 \ 🐦/$| 🐦 /🐦 /🐦🐦🐦| 🐦 \ $| 🐦 \__/
|
||||
| 🐦🐦🐦$| $| 🐦 /🐦/|____ $| 🐦 | $| 🐦🐦🐦
|
||||
| 🐦____/| $| 🐦🐦🐦/ /🐦🐦🐦| 🐦 | 🐦\____ 🐦
|
||||
| 🐦 | $| 🐦_ 🐦 /🐦__ $| 🐦 | 🐦/🐦 \ 🐦
|
||||
| 🐦 | $| 🐦 \ $| 🐦🐦🐦| 🐦🐦🐦| 🐦🐦🐦/
|
||||
|__/ |__|__/ \__/\_______/\______/ \______/ .
|
||||
${c1}
|
||||
'',,, ,,,d,
|
||||
',, ,,'
|
||||
', ,.
|
||||
., '
|
||||
. .
|
||||
' .
|
||||
.. oddddkdlc:;,.. ..
|
||||
. ............lllc, .
|
||||
. ....................: .
|
||||
. . ....................
|
||||
'. ..........'o........d0XX0.
|
||||
....lllllllcOOOcllllll............cxlxc...;okkkx.
|
||||
..................................';lc'...lo.
|
||||
.'''''''''''''.....................,;,.......
|
||||
',,,,,,,,,,,,,,,,''...............dkkkd......
|
||||
',,,,,,,,,,,,,,,,,,,'............;okkkd;....
|
||||
.,,,,,,,,,,,,,,,,,,,,,............;cll;.....
|
||||
,,,,,,,,,,,,,,,,,,,,'....................:d,
|
||||
,,,,,,,,,,,,,,,,,,,....................oxxx:
|
||||
.,,,,,,,,,,,,,,,,,'..................oxxxxx. .
|
||||
.,,,,,,,,,,,,,,'.......... ,oxxxxxxx .
|
||||
.;,,,,,,,,,,,,'.. 'cxxxxxxxxx,
|
||||
:dl:,'',,'.... .;lxxxxxxxxxd;
|
||||
,codol:;'. ...,;cldxxxxxxxxxoc.
|
||||
.:cxxxxxdlccccc:ccldxxxxxxxxxxxxxx::.
|
||||
.'::dxxxxxxxxxxxxxxxxxxxxxxxd::'.
|
||||
..,::cdxxxxxxxxxxxxxdc::,..
|
||||
...,;:::::::;,...
|
||||
""")
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
puffos = AsciiArt(match=r'''"PuffOS"*''', color='3', ascii=r"""
|
||||
puffos = AsciiArt(match=r'''"PuffOS"*''', color='3', ascii=r'''
|
||||
${c1}
|
||||
_,..._,m,
|
||||
,/' '"";
|
||||
/ ".
|
||||
,'mmmMMMMmm. \
|
||||
_/-"^^^^^"\""%#%mm, ;
|
||||
_/-"^^^^^"""%#%mm, ;
|
||||
,m,_,' "###) ;,
|
||||
(###% \#/ ;##mm.
|
||||
^#/ __ ___ ; (######)
|
||||
@@ -16,5 +16,5 @@ ${c1}
|
||||
_; (#\"// \"/#) ; ,/
|
||||
@##\ \##/ = `"=" ,;mm/
|
||||
`\##>.____,...,____,<####@
|
||||
""")
|
||||
''')
|
||||
|
||||
@@ -2,24 +2,26 @@
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
reborn_os = AsciiArt(match=r'''"Reborn OS"* | "Reborn"*''', color='2 2 8', ascii=r"""
|
||||
${c3}
|
||||
mMMMMMMMMM MMMMMMMMMm
|
||||
NM MN
|
||||
MM ${c1}dddddddd dddddddd ${c3}MN
|
||||
mM ${c1}dd dd ${c3}MM
|
||||
${c1}dd hhhhhh hhhhh dd
|
||||
${c3}mM ${c1}hh hh ${c3}Mm
|
||||
NM ${c1}hd ${c3}mMMMMMMd ${c1}dh ${c3}MN
|
||||
NM ${c1}dd hh ${c3}mMMMMMMMMm ${c1}hh dd ${c3}MN
|
||||
NM ${c1}dd hh ${c3}mMMMMMMMMMMm ${c1}hh dd ${c3}MN
|
||||
NM ${c1}dd hh ${c3}mMMMMMMMMm ${c1}hh dd ${c3}MN
|
||||
NM ${c1}hd ${c3}mMMMMMMm ${c1}dh ${c3}MN
|
||||
mM ${c1}hh hh ${c3}Mm
|
||||
${c1}dd hhhhhh hhhhhh dd
|
||||
${c3}MM ${c1}dd dd ${c3}MM
|
||||
MM ${c1}dddddddd dddddddd ${c3}MN
|
||||
NM MN
|
||||
mMMMMMMMMM MMMMMMMMMm
|
||||
reborn_os = AsciiArt(match=r'''"Reborn OS"* | "Reborn"*''', color='0 4 6', ascii=r"""
|
||||
${c1} .======================.
|
||||
${c1}.#${c2}#*********${c1}%%${c2}*********#${c1}%:
|
||||
${c1}:%${c2}#**********${c1}%%${c2}**********#${c1}%-
|
||||
${c1}-%${c2}************${c1}%%${c2}************${c1}%=
|
||||
${c1}+%${c2}******${c1}%%#####${c1}%%#####%%${c2}******${c1}%+
|
||||
${c1}*%%#${c2}****${c1}%#${c3}+=====${c1}%%${c3}=====+${c1}#%${c2}****${c1}#%%*
|
||||
${c1}*%${c2}*#${c1}#%%#%#${c3}====+++${c1}%%${c3}+++====${c1}#%#%%#${c2}#*${c1}##.
|
||||
${c1}.##${c2}*****${c1}#%%%#${c3}*++${c1}%######%${c3}*+*${c1}#%%%#${c2}*****${c1}#%.
|
||||
${c1}:%#${c2}*****${c1}#%${c3}*=+*${c1}#%%${c3}*++++++*${c1}%%#${c3}*+=*${c1}%#${c2}*****${c1}#%:
|
||||
${c1}-%#${c2}*****${c1}#%${c3}+====*${c1}%${c3}*++++++++*${c1}%#${c3}====+${c1}%#${c2}******${c1}%-
|
||||
${c1}-%#${c2}*****${c1}#%${c3}+====*${c1}%${c3}*++++++++*${c1}%#${c3}====+${c1}%#${c2}******${c1}%=
|
||||
${c1}:%#${c2}*****${c1}#%${c3}*=+*${c1}#%%${c3}*++++++*${c1}%%#${c3}*+=*${c1}%#${c2}*****${c1}#%-
|
||||
${c1}.##${c2}*****${c1}#%%%#${c3}*+*${c1}%######%${c3}*+*${c1}#%%%#${c2}*****${c1}#%:
|
||||
${c1}.##${c2}**${c1}#%%#%#${c3}====+++${c1}%%${c3}+++====${c1}#%#%%#${c2}#*${c1}##.
|
||||
${c1}*%%#${c2}****${c1}%#${c3}+=====${c1}%%${c3}=====+${c1}#%${c2}****${c1}#%%*
|
||||
${c1}+%${c2}******${c1}%%#####%%#####%%${c2}******${c1}%*
|
||||
${c1}-%${c2}************${c1}%%${c2}************${c1}%=
|
||||
${c1}:%${c2}#**********${c1}%%${c2}**********#${c1}%-
|
||||
${c1}:%${c2}#*********${c1}%%${c2}*********#${c1}%:
|
||||
${c1}.======================.
|
||||
""")
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
rhino_linux = AsciiArt(match=r'''"Rhino Linux"*''', color='5 4', ascii=r"""
|
||||
${c1}
|
||||
${c1} ..','.. l.
|
||||
.,coooooooooc,..ool
|
||||
;oooooooooooooooooooo.,coo.
|
||||
;oooooooooooooooooooooooooo ,
|
||||
.ooooooooooooooooooooooooooo . ,o
|
||||
oollcccccccccllloooooooooooolcoo..oo
|
||||
ll;':::::::::::::::ccloooooooooooooo:
|
||||
.;''';::::::::::::::::::ccloooooooooo
|
||||
''''',:::::::::::::::::::::::cclllllc
|
||||
'''''';::::::::::::::::::::::::::::::
|
||||
${c1}.'''''';::::::::::::::::${c2}ll${c1}:::::::::::
|
||||
${c1} ''''''';:::::::::::::::${c2}d0${c1}::
|
||||
${c1}.''''''',;:::::::${c2}cc${c1}::::${c2}0N:'
|
||||
${c1}''''''''',,;::::${c2}cK${c1}:::${c2}dMX,
|
||||
${c1}'''''''''''',,,${c2}dMccOMM${c1}:
|
||||
${c1}.''''''''''''${c2}cWM0WMM${c1}.
|
||||
${c1}'''''''':${c2}kMMMMM${c1}.
|
||||
${c2}odxONMMMM
|
||||
;Kl
|
||||
""")
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
salix = AsciiArt(match=r'''"Salix"*''', color='2', ascii=r'''
|
||||
${c1} __s_aaaaaaaaauuoXSSSSSSSS:
|
||||
._xSSSSSSSSSSSSSSSSSSSSSSSSSS:
|
||||
_aSSSSSSSSSSSSSSSSSSSSSSSSSSSSS:
|
||||
_xSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS:
|
||||
<XSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS:
|
||||
-"^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^'
|
||||
|
||||
.ssssssssssssssssssssssssssssssssssss
|
||||
{SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSl
|
||||
oSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS;
|
||||
:XSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS;
|
||||
{SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS
|
||||
-"""""""""""""""""""""""""""""""""""'
|
||||
|
||||
<assssssssssssssssssssssssssssssss>
|
||||
nSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS}
|
||||
nSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS}`
|
||||
XSSSSSSSSSSSSSSSSSSSSSSSSSSSS"`
|
||||
SSSSSSSSSSSSSSSSSSSSSSSSS!"`
|
||||
-""""""""""""""""""""""`
|
||||
''')
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
skiffos = AsciiArt(match=r'''"SkiffOS"*''', color='4 7', ascii=r"""
|
||||
skiffos = AsciiArt(match=r'''"SkiffOS"*''', color='4 7', ascii=r'''
|
||||
${c2}
|
||||
,@@@@@@@@@@@w,_
|
||||
${c2}====~~~,,.${c2}A@@@@@@@@@@@@@@@@@W,_
|
||||
@@ -12,6 +12,6 @@ ${c2}
|
||||
${c2}*@@@@@@@@@@@@@@@@@@@@@@@@@p${c1}||||==,
|
||||
${c1}`'||LLL{{""${c2}@$B@@@@@@@@@@@@@@@p${c1}||
|
||||
${c1}`~=|||||||||||L"${c2}$@@@@@@@@@@@
|
||||
${c1}````'"\"\""\"\""${c2}'"\"\""\"\"\""
|
||||
""")
|
||||
${c1}````'"""""""${c2}'""""""""
|
||||
''')
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
slackel = AsciiArt(match=r'''"Slackel"*''', color='3', ascii=r'''
|
||||
${c1} _aawmmmmmwwaaaaas,,,_.
|
||||
.ammmmm###mmmmmmm###BQmm##mws
|
||||
.am###mmBmBmBmBmBmBmmmmm#mmmm#2
|
||||
<q###mmBmBmBmBmBmBmBmBmBmBmmBmZ`
|
||||
um#mmmBmBm##U##mmBmBmBmWmmBmWm#(
|
||||
.wm#mmBBmm#Y~ ~XmBmBmWmmmmmBm#e
|
||||
.dm#mmWmm#Z' ]#mBmBmmBZ!""""`
|
||||
.dm#mmBmm#2` ]mmmBmBm#2
|
||||
jm#mmWmm#2` dmmBmBmB#(
|
||||
)m##mBmmWZ` )##mBmBmmZ
|
||||
:dmmmBmBm#' .d#mBmBmWZ(
|
||||
j#mmBmBmme jmmmBmBm#2
|
||||
_m#mBmWmmm' )mmmBmBmmZ`
|
||||
]##mBmmm#2 <m#mBmBmB#^
|
||||
dmmmBmWm#C <m#mBmBmB#(
|
||||
ZmmBmBmmmh. _jm#mmBmBm#(
|
||||
XBmBmBmBmm6s_aum##mmBmBm&^
|
||||
3$mBmBmBmmm#mmmmmmBmBm#2'
|
||||
+ZmBmBmWmBmBmWmmBmBm##!
|
||||
)ZmBmBmmmBmBmmBmB##!`
|
||||
-4U#mBmWmBmBm##2"
|
||||
-!!XU##US*?"-
|
||||
''')
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
tatra = AsciiArt(match=r'''"Tatra"*''', color='4 7', ascii=r"""
|
||||
${c1}
|
||||
. .:. . .:.
|
||||
.^^.!.:::. .^!?J?^
|
||||
.:^.^!!!~:~^. .7??77!~~^.
|
||||
.~^.!??77?!.^~: ..:^^7JJJ7~~^.
|
||||
.^~.^7???7~.~~. .7??????????!
|
||||
.:^:^^~^^:!^ ^: .......^!:...
|
||||
.!7~.::.!.::. ~BG~ :^ ^~:
|
||||
:!!~ ~. ?BBBB! ^?J!. .!~.
|
||||
:!. .JBY. .Y#BBBY?~!???J7. :^^.
|
||||
.. :5#B#P~P#BBP?7?55J?J7:
|
||||
^P#BBBBBBBB5?7J5555J!.....
|
||||
!BBBBBBGBBGJ77::Y555J?77777^
|
||||
?BBBBG5JJ5PJ?!: .?Y??????77?~.
|
||||
.YBGPYJ??????Y?^^^^~7?????????7?!.
|
||||
.^^:..::::::::.....:::::::::::..:.
|
||||
""")
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
trisquel = AsciiArt(match=r'''"Trisquel"*''', color='4 6', ascii=r"""
|
||||
trisquel = AsciiArt(match=r'''"Trisquel"*''', color='4 6', ascii=r'''
|
||||
${c1} ,o$$$o.
|
||||
,o$$Y"\""Y$$b
|
||||
,o$$Y"""Y$$b
|
||||
,o$$$$$$o. ,$$' , Y$$b
|
||||
,o$$$$$$$$$$$$o. :$ b Y$$.
|
||||
,$$"' "Y$$$$o. 'b. ,b d$$$
|
||||
@@ -12,7 +12,7 @@ $$' .d$$$$b '$$$$o 'Y$$$Y d$$$'
|
||||
$$' q' 'b '$$$$$o._ _.o$$$$'
|
||||
.$$,_ _,d$ ,$$$$$$$$$$$$${c2}$$$$Y'
|
||||
${c1} '$$$$aaa$$$' .$$$$$$${c2}$$$$$$$$'
|
||||
${c1} "\"\"" ${c2}d$$$$"'
|
||||
${c1} """" ${c2}d$$$$"'
|
||||
d$$$' .d$$b.
|
||||
$$$$ .$" 'a$.
|
||||
$$$$ $b $$.
|
||||
@@ -20,5 +20,5 @@ ${c1} "\"\"" ${c2}d$$$$"'
|
||||
'$$$. .$$'
|
||||
'a$$$o._.o$$a'
|
||||
'a$$$$a'
|
||||
""")
|
||||
''')
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
unicodearch = AsciiArt(match=r'''"unicodearch"*''', color='6 6 7 1', ascii=r"""
|
||||
${c1} ▄
|
||||
▟█▙
|
||||
▟███▙
|
||||
▟█████▙
|
||||
▟███████▙
|
||||
▂▔▀▜██████▙
|
||||
▟██▅▂▝▜█████▙
|
||||
▟█████████████▙
|
||||
▟███████████████▙
|
||||
▟█████████████████▙
|
||||
▟███████████████████▙
|
||||
▟█████████▛▀▀▜████████▙
|
||||
▟████████▛ ▜███████▙
|
||||
▟█████████ ████████▙
|
||||
▟██████████ █████▆▅▄▃▂
|
||||
▟██████████▛ ▜█████████▙
|
||||
▟██████▀▀▀ ▀▀██████▙
|
||||
▟███▀▘ ▝▀███▙
|
||||
▟▛▀ ▀▜▙
|
||||
""")
|
||||
|
||||
+20
-15
@@ -3,20 +3,25 @@
|
||||
from . import AsciiArt
|
||||
|
||||
venom = AsciiArt(match=r'''"Venom"*''', color='8 4', ascii=r"""
|
||||
${c1} ::::::: :::::::
|
||||
mMMMMMMm dMMMMMMm
|
||||
/MMMMMMMo +MMMMMMM/
|
||||
yMMMMMMN mMMMMMMy
|
||||
NMMMMMMs oMMMMMMm
|
||||
+MMMMMMN: NMMMMMM+
|
||||
hMMMMMMy sMMMMMMy
|
||||
:NMMMMMM::NMMMMMN:
|
||||
oMMMMMMyyMMMMMM+
|
||||
dMMMMMMMMMMMMh
|
||||
/MMMMMMMMMMMN:
|
||||
sMMMMMMMMMMo
|
||||
mMMMMMMMMd
|
||||
+MMMMMMMN:
|
||||
::::::
|
||||
${c1}
|
||||
`-`
|
||||
-yys+/-`
|
||||
`oyyyyy: /osyyyyso+:.
|
||||
/yyyyy+`+yyyyyyyyyys/.
|
||||
.-yyyyys.:+//+oyyyyyyyo.
|
||||
`oy/`oyyyyy/ ./syyyyy:
|
||||
syyys`:yyyyyo` :yyyyy:
|
||||
/yyyyo .syyyyy- .yyyyy.
|
||||
yyyyy. +yyyyy/ /yyyy/
|
||||
`yyyyy :yyyyys` -yyyyo
|
||||
yyyyy. `syyyyy- /yyyy/
|
||||
/yyyyo /yyyyy+ .yyyyy.
|
||||
syyyys. -yyyyys.:yyyy:
|
||||
`oyyyyyo-` `oyyyyy:.sy:
|
||||
:syyyyyyso+/++`/yyyyyo``
|
||||
-oyyyyyyyyyyy-.syyyys.
|
||||
-/+osyyyyso.`+yyyyy/
|
||||
.-/+syo`
|
||||
`.
|
||||
""")
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
venom_small = AsciiArt(match=r'''"venom_small"*''', color='8 4', ascii=r"""
|
||||
${c1} ++**
|
||||
*===**====+*
|
||||
*====* +===+
|
||||
*==*+===* *===*
|
||||
*===* *===+ *===*
|
||||
*===* +===+ *===*
|
||||
*===* +===* *===*
|
||||
*===* *===+*==*
|
||||
+===+ *===+=*
|
||||
*+====**===*
|
||||
**++
|
||||
""")
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
windows95 = AsciiArt(match=r'''"Windows95"''', color='6 4 3 2 1 0', ascii=r'''
|
||||
${c6} ___
|
||||
.--=+++++=-:.
|
||||
. _ *%@@@@@@@@@@@@@@*
|
||||
*:+:.__ :+* @@@ @"${c5}_*&%${c6}@@${c4}%&&&*${c6}"@@@
|
||||
"+.-#+ +%* " _ ${c5}++&&&%${c6}@@${c4}%&&&&&#${c6}@@
|
||||
${c5} " , ${c6}%@@ ${c5}&&&&&%${c6}@@${c4}%&&&&&#${c6}@@
|
||||
${c5} * oo *# ${c6}" _ ${c5}&&&&&%${c6}@@${c4}%&&&&&#${c6}@@
|
||||
${c5} " , ${c6}%@@ ${c5}&&&&"${c6}@@@@#*${c4}"&&&${c6}@@
|
||||
.${c5} * oo *# ${c6}" _ %@@@@@@@@@@@@@@@@
|
||||
*:+:.__ :=* %@@ @"${c1}**&%${c6}@@${c3}%&&&*${c6}"@@@
|
||||
"+.-#+ +%* " _ ${c1}&&&&&%${c6}@@${c3}%&&&&&#${c6}@@
|
||||
${c1} " , ${c6}%@@ ${c1}&&&&&%${c6}@@${c3}%&&&&&#${c6}@@
|
||||
${c1} * oo *# ${c6}" _ ${c1}&&&&&%${c6}@@${c3}%&&&&&#${c6}@@
|
||||
${c1} " , ${c6}%@@ ${c1}&&*"${c6}%@@@@@@${c3}"*%&${c6}@@
|
||||
.${c1} * oo *# ${c6}" _ @@@@@@@@@@@@@@@@@
|
||||
*:+:.__ :+# @@@ @%#=+""""""+==%#@
|
||||
"+.-#+ +%* %+" " ":@
|
||||
" "
|
||||
''')
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
openwrt = AsciiArt(match=r'''"OpenWrt"*''', color='4 7 1', ascii=r"""
|
||||
wrt = AsciiArt(match=r'''*"Wrt"*''', color='4 7 1', ascii=r"""
|
||||
${c1} _______
|
||||
| |.-----.-----.-----.
|
||||
| - || _ | -__| |
|
||||
@@ -0,0 +1,34 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
xenia = AsciiArt(match=r'''"Xenia"*''', color='#55CDFD' '#F6AAB7' '#FFFFFF', ascii=r"""
|
||||
${c3} !${c3}`${c3} @
|
||||
${c3} @${c3}```${c3}b @@@@@
|
||||
${c3} @${c3}`````${c3}@ @/${c3}@@@@
|
||||
${c3} @@${c3}``'))))))))))C@@
|
||||
${c3} @@@){)))))())))))))
|
||||
${c3} @r))))@${c1}oooo${c3})))))h)))[
|
||||
${c3} rr)))j${c1}oooooo${c3}(x${c1}ooooo${c3}$@)
|
||||
${c3} rrrxr))r/l;${c1},,,${c3}z@{${c1},,,,,${c3}@@
|
||||
${c3} rr ) ${c2}v${c3} @;@rx
|
||||
${c3} rrr) ${c2}\__^__/${c3} ji
|
||||
${c3} rj]. . r
|
||||
${c3}[[${c2}]]${c1}11111111111111111]
|
||||
${c2}]${c3}[[[${c2}]]][${c1}11111111111111111<
|
||||
${c2}]${c3}[[[[[${c2}]]]]]]]]]]]]]]${c1}-111111[
|
||||
${c2}]-${c3}[[[[[[;${c2}]]]]]]]]]]]]]]]]${c1} 1
|
||||
${c2}]]${c3}[[[[[[[[[[[${c2}]]]]]]]]]]]]]
|
||||
${c1}1${c2}]][${c3}[[[[[[[[[[[[[${c2}<]]]]]]]]]
|
||||
${c1}11${c2}]]]${c3}[[[[[[[[[[[[[[[${c2}]]]]]]]
|
||||
${c1}111${c2}]]]]'${c3}[[[[[[[[[[[[[[${c2}]]]]
|
||||
${c1}111-${c2}]]]]]${c3}[[[[[[[[[[[[[${c2}]]
|
||||
${c1}11111${c2}]]]]]_${c3}[[[[[[[[[[${c2}]
|
||||
${c1}11111${c2}]]]i${c3}[[[[[[[[
|
||||
${c1}1111${c2}]]+${c3}[[[[[[^
|
||||
${c1}11 ${c2}]]${c3}[[[[[[
|
||||
${c1}11 +${c2}]${c3}[[[[
|
||||
${c1}1 ${c2}]${c3}[[
|
||||
`
|
||||
""")
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
xenia2 = AsciiArt(match=r'''"Xenia2"*''', color='#55CDFD' '#F6AAB7' '#FFFFFF', ascii=r"""
|
||||
${c2} ,c. .c;
|
||||
${c2} .${c1}KMMMk${c2}.... ....${c1}kMMMK${c2}.
|
||||
${c2} .${c1}WMMMMMX${c2}..... .....${c1}KMMMMMW.
|
||||
${c1} XMMMMMMM0${c2}..... ....${c1}OMMMMMMMN
|
||||
${c1} dMMMMMMMMM;${c2}.... ..... ....,${c1}MMMMMMMMMd
|
||||
${c1} WMMMMMMMMMl;${c3}okKKKKKKKKKOo${c1};cMMMMMMMMMM
|
||||
${c1} 'MMMMMMMNX${c2}K0${c3}KKKKKKKKKKKKKKK${c2}0K${c1}XNMMMMMMM;
|
||||
${c1} oMMMMMMM${c2}Oxo${c3}KKKKKKKKKKKKKKKKK${c2}oxO${c1}MMMMMMMd
|
||||
${c1} dMMMMMMM${c2}dxxx${c3}KKKKKKKKKKKKKKK${c2}xxxd${c1}NMMMMMMk
|
||||
${c1} :MMMMX0${c2}xxxxxx${c3}0KKKKKKKK0KK0${c2}xxxxxx0${c1}XMMMMc
|
||||
${c1} MMMO${c2}xxxxxxxxdx${c3}kdd${c2}0x0${c3}ddk${c2}xdxxxxxxxx${c1}OMMM
|
||||
${c1} ;${c2}xxkxddxxxxdodxxxxdxdxxxxdodxxxxddxkxx${c1};
|
||||
${c1}dxd${c2}KMMMWXo${c1}'.....'${c2}cdxxxdc${c1}'.....'${c2}lXWMMMX${c1}dxd
|
||||
${c1}cxd${c2}XMMMN${c1},..........${c2}dxd${c1}'.........'${c2}XMMMN${c1}dxl
|
||||
${c1} .xx${c2}WMMl${c1}...''....'.;k:.'....''...${c2}lMMW${c1}xx.
|
||||
${c1}..:kXMMx..'....''..kMk..''....'..xMMXkc..
|
||||
${c1} dMMMMMMd.....'...xMMMx...''....dMMMMMMx
|
||||
${c1} kMMMMWOoc:coOkolllokOoc:coOWMMMMO
|
||||
${c1} .MMMMMMMMl${c2}...${c1}lNMMMMMMM.
|
||||
${c1} KMMMMMMX${c2}l${c1}KMMMMMMX
|
||||
${c1} .MMMMMMMMM.
|
||||
""")
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
# This file is automatically generated. Please do not modify.
|
||||
|
||||
from . import AsciiArt
|
||||
|
||||
xray_os = AsciiArt(match=r'''"Xray_OS"*''', color='15 14 16 24', ascii=r"""
|
||||
${c1} ${c1}rrrrrraaaaaaaaaaaayyyy
|
||||
${c1}xxrrrrrrrraaaaaaaaaaaayyyyyyyyy
|
||||
${c1}xxxxxrrrrrrrraaaaaaaaaaaayyyyyyy${c3}yyyyy${c2}yyyyyyyyyy
|
||||
${c1}xxxxxxxrrrrrrrraaaaa ${c2}aaaaayyyyyyyyyyyyyyyyyyy
|
||||
${c1}xxxxxx${c3}xxx${c1}rrrrrrrraaaa ${c2}aaaaaaayyyyyyyyyyyyyyyyy
|
||||
${c1}xxxxxx${c3}xxxxxr${c1}rrrrrrraa ${c2}aaaaaaaaay${c3}yyyyyyyyy${c2}yyyy ${c1}yy
|
||||
${c1}xxxxxxx${c3}xxx${c1}xxrrrrrrrra ${c2}aaaaaaaaa${c3}ayyyyyyyyyyyy${c1}yyyyyy
|
||||
${c1}xxxxxxxxxxxxrrrrrrrr ${c2}aaaaaaaaaaa${c3}yyyyyyyyyyyy${c1}yyyyyyy
|
||||
${c1}xxxxxxxxxxxxxrrrrrr ${c2}raaaaaaaaaaaayyy${c3}yyyyyyyy${c1}yyyyyy${c1}yyy
|
||||
${c1}xxxxxxxxxxxxxrrrrr ${c2}rraaaaaaaaaaaayyyyy${c3}yy${c2}yyyyyy ${c1}yyyyyy
|
||||
${c1}xxxxxxxx${c3}xxxx${c1}xrrrrr${c2}rr${c3}raaaaaaa${c2}aaaaayyyyyyyyyy ${c1}yyyyyyyyy
|
||||
${c1}xxxxxxx${c3}xxxx${c1}xxrrrrrrr${c3}raaaaaa${c2}aaaaaayyyyyyy ${c1}yyyyyyyyyyyy
|
||||
${c1}xxxxxxx${c3}xxx${c1}xxxrrrrrrrr${c3}aaaaaa${c2}aaaaaayyyy ${c1}yyyyyyyyyyyyyy
|
||||
${c1}xxxxxxxxxxxxrrrrrrrra ${c2}aaaaaaaaaay ${c1}yyyyyyyyyyyyyyyy
|
||||
${c1}xxxxxxxxxxxrrrrrrr ${c2}aaaaaaaaaaaayyyy${c1}yyyyyyyyyyyyy
|
||||
${c1}xxxxxxx${c3}xxxrr${c1}rrrr ${c2}raaaaaaaaaaaa ${c1}yyyyyyyyyyyyyyy
|
||||
${c1}xxxxxxxxrrrr ${c2}rrraaaaaaaaa ${c1}aayyyyyyyyyyyyyy
|
||||
${c1}xxxxxxrrrrrrr ${c2}aaaaaa ${c1}aaaayyyyyyyyyyyy
|
||||
${c1}xxxrrrrrr ${c2}raaa ${c1}aaaaaaayyyyyyyyy
|
||||
${c1}rrrr ${c2}rr ${c1}aaaaaaaaaayyyyyy
|
||||
${c2}r ${c1}aaaaaaaaaa
|
||||
""")
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
from hyfetch.constants import CACHE_PATH
|
||||
from hyfetch.neofetch_util import get_distro_name
|
||||
|
||||
|
||||
def get_font_logo() -> str:
|
||||
cache = CACHE_PATH / 'font_logo_cache.txt'
|
||||
if cache.exists():
|
||||
return cache.read_text('utf-8')
|
||||
|
||||
font_logos: dict[str, str] = json.loads((Path(__file__).parent / 'data/font_logos.json').read_text('utf-8'))
|
||||
font_logos = {k.lower(): v for k, v in font_logos.items()}
|
||||
|
||||
# Get the distro
|
||||
distro = get_distro_name().lower()
|
||||
|
||||
# Find most likely distro by containing string
|
||||
for k in font_logos.keys():
|
||||
if k in distro:
|
||||
distro = k
|
||||
# If not found, try matching partial string (by splitting with " ")
|
||||
if not distro:
|
||||
for k in font_logos.keys():
|
||||
if any(x in distro for x in k.split(' ')):
|
||||
distro = k
|
||||
# If still not found, give up
|
||||
if not distro:
|
||||
raise ValueError(f'No font logo found for distro: {distro}. The supported logos are in https://github.com/Lukas-W/font-logos')
|
||||
|
||||
logo = font_logos[distro]
|
||||
cache.parent.mkdir(parents=True, exist_ok=True)
|
||||
cache.write_text(logo)
|
||||
|
||||
return logo
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user