mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-12 18:32:10 +02:00
Compare commits
1314 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ab0f69731e | |||
| 37afe5a79d | |||
| 0ebf09754b | |||
| 0b1bc5b527 | |||
| 3d107764fa | |||
| 4863a173e4 | |||
| 8ea4468eec | |||
| b0ba084b5e | |||
| 43d01f26ea | |||
| b5ffc32b80 | |||
| 4ff931c06f | |||
| 6eef800ea2 | |||
| b9e4d04d65 | |||
| 9c791b2c12 | |||
| 76b6768141 | |||
| 42002a6240 | |||
| ef7f5aeac3 | |||
| d5214af189 | |||
| a33d6326f1 | |||
| df99241424 | |||
| 5b1ad1008d | |||
| 39024abae9 | |||
| 4dba32aabb | |||
| 753ddec3c5 | |||
| b04587e0cb | |||
| 3abcf4195f | |||
| af8a42270c | |||
| 1c9e521775 | |||
| 7fe08bddd0 | |||
| 41da49f579 | |||
| f169165599 | |||
| 2c4caf8e0d | |||
| 51b370a105 | |||
| 14cf6bfdc1 | |||
| 4d00dc6802 | |||
| d7de7c41ca | |||
| d80fe3f004 | |||
| dcce4ccdb0 | |||
| 191c5f2ef5 | |||
| 1dc794fac0 | |||
| 5936c1cef4 | |||
| 04f26a29eb | |||
| c9ad429a1b | |||
| 2b42db58da | |||
| 32757b0e43 | |||
| c5598d2361 | |||
| 203cd7cbcf | |||
| fb309134b5 | |||
| 8b162e89de | |||
| 9670b585fb | |||
| 3b76ade662 | |||
| 1b1df2e731 | |||
| 6c19a8b4ec | |||
| 71728247ab | |||
| 4344aa2ff1 | |||
| b7d8c12015 | |||
| 63d16ca854 | |||
| f15a1e96ce | |||
| 55bfcd6d86 | |||
| 880284fa9c | |||
| 143939f19b | |||
| a979d8ae81 | |||
| b5897f784f | |||
| 83cc7a94a4 | |||
| 5edda068f2 | |||
| 6d5cb520ed | |||
| e7ecba4460 | |||
| e0c239729b | |||
| 6570a7accc | |||
| 0c4ec62cac | |||
| 5d11b65d53 | |||
| 8b40117c08 | |||
| b1f2bf3526 | |||
| d8452f71ed | |||
| 2a269bfd4c | |||
| cafe82b462 | |||
| db8ee8159d | |||
| f0765b1a13 | |||
| 93566cb73c | |||
| 6d0d093d62 | |||
| 54fe4ffece | |||
| 124bbb06f9 | |||
| f04a53337d | |||
| 514efab8eb | |||
| 232cd6659b | |||
| 7c93f9c82a | |||
| e5b6e3612a | |||
| 6cb15885c7 | |||
| e6d90c2081 | |||
| 679d868b4a | |||
| 72d240f325 | |||
| 2ca7e037ef | |||
| 5e9c31ac31 | |||
| bcb48774a0 | |||
| 9ff7969acf | |||
| 7fbd06a135 | |||
| bbb906ba10 | |||
| 2de674ec9a | |||
| b700d9ded5 | |||
| 359cb0a79a | |||
| 45f9de6cd2 | |||
| 233c481f7a | |||
| b677f1e902 | |||
| 8d82eedaef | |||
| 4dc27b365f | |||
| e5c3fa4023 | |||
| bdba78c45c | |||
| f95167e907 | |||
| 3908c39ce2 | |||
| 858d3749f4 | |||
| 51f36fa4b4 | |||
| bfe30eec79 | |||
| 4dd2f2d34b | |||
| 60431c0321 | |||
| 7b2b3405ae | |||
| 965ed4ba79 | |||
| 00603357ea | |||
| 5ea299a8d2 | |||
| 368a4c5a73 | |||
| 8df0a1c97e | |||
| 7098cd86cb | |||
| 681749ed54 | |||
| c4695b8cf1 | |||
| 1d12003555 | |||
| 16b10c162b | |||
| 51cfd4b5ed | |||
| a0452b8323 | |||
| ebf38e829d | |||
| 4c2af4071c | |||
| e3b8e94055 | |||
| 1d4b0236ac | |||
| da42108732 | |||
| 8b8efcdcce | |||
| 8bc4464b64 | |||
| 4361c5e787 | |||
| 558a90d4e0 | |||
| 881730d0bd | |||
| ac8fc63c28 | |||
| 8686820c1a | |||
| 39b3dc001a | |||
| ba60d7975c | |||
| 51a4f34bb5 | |||
| 01bb73b9e8 | |||
| 56da8f8110 | |||
| 6d6302e327 | |||
| 20277b9ee9 | |||
| b6d95a0ce5 | |||
| daf5421be7 | |||
| b739dfee0b | |||
| 80101a5803 | |||
| cf33bef128 | |||
| 7e786bee31 | |||
| cbea6c3cb1 | |||
| 48a234d742 | |||
| c271708f7d | |||
| b42f11442c | |||
| 73918956d7 | |||
| 6559c7f42d | |||
| 56950e790f | |||
| e7642ea3a2 | |||
| a88ef86ce3 | |||
| fcf4aca3b7 | |||
| 3f8d141313 | |||
| 97a9be27b9 | |||
| dc46ecbcac | |||
| 984fadf70f | |||
| 1a42cbe1cf | |||
| 9c7cfb864f | |||
| 6d795a3572 | |||
| 2af56232a4 | |||
| 3196f5efaa | |||
| 1626ced83c | |||
| 241ddb79b0 | |||
| 66ce39e3fc | |||
| 3fae9e0274 | |||
| 5eaf98ecd2 | |||
| 00b7c5b56c | |||
| 305ab14e7b | |||
| a58fc4f77d | |||
| b653ef730d | |||
| dc464d6efe | |||
| 1c3f0eb7c0 | |||
| 476cd67345 | |||
| 2c736697d2 | |||
| 738ad59f54 | |||
| 5476e01407 | |||
| 4f0b00116e | |||
| 6490e2707f | |||
| ccf3909372 | |||
| 18eef29d0a | |||
| f6c25667fe | |||
| 97fa52fef0 | |||
| c5a8950ad4 | |||
| 111c1bab75 | |||
| 47dfd8a271 | |||
| bc1d305aaa | |||
| dda39f0c67 | |||
| 0b72c9b083 | |||
| 69f3d9ae33 | |||
| db46e06f2e | |||
| 7223803a76 | |||
| 9db4ec82fd | |||
| 62180366fc | |||
| 0feec933ea | |||
| 6c03db8be9 | |||
| f0564fb9a7 | |||
| 8bf1aca7fc | |||
| 445311978e | |||
| d9f5e006b5 | |||
| 21fbf14fb8 | |||
| bc8ce39193 | |||
| ac3fc219cf | |||
| dd30c82b83 | |||
| b41cdb0ca6 | |||
| 2b03bacb28 | |||
| 7dcc7d40d5 | |||
| a0fd59d869 | |||
| 1c352bb4de | |||
| 29d626f41d | |||
| 8ca6bb084d | |||
| 0b3ef5d35c | |||
| 98c8c5b344 | |||
| eeae601924 | |||
| 773e3ea497 | |||
| 317c0cfb86 | |||
| e0c31be9d5 | |||
| 75f00af98d | |||
| 9d6bb7d717 | |||
| 2ae9c3da33 | |||
| bf1af71d03 | |||
| 61656a1a7a | |||
| ba18705d2e | |||
| 873454191f | |||
| f8908b9a36 | |||
| 8ca551cccc | |||
| 0869809857 | |||
| c31779e99d | |||
| 89ad35d8a1 | |||
| d651f3de43 | |||
| c34c3e5aae | |||
| c5c61584d9 | |||
| 48c3b4f980 | |||
| 93bca8d480 | |||
| c690fe5aa9 | |||
| 55e674e1cb | |||
| 0495c47909 | |||
| 2f79c39f62 | |||
| 44056f1c85 | |||
| 6358bd7844 | |||
| 11d77e0d09 | |||
| ec25659503 | |||
| 35dbcb2588 | |||
| 8b6a74f2ec | |||
| 2ea6c3767e | |||
| 827bc26b0a | |||
| e12f3631d4 | |||
| 52c9730542 | |||
| 225d9e7771 | |||
| d031d6c20f | |||
| 35af768d92 | |||
| 22c4620345 | |||
| 81738aa303 | |||
| 113f7d34d8 | |||
| 62513004c8 | |||
| 1b36c3cd5f | |||
| 78874ae583 | |||
| a447928853 | |||
| 9f446bdad7 | |||
| 4cf060eb27 | |||
| 08d419d75c | |||
| 3ae1bfdc24 | |||
| 0e257f25c2 | |||
| 195e148cc1 | |||
| 5ab192ee05 | |||
| 4897152af6 | |||
| 69418cb527 | |||
| 0e90f3a7d4 | |||
| 1a663e72da | |||
| e0ae1ac1a2 | |||
| e0d141ecf6 | |||
| 29eb8bb57d | |||
| bc1f240558 | |||
| 3e15a2591a | |||
| 0ec9443de5 | |||
| 4a4ca9a4a8 | |||
| acf76e565a | |||
| 778aa21192 | |||
| dfdc7284a2 | |||
| 231d7fcd4d | |||
| a3184601dc | |||
| e3dfeeb8db | |||
| ccdcd6ab6f | |||
| 64d205628e | |||
| ff13adf1b4 | |||
| c38fd9ec10 | |||
| 96793ec604 | |||
| b79a336576 | |||
| d36e3a793b | |||
| d48bb48e4f | |||
| 835001eb2f | |||
| 5647703e4d | |||
| eff0108bb5 | |||
| 31c1431ac6 | |||
| fa2c56cb9f | |||
| 104b33c1f7 | |||
| cb4502dacc | |||
| 3dc86391ab | |||
| f5a67b25f4 | |||
| d8be61411e | |||
| 61968ca95c | |||
| 9f190b46c9 | |||
| a6aac70a5e | |||
| 3aa43212ff | |||
| 7c39b64fb4 | |||
| e1963e41be | |||
| a1d4cbf67f | |||
| f5b9e09d91 | |||
| 9742dda795 | |||
| 677c213397 | |||
| 8f0a12323b | |||
| b49f0b3d9c | |||
| bc686b2c84 | |||
| 7c2f7fa4f2 | |||
| 5fd059827d | |||
| 240928138e | |||
| 508a50f803 | |||
| bd40d8756e | |||
| b732e0c6d7 | |||
| 96685b7ebe | |||
| 49a1e42efd | |||
| b0fd11fcbd | |||
| b6127ff2c9 | |||
| f3babe3187 | |||
| e9c0d886d1 | |||
| d6a4946511 | |||
| 43e0cc22ff | |||
| c42ea6eeea | |||
| fe7962d5d2 | |||
| e84195bca0 | |||
| bf0133fe60 | |||
| 942c15b7b0 | |||
| 61a0bbcc8d | |||
| 8b3673eb38 | |||
| 22f9948497 | |||
| 107f39eb15 | |||
| 4e44c0520b | |||
| 55eb3c59d4 | |||
| 878ccf1375 | |||
| ebb0cf77bd | |||
| 17914dc29e | |||
| 14dfe171fb | |||
| 265c334399 | |||
| fc303c58db | |||
| 01e7503263 | |||
| ffd0455fe3 | |||
| 7df2ed2251 | |||
| 2edc41dd9a | |||
| cada77163e | |||
| 7cecdb0e6d | |||
| 420a9e9d7b | |||
| b96d8ad00b | |||
| 52970e2d13 | |||
| 4594734b66 | |||
| eb54c89b4a | |||
| 43301afc47 | |||
| 09e28451ec | |||
| 35c2f8c924 | |||
| 3ec7e94b47 | |||
| a720e1f945 | |||
| 70061625f7 | |||
| 5cd4316f98 | |||
| e946861eb0 | |||
| f09aebecd5 | |||
| 8f266eb2a7 | |||
| 8ee08d0067 | |||
| e936ddef6b | |||
| c706201282 | |||
| e24e3b6b29 | |||
| 135547fd50 | |||
| da05bed32f | |||
| 636471c366 | |||
| cbc84fda6c | |||
| fc7a0a8484 | |||
| 4d3b6c3b1b | |||
| 70e67177fe | |||
| 9fe7d6dbfa | |||
| a139a8c4a5 | |||
| da568c986e | |||
| 727fbc0276 | |||
| 20aabdfd78 | |||
| e79aaf5ce1 | |||
| 53c2d07161 | |||
| 6b9f594620 | |||
| ba3968784f | |||
| 021ece1681 | |||
| 9787b56460 | |||
| 54792e61ff | |||
| b34e2a4055 | |||
| 3b56200ee4 | |||
| de95a62e2f | |||
| 72cb64a500 | |||
| d48bd733f0 | |||
| 0585ea7797 | |||
| 794035f8d9 | |||
| 723552f68b | |||
| 8dd38f5744 | |||
| 616a5c7aea | |||
| 5e1e94473e | |||
| 4eae8ac244 | |||
| 8aeb7c2f10 | |||
| c20b532c7a | |||
| 3c59161aca | |||
| bd454632c3 | |||
| e73adc27a0 | |||
| 15c6014c04 | |||
| 54f18982ac | |||
| 99c2f2a2c8 | |||
| 45f35b1c4d | |||
| 428c05b9de | |||
| 23ca6d94ab | |||
| 9e4e0cb838 | |||
| 95a370e5a2 | |||
| e013005f34 | |||
| 92b86f7cbb | |||
| 2e4b7baf44 | |||
| a47ff0b2dc | |||
| 1f13f6c8f5 | |||
| b0bb6fb58e | |||
| 37029dbbe3 | |||
| 35428606e7 | |||
| 2c65eee00f | |||
| a1bf014352 | |||
| 412fc94dab | |||
| b65de28805 | |||
| bc86c66cdd | |||
| 9afa01812d | |||
| 30a8a94cd2 | |||
| 3a54617196 | |||
| 3e3a03a233 | |||
| b407669b69 | |||
| e14ea926a5 | |||
| 9d8f794cb9 | |||
| 825b8b8715 | |||
| 0c94fd87db | |||
| 473a08d85c | |||
| ae5132c388 | |||
| 1addcec7a2 | |||
| e75c37c101 | |||
| b9ab823f77 | |||
| a63d854681 | |||
| 576548b15e | |||
| 3043971259 | |||
| ccf4f22f8b | |||
| f932db713c | |||
| d2e8a8fd9e | |||
| 4c1f7c114a | |||
| 90bbfe195f | |||
| 1689fc81e9 | |||
| 4190dd5a6e | |||
| 074f882d7e | |||
| 53102380b8 | |||
| 822bc158ba | |||
| 8fbc29a70c | |||
| 0ef677a98c | |||
| 10b0d0ca3e | |||
| ec4e820e92 | |||
| 6c09fe49e4 | |||
| 1ce6398391 | |||
| d1bf208a92 | |||
| 7ce1e553b8 | |||
| 9c878b6943 | |||
| 6b9a6fd103 | |||
| 896fe60461 | |||
| dadcccdf26 | |||
| 0746af7549 | |||
| 88c3b7d118 | |||
| 173d9695b6 | |||
| 4b265cd56a | |||
| 1f211cf8d1 | |||
| bac60357c6 | |||
| 3a0e188570 | |||
| 9d5b40686b | |||
| a321cd877e | |||
| 5f810de1e0 | |||
| 3f0a93d057 | |||
| cbca6a965c | |||
| fde1195c27 | |||
| 9856d97bd1 | |||
| 2751737ebe | |||
| 834292df29 | |||
| a9a29869a4 | |||
| 242fb50461 | |||
| b5c4ffcc85 | |||
| 2c3628c630 | |||
| 4cca9bf198 | |||
| 0ed27d9700 | |||
| 9bca4eb48f | |||
| 462b80fc36 | |||
| f49620a95b | |||
| 6e0949c739 | |||
| 4b18ab0de7 | |||
| 8abd75a746 | |||
| d5b215e074 | |||
| 0b22427091 | |||
| aa34910b6c | |||
| 52972ed833 | |||
| 68e75effab | |||
| bb79370d03 | |||
| 9613cdd146 | |||
| 724b816252 | |||
| 7c89a10add | |||
| fb5ec76eb3 | |||
| 7141214f95 | |||
| 7d6074968f | |||
| 3bd380802b | |||
| ec1200dc06 | |||
| 5c18c061b3 | |||
| acf610416c | |||
| 90d3b3d49f | |||
| bbc5b4de98 | |||
| 7f9b6187a6 | |||
| 8067e43631 | |||
| 61dba1ea05 | |||
| a94df76bfa | |||
| b2b748b07c | |||
| 77ce6b0e4c | |||
| d28d307b63 | |||
| 3492f9bfa1 | |||
| 79c67ec0d7 | |||
| 6527f03a9b | |||
| a8b629f58c | |||
| 5df00a3394 | |||
| 8a7c83cac6 | |||
| 27bffb3464 | |||
| 875afb7cde | |||
| 3e99a7035b | |||
| 63873763de | |||
| 27c83e88f2 | |||
| f48904805f | |||
| 531cd0909a | |||
| eafcdfec9e | |||
| d6bd855733 | |||
| af7e2d47d1 | |||
| f71c0b0866 | |||
| 1400291ae9 | |||
| 7799dbe481 | |||
| 8426833c36 | |||
| 235a2018fc | |||
| 470e3b4e57 | |||
| 1942dce980 | |||
| efca4f3597 | |||
| 43ddbdca85 | |||
| 5d29e26509 | |||
| 8daec2568c | |||
| 320e1bf4e0 | |||
| 38e98d3d51 | |||
| 50964fcddf | |||
| 6c7a8a8c41 | |||
| 92082eed54 | |||
| 26b3a84b8a | |||
| 0747fc0887 | |||
| 60fbe1fd0b | |||
| f8667d9faa | |||
| 1c89bbc34e | |||
| b37f020270 | |||
| fbc9569e13 | |||
| a923f61115 | |||
| bc0a515998 | |||
| 87d89130ad | |||
| f46aa316cb | |||
| fdb5f30cb8 | |||
| 91f1c4db10 | |||
| 44e2948b1d | |||
| b86acf6c36 | |||
| 9a15666248 | |||
| f5dfec6dcb | |||
| 8c55c06fa7 | |||
| 8159f473cc | |||
| dca3b154ef | |||
| 79b61f1391 | |||
| ba54763dde | |||
| 451bc394ee | |||
| 93f9ed1bf5 | |||
| d9e4389ed4 | |||
| b465052ad2 | |||
| 2e6b9cd503 | |||
| 0557f16c16 | |||
| 08e252a44c | |||
| 90e2d8f8d9 | |||
| 0dd8d80e02 | |||
| 3cddf31987 | |||
| fe1c5c8f6f | |||
| 994bd53d30 | |||
| 383a4190ca | |||
| 42f2e5a745 | |||
| 14b8bb2bb5 | |||
| b68ad3626c | |||
| cd25803e32 | |||
| 3d6bffe7fe | |||
| e694c8ac84 | |||
| dfff57dd85 | |||
| c5141855a2 | |||
| 6cb186f229 | |||
| e91f62aa70 | |||
| ab5cf94099 | |||
| d9eccd70ed | |||
| 025febc78d | |||
| 69cc19d6f5 | |||
| 2e4dd1d262 | |||
| 24ec0e6035 | |||
| 6e50aaf3ff | |||
| e7cd5f618d | |||
| 55e4896524 | |||
| 594c73461e | |||
| 94ceeb4482 | |||
| 4ee7dd72d0 | |||
| 414f7ce067 | |||
| e1dffe794b | |||
| 181b775f73 | |||
| c4c934d23e | |||
| 31c73543e8 | |||
| d79e1d7fbc | |||
| 3883047dce | |||
| 4eebc1b6ee | |||
| 08b79ff4ae | |||
| ffc38eb0f1 | |||
| 37ee193c40 | |||
| c10027f1d7 | |||
| 039fa1ba77 | |||
| 0db820a6c1 | |||
| 8b611899d1 | |||
| ba7e1eb18b | |||
| 6979b1efc5 | |||
| 4a61cdb1c9 | |||
| 75c28ec671 | |||
| 639252ece0 | |||
| a31d8ce87b | |||
| 41143c23f4 | |||
| 3c2e21b7b1 | |||
| 3eaebd3359 | |||
| 768bc154d4 | |||
| 00cc19e28b | |||
| bf0564f9e5 | |||
| dbb060eb62 | |||
| 1314c18a52 | |||
| 05f5e25c66 | |||
| 4b4c37ed88 | |||
| 8970774e5f | |||
| 69c86c95b7 | |||
| 910ba413da | |||
| dbed1b32b4 | |||
| 278a3834ce | |||
| 5ce3220f50 | |||
| c1c6ccce9a | |||
| e2526521a2 | |||
| 1956c66a5e | |||
| c601b68bc6 | |||
| 528f9f152c | |||
| 64d2c4410e | |||
| 6e4de3e9f1 | |||
| ce51dbf7ea | |||
| abc6c0593c | |||
| b63bd5b8c9 | |||
| 4236d830cc | |||
| c851c39837 | |||
| 1cd196b726 | |||
| f8a8864be5 | |||
| 683e90cec6 | |||
| 08de5eabed | |||
| c7ecc33b64 | |||
| ee7f574349 | |||
| 10f58e405e | |||
| d81a7b6278 | |||
| 48daf4ac1e | |||
| 6d01c0b438 | |||
| 3cc0e40e5a | |||
| 679def253d | |||
| 4dc5033c80 | |||
| b3603391eb | |||
| f6a363f7ad | |||
| 3e69361196 | |||
| 04bd5045b9 | |||
| 886bde47d6 | |||
| 254fb82520 | |||
| af884bb638 | |||
| e8e43c10fc | |||
| 9090dbd276 | |||
| f683586623 | |||
| d71d6a679d | |||
| 17eb22dfdb | |||
| c09a788ce3 | |||
| ab32056c3f | |||
| e15049856f | |||
| 16423487fb | |||
| 6b95eb2c74 | |||
| 2b82e9ab02 | |||
| 5fe2cc6350 | |||
| 50739ee890 | |||
| 97ce079488 | |||
| 7045dea284 | |||
| 7887067301 | |||
| 39cfc7aac8 | |||
| 44af8b85ad | |||
| 85594d2056 | |||
| 14cd933969 | |||
| 6550b77c2f | |||
| 7147f23504 | |||
| 94164b873c | |||
| 9cfe7a74bc | |||
| 604aacbae2 | |||
| 04c486d3db | |||
| 152f3cdee1 | |||
| b7890e1e2a | |||
| 8913620aa5 | |||
| 2a103f620d | |||
| 8d0ceff7fa | |||
| ce9f4daec4 | |||
| e639700387 | |||
| 3da344db1f | |||
| 31a35cf845 | |||
| 77c916f747 | |||
| c9dbf990d8 | |||
| ed4d903e69 | |||
| 299451ca62 | |||
| 6319b68c2c | |||
| c37ac4da2b | |||
| 643db92cd1 | |||
| 99795154b5 | |||
| 6cf403da7d | |||
| 4f3e82330b | |||
| 0c401a0112 | |||
| d4b1ae9751 | |||
| 831659966f | |||
| 5f261702a9 | |||
| c2da9b0cb1 | |||
| 239233f4e0 | |||
| b00593ae05 | |||
| b4e6688dfe | |||
| b022babd7e | |||
| 52c7f9f973 | |||
| e0eba8ce21 | |||
| cdd4cee968 | |||
| 1b23edc5c1 | |||
| e5d6006006 | |||
| 18f3809681 | |||
| 1cd87dc994 | |||
| 1e58e04024 | |||
| 408d939664 | |||
| 9b1061719c | |||
| 179539ccba | |||
| 6d73ecb944 | |||
| b981e4fd8b | |||
| 8e660136e0 | |||
| 90ca39b464 | |||
| 63f7e15554 | |||
| ab37216f7d | |||
| 57440a7a45 | |||
| f50059dc7b | |||
| 92fb5cb0c1 | |||
| 5f84630276 | |||
| 22696fe3de | |||
| cd00820546 | |||
| 918153f974 | |||
| 58e67dcc7a | |||
| 940d15c2e6 | |||
| 9ffa46652d | |||
| d45dc53da0 | |||
| 00d1812e8d | |||
| 50dc260fd6 | |||
| bf99aeda92 | |||
| 397822d0db | |||
| 12746a9681 | |||
| 355e21c099 | |||
| 9036b891a8 | |||
| b7e4e91664 | |||
| aabab6dff5 | |||
| 62c2eb4d96 | |||
| c69a6b7640 | |||
| 0521513609 | |||
| a1c5fe2bf2 | |||
| 2d4a77b6f0 | |||
| 9027f72353 | |||
| fe0f292cec | |||
| 06ecd5a1ff | |||
| 8fdaa987e3 | |||
| 15804091b0 | |||
| d8b44a5eae | |||
| 6357dcc6b4 | |||
| 947cddd926 | |||
| 246ff0bc88 | |||
| 339de56407 | |||
| 795bbde459 | |||
| f32bf9e94f | |||
| 8facb7c6e9 | |||
| 92c65aad10 | |||
| 76d6e86fe5 | |||
| e3d7eab4df | |||
| ff8d4b46ef | |||
| 4fb7860a8e | |||
| f188e9518d | |||
| a39419b12a | |||
| 941502d718 | |||
| de146c6370 | |||
| 09efb0d897 | |||
| 8defffabff | |||
| 1b543b1eb8 | |||
| ab17fb08ef | |||
| a4bc3c812d | |||
| c8fcabf4cc | |||
| a961a964ff | |||
| 412de625b2 | |||
| b739736527 | |||
| 2b19f8078e | |||
| 56eabbe2cb | |||
| b0215aae37 | |||
| 86cfa4eded | |||
| bab1e4ff82 | |||
| 6ec59f8654 | |||
| d3459af71f | |||
| 00b5f17f0d | |||
| b8ad833b4b | |||
| fb412576e1 | |||
| d551651d63 | |||
| 4e234c52a3 | |||
| edc718d1d1 | |||
| 42e01e7b8f | |||
| 8edfda979e | |||
| cc3595c3a4 | |||
| 8c72792e31 | |||
| f7ebeb58e2 | |||
| ea4a4f0691 | |||
| 81984e6e97 | |||
| f46e97fc62 | |||
| 7821552761 | |||
| cd8a0fc5f1 | |||
| 30f32f1fb5 | |||
| 9af918b1ef | |||
| 37b8bb4fc0 | |||
| 66edea702e | |||
| 930fb06ca7 | |||
| ca9c67353f | |||
| ea6ad4ac86 | |||
| 6ed8aac6bb | |||
| cfabee4ba7 | |||
| 3a35f9735b | |||
| 05fa8b0994 | |||
| 07f6f93415 | |||
| d2de3a01bb | |||
| c9b7c65ba5 | |||
| 6ad8e68d26 | |||
| b128260eb2 | |||
| ecfaf4d54d | |||
| 72bdee7fbf | |||
| bdb9593c0d | |||
| 1e234754c2 | |||
| 4a4afdadb8 | |||
| 7cadece9a0 | |||
| 724ab6ba69 | |||
| 6370485dcb | |||
| 60d343ca14 | |||
| bdc844f857 | |||
| d49c018f86 | |||
| be2201b5fc | |||
| 9ba1cd1291 | |||
| 22fa9b51e8 | |||
| f781f8d9ea | |||
| 06ecc9c480 | |||
| 50288d91e4 | |||
| 499b4ff445 | |||
| dd0021cd5e | |||
| f5b70dd8b7 | |||
| 8f8ca11203 | |||
| 121d399641 | |||
| 26ae4eb21b | |||
| 52a81dbdc4 | |||
| f924a8bf06 | |||
| c7363f904a | |||
| 53ffe8459f | |||
| 1b702e123e | |||
| 14dccce393 | |||
| d040cc810f | |||
| 224bea2559 | |||
| 777d3e599d | |||
| 7c47bc2656 | |||
| e4d31381d8 | |||
| abf8d75454 | |||
| 2ce152beaf | |||
| 766ed07999 | |||
| ddc2131343 | |||
| b64d8a013d | |||
| e6db59fdde | |||
| 7ea0bbfb21 | |||
| ab041e0ad2 | |||
| 207f742624 | |||
| 68f0b11b6f | |||
| b86c0880b9 | |||
| 75f4a3d92d | |||
| 70fa1341a8 | |||
| 0a55314d37 | |||
| 2198e6123e | |||
| dd37ee0e50 | |||
| 7006ae0420 | |||
| 86458ab32a | |||
| 67ca907e38 | |||
| e15d06bbad | |||
| eb53797174 | |||
| c8c32a78b0 | |||
| 1c032624ac | |||
| 5087ea77b4 | |||
| b6b42e69c3 | |||
| 000a688bb6 | |||
| 3e25b213b1 | |||
| a69cf456ea | |||
| 072b76cb12 | |||
| ca8f54d331 | |||
| 6423feaa94 | |||
| 92ada88ea7 | |||
| 1789ef85d7 | |||
| 42509f115c | |||
| 340a58bda1 | |||
| 08dfd1321c | |||
| 45d324a8c6 | |||
| afa986efd4 | |||
| bc6e8c7813 | |||
| 627fee23d1 | |||
| 27b474f205 | |||
| 418c7eecc7 | |||
| 350250d640 | |||
| 3cc21905af | |||
| c698eb8eb5 | |||
| 463c24beb8 | |||
| a5d1b96ecc | |||
| 63106ebdc1 | |||
| fd36783adb | |||
| 3b5186da53 | |||
| 0140a46090 | |||
| 9c38e1255f | |||
| 663f9d69ff | |||
| d12e5ab801 | |||
| 1d770d85f6 | |||
| 5b00afe45d | |||
| 5b276567ac | |||
| 56566916e3 | |||
| 2c0b4ca3a2 | |||
| 54ffdd32dc | |||
| 64f24bdee9 | |||
| 4706f97bf0 | |||
| 0bdb198d52 | |||
| fc7710821e | |||
| e22a9990ec | |||
| fc7f3a1650 | |||
| 915af9546d | |||
| 54a68640ef | |||
| ec1af7c92b | |||
| a1e20270ad | |||
| 4996986ce6 | |||
| e6de2d4fd9 | |||
| 5347e74a1b | |||
| 0ea5639a22 | |||
| aa3a916d5a | |||
| 6e64b758bf | |||
| 49ef7fc51f | |||
| 0e9a5acdbd | |||
| 4f6e80e940 | |||
| df87cdfa6e | |||
| dee4b36a46 | |||
| d04a26337a | |||
| 2afe8d11d1 | |||
| f31d3b8b21 | |||
| 8a20af9917 | |||
| fc5c2f6213 | |||
| 6c314e148a | |||
| a86d0017a9 | |||
| 4038ed2656 | |||
| 0f4bb47c2f | |||
| 19f7c67ede | |||
| ff7e81ed81 | |||
| 681a102a2b | |||
| ba27f4f2ef | |||
| cbe33a4860 | |||
| 5847e3f269 | |||
| b248dfa01c | |||
| 357aa77e21 | |||
| a44bde6f94 | |||
| 5825bce57d | |||
| 996cdd3155 | |||
| 61cdfcabf8 | |||
| 359a77097c | |||
| 1323d007d3 | |||
| d2215f26ac | |||
| 958e7dbd8f | |||
| 5b10cde59f | |||
| e8f2b9a1c7 | |||
| 0686d1db4a | |||
| 7c284f9ee8 | |||
| dc04273bd7 | |||
| d698be6239 | |||
| e44df27c96 | |||
| b365d4cca1 | |||
| 19d3c948ad | |||
| 4a581039d5 | |||
| 79849fb2b5 | |||
| c116a5abdf | |||
| 8f082730a8 | |||
| b81c4a04db | |||
| e26a05e3ac | |||
| f08a1fb0b4 | |||
| 2a82009ffe | |||
| e851f3a7ed | |||
| 3a865df09e | |||
| bae80e2932 | |||
| 4445e1e78d | |||
| f0e3d3d8e1 | |||
| a313fd1572 | |||
| 927d44d919 | |||
| 3b9a91e8af | |||
| 70b4582bb6 | |||
| 461552b8d0 | |||
| 0f3db37199 | |||
| 67f16b269a | |||
| 25671fa4b4 | |||
| 4eaa04d4a4 | |||
| 7592885b9f | |||
| 508a3fde36 | |||
| f0273224e0 | |||
| 31e833c02e | |||
| a20d915412 | |||
| d3453de73c | |||
| 79a11c4728 | |||
| 24591417ce | |||
| de6d066fc9 | |||
| 6362c896f8 | |||
| 0418e9ca5e | |||
| ba0eeab18c | |||
| 5ef630cbc8 | |||
| 1699d14984 | |||
| 501746a270 | |||
| e6bd1c340f | |||
| 49fc95689d | |||
| 3d84ad19be | |||
| 57aa0cf499 | |||
| 6496dcd7d0 | |||
| 1c066bc69a | |||
| 2f1e37bb7c | |||
| fd3c87abe7 | |||
| af075b8ef8 | |||
| 71d461266e | |||
| 163781557f | |||
| 16e6decebf | |||
| e10c9cc164 | |||
| 7ef994d0cf | |||
| 019c9f0f77 | |||
| 5fec607ebe | |||
| b065b3da51 | |||
| 1337525eb5 | |||
| 30ea52938e | |||
| d43ed33661 | |||
| 03aab33507 | |||
| 420d1cf804 | |||
| 5d901da81b | |||
| 5c783e64c0 | |||
| 2efa5a1869 | |||
| 5bfabe7a52 | |||
| c9c9a58f59 | |||
| 546908fc29 | |||
| 0a17da2da0 | |||
| bc6fd025cb | |||
| 9e49451340 | |||
| 4d185e64ac | |||
| 1fa9a61b3f | |||
| 234552fbf2 | |||
| 8423efb686 | |||
| cd8c15d01e | |||
| 3163cfb1b6 | |||
| 7ae007a1d0 | |||
| 0b52d75415 | |||
| 3a7f4f5848 | |||
| 072f67988f | |||
| c640ddbff7 | |||
| 981ae6bdd1 | |||
| 977e3f317e | |||
| e2ee24598c | |||
| 1be90084ab | |||
| 6ded0f9bb0 | |||
| d60b25e424 | |||
| 874f3918b7 | |||
| 61690a1804 | |||
| 1e43e35857 | |||
| 8c86003220 | |||
| 18c3cd2e66 | |||
| b21f35e914 | |||
| 32e3ed1fda | |||
| 6f87026b0c | |||
| e23edae917 | |||
| bdc867031a | |||
| e96b0f7a73 | |||
| 37fe446a58 | |||
| f03a0bc202 | |||
| bcbc5a4bff | |||
| 0b1e2faba1 | |||
| 4708a5e59c | |||
| 7925469e2f | |||
| 53116d65f1 | |||
| 01917b781b | |||
| d01fc56ea2 | |||
| 9c870a57f0 | |||
| 7e557a06b3 | |||
| fa63038862 | |||
| 8439204cef | |||
| 710df0b87b | |||
| 302f0fc85f | |||
| 241aa3a02c | |||
| a17f3dc3f8 | |||
| 34c0bf58cb | |||
| b64b93fc4a | |||
| a9f43ff466 | |||
| 924d78d3c4 | |||
| fa92bb84ae | |||
| 288d25e17c | |||
| 610fc2ea36 | |||
| 716c0e2b5c | |||
| 945aed7160 | |||
| 1d4d68f6e0 | |||
| 3e1167260d | |||
| 0130f610e9 | |||
| 94941daf4f | |||
| 2bbd723321 | |||
| 608382109c | |||
| bdc5174f68 | |||
| bc869f1be9 | |||
| dc69e44829 | |||
| d236850119 | |||
| 60ec8c9097 | |||
| 42e7a7d2f7 | |||
| e766809e3a | |||
| cb1f0300b9 | |||
| f2a29309f3 | |||
| 6e7b4bab75 | |||
| b4f39e251c | |||
| af6196fe6e | |||
| bca56b2049 | |||
| f4401f172e | |||
| c11b88fee5 | |||
| 88b1b558d7 | |||
| ba6cdc77c9 | |||
| b952772902 | |||
| 7a322154fa | |||
| 0b6ca158ea | |||
| 100cd9a72b | |||
| 98fb810f1f | |||
| c613e558fd | |||
| c324f83826 | |||
| e50421a6ce | |||
| 417b944e1c | |||
| cb8b4b335d | |||
| c0160537b0 | |||
| 4cb7a6424a | |||
| 7d6c79d73e | |||
| 8652737f64 | |||
| d6ac89ea8d | |||
| 2b620cf487 | |||
| f644df481c | |||
| e99ecacb52 | |||
| 3e22dd4b0e | |||
| 19f30ec687 | |||
| 76bee78200 | |||
| ce7455d8f0 | |||
| 5e27ee0f57 | |||
| 84a5c6ebe8 | |||
| ad7e23f64c | |||
| 2738f20eea | |||
| 09362b236c | |||
| 3cfef81877 | |||
| 3a04ae2542 | |||
| dbaf8a319d | |||
| 2fe2a21bfe | |||
| 37639c3582 | |||
| 9a74e6d7bc | |||
| 5d13389827 | |||
| 1c2c6644d5 | |||
| ffcddf30e3 | |||
| 22c92c7b05 | |||
| b569048010 | |||
| f703d9ac89 | |||
| ed6abfd626 | |||
| 50388efc78 | |||
| 7e8fb0fa14 | |||
| 9d70469665 | |||
| a94f0efb5b | |||
| da3a9be7c6 | |||
| cd8ab8e55a | |||
| 1b5b32afad | |||
| 917f784438 | |||
| c2d5d5cca1 | |||
| b435738c34 | |||
| 934905e63a | |||
| d15bb8a232 | |||
| c22bca1f87 | |||
| e04cc9c9d5 | |||
| 7a2bf4e0ac | |||
| 662f5127fa | |||
| fb9117553b | |||
| 9f24e4363f | |||
| 084f9294f2 | |||
| a9f1f9a647 | |||
| 0aed89036b | |||
| df15bbc5f2 | |||
| e6b0bd3817 | |||
| 11cd7153a2 | |||
| f8bc1cb605 | |||
| 8b8eb6f290 | |||
| 056fe21ee2 | |||
| cb0a88df22 | |||
| 298c0431c3 | |||
| 448de9afa5 | |||
| 9401a4b9ad | |||
| ea92ad3785 | |||
| 7aaad5e03e | |||
| 645bf5c839 | |||
| 7638e0e4a1 | |||
| 302b8a7b1b | |||
| dbb9d8a660 | |||
| c51a164042 | |||
| 6b8a62da6e | |||
| 578ca23e75 | |||
| 2e73a90835 | |||
| cc6273fecc | |||
| e63b777916 | |||
| 907567f511 | |||
| e0fd7308be | |||
| b761034aae | |||
| 04d6b1453d | |||
| 11d1754686 | |||
| 25e84decff | |||
| 7d665b203f | |||
| ac62442798 | |||
| 758f96de60 | |||
| db623b9c86 | |||
| c353bf3c96 | |||
| 338b552499 | |||
| 5d73cc1232 | |||
| faddef7a3b | |||
| 2d9bbc8049 | |||
| 64afaa07e7 | |||
| 5cf3ab23b0 | |||
| 3fe926d3a0 | |||
| f71bb682de | |||
| 904f860f3c | |||
| 8f15c9604c | |||
| ff28f5807b | |||
| 6a317366d7 | |||
| dc3e4a2d18 | |||
| 46c4a71ba3 | |||
| f0759acd11 | |||
| 96c7c2966d | |||
| 554e7bce4a | |||
| 70377a8afd | |||
| 51bc6d421a | |||
| be0756f8ba | |||
| 71a2cb4e1b | |||
| 2eba761bed | |||
| 4b5e1a816b | |||
| a92e4b2d67 | |||
| a32404ba98 | |||
| 0a792e4935 | |||
| 05108977e8 | |||
| 25353261d0 | |||
| 4b517263d0 | |||
| 98a65966e7 | |||
| 32dcf9487f | |||
| e3a698f7b1 | |||
| 1631f74700 | |||
| 78c6d71049 | |||
| 0b9ecdeade | |||
| 185a9211f1 | |||
| 24459b2fbf | |||
| 88c8dcb3e8 | |||
| f3a8fedf0a | |||
| 6b8b7c1a62 | |||
| af26828f91 | |||
| f4c43abbf7 | |||
| e84739bff0 | |||
| 66aad0e4f1 | |||
| 77c43c0214 | |||
| 31ae7a642a | |||
| 1bbb21486c | |||
| 316d8ddf9b | |||
| 5d8c21a5ca | |||
| 240ba5c00c | |||
| 554184ec72 | |||
| 7a055a2254 | |||
| 0a807ac1a3 | |||
| 4d831c8c73 | |||
| e6e78a7aae | |||
| 09bef5f41d | |||
| e394efdd85 | |||
| c10b652a2e | |||
| 1594a69d6c | |||
| 9b1e318bd1 | |||
| e292bf1dee | |||
| 55a0c6e97d | |||
| 8b8e4a40a4 | |||
| 8be070998f | |||
| 093f56a03d | |||
| bd9744c27c | |||
| adc25f4420 | |||
| 229fe7c7bf | |||
| 5d571752ae | |||
| 512ddfae6b | |||
| 7b689f94df | |||
| 9eed149b09 | |||
| 0f5d321df8 | |||
| 4e84094fd8 | |||
| 7b9fce0189 |
@@ -0,0 +1,89 @@
|
||||
# find . -type f \( -name "*.c" -o -name "*.h" -o -name "*.cpp" -o -name "*.hpp" -o -name "*.m" -o -name "*.mm" \) -print0 | xargs -0 clang-format -i
|
||||
|
||||
BasedOnStyle: LLVM
|
||||
|
||||
UseTab: Never
|
||||
IndentWidth: 4
|
||||
TabWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
|
||||
ColumnLimit: 0
|
||||
ReflowComments: true
|
||||
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeCloseBracketBracedList: true
|
||||
BraceWrapping:
|
||||
AfterControlStatement: false
|
||||
AfterEnum: false
|
||||
AfterFunction: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
AfterExternBlock: false
|
||||
BeforeElse: false
|
||||
BeforeCatch: false
|
||||
SplitEmptyFunction: false
|
||||
SplitEmptyRecord: false
|
||||
SplitEmptyNamespace: false
|
||||
IndentExternBlock: NoIndent
|
||||
|
||||
AllowShortIfStatementsOnASingleLine: AllIfsAndElse
|
||||
AllowShortLoopsOnASingleLine: true
|
||||
AllowShortBlocksOnASingleLine: true
|
||||
AllowShortFunctionsOnASingleLine: Empty
|
||||
InsertBraces: true
|
||||
|
||||
PointerAlignment: Left
|
||||
DerivePointerAlignment: false
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpacesInParentheses: false
|
||||
SpaceAfterCStyleCast: true
|
||||
SpacesInLineCommentPrefix:
|
||||
Minimum: 1
|
||||
Maximum: 1
|
||||
SpacesInContainerLiterals: true
|
||||
|
||||
SortIncludes: Never
|
||||
IndentPPDirectives: BeforeHash
|
||||
PPIndentWidth: 4
|
||||
|
||||
IndentCaseLabels: true
|
||||
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignOperands: DontAlign
|
||||
|
||||
BinPackParameters: false
|
||||
BinPackArguments: false
|
||||
AlignAfterOpenBracket: DontAlign
|
||||
BracedInitializerIndentWidth: 4
|
||||
Cpp11BracedListStyle: Block
|
||||
|
||||
ForEachMacros:
|
||||
- FF_LIST_FOR_EACH
|
||||
- yyjson_obj_foreach
|
||||
- yyjson_arr_foreach
|
||||
- yyjson_mut_obj_foreach
|
||||
- yyjson_mut_arr_foreach
|
||||
|
||||
AttributeMacros:
|
||||
- FF_A_FALLTHROUGH
|
||||
- FF_A_DEPRECATED
|
||||
- FF_A_CLEANUP
|
||||
- FF_A_NODISCARD
|
||||
- FF_A_PRINTF
|
||||
- FF_A_SCANF
|
||||
- FF_A_NONNULL
|
||||
- FF_A_RETURNS_NONNULL
|
||||
- FF_A_UNUSED
|
||||
- FF_A_PACKED
|
||||
- FF_A_WEAK_IMPORT
|
||||
|
||||
MaxEmptyLinesToKeep: 1
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
|
||||
---
|
||||
Language: ObjC
|
||||
ObjCBlockIndentWidth: 4
|
||||
ObjCSpaceAfterProperty: true
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
ObjCBreakBeforeNestedBlockParam: true
|
||||
@@ -0,0 +1,3 @@
|
||||
src/3rdparty/**
|
||||
build/**
|
||||
src/logo/builtin.c
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
[codespell]
|
||||
check-filenames =
|
||||
builtin = clear,rare,usage,informal
|
||||
skip = */.git,*/cmake-build-*,*/.idea,*/completions,*/presets,*/screenshots,*/tests,*/3rdparty,*/logo/ascii,./src/detection/gpu/asahi_drm.h
|
||||
ignore-words-list = iterm,compiletime,unknwn,pengwin,siduction,master,slave,sur,doas,conexant,ags,bu
|
||||
skip = */.git,*/cmake-build-*,*/.idea,*/completions,*/presets,*/screenshots,*/tests,*/3rdparty,*/logo/ascii,./src/detection/gpu/asahi_drm.h,./src/detection/cpu/cpu_x86.c,./src/detection/gpu/gpu_bsddrm.c,./src/detection/displayserver/linux/wayland/*-protocol.*,./build,./build-*,./build_*,./src/common/impl/genconfig.c
|
||||
ignore-words-list = iterm,compiletime,unknwn,pengwin,siduction,master,slave,sur,doas,conexant,ags,bu,renderD,SME,Carmel,kinda,symbole,connexion,comando,processus,lokale,adres,titel,som,environnement,Sistem,Lokal,Lokal,Sistem,Paket,Hava
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
github: LinusDierheimer
|
||||
ko_fi: carterli
|
||||
custom: https://paypal.me/zhangsongcui
|
||||
@@ -16,6 +16,15 @@ body:
|
||||
options:
|
||||
- label: I have checked the FAQ but the issue is not covered
|
||||
required: true
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Not a known issue
|
||||
description: Please check if the issue is already known and being worked on.
|
||||
options:
|
||||
- label: I have checked the existing issues but the issue is not covered
|
||||
required: true
|
||||
- label: My issue is not about crashing on Fedora and KDE 6.6
|
||||
required: true
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: "### General description of the bug"
|
||||
|
||||
@@ -6,33 +6,67 @@ body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Tip: A logo can be displayed by fastfetch without getting into fastfetch's official repo.
|
||||
For highly customized logo for personal use, it's recommended to keep it locally.
|
||||
Please refer to https://github.com/fastfetch-cli/fastfetch/wiki/Migrate-Neofetch-Logo-To-Fastfetch
|
||||
> [!WARNING]
|
||||
> **NB:** If your logo request does not meet the basic requirements outlined in this template, the issue may be closed at any time without any further explanation.
|
||||
|
||||
**Tip:** You can display a logo in fastfetch without adding it to fastfetch's official repo.
|
||||
For highly customized, personal logos, we recommend keeping them locally.
|
||||
You can test your logo locally using:
|
||||
`fastfetch -l /path/to/logo.txt --logo-color-1 white --logo-color-2 red`
|
||||
Please refer to the [Migration Guide](https://github.com/fastfetch-cli/fastfetch/wiki/Migrate-Neofetch-Logo-To-Fastfetch) for details on color placeholders (`$1`, `$2`, etc.).
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: OS
|
||||
description: Paste content of `/etc/os-release` and `/etc/lsb-release` here. If none of these files exist, describe a way to identify the distro
|
||||
description: Paste the contents of `/etc/os-release` (specifically the `ID` and `PRETTY_NAME` fields). If neither file exists, describe how to identify the distro.
|
||||
placeholder: cat /etc/os-release
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Public repository URL
|
||||
description: A public repository is required to verify the request. Please provide a link to the repository where the distro is developed.
|
||||
placeholder: https://github.com/example/distro
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Distro Website
|
||||
description: To help prevent spam and verify the request, a distro website is required, and a downloadable ISO must be available on that site.
|
||||
placeholder: https://example.com
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: ASCII Art
|
||||
description: An ASCII logo should not take up too much space (smaller than 50x20 characters). Please also include the color codes if not available in `os-release`
|
||||
placeholder: Paste ASCII art here
|
||||
description: |
|
||||
The ASCII logo should not take up too much space (smaller than 50x20 characters, W x H).
|
||||
**Important:** Fastfetch uses `$1`, `$2`, `$3` etc. for color placeholders. Do NOT use hardcoded ANSI escape codes (like `\033[38;2...m`) or Neofetch's `${c1}` syntax.
|
||||
Take <https://github.com/fastfetch-cli/fastfetch/tree/dev/src/logo/ascii> as examples.
|
||||
placeholder: Paste ASCII art with $1, $2 placeholders here
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Original Image
|
||||
description: If the ASCII art is based on an image, please provide a link to the original image
|
||||
placeholder: Image URL or distro website URL
|
||||
label: Original Image URL
|
||||
description: If the ASCII art is based on an image, please provide a link to the original image file.
|
||||
placeholder: Image URL from the distro website mentioned above
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Checklist
|
||||
options:
|
||||
- label: The ASCII art is smaller than 50x20 characters (width x height)
|
||||
- label: My distro has reached a stable state (out of beta, alpha, RC).
|
||||
required: true
|
||||
- label: The ASCII art contains color codes, or the color codes are available in `os-release`
|
||||
- label: The ASCII art is smaller than 50x20 characters (W x H).
|
||||
required: true
|
||||
- label: The ASCII art uses `$N` color placeholders (or colors are natively available in `os-release`).
|
||||
required: true
|
||||
- label: The ASCII art has no unnecessary trailing spaces at the end of lines.
|
||||
required: true
|
||||
- label: I promise that I will send a removal request if the distro is discontinued.
|
||||
required: true
|
||||
|
||||
@@ -0,0 +1,405 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Fastfetch · Benchmark</title>
|
||||
<style>
|
||||
:root {
|
||||
color-scheme: light;
|
||||
--page: #f5f7fb;
|
||||
--card: #fff;
|
||||
--text: #172033;
|
||||
--muted: #64748b;
|
||||
--border: #dbe3ef;
|
||||
--accent: #2563eb;
|
||||
--accent-soft: #dbeafe;
|
||||
--chart-text: #334155;
|
||||
--chart-grid: #cbd5e1;
|
||||
}
|
||||
:root[data-theme="dark"] {
|
||||
color-scheme: dark;
|
||||
--page: #0f172a; --card: #172033; --text: #e5edf8; --muted: #9aabc1; --border: #334155; --accent-soft: #1e3a8a;
|
||||
--chart-text: #f1f5f9;
|
||||
--chart-grid: #475569;
|
||||
}
|
||||
* { box-sizing: border-box; }
|
||||
body { max-width: 1440px; margin: 0 auto; padding: 2.5rem 1.25rem 4rem; background: var(--page); color: var(--text); font: 16px/1.5 system-ui, -apple-system, sans-serif; }
|
||||
header { margin-bottom: 1.75rem; }
|
||||
.header-row { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
|
||||
h1 { margin: 0; font-size: clamp(2rem, 4vw, 3rem); letter-spacing: -.04em; }
|
||||
h2 { margin: 0; font-size: 1.25rem; }
|
||||
p { color: var(--muted); }
|
||||
.intro { margin: .6rem 0 1rem; }
|
||||
.links a { color: var(--accent); font-weight: 600; text-decoration: none; }
|
||||
.links a:hover { text-decoration: underline; }
|
||||
.theme-toggle, .fullscreen { border: 1px solid var(--border); border-radius: .55rem; padding: .5rem .8rem; background: var(--card); color: var(--text); cursor: pointer; font: inherit; font-weight: 600; }
|
||||
.theme-toggle:hover, .fullscreen:hover { border-color: var(--accent); color: var(--accent); }
|
||||
.tabs { display: flex; flex-wrap: wrap; gap: .6rem; margin: 1.5rem 0; padding: .35rem; border: 1px solid var(--border); border-radius: .8rem; background: var(--card); }
|
||||
.tab { border: 0; border-radius: .55rem; padding: .65rem 1.15rem; background: transparent; color: var(--muted); cursor: pointer; font: inherit; font-weight: 700; }
|
||||
.tab:hover, .tab[aria-selected="true"] { background: var(--accent); color: #fff; }
|
||||
.tab-panel[hidden] { display: none; }
|
||||
.platform-title { display: flex; align-items: center; gap: .65rem; margin: 1.5rem 0 1rem; }
|
||||
.platform-title::before { content: ''; width: .35rem; height: 1.4rem; border-radius: 1rem; background: var(--accent); }
|
||||
.charts { display: flex; flex-direction: column; gap: 1.25rem; }
|
||||
.chart { min-width: 0; padding: 1.25rem; border: 1px solid var(--border); border-radius: 1rem; background: var(--card); box-shadow: 0 8px 28px #0f172a0c; }
|
||||
.chart:fullscreen { overflow: auto; padding: 2rem; background: var(--page); }
|
||||
.chart:fullscreen .canvas-wrap { height: calc(100vh - 13rem); }
|
||||
.chart-header { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; margin-bottom: .75rem; }
|
||||
.chart-header span { color: var(--muted); font-size: .85rem; }
|
||||
.canvas-wrap { position: relative; height: 360px; }
|
||||
.chart-actions { display: flex; align-items: center; gap: .75rem; }
|
||||
.legend-actions { display: flex; flex-wrap: wrap; gap: .45rem; margin-top: 1rem; }
|
||||
.legend-action { border: 1px solid var(--border); border-radius: .45rem; padding: .35rem .6rem; background: var(--card); color: var(--muted); cursor: pointer; font: inherit; font-size: .8rem; }
|
||||
.legend-action:hover { border-color: var(--accent); color: var(--accent); }
|
||||
.legend { display: flex; flex-wrap: wrap; gap: .35rem .9rem; margin-top: 1rem; }
|
||||
.legend-item { display: inline-flex; align-items: center; gap: .4rem; border: 0; padding: .15rem 0; background: transparent; color: var(--text); cursor: pointer; font: inherit; font-size: .85rem; }
|
||||
.legend-item.is-hidden { color: var(--muted); }
|
||||
.legend-swatch { width: .75rem; height: .75rem; border-radius: 50%; }
|
||||
.legend-item.is-hidden .legend-swatch { opacity: .35; }
|
||||
.chart-tooltip { position: fixed; z-index: 1000; pointer-events: none; width: min(90vw, 900px); max-height: calc(100vh - 24px); overflow: hidden; padding: .7rem .85rem; border: 1px solid var(--border); border-radius: .6rem; background: var(--card); color: var(--text); box-shadow: 0 10px 30px #0f172a33; font-size: .8rem; opacity: 0; transition: opacity .1s ease; }
|
||||
.chart-tooltip-title { margin-bottom: .35rem; font-weight: 700; white-space: normal; overflow-wrap: anywhere; }
|
||||
.chart-tooltip-body { max-height: calc(100vh - 76px); overflow: auto; columns: 220px auto; column-gap: 1.5rem; }
|
||||
.chart-tooltip-row { display: flex; align-items: center; gap: .45rem; break-inside: avoid; white-space: nowrap; }
|
||||
.chart-tooltip-swatch { width: .55rem; height: .55rem; border-radius: 50%; flex: 0 0 auto; }
|
||||
.empty { padding: 2rem 0; color: var(--muted); }
|
||||
</style>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js/dist/chart.umd.min.js"></script>
|
||||
<script src="data.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<div class="header-row">
|
||||
<h1>Fastfetch Benchmark</h1>
|
||||
<button id="theme-toggle" class="theme-toggle" type="button"></button>
|
||||
</div>
|
||||
<p class="intro">Performance history grouped by CPU family. Each chart contains all modules and total process time for one operating system and architecture. Module curves are available from the legend and hidden by default.</p>
|
||||
<p class="links"><a href="data.js">Download raw benchmark data</a></p>
|
||||
</header>
|
||||
<nav id="tabs" class="tabs" aria-label="CPU architecture"></nav>
|
||||
<main id="panels"></main>
|
||||
<script>
|
||||
(() => {
|
||||
const benchmarkData = window.BENCHMARK_DATA || {};
|
||||
const entries = Object.values(benchmarkData.entries || {}).flat();
|
||||
const groups = new Map();
|
||||
|
||||
function architectureFamily(arch) {
|
||||
const normalized = arch.toLowerCase();
|
||||
if (/^(amd64|x86_64|x86|i[3-6]86)$/.test(normalized)) return 'Intel';
|
||||
if (/^(aarch64|arm64|armv[5-8].*|arm)$/.test(normalized)) return 'ARM';
|
||||
return 'Other';
|
||||
}
|
||||
|
||||
function parseName(name) {
|
||||
let match = name.match(/^fastfetch (linux|macos|windows) ([^ ]+) (module .+|total process time)$/i);
|
||||
if (match) {
|
||||
return { platform: match[1].toLowerCase(), arch: match[2], metric: match[3] };
|
||||
}
|
||||
|
||||
// Keep older macOS records visible while new records use the platform field.
|
||||
match = name.match(/^fastfetch ([^ ]+) (module .+|total process time)$/i);
|
||||
return match ? { platform: 'macos', arch: match[1], metric: match[2] } : null;
|
||||
}
|
||||
|
||||
function entryMetadata(entry) {
|
||||
const raw = entry.commit && entry.commit.timestamp || entry.date;
|
||||
const date = new Date(raw);
|
||||
return {
|
||||
date: Number.isNaN(date.valueOf()) ? String(entry.date || '') : date.toISOString(),
|
||||
sha: entry.commit && entry.commit.id ? entry.commit.id : 'unknown'
|
||||
};
|
||||
}
|
||||
|
||||
for (const entry of entries) {
|
||||
const metricsByGroup = new Map();
|
||||
for (const bench of entry.benches || []) {
|
||||
const parsed = parseName(bench.name);
|
||||
if (!parsed) continue;
|
||||
const key = `${parsed.platform} ${parsed.arch}`;
|
||||
if (!metricsByGroup.has(key)) metricsByGroup.set(key, new Map());
|
||||
metricsByGroup.get(key).set(parsed.metric, bench.value);
|
||||
}
|
||||
|
||||
for (const [key, metrics] of metricsByGroup) {
|
||||
if (!groups.has(key)) groups.set(key, []);
|
||||
groups.get(key).push({ ...entryMetadata(entry), metrics });
|
||||
}
|
||||
}
|
||||
|
||||
const colors = [
|
||||
'#2563eb', '#dc2626', '#16a34a', '#9333ea', '#ea580c', '#0891b2',
|
||||
'#db2777', '#65a30d', '#4f46e5', '#ca8a04', '#0f766e', '#be123c'
|
||||
];
|
||||
const tabs = document.getElementById('tabs');
|
||||
const panels = document.getElementById('panels');
|
||||
const root = document.documentElement;
|
||||
const themeToggle = document.getElementById('theme-toggle');
|
||||
const savedTheme = localStorage.getItem('fastfetch-benchmark-theme');
|
||||
let theme = savedTheme || (matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
|
||||
const chartsByInstance = [];
|
||||
|
||||
function chartColors() {
|
||||
const styles = getComputedStyle(root);
|
||||
return {
|
||||
text: styles.getPropertyValue('--chart-text').trim(),
|
||||
grid: styles.getPropertyValue('--chart-grid').trim()
|
||||
};
|
||||
}
|
||||
|
||||
function externalTooltipHandler(context) {
|
||||
const { chart, tooltip } = context;
|
||||
let tooltipElement = chart.canvas.parentNode.querySelector('.chart-tooltip');
|
||||
if (!tooltipElement) {
|
||||
tooltipElement = document.createElement('div');
|
||||
tooltipElement.className = 'chart-tooltip';
|
||||
chart.canvas.parentNode.appendChild(tooltipElement);
|
||||
}
|
||||
|
||||
if (tooltip.opacity === 0) {
|
||||
tooltipElement.style.opacity = '0';
|
||||
return;
|
||||
}
|
||||
|
||||
tooltipElement.replaceChildren();
|
||||
const title = document.createElement('div');
|
||||
title.className = 'chart-tooltip-title';
|
||||
const row = chart._benchmarkRows[tooltip.dataPoints[0].dataIndex];
|
||||
title.textContent = `${new Date(row.date).toLocaleString()} · ${row.sha}`;
|
||||
tooltipElement.appendChild(title);
|
||||
const bodyElement = document.createElement('div');
|
||||
bodyElement.className = 'chart-tooltip-body';
|
||||
for (const body of [...tooltip.dataPoints].sort((a, b) => b.parsed.y - a.parsed.y)) {
|
||||
const item = document.createElement('div');
|
||||
item.className = 'chart-tooltip-row';
|
||||
const swatch = document.createElement('span');
|
||||
swatch.className = 'chart-tooltip-swatch';
|
||||
swatch.style.background = body.dataset.borderColor;
|
||||
const value = document.createElement('span');
|
||||
value.textContent = `${body.dataset.label}: ${body.formattedValue} ms`;
|
||||
item.append(swatch, value);
|
||||
bodyElement.appendChild(item);
|
||||
}
|
||||
tooltipElement.appendChild(bodyElement);
|
||||
|
||||
const canvasRect = chart.canvas.getBoundingClientRect();
|
||||
const margin = 12;
|
||||
let left = canvasRect.left + tooltip.caretX + margin;
|
||||
let top = canvasRect.top + tooltip.caretY + margin;
|
||||
tooltipElement.style.left = `${left}px`;
|
||||
tooltipElement.style.top = `${top}px`;
|
||||
tooltipElement.style.opacity = '0';
|
||||
const tooltipRect = tooltipElement.getBoundingClientRect();
|
||||
if (left + tooltipRect.width > window.innerWidth - margin) left = canvasRect.left + tooltip.caretX - tooltipRect.width - margin;
|
||||
if (top + tooltipRect.height > window.innerHeight - margin) top = canvasRect.top + tooltip.caretY - tooltipRect.height - margin;
|
||||
tooltipElement.style.left = `${Math.max(margin, left)}px`;
|
||||
tooltipElement.style.top = `${Math.max(margin, top)}px`;
|
||||
tooltipElement.style.opacity = '1';
|
||||
}
|
||||
|
||||
function updateTheme() {
|
||||
root.dataset.theme = theme;
|
||||
themeToggle.textContent = theme === 'dark' ? '☀ Light mode' : '☾ Dark mode';
|
||||
themeToggle.setAttribute('aria-label', `Switch to ${theme === 'dark' ? 'light' : 'dark'} mode`);
|
||||
const colors = chartColors();
|
||||
Chart.defaults.color = colors.text;
|
||||
Chart.defaults.borderColor = colors.grid;
|
||||
for (const chart of chartsByInstance) {
|
||||
chart.options.scales.x.title.color = colors.text;
|
||||
chart.options.scales.x.ticks.color = colors.text;
|
||||
chart.options.scales.x.grid.color = colors.grid;
|
||||
chart.options.scales.y.title.color = colors.text;
|
||||
chart.options.scales.y.ticks.color = colors.text;
|
||||
chart.options.scales.y.grid.color = colors.grid;
|
||||
chart.update();
|
||||
}
|
||||
}
|
||||
themeToggle.addEventListener('click', () => {
|
||||
theme = theme === 'dark' ? 'light' : 'dark';
|
||||
localStorage.setItem('fastfetch-benchmark-theme', theme);
|
||||
updateTheme();
|
||||
});
|
||||
updateTheme();
|
||||
const families = new Map();
|
||||
|
||||
for (const [key, rows] of groups) {
|
||||
const arch = key.slice(key.lastIndexOf(' ') + 1);
|
||||
const family = architectureFamily(arch);
|
||||
if (!families.has(family)) families.set(family, []);
|
||||
families.get(family).push({ key, rows });
|
||||
}
|
||||
|
||||
const familyOrder = ['Intel', 'ARM', 'Other'];
|
||||
const availableFamilies = familyOrder.filter(family => families.has(family));
|
||||
|
||||
for (const [index, family] of availableFamilies.entries()) {
|
||||
const tab = document.createElement('button');
|
||||
const panelId = `panel-${family.toLowerCase()}`;
|
||||
tab.className = 'tab';
|
||||
tab.type = 'button';
|
||||
tab.id = `tab-${family.toLowerCase()}`;
|
||||
tab.setAttribute('role', 'tab');
|
||||
tab.textContent = family;
|
||||
tab.setAttribute('aria-controls', panelId);
|
||||
tab.setAttribute('aria-selected', index === 0 ? 'true' : 'false');
|
||||
tabs.appendChild(tab);
|
||||
|
||||
const panel = document.createElement('section');
|
||||
panel.className = 'tab-panel';
|
||||
panel.id = panelId;
|
||||
panel.setAttribute('role', 'tabpanel');
|
||||
panel.hidden = index !== 0;
|
||||
panel.setAttribute('aria-labelledby', tab.id);
|
||||
const title = document.createElement('h2');
|
||||
title.className = 'platform-title';
|
||||
title.textContent = `${family} processors`;
|
||||
panel.appendChild(title);
|
||||
const chartGrid = document.createElement('div');
|
||||
chartGrid.className = 'charts';
|
||||
panel.appendChild(chartGrid);
|
||||
panels.appendChild(panel);
|
||||
|
||||
tab.addEventListener('click', () => {
|
||||
for (const otherTab of tabs.children) otherTab.setAttribute('aria-selected', otherTab === tab ? 'true' : 'false');
|
||||
for (const otherPanel of panels.children) otherPanel.hidden = otherPanel !== panel;
|
||||
});
|
||||
|
||||
for (const { key, rows } of families.get(family).sort((a, b) => a.key.localeCompare(b.key))) {
|
||||
rows.sort((a, b) => a.date.localeCompare(b.date));
|
||||
const metrics = [...new Set(rows.flatMap(row => [...row.metrics.keys()]))].sort((a, b) => {
|
||||
if (a === 'total process time') return -1;
|
||||
if (b === 'total process time') return 1;
|
||||
return a.localeCompare(b);
|
||||
});
|
||||
const section = document.createElement('article');
|
||||
section.className = 'chart';
|
||||
const chartHeader = document.createElement('div');
|
||||
chartHeader.className = 'chart-header';
|
||||
const chartTitle = document.createElement('h2');
|
||||
chartTitle.textContent = key;
|
||||
const chartActions = document.createElement('div');
|
||||
chartActions.className = 'chart-actions';
|
||||
const chartHint = document.createElement('span');
|
||||
chartHint.textContent = `${rows.length} run${rows.length === 1 ? '' : 's'}`;
|
||||
const fullscreen = document.createElement('button');
|
||||
fullscreen.className = 'fullscreen';
|
||||
fullscreen.type = 'button';
|
||||
fullscreen.textContent = '⛶ Fullscreen';
|
||||
fullscreen.addEventListener('click', () => {
|
||||
if (document.fullscreenElement) document.exitFullscreen();
|
||||
else section.requestFullscreen();
|
||||
});
|
||||
chartActions.append(chartHint, fullscreen);
|
||||
chartHeader.append(chartTitle, chartActions);
|
||||
const canvasWrap = document.createElement('div');
|
||||
canvasWrap.className = 'canvas-wrap';
|
||||
const canvas = document.createElement('canvas');
|
||||
canvasWrap.appendChild(canvas);
|
||||
section.append(chartHeader, canvasWrap);
|
||||
chartGrid.appendChild(section);
|
||||
|
||||
const colorsForChart = chartColors();
|
||||
const chart = new Chart(canvas, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: rows.map(row => row.sha.slice(0, 7)),
|
||||
datasets: metrics.map((metric, index) => ({
|
||||
label: metric,
|
||||
data: rows.map(row => row.metrics.has(metric) ? row.metrics.get(metric) : null),
|
||||
borderColor: colors[index % colors.length],
|
||||
backgroundColor: colors[index % colors.length],
|
||||
pointRadius: 3,
|
||||
tension: 0.2,
|
||||
spanGaps: true,
|
||||
hidden: metric !== 'total process time'
|
||||
}))
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
interaction: { mode: 'index', intersect: false },
|
||||
plugins: {
|
||||
legend: { display: false },
|
||||
tooltip: {
|
||||
enabled: false,
|
||||
external: externalTooltipHandler,
|
||||
callbacks: {
|
||||
title: tooltipItems => {
|
||||
const row = rows[tooltipItems[0].dataIndex];
|
||||
return `${row.date} · ${row.sha}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
x: { title: { display: true, text: 'Date', color: colorsForChart.text }, ticks: { color: colorsForChart.text }, grid: { color: colorsForChart.grid } },
|
||||
y: { beginAtZero: true, title: { display: true, text: 'Milliseconds', color: colorsForChart.text }, ticks: { color: colorsForChart.text }, grid: { color: colorsForChart.grid } }
|
||||
}
|
||||
}
|
||||
});
|
||||
chart._benchmarkRows = rows;
|
||||
chartsByInstance.push(chart);
|
||||
const legendActions = document.createElement('div');
|
||||
legendActions.className = 'legend-actions';
|
||||
const legend = document.createElement('div');
|
||||
legend.className = 'legend';
|
||||
const legendItems = [];
|
||||
|
||||
function refreshLegend() {
|
||||
legendItems.forEach((item, metricIndex) => {
|
||||
item.classList.toggle('is-hidden', !chart.isDatasetVisible(metricIndex));
|
||||
});
|
||||
}
|
||||
|
||||
function setAllLegends(visible) {
|
||||
metrics.forEach((metric, metricIndex) => chart.setDatasetVisibility(metricIndex, visible));
|
||||
refreshLegend();
|
||||
chart.update();
|
||||
}
|
||||
|
||||
function addLegendAction(label, action) {
|
||||
const button = document.createElement('button');
|
||||
button.className = 'legend-action';
|
||||
button.type = 'button';
|
||||
button.textContent = label;
|
||||
button.addEventListener('click', action);
|
||||
legendActions.appendChild(button);
|
||||
}
|
||||
|
||||
addLegendAction('Show all', () => setAllLegends(true));
|
||||
addLegendAction('Toggle all', () => {
|
||||
metrics.forEach((metric, metricIndex) => chart.setDatasetVisibility(metricIndex, !chart.isDatasetVisible(metricIndex)));
|
||||
refreshLegend();
|
||||
chart.update();
|
||||
});
|
||||
addLegendAction('Reset', () => {
|
||||
metrics.forEach((metric, metricIndex) => chart.setDatasetVisibility(metricIndex, metric === 'total process time'));
|
||||
refreshLegend();
|
||||
chart.update();
|
||||
});
|
||||
|
||||
metrics.forEach((metric, metricIndex) => {
|
||||
const item = document.createElement('button');
|
||||
item.className = `legend-item${chart.isDatasetVisible(metricIndex) ? '' : ' is-hidden'}`;
|
||||
item.type = 'button';
|
||||
item.innerHTML = `<span class="legend-swatch" style="background:${colors[metricIndex % colors.length]}"></span>${metric}`;
|
||||
item.addEventListener('click', () => {
|
||||
chart.setDatasetVisibility(metricIndex, !chart.isDatasetVisible(metricIndex));
|
||||
item.classList.toggle('is-hidden', !chart.isDatasetVisible(metricIndex));
|
||||
chart.update();
|
||||
});
|
||||
legendItems.push(item);
|
||||
legend.appendChild(item);
|
||||
});
|
||||
section.append(legendActions, legend);
|
||||
}
|
||||
}
|
||||
|
||||
if (!groups.size) {
|
||||
tabs.hidden = true;
|
||||
panels.innerHTML = '<p class="empty">No benchmark data available.</p>';
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,18 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
day: "sunday"
|
||||
cooldown:
|
||||
default-days: 7
|
||||
open-pull-requests-limit: 10
|
||||
commit-message:
|
||||
prefix: "CI"
|
||||
labels:
|
||||
- "ci"
|
||||
groups:
|
||||
github-actions:
|
||||
patterns:
|
||||
- "*"
|
||||
@@ -0,0 +1,30 @@
|
||||
## Summary
|
||||
|
||||
<!-- Briefly describe what this PR does. -->
|
||||
|
||||
## Related issue (required for new logos for new distros)
|
||||
|
||||
<!--
|
||||
If this PR adds a new logo, it MUST be linked to an existing "Logo Request" issue and has the requests fulfilled.
|
||||
|
||||
Use one of the following formats so GitHub links it properly:
|
||||
- Closes #1234
|
||||
- Fixes #1234
|
||||
- Resolves #1234
|
||||
|
||||
PRs that add logos without an associated Logo Request issue will not be accepted.
|
||||
-->
|
||||
|
||||
Closes #
|
||||
|
||||
## Changes
|
||||
|
||||
-
|
||||
|
||||
## Screenshots
|
||||
|
||||
<!-- Required if this PR introduces visual changes. -->
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] I have tested my changes locally.
|
||||
@@ -0,0 +1,55 @@
|
||||
name: Reusable Benchmark
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
benchmark:
|
||||
runs-on: ubuntu-latest
|
||||
concurrency:
|
||||
group: benchmark
|
||||
cancel-in-progress: false
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: download benchmark data
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
pattern: benchmark-*
|
||||
path: benchmarks
|
||||
|
||||
- name: merge benchmark data
|
||||
run: jq -s 'add' benchmarks/*/benchmark.json > benchmark.json
|
||||
|
||||
- name: save benchmark dashboard
|
||||
run: cp .github/benchmark-index.html "$RUNNER_TEMP/benchmark-index.html"
|
||||
|
||||
- name: store benchmark result
|
||||
uses: benchmark-action/github-action-benchmark@52576c92bccf6ac60c8223ec7eb2565637cae9ba # v1.22.1
|
||||
with:
|
||||
name: Fastfetch
|
||||
tool: customSmallerIsBetter
|
||||
output-file-path: benchmark.json
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
ref: ${{ github.sha }}
|
||||
auto-push: true
|
||||
summary-always: true
|
||||
benchmark-data-dir-path: dev/bench
|
||||
|
||||
- name: publish benchmark dashboard
|
||||
run: |
|
||||
git fetch origin gh-pages
|
||||
git switch --force-create gh-pages FETCH_HEAD
|
||||
mkdir -p dev/bench
|
||||
cp "$RUNNER_TEMP/benchmark-index.html" dev/bench/index.html
|
||||
git config user.name github-action-benchmark
|
||||
git config user.email github@users.noreply.github.com
|
||||
git add dev/bench/index.html
|
||||
if ! git diff --cached --quiet; then
|
||||
git commit -m "Update benchmark dashboard"
|
||||
git push origin gh-pages
|
||||
fi
|
||||
@@ -0,0 +1,66 @@
|
||||
name: Reusable DragonFly amd64
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
shell: cpa.sh {0}
|
||||
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Start VM
|
||||
uses: cross-platform-actions/action@faa0c6197e94aacf1c5956460152c8380d3560a5 # v1.5.0
|
||||
with:
|
||||
operating_system: dragonflybsd
|
||||
version: '6.4.2'
|
||||
shell: bash
|
||||
cpu_count: 4
|
||||
|
||||
- name: Show system info
|
||||
run: |
|
||||
uname -a
|
||||
pkg --version
|
||||
|
||||
- name: Update and install dependencies
|
||||
run: |
|
||||
sudo pkg update
|
||||
sudo pkg install -y llvm cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm glib dconf dbus sqlite3-tcl egl opencl ocl-icd v4l_compat chafa libelf lua54 libva libvdpau
|
||||
|
||||
- name: CMake configuration
|
||||
run: env CC=clang cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -DCMAKE_BUILD_TYPE=${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }} .
|
||||
|
||||
- name: CMake build
|
||||
run: cmake --build . --target package --verbose -j4
|
||||
|
||||
- name: List features
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
- name: Run normal
|
||||
run: time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
|
||||
- name: Run json
|
||||
run: time ./fastfetch -c presets/ci.jsonc --format json
|
||||
|
||||
- name: Run flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
- name: Run ldd
|
||||
run: ldd fastfetch
|
||||
|
||||
- name: Run tests
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: fastfetch-dragonfly-amd64
|
||||
path: ./fastfetch-*.*
|
||||
@@ -0,0 +1,67 @@
|
||||
name: Reusable FreeBSD amd64
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
shell: cpa.sh {0}
|
||||
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Start VM
|
||||
uses: cross-platform-actions/action@faa0c6197e94aacf1c5956460152c8380d3560a5 # v1.5.0
|
||||
with:
|
||||
operating_system: freebsd
|
||||
version: '15.1'
|
||||
shell: bash
|
||||
cpu_count: 4
|
||||
|
||||
- name: Show system info
|
||||
run: |
|
||||
uname -a
|
||||
freebsd-version
|
||||
pkg -v
|
||||
|
||||
- name: Update and install dependencies
|
||||
run: |
|
||||
sudo pkg update
|
||||
sudo pkg install -y cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm glib dconf dbus sqlite3 egl opencl ocl-icd v4l_compat chafa lua54 libva libvdpau
|
||||
|
||||
- name: CMake configuration
|
||||
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -DCMAKE_BUILD_TYPE=${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }} .
|
||||
|
||||
- name: CMake build
|
||||
run: cmake --build . --target package --verbose -j4
|
||||
|
||||
- name: List features
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
- name: Run normal
|
||||
run: time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
|
||||
- name: Run json
|
||||
run: time ./fastfetch -c presets/ci.jsonc --format json
|
||||
|
||||
- name: Run flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
- name: Run ldd
|
||||
run: ldd fastfetch
|
||||
|
||||
- name: Run tests
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: fastfetch-freebsd-amd64
|
||||
path: ./fastfetch-*.*
|
||||
@@ -0,0 +1,60 @@
|
||||
name: Reusable Haiku amd64
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
shell: cpa.sh {0}
|
||||
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Start VM
|
||||
uses: cross-platform-actions/action@faa0c6197e94aacf1c5956460152c8380d3560a5 # v1.5.0
|
||||
with:
|
||||
operating_system: haiku
|
||||
version: 'r1beta6'
|
||||
shell: bash
|
||||
cpu_count: 4
|
||||
|
||||
- name: Show system info
|
||||
run: uname -a
|
||||
|
||||
- name: Install dependencies
|
||||
shell: cpa.sh {0} --reboot
|
||||
run: pkgman install -y git dbus_devel mesa_devel libelf_devel imagemagick_devel opencl_headers ocl_icd_devel vulkan_devel zlib_devel chafa_devel cmake llvm22_clang ninja pkgconfig python3.10 lua || pkgman install -y git dbus_devel mesa_devel libelf_devel imagemagick_devel opencl_headers ocl_icd_devel vulkan_devel zlib_devel chafa_devel cmake llvm22_clang ninja pkgconfig python3.10 lua
|
||||
|
||||
- name: CMake configuration
|
||||
run: CC=clang CXX=clang++ cmake -GNinja -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -DCMAKE_BUILD_TYPE=${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }} .
|
||||
|
||||
- name: CMake build
|
||||
run: cmake --build . --target package --verbose -j4
|
||||
|
||||
- name: List features
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
- name: Run normal
|
||||
run: time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
|
||||
- name: Run json
|
||||
run: time ./fastfetch -c presets/ci.jsonc --format json
|
||||
|
||||
- name: Run flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
- name: Run tests
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: fastfetch-haiku-amd64
|
||||
path: ./fastfetch-*.*
|
||||
@@ -0,0 +1,47 @@
|
||||
name: Reusable Linux armv7l
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: run VM
|
||||
uses: uraimo/run-on-arch-action@460cb8e6d9f726a588fc9b5e681c8a6cab09ae41 # v3.2.0
|
||||
id: runcmd
|
||||
with:
|
||||
arch: armv7
|
||||
distro: ubuntu22.04
|
||||
githubToken: ${{ github.token }}
|
||||
run: |
|
||||
uname -a
|
||||
apt-get update && apt-get install -y software-properties-common ca-certificates gpg curl
|
||||
add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
||||
curl -L https://apt.kitware.com/keys/kitware-archive-latest.asc | gpg --dearmor - | tee /usr/share/keyrings/kitware-archive-keyring.gpg >/dev/null
|
||||
echo 'deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ jammy main' | tee /etc/apt/sources.list.d/kitware.list >/dev/null
|
||||
echo -e 'Acquire::https::Verify-Peer "false";\nAcquire::https::Verify-Host "false";' >> /etc/apt/apt.conf.d/99ignore-certificates
|
||||
apt-get update && apt-get install -y cmake make gcc-13 libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev libefl-all-dev liblua5.4-dev libvdpau-dev libva-dev rpm
|
||||
CC=gcc-13 cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: fastfetch-linux-armv7l
|
||||
path: ./fastfetch-*.*
|
||||
@@ -0,0 +1,135 @@
|
||||
name: Reusable Linux Hosts
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
arch:
|
||||
required: true
|
||||
type: string
|
||||
runs-on:
|
||||
required: true
|
||||
type: string
|
||||
outputs:
|
||||
ffversion:
|
||||
description: fastfetch version from linux host build
|
||||
value: ${{ jobs.build.outputs.ffversion }}
|
||||
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
|
||||
env:
|
||||
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{ inputs.runs-on }}
|
||||
outputs:
|
||||
ffversion: ${{ steps.ffversion.outputs.ffversion }}
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: uname -a
|
||||
run: uname -a
|
||||
|
||||
- name: cat /etc/os-release
|
||||
run: cat /etc/os-release
|
||||
|
||||
- name: cat /proc/cpuinfo
|
||||
run: cat /proc/cpuinfo
|
||||
|
||||
- name: add gcc-13 repo
|
||||
run: sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
||||
|
||||
- name: install required packages
|
||||
run: sudo apt-get update && sudo apt-get install -y gcc-13 jq libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev libddcutil-dev libefl-all-dev libunwind-dev liblua5.4-dev libvdpau-dev libva-dev rpm ninja-build
|
||||
|
||||
- name: install linuxbrew packages
|
||||
run: |
|
||||
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
||||
/home/linuxbrew/.linuxbrew/bin/brew install imagemagick chafa quickjs-ng --ignore-dependencies
|
||||
|
||||
- name: Initialize CodeQL
|
||||
if: inputs.arch == 'amd64'
|
||||
uses: github/codeql-action/init@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4.37.8
|
||||
with:
|
||||
languages: c
|
||||
|
||||
- name: configure project
|
||||
run: CC=gcc-13 CMAKE_PREFIX_PATH=/home/linuxbrew/.linuxbrew PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/lib/pkgconfig:$PKG_CONFIG_PATH cmake -GNinja -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --target package --verbose -j4
|
||||
|
||||
- name: perform CodeQL analysis
|
||||
if: inputs.arch == 'amd64'
|
||||
uses: github/codeql-action/analyze@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4.37.8
|
||||
|
||||
- name: list features
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
- name: run fastfetch
|
||||
run: time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
|
||||
- name: run fastfetch --format json
|
||||
run: |
|
||||
{ time -p ./fastfetch -c presets/ci.jsonc --format json > fastfetch.raw.json 2> fastfetch.error; } 2> fastfetch.time
|
||||
sed -n '/^[[:space:]]*\[/,$p' fastfetch.raw.json > fastfetch.json
|
||||
cat fastfetch.json
|
||||
cat fastfetch.error >&2
|
||||
cat fastfetch.time >&2
|
||||
|
||||
- name: prepare benchmark data
|
||||
run: |
|
||||
real_seconds=$(awk '$1 == "real" { print $2 }' fastfetch.time)
|
||||
jq -e 'type == "array"' fastfetch.json > /dev/null
|
||||
jq --arg platform "linux" --arg arch "${{ inputs.arch }}" --argjson real_seconds "$real_seconds" '
|
||||
map(select(.stat | type == "number") | {
|
||||
name: ("fastfetch " + $platform + " " + $arch + " module " + .type),
|
||||
unit: "ms",
|
||||
value: .stat
|
||||
}) + [{
|
||||
name: ("fastfetch " + $platform + " " + $arch + " total process time"),
|
||||
unit: "ms",
|
||||
value: ($real_seconds * 1000)
|
||||
}]
|
||||
' fastfetch.json > benchmark.json
|
||||
cat benchmark.json
|
||||
|
||||
- name: run flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
- name: print dependencies
|
||||
run: ldd fastfetch
|
||||
|
||||
- name: run tests
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- name: get fastfetch version
|
||||
id: ffversion
|
||||
run: echo "ffversion=$(./fastfetch --version-raw)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: polyfill glibc
|
||||
run: |
|
||||
wget https://github.com/CarterLi/polyfill-glibc/releases/download/v0.0.1/polyfill-glibc-${{ inputs.arch }} -O polyfill-glibc
|
||||
chmod +x polyfill-glibc
|
||||
strip fastfetch && ./polyfill-glibc fastfetch --target-glibc=2.17
|
||||
strip flashfetch && ./polyfill-glibc flashfetch --target-glibc=2.17
|
||||
echo 'set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}-polyfilled")' >> CPackConfig.cmake
|
||||
echo 'set(CPACK_PACKAGE_RELOCATABLE OFF)' >> CPackConfig.cmake
|
||||
echo 'set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.17)")' >> CPackConfig.cmake
|
||||
echo 'set(CPACK_RPM_SPEC_MORE_DEFINE "%global __os_install_post %{nil}")' >> CPackConfig.cmake
|
||||
cpack -V
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: fastfetch-linux-${{ inputs.arch }}
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
- name: upload benchmark data
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: benchmark-linux-${{ inputs.arch }}
|
||||
path: benchmark.json
|
||||
@@ -0,0 +1,73 @@
|
||||
name: Reusable Linux i686
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: uname -a
|
||||
run: uname -a
|
||||
|
||||
- name: cat /etc/os-release
|
||||
run: cat /etc/os-release
|
||||
|
||||
- name: cat /proc/cpuinfo
|
||||
run: cat /proc/cpuinfo
|
||||
|
||||
- name: add gcc-13 repo
|
||||
run: sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
||||
|
||||
- name: install required packages
|
||||
run: sudo apt-get update && sudo apt-get install -y gcc-13 gcc-13-multilib libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev libddcutil-dev libefl-all-dev libunwind-dev liblua5.4-dev libvdpau-dev libva-dev rpm ninja-build
|
||||
|
||||
- name: install linuxbrew packages
|
||||
run: |
|
||||
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
||||
/home/linuxbrew/.linuxbrew/bin/brew install imagemagick chafa quickjs-ng --ignore-dependencies
|
||||
|
||||
- name: cmake version
|
||||
run: cmake --version
|
||||
|
||||
- name: configure project
|
||||
run: CC=gcc-13 CMAKE_PREFIX_PATH=/home/linuxbrew/.linuxbrew PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/lib/pkgconfig:$PKG_CONFIG_PATH cmake -DCMAKE_C_FLAGS="-m32 -march=i686 -mtune=i686" -DCMAKE_SYSTEM_PROCESSOR_OVERRIDE=i686 -DCPACK_DEBIAN_PACKAGE_ARCHITECTURE=i386 -GNinja -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --target package --verbose -j4
|
||||
|
||||
- name: check deb package
|
||||
run: dpkg -I fastfetch-*.deb
|
||||
|
||||
- name: list features
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
- name: run fastfetch
|
||||
run: time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
|
||||
- name: run fastfetch --format json
|
||||
run: time ./fastfetch -c presets/ci.jsonc --format json
|
||||
|
||||
- name: run flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
- name: print dependencies
|
||||
run: ldd fastfetch
|
||||
|
||||
- name: run tests
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: fastfetch-linux-i686
|
||||
path: ./fastfetch-*.*
|
||||
@@ -0,0 +1,60 @@
|
||||
name: Reusable Linux loong64
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: set up QEMU for loong64
|
||||
uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4.2.0
|
||||
|
||||
- name: build in loong64 container
|
||||
run: |
|
||||
docker run --rm --platform linux/loong64 \
|
||||
-v ${{ github.workspace }}:/workspace \
|
||||
-w /workspace \
|
||||
lcr.loongnix.cn/debian:14 \
|
||||
bash -c '
|
||||
set -e
|
||||
uname -a
|
||||
cat /etc/os-release || true
|
||||
|
||||
apt-get update
|
||||
apt-get install -y --no-install-recommends \
|
||||
cmake make gcc g++ \
|
||||
libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev \
|
||||
libdconf-dev libdbus-1-dev libmagickcore-dev \
|
||||
libsqlite3-dev librpm-dev \
|
||||
libegl-dev libglx-dev ocl-icd-opencl-dev \
|
||||
libpulse-dev libdrm-dev \
|
||||
libelf-dev libefl-all-dev \
|
||||
liblua5.4-dev \
|
||||
libvdpau-dev libva-dev \
|
||||
rpm
|
||||
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
cmake --build . --target package --verbose -j$(nproc)
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest --output-on-failure
|
||||
'
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: fastfetch-linux-loong64
|
||||
path: ./fastfetch-*.*
|
||||
@@ -0,0 +1,48 @@
|
||||
name: Reusable Linux VMs
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
arch:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: run VM
|
||||
uses: uraimo/run-on-arch-action@460cb8e6d9f726a588fc9b5e681c8a6cab09ae41 # v3.2.0
|
||||
id: runcmd
|
||||
with:
|
||||
arch: ${{ inputs.arch }}
|
||||
distro: ubuntu22.04
|
||||
githubToken: ${{ github.token }}
|
||||
run: |
|
||||
uname -a
|
||||
apt-get update && apt-get install -y software-properties-common
|
||||
add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
||||
apt-get update && apt-get install -y cmake make gcc-13 libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libchafa-dev libelf-dev libefl-all-dev liblua5.4-dev libvdpau-dev libva-dev rpm
|
||||
CC=gcc-13 cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: fastfetch-linux-${{ inputs.arch }}
|
||||
path: ./fastfetch-*.*
|
||||
@@ -0,0 +1,90 @@
|
||||
name: Reusable macOS Hosts
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
arch:
|
||||
required: true
|
||||
type: string
|
||||
runs-on:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{ inputs.runs-on }}
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: uname -a
|
||||
run: uname -a
|
||||
|
||||
- name: install required packages
|
||||
run: |
|
||||
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew update
|
||||
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew install --overwrite vulkan-loader vulkan-headers molten-vk imagemagick chafa lua quickjs-ng jq
|
||||
|
||||
- name: configure project
|
||||
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --target package --verbose -j4
|
||||
|
||||
- name: list features
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
- name: run fastfetch
|
||||
run: time ./fastfetch -c presets/ci.jsonc --structure-disabled vulkan:bluetooth:bluetoothradio --stat false
|
||||
|
||||
- name: run fastfetch --format json
|
||||
run: |
|
||||
{ time -p ./fastfetch -c presets/ci.jsonc --structure-disabled vulkan:bluetooth:bluetoothradio --format json > fastfetch.raw.json 2> fastfetch.error; } 2> fastfetch.time
|
||||
sed -n '/^[[:space:]]*\[/,$p' fastfetch.raw.json > fastfetch.json
|
||||
cat fastfetch.json
|
||||
cat fastfetch.error >&2
|
||||
cat fastfetch.time >&2
|
||||
|
||||
- name: prepare benchmark data
|
||||
run: |
|
||||
real_seconds=$(awk '$1 == "real" { print $2 }' fastfetch.time)
|
||||
jq -e 'type == "array"' fastfetch.json > /dev/null
|
||||
jq --arg platform "macos" --arg arch "${{ inputs.arch }}" --argjson real_seconds "$real_seconds" '
|
||||
map(select(.stat | type == "number") | {
|
||||
name: ("fastfetch " + $platform + " " + $arch + " module " + .type),
|
||||
unit: "ms",
|
||||
value: .stat
|
||||
}) + [{
|
||||
name: ("fastfetch " + $platform + " " + $arch + " total process time"),
|
||||
unit: "ms",
|
||||
value: ($real_seconds * 1000)
|
||||
}]
|
||||
' fastfetch.json > benchmark.json
|
||||
cat benchmark.json
|
||||
|
||||
- name: run flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
- name: print dependencies
|
||||
run: otool -L fastfetch
|
||||
|
||||
- name: run tests
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: fastfetch-macos-${{ inputs.arch }}
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
- name: upload benchmark data
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: benchmark-macos-${{ inputs.arch }}
|
||||
path: benchmark.json
|
||||
@@ -0,0 +1,50 @@
|
||||
name: Reusable Musl amd64
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: setup alpine linux
|
||||
uses: jirutka/setup-alpine@ae3b3ddba35054804fc4a3507b519fa7e8152050 # v1.4.1
|
||||
with:
|
||||
branch: edge
|
||||
|
||||
- name: install dependencies
|
||||
run: |
|
||||
cat /etc/alpine-release
|
||||
uname -a
|
||||
apk add cmake samurai vulkan-loader-dev libxcb-dev libxrandr-dev rpm-dev wayland-dev libdrm-dev dconf-dev imagemagick-dev chafa-dev zlib-dev dbus-dev mesa-dev opencl-dev sqlite-dev networkmanager-dev pulseaudio-dev ddcutil-dev elfutils-dev lua5.4-dev quickjs-ng-dev libvdpau-dev libva-dev gcc g++
|
||||
shell: alpine.sh --root {0}
|
||||
|
||||
- name: build
|
||||
run: |
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr -DIS_MUSL=ON -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -GNinja .
|
||||
cmake --build . --target package --verbose -j4
|
||||
shell: alpine.sh {0}
|
||||
|
||||
- name: run
|
||||
run: |
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest --output-on-failure
|
||||
shell: alpine.sh {0}
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: fastfetch-musl-amd64
|
||||
path: ./fastfetch-*.*
|
||||
@@ -0,0 +1,65 @@
|
||||
name: Reusable NetBSD amd64
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
shell: cpa.sh {0}
|
||||
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Start VM
|
||||
uses: cross-platform-actions/action@faa0c6197e94aacf1c5956460152c8380d3560a5 # v1.5.0
|
||||
with:
|
||||
operating_system: netbsd
|
||||
version: '10.1'
|
||||
shell: bash
|
||||
cpu_count: 4
|
||||
|
||||
- name: Show system info
|
||||
run: |
|
||||
uname -a
|
||||
pkgin -v
|
||||
|
||||
- name: Update and install dependencies
|
||||
run: |
|
||||
sudo pkgin -y install clang cmake git pkgconf wayland vulkan-headers dconf dbus sqlite3 ImageMagick libva libvdpau
|
||||
|
||||
- name: CMake configuration
|
||||
run: CC=clang cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -DCMAKE_BUILD_TYPE=${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }} .
|
||||
|
||||
- name: CMake build
|
||||
run: cmake --build . --target package --verbose -j4
|
||||
|
||||
- name: List features
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
- name: Run normal
|
||||
run: time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
|
||||
- name: Run json
|
||||
run: time ./fastfetch -c presets/ci.jsonc --format json
|
||||
|
||||
- name: Run flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
- name: Run ldd
|
||||
run: ldd fastfetch
|
||||
|
||||
- name: Run tests
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: fastfetch-netbsd-amd64
|
||||
path: ./fastfetch-*.*
|
||||
@@ -0,0 +1,45 @@
|
||||
name: Reusable No Features Test
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: uname -a
|
||||
run: uname -a
|
||||
|
||||
- name: configure project
|
||||
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr . -DENABLE_VULKAN=OFF -DENABLE_WAYLAND=OFF -DENABLE_XCB_RANDR=OFF -DENABLE_XCB=OFF -DENABLE_XRANDR=OFF -DENABLE_X11=OFF -DENABLE_DRM=OFF -DENABLE_DRM_AMDGPU=OFF -DENABLE_GIO=OFF -DENABLE_DCONF=OFF -DENABLE_DBUS=OFF -DENABLE_SQLITE3=OFF -DENABLE_RPM=OFF -DENABLE_IMAGEMAGICK7=OFF -DENABLE_IMAGEMAGICK6=OFF -DENABLE_CHAFA=OFF -DENABLE_ZLIB=OFF -DENABLE_EGL=OFF -DENABLE_GLX=OFF -DENABLE_OPENCL=OFF -DENABLE_FREETYPE=OFF -DENABLE_PULSE=OFF -DENABLE_DDCUTIL=OFF -DENABLE_ELF=OFF -DENABLE_EET=OFF -DENABLE_THREADS=OFF
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --target package --verbose -j4
|
||||
|
||||
- name: list features
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
- name: run fastfetch
|
||||
run: time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
|
||||
- name: run fastfetch --format json
|
||||
run: time ./fastfetch -c presets/ci.jsonc --format json
|
||||
|
||||
- name: run flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
- name: print dependencies
|
||||
run: ldd fastfetch
|
||||
|
||||
- name: run tests
|
||||
run: ctest --output-on-failure
|
||||
@@ -0,0 +1,70 @@
|
||||
name: Reusable OmniOS amd64
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
shell: cpa.sh {0}
|
||||
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Start VM
|
||||
uses: cross-platform-actions/action@faa0c6197e94aacf1c5956460152c8380d3560a5 # v1.5.0
|
||||
with:
|
||||
operating_system: omnios
|
||||
version: 'r151058'
|
||||
shell: bash
|
||||
cpu_count: 4
|
||||
|
||||
- name: Show system info
|
||||
run: |
|
||||
uname -a
|
||||
|
||||
- name: Update and install dependencies
|
||||
run: |
|
||||
sudo pkg update --accept || true
|
||||
sudo pkg install gcc14 cmake git pkg-config glib2 dbus sqlite-3 imagemagick ninja
|
||||
|
||||
- name: CMake configuration
|
||||
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -GNinja -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -DCMAKE_BUILD_TYPE=${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }} .
|
||||
|
||||
- name: CMake build
|
||||
run: cmake --build . --verbose -j4
|
||||
|
||||
- name: List features
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
- name: Run normal
|
||||
run: time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
|
||||
- name: Run json
|
||||
run: time ./fastfetch -c presets/ci.jsonc --format json
|
||||
|
||||
- name: Run flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
- name: Run ldd
|
||||
run: ldd fastfetch
|
||||
|
||||
- name: Run tests
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- name: Package
|
||||
run: |
|
||||
echo 'set(CPACK_PACKAGE_FILE_NAME "fastfetch-omnios-amd64")' >> CPackConfig.cmake
|
||||
cpack -V
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: fastfetch-omnios-amd64
|
||||
path: ./fastfetch-*.*
|
||||
@@ -0,0 +1,65 @@
|
||||
name: Reusable OpenBSD amd64
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
shell: cpa.sh {0}
|
||||
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Start VM
|
||||
uses: cross-platform-actions/action@faa0c6197e94aacf1c5956460152c8380d3560a5 # v1.5.0
|
||||
with:
|
||||
operating_system: openbsd
|
||||
version: '7.9'
|
||||
shell: bash
|
||||
cpu_count: 4
|
||||
|
||||
- name: Show system info
|
||||
run: |
|
||||
uname -a
|
||||
|
||||
- name: Update and install dependencies
|
||||
run: |
|
||||
sudo pkg_add -u
|
||||
sudo pkg_add -r llvm-21.1.8p4 cmake git wayland vulkan-headers vulkan-loader glib2 dconf dbus sqlite3 imagemagick chafa lua-5.4.8p0 # pkg-config is preinstalled
|
||||
|
||||
- name: CMake configuration
|
||||
run: CC=clang-21 cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -DCMAKE_BUILD_TYPE=${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }} .
|
||||
|
||||
- name: CMake build
|
||||
run: cmake --build . --target package --verbose -j4
|
||||
|
||||
- name: List features
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
- name: Run normal
|
||||
run: time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
|
||||
- name: Run json
|
||||
run: time ./fastfetch -c presets/ci.jsonc --format json
|
||||
|
||||
- name: Run flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
- name: Run ldd
|
||||
run: ldd fastfetch
|
||||
|
||||
- name: Run tests
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: fastfetch-openbsd-amd64
|
||||
path: ./fastfetch-*.*
|
||||
@@ -0,0 +1,61 @@
|
||||
name: Reusable Release
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
ffversion:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: get latest release version
|
||||
id: get_version_release
|
||||
uses: pozetroninc/github-action-get-latest-release@2a61c339ea7ef0a336d1daa35ef0cb1418e7676c # v0.8.0
|
||||
with:
|
||||
repository: ${{ github.repository }}
|
||||
|
||||
- name: download artifacts
|
||||
if: inputs.ffversion != steps.get_version_release.outputs.release
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
|
||||
- name: create release
|
||||
if: inputs.ffversion != steps.get_version_release.outputs.release
|
||||
uses: ncipollo/release-action@339a81892b84b4eeb0f6e744e4574d79d0d9b8dd # v1.21.0
|
||||
with:
|
||||
tag: ${{ inputs.ffversion }}
|
||||
commit: ${{ github.sha }}
|
||||
artifactErrorsFailBuild: true
|
||||
artifacts: fastfetch-*/fastfetch-*
|
||||
body: "Please refer to [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/${{ inputs.ffversion }}/CHANGELOG.md) for details."
|
||||
|
||||
- name: download source tarballs
|
||||
if: inputs.ffversion != steps.get_version_release.outputs.release
|
||||
run: |
|
||||
for i in 1 2 3 4 5; do curl -L --remote-name-all --output-dir fastfetch-source --create-dirs https://github.com/${{ github.repository }}/archive/refs/tags/${{ inputs.ffversion }}.{tar.gz,zip} && break || sleep 5; done
|
||||
ls fastfetch-*/*
|
||||
|
||||
- name: generate release notes
|
||||
if: inputs.ffversion != steps.get_version_release.outputs.release
|
||||
run: |
|
||||
echo "Please refer to [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/${{ inputs.ffversion }}/CHANGELOG.md) for details." > fastfetch-release-notes.md
|
||||
echo -e "\n---\n\n<details><summary>SHA256SUMs</summary><br>\n\n\`\`\`" >> fastfetch-release-notes.md
|
||||
sha256sum fastfetch-*/* >> fastfetch-release-notes.md
|
||||
echo -e "\`\`\`\n</details>" >> fastfetch-release-notes.md
|
||||
echo -e "\n<details><summary>SHA512SUMs</summary><br>\n\n\`\`\`" >> fastfetch-release-notes.md
|
||||
sha512sum fastfetch-*/* >> fastfetch-release-notes.md
|
||||
echo -e "\`\`\`\n</details>" >> fastfetch-release-notes.md
|
||||
|
||||
- name: update release body
|
||||
if: inputs.ffversion != steps.get_version_release.outputs.release
|
||||
uses: ncipollo/release-action@339a81892b84b4eeb0f6e744e4574d79d0d9b8dd # v1.21.0
|
||||
with:
|
||||
tag: ${{ inputs.ffversion }}
|
||||
commit: ${{ github.sha }}
|
||||
bodyFile: fastfetch-release-notes.md
|
||||
allowUpdates: true
|
||||
@@ -0,0 +1,46 @@
|
||||
name: Reusable Solaris amd64
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: run VM
|
||||
uses: vmactions/solaris-vm@315163f088b66e55bbcc45928bd224d4973b2312 # v1.3.8
|
||||
with:
|
||||
usesh: true
|
||||
envs: 'CMAKE_BUILD_TYPE'
|
||||
release: "11.4-gcc-14"
|
||||
prepare: |
|
||||
uname -a
|
||||
pkg install cmake git pkg-config glib2 dbus sqlite-3 imagemagick ninja dconf mesa lua
|
||||
|
||||
run: |
|
||||
export PKG_CONFIG_PATH=/usr/lib/64/pkgconfig
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -GNinja .
|
||||
cmake --build . --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest --output-on-failure
|
||||
echo 'set(CPACK_PACKAGE_FILE_NAME "fastfetch-solaris-amd64")' >> CPackConfig.cmake
|
||||
cpack -V
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: fastfetch-solaris-amd64
|
||||
path: ./fastfetch-*.*
|
||||
@@ -0,0 +1,24 @@
|
||||
name: Reusable Spellcheck
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
spellcheck:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Install codespell
|
||||
shell: bash
|
||||
run: |
|
||||
pip3 install codespell
|
||||
codespell --version
|
||||
|
||||
- name: Run Spellchecker
|
||||
run: codespell
|
||||
@@ -0,0 +1,146 @@
|
||||
name: Reusable Windows Hosts
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
arch:
|
||||
required: true
|
||||
type: string
|
||||
runs-on:
|
||||
required: true
|
||||
type: string
|
||||
msystem:
|
||||
required: true
|
||||
type: string
|
||||
msystem-lower:
|
||||
required: true
|
||||
type: string
|
||||
msys-arch:
|
||||
required: true
|
||||
type: string
|
||||
secrets:
|
||||
SIGNPATH_API_TOKEN:
|
||||
description: SignPath REST API token used to submit the signing request
|
||||
# Optional so that runs without the secret (pull requests, forks)
|
||||
# still work; the signing step is skipped there anyway.
|
||||
required: false
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
# The SignPath action reads job details and downloads the unsigned
|
||||
# artifact with the workflow token.
|
||||
actions: read
|
||||
|
||||
env:
|
||||
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{ inputs.runs-on }}
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: setup-msys2
|
||||
uses: msys2/setup-msys2@66cd2cce69caa17b53920067426061ca1de3a884 # v2.32.0
|
||||
with:
|
||||
msystem: ${{ inputs.msystem }}
|
||||
update: true
|
||||
install: git mingw-w64-clang-${{ inputs.msys-arch }}-7zip mingw-w64-clang-${{ inputs.msys-arch }}-cmake mingw-w64-clang-${{ inputs.msys-arch }}-clang mingw-w64-clang-${{ inputs.msys-arch }}-jq mingw-w64-clang-${{ inputs.msys-arch }}-vulkan-loader mingw-w64-clang-${{ inputs.msys-arch }}-vulkan-headers mingw-w64-clang-${{ inputs.msys-arch }}-opencl-icd mingw-w64-clang-${{ inputs.msys-arch }}-opencl-headers mingw-w64-clang-${{ inputs.msys-arch }}-cppwinrt mingw-w64-clang-${{ inputs.msys-arch }}-imagemagick mingw-w64-clang-${{ inputs.msys-arch }}-chafa mingw-w64-clang-${{ inputs.msys-arch }}-lua mingw-w64-clang-${{ inputs.msys-arch }}-quickjs-ng mingw-w64-clang-${{ inputs.msys-arch }}-directx-headers
|
||||
|
||||
- name: print msys version
|
||||
run: uname -a
|
||||
|
||||
- name: configure project
|
||||
run: env PKG_CONFIG_PATH=/${{ inputs.msystem-lower }}/lib/pkgconfig/:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --verbose -j4
|
||||
|
||||
- name: copy necessary dlls
|
||||
run: cp /${{ inputs.msystem-lower }}/bin/{lua55,libqjs-0}.dll .
|
||||
|
||||
- name: list features
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
- name: run fastfetch
|
||||
run: time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
|
||||
- name: run fastfetch --format json
|
||||
run: |
|
||||
{ time -p ./fastfetch -c presets/ci.jsonc --format json > fastfetch.raw.json 2> fastfetch.error; } 2> fastfetch.time
|
||||
sed -n '/^[[:space:]]*\[/,$p' fastfetch.raw.json > fastfetch.json
|
||||
cat fastfetch.json
|
||||
cat fastfetch.error >&2
|
||||
cat fastfetch.time >&2
|
||||
|
||||
- name: prepare benchmark data
|
||||
run: |
|
||||
real_seconds=$(awk '$1 == "real" { print $2 }' fastfetch.time)
|
||||
jq -e 'type == "array"' fastfetch.json > /dev/null
|
||||
jq --arg platform "windows" --arg arch "${{ inputs.arch }}" --argjson real_seconds "$real_seconds" '
|
||||
map(select(.stat | type == "number") | {
|
||||
name: ("fastfetch " + $platform + " " + $arch + " module " + .type),
|
||||
unit: "ms",
|
||||
value: .stat
|
||||
}) + [{
|
||||
name: ("fastfetch " + $platform + " " + $arch + " total process time"),
|
||||
unit: "ms",
|
||||
value: ($real_seconds * 1000)
|
||||
}]
|
||||
' fastfetch.json > benchmark.json
|
||||
cat benchmark.json
|
||||
|
||||
- name: run flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
- name: print dependencies
|
||||
run: ldd fastfetch
|
||||
|
||||
- name: run tests
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- if: github.event_name == 'push' && github.repository == 'fastfetch-cli/fastfetch'
|
||||
id: upload-unsigned-artifact
|
||||
name: upload artifacts for signing
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: fastfetch-windows-${{ inputs.arch }}
|
||||
path: |
|
||||
*.dll
|
||||
fastfetch.exe
|
||||
flashfetch.exe
|
||||
|
||||
- if: github.event_name == 'push' && github.repository == 'fastfetch-cli/fastfetch'
|
||||
name: submit signing request
|
||||
uses: signpath/github-action-submit-signing-request@c92b958760219087e01f8d67a1669ed57afe2627 # v2.3
|
||||
with:
|
||||
api-token: '${{ secrets.SIGNPATH_API_TOKEN }}'
|
||||
organization-id: '${{ vars.SIGNPATH_ORG_ID }}'
|
||||
project-slug: 'fastfetch'
|
||||
signing-policy-slug: ${{ github.ref == 'refs/heads/master' && 'release-signing' || 'test-signing' }}
|
||||
github-artifact-id: '${{ steps.upload-unsigned-artifact.outputs.artifact-id }}'
|
||||
wait-for-completion: true
|
||||
output-artifact-directory: '.'
|
||||
|
||||
- name: create zip archive
|
||||
run: 7z a -tzip -mx9 -bd -y fastfetch-windows-${{ inputs.arch }}.zip LICENSE *.dll fastfetch.exe flashfetch.exe presets
|
||||
|
||||
- name: create 7z archive
|
||||
run: 7z a -t7z -mx9 -bd -y fastfetch-windows-${{ inputs.arch }}.7z LICENSE *.dll fastfetch.exe flashfetch.exe presets
|
||||
|
||||
- name: upload true artifacts
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: fastfetch-windows-${{ inputs.arch }}
|
||||
path: ./fastfetch-windows-${{ inputs.arch }}.*
|
||||
overwrite: true
|
||||
|
||||
- name: upload benchmark data
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: benchmark-windows-${{ inputs.arch }}
|
||||
path: benchmark.json
|
||||
+87
-589
@@ -4,66 +4,22 @@ on:
|
||||
- push
|
||||
- pull_request
|
||||
|
||||
env:
|
||||
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
|
||||
|
||||
jobs:
|
||||
spellcheck:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Install codespell
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt-get update || true
|
||||
sudo apt-get install -y codespell
|
||||
|
||||
- name: Run Spellchecker
|
||||
run: codespell
|
||||
permissions:
|
||||
contents: read
|
||||
uses: ./.github/workflows/build-spellcheck.yml
|
||||
|
||||
no-features-test:
|
||||
needs: spellcheck
|
||||
name: No-features-test
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: uname -a
|
||||
run: uname -a
|
||||
|
||||
- name: configure project
|
||||
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr . -DENABLE_VULKAN=OFF -DENABLE_WAYLAND=OFF -DENABLE_XCB_RANDR=OFF -DENABLE_XCB=OFF -DENABLE_XRANDR=OFF -DENABLE_X11=OFF -DENABLE_DRM=OFF -DENABLE_DRM_AMDGPU=OFF -DENABLE_GIO=OFF -DENABLE_DCONF=OFF -DENABLE_DBUS=OFF -DENABLE_SQLITE3=OFF -DENABLE_RPM=OFF -DENABLE_IMAGEMAGICK7=OFF -DENABLE_IMAGEMAGICK6=OFF -DENABLE_CHAFA=OFF -DENABLE_ZLIB=OFF -DENABLE_EGL=OFF -DENABLE_GLX=OFF -DENABLE_OPENCL=OFF -DENABLE_FREETYPE=OFF -DENABLE_PULSE=OFF -DENABLE_DDCUTIL=OFF -DENABLE_ELF=OFF -DENABLE_DIRECTX_HEADERS=OFF -DENABLE_THREADS=OFF
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --target package --verbose -j4
|
||||
|
||||
- name: list features
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
- name: run fastfetch
|
||||
run: time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
|
||||
- name: run fastfetch --format json
|
||||
run: time ./fastfetch -c presets/ci.jsonc --format json
|
||||
|
||||
- name: run flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
- name: print dependencies
|
||||
run: ldd fastfetch
|
||||
|
||||
- name: run tests
|
||||
run: ctest --output-on-failure
|
||||
uses: ./.github/workflows/build-no-features-test.yml
|
||||
|
||||
linux-hosts:
|
||||
needs: no-features-test
|
||||
name: Linux-${{ matrix.arch }}
|
||||
runs-on: ${{ matrix.runs-on }}
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
@@ -74,162 +30,36 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
- arch: aarch64
|
||||
runs-on: ubuntu-22.04-arm
|
||||
outputs:
|
||||
ffversion: ${{ steps.ffversion.outputs.ffversion }}
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v5
|
||||
uses: ./.github/workflows/build-linux-hosts.yml
|
||||
with:
|
||||
arch: ${{ matrix.arch }}
|
||||
runs-on: ${{ matrix.runs-on }}
|
||||
|
||||
- name: uname -a
|
||||
run: uname -a
|
||||
|
||||
- name: cat /etc/os-release
|
||||
run: cat /etc/os-release
|
||||
|
||||
- name: cat /proc/cpuinfo
|
||||
run: cat /proc/cpuinfo
|
||||
|
||||
- name: install required packages
|
||||
run: sudo apt-get update && sudo apt-get install -y libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev libddcutil-dev libchafa-dev directx-headers-dev rpm ninja-build
|
||||
|
||||
- name: install linuxbrew packages
|
||||
run: |
|
||||
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
||||
/home/linuxbrew/.linuxbrew/bin/brew install imagemagick --ignore-dependencies
|
||||
|
||||
- name: Initialize CodeQL
|
||||
if: matrix.arch == 'amd64'
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: c
|
||||
|
||||
- name: configure project
|
||||
run: PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/lib/pkgconfig:$PKG_CONFIG_PATH cmake -GNinja -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --target package --verbose -j4
|
||||
|
||||
- name: perform CodeQL analysis
|
||||
if: matrix.arch == 'amd64'
|
||||
uses: github/codeql-action/analyze@v3
|
||||
|
||||
- name: list features
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
- name: run fastfetch
|
||||
run: time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
|
||||
- name: run fastfetch --format json
|
||||
run: time ./fastfetch -c presets/ci.jsonc --format json
|
||||
|
||||
- name: run flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
- name: print dependencies
|
||||
run: ldd fastfetch
|
||||
|
||||
- name: run tests
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- name: get fastfetch version
|
||||
id: ffversion
|
||||
run: echo "ffversion=$(./fastfetch --version-raw)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: polyfill glibc
|
||||
run: |
|
||||
wget https://github.com/CarterLi/polyfill-glibc/releases/download/v0.0.1/polyfill-glibc-${{ matrix.arch }} -O polyfill-glibc
|
||||
chmod +x polyfill-glibc
|
||||
strip fastfetch && ./polyfill-glibc fastfetch --target-glibc=2.17
|
||||
strip flashfetch && ./polyfill-glibc flashfetch --target-glibc=2.17
|
||||
echo 'set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}-polyfilled")' >> CPackConfig.cmake
|
||||
cpack
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-linux-${{ matrix.arch }}
|
||||
path: ./fastfetch-*.*
|
||||
linux-i686:
|
||||
needs: no-features-test
|
||||
name: Linux-i686
|
||||
permissions:
|
||||
contents: read
|
||||
uses: ./.github/workflows/build-linux-i686.yml
|
||||
|
||||
linux-armv7l:
|
||||
needs: no-features-test
|
||||
name: Linux-armv7l
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v5
|
||||
uses: ./.github/workflows/build-linux-armv7l.yml
|
||||
|
||||
- name: run VM
|
||||
uses: uraimo/run-on-arch-action@v3
|
||||
id: runcmd
|
||||
with:
|
||||
arch: armv7
|
||||
distro: ubuntu20.04
|
||||
githubToken: ${{ github.token }}
|
||||
run: |
|
||||
uname -a
|
||||
apt-get update && apt-get install -y ca-certificates gpg curl
|
||||
curl -L https://apt.kitware.com/keys/kitware-archive-latest.asc | gpg --dearmor - | tee /usr/share/keyrings/kitware-archive-keyring.gpg >/dev/null
|
||||
echo 'deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ focal main' | tee /etc/apt/sources.list.d/kitware.list >/dev/null
|
||||
echo -e 'Acquire::https::Verify-Peer "false";\nAcquire::https::Verify-Host "false";' >> /etc/apt/apt.conf.d/99ignore-certificates
|
||||
apt-get update && apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev rpm
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-linux-armv7l
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
linux-armv6l:
|
||||
name: Linux-armv6l
|
||||
runs-on: ubuntu-24.04
|
||||
linux-loong64:
|
||||
needs: no-features-test
|
||||
name: Linux-loong64
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: run VM
|
||||
uses: uraimo/run-on-arch-action@v3
|
||||
id: runcmd
|
||||
with:
|
||||
arch: armv6
|
||||
distro: bookworm
|
||||
githubToken: ${{ github.token }}
|
||||
run: |
|
||||
uname -a
|
||||
apt-get update && apt-get install -y wget
|
||||
apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev rpm
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-linux-armv6l
|
||||
path: ./fastfetch-*.*
|
||||
uses: ./.github/workflows/build-linux-loong64.yml
|
||||
|
||||
linux-vms:
|
||||
needs: no-features-test
|
||||
name: Linux-${{ matrix.arch }}
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
strategy:
|
||||
matrix:
|
||||
@@ -237,78 +67,21 @@ jobs:
|
||||
- arch: riscv64
|
||||
- arch: ppc64le
|
||||
- arch: s390x
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: run VM
|
||||
uses: uraimo/run-on-arch-action@v3
|
||||
id: runcmd
|
||||
with:
|
||||
arch: ${{ matrix.arch }}
|
||||
distro: ubuntu20.04
|
||||
githubToken: ${{ github.token }}
|
||||
run: |
|
||||
uname -a
|
||||
apt-get update && apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libchafa-dev libelf-dev rpm
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-linux-${{ matrix.arch }}
|
||||
path: ./fastfetch-*.*
|
||||
uses: ./.github/workflows/build-linux-vms.yml
|
||||
with:
|
||||
arch: ${{ matrix.arch }}
|
||||
|
||||
musl-amd64:
|
||||
needs: no-features-test
|
||||
name: Musl-amd64
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: setup alpine linux
|
||||
uses: jirutka/setup-alpine@master
|
||||
|
||||
- name: install dependencies
|
||||
run: |
|
||||
cat /etc/alpine-release
|
||||
uname -a
|
||||
apk add cmake samurai vulkan-loader-dev libxcb-dev libxrandr-dev rpm-dev wayland-dev libdrm-dev dconf-dev imagemagick-dev chafa-dev zlib-dev dbus-dev mesa-dev opencl-dev sqlite-dev networkmanager-dev pulseaudio-dev ddcutil-dev elfutils-dev gcc g++
|
||||
shell: alpine.sh --root {0}
|
||||
|
||||
- name: build
|
||||
run: |
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr -DIS_MUSL=ON -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -GNinja .
|
||||
cmake --build . --target package --verbose -j4
|
||||
shell: alpine.sh {0}
|
||||
|
||||
- name: run
|
||||
run: |
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest --output-on-failure
|
||||
shell: alpine.sh {0}
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-musl-amd64
|
||||
path: ./fastfetch-*.*
|
||||
permissions:
|
||||
contents: read
|
||||
uses: ./.github/workflows/build-musl-amd64.yml
|
||||
|
||||
macos-hosts:
|
||||
needs: no-features-test
|
||||
name: macOS-${{ matrix.arch }}
|
||||
runs-on: ${{ matrix.runs-on }}
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
strategy:
|
||||
matrix:
|
||||
@@ -317,266 +90,68 @@ jobs:
|
||||
runs-on: macos-15-intel
|
||||
- arch: aarch64
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v5
|
||||
uses: ./.github/workflows/build-macos-hosts.yml
|
||||
with:
|
||||
arch: ${{ matrix.arch }}
|
||||
runs-on: ${{ matrix.runs-on }}
|
||||
|
||||
- name: uname -a
|
||||
run: uname -a
|
||||
omnios-amd64:
|
||||
needs: no-features-test
|
||||
name: OmniOS-amd64
|
||||
permissions:
|
||||
contents: read
|
||||
uses: ./.github/workflows/build-omnios-amd64.yml
|
||||
|
||||
- name: install required packages
|
||||
run: |
|
||||
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew install --overwrite vulkan-loader vulkan-headers molten-vk imagemagick chafa
|
||||
|
||||
- name: configure project
|
||||
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --target package --verbose -j4
|
||||
|
||||
- name: list features
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
- name: run fastfetch
|
||||
run: time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
|
||||
- name: run fastfetch --format json
|
||||
run: time ./fastfetch -c presets/ci.jsonc --format json
|
||||
|
||||
- name: run flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
- name: print dependencies
|
||||
run: otool -L fastfetch
|
||||
|
||||
- name: run tests
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-macos-${{ matrix.arch }}
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
sunos-amd64:
|
||||
runs-on: ubuntu-latest
|
||||
name: SunOS-amd64
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: run VM
|
||||
uses: vmactions/omnios-vm@v1
|
||||
with:
|
||||
usesh: true
|
||||
prepare: |
|
||||
uname -a
|
||||
pkg install pkg:/package/pkg
|
||||
pkg update --accept
|
||||
pkg install gcc14 cmake git pkg-config glib2 dbus sqlite-3 imagemagick
|
||||
|
||||
run: |
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest --output-on-failure
|
||||
cpack
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-sunos-amd64
|
||||
path: ./fastfetch-*.*
|
||||
solaris-amd64:
|
||||
needs: no-features-test
|
||||
name: Solaris-amd64
|
||||
permissions:
|
||||
contents: read
|
||||
uses: ./.github/workflows/build-solaris-amd64.yml
|
||||
|
||||
freebsd-amd64:
|
||||
needs: no-features-test
|
||||
name: FreeBSD-amd64
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: run VM
|
||||
uses: cross-platform-actions/action@master
|
||||
with:
|
||||
operating_system: freebsd
|
||||
architecture: x86-64
|
||||
cpu_count: 4
|
||||
shell: bash
|
||||
version: '14.3'
|
||||
run: |
|
||||
uname -a
|
||||
sudo pkg update
|
||||
sudo pkg install -y cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm glib dconf dbus sqlite3-tcl egl opencl ocl-icd v4l_compat chafa
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-freebsd-amd64
|
||||
path: ./fastfetch-*.*
|
||||
uses: ./.github/workflows/build-freebsd-amd64.yml
|
||||
|
||||
openbsd-amd64:
|
||||
needs: no-features-test
|
||||
name: OpenBSD-amd64
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: run VM
|
||||
uses: cross-platform-actions/action@master
|
||||
with:
|
||||
operating_system: openbsd
|
||||
architecture: x86-64
|
||||
cpu_count: 4
|
||||
shell: bash
|
||||
version: '7.7'
|
||||
run: |
|
||||
uname -a
|
||||
sudo pkg_add -r cmake git pkgconf wayland vulkan-headers vulkan-loader glib2 dconf dbus sqlite3 imagemagick chafa
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-openbsd-amd64
|
||||
path: ./fastfetch-*.*
|
||||
uses: ./.github/workflows/build-openbsd-amd64.yml
|
||||
|
||||
netbsd-amd64:
|
||||
needs: no-features-test
|
||||
name: NetBSD-amd64
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: run VM
|
||||
uses: cross-platform-actions/action@master
|
||||
with:
|
||||
operating_system: netbsd
|
||||
architecture: x86-64
|
||||
cpu_count: 4
|
||||
shell: bash
|
||||
version: '10.1'
|
||||
run: |
|
||||
uname -a
|
||||
sudo pkgin -y install cmake git pkgconf wayland vulkan-headers dconf dbus sqlite3 ImageMagick
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-netbsd-amd64
|
||||
path: ./fastfetch-*.*
|
||||
uses: ./.github/workflows/build-netbsd-amd64.yml
|
||||
|
||||
dragonfly-amd64:
|
||||
needs: no-features-test
|
||||
name: DragonFly-amd64
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: run VM
|
||||
uses: vmactions/dragonflybsd-vm@v1
|
||||
with:
|
||||
usesh: yes
|
||||
prepare: |
|
||||
uname -a
|
||||
pkg update
|
||||
pkg install -y cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm glib dconf dbus sqlite3-tcl egl opencl ocl-icd v4l_compat chafa libelf
|
||||
|
||||
run: |
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-dragonfly-amd64
|
||||
path: ./fastfetch-*.*
|
||||
uses: ./.github/workflows/build-dragonfly-amd64.yml
|
||||
|
||||
haiku-amd64:
|
||||
needs: no-features-test
|
||||
name: Haiku-amd64
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: run VM
|
||||
uses: cross-platform-actions/action@master
|
||||
with:
|
||||
operating_system: haiku
|
||||
version: 'r1beta5'
|
||||
architecture: x86-64
|
||||
cpu_count: 4
|
||||
shell: bash
|
||||
run: |
|
||||
uname -a
|
||||
pkgman install -y git dbus_devel mesa_devel libelf_devel imagemagick_devel opencl_headers ocl_icd_devel vulkan_devel zlib_devel chafa_devel cmake gcc make pkgconfig python3.10 || pkgman install -y git dbus_devel mesa_devel libelf_devel imagemagick_devel opencl_headers ocl_icd_devel vulkan_devel zlib_devel chafa_devel cmake gcc make pkgconfig python3.10
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-haiku-amd64
|
||||
path: ./fastfetch-*.*
|
||||
uses: ./.github/workflows/build-haiku-amd64.yml
|
||||
|
||||
windows-hosts:
|
||||
needs: no-features-test
|
||||
name: Windows-${{ matrix.arch }}
|
||||
runs-on: ${{ matrix.runs-on }}
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
# The SignPath action reads job details and downloads the unsigned
|
||||
# artifact with the workflow token.
|
||||
actions: read
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
@@ -590,70 +165,35 @@ jobs:
|
||||
msystem: CLANGARM64
|
||||
msystem-lower: clangarm64
|
||||
msys-arch: aarch64
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v5
|
||||
uses: ./.github/workflows/build-windows-hosts.yml
|
||||
with:
|
||||
arch: ${{ matrix.arch }}
|
||||
runs-on: ${{ matrix.runs-on }}
|
||||
msystem: ${{ matrix.msystem }}
|
||||
msystem-lower: ${{ matrix.msystem-lower }}
|
||||
msys-arch: ${{ matrix.msys-arch }}
|
||||
secrets:
|
||||
SIGNPATH_API_TOKEN: ${{ secrets.SIGNPATH_API_TOKEN }}
|
||||
|
||||
- name: setup-msys2
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: ${{ matrix.msystem }}
|
||||
update: true
|
||||
install: git mingw-w64-clang-${{ matrix.msys-arch }}-7zip mingw-w64-clang-${{ matrix.msys-arch }}-cmake mingw-w64-clang-${{ matrix.msys-arch }}-clang mingw-w64-clang-${{ matrix.msys-arch }}-vulkan-loader mingw-w64-clang-${{ matrix.msys-arch }}-vulkan-headers mingw-w64-clang-${{ matrix.msys-arch }}-opencl-icd mingw-w64-clang-${{ matrix.msys-arch }}-opencl-headers mingw-w64-clang-${{ matrix.msys-arch }}-cppwinrt mingw-w64-clang-${{ matrix.msys-arch }}-imagemagick mingw-w64-clang-${{ matrix.msys-arch }}-chafa
|
||||
|
||||
- name: print msys version
|
||||
run: uname -a
|
||||
|
||||
- name: configure project
|
||||
run: env PKG_CONFIG_PATH=/${{ matrix.msystem-lower }}/lib/pkgconfig/:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --verbose -j4
|
||||
|
||||
- name: copy necessary dlls
|
||||
run: cp /${{ matrix.msystem-lower }}/bin/{OpenCL,vulkan-1}.dll .
|
||||
|
||||
- name: list features
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
- name: run fastfetch
|
||||
run: time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
|
||||
- name: run fastfetch --format json
|
||||
run: time ./fastfetch -c presets/ci.jsonc --format json
|
||||
|
||||
- name: run flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
- name: print dependencies
|
||||
run: ldd fastfetch
|
||||
|
||||
- name: run tests
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- name: create zip archive
|
||||
run: 7z a -tzip -mx9 -bd -y fastfetch-windows-${{ matrix.arch }}.zip LICENSE *.dll fastfetch.exe flashfetch.exe presets
|
||||
|
||||
- name: create 7z archive
|
||||
run: 7z a -t7z -mx9 -bd -y fastfetch-windows-${{ matrix.arch }}.7z LICENSE *.dll fastfetch.exe flashfetch.exe presets
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-windows-${{ matrix.arch }}
|
||||
path: ./fastfetch-windows-${{ matrix.arch }}.*
|
||||
benchmark:
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/dev' && github.repository == 'fastfetch-cli/fastfetch'
|
||||
name: Benchmark
|
||||
needs:
|
||||
- linux-hosts
|
||||
- macos-hosts
|
||||
- windows-hosts
|
||||
permissions:
|
||||
contents: write
|
||||
uses: ./.github/workflows/build-benchmark.yml
|
||||
|
||||
release:
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'fastfetch-cli/fastfetch'
|
||||
name: Release
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- linux-hosts
|
||||
- linux-i686
|
||||
- linux-armv7l
|
||||
- linux-armv6l
|
||||
- linux-loong64
|
||||
- linux-vms
|
||||
- musl-amd64
|
||||
- macos-hosts
|
||||
@@ -661,54 +201,12 @@ jobs:
|
||||
- openbsd-amd64
|
||||
- netbsd-amd64
|
||||
- dragonfly-amd64
|
||||
- sunos-amd64
|
||||
- solaris-amd64
|
||||
- omnios-amd64
|
||||
- haiku-amd64
|
||||
- windows-hosts
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- name: get latest release version
|
||||
id: get_version_release
|
||||
uses: pozetroninc/github-action-get-latest-release@master
|
||||
with:
|
||||
repository: ${{ github.repository }}
|
||||
|
||||
- name: download artifacts
|
||||
if: needs.linux-hosts.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
uses: actions/download-artifact@v5
|
||||
|
||||
- name: create release
|
||||
if: needs.linux-hosts.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
uses: ncipollo/release-action@v1
|
||||
with:
|
||||
tag: ${{ needs.linux-hosts.outputs.ffversion }}
|
||||
commit: ${{ github.sha }}
|
||||
artifactErrorsFailBuild: true
|
||||
artifacts: fastfetch-*/fastfetch-*
|
||||
body: "Please refer to [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/${{ needs.linux-hosts.outputs.ffversion }}/CHANGELOG.md) for details."
|
||||
|
||||
- name: download source tarballs
|
||||
if: needs.linux-hosts.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
run: |
|
||||
for i in 1 2 3 4 5; do curl -L --remote-name-all --output-dir fastfetch-source --create-dirs https://github.com/${{ github.repository }}/archive/refs/tags/${{ needs.linux-hosts.outputs.ffversion }}.{tar.gz,zip} && break || sleep 5; done
|
||||
ls fastfetch-*/*
|
||||
|
||||
- name: generate release notes
|
||||
if: needs.linux-hosts.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
run: |
|
||||
echo "Please refer to [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/${{ needs.linux-hosts.outputs.ffversion }}/CHANGELOG.md) for details." > fastfetch-release-notes.md
|
||||
echo -e "\n---\n\n<details><summary>SHA256SUMs</summary><br>\n\n\`\`\`" >> fastfetch-release-notes.md
|
||||
sha256sum fastfetch-*/* >> fastfetch-release-notes.md
|
||||
echo -e "\`\`\`\n</details>" >> fastfetch-release-notes.md
|
||||
echo -e "\n<details><summary>SHA512SUMs</summary><br>\n\n\`\`\`" >> fastfetch-release-notes.md
|
||||
sha512sum fastfetch-*/* >> fastfetch-release-notes.md
|
||||
echo -e "\`\`\`\n</details>" >> fastfetch-release-notes.md
|
||||
|
||||
- name: update release body
|
||||
if: needs.linux-hosts.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
uses: ncipollo/release-action@v1
|
||||
with:
|
||||
tag: ${{ needs.linux-hosts.outputs.ffversion }}
|
||||
commit: ${{ github.sha }}
|
||||
bodyFile: fastfetch-release-notes.md
|
||||
allowUpdates: true
|
||||
uses: ./.github/workflows/build-release.yml
|
||||
with:
|
||||
ffversion: ${{ needs.linux-hosts.outputs.ffversion }}
|
||||
|
||||
+10
-5
@@ -1,8 +1,10 @@
|
||||
build/
|
||||
.vs/
|
||||
.vscode/
|
||||
.cache/
|
||||
.kdev4/
|
||||
/build/
|
||||
/build_*/
|
||||
/build-*/
|
||||
/.vs/
|
||||
/.vscode/
|
||||
/.cache/
|
||||
/.kdev4/
|
||||
.DS_Store
|
||||
cscope.*
|
||||
tags
|
||||
@@ -10,3 +12,6 @@ fastfetch.kdev4
|
||||
*.user
|
||||
*.user.*
|
||||
*.swp
|
||||
*.log
|
||||
/*.zh.md
|
||||
/.*-ai/
|
||||
|
||||
+678
-4
@@ -1,3 +1,677 @@
|
||||
# 2.68.0
|
||||
|
||||
Changes:
|
||||
* The DE / WM / LM modules now reports the full name "Desktop Environment" / "Window Manager" / "Login Manager" instead of the abbreviations.
|
||||
|
||||
Features:
|
||||
* Improved Login Manager (LM) module
|
||||
* Added support on macOS, Windows and POSIX systems without systemd (by process list enumeration).
|
||||
* Reports pretty name on Linux.
|
||||
* Added Top module to print processes with the highest CPU, memory or disk I/O usage. (Top)
|
||||
* Added module key localization support. (General)
|
||||
* Added a new option `--key-language <?lang>` (`display.key.language: "<?lang>"` in JSON config). When left empty, it defaults to the system locale.
|
||||
* See `fastfetch -h key-language` for all supported languages.
|
||||
* Improved Wi-Fi module
|
||||
* Added Wifi channel width detection, exposed via `{channel-width}` in custom format (reports 0 when not supported).
|
||||
* Improved Wifi channel frequency accuracy and fortified detection on Windows, macOS.
|
||||
* Added Wifi detection support on SunOS, Haiku.
|
||||
* Added Battery detection support on SunOS. (Battery, SunOS)
|
||||
* Added terminal font size detection support on Termux. (TerminalFont, Android)
|
||||
* Improved GTK theme/icons/font detection on standalone WMs such as Hyprland, sway, niri and i3. (Theme, Linux)
|
||||
* Improved fish completion scripts to print enum descriptions. (Completion)
|
||||
* Enabled Wayland support on Android. (DisplayServer, Android)
|
||||
* Added DE detection support for ASUS Zenfone. (DE, Android)
|
||||
* Added new ARM SoCs (CPU, Linux / Android)
|
||||
|
||||
Bugfixes:
|
||||
* Fixed I/O rate calculation precision in DiskIO and NetIO, and prevented division by zero. (DiskIO / NetIO)
|
||||
* Fixed the fast path of ash version detection. (Shell)
|
||||
* Fixed memory usage detection support on x86-32 FreeBSD (Memory, FreeBSD)
|
||||
* Note: Although 32-bit systems are still supported, they are deprecated and barely tested. Users are encouraged to upgrade to 64-bit systems.
|
||||
* Some internal cleanups and optimizations.
|
||||
|
||||
Logos:
|
||||
* Added macOS_old
|
||||
* Added Omarchy, Omarchy2
|
||||
|
||||
# 2.67.1
|
||||
|
||||
Bugfixes:
|
||||
* Fixed a `Symbol not found` error when running on macOS 10.15. (#2499, Codec, macOS)
|
||||
* Fixed Alacritty font size never being parsed from the TOML config. (#2501, TerminalFont)
|
||||
* Fixed bright colors incorrectly being active when the terminal uses a light theme. (#2509, Display)
|
||||
* Fixed Ghostty terminal font detection (TerminalFont)
|
||||
* Now tries to load the config with the `.ghostty` extension. (#2500)
|
||||
* Fixed `font-family` fallback order. (#2510)
|
||||
* Some internal cleanups and optimizations.
|
||||
|
||||
Features:
|
||||
* Added a C23 compiler check so the build process gracefully exits during CMake configuration if the compiler is unsupported. (CMake)
|
||||
* Added compatibility workarounds for Apple Clang 16 to fix building on macOS 14. (CMake, macOS)
|
||||
* Reported real Android version codenames (e.g., "Baklava", "Vanilla Ice Cream") instead of "REL". (OS, Android)
|
||||
* Added Loadavg detection support on Haiku R1B6. (Loadavg, Haiku)
|
||||
* Enabled image logo support in the Zellij terminal multiplexer. (#2507, Logo)
|
||||
* Improved Locale detection on Windows (Locale, Windows)
|
||||
* Now respects `LC_ALL` and `LANG` environment variables if set for better compatibility with MSYS2/cygwin.
|
||||
* Appends the active system Code Page (e.g., `.UTF-8` or `.Windows-1252`) to the default system locale fallback.
|
||||
|
||||
# 2.67.0
|
||||
|
||||
Changes:
|
||||
* The minimum supported compiler version has been raised to GCC 13 (released on 2023-04-26) and Clang 16 (released on 2023-03-17) to accommodate the new C23 syntax used throughout the codebase. (General)
|
||||
* As a result, building from source in Debian 12 (which only ships GCC 12 by default) is no longer supported. Users must upgrade their compiler or use the prebuilt binaries from the GitHub releases page.
|
||||
* The `general.preRun` option has been removed due to security concerns. (General)
|
||||
* Users who relied on this option to run a command before printing output will need to move that logic to an external wrapper.
|
||||
* The `{status}` placeholder in Battery custom format is now an array type instead of a single comma-separated string. (Battery)
|
||||
* This is a breaking change for users who print `{status}` in Lua scripts. They can use `table.concat(...)` to join the array into a single string if needed.
|
||||
* The `--gen-config-*` flags (`--gen-config-full`, `--gen-config-force`, `--gen-config-full-force`) have been removed and their functions have been merged into `--gen-config`. (Global)
|
||||
* See features below.
|
||||
|
||||
Features:
|
||||
* `--gen-config` now opens an interactive configuration TUI to make generating config files easier.
|
||||
* It falls back to non-interactive generation when `$NO_COLOR` is set or when stdin/stdout is not a TTY. This behavior can also be used to disable the interactive mode.
|
||||
* Added an experimental [WebUI](https://fastfetch-cli.github.io/fastfetch-config/) ([separate project](https://github.com/fastfetch-cli/fastfetch-config)) for generating and editing configs.
|
||||
* Added `-w`/`--watch` as a seconds-based alias for `--dynamic-interval`, defaulting to 1 second when no value is provided. (#2478, Watch)
|
||||
* Added InitSystem detection on Windows, reporting the first userland process (`smss.exe`). (InitSystem, Windows)
|
||||
* Added CPU and GPU temperature detection support for Apple M5 series chips. (CPU / GPU, macOS)
|
||||
* Reported `Basic` as the Windows theme when DWM is disabled. (Theme, Windows)
|
||||
* Improved Ghostty terminal font detection performance. (#2122, TerminalFont)
|
||||
* It now parses Ghostty directly instead of running `ghostty +show-config`.
|
||||
* Added support for a wider range of TOML config syntaxes used by Alacritty. (#2456, TerminalFont)
|
||||
|
||||
Bugfixes:
|
||||
* Fixed a potential fish version detection error. (Shell, Linux)
|
||||
* Fixed incorrect resolution reporting when a monitor advertises multiple preferred modes. (#2481, Display, Linux)
|
||||
* Fixed connected monitors being missed when Wayland output events arrive late. (#2451, Display, Linux)
|
||||
* Fixed VP9 codec detection on macOS. (Codec, macOS)
|
||||
* Corrected Base64 encoding on big-endian hosts. (#2470)
|
||||
* Fixed invalid URL parsing in the PublicIP module. (PublicIP)
|
||||
* Correctly reported virtual GPUs on Windows. (#2461, GPU, Windows)
|
||||
* Added a size limit for network responses to prevent excessive memory usage and mitigate potential attacks. (PublicIP / Weather)
|
||||
* Fixed Ubuntu Studio Core detection. (OS, Linux)
|
||||
* Relaxed the HTTP response check so that both `HTTP/1.0` and `HTTP/1.1` responses are accepted when fetching data over the network. (PublicIP / Weather)
|
||||
* Various internal cleanups and optimizations:
|
||||
* Fixed multiple memory leaks (Separator, Camera, Codec, Display).
|
||||
* Added integer overflow checks to the string buffer implementation.
|
||||
* Various code cleanups and compiler warning fixes.
|
||||
|
||||
Logos:
|
||||
* Removed Hypros, MagpieOS, Furreto, EmperorOS and Magix
|
||||
|
||||
# 2.66.0
|
||||
|
||||
Changes:
|
||||
* CPU package count is no longer reported in the default output.
|
||||
* Users can still print it in custom formats via `{packages}`
|
||||
|
||||
Bugfixes:
|
||||
* Fixed compatibility with WSL 2.9.3 (#2433, WM, Linux)
|
||||
* Fixed AMD GPU names not being queried accurately in `driverSpecific` mode (GPU, Linux)
|
||||
* Fixed GPU core counting for Apple Silicon GPU on Asahi Linux (GPU, Linux)
|
||||
* Some internal cleanups and optimizations.
|
||||
|
||||
Features:
|
||||
* Added Astra Linux version detection (OS, Linux)
|
||||
* Improved performance of Windows PowerShell version detection (Shell, Windows)
|
||||
* Improved performance of Media module on macOS (Media, macOS)
|
||||
* Added proxmox backup server detection (#2443, OS, Linux)
|
||||
|
||||
Logos:
|
||||
* Added Flatcar, Azure Linux
|
||||
* Added Chimera_small, Chimera2, Parabola2_small, PostmarketOS2, Qubes_small
|
||||
* Updated linuxmint_small
|
||||
* Cleaned up distro names
|
||||
|
||||
# 2.65.2
|
||||
|
||||
Changes:
|
||||
* Memory usage calculations now exclude the ZFS ARC cache on Linux, FreeBSD, NetBSD, and SunOS. (#1995 / #2418, Memory)
|
||||
* This prevents the Memory module from reporting artificially high memory usage on systems with the ZFS kmod enabled.
|
||||
|
||||
Bugfixes:
|
||||
* The GPU module no longer pings sleeping dedicated GPUs on dual-GPU laptops. (#2419, GPU)
|
||||
* As a result, PCIe link speed detection (introduced in v2.65.0) is now only enabled in `driverSpecific` mode.
|
||||
* Fixed a crash when detecting hardware codec support with the `amdgpu` driver on Linux. (#2419, Codec, Linux)
|
||||
|
||||
Logos:
|
||||
* Updated CachyOS_small; fixed CachyOS logo colors to match the official logo better
|
||||
* Added Turkish
|
||||
|
||||
# 2.65.1
|
||||
|
||||
No changes
|
||||
|
||||
# 2.65.0
|
||||
|
||||
Changes:
|
||||
* `display.disableLinewrap` now defaults to `false`.
|
||||
* This allows long lines to wrap instead of being truncated, preventing confusion for new users.
|
||||
* Wrapped lines may overlap with the image logo. Users who prefer the old behavior can set `display.disableLinewrap: true` in their config file or use `--disable-linewrap true` on the command line.
|
||||
* Reorders package manager variables in custom format strings, moving aggregate variables (e.g., `all`, `brew-all`, `flatpak-all`) to the end. (Packages)
|
||||
* This is a breaking change for users relying on numeric placeholders (e.g., `{1}`). Numeric placeholders are a long-deprecated feature; named placeholders (e.g., `{pacman}`) are always preferred and future-proof.
|
||||
* Enables `showPeCoreCount` by default to better display hybrid-architecture core counts. (CPU)
|
||||
* No longer accepts `chafa` options in config files if `chafa` support was disabled at compile time. (Logo)
|
||||
* This may affect users who generated their config files using `fastfetch --gen-full-config`. To resolve this, simply remove the `chafa` section from the config file.
|
||||
|
||||
Features:
|
||||
* Adds detection for CPU code names (e.g., "Alder Lake", "Zen 4") and manufacturing technologies (e.g., "Intel 7", "TSMC N4") on x86 processors. (#1501, CPU, X86)
|
||||
* These can be used in custom formats via `{code-name}` and `{technology}`.
|
||||
* Adds PCIe link speed detection (current and max generation & lanes) for GPUs on Linux and Windows.
|
||||
* These can be used in custom formats via `{pcie-max-speed}` and `{pcie-curr-speed}`.
|
||||
* Adds HDR display detection via the `wp-color-management-v1` Wayland protocol. (#2356, Display, Linux)
|
||||
* Previously, HDR detection was only supported on KDE Plasma.
|
||||
* Adds the `egl-ext` detection method, which uses `EGL_EXT_device_enumeration` for GPU enumeration. (GPU)
|
||||
* Adds terminal version and font detection for `kmscon`. (#2393, Terminal / TerminalFont, Linux)
|
||||
* Adds the currently-in-beta code name "Golden Gate" for macOS 27. (OS, macOS)
|
||||
* Adds WPA version detection on FreeBSD. (Wifi, FreeBSD)
|
||||
* Adds package manager support for `porg` (#2405) and `install-release` (#2342). (Packages, Linux)
|
||||
* Adds Weston version detection. (WM, Linux)
|
||||
* Improves the core type (P-Core/E-Core) fetching mechanism on Windows by using `EfficiencyClass` instead of legacy frequency inference. (CPU, Windows)
|
||||
* Improves display detection compatibility with KDE 6.7. (Display, Linux)
|
||||
* Improves display serial number detection, now preferring alphanumeric serial numbers when available. (Display)
|
||||
* This can be used in custom formats via `{serial}`.
|
||||
* Improves the performance of `emerge` package manager detection. (#2406, Packages, Linux)
|
||||
* Improves error messages for config file parsing errors.
|
||||
* Improves reliability of the `Codec` module on Linux (Codec, Linux)
|
||||
* Adds `va-x11` backend for VA-API and VDPAU, which is used if `va-drm` backend fails to initialize.
|
||||
* Fixes an issue where the Codec module incorrectly reports no results when the `codec.showType` option is set.
|
||||
|
||||
Bugfixes:
|
||||
* Fixes physical core detection on non-x86 architectures and simplifies the frequency detection code. (CPU, Linux)
|
||||
* Fixes console mode and output code page initialization issues when running `fastfetch` in `Conhost`. (#2383, Windows)
|
||||
* Fixes public IP detection randomly failing on Linux. (#2401, PublicIP, Linux)
|
||||
* Fixes several memory leaks.
|
||||
|
||||
Logos:
|
||||
* Adds Zerene OS. (#2404)
|
||||
|
||||
# 2.64.2
|
||||
|
||||
Bugfixes:
|
||||
* Fixes image rendering being wiped quickly (#2374)
|
||||
* Regression from v2.64.0
|
||||
* Fixes ASCII logo being overwritten in `--dynamic-interval` mode
|
||||
* Regression from v2.64.0
|
||||
|
||||
Logos:
|
||||
* Updates OpenWrt and adds a small variant (#2376)
|
||||
* The old one is renamed to `openwrt_old`
|
||||
|
||||
# 2.64.1
|
||||
|
||||
Features:
|
||||
* Adds a CMake option `-DPACKAGES_REMOVE_DISABLED` to remove detection code of disabled packages (`-DPACKAGES_DISABLE_<PACKAGE_NAME>`) for slightly smaller binary size (Packages)
|
||||
|
||||
Bugfixes:
|
||||
* Fixes compatibility issues with Lua 5.3
|
||||
* Avoid possible infinite recursion in `encode_json` when encoding deeply nested tables or circular references
|
||||
* Fixes compilation issues when building with old macOS SDKs
|
||||
|
||||
# 2.64.0
|
||||
|
||||
New **optional build** dependencies:
|
||||
* [`libva`](https://github.com/intel/libva) and [`libvdpau`](https://www.freedesktop.org/wiki/Software/VDPAU) for the new `Codec` module.
|
||||
* [Lua 5.3 to 5.5](https://www.lua.org/) for Lua scripting support, or [QuickJS](https://github.com/quickjs-ng/quickjs) v0.15.0 or newer for JavaScript scripting support.
|
||||
|
||||
Features:
|
||||
* Adds `Codec` module support for Windows, macOS, Linux, and Android for hardware-accelerated video codec detection (Codec)
|
||||
* Backends used (results may vary depending on the backend due to driver differences):
|
||||
* Linux and BSD: VA-API (default) and VDPAU (fallback for NVIDIA). Fastfetch must be built with `libva` and `libvdpau` support to enable these backends.
|
||||
* Windows: D3D12VA (Windows 11) and D3D11VA+MFT (Windows 10 or older)
|
||||
* macOS: VideoToolbox
|
||||
* Android: AMediaCodec
|
||||
* Common: Vulkan Video (disabled by default; can be enabled with `"useVulkan": true`)
|
||||
* By default, both encoders and decoders are reported. If no codecs are detected for a given type, `None` is reported. This behavior can be configured using the `"showType": "encoder|decoder"` option.
|
||||
* Adds experimental Lua script support for custom formats (Global)
|
||||
* Basic usage (using `Title` as an example): `{ "type": "title", "format": "lua:return string.format('Hello %s@%s', (...).userName, (...).hostName)" }`. The `lua:` prefix indicates a Lua script. A `return` statement is required to pass the final result back to the fastfetch module; otherwise, `nil` is returned implicitly and the entire module output is skipped.
|
||||
* Parameters are passed via variable arguments `(...)`. Users can assign them to named variables for better readability. For example: `lua:local args = ...; string.format('Hello %s@%s', args.userName, args.hostName)`.
|
||||
* The Lua interpreter instance is shared across all modules. This allows users to store and manipulate data across modules. For example:
|
||||
* `{ "type": "shell", "format": "lua:shell = ..." } // Note: no "return" here`
|
||||
* `{ "type": "terminal", "format": "lua:return shell.prettyName .. ' in ' .. (...).prettyName" } // This will print the detected shell and terminal names`
|
||||
* A `json_encode(table, is_pretty)` function has been added to the Lua API for easier debugging. For example, `lua:return json_encode(...)` will print all available variables and their values in JSON format.
|
||||
* Supported Lua versions: Lua 5.3 to 5.5 (Lua 5.1 and LuaJIT are not supported). The Lua version is auto-detected at build time. Once built, users can check the configured Lua version using `fastfetch --list-features`.
|
||||
* Adds experimental QuickJS script support for custom formats as an alternative to Lua (Global)
|
||||
* Basic usage: `{ "type": "title", "format": "qjs:`Hello ${this.userName}@${this.hostName}`" }`. The `qjs:` prefix indicates a JavaScript script. No `return` statement is needed; the final result is simply the evaluated value of the script.
|
||||
* Parameters are passed via the `this` object. Usage is mostly the same as Lua, but using JavaScript syntax.
|
||||
* Requires [quickjs-ng v0.15.0](https://github.com/quickjs-ng/quickjs/releases/tag/v0.15.0) or newer.
|
||||
* Adds CMake options `-DMODULE_DISABLE_<MODULE_NAME>=ON` to disable modules at compile time for a smaller binary size
|
||||
* Use `cmake -L . | grep MODULE_DISABLE_` to list all available options.
|
||||
* These options rely on LTO for dead code elimination (`-DCMAKE_BUILD_TYPE=Release` should enable LTO by default).
|
||||
* Adds the ability to remove unneeded ASCII logos without modifying the fastfetch source code, further reducing binary size
|
||||
* Simply remove the corresponding logo file from the logo directory (`src/logo/ascii/[a-z]/*`) and re-run `cmake`.
|
||||
* Improves string manipulation specifiers in custom formats
|
||||
* They are now ANSI escape-aware and work correctly with colored output (e.g., percentages with `num-color`) (#2364). Limitations:
|
||||
* They are still not wide-character aware and treat CJK and emoji characters as raw bytes.
|
||||
* Escape sequences in the middle of strings are not supported.
|
||||
* A new `|` specifier has been added to center strings. For example, `{user-name|20}` will center the username in a 20-character-wide field.
|
||||
* Adds preliminary `Bootmgr`, `Brightness`, and `WMTheme` detection support for Haiku (#2358, Haiku)
|
||||
* Adds `Wallpaper` and `WMTheme` detection support for the COSMIC desktop environment (Linux)
|
||||
* Improves terminal name detection for Nix packages (#2352, Terminal, Linux)
|
||||
* Adds DDC/CI brightness detection support for FreeBSD (Brightness, FreeBSD)
|
||||
* DDC/CI communication can be very slow. Users can set the `ddcciSleep: null` option to skip DDC/CI detection.
|
||||
* Reworks the built-in logo printing logic. ASCII logos and modules are now printed line by line, avoiding issues like #2239
|
||||
* Note: Image logos are not affected by this change and still print the entire image first before printing any modules.
|
||||
* Adds a new `--logo-padding-bottom` option to control the padding between the bottom of the logo and the first module when `--logo-position top` is used
|
||||
* Previously, `--logo-padding-right` was used for both right and bottom padding.
|
||||
* Adds `Samsung Exynos 2600` to CPU detection (CPU, Android)
|
||||
* Adds terminal font detection support for the Muxy terminal (TerminalFont, macOS)
|
||||
* Improves the performance of BusyBox (ash) version detection and always reports `ash` as the pretty name (Shell, Linux)
|
||||
|
||||
Bugfixes:
|
||||
* Fixes SwayFX version detection (WM, Linux)
|
||||
* Fixes fallback font detection for Ghostty (TerminalFont, macOS)
|
||||
* Fixes `--stat` output to correctly align with the right border (Global)
|
||||
* Fixes boot manager on macOS 26 (mBoot) is incorrectly reported as `iBoot` (Bootmgr, macOS)
|
||||
|
||||
Logos:
|
||||
* Adds Quasar (#2338, #2323), Origami, Origami_small (#2321, #2322), BerserkArch (#2324, #2310), and NixOS2 (#2346)
|
||||
* Minor tweaks and color fixes for the NixOS_small logo (#2357)
|
||||
* Updates NurOS (#2366)
|
||||
|
||||
# 2.63.1
|
||||
|
||||
Bugfixes:
|
||||
* Fixes media length detection for Chrome on Linux (Media, Linux)
|
||||
* Fixes segmentation fault when specifying unsupported modules on command line
|
||||
* Disables usage of Netlink for Wi-Fi detection on s390x architectures (Wifi, Linux)
|
||||
|
||||
# 2.63.0
|
||||
|
||||
Changes:
|
||||
* Introduces a new **build-only** dependency, `libefl`, for querying the Enlightenment window manager configuration:
|
||||
* `libefl-all-dev` on Debian/Ubuntu
|
||||
* `libefl-devel` on Fedora
|
||||
* `efl` on Arch Linux
|
||||
* The Windows-specific options `battery.useSetupApi` and `global.wmiTimeout` have been removed. (Windows)
|
||||
|
||||
Features:
|
||||
* Adds wallpaper detection support on Haiku (#2314, Wallpaper, Haiku)
|
||||
* Adds Wi-Fi 6 GHz channel detection and improves protocol reporting (Wifi, Linux)
|
||||
* Improves Deepin version detection using `/etc/os-version` (#2300, OS, Linux)
|
||||
* Adds Ubuntu Kylin and Ubuntu Unity flavor detection (OS, Linux)
|
||||
* Adds NebiDE support (WMTheme, Linux)
|
||||
* Adds package counting for `cards` on NuTyX (#2287, Packages, Linux)
|
||||
* Adds `{am-pm}` to custom format for 12-hour time with am/pm (DateTime)
|
||||
* Adds support for the Enlightenment desktop environment (#2165, WM, Linux)
|
||||
* Adds support for playback progress detection (Media)
|
||||
* The module now prints the current playback position and total media duration when supported by the player. If you prefer the previous behavior, you can set `media.percent.type: ["hide-others"]` to hide the new fields.
|
||||
* Adds support for `global.playerName` for Windows (Media, Windows)
|
||||
* This allows detecting a specified media player while ignoring others.
|
||||
* Multi-battery detection is enabled on Windows by default (Battery, Windows)
|
||||
|
||||
Bugfixes:
|
||||
* Improves DisplayServer compatibility on Linux by handling newer `kde-output-device-v2` protocol updates (DisplayServer, Linux)
|
||||
* This fixes a long-standing issue where display detection fails with an `interface 'kde_output_device_mode_v2' has no event X` error.
|
||||
* Improves Wi-Fi reliability on Linux by switching to a netlink implementation (Wifi, Linux)
|
||||
* Improves network interface reliability and default route selection on macOS and Windows (Netif, macOS / Windows)
|
||||
* Validates temperature color thresholds as integers when parsing JSON configs (Temps)
|
||||
* Fixes TDE Konsole version detection (#2319, Terminal, Linux)
|
||||
* Various internal cleanups and optimizations
|
||||
|
||||
Logos:
|
||||
* Adds KibaOS, NebiOS, XJ380, openRuyi, Ximper
|
||||
* Fixes GNOME OS built-in logo detection (#2296)
|
||||
|
||||
# 2.62.1
|
||||
|
||||
Bugfixes:
|
||||
* Fixes the Host module not working on some devices (#2279, Host, Linux)
|
||||
* Regression from v2.61.0
|
||||
|
||||
Logos:
|
||||
* Adds EN-OS, LimeOS, Redrose and Uzbek
|
||||
|
||||
# 2.62.0
|
||||
|
||||
Changes:
|
||||
* Sort package managers alphabetically in output and format arguments (Packages)
|
||||
* The positional order of format arguments has changed — this is a breaking change for users relying on numeric placeholders. Named arguments are always preferred; e.g., use `{pacman}` (refer to `fastfetch -h packages-format`) instead of `{1}` to keep your config future-proof.
|
||||
|
||||
Features:
|
||||
* Reports `Unused` instead of `Disabled` for zero-size swap on macOS (#2248, Swap, macOS)
|
||||
* Improves the robustness of default route detection on Linux (#2252, LocalIP, Linux)
|
||||
* PhysicalDisk module improvements
|
||||
* Detects virtual disks and adds support for hiding them via `hideVirtual` option (defaults to `false`)
|
||||
* Detects unused/disconnected disks and adds support for hiding them via `hideUnused` option (defaults to `true`)
|
||||
* Adds support for OpenBSD and NetBSD (root privileges are required to access disk information)
|
||||
* Improves interconnect type detection on SunOS
|
||||
* Adds floppy drive support on Windows
|
||||
* Rewrites Windows GPU detection with D3DKMT APIs, unifying it with WSL GPU detection (GPU, Windows)
|
||||
* Verifies that the battery and power adapter are present before detection (Battery / PowerAdapter, Linux)
|
||||
* Improves PhysicalMemory reliability on OpenBSD and FreeBSD, including support for x86 UEFI systems on OpenBSD and non-UEFI systems on FreeBSD (PhysicalMemory, OpenBSD / FreeBSD)
|
||||
* Adds `display.common.(ndigits|spaceBeforeUnit)` options to configure common formatting for duration, percent, size, frequency and temperature values (#2234)
|
||||
* Slightly improves performance by skipping probes for ignored device types (Sound)
|
||||
* Adds support for AppImage package detection (#2179, Packages, Linux)
|
||||
|
||||
Bugfixes:
|
||||
* Fixes a potential crash on certain Intel GPU models when using `--gpu-driver-specific` (#2259, GPU, Linux)
|
||||
* Doesn't report partitions as physical disks (DiskIO, NetBSD)
|
||||
* Fixes a typo (#2260, Wifi, macOS)
|
||||
* Corrects documentation for zpool format placeholders (#2261, Zpool)
|
||||
* Restores Windows 8.1 support (Cursor, Windows)
|
||||
* Fixes an out-of-bounds memory access when swaps are disabled (Swap, Windows)
|
||||
* Fixes battery status being incorrectly reported as `Charging` on systems with multiple batteries (#2263, Battery, Linux)
|
||||
* Fixes ash shell version detection (#2271, Shell, Linux)
|
||||
* Uses the `iterm` image protocol automatically on iTerm terminals for auto logo type (Logo)
|
||||
* Adds missing options when generating full config file
|
||||
|
||||
Logos:
|
||||
* Updates AerynOS (#2272)
|
||||
|
||||
# 2.61.0
|
||||
|
||||
Changes:
|
||||
* Support for Windows 7 and 8 has been removed.
|
||||
* Windows 8.1 is now the oldest version supported by fastfetch.
|
||||
* The GPU module on WSL no longer relies on `DXCore`.
|
||||
* The `directx-headers` dependency is no longer required.
|
||||
* Fastfetch on Linux is now pure C; a C++ compiler is no longer required.
|
||||
* GPU type detection is now slightly less accurate, but detection speed should be slightly faster.
|
||||
* The GPU module on Windows now uses `DXCore` for more accurate GPU type detection (requires Windows 10 or later).
|
||||
* This feature is built only when `DXCore` headers are available, which requires installing `mingw-w64-<msystem>-x86_64-directx-headers` on MSYS2.
|
||||
|
||||
Features:
|
||||
* Adds a `brightness` option for color display configuration (#2238, Colors)
|
||||
* Adds support for detecting Bluetooth keyboards on Linux (#2220, Keyboard)
|
||||
* Adds support for detecting GlazeWM (WM, macOS)
|
||||
* Adds a `showEmptySlots` option to display empty memory slots on Linux (#2222, PhysicalMemory)
|
||||
* Adds marketing product name detection on Asahi Linux (Host, Linux)
|
||||
* Adds support for new M5 Mac models (Host, macOS)
|
||||
* Improves SMBIOS robustness by validating malformed data and improving error handling
|
||||
* Improves reliability when terminating child processes (Processing, Windows)
|
||||
* Improves Intel Mac support by querying SMBIOS data directly (Global, macOS)
|
||||
* Includes numerous internal cleanups and optimizations
|
||||
|
||||
Bugfixes:
|
||||
* Fixes missing memory devices on some machines (PhysicalMemory)
|
||||
* Fixes CPUCache deduplication for shared caches (#2228, CPUCache, Linux)
|
||||
* Fixes WM version reporting for niri (#2218, WM, Linux)
|
||||
* Fixes SSID decoding issues from `iw` output (Wifi, Linux)
|
||||
* Fixes the CMD code page being changed after running fastfetch on Windows (#2245, Windows)
|
||||
|
||||
# 2.60.0
|
||||
|
||||
Changes:
|
||||
* The CMake option `ENABLE_WIN7_COMPAT:BOOLEAN` now defaults to `OFF` and will be removed in v2.61.0, effectively dropping support for Windows 7 in the next release.
|
||||
* This follows the Windows 7 deprecation notice introduced in v2.57.0.
|
||||
* `wm.detectPlugin` now defaults to `true` (WM)
|
||||
|
||||
Features:
|
||||
* Adds `{cwd}` for custom title formatting, which displays the current working directory (Title)
|
||||
* Adds support for detecting the Zed version (#2200, Editor)
|
||||
* Adds support for detecting `moss` packages (Packages, Linux)
|
||||
* Adds support for detecting komorebi, FancyWM, and GlazeWM (WM, Windows)
|
||||
* Adds support for WM plugin version detection on macOS (WM, macOS)
|
||||
* Adds support for retrieving the executable path on OpenBSD (#2195, OpenBSD)
|
||||
|
||||
Bugfixes:
|
||||
* Fixes a potential segmentation fault caused by dereferencing a negative index (#2198)
|
||||
* Fixes `tempSensor` parsing so that it accepts only string values (#2202, CPU)
|
||||
* Fixes an issue that unexpectedly caused fewer devices to be reported (Keyboard, Linux)
|
||||
* Improves WM detection on LXQt by querying WM settings only when no WM has already been detected (#2199, WM, Linux)
|
||||
* Fixes memory leaks in DBus connection handling and in the OpenGL EGL context lifecycle
|
||||
* Fixes niri version detection on Fedora (WM, Linux)
|
||||
* Includes various internal cleanups and optimizations
|
||||
|
||||
Logos:
|
||||
* Adds `RengeOS` (#2170)
|
||||
* Adds `Emmabuntüs` (#2207)
|
||||
* Updates Artix Linux (#2157)
|
||||
* Updates Linux Mint (#2186)
|
||||
* Renames `Refracted Devuan` to `Refracta`
|
||||
* Renames `ExodiaPredator` to `ExodiaOS`
|
||||
|
||||
# 2.59.0
|
||||
|
||||
Changes:
|
||||
* Fastfetch no longer relies on the unreliable environment variables `$USER` or `%USERPROFILE%` to determine the current username (Title)
|
||||
* People who set `$USER` to customize the Fastfetch title should use `{ "type": "title", "format": "your-custom-user-name" }` to achieve the same result.
|
||||
* Fastfetch no longer tries to probe inaccessible remote disk drives on Windows (Disk, Windows)
|
||||
* People who have remote drives may use `{ "type": "disk", "hideFolders": "X:\\" }` to ignore problematic ones.
|
||||
* This change removes some ugly hacks from the codebase and matches the behavior on `*nix`.
|
||||
|
||||
Features:
|
||||
* Adds Oracle Solaris support (#2176, SunOS)
|
||||
* Adds UID / SID detection (Title)
|
||||
* In custom format: `{user-id}`
|
||||
* Switches to native GPU detection on GNU/Hurd and removes the `libpciaccess` dependency (GPU, Hurd)
|
||||
* Improves memory size detection on macOS (Memory, macOS)
|
||||
* Avoids relying on `hw.memsize_usable` by default, which may not be available on older macOS versions
|
||||
* Improves Windows disk detection accuracy and performance (Disk, Windows)
|
||||
* Adds more ARM CPU parts and removes duplicated cases (CPU, ARM)
|
||||
|
||||
Logos:
|
||||
* Adds 6-color support to the NixOS logo (including the small variant) (#2180)
|
||||
|
||||
# 2.58.0
|
||||
|
||||
An early release to fix compatibility issues with KDE Plasma 6.6.
|
||||
|
||||
Breaking changes:
|
||||
* The `de.slowVersionDetection` option has been removed. Slow version detection is now always enabled, as required on non-FHS-compliant distros (e.g., NixOS). (#2149, DE, Linux)
|
||||
|
||||
Features:
|
||||
* Adds the `--structure-disabled <modules...>` command-line flag to temporarily disable module structure printing.
|
||||
* For example: `fastfetch --structure-disabled colors` removes the color blocks from the default output.
|
||||
* Supports chassis type detection on Linux ARM devices when reported via the device tree (Chassis, Linux)
|
||||
* Supports Bedrock Linux version detection (#2155, OS, Linux)
|
||||
* Honors the `DBPath` and `RootDir` settings in `pacman.conf` when detecting Pacman packages (#2154, Packages, Linux)
|
||||
|
||||
Bugfixes:
|
||||
* Fixes a crash issue on KDE Plasma 6.6 (Display, Linux)
|
||||
* Fixes the Command module not working with `--dynamic-interval` (#2152, Command)
|
||||
* Fixes Quartz Compositor version detection. It now correctly reports the version of `WindowServer` (`SkyLight`) instead of `WindowManager`. (WM, macOS)
|
||||
|
||||
Logos:
|
||||
* Adds Kiss2
|
||||
|
||||
# 2.57.1
|
||||
|
||||
Features:
|
||||
* Tiny performance improvements (Windows)
|
||||
* Improves the reliability of hostname retrieval (Title, Windows)
|
||||
|
||||
Bugfixes:
|
||||
* Fixes potential compilation issues on Linux (#2142, Linux)
|
||||
* Fixes compilation errors on macOS when building with older SDKs (#2140, macOS)
|
||||
* Fixes compilation issues when building with `-DENABLE_SYSTEM_YYJSON=ON` (#2143)
|
||||
|
||||
Logos:
|
||||
* Updates PrismLinux and adds a small variant
|
||||
|
||||
# 2.57.0
|
||||
|
||||
Deprecation notice:
|
||||
* Support for Windows 7 (and 8.x) is deprecated and will be removed in a future release. Extended support for Windows 7 (and 8.1) ended on January 10, 2023. These versions do not officially support ANSI escape codes (running fastfetch on them requires a third-party terminal such as ConEmu). In addition, Windows 7 lacks some APIs used by fastfetch. Fastfetch currently loads these APIs dynamically at runtime to maintain compatibility, but this adds complexity to the codebase and increases the maintenance burden.
|
||||
* A CMake flag `ENABLE_WIN7_COMPAT:BOOLEAN` has been introduced (defaults to `ON` for now). If set to `OFF`, Windows 7 compatibility code is excluded, and the resulting binaries will support only Windows 10 (version 1607 and later) and Windows 11.
|
||||
* The main prebuilt Windows binaries on the Release page (`fastfetch-windows-amd64.*`) are built with `ENABLE_WIN7_COMPAT=OFF`. These are the binaries used by `scoop` and `winget`. Users who need Windows 7 (or 8.x) support can download the `-win7` variant instead.
|
||||
* ~~The `ENABLE_WIN7_COMPAT` CMake option and the `-win7` variant binaries are planned to be removed in 2.60.0~~.
|
||||
|
||||
Features:
|
||||
* Supports COSMIC DE version detection (DE, Linux)
|
||||
* Supports niri version detection (#2121, WM, Linux)
|
||||
* Supports cosmic-term version and terminal font detection (Terminal / TerminalFont, Linux)
|
||||
* Supports urxvt font detection (TerminalFont, Linux) (#2105)
|
||||
* Improves xterm font detection by checking `xterm.vt100.faceName` (TerminalFont, Linux)
|
||||
* Supports Secure Boot detection (Bootmgr, macOS)
|
||||
* Supports DPI scale factor detection on Windows 7 (Display, Windows)
|
||||
* Supports xterm 256-color codes in color configuration
|
||||
* In `display.color`: "`@<color-index>`" (e.g., "`@34`" for color index `34`)
|
||||
* In `*.format` strings: "`#@<color-index>`" (e.g., "`#@34`" for color index `34`)
|
||||
* Improves uptime accuracy on Windows 10+ (Uptime, Windows)
|
||||
* Adds a new module `Logo` to query built-in logo raw data in JSON output (Logo)
|
||||
* Usage: `fastfetch -s logo -l <logo-name> -j # Supported in JSON format only`
|
||||
* Supports shell version detection even if the binary has been deleted (#2136, Shell, Linux)
|
||||
* Overall code refinements and optimizations
|
||||
|
||||
Bugfixes:
|
||||
* Skips local / loopback routes when detecting network interfaces (LocalIP, Linux) (#2127)
|
||||
* Fixes CPU speed detection on s390x (CPU, Linux) (#2129)
|
||||
* Fixes GPU detection error handling and supports case-insensitive PCI ID parsing (GPU, Windows)
|
||||
* Fixes some networking issues and memory leaks (Networking)
|
||||
* Fixes `exePath` reporting relative paths on macOS (Shell, macOS)
|
||||
|
||||
Logos:
|
||||
* Adds openSUSE Tumbleweed braille logo
|
||||
* Adds Xinux
|
||||
* Renames HydraPWK to NetHydra
|
||||
* Fixes colors of deepin and UOS
|
||||
* Fixes colors of macOS and variants
|
||||
|
||||
# 2.56.1
|
||||
|
||||
Features:
|
||||
* Improves compatibility with KDE Plasma 6.5 (#2093, Display)
|
||||
* Adds a `tempSensor` option to specify the sensor name used for CPU temperature detection (CPU)
|
||||
* Example: `{ "type": "cpu", "tempSensor": "hwmon0" /* Use /sys/class/hwmon/hwmon0 for temperature detection */ }`
|
||||
* Refines Memory usage detection on macOS to match Activity Monitor more closely (Memory, macOS)
|
||||
* Minor optimizations
|
||||
|
||||
Bugfixes:
|
||||
* Fixes cache line size detection (CPU, macOS)
|
||||
|
||||
Logos:
|
||||
* Removes Opak
|
||||
* Updates GXDE
|
||||
|
||||
# 2.56.0
|
||||
|
||||
Features:
|
||||
* Enhances config file loading. `--config` and `-c` with relative path now also searches paths defined in `fastfetch --list-config-paths` (typically `~/.config/fastfetch/`)
|
||||
* This allows users to use `fastfetch -c my-config` without needing to specify the full path.
|
||||
* Adds NUMA node count detection (CPU)
|
||||
* Exposed via `{numa-nodes}` in custom format
|
||||
* Supported on Linux, FreeBSD and Windows
|
||||
* Supports the newest Alacritty config format (#2070, TerminalFont)
|
||||
* Detects driver specific info for Zhaoxin GPUs (GPU, Linux)
|
||||
* Detects Android OEM UI for certain OSes (DE, Android)
|
||||
* Improves users detection on Linux (#2064, Users, Linux)
|
||||
* Adds systemd fallback when utmp is unavailable
|
||||
* Fixes resource leaks
|
||||
* Always reports the newest session info
|
||||
* Adds kiss package manager support (#2072, Packages, Linux)
|
||||
* Reports `sshd` if `$SSH_TTY` is not available (Terminal)
|
||||
* Zpool module rewrite (#2051, Zpool)
|
||||
* Adds new Zpool properties: allocated, guid, readOnly
|
||||
* Zpool module now uses runtime lookup for properties to ensure portability
|
||||
* Adds NetBSD (requires `sudo`) and macOS support
|
||||
* Adds `splitLines` option for Command module, which splits the output into sub modules, each containing one line of the output (Command)
|
||||
```
|
||||
* Command output:
|
||||
Line 1
|
||||
Line 2
|
||||
Line 3
|
||||
|
||||
* Old behavior:
|
||||
Command: Line 1
|
||||
Line 2
|
||||
Line 3
|
||||
|
||||
* With `"splitLines": true`:
|
||||
Command 1: Line 1
|
||||
Command 2: Line 2
|
||||
Command 3: Line 3
|
||||
```
|
||||
|
||||
Bugfixes:
|
||||
* Fixes {m,o}ksh version detection on Linux (Shell)
|
||||
* Fixes Alacritty config parsing for TOML format (#2070, TerminalFont)
|
||||
* Improves builtin logo printing for piping and buffering (#2065, Logo)
|
||||
* Uses absolute path when detecting shell and terminal version if available (#2067, TerminalShell)
|
||||
|
||||
Logos:
|
||||
* Updates Codex Linux logo (#2071)
|
||||
* Adds OS/2 Warp logo (#2062)
|
||||
* Adds Amiga logo (#2061)
|
||||
|
||||
# 2.55.1
|
||||
|
||||
Bugfixes:
|
||||
* Fix parallel command execution breaks randomly (#2056 / #2058, Command)
|
||||
* Regression from v2.55.0
|
||||
* Fix `dylib` searching path on macOS (macOS)
|
||||
* Regression from v2.55.0
|
||||
* Fix an uninitialized field (#2057, Display)
|
||||
|
||||
# 2.55.0
|
||||
|
||||
Changes:
|
||||
* Commands are now executed in parallel by default to improve performance (#2045, Command)
|
||||
* This behavior can be disabled in the config file with `"parallel": false` if it causes problems with certain scripts
|
||||
* Folder/filesystem hiding is moved to the detection stage; hidden entries are no longer probed, improving performance (#2043, Disk)
|
||||
|
||||
Features:
|
||||
* Adds `command.parallel` and `command.useStdErr` config options (Command)
|
||||
* `parallel`: set to `false` to disable parallel execution (see Changes above)
|
||||
* `useStdErr`: set to `true` to use stderr output instead of stdout
|
||||
* Adds the command-line flag `--dynamic-interval <interval-in-ms>` to enable dynamic output auto-refresh (#2041)
|
||||
* Due to internal limitations, some modules do not support dynamic updates (notably Display and Media)
|
||||
* Adds support for using the current playing media's cover art as a logo source (Media / Logo)
|
||||
* Usage: `"logo": { "type": "<image-protocol>", "source": "media-cover" }` in JSON config; or `--<image-protocol> media-cover` in command line
|
||||
* Supports local sources only
|
||||
* Adds native GPU detection support on OpenBSD and NetBSD (instead of depending on `libpciaccess`) (GPU)
|
||||
* No functional changes
|
||||
* Root privileges are required to access PCI config space on OpenBSD (as always)
|
||||
* Adds GPU detection support on GNU/Hurd (GPU)
|
||||
* Requires building with `libpciaccess`
|
||||
* Shows Debian point release on Raspberry Pi OS (#2032, OS, Linux)
|
||||
* Adds `Brush` shell version detection (Shell)
|
||||
* Improves Mac family detection via prefix matching (Host)
|
||||
|
||||
Bugfixes:
|
||||
* Ignores `run-parts` during terminal/shell detection (#2048, Terminal / Shell, Linux)
|
||||
* Fixes fish version detection when `LC_ALL` is set (#2014, Shell, Linux)
|
||||
* Hides the module when no desktop icons are found (#2023, Icons, Windows)
|
||||
* Skips auxiliary display controllers to prevent the module from reporting duplicate entries (#2034, GPU, Linux)
|
||||
* Refines Apple rpath handling; fixes building for the Homebrew version on macOS (#1998, CMake)
|
||||
|
||||
Logos:
|
||||
* Adds Vincent OS and MacaroniOS
|
||||
|
||||
# 2.54.0
|
||||
|
||||
Windows binaries in Release page are now signed by SignPath.
|
||||
|
||||
Changes:
|
||||
* Moves macOS and Windows design language detection from the DE module to the Theme module
|
||||
|
||||
Features:
|
||||
* Adds `--json` and `-j` command line flags as a shortcut for `--format json`
|
||||
* Various improvements to the OS module (OS)
|
||||
* Displays point releases for Debian
|
||||
* Displays code names for Ubuntu
|
||||
* Displays build ID for macOS
|
||||
* Displays code names for Windows (previously shown in the Kernel module)
|
||||
* Adds basic support for Wine (Windows)
|
||||
* Adds basic support for hppa and sh architectures (CPU, Linux)
|
||||
* Improves T-Head SoC name detection from the device tree (#1997, CPU, Linux)
|
||||
* Supports glob patterns in `Disk.hideFolders` (Disk)
|
||||
* For example, `/boot/*` will match both `/boot/efi` and `/boot/firmware`
|
||||
* Adds brightness-level detection for external monitor support on Intel macOS (Brightness, macOS)
|
||||
* Adds configurable spacing between icon and text in keys
|
||||
* `display.key.type: "both-N"` where N is `0-4`
|
||||
* Useful for non-monospaced Nerd Fonts
|
||||
* Adds detection support for modern Samsung Exynos SoCs (CPU, Android)
|
||||
* Adds a new CMake option `-DENABLE_WORDEXP=<ON|OFF>` to enable or disable using `wordexp(3)` for acquiring logo file paths (`logo.source`)
|
||||
* Enabled by default for compatibility
|
||||
* Disabling this option reverts to using `glob(3)`, which is less functional but more secure
|
||||
|
||||
Bugfixes:
|
||||
* Avoids integer overflow when calculating swap size (#1988, Swap, Windows)
|
||||
* Trims whitespace from full user name (Title, macOS)
|
||||
* Fixes default font size for Ghostty (#1986, TerminalFont, Linux)
|
||||
* Works around an issue that could report impossibly high memory usage in rare cases (#1988, Memory, Linux)
|
||||
* Fixes incorrect glibc dependency in polyfilled DEB packages (#1983, Linux)
|
||||
* Fixes corrupted binaries in polyfilled RPM packages (#1990, Linux)
|
||||
* Fixes crashes on ancient Android kernels (#1993, Disk, Android)
|
||||
* Fixes incorrect usage of `glob(3)` (OpenBSD)
|
||||
* Prefers resolutions reported by RandR mode info, fixing incorrect resolutions on XFCE when DPI scaling is enabled (Display, Linux)
|
||||
* Various code cleanups and minor fixes
|
||||
|
||||
Logos:
|
||||
* Adds secureblue, PrismLinux, EmperorOS and Zraxyl
|
||||
* Updates T2
|
||||
|
||||
# 2.53.0
|
||||
|
||||
Changes:
|
||||
@@ -167,7 +841,7 @@ Features:
|
||||
* Added support for interface speed detection on SunOS (LocalIP, SunOS)
|
||||
* Added detection support for Xlibre (#1888, WM, Linux)
|
||||
* Improved the accuracy of color detection (Cursor, macOS)
|
||||
* Improved the proformance of `Nix` package manager detection on macOS by porting optimizations form Linux port (#1893, Packages, macOS)
|
||||
* Improved the performance of `Nix` package manager detection on macOS by porting optimizations from the Linux port (#1893, Packages, macOS)
|
||||
|
||||
Bugfixes:
|
||||
* Fixed custom object inheriting a key from the previous custom object if the key is blank (#1477)
|
||||
@@ -678,7 +1352,7 @@ Features:
|
||||
* Change package manager name of NetBSD from `pkg` to `pkgsrc` (#1515, Packages, NetBSD)
|
||||
* Detect SOC name on RISCV (#1519, CPU, Linux)
|
||||
* Report marketing name of new QS8Es (CPU, Android)
|
||||
* Acquire acquire more os info from lsb-release if missing from os-release (#1521)
|
||||
* Acquire more OS info from lsb-release if missing from os-release (#1521)
|
||||
* CMake: add option `-DCUSTOM_LSB_RELEASE_PATH` to specify the path of `lsb-release` file
|
||||
* `-DCUSTOM_OS_RELEASE_PATH` has been supported since `v2.11.4`
|
||||
* Report more SOC names on Android (CPU, Android)
|
||||
@@ -1146,7 +1820,7 @@ Logos:
|
||||
|
||||
Bugfixes:
|
||||
* Fix bad Intel Arc GPU name detection, which was supposed to be fixed in the last version but the change was reverted accidentally (#1177, GPU, Linux)
|
||||
* Fix arm32 CPU name detection no longer work. Regression of 2.21.2 (CPU, Linux)
|
||||
* Fix arm32 CPU name detection no longer working. Regression of 2.21.2 (CPU, Linux)
|
||||
|
||||
# 2.21.2
|
||||
|
||||
@@ -2641,7 +3315,7 @@ Features:
|
||||
* Enhance `--percent-type` to allow hiding other texts (#387)
|
||||
* Add Wifi module support for Linux
|
||||
* Detect scaled resolutions (Windows, macOS)
|
||||
* Optimise font module printing (Windows)
|
||||
* Optimize font module printing (Windows)
|
||||
* Detect pacman package count inside MSYS2 environment (Windows)
|
||||
* Add Wifi / Battery module support for Android
|
||||
* Disk name support for Linux
|
||||
|
||||
+603
-325
File diff suppressed because it is too large
Load Diff
+724
@@ -0,0 +1,724 @@
|
||||
# Contributing to fastfetch
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
Note
|
||||
</summary>
|
||||
|
||||
This document is generated by AI, and mainly for AI use. It is not a substitute for human review, and may contain errors or omissions. Please verify any information before relying on it.
|
||||
</details>
|
||||
|
||||
Thanks for your interest in fastfetch. This document covers building, architecture, how to add a module or a logo, code style, commit conventions, and the pull request workflow.
|
||||
|
||||
fastfetch is a system information tool written in C23, supporting Linux, macOS, Windows, the BSDs, Solaris, Haiku and Android. The project is borderline obsessive about **startup time** and **optional dependencies** — many design decisions only make sense under that constraint, and this document keeps coming back to it.
|
||||
|
||||
---
|
||||
|
||||
## Table of contents
|
||||
|
||||
- [Contributor quick reference](#contributor-quick-reference)
|
||||
- [Getting started](#getting-started)
|
||||
- [Code map](#code-map)
|
||||
- [Core architecture: modules vs. detection](#core-architecture-modules-vs-detection)
|
||||
- [Module registration](#module-registration)
|
||||
- [Walkthrough: adding a module](#walkthrough-adding-a-module)
|
||||
- [Walkthrough: adding a logo](#walkthrough-adding-a-logo)
|
||||
- [Platform conventions](#platform-conventions)
|
||||
- [Code style](#code-style)
|
||||
- [Commit messages](#commit-messages)
|
||||
- [Changelog](#changelog)
|
||||
- [Tests](#tests)
|
||||
- [Pull requests](#pull-requests)
|
||||
- [Gotchas](#gotchas)
|
||||
|
||||
---
|
||||
|
||||
## Contributor quick reference
|
||||
|
||||
| Task | Start here | Verify with |
|
||||
|---|---|---|
|
||||
| Build and run fastfetch | `run.sh`, `CMakeLists.txt` | `./run.sh` |
|
||||
| Add a module | `src/modules/<name>/`, `src/detection/<name>/`, `src/modules/modules.c` | `cmake -B build && cmake --build build -j` |
|
||||
| Add a platform implementation | `src/detection/<name>/<name>_<platform>.c` | Build on the target platform or CI |
|
||||
| Add an ASCII logo | `src/logo/ascii/<letter>/<name>.txt`, matching `<letter>.inc` | `./build/fastfetch --logo <name>` |
|
||||
| Change formatting or JSON output | `src/modules/<name>/<name>.c` | `./build/fastfetch -s <name> --format json` |
|
||||
| Change shared formatting or containers | `src/common/format.h`, `src/common/color.h`, `src/common/FFstrbuf.h` | Build and run the matching test |
|
||||
| Run the test suite | `tests/`, `build/` | `cd build && ctest --output-on-failure` |
|
||||
|
||||
For a normal code change, the shortest useful loop is: configure, build the `fastfetch` target, run the affected module, then run the tests. If you add a directory or a generated input, re-run `cmake -B build` so CMake refreshes its file globs.
|
||||
|
||||
---
|
||||
|
||||
## Getting started
|
||||
|
||||
### Building
|
||||
|
||||
The quickest way is `run.sh` in the repository root — it creates `build/`, configures, compiles and runs the binary:
|
||||
|
||||
```sh
|
||||
./run.sh # build and run
|
||||
./run.sh --format json # arguments are forwarded to fastfetch
|
||||
```
|
||||
|
||||
Manual build:
|
||||
|
||||
```sh
|
||||
cmake -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
cmake --build build --target fastfetch -j$(nproc)
|
||||
./build/fastfetch
|
||||
```
|
||||
|
||||
The default build type is `RelWithDebInfo`. LTO is enabled whenever `ENABLE_LTO=ON` **and** `CMAKE_BUILD_TYPE != Debug` — so the default already has it, and only `Debug` builds lack it. This matters because LTO here is not merely an optimization: it is what strips the code of disabled modules. See [Gotchas](#gotchas).
|
||||
|
||||
### Common build options
|
||||
|
||||
| Option | Default | Notes |
|
||||
|---|---|---|
|
||||
| `CMAKE_BUILD_TYPE` | `RelWithDebInfo` | LTO is on for anything but `Debug` |
|
||||
| `BUILD_TESTS` | `OFF` | Builds the unit tests in `tests/` |
|
||||
| `BUILD_FLASHFETCH` | `ON` | Also builds the stripped-down `flashfetch` |
|
||||
| `BINARY_LINK_TYPE` | `dlopen` | `dlopen` / `dynamic` / `static` |
|
||||
| `ENABLE_ASAN` | `OFF` | Address Sanitizer |
|
||||
| `ENABLE_LTO` | `ON` | Link-time optimization |
|
||||
| `MODULE_DISABLE_<NAME>` | `OFF` | Disable a module, e.g. `MODULE_DISABLE_GPU=ON` |
|
||||
| `SET_TWEAK` | `ON` | Appends a tweak to the dev version; turned off for releases |
|
||||
|
||||
`BINARY_LINK_TYPE=dlopen` (the default) is a deliberate design choice: optional dependencies (Vulkan, Wayland, DBus, ImageMagick, chafa, …) are loaded at runtime, so a missing library never prevents startup. When adding a third-party dependency, use the dlopen helpers in `common/library.h` — do not link it directly.
|
||||
|
||||
For a minimal-dependency build, see `.github/workflows/build-no-features-test.yml`:
|
||||
|
||||
```sh
|
||||
cmake -DBUILD_TESTS=On -DENABLE_VULKAN=OFF -DENABLE_WAYLAND=OFF -DENABLE_X11=OFF \
|
||||
-DENABLE_DBUS=OFF -DENABLE_ZLIB=OFF ... .
|
||||
```
|
||||
|
||||
### Dependencies
|
||||
|
||||
Required: CMake ≥ 3.21 and a C23 compiler (GCC, Clang or MSVC). Everything else is optional.
|
||||
|
||||
Optional dependencies are auto-detected: libpci, libdrm, vulkan, wayland, xcb, xrandr, dbus, sqlite3, rpm, imagemagick{6,7}, chafa, zlib, egl, glx, opencl, freetype, pulse, ddcutil, elf, libzfs, and more.
|
||||
|
||||
---
|
||||
|
||||
## Code map
|
||||
|
||||
```
|
||||
src/
|
||||
├── fastfetch.c entry point: CLI parsing, module dispatch, main loop (36 KB)
|
||||
├── flashfetch.c entry point for the stripped-down build
|
||||
├── options/ global (non-module) config: general / display / logo
|
||||
├── modules/ module layer — module formatting and output
|
||||
├── detection/ detection layer — platform-specific data retrieval
|
||||
├── common/ infrastructure: FFstrbuf, FFlist, formatting, printing, networking
|
||||
├── logo/ 530 ASCII logos plus the image logo backends
|
||||
└── 3rdparty/ yyjson, widecharwidth, display-library
|
||||
```
|
||||
|
||||
Flow of control:
|
||||
|
||||
```
|
||||
fastfetch.c → options/ (global configuration)
|
||||
→ modules/ (76 modules, formatting and output)
|
||||
→ detection/ (one platform implementation each, raw data)
|
||||
→ common/ (infrastructure)
|
||||
```
|
||||
|
||||
The number of module directories and detection directories does not match, and that is expected. The following relationships are structural rather than a fixed inventory:
|
||||
|
||||
- **13 modules have no detection directory** — they are either pure layout (`break`, `separator`, `colors`, `title`, `logo`) or reuse someone else's detection result (`display`, `monitor`, `kernel`, `shell`, `terminal`, `player`, `custom`, `datetime`).
|
||||
- **4 detection directories serve modules with different names** — `displayserver` (→ `display`, `monitor`), `gtk_qt` (→ `theme`, `icons`, `font`, `cursor`), `terminalshell` (→ `terminal`, `shell`) and `libc`.
|
||||
|
||||
So do not assume `modules/<x>/` always has a matching `detection/<x>/`.
|
||||
|
||||
### Layer boundaries
|
||||
|
||||
| Layer | Owns | Must not |
|
||||
|---|---|---|
|
||||
| `options/` | **Global** config (colors, logo, threading, timeouts) | hold per-module options |
|
||||
| `modules/` | formatting, printing, JSON serialization | read `/proc`, call Win32 APIs, parse sysfs |
|
||||
| `detection/` | cross-platform data retrieval, clean result structs | print anything, read display config |
|
||||
| `common/` | general-purpose utilities, no business logic | depend on a specific module |
|
||||
|
||||
The test is simple: **no file under `detection/` should contain `printf` or read `instance.config`.** Symmetrically, no file under `modules/` should contain `#ifdef __linux__`.
|
||||
|
||||
---
|
||||
|
||||
## Core architecture: modules vs. detection
|
||||
|
||||
This is the single most important convention in the codebase. Every feature is a fixed set of files — using CPU as the example:
|
||||
|
||||
```
|
||||
modules/cpu/option.h module option struct
|
||||
modules/cpu/cpu.c formatting and output
|
||||
detection/cpu/cpu.h platform-independent interface
|
||||
detection/cpu/cpu_linux.c ┐
|
||||
detection/cpu/cpu_apple.c │
|
||||
detection/cpu/cpu_windows.c ├─ platform implementations, one linked per build
|
||||
detection/cpu/cpu_bsd.c │
|
||||
detection/cpu/cpu_nosupport.c ┘
|
||||
```
|
||||
|
||||
The interface is deliberately minimal — usually just two things:
|
||||
|
||||
```c
|
||||
typedef struct FFCPUResult { ... } FFCPUResult; // result struct
|
||||
const char* ffDetectCPU(const FFCPUOptions* options, FFCPUResult* cpu);
|
||||
```
|
||||
|
||||
The `const char*` return value is an **error string**; `nullptr` means success. This pattern is used throughout `detection/` — please keep it consistent.
|
||||
|
||||
Helper functions are only exposed when they are genuinely shared between platform implementations (as in `cpu.h`: `ffCPUAppleCodeToName`, `ffCPUDetectByCpuid`).
|
||||
|
||||
**The payoff:** adding a platform never touches `modules/`; fixing output formatting never touches `detection/`.
|
||||
|
||||
---
|
||||
|
||||
## Module registration
|
||||
|
||||
### The descriptor
|
||||
|
||||
Every module exports one `FFModuleBaseInfo` (defined in `common/option.h:46`) — essentially a hand-written vtable:
|
||||
|
||||
```c
|
||||
typedef struct FFModuleBaseInfo {
|
||||
const char* name; // lookup key, e.g. "cpu"
|
||||
const char* description; // help text
|
||||
FFModuleDisplayName displayName; // module name in 20 languages
|
||||
|
||||
void (*initOptions)(void* options);
|
||||
void (*destroyOptions)(void* options);
|
||||
void (*parseJsonObject)(void* options, struct yyjson_val* module);
|
||||
bool (*printModule)(void* options);
|
||||
bool (*generateJsonResult)(void* options, yyjson_mut_doc*, yyjson_mut_val*);
|
||||
void (*generateJsonConfig)(void* options, yyjson_mut_doc*, yyjson_mut_val*);
|
||||
|
||||
FFModuleFormatArgList formatArgs; // format placeholder table
|
||||
const uint8_t defaultOrder; // sort weight
|
||||
} FFModuleBaseInfo;
|
||||
```
|
||||
|
||||
The source comment openly admits this is UB — `void*` is not compatible with `FF*Options*`. It is a pragmatic compromise to get polymorphism in C. Don't try to "fix" it.
|
||||
|
||||
### The registry: a first-letter hash bucket
|
||||
|
||||
`src/modules/modules.c` defines 26 `static FFModuleBaseInfo*` arrays (`A[]` through `Z[]`), each terminated by `nullptr`, collected into `ffModuleInfos[26]`:
|
||||
|
||||
```c
|
||||
FFModuleBaseInfo** modules = ffModuleInfos[toupper(name[0]) - 'A']; // O(1) bucket lookup
|
||||
for (; *modules; ++modules) { // linear scan in the bucket
|
||||
if (ffStrEqualsIgnCase(name, (*modules)->name)) { ... }
|
||||
}
|
||||
```
|
||||
|
||||
The registry is small enough that a subtraction plus a few string comparisons is preferable to a general-purpose hash table. When adding a module, place its descriptor in the bucket matching the first letter of `.name`; keep the existing `nullptr` terminator at the end.
|
||||
|
||||
### The calling convention: zero heap allocation
|
||||
|
||||
Every dispatch site (`jsonconfig.c:98`, `commandoption.c:189`) follows the same pattern:
|
||||
|
||||
```c
|
||||
alignas(uint64_t) uint8_t optionBuf[FF_OPTION_MAX_SIZE]; // 256 bytes, on the stack
|
||||
baseInfo->initOptions(optionBuf);
|
||||
baseInfo->parseJsonObject(optionBuf, jsonVal); // JSONC path only
|
||||
baseInfo->printModule(optionBuf); // or generateJsonResult
|
||||
baseInfo->destroyOptions(optionBuf);
|
||||
```
|
||||
|
||||
`FF_OPTION_MAX_SIZE = 1 << 8` (256 bytes). Every module's `option.h` must end with:
|
||||
|
||||
```c
|
||||
static_assert(sizeof(FFCPUOptions) <= FF_OPTION_MAX_SIZE, "FFCPUOptions size exceeds maximum allowed size");
|
||||
```
|
||||
|
||||
**Meaning: no module option struct may exceed 256 bytes.** Hard constraint, enforced at compile time.
|
||||
|
||||
The three dispatch entry points:
|
||||
|
||||
| Entry point | Location | Used for |
|
||||
|---|---|---|
|
||||
| `parseModuleJsonObject` | `common/impl/jsonconfig.c:90` | the `modules[]` array in a JSONC config |
|
||||
| `parseStructureCommand` | `common/impl/commandoption.c:181` | the colon-separated structure string |
|
||||
| `ffParseModuleOptions` | `common/impl/commandoption.c:13` | **deprecated** — see [Gotchas](#4-cli-module-options-are-removed) |
|
||||
|
||||
### Build-time module discovery
|
||||
|
||||
`CMakeLists.txt:131` globs `src/modules/*/` and generates a `MODULE_DISABLE_<UPPER>` option per directory:
|
||||
|
||||
```cmake
|
||||
file(GLOB FF_MODULE_DIRS RELATIVE "..." ".../src/modules/*/")
|
||||
foreach(FF_MODULE_DIR ${FF_MODULE_DIRS})
|
||||
option(MODULE_DISABLE_${FF_MODULE_UPPER} "Disable module ${FF_MODULE_DIR}" OFF)
|
||||
endforeach()
|
||||
```
|
||||
|
||||
**Adding a module requires no CMake change.** The same trick generates the package manager switches (`:146` regex-scans `src/modules/packages/option.h` for `FF_PACKAGES_FLAG_*_BIT`).
|
||||
|
||||
---
|
||||
|
||||
## Walkthrough: adding a module
|
||||
|
||||
Adding a `Foo` module, step by step.
|
||||
|
||||
### 1. Define the option struct
|
||||
|
||||
`src/modules/foo/option.h`:
|
||||
|
||||
```c
|
||||
#pragma once
|
||||
|
||||
#include "common/option.h"
|
||||
|
||||
typedef struct FFFooOptions {
|
||||
FFModuleArgs moduleArgs; // must be the first field
|
||||
bool showBar;
|
||||
} FFFooOptions;
|
||||
|
||||
static_assert(sizeof(FFFooOptions) <= FF_OPTION_MAX_SIZE, "FFFooOptions size exceeds maximum allowed size");
|
||||
```
|
||||
|
||||
`FFModuleArgs` must come first. It provides `key`, `format`, `outputColor`, `keyColor`, `keyIcon` and `keyWidth`; because it is the first field, `ffJsonConfigParseModuleArgs()` can handle these generically and you get them **for free — no parsing code to write**.
|
||||
|
||||
Note these fields can only be set through the JSON config; CLI module options have been removed (see [Gotchas](#4-cli-module-options-are-removed)).
|
||||
|
||||
### 2. Implement detection
|
||||
|
||||
`src/detection/foo/foo.h`:
|
||||
|
||||
```c
|
||||
#pragma once
|
||||
#include "fastfetch.h"
|
||||
|
||||
typedef struct FFFooResult {
|
||||
FFstrbuf name;
|
||||
uint32_t count;
|
||||
} FFFooResult;
|
||||
|
||||
const char* ffDetectFoo(const FFFooOptions* options, FFFooResult* result);
|
||||
```
|
||||
|
||||
`src/detection/foo/foo_linux.c`:
|
||||
|
||||
```c
|
||||
#include "foo.h"
|
||||
|
||||
const char* ffDetectFoo(const FFFooOptions* options, FFFooResult* result) {
|
||||
// read /sys, /proc, sysfs, dbus, ...
|
||||
return nullptr; // success; return an error string on failure
|
||||
}
|
||||
```
|
||||
|
||||
**Write one file per target platform, and a `foo_nosupport.c` fallback for the rest.** There are already 45 `*_nosupport.c` files doing exactly this.
|
||||
|
||||
### 3. Implement the module
|
||||
|
||||
`src/modules/foo/foo.c` — implement the six functions, then define the descriptor:
|
||||
|
||||
```c
|
||||
FFModuleBaseInfo ffFooModuleInfo = {
|
||||
.name = "Foo",
|
||||
.description = "Print foo information",
|
||||
.displayName = {
|
||||
.en = "Foo", .ar = "Foo", .cs = "Foo", .de = "Foo", .es = "Foo",
|
||||
.fr = "Foo", .gl = "Foo", .he = "Foo", .id = "Foo", .it = "Foo",
|
||||
.ja = "Foo", .ko = "Foo", .pl = "Foo", .pt = "Foo", .ru = "Foo",
|
||||
.tr = "Foo", .uk = "Foo", .vi = "Foo", .zh_CN = "Foo", .zh_TW = "Foo",
|
||||
},
|
||||
.initOptions = (void*) ffInitFooOptions,
|
||||
.destroyOptions = (void*) ffDestroyFooOptions,
|
||||
.parseJsonObject = (void*) ffParseFooJsonObject,
|
||||
.printModule = (void*) ffPrintFoo,
|
||||
.generateJsonResult = (void*) ffGenerateFooJsonResult,
|
||||
.generateJsonConfig = (void*) ffGenerateFooJsonConfig,
|
||||
.formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) {
|
||||
{ "Name", "name" },
|
||||
{ "Count", "count" },
|
||||
})),
|
||||
.defaultOrder = 73,
|
||||
};
|
||||
```
|
||||
|
||||
Points to note:
|
||||
|
||||
- **`displayName`** is a literal block of all 20 language fields — there is no shortcut macro, so copy the layout from a neighboring module: **`en`, `ar`, `cs`, `de`, `es`, `fr`, `gl`, `he`, `id`, `it`, `ja`, `ko`, `pl`, `pt`, `ru`, `tr`, `uk`, `vi`, `zh_CN`, `zh_TW`**.
|
||||
**Fill in all 20.** The struct is read by byte offset (see [Gotchas](#6-localization-uses-byte-offsets-not-enums)) and there is **no fallback** — a missing field means the key prints empty in that language.
|
||||
- **`formatArgs`** must be exhaustive. It drives the placeholder list printed by `fastfetch -h foo-format`; **anything you omit is invisible and unusable to the user.**
|
||||
- The `moduleFormat` section in `doc/json_schema.json` is generated by `fastfetch -h format-json`. Its metadata comes from `FFModuleBaseInfo::formatArgs`. To keep the schema and module descriptors consistent, do not edit the `moduleFormat` section in `doc/json_schema.json` by hand; update the module metadata and regenerate it instead.
|
||||
- **`defaultOrder`**: use the current maximum plus 1. Search the existing descriptors for `.defaultOrder =` before choosing a value; do not copy a hard-coded value from this document. Leaving it out, or setting it to `0`, makes the module **disappear** from the interactive `--gen-config` picker. Only `logo`, `command` and `custom` do this deliberately, because they need user arguments or are invoked directly by the display layer.
|
||||
|
||||
### 4. Register it
|
||||
|
||||
- Add `#include "modules/foo/foo.h"` to `src/modules/modules.h`
|
||||
- Insert into the `F[]` array in `src/modules/modules.c`:
|
||||
|
||||
```c
|
||||
#if !FF_MODULE_DISABLE_FOO
|
||||
&ffFooModuleInfo,
|
||||
#endif
|
||||
```
|
||||
|
||||
`FF_MODULE_DISABLE_FOO` is generated by CMake — you do not define it yourself.
|
||||
|
||||
### 5. Modules that need warm-up
|
||||
|
||||
If your module needs a sampling interval (CPU usage) or a network round-trip (public IP, weather), also implement `ffPrepareFoo()` and register it in the switch inside `ffPrepareCommandOption()` in `common/impl/commandoption.c`, under the right first-letter `case`. Six modules do this today: CPUUsage, DiskIO, NetIO, PublicIP, Top and Weather.
|
||||
|
||||
### 6. Verify
|
||||
|
||||
```sh
|
||||
cmake -B build && cmake --build build -j
|
||||
./build/fastfetch -s foo --format json # JSON output
|
||||
./build/fastfetch -h foo-format # list formatArgs placeholders
|
||||
./build/fastfetch --gen-config # confirm it appears in the picker
|
||||
```
|
||||
|
||||
Note the `-format` suffix on the help flag: `fastfetch -h foo` does not work, only `fastfetch -h foo-format`.
|
||||
|
||||
---
|
||||
|
||||
## Walkthrough: adding a logo
|
||||
|
||||
A new logo **must** have a corresponding "Logo Request" issue, linked from the PR with `Closes #1234`. Logo PRs without a linked issue are not accepted.
|
||||
|
||||
### 1. Drop in the ASCII file
|
||||
|
||||
```
|
||||
src/logo/ascii/<first-letter>/<distro>.txt
|
||||
```
|
||||
|
||||
For example `src/logo/ascii/o/omarchy.txt`. Directories are already split by first letter (`a/` … `z/`, plus `_/`).
|
||||
|
||||
The file is plain ASCII art with `$1` … `$9` as color placeholders:
|
||||
|
||||
```
|
||||
$3 ,-^-___
|
||||
$3 /\\\///
|
||||
$2refined.$1 /\\\\//
|
||||
```
|
||||
|
||||
- `$1` … `$9` map to palette slots 1–9; at most 9 (`FASTFETCH_LOGO_MAX_COLORS = 9`)
|
||||
- `$$` is a literal `$`
|
||||
- Characters without a placeholder inherit the current color. Of the 530 existing logos, 239 use no placeholders at all (monochrome) and 291 do — **new logos should use placeholders**; monochrome is a legacy style
|
||||
- Tabs are expanded to 4 spaces
|
||||
- Colors can be overridden with `--logo-color-1` … `--logo-color-9`
|
||||
|
||||
### 2. Register it in the `.inc`
|
||||
|
||||
CMake turns each `.txt` into a `FASTFETCH_DATATEXT_LOGO_<UPPERCASE>` macro (`CMakeLists.txt:418`), but **the registry itself is maintained by hand**. Edit `src/logo/ascii/<first-letter>.inc`:
|
||||
|
||||
```c
|
||||
#ifdef FASTFETCH_DATATEXT_LOGO_OMARCHY
|
||||
// Omarchy
|
||||
{
|
||||
.names = { "omarchy", "Omarchy" },
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_OMARCHY,
|
||||
.colors = {
|
||||
FF_COLOR_FG_BLUE,
|
||||
FF_COLOR_FG_WHITE,
|
||||
FF_COLOR_FG_CYAN,
|
||||
},
|
||||
},
|
||||
#endif
|
||||
```
|
||||
|
||||
- `names` is matched case-insensitively. Do not add names that differ only by case, because they can never be distinguished. Every name is also shown by `--list-logos`, so use user-friendly spelling such as an initial capital where appropriate.
|
||||
- For a new logo, use exactly one name unless there is a specific compatibility reason to add more. That name should first be the `ID` from `/etc/os-release`. If the ID cannot distinguish this logo from another logo for the same OS, use the `NAME` value instead. `logoGetBuiltinDetected` in `src/logo/logo.c` documents the detection order: `ID`, then `NAME`, then tokens from `ID_LIKE`, then the platform name fallback. Manual `logo-source` selection uses the name directly.
|
||||
- `colors` is positional — entry 0 is `$1`, entry 1 is `$2`, and so on
|
||||
- `colors[0]` also becomes the title color and `colors[1]` the key color, unless the user overrides them
|
||||
|
||||
If the same OS has multiple logo variants, mark the variant explicitly with `.type`:
|
||||
|
||||
```c
|
||||
.type = FF_LOGO_LINE_TYPE_SMALL_BIT,
|
||||
```
|
||||
|
||||
Use `FF_LOGO_LINE_TYPE_ALTER_BIT` for an alternate logo, `FF_LOGO_LINE_TYPE_SMALL_BIT` for a small logo, or combine the flags when both apply. This is also a lookup optimization: a logo marked `FF_LOGO_LINE_TYPE_SMALL_BIT` is considered only for `type = small`, while a logo marked `FF_LOGO_LINE_TYPE_ALTER_BIT` is never selected by automatic detection. Alternate logos are available only when explicitly requested through `--logo <source>`.
|
||||
|
||||
### 3. Verify
|
||||
|
||||
```sh
|
||||
./build/fastfetch --logo omarchy
|
||||
./build/fastfetch --list-logos | grep -i omarchy
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Platform conventions
|
||||
|
||||
The `detection/` layer picks its implementation by **filename suffix**; the choice is made at build time from `CMAKE_SYSTEM_NAME`:
|
||||
|
||||
| Suffix | Platform |
|
||||
|---|---|
|
||||
| `_linux.c` | Linux |
|
||||
| `_apple.c` / `_apple.m` | macOS / iOS (`.m` for Objective-C) |
|
||||
| `_windows.c` / `_windows.cpp` | Windows (`.cpp` for WinRT / WMI) |
|
||||
| `_bsd.c` | FreeBSD |
|
||||
| `_nbsd.c` | NetBSD |
|
||||
| `_obsd.c` | OpenBSD |
|
||||
| `_sunos.c` | Solaris / illumos |
|
||||
| `_haiku.c` / `.cpp` | Haiku |
|
||||
| `_android.c` | Android (Termux) |
|
||||
| `_gnu.c` | GNU/Hurd |
|
||||
| `_nosupport.c` | Empty fallback |
|
||||
|
||||
Current distribution of platform files in `detection/`:
|
||||
|
||||
| Suffix | Files | Suffix | Files |
|
||||
|---|---|---|---|
|
||||
| `_linux` | 58 | `_obsd` | 16 |
|
||||
| `_windows` | 47 | `_haiku` | 13 |
|
||||
| `_apple` | 46 | `_android` | 12 |
|
||||
| `_nosupport` | 45 | `_gnu` | 3 |
|
||||
| `_bsd` | 29 | | |
|
||||
| `_sunos` | 19 | | |
|
||||
| `_nbsd` | 17 | | |
|
||||
|
||||
(These are repository inventory figures, counting `.c`, `.m`, `.cpp`, and `.h`; they may change as platforms and modules are added.)
|
||||
|
||||
**Don't pile `#ifdef __linux__` into one file.** When adding platform support, copy the closest existing implementation and change the suffix.
|
||||
|
||||
`common/` uses the same idea: `common/impl/` contains `io_unix.c` / `io_windows.c`, `netif_linux.c` / `netif_apple.c` / `netif_bsd.c` and so on, with `common/apple/`, `common/windows/` and `common/haiku/` holding platform-specific helpers.
|
||||
|
||||
When several platform suffixes could apply, use the most specific implementation supported by the build system (for example, `_nbsd.c` instead of the generic `_bsd.c` on NetBSD). Keep the generic file as the fallback for platforms that share its conventions.
|
||||
|
||||
---
|
||||
|
||||
## Code style
|
||||
|
||||
### Formatting
|
||||
|
||||
The project uses clang-format with `BasedOnStyle: LLVM` plus these key overrides:
|
||||
|
||||
```yaml
|
||||
IndentWidth: 4
|
||||
UseTab: Never
|
||||
ColumnLimit: 0 # never wrap
|
||||
InsertBraces: true # braces even on single-statement ifs
|
||||
PointerAlignment: Left # char* p, not char *p
|
||||
SortIncludes: Never # include order is managed by hand
|
||||
AlignAfterOpenBracket: DontAlign
|
||||
BinPackParameters: false # all params on one line, or one per line
|
||||
```
|
||||
|
||||
Before committing:
|
||||
|
||||
```sh
|
||||
clang-format -i src/modules/foo/*.c src/modules/foo/*.h
|
||||
```
|
||||
|
||||
`src/3rdparty/**`, `build/**` and `src/logo/builtin.c` are listed in `.clang-format-ignore` — **do not reformat them.**
|
||||
|
||||
`.editorconfig` adds LF line endings, 4-space indent, a final newline, and trailing whitespace trimmed (except in Markdown).
|
||||
|
||||
### Naming
|
||||
|
||||
| Kind | Convention | Example |
|
||||
|---|---|---|
|
||||
| Functions | `ff` + PascalCase | `ffDetectCPU`, `ffPrintCPU` |
|
||||
| Types | `FF` + PascalCase | `FFCPUResult`, `FFModuleBaseInfo` |
|
||||
| Variables / fields | camelCase | `coresPhysical`, `keyWidth` |
|
||||
| Macros | SCREAMING_SNAKE_CASE | `FF_OPTION_MAX_SIZE` |
|
||||
| Module options | `FF<Name>Options` | `FFCPUOptions` |
|
||||
| Detection results | `FF<Name>Result` | `FFCPUResult` |
|
||||
|
||||
### Spelling
|
||||
|
||||
CI runs codespell (`.codespellrc`). Known false positives live in `ignore-words-list` (`iterm`, `compiletime`, and various non-English distro words). Add new words there rather than changing the code.
|
||||
|
||||
### Compiler warnings
|
||||
|
||||
The build enables `-Wall -Wextra -Wconversion` plus several `-Werror`s:
|
||||
|
||||
```
|
||||
-Werror=uninitialized -Werror=return-type -Werror=vla
|
||||
-Werror=incompatible-pointer-types -Werror=implicit-function-declaration -Werror=int-conversion
|
||||
```
|
||||
|
||||
**`-Wconversion` is strict**: every implicit narrowing conversion needs an explicit cast.
|
||||
|
||||
---
|
||||
|
||||
## Commit messages
|
||||
|
||||
Format:
|
||||
|
||||
```
|
||||
<Scope>[ (Platform)]: <third-person singular verb> <object>
|
||||
```
|
||||
|
||||
Scope is the module or subsystem name; Platform is optional. Use the third-person singular present tense, capitalize the first letter, no trailing period.
|
||||
|
||||
Real examples from recent history:
|
||||
|
||||
```
|
||||
Processes (Haiku): honors `options->countKprocs`
|
||||
WM (macOS): improves reliability of WM plugin detection
|
||||
Memory (Windows): prefers `NQSI`
|
||||
Top (Linux): improves performance of `stat` parsing
|
||||
Logo (Builtin): adds omarchy
|
||||
Global: introduces global macro `FF_PATH_PKG_BASE` to replace `_PATH_LOCALBASE`
|
||||
LM (OpenBSD): adds support
|
||||
CI: disables fail on alert
|
||||
Doc: updates README
|
||||
Presets: moves `top` to the bottom of running modules [ci skip]
|
||||
```
|
||||
|
||||
Common verbs: `adds`, `removes`, `fixes`, `improves`, `updates`, `corrects`, `prefers`, `honors`, `disables`, `enables`, `introduces`, `detects`, `reports`, `skips`, `uses`.
|
||||
|
||||
Scopes in use: `Top`, `Processes`, `Memory`, `Logo (Builtin)`, `CI`, `Doc`, `Presets`, `Global`, plus individual module names.
|
||||
|
||||
Documentation-only changes get a `[ci skip]` suffix.
|
||||
|
||||
---
|
||||
|
||||
## Changelog
|
||||
|
||||
User-visible changes go into `CHANGELOG.md`, under the topmost version heading:
|
||||
|
||||
```markdown
|
||||
# Unreleased
|
||||
|
||||
Changes:
|
||||
* The DE / WM / LM modules now reports the full name ...
|
||||
|
||||
Features:
|
||||
* Added Top module to print processes with the highest CPU, memory or disk I/O usage. (Top)
|
||||
* Improved Wi-Fi module
|
||||
* Added Wifi channel width detection, exposed via `{channel-width}` in custom format.
|
||||
* Improved Wifi channel frequency accuracy on Windows, macOS.
|
||||
* Added Battery detection support on SunOS. (Battery, SunOS)
|
||||
|
||||
Bugfixes:
|
||||
* Fixed I/O rate calculation precision in DiskIO and NetIO. (DiskIO / NetIO)
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
- Three sections: `Changes:` (behavior changes), `Features:`, `Bugfixes:`
|
||||
- Past tense: `Added` / `Fixed` / `Improved`
|
||||
- End each entry with its scope: `(Module, Platform)` or `(ModuleA / ModuleB)`
|
||||
- Sub-bullets are indented 4 spaces
|
||||
|
||||
---
|
||||
|
||||
## Tests
|
||||
|
||||
Tests are standalone executables in `tests/` using a `VERIFY` macro that exits non-zero on failure:
|
||||
|
||||
```c
|
||||
#define VERIFY(expression) \
|
||||
if (!(expression)) testFailed(&strbuf, #expression, __LINE__)
|
||||
```
|
||||
|
||||
Current tests: `strbuf.c`, `list.c`, `format.c`, `color.c`, `duration.c`, `strutil.c`.
|
||||
|
||||
```sh
|
||||
cmake -B build -DBUILD_TESTS=On
|
||||
cmake --build build
|
||||
cd build && ctest --output-on-failure
|
||||
```
|
||||
|
||||
Coverage focuses on the core data structures and the formatting engine in `common/`. The `detection/` layer has no automated tests (it depends too heavily on a real system) and is instead covered by the CI matrix — 20 workflows under `.github/workflows/` spanning Linux (including musl, loong64, armv7l, i686), macOS, Windows, FreeBSD, NetBSD, OpenBSD, DragonFly, Solaris, OmniOS and Haiku, plus spellcheck and benchmark jobs.
|
||||
|
||||
**If you touch `common/FFstrbuf.h`, `common/format.h` or `common/color.h`, please extend the matching test.**
|
||||
|
||||
---
|
||||
|
||||
## Pull requests
|
||||
|
||||
1. **Open an issue first** (feature request / bug report / logo request) so you don't waste effort. Templates are in `.github/ISSUE_TEMPLATE/`.
|
||||
2. Branch off `dev` — **`dev` is the main development branch**, not `master`.
|
||||
3. Follow the [commit message convention](#commit-messages).
|
||||
4. Update `CHANGELOG.md` for user-visible changes.
|
||||
5. Open the PR against `dev` and fill in `.github/pull_request_template.md`:
|
||||
- Summary
|
||||
- Related issue (**required for new logos**, otherwise the PR won't be accepted)
|
||||
- Changes
|
||||
- Screenshots (required for visual changes)
|
||||
- Checklist: confirm you tested locally
|
||||
|
||||
### Pre-submit checklist
|
||||
|
||||
```sh
|
||||
clang-format -i <changed files> # format
|
||||
codespell # spelling
|
||||
cmake -B build -DBUILD_TESTS=On && cmake --build build -j
|
||||
cd build && ctest --output-on-failure # tests
|
||||
./build/fastfetch --format json # verify JSON output is well-formed
|
||||
./build/fastfetch -c presets/all.jsonc --stat false # smoke-test every module
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Gotchas
|
||||
|
||||
Things that are easy to get wrong when reading this codebase. Most of them follow from the "obsessively fast startup" goal.
|
||||
|
||||
### 1. Option structs must not exceed 256 bytes
|
||||
|
||||
`FF_OPTION_MAX_SIZE = 1 << 8`. Exceeding it is caught at compile time by `static_assert`. Don't try to raise the value — it determines the stack cost of every module invocation.
|
||||
|
||||
### 2. `FF_MODULE_DISABLE_*` controls registration, not compilation
|
||||
|
||||
```c
|
||||
// verbatim from the top of modules/modules.c:
|
||||
// FF_MODULE_DISABLE_<module> only controls if the module is registered,
|
||||
// the module code itself is still compiled.
|
||||
// We rely `LTO` to remove the unused code (only enabled in Release mode)
|
||||
```
|
||||
|
||||
**Disabling modules in a Debug build does not shrink the binary.** LTO is enabled whenever `CMAKE_BUILD_TYPE != Debug`, and the default `RelWithDebInfo` already satisfies that — so measure size with `RelWithDebInfo` or `Release`, never with `Debug`. (The "Release mode" wording in the comment above is imprecise.)
|
||||
|
||||
### 3. CMake globs don't trigger reconfiguration
|
||||
|
||||
Both the module directories and the logo files are discovered by glob. CMake will not notice new files on its own — you need to re-run `cmake -B build` (or delete `build/CMakeCache.txt` and start over). This is the classic CMake footgun.
|
||||
|
||||
### 4. CLI module options are removed
|
||||
|
||||
Per-module command-line flags such as `--cpu-temp` are **no longer supported**. The only job of `ffParseModuleOptions` now is to translate the flag into a JSON key, then `exit(477)` with a pointer to the config file:
|
||||
|
||||
```
|
||||
Error: Unsupported module option: --cpu-temp
|
||||
Support of module options has been removed. Please add the flag to the JSON config instead.
|
||||
Example (demonstration only): `{ "modules": [ { "type": "cpu", "temp": true } ] }`
|
||||
```
|
||||
|
||||
**JSONC is the first-class configuration interface; the command line is not.** When adding module options, implement `parseJsonObject` only — do not add a CLI branch.
|
||||
|
||||
### 5. `defaultOrder = 0` hides a module from `--gen-config`
|
||||
|
||||
`collectModuleInfos` (`genconfig.c:186`) skips any module whose `defaultOrder` is `0`. C zero-initializes the field, so **omitting it is the same as setting it to 0**. Only `logo`, `command` and `custom` do this on purpose.
|
||||
|
||||
`defaultOrder` affects only the ordering in the interactive `--gen-config` picker; it has no effect on runtime output order.
|
||||
|
||||
### 6. Localization uses byte offsets, not enums
|
||||
|
||||
`instance.config.display.keyLanguage` does not hold a language enum — it holds a **byte offset** such as `offsetof(FFModuleDisplayName, zh_CN)`. The macro `FF_MODULE_GET_DISPLAY_NAME` (`common/option.h:123`) does plain pointer arithmetic with it:
|
||||
|
||||
```c
|
||||
#define FF_MODULE_GET_DISPLAY_NAME(moduleName) \
|
||||
(*(const char**) ((uint8_t*) &ff ## moduleName ## ModuleInfo.displayName + instance.config.display.keyLanguage))
|
||||
```
|
||||
|
||||
Consequence: **the field order of `FFModuleDisplayName` must never change** — reordering silently scrambles every language.
|
||||
|
||||
### 7. The `multithreading` switch barely does anything
|
||||
|
||||
The global `multithreading` option currently takes effect in exactly one place: `common/impl/networking_linux.c:339`. Modules are still printed sequentially. Modules that need concurrency go through the `ffPrepare*` warm-up hooks instead, which start sampling or fire off requests before the print loop begins.
|
||||
|
||||
### 8. Don't print or read config inside `detection/`
|
||||
|
||||
The `detection/` layer must stay pure: read system state, fill a struct, return an error string. Any `printf` or any read of `instance.config` there is a design error.
|
||||
|
||||
### 9. `src/logo/builtin.c` and `3rdparty/` are formatting-exempt
|
||||
|
||||
The former is a large generated/hand-maintained data table, the latter is upstream code. Both are excluded via `.clang-format-ignore` — leave them alone.
|
||||
|
||||
---
|
||||
|
||||
## Reference
|
||||
|
||||
- Configuration guide: <https://github.com/fastfetch-cli/fastfetch/wiki/Configuration>
|
||||
- JSON schema: `doc/json_schema.json`
|
||||
- Example presets: `presets/` (`all.jsonc`, `neofetch.jsonc`, `ci.jsonc`, …)
|
||||
- Man page source: `doc/fastfetch.1.in`
|
||||
- Code generation scripts: `scripts/` (`gen-pciids.py`, `gen-amdgpuids.py`, `gen-man.py`)
|
||||
@@ -1,7 +1,7 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021-2023 Linus Dierheimer
|
||||
Copyright (c) 2022-2025 Carter Li
|
||||
Copyright (c) 2022-2026 Carter Li
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
# Fastfetch
|
||||
|
||||
Fastfetch 是一款类似 neofetch 的系统信息展示工具,主要用 C 编写,强调性能和可定制性。支持 Linux、macOS、Windows 7+、Android、FreeBSD、OpenBSD、NetBSD、DragonFly、Haiku、SunOS。
|
||||
|
||||
示例配置见 presets/examples,更多截图与平台说明见 Wiki。
|
||||
|
||||
## 安装
|
||||
|
||||
Linux(部分):
|
||||
- Debian 13+ / Ubuntu: apt install fastfetch
|
||||
- Arch: pacman -S fastfetch
|
||||
- Fedora: dnf install fastfetch
|
||||
- openSUSE: zypper install fastfetch
|
||||
- Linuxbrew:brew install fastfetch
|
||||
- 各发行版打包状态:https://repology.org/project/fastfetch/versions
|
||||
|
||||
macOS:
|
||||
- Homebrew:brew install fastfetch
|
||||
- MacPorts:sudo port install fastfetch
|
||||
|
||||
Windows:
|
||||
- scoop install fastfetch
|
||||
- choco install fastfetch
|
||||
- winget install fastfetch
|
||||
- MSYS2:pacman -S mingw-w64-<subsystem>-<arch>-fastfetch
|
||||
|
||||
BSD:
|
||||
- FreeBSD:pkg install fastfetch
|
||||
- NetBSD:pkgin in fastfetch
|
||||
- OpenBSD:pkg_add fastfetch
|
||||
|
||||
Android(Termux):
|
||||
- pkg install fastfetch
|
||||
|
||||
Nightly 构建:
|
||||
- https://nightly.link/fastfetch-cli/fastfetch/workflows/ci/dev?preview
|
||||
|
||||
## 源码构建
|
||||
|
||||
基本上是 `cmake . && make`。详见 Wiki:https://github.com/fastfetch-cli/fastfetch/wiki/Building
|
||||
|
||||
## 使用
|
||||
|
||||
- 默认运行:`fastfetch`
|
||||
- 查看所有可用模块示例:`fastfetch -c all.jsonc`
|
||||
- 以 JSON 输出指定模块:`fastfetch -s <module1>[:<module2>] --format json`
|
||||
- 完整命令行帮助:`fastfetch --help`
|
||||
- 生成最小配置:`fastfetch --gen-config [</path/to/config.jsonc>]`
|
||||
- 生成完整配置:`fastfetch --gen-config-full`
|
||||
- 请使用支持 JSON schema 的编辑器(如 VSCode)编辑配置文件!
|
||||
- 如果你连接 Github 有网络困难(智能提示不生效),可将配置文件中的 `$schema` 的值替换为 `https://gitee.com/carterl/fastfetch/raw/dev/doc/json_schema.json`
|
||||
|
||||
## 定制
|
||||
|
||||
- 配置使用 JSONC,语法与选项见 Wiki:https://github.com/fastfetch-cli/fastfetch/wiki/Configuration
|
||||
- 预设示例位于 presets,可用 `-c <filename>` 加载
|
||||
- Logo 选项与图像显示见文档:https://github.com/fastfetch-cli/fastfetch/wiki/Logo-options
|
||||
- 模块格式化(示例,仅显示 GPU 名称):
|
||||
```jsonc
|
||||
{
|
||||
"modules": [
|
||||
{ "type": "gpu", "format": "{name}" }
|
||||
]
|
||||
}
|
||||
```
|
||||
详见:https://github.com/fastfetch-cli/fastfetch/wiki/Format-String-Guide
|
||||
|
||||
## 反馈与支持
|
||||
|
||||
- 使用问题:Discussions https://github.com/fastfetch-cli/fastfetch/discussions
|
||||
- 疑似缺陷:Issues https://github.com/fastfetch-cli/fastfetch/issues(请填写模版)
|
||||
|
||||
## 赞助
|
||||
|
||||
<img src="https://github.com/user-attachments/assets/a36a6501-e8b0-4a10-9061-b9206d12ffba" width="220">
|
||||
@@ -1,5 +1,6 @@
|
||||
# Fastfetch
|
||||
|
||||
[](https://fastfetch-cli.github.io/fastfetch/dev/bench)
|
||||
[](https://github.com/fastfetch-cli/fastfetch/actions)
|
||||
[](https://github.com/fastfetch-cli/fastfetch/blob/dev/LICENSE)
|
||||
[](https://github.com/fastfetch-cli/fastfetch/graphs/contributors)
|
||||
@@ -11,8 +12,11 @@
|
||||
[](https://repology.org/project/fastfetch/versions)
|
||||
[](https://repology.org/project/fastfetch/versions)
|
||||
[](https://deepwiki.com/fastfetch-cli/fastfetch)
|
||||
[](README-cn.md)
|
||||
|
||||
Fastfetch is a [neofetch](https://github.com/dylanaraps/neofetch)-like tool for fetching system information and displaying it in a visually appealing way. It is written mainly in C, with a focus on performance and customizability. Currently, it supports Linux, macOS, Windows 7+, Android, FreeBSD, OpenBSD, NetBSD, DragonFly, Haiku, and SunOS.
|
||||
Fastfetch is a [neofetch](https://github.com/dylanaraps/neofetch)-like tool for fetching system information and displaying it in a visually appealing way. It is written mainly in C, with a focus on performance and customizability. Currently, it supports Linux, macOS, Windows 8.1+, Android, FreeBSD, OpenBSD, NetBSD, DragonFly, Haiku and SunOS (illumos, Solaris).
|
||||
|
||||
> Note: Fastfetch is only actively tested on x86-64 and aarch64 platforms. It may work on other platforms but is not guaranteed to do so.
|
||||
|
||||
<img src="screenshots/example1.png" width="49%" align="left" />
|
||||
<img src="https://upload.wikimedia.org/wikipedia/commons/2/24/Transparent_Square_Tiles_Texture.png" width="49%" height="16px" align="left" />
|
||||
@@ -36,7 +40,8 @@ Some distributions package outdated versions of fastfetch. Older versions receiv
|
||||
<img src="https://repology.org/badge/vertical-allrepos/fastfetch.svg?columns=2" alt="Packaging status" align="right">
|
||||
</a>
|
||||
|
||||
* Debian: `apt install fastfetch` (for Debian 13 or newer)
|
||||
* Ubuntu: [`ppa:zhangsongcui3371/fastfetch`](https://launchpad.net/~zhangsongcui3371/+archive/ubuntu/fastfetch) (Ubuntu 22.04 or newer; latest version)
|
||||
* Debian / Ubuntu: `apt install fastfetch` (Debian 13 or newer; Ubuntu 25.04 or newer)
|
||||
* Debian / Ubuntu: Download `fastfetch-linux-<proper architecture>.deb` from [Github release page](https://github.com/fastfetch-cli/fastfetch/releases/latest) and double-click it (for Ubuntu 20.04 or newer and Debian 11 or newer).
|
||||
* Arch Linux: `pacman -S fastfetch`
|
||||
* Fedora: `dnf install fastfetch`
|
||||
@@ -95,7 +100,7 @@ See the Wiki: https://github.com/fastfetch-cli/fastfetch/wiki/Building
|
||||
* View all data that fastfetch detects: `fastfetch -s <module1>[:<module2>][:<module3>] --format json`
|
||||
* Display help messages: `fastfetch --help`
|
||||
* Generate a minimal config file: `fastfetch [-s <module1>[:<module2>]] --gen-config [</path/to/config.jsonc>]`
|
||||
* Use: `--gen-config-full` to generate a full config file with all optional options
|
||||
* Use [The online configuration generator](https://fastfetch-cli.github.io/fastfetch-config/) to generate a full config file with all optional options
|
||||
|
||||
## Customization
|
||||
|
||||
@@ -103,6 +108,10 @@ Fastfetch uses JSONC (JSON with comments) for configuration. [See the Wiki for d
|
||||
|
||||
Logos can also be heavily customized; see the [logo documentation](https://github.com/fastfetch-cli/fastfetch/wiki/Logo-options) for more information.
|
||||
|
||||
### WARNING
|
||||
|
||||
Fastfetch supports a `Command` module that can run arbitrary shell commands. If you copy-paste a config file from an untrusted source, it may contain malicious commands that can harm your system or compromise your privacy. Please always review the config file before using it.
|
||||
|
||||
## FAQ
|
||||
|
||||
### Q: Neofetch is good enough. Why do I need fastfetch?
|
||||
@@ -191,7 +200,8 @@ See [#1096](https://github.com/fastfetch-cli/fastfetch/issues/1096).
|
||||
|
||||
### Q: Fastfetch shows fewer dpkg packages than neofetch. Is it a bug?
|
||||
|
||||
Neofetch incorrectly counts `rc` packages (packages that have been removed but still have configuration files remaining). See bug: https://github.com/dylanaraps/neofetch/issues/2278
|
||||
1. Neofetch incorrectly counts `rc` packages for apt (packages that have been removed but still have configuration files remaining). See bug: https://github.com/dylanaraps/neofetch/issues/2278
|
||||
2. Neofetch incorrectly counts `gpg-pubkey` as packages for rpm. You may check the results of `dnf list --installed | wc -l` and `rpm -qa | wc -l` to see the difference.
|
||||
|
||||
### Q: I use Debian / Ubuntu / Debian-derived distro. My GPU is detected as `XXXX Device XXXX (VGA compatible)`. Is this a bug?
|
||||
|
||||
@@ -317,14 +327,19 @@ If you find Fastfetch useful, please consider donating.
|
||||
* Current maintainer: [@CarterLi](https://paypal.me/zhangsongcui)
|
||||
* Original author: [@LinusDierheimer](https://github.com/sponsors/LinusDierheimer)
|
||||
|
||||
## Code signing
|
||||
|
||||
* Free code signing provided by [SignPath.io](https://about.signpath.io/), certificate by [SignPath Foundation](https://signpath.org/)
|
||||
* This program will not transfer any information to other networked systems unless specifically requested by the user or the person installing or operating it
|
||||
|
||||
## Star History
|
||||
|
||||
Give us a star to show your support!
|
||||
|
||||
<a href="https://star-history.com/#fastfetch-cli/fastfetch&Date">
|
||||
<a href="https://star-history.dera.page/#fastfetch-cli/fastfetch&Date">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=fastfetch-cli/fastfetch&type=Date&theme=dark" />
|
||||
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=fastfetch-cli/fastfetch&type=Date" />
|
||||
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=fastfetch-cli/fastfetch&type=Date" />
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://star-history.dera.page/svg?repos=fastfetch-cli/fastfetch&type=Date&theme=dark" />
|
||||
<source media="(prefers-color-scheme: light)" srcset="https://star-history.dera.page/svg?repos=fastfetch-cli/fastfetch&type=Date" />
|
||||
<img alt="Star History Chart" src="https://star-history.dera.page/svg?repos=fastfetch-cli/fastfetch&type=Date" />
|
||||
</picture>
|
||||
</a>
|
||||
|
||||
+56
-24
@@ -63,46 +63,78 @@ echo '
|
||||
import json, subprocess, sys
|
||||
|
||||
|
||||
def escape_fish_dq(s: str) -> str:
|
||||
"""Escape special characters for Fish double quotes to prevent unexpected expansions. One slash in output needs four slashes in script"""
|
||||
return str(s).replace("\\\\", "\\\\\\\\").replace("\\"", "\\\\\\"").replace("$", "\\\\$")
|
||||
|
||||
|
||||
def main():
|
||||
data: dict[str, list[dict]] = json.loads(subprocess.check_output(["fastfetch", "--help-raw"]))
|
||||
|
||||
enum_functions = []
|
||||
complete_commands = []
|
||||
|
||||
for key in data:
|
||||
for flag in data[key]:
|
||||
if flag["long"] == "logo-color-[1-9]":
|
||||
long_name = flag.get("long", "")
|
||||
|
||||
# Handle pseudo flag logo-color-[1-9]
|
||||
if long_name == "logo-color-[1-9]":
|
||||
safe_desc_global = escape_fish_dq(flag.get("desc", ""))
|
||||
for i in range(1, 10):
|
||||
print(f"""complete -c fastfetch -d "{flag["desc"]}" -l "logo-color-{i}" -x -a "(__fastfetch_complete_color)" """)
|
||||
complete_commands.append(f"complete -c fastfetch -d \"{safe_desc_global}\" -l \"logo-color-{i}\" -x -a \"(__fastfetch_complete_color)\"")
|
||||
continue
|
||||
|
||||
if flag.get("pseudo", False):
|
||||
continue
|
||||
|
||||
command_prefix = f"""complete -c fastfetch -d "{flag["desc"]}" -l "{flag["long"]}\""""
|
||||
safe_desc_global = escape_fish_dq(flag.get("desc", ""))
|
||||
command_prefix = f"complete -c fastfetch -d \"{safe_desc_global}\" -l \"{long_name}\""
|
||||
|
||||
if "short" in flag:
|
||||
command_prefix += f""" -o {flag["short"]}"""
|
||||
short_name = flag["short"]
|
||||
command_prefix += f" -o {short_name}"
|
||||
|
||||
if "arg" in flag:
|
||||
type: str = flag["arg"]["type"]
|
||||
if type == "bool":
|
||||
print(f"{command_prefix} -x -a \"(__fastfetch_complete_bool)\"")
|
||||
elif type == "color":
|
||||
print(f"{command_prefix} -x -a \"(__fastfetch_complete_color)\"")
|
||||
elif type == "command":
|
||||
print(f"{command_prefix} -x -a \"(__fastfetch_complete_command)\"")
|
||||
elif type == "config":
|
||||
print(f"{command_prefix} -x -a \"(__fastfetch_complete_config)\"")
|
||||
elif type == "enum":
|
||||
temp: str = " ".join(flag["arg"]["enum"])
|
||||
print(f"{command_prefix} -x -a \"{temp}\"")
|
||||
elif type == "logo":
|
||||
print(f"{command_prefix} -x -a \"(__fastfetch_complete_logo)\"")
|
||||
elif type == "structure":
|
||||
print(f"{command_prefix} -x -a \"(__fish_complete_list : __fastfetch_complete_structure)\"")
|
||||
elif type == "path":
|
||||
print(f"{command_prefix} -r -F")
|
||||
arg_type: str = flag["arg"]["type"]
|
||||
if arg_type == "bool":
|
||||
complete_commands.append(f"{command_prefix} -x -a \"(__fastfetch_complete_bool)\"")
|
||||
elif arg_type == "color":
|
||||
complete_commands.append(f"{command_prefix} -x -a \"(__fastfetch_complete_color)\"")
|
||||
elif arg_type == "command":
|
||||
complete_commands.append(f"{command_prefix} -x -a \"(__fastfetch_complete_command)\"")
|
||||
elif arg_type == "config":
|
||||
complete_commands.append(f"{command_prefix} -x -a \"(__fastfetch_complete_config)\"")
|
||||
elif arg_type == "enum":
|
||||
# Sanitize flag name to create a valid Fish function name
|
||||
func_name = long_name.replace("-", "_").replace("[", "_").replace("]", "_")
|
||||
func_name = f"__fastfetch_complete_enum_{func_name}"
|
||||
|
||||
# Generate the enum function
|
||||
func_lines = [f"function {func_name}"]
|
||||
for enum_val, enum_desc in flag["arg"]["enum"].items():
|
||||
safe_val = escape_fish_dq(enum_val)
|
||||
safe_desc = escape_fish_dq(enum_desc)
|
||||
func_lines.append(f" echo -e \"{safe_val}\\t{safe_desc}\"")
|
||||
func_lines.append("end\n")
|
||||
enum_functions.append("\n".join(func_lines))
|
||||
|
||||
# Append complete command pointing to the new function
|
||||
complete_commands.append(f"{command_prefix} -x -a \"({func_name})\"")
|
||||
elif arg_type == "logo":
|
||||
complete_commands.append(f"{command_prefix} -x -a \"(__fastfetch_complete_logo)\"")
|
||||
elif arg_type == "structure":
|
||||
complete_commands.append(f"{command_prefix} -x -a \"(__fish_complete_list : __fastfetch_complete_structure)\"")
|
||||
elif arg_type == "path":
|
||||
complete_commands.append(f"{command_prefix} -r -F")
|
||||
else:
|
||||
print(f"{command_prefix} -x")
|
||||
complete_commands.append(f"{command_prefix} -x")
|
||||
else:
|
||||
print(f"{command_prefix} -f")
|
||||
complete_commands.append(f"{command_prefix} -f")
|
||||
|
||||
# Print generated enum functions first, then complete rules
|
||||
print("\n".join(enum_functions))
|
||||
print("\n".join(complete_commands))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
+121
-1
@@ -1,3 +1,124 @@
|
||||
fastfetch (2.68.0~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Update to 2.68.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Tue, 01 Sep 2026 16:34:36 +0800
|
||||
|
||||
fastfetch (2.67.0~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Update to 2.67.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Thu, 06 Aug 2026 16:22:22 +0800
|
||||
|
||||
fastfetch (2.66.0~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Update to 2.66.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Fri, 10 Jul 2026 15:13:37 +0800
|
||||
|
||||
fastfetch (2.65.2~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Update to 2.65.2
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Mon, 29 Jun 2026 10:05:47 +0800
|
||||
|
||||
fastfetch (2.65.1~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Update to 2.65.1
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Wed, 24 Jun 2026 14:21:06 +0800
|
||||
|
||||
fastfetch (2.64.2~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Update to 2.64.2
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Mon, 08 Jun 2026 15:45:11 +0800
|
||||
|
||||
fastfetch (2.63.1~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Update to 2.63.1
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Fri, 15 May 2026 09:31:54 +0800
|
||||
|
||||
fastfetch (2.63.0~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Update to 2.63.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Wed, 13 May 2026 16:02:28 +0800
|
||||
|
||||
fastfetch (2.62.1~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Update to 2.62.1
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Fri, 24 Apr 2026 15:45:15 +0800
|
||||
|
||||
fastfetch (2.62.0~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Update to 2.62.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Wed, 22 Apr 2026 09:49:55 +0800
|
||||
|
||||
fastfetch (2.61.0~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Update to 2.61.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Mon, 30 Mar 2026 09:51:18 +0800
|
||||
|
||||
fastfetch (2.58.0~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Update to 2.58.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Thu, 22 Jan 2026 15:30:58 +0800
|
||||
|
||||
fastfetch (2.57.1~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Update to 2.57.1
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Wed, 14 Jan 2026 14:00:17 +0800
|
||||
|
||||
fastfetch (2.57.0~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Update to 2.57.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Mon, 12 Jan 2026 10:11:21 +0800
|
||||
|
||||
fastfetch (2.56.1~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Update to 2.56.1
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Thu, 18 Dec 2025 14:57:36 +0800
|
||||
|
||||
fastfetch (2.56.0~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Update to 2.56.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Mon, 08 Dec 2025 09:21:58 +0800
|
||||
|
||||
fastfetch (2.55.1~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Update to 2.55.1
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Mon, 17 Nov 2025 10:15:44 +0800
|
||||
|
||||
fastfetch (2.55.0~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Update to 2.55.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Wed, 12 Nov 2025 09:15:24 +0800
|
||||
|
||||
fastfetch (2.54.1~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Fix building on plucky
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Mon, 20 Oct 2025 14:27:02 +0800
|
||||
|
||||
fastfetch (2.54.0~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Update to 2.54.0
|
||||
* Test independent changelog entries for different Ubuntu releases
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Mon, 20 Oct 2025 10:47:02 +0800
|
||||
|
||||
fastfetch (2.53.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.53.0
|
||||
@@ -435,4 +556,3 @@ fastfetch (2.7.1) jammy; urgency=medium
|
||||
* Initial release.
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Tue, 06 Feb 2024 15:01:11 +0800
|
||||
|
||||
Vendored
+1
-1
@@ -2,7 +2,7 @@ Source: fastfetch
|
||||
Section: universe/utils
|
||||
Priority: optional
|
||||
Maintainer: Carter Li <zhangsongcui@live.cn>
|
||||
Build-Depends: libelf-dev, libvulkan-dev, libwayland-dev, libxrandr-dev, libxcb-randr0-dev, libdconf-dev, libdbus-1-dev, libmagickcore-dev, libsqlite3-dev, librpm-dev, libegl-dev, libglx-dev, ocl-icd-opencl-dev, libpulse-dev, libdrm-dev, libddcutil-dev, libchafa-dev, directx-headers-dev, pkgconf, cmake (>= 3.12), debhelper (>= 11.2), dh-cmake, dh-cmake-compat (= 1), dh-sequence-cmake, dh-sequence-ctest, ninja-build
|
||||
Build-Depends: libelf-dev, libvulkan-dev, libwayland-dev, libxrandr-dev, libxcb-randr0-dev, libdconf-dev, libdbus-1-dev, libmagickcore-dev, libsqlite3-dev, librpm-dev, libegl-dev, libglx-dev, ocl-icd-opencl-dev, libpulse-dev, libdrm-dev, libddcutil-dev, libchafa-dev, libefl-all-dev, pkgconf, cmake (>= 3.12), debhelper (>= 11.2), dh-cmake, dh-cmake-compat (= 1), dh-sequence-cmake, dh-sequence-ctest, ninja-build, python3-setuptools
|
||||
Standards-Version: 4.0.0
|
||||
Homepage: https://github.com/fastfetch-cli/fastfetch
|
||||
|
||||
|
||||
Vendored
-1
@@ -1 +0,0 @@
|
||||
fastfetch_2.53.0_source.buildinfo universe/utils optional
|
||||
Vendored
+74
-2
@@ -1,4 +1,76 @@
|
||||
#!/usr/bin/env bash
|
||||
# WARNING: DO NOT RUN THIS SCRIPT UNLESS YOU KNOW WHAT YOU ARE DOING.
|
||||
|
||||
debuild -S -i -I
|
||||
dput ppa:zhangsongcui3371/fastfetch ~/fastfetch_*.changes
|
||||
set -euo pipefail
|
||||
|
||||
command -v debuild >/dev/null 2>&1 || { echo "debuild not found. Install devscripts." >&2; exit 1; }
|
||||
command -v dput >/dev/null 2>&1 || { echo "dput not found." >&2; exit 1; }
|
||||
|
||||
SCRIPT_DIR="$(cd -- "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
|
||||
ROOT_DIR="$(cd -- "$SCRIPT_DIR/.." >/dev/null 2>&1 && pwd)"
|
||||
OUT_DIR="$(dirname "$ROOT_DIR")"
|
||||
PPA="ppa:zhangsongcui3371/fastfetch"
|
||||
CODENAMES=( jammy noble plucky questing resolute stonking )
|
||||
DRY_RUN=0
|
||||
|
||||
if [[ -d "$OUT_DIR/build" ]]; then
|
||||
echo "Output directory exists: $OUT_DIR/build" >&2
|
||||
echo "Please move or delete it before proceeding." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TEMPLATE="$ROOT_DIR/debian/changelog.tpl"
|
||||
CHANGELOG_DEBIAN="$ROOT_DIR/debian/changelog"
|
||||
|
||||
if [[ ! -f "$TEMPLATE" ]]; then
|
||||
echo "Template not found: $TEMPLATE" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! grep -q '#UBUNTU_CODENAME#' "$TEMPLATE"; then
|
||||
echo "Template missing placeholder: #UBUNTU_CODENAME#" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "IMPORTANT: Before proceeding, please ensure that 'debian/changelog.tpl' is up-to-date"
|
||||
echo " with the correct version number, release notes, and maintainer information."
|
||||
echo
|
||||
echo " The template must contain a placeholder like '#UBUNTU_CODENAME#' for the codename."
|
||||
echo
|
||||
read -p "Have you reviewed and updated 'debian/changelog.tpl'? (y/N): " -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cleanup() {
|
||||
rm -f "$CHANGELOG_DEBIAN"
|
||||
rm -f "$ROOT_DIR/debian/files"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
shopt -s nullglob
|
||||
|
||||
for codename in "${CODENAMES[@]}"; do
|
||||
echo "==> Publishing distro: $codename"
|
||||
sed "s/#UBUNTU_CODENAME#/${codename}/g" "$TEMPLATE" > "$CHANGELOG_DEBIAN"
|
||||
|
||||
( cd "$ROOT_DIR" && debuild -S -i -I )
|
||||
|
||||
changes=( "$OUT_DIR"/fastfetch_*~${codename}_source.changes )
|
||||
if [[ ${#changes[@]} -ne 1 ]]; then
|
||||
echo "Unable to uniquely identify .changes for '$codename' in: $OUT_DIR" >&2
|
||||
printf 'Found:\n'; printf ' %s\n' "${changes[@]}" >&2 || true
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ $DRY_RUN -eq 1 ]]; then
|
||||
echo "[DRY-RUN] dput \"$PPA\" \"${changes[0]}\""
|
||||
else
|
||||
dput "$PPA" "${changes[0]}"
|
||||
fi
|
||||
|
||||
rm -f "$OUT_DIR"/fastfetch_*~${codename}_source.{changes,dsc,tar.*}
|
||||
|
||||
echo "<== Done: $codename"
|
||||
done
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
{
|
||||
"short": "h",
|
||||
"long": "help",
|
||||
"desc": "Display this help message or help for a specific command",
|
||||
"desc": "Show this help message or help for a specific command",
|
||||
"arg": {
|
||||
"type": "command",
|
||||
"optional": true
|
||||
@@ -12,11 +12,11 @@
|
||||
{
|
||||
"short": "v",
|
||||
"long": "version",
|
||||
"desc": "Show the full version of fastfetch"
|
||||
"desc": "Show the full Fastfetch version"
|
||||
},
|
||||
{
|
||||
"long": "version-raw",
|
||||
"desc": "Display the raw version string (major.minor.patch)"
|
||||
"desc": "Show the raw version string (major.minor.patch)"
|
||||
},
|
||||
{
|
||||
"long": "list-config-paths",
|
||||
@@ -36,7 +36,7 @@
|
||||
},
|
||||
{
|
||||
"long": "list-presets",
|
||||
"desc": "List presets that fastfetch knows about",
|
||||
"desc": "List available presets",
|
||||
"remark": "Presets can be loaded with \"--config <preset-name>\""
|
||||
},
|
||||
{
|
||||
@@ -46,15 +46,15 @@
|
||||
},
|
||||
{
|
||||
"long": "print-logos",
|
||||
"desc": "Display available logos"
|
||||
"desc": "Show available logos"
|
||||
},
|
||||
{
|
||||
"long": "print-structure",
|
||||
"desc": "Display the default structure"
|
||||
"desc": "Show the default structure"
|
||||
},
|
||||
{
|
||||
"long": "format",
|
||||
"desc": "Set output format",
|
||||
"desc": "Set the output format",
|
||||
"arg": {
|
||||
"type": "enum",
|
||||
"enum": {
|
||||
@@ -63,6 +63,36 @@
|
||||
},
|
||||
"default": "default"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "json",
|
||||
"short": "j",
|
||||
"arg": {
|
||||
"type": "bool",
|
||||
"default": false,
|
||||
"optional": true
|
||||
},
|
||||
"desc": "Enable or disable JSON output",
|
||||
"remark": "Shortcut for `--format json`"
|
||||
},
|
||||
{
|
||||
"long": "dynamic-interval",
|
||||
"desc": "Keep Fastfetch running and refresh the output every <num> milliseconds",
|
||||
"remark": "Set to 0 (default) to disable this behavior; does not work with --json",
|
||||
"arg": {
|
||||
"type": "num",
|
||||
"default": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "watch",
|
||||
"short": "w",
|
||||
"desc": "Alias of dynamic-interval, but the value is in seconds instead of milliseconds. If no value is provided, it defaults to 1 second",
|
||||
"arg": {
|
||||
"type": "num",
|
||||
"optional": true,
|
||||
"default": 1
|
||||
}
|
||||
}
|
||||
],
|
||||
"Config": [
|
||||
@@ -70,33 +100,15 @@
|
||||
"short": "c",
|
||||
"long": "config",
|
||||
"desc": "Specify the config file or preset to load",
|
||||
"remark": "The file will be searched according to the order shown by \"fastfetch --list-config-paths\". Use \"none\" to disable further config loading. See also https://github.com/fastfetch-cli/fastfetch/wiki/Configuration for more info",
|
||||
"remark": "The file is searched in the order shown by \"fastfetch --list-config-paths\". Use \"-\" to read config from stdin, or \"none\" to disable further config loading. See also https://github.com/fastfetch-cli/fastfetch/wiki/Configuration for details",
|
||||
"arg": {
|
||||
"type": "config"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "gen-config",
|
||||
"desc": "Generate a minimal config file at the specified path",
|
||||
"remark": "Defaults to \"~/.config/fastfetch/config.jsonc\". Will print the generated config if <path> is \"-\"",
|
||||
"arg": {
|
||||
"type": "path",
|
||||
"optional": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "gen-config-full",
|
||||
"desc": "Generate a full config file with all optional options at the specified path",
|
||||
"remark": "Defaults to \"~/.config/fastfetch/config.jsonc\". Will print the generated config if <path> is \"-\"",
|
||||
"arg": {
|
||||
"type": "path",
|
||||
"optional": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "gen-config-force",
|
||||
"desc": "Generate a config file at the specified path, overwriting any existing file",
|
||||
"remark": "Defaults to \"~/.config/fastfetch/config.jsonc\"",
|
||||
"desc": "Interactively generate a config file at the specified path",
|
||||
"remark": "Opens an interactive configuration UI when run in a terminal. Falls back to non-interactive generation when env-var `$NO_COLOR` is set or stdin/stdout is not a TTY. Defaults to \"~/.config/fastfetch/config.jsonc\". Prints the generated config if <path> is \"-\"",
|
||||
"arg": {
|
||||
"type": "path",
|
||||
"optional": true
|
||||
@@ -132,7 +144,7 @@
|
||||
},
|
||||
{
|
||||
"long": "ds-force-drm",
|
||||
"desc": "Specify whether only DRM should be used to detect displays",
|
||||
"desc": "Specify whether display detection should use DRM only",
|
||||
"remark": [
|
||||
"Use this option if you encounter problems with other detection methods.",
|
||||
"Linux only"
|
||||
@@ -150,7 +162,7 @@
|
||||
},
|
||||
{
|
||||
"long": "detect-version",
|
||||
"desc": "Specify whether to detect and display versions of terminal, shell, editor, and others",
|
||||
"desc": "Specify whether to detect and display versions for terminal, shell, editor, and others",
|
||||
"remark": "Mainly for benchmarking",
|
||||
"arg": {
|
||||
"type": "bool",
|
||||
@@ -163,31 +175,31 @@
|
||||
{
|
||||
"short": "l",
|
||||
"long": "logo",
|
||||
"desc": "Set the logo source. Use \"none\" to disable the logo",
|
||||
"remark": "Should be the name of a built-in logo or a path to an image file. See also https://github.com/fastfetch-cli/fastfetch/wiki/Logo-options",
|
||||
"desc": "Set the logo source. Use \"none\" to disable logo output",
|
||||
"remark": "Use either a built-in logo name or a path to an image file. See also https://github.com/fastfetch-cli/fastfetch/wiki/Logo-options",
|
||||
"arg": {
|
||||
"type": "logo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "logo-type",
|
||||
"desc": "Set the type of the logo specified in \"--logo\"",
|
||||
"desc": "Set the type of logo specified by \"--logo\"",
|
||||
"remark": "See also https://github.com/fastfetch-cli/fastfetch/wiki/Logo-options",
|
||||
"arg": {
|
||||
"type": "enum",
|
||||
"enum": {
|
||||
"auto": "If something is given, first try built-in, then file. Otherwise detect logo",
|
||||
"auto": "If a value is provided, try built-in first, then file. Otherwise auto-detect the logo",
|
||||
"builtin": "Built-in ASCII art",
|
||||
"small": "Built-in ASCII art, small version",
|
||||
"file": "Text file, printed with color code replacement",
|
||||
"file-raw": "Text file, printed as is",
|
||||
"data": "Text data, printed with color code replacement",
|
||||
"data-raw": "Text data, printed as is",
|
||||
"sixel": "Image file, printed as sixel codes",
|
||||
"kitty": "Image file, printed using kitty graphics protocol",
|
||||
"sixel": "Image file, rendered as sixel",
|
||||
"kitty": "Image file, rendered using the Kitty graphics protocol",
|
||||
"kitty-direct": "Image file, tells the terminal emulator to read image data from the specified file",
|
||||
"kitty-icat": "Image file, uses `kitten icat` to display the image. Requires binary `kitten` to be installed",
|
||||
"iterm": "Image file, printed using iterm graphics protocol",
|
||||
"kitty-icat": "Image file, displayed using `kitten icat`. Requires the `kitten` binary",
|
||||
"iterm": "Image file, rendered using the iTerm graphics protocol",
|
||||
"chafa": "Image file, printed as ASCII art using libchafa",
|
||||
"raw": "Image file, printed as raw binary string",
|
||||
"none": "Disable logo printing"
|
||||
@@ -259,7 +271,7 @@
|
||||
},
|
||||
{
|
||||
"long": "logo-print-remaining",
|
||||
"desc": "Specify whether to print the remaining logo if it has more lines than modules to display",
|
||||
"desc": "Specify whether to print remaining logo lines when the logo is taller than the module list",
|
||||
"arg": {
|
||||
"type": "bool",
|
||||
"optional": true,
|
||||
@@ -268,7 +280,7 @@
|
||||
},
|
||||
{
|
||||
"long": "logo-position",
|
||||
"desc": "Set the position where the logo should be displayed",
|
||||
"desc": "Set the display position of the logo",
|
||||
"arg": {
|
||||
"type": "enum",
|
||||
"enum": {
|
||||
@@ -378,7 +390,7 @@
|
||||
{
|
||||
"long": "chafa-fg-only",
|
||||
"desc": "Produce character-cell output using foreground colors only",
|
||||
"remark": "See chafa document for detail",
|
||||
"remark": "See the Chafa documentation for details",
|
||||
"arg": {
|
||||
"type": "bool",
|
||||
"optional": true,
|
||||
@@ -388,7 +400,7 @@
|
||||
{
|
||||
"long": "chafa-symbols",
|
||||
"desc": "Specify character symbols to employ in final output",
|
||||
"remark": "See chafa document for detail",
|
||||
"remark": "See the Chafa documentation for details",
|
||||
"arg": {
|
||||
"type": "str"
|
||||
}
|
||||
@@ -396,7 +408,7 @@
|
||||
{
|
||||
"long": "chafa-canvas-mode",
|
||||
"desc": "Determine how colors are used in the output",
|
||||
"remark": "This value maps the int value of enum ChafaCanvasMode. See chafa document for detail",
|
||||
"remark": "This value maps to the integer value of enum ChafaCanvasMode. See the Chafa documentation for details",
|
||||
"arg": {
|
||||
"type": "enum",
|
||||
"enum": {
|
||||
@@ -413,8 +425,8 @@
|
||||
},
|
||||
{
|
||||
"long": "chafa-color-space",
|
||||
"desc": "Set color space used for quantization",
|
||||
"remark": "This value maps the int value of enum ChafaColorSpace. See chafa document for detail",
|
||||
"desc": "Set the color space used for quantization",
|
||||
"remark": "This value maps to the integer value of enum ChafaColorSpace. See the Chafa documentation for details",
|
||||
"arg": {
|
||||
"type": "enum",
|
||||
"enum": {
|
||||
@@ -425,8 +437,8 @@
|
||||
},
|
||||
{
|
||||
"long": "chafa-dither-mode",
|
||||
"desc": "Set output dither mode (No effect with 24-bit color)",
|
||||
"remark": "This value maps the int value of enum ChafaDitherMode. See chafa document for detail",
|
||||
"desc": "Set the output dithering mode (no effect with 24-bit color)",
|
||||
"remark": "This value maps to the integer value of enum ChafaDitherMode. See the Chafa documentation for details",
|
||||
"arg": {
|
||||
"type": "enum",
|
||||
"enum": {
|
||||
@@ -442,15 +454,23 @@
|
||||
"short": "s",
|
||||
"long": "structure",
|
||||
"desc": "Set the structure of the fetch",
|
||||
"remark": "Must be a colon-separated list of keys. Use \"fastfetch --list-modules\" to see available options",
|
||||
"remark": "Must be a colon-separated list of module keys. Use \"fastfetch --list-modules\" to see available options",
|
||||
"arg": {
|
||||
"type": "structure",
|
||||
"default": "\"fastfetch --print-structure\""
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "structure-disabled",
|
||||
"desc": "Disable specific modules in the structure",
|
||||
"remark": "Must be a colon-separated list of keys",
|
||||
"arg": {
|
||||
"type": "structure"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "stat",
|
||||
"desc": "Show time usage (in ms) for individual modules",
|
||||
"desc": "Show execution time (ms) for individual modules",
|
||||
"arg": {
|
||||
"type": "bool",
|
||||
"optional": true,
|
||||
@@ -513,7 +533,7 @@
|
||||
{
|
||||
"long": "duration-abbreviation",
|
||||
"desc": "Specify whether to abbreviate duration values",
|
||||
"remark": "If true, the output will be in the form of \"1h 2m\" instead of \"1 hour, 2 mins\"",
|
||||
"remark": "If true, output is shown as \"1h 2m\" instead of \"1 hour, 2 mins\"",
|
||||
"arg": {
|
||||
"type": "bool",
|
||||
"optional": true,
|
||||
@@ -554,12 +574,49 @@
|
||||
"enum": {
|
||||
"none": "Disable keys",
|
||||
"string": "Show string",
|
||||
"icon": "Show icon (requires newest nerd font)",
|
||||
"both": "Show both icon and string"
|
||||
"icon": "Show icon (requires a recent Nerd Font)",
|
||||
"both": "Show both icon and string (alias of `both-1`)",
|
||||
"both-0": "Show both icon and string with no spaces between them",
|
||||
"both-1": "Show both icon and string with a space between them",
|
||||
"both-2": "Show both icon and string with 2 spaces between them",
|
||||
"both-3": "Show both icon and string with 3 spaces between them",
|
||||
"both-4": "Show both icon and string with 4 spaces between them"
|
||||
},
|
||||
"default": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "key-language",
|
||||
"desc": "Specify the language used for module keys",
|
||||
"remark": "Leave empty for auto-detection based on the system locale. Unsupported locales fall back to English",
|
||||
"arg": {
|
||||
"type": "enum",
|
||||
"default": "en",
|
||||
"optional": true,
|
||||
"enum": {
|
||||
"en": "English",
|
||||
"ar": "Arabic",
|
||||
"cs": "Czech",
|
||||
"de": "German",
|
||||
"es": "Spanish",
|
||||
"fr": "French",
|
||||
"gl": "Galician",
|
||||
"he": "Hebrew",
|
||||
"id": "Indonesian",
|
||||
"it": "Italian",
|
||||
"ja": "Japanese",
|
||||
"ko": "Korean",
|
||||
"pl": "Polish",
|
||||
"pt": "Portuguese",
|
||||
"ru": "Russian",
|
||||
"tr": "Turkish",
|
||||
"uk": "Ukrainian",
|
||||
"vi": "Vietnamese",
|
||||
"zh_CN": "Simplified Chinese",
|
||||
"zh_TW": "Traditional Chinese"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "bright-color",
|
||||
"desc": "Specify whether keys, title, and ASCII logo should be printed in bright color",
|
||||
@@ -606,7 +663,7 @@
|
||||
},
|
||||
{
|
||||
"long": "percent-type",
|
||||
"desc": "Set the percentage output type",
|
||||
"desc": "Set the percentage output style",
|
||||
"remark": [
|
||||
"1 for percentage number",
|
||||
"2 for multi-color bar",
|
||||
@@ -622,7 +679,7 @@
|
||||
},
|
||||
{
|
||||
"long": "percent-ndigits",
|
||||
"desc": "Set the number of digits to keep after the decimal point when formatting percentage numbers",
|
||||
"desc": "Set the number of decimal places to use when formatting percentages",
|
||||
"arg": {
|
||||
"type": "num",
|
||||
"default": 0
|
||||
@@ -669,7 +726,7 @@
|
||||
},
|
||||
{
|
||||
"long": "percent-width",
|
||||
"desc": "Specify the width of the percentage number, in number of characters",
|
||||
"desc": "Specify the width of the percentage number, in characters",
|
||||
"remark": "This option affects only percentage numbers, not bars",
|
||||
"arg": {
|
||||
"type": "num",
|
||||
@@ -678,7 +735,7 @@
|
||||
},
|
||||
{
|
||||
"long": "bar-char-elapsed",
|
||||
"desc": "Set the character to use in the elapsed part of percentage bars",
|
||||
"desc": "Set the character used for the elapsed part of percentage bars",
|
||||
"arg": {
|
||||
"type": "str",
|
||||
"default": "\u25a0"
|
||||
@@ -686,7 +743,7 @@
|
||||
},
|
||||
{
|
||||
"long": "bar-char-total",
|
||||
"desc": "Set the character to use in the total part of percentage bars",
|
||||
"desc": "Set the character used for the total part of percentage bars",
|
||||
"arg": {
|
||||
"type": "str",
|
||||
"default": "-"
|
||||
@@ -710,7 +767,7 @@
|
||||
},
|
||||
{
|
||||
"long": "bar-border-left-elapsed",
|
||||
"desc": "If both bar-border-left-elapsed and bar-border-right-elapsed are set, the border will be used as parts of bar content",
|
||||
"desc": "If both bar-border-left-elapsed and bar-border-right-elapsed are set, the border is used as part of the bar content",
|
||||
"arg": {
|
||||
"type": "string",
|
||||
"default": ""
|
||||
@@ -718,7 +775,7 @@
|
||||
},
|
||||
{
|
||||
"long": "bar-border-right-elapsed",
|
||||
"desc": "If both bar-border-left-elapsed and bar-border-right-elapsed are set, the border will be used as parts of bar content",
|
||||
"desc": "If both bar-border-left-elapsed and bar-border-right-elapsed are set, the border is used as part of the bar content",
|
||||
"arg": {
|
||||
"type": "string",
|
||||
"default": ""
|
||||
@@ -726,8 +783,8 @@
|
||||
},
|
||||
{
|
||||
"long": "bar-color-elapsed",
|
||||
"desc": "Set the color to use in the elapsed part of percentage bars",
|
||||
"remark": "By default, auto selected by percent-color-{green,yellow,red}",
|
||||
"desc": "Set the color used for the elapsed part of percentage bars",
|
||||
"remark": "By default, this is auto-selected by percent-color-{green,yellow,red}",
|
||||
"arg": {
|
||||
"type": "color",
|
||||
"default": "<auto>"
|
||||
@@ -735,7 +792,7 @@
|
||||
},
|
||||
{
|
||||
"long": "bar-color-total",
|
||||
"desc": "Set the color to use in the total part of percentage bars",
|
||||
"desc": "Set the color used for the total part of percentage bars",
|
||||
"arg": {
|
||||
"type": "color",
|
||||
"default": "light_white"
|
||||
@@ -743,7 +800,7 @@
|
||||
},
|
||||
{
|
||||
"long": "bar-color-border",
|
||||
"desc": "Set the color to use in the borders of percentage bars",
|
||||
"desc": "Set the color used for percentage bar borders",
|
||||
"arg": {
|
||||
"type": "color",
|
||||
"default": "light_white"
|
||||
@@ -759,7 +816,7 @@
|
||||
},
|
||||
{
|
||||
"long": "no-buffer",
|
||||
"desc": "Specify whether the stdout application buffer should be disabled",
|
||||
"desc": "Specify whether stdout buffering should be disabled",
|
||||
"arg": {
|
||||
"type": "bool",
|
||||
"optional": true,
|
||||
@@ -768,7 +825,7 @@
|
||||
},
|
||||
{
|
||||
"long": "size-ndigits",
|
||||
"desc": "Set the number of digits to keep after the decimal point when formatting sizes",
|
||||
"desc": "Set the number of decimal places to use when formatting sizes",
|
||||
"arg": {
|
||||
"type": "num"
|
||||
}
|
||||
@@ -819,7 +876,7 @@
|
||||
},
|
||||
{
|
||||
"long": "freq-ndigits",
|
||||
"desc": "Set the number of digits to keep after the decimal point when printing CPU/GPU frequency in GHz",
|
||||
"desc": "Set the number of decimal places to use when printing CPU/GPU frequency in GHz",
|
||||
"arg": {
|
||||
"type": "num",
|
||||
"default": 2
|
||||
@@ -839,7 +896,7 @@
|
||||
},
|
||||
{
|
||||
"long": "fraction-ndigits",
|
||||
"desc": "Set the number of digits to keep after the decimal point when printing ordinary fraction numbers",
|
||||
"desc": "Set the number of decimal places to use when printing fractional values",
|
||||
"remark": "If negative, the number of digits will be automatically determined based on the value",
|
||||
"arg": {
|
||||
"type": "num",
|
||||
@@ -852,7 +909,7 @@
|
||||
"arg": {
|
||||
"type": "enum",
|
||||
"enum": {
|
||||
"default": "Use the behavior defined internally",
|
||||
"default": "Use the built-in behavior",
|
||||
"always": "Always keep trailing zeros",
|
||||
"never": "Never keep trailing zeros"
|
||||
}
|
||||
@@ -874,7 +931,7 @@
|
||||
},
|
||||
{
|
||||
"long": "temp-ndigits",
|
||||
"desc": "Set the number of digits to keep after the decimal point when printing temperature",
|
||||
"desc": "Set the number of decimal places to use when printing temperatures",
|
||||
"arg": {
|
||||
"type": "num",
|
||||
"default": 2
|
||||
+705
-309
File diff suppressed because it is too large
Load Diff
+9
-4
@@ -50,6 +50,10 @@
|
||||
"driverSpecific": true,
|
||||
"temp": true
|
||||
},
|
||||
{
|
||||
"type": "codec",
|
||||
"splitGPU": true
|
||||
},
|
||||
"memory",
|
||||
"physicalmemory",
|
||||
{
|
||||
@@ -95,16 +99,17 @@
|
||||
"gamepad",
|
||||
"mouse",
|
||||
"keyboard",
|
||||
{
|
||||
"type": "weather",
|
||||
"timeout": 1000
|
||||
},
|
||||
"top",
|
||||
"netio",
|
||||
"diskio",
|
||||
{
|
||||
"type": "physicaldisk",
|
||||
"temp": true
|
||||
},
|
||||
{
|
||||
"type": "weather",
|
||||
"timeout": 1000
|
||||
},
|
||||
"tpm",
|
||||
"version",
|
||||
"break",
|
||||
|
||||
+12
-6
@@ -52,6 +52,10 @@
|
||||
"driverSpecific": true,
|
||||
"temp": true
|
||||
},
|
||||
{
|
||||
"type": "codec",
|
||||
"splitGPU": true
|
||||
},
|
||||
"memory",
|
||||
"physicalmemory",
|
||||
{
|
||||
@@ -90,25 +94,27 @@
|
||||
"opengl",
|
||||
"opencl",
|
||||
"users",
|
||||
// "bluetooth", // doesn't work on macOS because it requires bluetooth permissions
|
||||
// "bluetoothradio",
|
||||
"bluetooth",
|
||||
"bluetoothradio",
|
||||
"sound",
|
||||
"camera",
|
||||
"gamepad",
|
||||
"mouse",
|
||||
"keyboard",
|
||||
{
|
||||
"type": "weather",
|
||||
"timeout": 1000
|
||||
},
|
||||
"top",
|
||||
"netio",
|
||||
"diskio",
|
||||
{
|
||||
"type": "physicaldisk",
|
||||
"temp": true
|
||||
},
|
||||
{
|
||||
"type": "weather",
|
||||
"timeout": 1000
|
||||
},
|
||||
"tpm",
|
||||
"version",
|
||||
"logo",
|
||||
"break",
|
||||
"colors"
|
||||
]
|
||||
|
||||
+13
-16
@@ -1,6 +1,3 @@
|
||||
// Load with --load-config examples/2.jsonc
|
||||
// Note that you must replace the image path to an existing image to display it.
|
||||
|
||||
{
|
||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||
"logo": {
|
||||
@@ -45,12 +42,12 @@
|
||||
},
|
||||
{
|
||||
"type": "kernel",
|
||||
"key": "│ ├",
|
||||
"key": "│ ├{icon}",
|
||||
"keyColor": "yellow"
|
||||
},
|
||||
{
|
||||
"type": "packages",
|
||||
"key": "│ ├",
|
||||
"key": "│ ├{icon}",
|
||||
"keyColor": "yellow"
|
||||
},
|
||||
{
|
||||
@@ -65,22 +62,22 @@
|
||||
},
|
||||
{
|
||||
"type": "lm",
|
||||
"key": "│ ├",
|
||||
"key": "│ ├{icon}",
|
||||
"keyColor": "blue"
|
||||
},
|
||||
{
|
||||
"type": "wmtheme",
|
||||
"key": "│ ├",
|
||||
"key": "│ ├{icon}",
|
||||
"keyColor": "blue"
|
||||
},
|
||||
{
|
||||
"type": "icons",
|
||||
"key": "│ ├",
|
||||
"key": "│ ├{icon}",
|
||||
"keyColor": "blue"
|
||||
},
|
||||
{
|
||||
"type": "terminal",
|
||||
"key": "│ ├",
|
||||
"key": "│ ├{icon}",
|
||||
"keyColor": "blue"
|
||||
},
|
||||
{
|
||||
@@ -95,32 +92,32 @@
|
||||
},
|
||||
{
|
||||
"type": "cpu",
|
||||
"key": "│ ├",
|
||||
"key": "│ ├{icon}",
|
||||
"keyColor": "green"
|
||||
},
|
||||
{
|
||||
"type": "gpu",
|
||||
"key": "│ ├",
|
||||
"key": "│ ├{icon}",
|
||||
"keyColor": "green"
|
||||
},
|
||||
{
|
||||
"type": "disk",
|
||||
"key": "│ ├",
|
||||
"key": "│ ├{icon}",
|
||||
"keyColor": "green"
|
||||
},
|
||||
{
|
||||
"type": "memory",
|
||||
"key": "│ ├",
|
||||
"key": "│ ├{icon}",
|
||||
"keyColor": "green"
|
||||
},
|
||||
{
|
||||
"type": "swap",
|
||||
"key": "│ ├",
|
||||
"key": "│ ├{icon}",
|
||||
"keyColor": "green"
|
||||
},
|
||||
{
|
||||
"type": "uptime",
|
||||
"key": "│ ├",
|
||||
"key": "│ ├{icon}",
|
||||
"keyColor": "green"
|
||||
},
|
||||
{
|
||||
@@ -135,7 +132,7 @@
|
||||
},
|
||||
{
|
||||
"type": "player",
|
||||
"key": "│ ├",
|
||||
"key": "│ ├{icon}",
|
||||
"keyColor": "cyan"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Inspired by Catnap
|
||||
// Inspired by Catnap (https://github.com/iinsertNameHere/catnap)
|
||||
{
|
||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||
"logo": {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Inspired by Catnap
|
||||
// Inspired by Catnap (https://github.com/iinsertNameHere/catnap)
|
||||
{
|
||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||
"logo": {
|
||||
@@ -12,7 +12,7 @@
|
||||
},
|
||||
"modules": [
|
||||
{
|
||||
// draw borders first to make colors of left and right border consistant
|
||||
// draw borders first to make colors of left and right border consistent
|
||||
"key": " user",
|
||||
"type": "title",
|
||||
"format": "{user-name}",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Inspired by Catnap
|
||||
// Inspired by Catnap (https://github.com/iinsertNameHere/catnap)
|
||||
{
|
||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||
"logo": {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Inspired by Catnap
|
||||
// Inspired by Catnap (https://github.com/iinsertNameHere/catnap)
|
||||
{
|
||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||
"logo": {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Load with --load-config examples/2.jsonc
|
||||
// Load with --config examples/2.jsonc
|
||||
// Note that you must replace the image path to an existing image to display it.
|
||||
|
||||
{
|
||||
|
||||
+52
-51
@@ -9,25 +9,26 @@
|
||||
// Constants are reusable strings referenced by {$1}, {$2}, etc.
|
||||
// These contain ANSI escape codes for cursor positioning
|
||||
"constants": [
|
||||
"──────────────────────────────────────────────", // {$1} - horizontal line for borders
|
||||
"──────────────────────────────────────────────", // {$1} - horizontal line for inner borders
|
||||
"\u001b[47D", // {$2} - move cursor left 47 columns
|
||||
"\u001b[47C", // {$3} - move cursor right 47 columns
|
||||
"\u001b[46C" // {$4} - move cursor right 46 columns
|
||||
"\u001b[46C", // {$4} - move cursor right 46 columns
|
||||
"══════════════════════════════════════════════" // {$5} - horizontal line for outer borders
|
||||
],
|
||||
"brightColor": false
|
||||
},
|
||||
"modules": [
|
||||
{
|
||||
"type": "version",
|
||||
"key": "┌───────────────┬─{$1}┐\u001b[41D",
|
||||
"key": "╔═══════════════╦═{$5}╗\u001b[41D",
|
||||
"format": "\u001b[1m{#keys} {1} - {2} "
|
||||
},
|
||||
{
|
||||
"type": "os",
|
||||
// Key format breakdown for OS module:
|
||||
// "│ {icon} \u001b[s{sysname}\u001b[u\u001b[10C│{$3}│{$2}"
|
||||
// "║ {icon} \u001b[s{sysname}\u001b[u\u001b[10C│{$3}║{$2}"
|
||||
//
|
||||
// │ - Left border of key block
|
||||
// ║ - Left border of key block
|
||||
// {icon} - OS icon (defined internally by fastfetch)
|
||||
// \u001b[s - ANSI escape: save cursor position (ESC[s)
|
||||
// {sysname} - Format variable: system name (e.g., "Linux", "Darwin")
|
||||
@@ -36,28 +37,28 @@
|
||||
// \u001b[10C - ANSI escape: move cursor right 10 columns (ESC[10C)
|
||||
// │ - Right border of key block (always 10 columns from left border)
|
||||
// {$3} - Reference to constants[2]: move cursor right 47 columns
|
||||
// │ - Right border of value block
|
||||
// ║ - Right border of value block
|
||||
// {$2} - Reference to constants[1]: move cursor left 47 columns
|
||||
//
|
||||
// This creates a fixed-width layout where the key block is exactly 10 columns wide,
|
||||
// regardless of the actual content length. The cursor manipulation ensures proper
|
||||
// alignment for the table-like structure.
|
||||
"key": "│ {icon} \u001b[s{sysname}\u001b[u\u001b[10C│{$3}│{$2}"
|
||||
"key": "║ {icon} \u001b[s{sysname}\u001b[u\u001b[10C║{$3}║{$2}"
|
||||
},
|
||||
{
|
||||
"type": "datetime",
|
||||
"key": "│ {icon} Fetched │{$3}│{$2}",
|
||||
"key": "║ {icon} Fetched ║{$3}║{$2}",
|
||||
"format": "{year}-{month-pretty}-{day-pretty} {hour-pretty}:{minute-pretty}:{second-pretty} {timezone-name}"
|
||||
},
|
||||
{
|
||||
"type": "locale",
|
||||
"key": "│ {icon} Locale │{$3}│{$2}"
|
||||
"key": "║ {icon} Locale ║{$3}║{$2}"
|
||||
},
|
||||
|
||||
// Hardware section with cyan color theme
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "│{#cyan}┌──────────────┬{$1}┐{#keys}│\u001b[37D",
|
||||
"key": "║{#cyan}┌──────────────┬{$1}┐{#keys}║\u001b[37D",
|
||||
"format": "{#bright_cyan} Hardware "
|
||||
},
|
||||
{
|
||||
@@ -66,113 +67,113 @@
|
||||
// │{#cyan}│ - Left border with cyan color
|
||||
// {icon} - Chassis icon
|
||||
// Chassis - Fixed label text
|
||||
// │{$4}│{#keys}│{$2} - Positioning and borders for value area
|
||||
"key": "│{#cyan}│ {icon} Chassis │{$4}│{#keys}│{$2}"
|
||||
// │{$4}│{#keys}║{$2} - Positioning and borders for value area
|
||||
"key": "║{#cyan}│ {icon} Chassis │{$4}│{#keys}║{$2}"
|
||||
},
|
||||
{
|
||||
"type": "memory",
|
||||
"key": "│{#cyan}│ {icon} RAM │{$4}│{#keys}│{$2}"
|
||||
"key": "║{#cyan}│ {icon} RAM │{$4}│{#keys}║{$2}"
|
||||
},
|
||||
{
|
||||
"type": "swap",
|
||||
"key": "│{#cyan}│ {icon} SWAP │{$4}│{#keys}│{$2}"
|
||||
"key": "║{#cyan}│ {icon} SWAP │{$4}│{#keys}║{$2}"
|
||||
},
|
||||
{
|
||||
"type": "cpu",
|
||||
"key": "│{#cyan}│ {icon} CPU │{$4}│{#keys}│{$2}",
|
||||
"key": "║{#cyan}│ {icon} CPU │{$4}│{#keys}║{$2}",
|
||||
"showPeCoreCount": true
|
||||
},
|
||||
{
|
||||
"type": "gpu",
|
||||
"key": "│{#cyan}│ {icon} GPU │{$4}│{#keys}│{$2}"
|
||||
"key": "║{#cyan}│ {icon} GPU │{$4}│{#keys}║{$2}"
|
||||
},
|
||||
{
|
||||
"type": "disk",
|
||||
"key": "│{#cyan}│ {icon} Disk │{$4}│{#keys}│{$2}",
|
||||
"key": "║{#cyan}│ {icon} Disk │{$4}│{#keys}║{$2}",
|
||||
"format": "{size-used} \/ {size-total} ({size-percentage}) - {filesystem}",
|
||||
},
|
||||
{
|
||||
"type": "battery",
|
||||
"key": "│{#cyan}│ {icon} Battery │{$4}│{#keys}│{$2}"
|
||||
"key": "║{#cyan}│ {icon} Battery │{$4}│{#keys}║{$2}"
|
||||
},
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "│{#cyan}└──────────────┴{$1}┘{#keys}│",
|
||||
"key": "║{#cyan}└──────────────┴{$1}┘{#keys}║",
|
||||
"format": ""
|
||||
},
|
||||
|
||||
// Desktop section with green color theme
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "│{#green}┌──────────────┬{$1}┐{#keys}│\u001b[37D",
|
||||
"key": "║{#green}┌──────────────┬{$1}┐{#keys}║\u001b[37D",
|
||||
"format": "{#bright_green} Desktop "
|
||||
},
|
||||
{
|
||||
"type": "de",
|
||||
"key": "│{#green}│ {icon} Desktop │{$4}│{#keys}│{$2}"
|
||||
"key": "║{#green}│ {icon} Desktop │{$4}│{#keys}║{$2}"
|
||||
},
|
||||
{
|
||||
"type": "wm",
|
||||
"key": "│{#green}│ {icon} Session │{$4}│{#keys}│{$2}"
|
||||
"key": "║{#green}│ {icon} Session │{$4}│{#keys}║{$2}"
|
||||
},
|
||||
{
|
||||
"type": "display",
|
||||
"key": "│{#green}│ {icon} Display │{$4}│{#keys}│{$2}",
|
||||
"key": "║{#green}│ {icon} Display │{$4}│{#keys}║{$2}",
|
||||
"compactType": "original-with-refresh-rate"
|
||||
},
|
||||
{
|
||||
"type": "gpu",
|
||||
"key": "│{#green}│ {icon} G-Driver │{$4}│{#keys}│{$2}",
|
||||
"key": "║{#green}│ {icon} G-Driver │{$4}│{#keys}║{$2}",
|
||||
"format": "{driver}"
|
||||
},
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "│{#green}└──────────────┴{$1}┘{#keys}│",
|
||||
"key": "║{#green}└──────────────┴{$1}┘{#keys}║",
|
||||
"format": ""
|
||||
},
|
||||
|
||||
// Terminal section with yellow color theme
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "│{#yellow}┌──────────────┬{$1}┐{#keys}│\u001b[37D",
|
||||
"key": "║{#yellow}┌──────────────┬{$1}┐{#keys}║\u001b[37D",
|
||||
"format": "{#bright_yellow} Terminal "
|
||||
},
|
||||
{
|
||||
"type": "shell",
|
||||
"key": "│{#yellow}│ {icon} Shell │{$4}│{#keys}│{$2}"
|
||||
"key": "║{#yellow}│ {icon} Shell │{$4}│{#keys}║{$2}"
|
||||
},
|
||||
{
|
||||
"type": "terminal",
|
||||
"key": "│{#yellow}│ {icon} Terminal │{$4}│{#keys}│{$2}"
|
||||
"key": "║{#yellow}│ {icon} Terminal │{$4}│{#keys}║{$2}"
|
||||
},
|
||||
{
|
||||
"type": "terminalfont",
|
||||
"key": "│{#yellow}│ {icon} Term Font │{$4}│{#keys}│{$2}"
|
||||
"key": "║{#yellow}│ {icon} Term Font │{$4}│{#keys}║{$2}"
|
||||
},
|
||||
{
|
||||
"type": "terminaltheme",
|
||||
"key": "│{#yellow}│ {icon} Colors │{$4}│{#keys}│{$2}"
|
||||
"key": "║{#yellow}│ {icon} Colors │{$4}│{#keys}║{$2}"
|
||||
},
|
||||
{
|
||||
"type": "packages",
|
||||
"key": "│{#yellow}│ {icon} Packages │{$4}│{#keys}│{$2}"
|
||||
"key": "║{#yellow}│ {icon} Packages │{$4}│{#keys}║{$2}"
|
||||
},
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "│{#yellow}└──────────────┴{$1}┘{#keys}│",
|
||||
"key": "║{#yellow}└──────────────┴{$1}┘{#keys}║",
|
||||
"format": ""
|
||||
},
|
||||
|
||||
// Development section with red color theme
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "│{#red}┌──────────────┬{$1}┐{#keys}│\u001b[39D",
|
||||
"key": "║{#red}┌──────────────┬{$1}┐{#keys}║\u001b[39D",
|
||||
"format": "{#bright_red} Development "
|
||||
},
|
||||
{
|
||||
"type": "command",
|
||||
"keyIcon": "", // Custom icon override
|
||||
"key": "│{#red}│ {icon} Rust │{$4}│{#keys}│{$2}",
|
||||
"key": "║{#red}│ {icon} Rust │{$4}│{#keys}║{$2}",
|
||||
"text": "rustc --version",
|
||||
"format": "rustc {~6,13}" // Print 6th to 13th characters (version number)
|
||||
},
|
||||
@@ -182,8 +183,8 @@
|
||||
"!system": "Windows" // Posix version
|
||||
},
|
||||
"keyIcon": "",
|
||||
"key": "│{#red}│ {icon} Clang │{$4}│{#keys}│{$2}",
|
||||
"text": "clang --version | head -1 | awk '{print $NF}'",
|
||||
"key": "║{#red}│ {icon} Clang │{$4}│{#keys}║{$2}",
|
||||
"text": "clang --version | sed -n 's/.*version \\([0-9][0-9.]*\\).*/\\1/p'",
|
||||
"format": "clang {}"
|
||||
},
|
||||
{
|
||||
@@ -192,67 +193,67 @@
|
||||
"system": "Windows" // Windows version
|
||||
},
|
||||
"keyIcon": "",
|
||||
"key": "│{#red}│ {icon} Clang │{$4}│{#keys}│{$2}",
|
||||
"key": "║{#red}│ {icon} Clang │{$4}│{#keys}║{$2}",
|
||||
"text": "clang --version | findstr version", // Finds the line with "version"
|
||||
"format": "clang {~-6}" // Prints the last 6 characters (version number)
|
||||
},
|
||||
{
|
||||
"type": "command",
|
||||
"keyIcon": "",
|
||||
"key": "│{#red}│ {icon} NodeJS │{$4}│{#keys}│{$2}",
|
||||
"key": "║{#red}│ {icon} NodeJS │{$4}│{#keys}║{$2}",
|
||||
"text": "node --version",
|
||||
"format": "node {~1}" // {~1} removes first character (v)
|
||||
},
|
||||
{
|
||||
"type": "command",
|
||||
"keyIcon": "",
|
||||
"key": "│{#red}│ {icon} Go │{$4}│{#keys}│{$2}",
|
||||
"key": "║{#red}│ {icon} Go │{$4}│{#keys}║{$2}",
|
||||
"text": "go version | cut -d' ' -f3",
|
||||
"format": "go {~2}" // {~2} removes first 2 characters (go)
|
||||
},
|
||||
{
|
||||
"type": "command",
|
||||
"keyIcon": "",
|
||||
"key": "│{#red}│ {icon} Zig │{$4}│{#keys}│{$2}",
|
||||
"key": "║{#red}│ {icon} Zig │{$4}│{#keys}║{$2}",
|
||||
"text": "zig version",
|
||||
"format": "zig {}"
|
||||
},
|
||||
{
|
||||
"type": "editor",
|
||||
"key": "│{#red}│ {icon} Editor │{$4}│{#keys}│{$2}"
|
||||
"key": "║{#red}│ {icon} Editor │{$4}│{#keys}║{$2}"
|
||||
},
|
||||
{
|
||||
"type": "command",
|
||||
"keyIcon": "",
|
||||
"key": "│{#red}│ {icon} Git │{$4}│{#keys}│{$2}",
|
||||
"key": "║{#red}│ {icon} Git │{$4}│{#keys}║{$2}",
|
||||
"text": "git version",
|
||||
"format": "git {~12}"
|
||||
},
|
||||
{
|
||||
"type": "font",
|
||||
"key": "│{#red}│ {icon} Interface │{$4}│{#keys}│{$2}"
|
||||
"key": "║{#red}│ {icon} Interface │{$4}│{#keys}║{$2}"
|
||||
},
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "│{#red}└──────────────┴{$1}┘{#keys}│",
|
||||
"key": "║{#red}└──────────────┴{$1}┘{#keys}║",
|
||||
"format": ""
|
||||
},
|
||||
|
||||
// Uptime section with magenta color theme
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "│{#magenta}┌──────────────┬{$1}┐{#keys}│\u001b[36D",
|
||||
"key": "║{#magenta}┌──────────────┬{$1}┐{#keys}║\u001b[36D",
|
||||
"format": "{#bright_magenta} Uptime "
|
||||
},
|
||||
{
|
||||
"type": "uptime",
|
||||
"key": "│{#magenta}│ {icon} Uptime │{$4}│{#keys}│{$2}"
|
||||
"key": "║{#magenta}│ {icon} Uptime │{$4}│{#keys}║{$2}"
|
||||
},
|
||||
{
|
||||
"type": "users",
|
||||
"myselfOnly": true, // Only show current user
|
||||
"keyIcon": "",
|
||||
"key": "│{#magenta}│ {icon} Login │{$4}│{#keys}│{$2}"
|
||||
"key": "║{#magenta}│ {icon} Login │{$4}│{#keys}║{$2}"
|
||||
},
|
||||
{
|
||||
"condition": { // Conditional module: only show on non-macOS
|
||||
@@ -260,7 +261,7 @@
|
||||
},
|
||||
"type": "disk",
|
||||
"keyIcon": "",
|
||||
"key": "│{#magenta}│ {icon} OS Age │{$4}│{#keys}│{$2}",
|
||||
"key": "║{#magenta}│ {icon} OS Age │{$4}│{#keys}║{$2}",
|
||||
"folders": "/", // Check root filesystem
|
||||
"format": "{create-time:10} [{days} days]" // Show creation time and age in days
|
||||
},
|
||||
@@ -270,18 +271,18 @@
|
||||
},
|
||||
"type": "disk",
|
||||
"keyIcon": "",
|
||||
"key": "│{#magenta}│ {icon} OS Age │{$4}│{#keys}│{$2}",
|
||||
"key": "║{#magenta}│ {icon} OS Age │{$4}│{#keys}║{$2}",
|
||||
"folders": "/System/Volumes/VM", // Work around for APFS on macOS
|
||||
"format": "{create-time:10} [{days} days]"
|
||||
},
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "│{#magenta}└──────────────┴{$1}┘{#keys}│",
|
||||
"key": "║{#magenta}└──────────────┴{$1}┘{#keys}║",
|
||||
"format": ""
|
||||
},
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "└─────────────────{$1}┘", // Bottom border of the entire layout
|
||||
"key": "╚═════════════════{$5}╝", // Bottom border of the entire layout
|
||||
"format": ""
|
||||
},
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Load with --load-config examples/3.jsonc
|
||||
// Load with --config examples/3.jsonc
|
||||
|
||||
{
|
||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,57 @@
|
||||
// Inspired by microfetch
|
||||
{
|
||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||
"logo": {
|
||||
"type": "small"
|
||||
},
|
||||
"general": {
|
||||
"detectVersion": false
|
||||
},
|
||||
"display": {
|
||||
"separator": " ",
|
||||
"brightColor": false,
|
||||
"key": {
|
||||
"type": "both-2"
|
||||
}
|
||||
},
|
||||
"modules": [
|
||||
{
|
||||
"type": "title",
|
||||
"format": "{user-name-colored}{#light_red}@{host-name-colored} {#}{cwd}"
|
||||
},
|
||||
{
|
||||
"type": "os",
|
||||
"key": "System "
|
||||
},
|
||||
{
|
||||
"type": "kernel",
|
||||
"key": "Kernel "
|
||||
},
|
||||
{
|
||||
"type": "shell",
|
||||
"key": "Shell "
|
||||
},
|
||||
{
|
||||
"type": "uptime",
|
||||
"key": "Uptime "
|
||||
},
|
||||
{
|
||||
"type": "wm",
|
||||
"key": "Desktop "
|
||||
},
|
||||
{
|
||||
"type": "memory",
|
||||
"key": "Memory "
|
||||
},
|
||||
{
|
||||
"type": "disk",
|
||||
"key": "Storage (/) ",
|
||||
"folders": "/"
|
||||
},
|
||||
{
|
||||
"type": "colors",
|
||||
"key": "Colors ",
|
||||
"symbol": "circle"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
// Load with --load-config examples/4.jsonc
|
||||
// Load with --config examples/4.jsonc
|
||||
|
||||
{
|
||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Load with --load-config examples/5.jsonc
|
||||
// Load with --config examples/5.jsonc
|
||||
|
||||
{
|
||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
// Load with --load-config examples/2.jsonc
|
||||
// Note that you must replace the image path to an existing image to display it.
|
||||
|
||||
{
|
||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||
"display": {
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
// Load with --load-config examples/2.jsonc
|
||||
// Note that you must replace the image path to an existing image to display it.
|
||||
|
||||
{
|
||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||
"logo": {
|
||||
|
||||
@@ -16,6 +16,13 @@
|
||||
"separator",
|
||||
"os",
|
||||
"host",
|
||||
{
|
||||
"type": "board",
|
||||
"key": "Host",
|
||||
"condition": {
|
||||
"succeeded": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "kernel",
|
||||
"format": "{release}"
|
||||
|
||||
@@ -6,6 +6,9 @@ def main(amdgpu_ids_path: str):
|
||||
with open(amdgpu_ids_path, 'r') as f:
|
||||
full_text = f.read()
|
||||
|
||||
if full_text == '':
|
||||
sys.exit(f'Error: {amdgpu_ids_path} file is empty')
|
||||
|
||||
products = []
|
||||
for line in full_text.split('\n'):
|
||||
if not line or line[0] == '#' or not ',\t' in line:
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ endBold = r"\fR" # end bold text tag
|
||||
# path to the current directory
|
||||
pathToCurrentDir = path.dirname(__file__)
|
||||
# path to the JSON option file
|
||||
pathToHelpFile = path.join(pathToCurrentDir, "../src/data/help.json")
|
||||
pathToHelpFile = path.join(pathToCurrentDir, "../doc/help.json")
|
||||
# man page section
|
||||
manSection = 1
|
||||
# title (center header)
|
||||
|
||||
@@ -18,6 +18,9 @@ def main(keep_vendor_list: set, pci_ids_path: str):
|
||||
with open(pci_ids_path, 'r') as f:
|
||||
full_text = f.read()
|
||||
|
||||
if full_text == '':
|
||||
sys.exit(f'Error: {pci_ids_path} file is empty')
|
||||
|
||||
dev_list_text = full_text[:full_text.rfind('\n\n\n')] # remove known classes
|
||||
for line in dev_list_text.split('\n'):
|
||||
if not line or line[0] == '#':
|
||||
|
||||
+141
-88
@@ -21,7 +21,7 @@
|
||||
// SOFTWARE.
|
||||
|
||||
/// \file adl_defines.h
|
||||
/// \brief Contains all definitions exposed by ADL for \ALL platforms.\n <b>Included in ADL SDK</b>
|
||||
/// \brief Contains all definitions exposed by ADL for \WIN platforms.\n <b>Included in ADL SDK</b>
|
||||
///
|
||||
/// This file contains all definitions used by ADL.
|
||||
/// The ADL definitions include the following:
|
||||
@@ -61,6 +61,8 @@
|
||||
#define ADL_ADAPTER_INDEX_ALL -1
|
||||
/// Defines APIs with iOption none
|
||||
#define ADL_MAIN_API_OPTION_NONE 0
|
||||
/// Defines the maximum of RPC endpoint
|
||||
#define ADL_MAX_RPC_ENDPOINT 32
|
||||
/// @}
|
||||
|
||||
/// \name Definitions for iOption parameter used by
|
||||
@@ -141,6 +143,12 @@
|
||||
#define ADL_ERR_FEATURESYNC_NOT_STARTED -24
|
||||
/// Adapter is in an invalid power state
|
||||
#define ADL_ERR_INVALID_POWER_STATE -25
|
||||
/// The RPC server is in busy state
|
||||
#define ADL_ERR_SERVER_BUSY -26
|
||||
/// The GPU is occupied by application which cannot be powered off
|
||||
#define ADL_ERR_GPU_IN_USE -27
|
||||
/// The general RPC connection error
|
||||
#define ADL_ERR_RPC -28
|
||||
|
||||
/// @}
|
||||
/// </A>
|
||||
@@ -380,6 +388,7 @@
|
||||
#define ADL_BUSTYPE_PCIE_GEN2 3 /* PCI Express 2nd generation bus */
|
||||
#define ADL_BUSTYPE_PCIE_GEN3 4 /* PCI Express 3rd generation bus */
|
||||
#define ADL_BUSTYPE_PCIE_GEN4 5 /* PCI Express 4th generation bus */
|
||||
#define ADL_BUSTYPE_PCIE_GEN5 6 /* PCI Express 5th generation bus */
|
||||
/// @}
|
||||
|
||||
/// \defgroup define_ws_caps Workstation Capabilities
|
||||
@@ -872,7 +881,7 @@
|
||||
typedef enum ADLThreadingModel
|
||||
{
|
||||
ADL_THREADING_UNLOCKED = 0, /*!< Default behavior. ADL will not enforce serialization of ADL API executions by multiple threads. Multiple threads will be allowed to enter to ADL at the same time. Note that ADL library is not guaranteed to be thread-safe. Client that calls ADL_Main_Control_Create have to provide its own mechanism for ADL calls serialization. */
|
||||
ADL_THREADING_LOCKED /*!< ADL will enforce serialization of ADL API when called by multiple threads. Only single thread will be allowed to enter ADL API at the time. This option makes ADL calls thread-safe. You shouldn't use this option if ADL calls will be executed on Linux on x-server rendering thread. It can cause the application to hung. */
|
||||
ADL_THREADING_LOCKED /*!< ADL will enforce serialization of ADL API when called by multiple threads. Only single thread will be allowed to enter ADL API at the time. This option makes ADL calls thread-safe. */
|
||||
}ADLThreadingModel;
|
||||
|
||||
/// @}
|
||||
@@ -1844,12 +1853,12 @@ enum ADLOD8FeatureControl
|
||||
ADL_OD8_TEMPERATURE_FAN = 1 << 6, //FanTargetTemperature
|
||||
ADL_OD8_TEMPERATURE_SYSTEM = 1 << 7, //MaxOpTemp
|
||||
ADL_OD8_MEMORY_TIMING_TUNE = 1 << 8,
|
||||
ADL_OD8_FAN_ZERO_RPM_CONTROL = 1 << 9 ,
|
||||
ADL_OD8_AUTO_UV_ENGINE = 1 << 10, //Auto under voltage
|
||||
ADL_OD8_AUTO_OC_ENGINE = 1 << 11, //Auto overclock engine
|
||||
ADL_OD8_AUTO_OC_MEMORY = 1 << 12, //Auto overclock memory
|
||||
ADL_OD8_FAN_CURVE = 1 << 13, //Fan curve
|
||||
ADL_OD8_WS_AUTO_FAN_ACOUSTIC_LIMIT = 1 << 14, //Workstation Manual Fan controller
|
||||
ADL_OD8_FAN_ZERO_RPM_CONTROL = 1 << 9,
|
||||
ADL_OD8_AUTO_UV_ENGINE = 1 << 10, //Auto under voltage
|
||||
ADL_OD8_AUTO_OC_ENGINE = 1 << 11, //Auto overclock engine
|
||||
ADL_OD8_AUTO_OC_MEMORY = 1 << 12, //Auto overclock memory
|
||||
ADL_OD8_FAN_CURVE = 1 << 13, //Fan curve
|
||||
ADL_OD8_WS_AUTO_FAN_ACOUSTIC_LIMIT = 1 << 14, //Workstation Manual Fan controller
|
||||
ADL_OD8_GFXCLK_QUADRATIC_CURVE = 1 << 15,
|
||||
ADL_OD8_OPTIMIZED_GPU_POWER_MODE = 1 << 16,
|
||||
ADL_OD8_ODVOLTAGE_LIMIT = 1 << 17,
|
||||
@@ -1860,43 +1869,45 @@ enum ADLOD8FeatureControl
|
||||
ADL_OD8_TDC_LIMIT = 1 << 22, //TDC slider
|
||||
ADL_OD8_FULL_CONTROL_MODE = 1 << 23, //Full control
|
||||
ADL_OD8_POWER_SAVING_FEATURE_CONTROL = 1 << 24, //Power saving feature control
|
||||
ADL_OD8_POWER_GAUGE = 1 << 25 //Power Gauge
|
||||
ADL_OD8_ACTIMING_PARAMETERS_TUNE = 1 << 25, // AC Timing Parameters Tuning
|
||||
ADL_OD8_OVERDRIVE_INTERFACE = 1 << 26, // Version info feature ID for RSX, do not expose in ADL.
|
||||
ADL_OD8_AUTO_UV_ENGINE_V2 = 1 << 27, // Auto UV 2.0 with actual stress testing.
|
||||
ADL_OD8_POWER_GAUGE = 1 << 28 //Power Gauge
|
||||
};
|
||||
|
||||
|
||||
typedef enum ADLOD8SettingId
|
||||
{
|
||||
OD8_GFXCLK_FMAX = 0,
|
||||
OD8_GFXCLK_FMIN,
|
||||
OD8_GFXCLK_FREQ1,
|
||||
OD8_GFXCLK_VOLTAGE1,
|
||||
OD8_GFXCLK_FREQ2,
|
||||
OD8_GFXCLK_VOLTAGE2,
|
||||
OD8_GFXCLK_FREQ3,
|
||||
OD8_GFXCLK_VOLTAGE3,
|
||||
OD8_UCLK_FMAX,
|
||||
OD8_POWER_PERCENTAGE,
|
||||
OD8_FAN_MIN_SPEED,
|
||||
OD8_FAN_ACOUSTIC_LIMIT,
|
||||
OD8_FAN_TARGET_TEMP,
|
||||
OD8_OPERATING_TEMP_MAX,
|
||||
OD8_AC_TIMING,
|
||||
OD8_FAN_ZERORPM_CONTROL,
|
||||
OD8_AUTO_UV_ENGINE_CONTROL,
|
||||
OD8_AUTO_OC_ENGINE_CONTROL,
|
||||
OD8_AUTO_OC_MEMORY_CONTROL,
|
||||
OD8_FAN_CURVE_TEMPERATURE_1,
|
||||
OD8_FAN_CURVE_SPEED_1,
|
||||
OD8_FAN_CURVE_TEMPERATURE_2,
|
||||
OD8_FAN_CURVE_SPEED_2,
|
||||
OD8_FAN_CURVE_TEMPERATURE_3,
|
||||
OD8_FAN_CURVE_SPEED_3,
|
||||
OD8_FAN_CURVE_TEMPERATURE_4,
|
||||
OD8_FAN_CURVE_SPEED_4,
|
||||
OD8_FAN_CURVE_TEMPERATURE_5,
|
||||
OD8_FAN_CURVE_SPEED_5,
|
||||
OD8_WS_FAN_AUTO_FAN_ACOUSTIC_LIMIT,
|
||||
OD8_GFXCLK_CURVE_COEFFICIENT_A, // As part of the agreement with UI team, the min/max voltage limits for the
|
||||
OD8_GFXCLK_FMAX = 0,
|
||||
OD8_GFXCLK_FMIN,
|
||||
OD8_GFXCLK_FREQ1,
|
||||
OD8_GFXCLK_VOLTAGE1,
|
||||
OD8_GFXCLK_FREQ2,
|
||||
OD8_GFXCLK_VOLTAGE2,
|
||||
OD8_GFXCLK_FREQ3,
|
||||
OD8_GFXCLK_VOLTAGE3,
|
||||
OD8_UCLK_FMAX,
|
||||
OD8_POWER_PERCENTAGE,
|
||||
OD8_FAN_MIN_SPEED, //10
|
||||
OD8_FAN_ACOUSTIC_LIMIT,
|
||||
OD8_FAN_TARGET_TEMP,
|
||||
OD8_OPERATING_TEMP_MAX,
|
||||
OD8_AC_TIMING,
|
||||
OD8_FAN_ZERORPM_CONTROL,
|
||||
OD8_AUTO_UV_ENGINE_CONTROL,
|
||||
OD8_AUTO_OC_ENGINE_CONTROL,
|
||||
OD8_AUTO_OC_MEMORY_CONTROL,
|
||||
OD8_FAN_CURVE_TEMPERATURE_1,
|
||||
OD8_FAN_CURVE_SPEED_1, //20
|
||||
OD8_FAN_CURVE_TEMPERATURE_2,
|
||||
OD8_FAN_CURVE_SPEED_2,
|
||||
OD8_FAN_CURVE_TEMPERATURE_3,
|
||||
OD8_FAN_CURVE_SPEED_3,
|
||||
OD8_FAN_CURVE_TEMPERATURE_4,
|
||||
OD8_FAN_CURVE_SPEED_4,
|
||||
OD8_FAN_CURVE_TEMPERATURE_5,
|
||||
OD8_FAN_CURVE_SPEED_5,
|
||||
OD8_WS_FAN_AUTO_FAN_ACOUSTIC_LIMIT,
|
||||
OD8_GFXCLK_CURVE_COEFFICIENT_A, // 30 As part of the agreement with UI team, the min/max voltage limits for the
|
||||
OD8_GFXCLK_CURVE_COEFFICIENT_B, // quadratic curve graph will be stored in the min and max limits of
|
||||
OD8_GFXCLK_CURVE_COEFFICIENT_C, // coefficient a, b and c. A, b and c themselves do not have limits.
|
||||
OD8_GFXCLK_CURVE_VFT_FMIN,
|
||||
@@ -1906,7 +1917,7 @@ typedef enum ADLOD8SettingId
|
||||
OD8_OD_VOLTAGE,// RSX - voltage offset feature
|
||||
OD8_ADV_OC_LIMITS_SETTING,
|
||||
OD8_PER_ZONE_GFX_VOLTAGE_OFFSET_POINT_1,
|
||||
OD8_PER_ZONE_GFX_VOLTAGE_OFFSET_POINT_2,
|
||||
OD8_PER_ZONE_GFX_VOLTAGE_OFFSET_POINT_2, //40
|
||||
OD8_PER_ZONE_GFX_VOLTAGE_OFFSET_POINT_3,
|
||||
OD8_PER_ZONE_GFX_VOLTAGE_OFFSET_POINT_4,
|
||||
OD8_PER_ZONE_GFX_VOLTAGE_OFFSET_POINT_5,
|
||||
@@ -1915,8 +1926,33 @@ typedef enum ADLOD8SettingId
|
||||
OD8_GFX_VOLTAGE_LIMIT_SETTING,
|
||||
OD8_TDC_PERCENTAGE,
|
||||
OD8_FULL_CONTROL_MODE_SETTING,
|
||||
OD8_FULL_CONTROL_MODE_GFXCLK,
|
||||
OD8_FULL_CONTROL_MODE_UCLK, // 50,
|
||||
OD8_IDLE_POWER_SAVING_FEATURE_CONTROL,
|
||||
OD8_RUNTIME_POWER_SAVING_FEATURE_CONTROL,
|
||||
OD8_FULL_CONTROL_MODE_FEATURE_CONTROL,
|
||||
OD8_PER_ZONE_GFX_VOLTAGE_OFFSET_FREQ_ANCHOR_1,
|
||||
OD8_PER_ZONE_GFX_VOLTAGE_OFFSET_FREQ_ANCHOR_2,
|
||||
OD8_PER_ZONE_GFX_VOLTAGE_OFFSET_FREQ_ANCHOR_3,
|
||||
OD8_PER_ZONE_GFX_VOLTAGE_OFFSET_FREQ_ANCHOR_4,
|
||||
OD8_PER_ZONE_GFX_VOLTAGE_OFFSET_FREQ_ANCHOR_5,
|
||||
OD8_PER_ZONE_GFX_VOLTAGE_OFFSET_FREQ_ANCHOR_6,
|
||||
OD8_PER_ZONE_GFX_VOLTAGE_OFFSET_VOLTAGE_LIMIT, //60
|
||||
OD8_ACTIMING_PARAMETER_TRRDS,
|
||||
OD8_ACTIMING_PARAMETER_TCL,
|
||||
OD8_ACTIMING_PARAMETER_TCWL,
|
||||
OD8_ACTIMING_PARAMETER_TRCDRD,
|
||||
OD8_ACTIMING_PARAMETER_TRCDWR,
|
||||
OD8_ACTIMING_PARAMETER_TRAS,
|
||||
OD8_ACTIMING_PARAMETER_TRPAB,
|
||||
OD8_ACTIMING_PARAMETER_TRFC,
|
||||
OD8_ACTIMING_PARAMETER_TRFCPB,
|
||||
OD8_ACTIMING_PARAMETER_TRREFD, //70
|
||||
OD8_ACTIMING_PARAMETER_TREF,
|
||||
OD8_ACTIMING_PARAMETER_TWR,
|
||||
OD8_ACTIMING_PARAMETER_TWTRS,
|
||||
OD8_OVERDRIVE_INTERFACE_ID, //74
|
||||
OD8_AUTO_UV_ENGINE_V2_ID, //75
|
||||
OD8_POWER_GAUGE,
|
||||
OD8_COUNT
|
||||
} ADLOD8SettingId;
|
||||
@@ -1980,28 +2016,28 @@ typedef enum ADLSensorType
|
||||
PMLOG_SSDGPU_POWERLIMIT = 49, // DGPU Power limit
|
||||
PMLOG_TEMPERATURE_HOTSPOT_GCD = 50,
|
||||
PMLOG_TEMPERATURE_HOTSPOT_MCD = 51,
|
||||
PMLOG_THROTTLER_TEMP_EDGE_PERCENTAGE = 52,
|
||||
PMLOG_THROTTLER_TEMP_HOTSPOT_PERCENTAGE = 53,
|
||||
PMLOG_THROTTLER_TEMP_HOTSPOT_GCD_PERCENTAGE = 54,
|
||||
PMLOG_THROTTLER_TEMP_HOTSPOT_MCD_PERCENTAGE = 55,
|
||||
PMLOG_THROTTLER_TEMP_MEM_PERCENTAGE = 56,
|
||||
PMLOG_THROTTLER_TEMP_VR_GFX_PERCENTAGE = 57,
|
||||
PMLOG_THROTTLER_TEMP_VR_MEM0_PERCENTAGE = 58,
|
||||
PMLOG_THROTTLER_TEMP_VR_MEM1_PERCENTAGE = 59,
|
||||
PMLOG_THROTTLER_TEMP_VR_SOC_PERCENTAGE = 60,
|
||||
PMLOG_THROTTLER_TEMP_LIQUID0_PERCENTAGE = 61,
|
||||
PMLOG_THROTTLER_TEMP_LIQUID1_PERCENTAGE = 62,
|
||||
PMLOG_THROTTLER_TEMP_PLX_PERCENTAGE = 63,
|
||||
PMLOG_THROTTLER_TDC_GFX_PERCENTAGE = 64,
|
||||
PMLOG_THROTTLER_TDC_SOC_PERCENTAGE = 65,
|
||||
PMLOG_THROTTLER_TDC_USR_PERCENTAGE = 66,
|
||||
PMLOG_THROTTLER_PPT0_PERCENTAGE = 67,
|
||||
PMLOG_THROTTLER_PPT1_PERCENTAGE = 68,
|
||||
PMLOG_THROTTLER_PPT2_PERCENTAGE = 69,
|
||||
PMLOG_THROTTLER_PPT3_PERCENTAGE = 70,
|
||||
PMLOG_THROTTLER_FIT_PERCENTAGE = 71,
|
||||
PMLOG_THROTTLER_GFX_APCC_PLUS_PERCENTAGE = 72,
|
||||
PMLOG_BOARD_POWER = 73,
|
||||
PMLOG_THROTTLE_PERCENTAGE_TEMP_GFX = 52,
|
||||
PMLOG_THROTTLE_PERCENTAGE_TEMP_MEM = 53,
|
||||
PMLOG_THROTTLE_PERCENTAGE_TEMP_VR = 54,
|
||||
PMLOG_THROTTLE_PERCENTAGE_POWER = 55,
|
||||
PMLOG_THROTTLE_PERCENTAGE_TDC = 56,
|
||||
PMLOG_THROTTLE_PERCENTAGE_VMAX = 57,
|
||||
PMLOG_BUS_CURR_MAX_SPEED = 58,
|
||||
PMLOG_RESERVED_1 = 59, //Currently Unused
|
||||
PMLOG_RESERVED_2 = 60, //Currently Unused
|
||||
PMLOG_RESERVED_3 = 61, //Currently Unused
|
||||
PMLOG_RESERVED_4 = 62, //Currently Unused
|
||||
PMLOG_RESERVED_5 = 63, //Currently Unused
|
||||
PMLOG_RESERVED_6 = 64, //Currently Unused
|
||||
PMLOG_RESERVED_7 = 65, //Currently Unused
|
||||
PMLOG_RESERVED_8 = 66, //Currently Unused
|
||||
PMLOG_RESERVED_9 = 67, //Currently Unused
|
||||
PMLOG_RESERVED_10 = 68, //Currently Unused
|
||||
PMLOG_RESERVED_11 = 69, //Currently Unused
|
||||
PMLOG_RESERVED_12 = 70, //Currently Unused
|
||||
PMLOG_RESERVED_13 = 71, //Currently Unused
|
||||
PMLOG_RESERVED_14 = 72,
|
||||
PMLOG_BOARD_POWER = 73,
|
||||
PMLOG_MAX_SENSORS_REAL
|
||||
} ADLSensorType;
|
||||
|
||||
@@ -2068,28 +2104,29 @@ typedef enum ADL_PMLOG_SENSORS
|
||||
ADL_PMLOG_SSDGPU_POWERLIMIT = 49, // DGPU Power limit
|
||||
ADL_PMLOG_TEMPERATURE_HOTSPOT_GCD = 50,
|
||||
ADL_PMLOG_TEMPERATURE_HOTSPOT_MCD = 51,
|
||||
ADL_PMLOG_THROTTLER_TEMP_EDGE_PERCENTAGE = 52,
|
||||
ADL_PMLOG_THROTTLER_TEMP_HOTSPOT_PERCENTAGE = 53,
|
||||
ADL_PMLOG_THROTTLER_TEMP_HOTSPOT_GCD_PERCENTAGE = 54,
|
||||
ADL_PMLOG_THROTTLER_TEMP_HOTSPOT_MCD_PERCENTAGE = 55,
|
||||
ADL_PMLOG_THROTTLER_TEMP_MEM_PERCENTAGE = 56,
|
||||
ADL_PMLOG_THROTTLER_TEMP_VR_GFX_PERCENTAGE = 57,
|
||||
ADL_PMLOG_THROTTLER_TEMP_VR_MEM0_PERCENTAGE = 58,
|
||||
ADL_PMLOG_THROTTLER_TEMP_VR_MEM1_PERCENTAGE = 59,
|
||||
ADL_PMLOG_THROTTLER_TEMP_VR_SOC_PERCENTAGE = 60,
|
||||
ADL_PMLOG_THROTTLER_TEMP_LIQUID0_PERCENTAGE = 61,
|
||||
ADL_PMLOG_THROTTLER_TEMP_LIQUID1_PERCENTAGE = 62,
|
||||
ADL_PMLOG_THROTTLER_TEMP_PLX_PERCENTAGE = 63,
|
||||
ADL_PMLOG_THROTTLER_TDC_GFX_PERCENTAGE = 64,
|
||||
ADL_PMLOG_THROTTLER_TDC_SOC_PERCENTAGE = 65,
|
||||
ADL_PMLOG_THROTTLER_TDC_USR_PERCENTAGE = 66,
|
||||
ADL_PMLOG_THROTTLER_PPT0_PERCENTAGE = 67,
|
||||
ADL_PMLOG_THROTTLER_PPT1_PERCENTAGE = 68,
|
||||
ADL_PMLOG_THROTTLER_PPT2_PERCENTAGE = 69,
|
||||
ADL_PMLOG_THROTTLER_PPT3_PERCENTAGE = 70,
|
||||
ADL_PMLOG_THROTTLER_FIT_PERCENTAGE = 71,
|
||||
ADL_PMLOG_THROTTLER_GFX_APCC_PLUS_PERCENTAGE = 72,
|
||||
ADL_PMLOG_BOARD_POWER = 73,
|
||||
ADL_PMLOG_THROTTLE_PERCENTAGE_TEMP_GFX = 52,
|
||||
ADL_PMLOG_THROTTLE_PERCENTAGE_TEMP_MEM = 53,
|
||||
ADL_PMLOG_THROTTLE_PERCENTAGE_TEMP_VR = 54,
|
||||
ADL_PMLOG_THROTTLE_PERCENTAGE_POWER = 55,
|
||||
ADL_PMLOG_THROTTLE_PERCENTAGE_TDC = 56,
|
||||
ADL_PMLOG_THROTTLE_PERCENTAGE_VMAX = 57,
|
||||
ADL_PMLOG_BUS_CURR_MAX_SPEED = 58,
|
||||
ADL_PMLOG_RESERVED_1 = 59, //Currently Unused
|
||||
ADL_PMLOG_RESERVED_2 = 60, //Currently Unused
|
||||
ADL_PMLOG_RESERVED_3 = 61, //Currently Unused
|
||||
ADL_PMLOG_RESERVED_4 = 62, //Currently Unused
|
||||
ADL_PMLOG_RESERVED_5 = 63, //Currently Unused
|
||||
ADL_PMLOG_RESERVED_6 = 64, //Currently Unused
|
||||
ADL_PMLOG_RESERVED_7 = 65, //Currently Unused
|
||||
ADL_PMLOG_RESERVED_8 = 66, //Currently Unused
|
||||
ADL_PMLOG_RESERVED_9 = 67, //Currently Unused
|
||||
ADL_PMLOG_RESERVED_10 = 68, //Currently Unused
|
||||
ADL_PMLOG_RESERVED_11 = 69, //Currently Unused
|
||||
ADL_PMLOG_RESERVED_12 = 70, //Currently Unused
|
||||
ADL_PMLOG_CLK_NPUCLK = 71, //NPU frequency
|
||||
ADL_PMLOG_NPU_BUSY_AVG = 72, //NPU busy
|
||||
ADL_PMLOG_BOARD_POWER = 73,
|
||||
ADL_PMLOG_TEMPERATURE_INTAKE = 74,
|
||||
ADL_PMLOG_MAX_SENSORS_REAL
|
||||
} ADL_PMLOG_SENSORS;
|
||||
|
||||
@@ -2393,6 +2430,9 @@ typedef enum ADL_PMLOG_SENSORS
|
||||
/// Indicates there is crossGPU clone
|
||||
#define ADL_CROSSGPUDISPLAYCLONE 0x2
|
||||
|
||||
|
||||
/// @}
|
||||
|
||||
/// @}
|
||||
|
||||
/// \defgroup define_D3DKMT_HANDLE
|
||||
@@ -2493,7 +2533,11 @@ typedef enum ADL_UIFEATURES_GROUP
|
||||
ADL_UIFEATURES_GROUP_PROVSR = 12,
|
||||
ADL_UIFEATURES_GROUP_SMA = 13,
|
||||
ADL_UIFEATURES_GROUP_CAMERA = 14,
|
||||
ADL_UIFEATURES_GROUP_FRTCPRO = 15
|
||||
ADL_UIFEATURES_GROUP_FRTCPRO = 15,
|
||||
ADL_UIFEATURES_GROUP_DELAGNEXT = 16,
|
||||
ADL_UIFEATURES_GROUP_RTBOOST = 17,
|
||||
ADL_UIFEATURES_GROUP_UAI = 18
|
||||
|
||||
} ADL_UIFEATURES_GROUP;
|
||||
|
||||
|
||||
@@ -2587,9 +2631,18 @@ typedef enum ADL_USER_SETTINGS
|
||||
ADL_USER_SETTINGS_USU_PROFILE = 1 << 4, //notify USU settings change
|
||||
ADL_USER_SETTINGS_CVDC_PROFILE = 1 << 5, //notify Color Vision Deficiency Corretion settings change
|
||||
ADL_USER_SETTINGS_SCE_PROFILE = 1 << 6,
|
||||
ADL_USER_SETTINGS_PROVSR = 1 << 7
|
||||
ADL_USER_SETTINGS_PROVSR = 1 << 7,
|
||||
ADL_USER_SETTINGS_RTBOOST_PROFILE=1 << 8,
|
||||
ADL_USER_SETTINGS_USU2_PROFILE = 1 << 9, //notify USU2 settings change
|
||||
} ADL_USER_SETTINGS;
|
||||
|
||||
//FRAME_TIMESTAMPS_SHARED_MEMORY type
|
||||
typedef enum FRAME_TIMESTAMPS_SHARED_MEMORY_TYPE
|
||||
{
|
||||
FRAME_TIMESTAMPS_SHARED_MEMORY_TYPE_UNKNOWN = 0,
|
||||
FRAME_TIMESTAMPS_SHARED_MEMORY_TYPE_LEGACY,
|
||||
FRAME_TIMESTAMPS_SHARED_MEMORY_TYPE_INDEXED
|
||||
}FRAME_TIMESTAMPS_SHARED_MEMORY_TYPE;
|
||||
#define ADL_REG_DEVICE_FUNCTION_1 0x00000001
|
||||
#endif /* ADL_DEFINES_H_ */
|
||||
|
||||
|
||||
+2
-6
@@ -33,14 +33,10 @@
|
||||
|
||||
#include "adl_structures.h"
|
||||
|
||||
#if defined (LINUX)
|
||||
#define __stdcall
|
||||
#endif /* (LINUX) */
|
||||
|
||||
/// Memory Allocation Call back
|
||||
typedef void* ( __stdcall *ADL_MAIN_MALLOC_CALLBACK )( int );
|
||||
|
||||
#define ADL_SDK_MAJOR_VERSION 17
|
||||
#define ADL_SDK_MINOR_VERSION 1
|
||||
#define ADL_SDK_MAJOR_VERSION 18
|
||||
#define ADL_SDK_MINOR_VERSION 0
|
||||
|
||||
#endif /* ADL_SDK_H_ */
|
||||
|
||||
+29
-36
@@ -21,7 +21,7 @@
|
||||
// SOFTWARE.
|
||||
|
||||
/// \file adl_structures.h
|
||||
///\brief This file contains the structure declarations that are used by the public ADL interfaces for \ALL platforms.\n <b>Included in ADL SDK</b>
|
||||
///\brief This file contains the structure declarations that are used by the public ADL interfaces for \WIN platforms.\n <b>Included in ADL SDK</b>
|
||||
///
|
||||
/// All data structures used in AMD Display Library (ADL) public interfaces should be defined in this header file.
|
||||
///
|
||||
@@ -41,7 +41,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
typedef struct AdapterInfo
|
||||
{
|
||||
/// \ALL_STRUCT_MEM
|
||||
/// \WIN_STRUCT_MEM
|
||||
|
||||
/// Size of the structure.
|
||||
int iSize;
|
||||
@@ -59,7 +59,7 @@ typedef struct AdapterInfo
|
||||
int iVendorID;
|
||||
/// Adapter name.
|
||||
char strAdapterName[ADL_MAX_PATH];
|
||||
/// Display name. For example, "\\\\Display0" for Windows or ":0:0" for Linux.
|
||||
/// Display name. For example, "\\\\Display0" for Windows.
|
||||
char strDisplayName[ADL_MAX_PATH];
|
||||
/// Present or not; 1 if present and 0 if not present.It the logical adapter is present, the display name such as \\\\.\\Display1 can be found from OS
|
||||
int iPresent;
|
||||
@@ -80,38 +80,8 @@ typedef struct AdapterInfo
|
||||
|
||||
#endif /* (_WIN32) || (_WIN64) */
|
||||
|
||||
#if defined (LINUX)
|
||||
/// \LNX_STRUCT_MEM
|
||||
|
||||
/// Internal X screen number from GPUMapInfo (DEPRICATED use XScreenInfo)
|
||||
int iXScreenNum;
|
||||
/// Internal driver index from GPUMapInfo
|
||||
int iDrvIndex;
|
||||
/// \deprecated Internal x config file screen identifier name. Use XScreenInfo instead.
|
||||
char strXScreenConfigName[ADL_MAX_PATH];
|
||||
|
||||
#endif /* (LINUX) */
|
||||
} AdapterInfo, *LPAdapterInfo;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///\brief Structure containing information about the Linux X screen information.
|
||||
///
|
||||
/// This structure is used to store the current screen number and xorg.conf ID name assoicated with an adapter index.
|
||||
/// This structure is updated during ADL_Main_Control_Refresh or ADL_ScreenInfo_Update.
|
||||
/// Note: This structure should be used in place of iXScreenNum and strXScreenConfigName in AdapterInfo as they will be
|
||||
/// deprecated.
|
||||
/// \nosubgrouping
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#if defined (LINUX)
|
||||
typedef struct XScreenInfo
|
||||
{
|
||||
/// Internal X screen number from GPUMapInfo.
|
||||
int iXScreenNum;
|
||||
/// Internal x config file screen identifier name.
|
||||
char strXScreenConfigName[ADL_MAX_PATH];
|
||||
} XScreenInfo, *LPXScreenInfo;
|
||||
#endif /* (LINUX) */
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///\brief Structure containing information about an controller mode
|
||||
///
|
||||
@@ -453,8 +423,12 @@ typedef struct ADLDDCInfo2
|
||||
int ulMaxBacklightMinLuminanceData;
|
||||
int ulMinBacklightMinLuminanceData;
|
||||
|
||||
// Display screen width/height
|
||||
int ulScreenWidth;
|
||||
int ulScreenHeight;
|
||||
|
||||
// Reserved for future use
|
||||
int iReserved[4];
|
||||
int iReserved[2];
|
||||
} ADLDDCInfo2, *LPADLDDCInfo2;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -3614,6 +3588,23 @@ typedef struct ADL_BOOST_SETTINGS
|
||||
int GlobalMinRes_Step; //Gloabl Min Resolution step value
|
||||
}ADL_BOOST_SETTINGS;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///\brief Structure containing information about BOOST Settings
|
||||
///
|
||||
/// Elements of BOOST settings.
|
||||
/// \nosubgrouping
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
typedef struct ADL_BOOST_SETTINGSX2
|
||||
{
|
||||
int Hotkey; // Hotkey value
|
||||
int GlobalEnable; //Global enable value
|
||||
int GlobalMinRes; //Gloabl Min Resolution value
|
||||
int GlobalMinRes_MinLimit; //Gloabl Min Resolution slider min limit value
|
||||
int GlobalMinRes_MaxLimit; //Gloabl Min Resolution slider max limit value
|
||||
int GlobalMinRes_Step; //Gloabl Min Resolution step value
|
||||
int VsrSupported; //Allows for interop with Upscaling/RSR
|
||||
}ADL_BOOST_SETTINGSX2;
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///\brief Structure containing information about ProVSR Settings change reason
|
||||
@@ -3817,7 +3808,7 @@ typedef struct ADL_RADEON_LED_PATTERN_CONFIG
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
typedef struct AdapterInfoX2
|
||||
{
|
||||
/// \ALL_STRUCT_MEM
|
||||
/// \WIN_STRUCT_MEM
|
||||
|
||||
/// Size of the structure.
|
||||
int iSize;
|
||||
@@ -4164,6 +4155,7 @@ typedef struct ADLHDCPSettings
|
||||
///
|
||||
/// This structure is used to store the Mantle Driver information
|
||||
/// \nosubgrouping
|
||||
/// \deprecated This structure has been deprecated.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct ADLMantleAppInfo
|
||||
@@ -4286,4 +4278,5 @@ typedef struct ADLSmartShiftSettings
|
||||
int iCurrentValue;
|
||||
int iFlags; //refer to define_smartshift_bits
|
||||
}ADLSmartShiftSettings, *LPADLSmartShiftSettings;
|
||||
#endif /* ADL_STRUCTURES_H_ */
|
||||
|
||||
#endif /* ADL_STRUCTURES_H_ */
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"home": "https://github.com/GPUOpen-LibrariesAndSDKs/display-library",
|
||||
"license": "MIT (embeded in source)",
|
||||
"version": "ADL SDK 17.1",
|
||||
"version": "ADL SDK 18.1",
|
||||
"author": "Advanced Micro Devices, Inc"
|
||||
}
|
||||
|
||||
@@ -1,32 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
#include "util/FFstrbuf.h"
|
||||
#include "util/FFlist.h"
|
||||
#include "common/FFstrbuf.h"
|
||||
#include "common/FFlist.h"
|
||||
|
||||
typedef struct FFPlatformSysinfo
|
||||
{
|
||||
typedef struct FFPlatformSysinfo {
|
||||
FFstrbuf name;
|
||||
FFstrbuf release;
|
||||
FFstrbuf version;
|
||||
FFstrbuf architecture;
|
||||
FFstrbuf displayVersion;
|
||||
uint32_t pageSize;
|
||||
} FFPlatformSysinfo;
|
||||
|
||||
typedef struct FFPlatform
|
||||
{
|
||||
typedef struct FFPlatform {
|
||||
FFstrbuf homeDir; // Trailing slash included
|
||||
FFstrbuf cacheDir; // Trailing slash included
|
||||
FFlist configDirs; // List of FFstrbuf, trailing slash included
|
||||
FFlist dataDirs; // List of FFstrbuf, trailing slash included
|
||||
FFstrbuf exePath; // The real path of current exe
|
||||
FFstrbuf exePath; // The real path of current exe (empty if unavailable)
|
||||
FFstrbuf cwd; // Trailing slash included
|
||||
|
||||
uint32_t pid;
|
||||
#ifndef _WIN32
|
||||
uint32_t uid;
|
||||
#else
|
||||
FFstrbuf sid;
|
||||
#endif
|
||||
FFstrbuf userName;
|
||||
FFstrbuf fullUserName;
|
||||
FFstrbuf hostName;
|
||||
FFstrbuf userShell;
|
||||
|
||||
FFPlatformSysinfo sysinfo;
|
||||
|
||||
#if _WIN32
|
||||
uint32_t initCP; // The code page used by the console when the program started
|
||||
#endif
|
||||
} FFPlatform;
|
||||
|
||||
void ffPlatformInit(FFPlatform* platform);
|
||||
@@ -0,0 +1,166 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define FF_LIST_DEFAULT_ALLOC 16
|
||||
|
||||
typedef struct FFlist {
|
||||
uint8_t* data;
|
||||
uint32_t length;
|
||||
uint32_t capacity;
|
||||
} FFlist;
|
||||
|
||||
// Removes the first element, and copy its value to `*result`
|
||||
bool ffListShift(FFlist* list, uint32_t elementSize, void* __restrict result);
|
||||
// Removes the last element, and copy its value to `*result`
|
||||
bool ffListPop(FFlist* list, uint32_t elementSize, void* __restrict result);
|
||||
|
||||
static inline void ffListInit(FFlist* list) {
|
||||
list->capacity = 0;
|
||||
list->length = 0;
|
||||
list->data = nullptr;
|
||||
}
|
||||
|
||||
static inline void ffListInitA(FFlist* list, uint32_t elementSize, uint32_t capacity) {
|
||||
ffListInit(list);
|
||||
list->capacity = capacity;
|
||||
list->data = __builtin_expect(capacity == 0, 0) ? nullptr : (uint8_t*) malloc((size_t) capacity * elementSize);
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline FFlist ffListCreate() {
|
||||
FFlist result;
|
||||
ffListInit(&result);
|
||||
return result;
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline FFlist ffListCreateA(uint32_t elementSize, uint32_t capacity) {
|
||||
FFlist result;
|
||||
ffListInitA(&result, elementSize, capacity);
|
||||
return result;
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline void* ffListGet(const FFlist* list, uint32_t elementSize, uint32_t index) {
|
||||
assert(list->capacity > index);
|
||||
return list->data + (index * elementSize);
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline uint32_t ffListFirstIndexComp(const FFlist* list, uint32_t elementSize, void* compElement, bool (*compFunc)(const void*, const void*)) {
|
||||
for (uint32_t i = 0; i < list->length; i++) {
|
||||
if (compFunc(ffListGet(list, elementSize, i), compElement)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return list->length;
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline bool ffListContains(const FFlist* list, uint32_t elementSize, void* compElement, bool (*compFunc)(const void*, const void*)) {
|
||||
return ffListFirstIndexComp(list, elementSize, compElement, compFunc) != list->length;
|
||||
}
|
||||
|
||||
static inline void ffListSort(FFlist* list, uint32_t elementSize, int (*compar)(const void*, const void*)) {
|
||||
qsort(list->data, list->length, elementSize, compar);
|
||||
}
|
||||
|
||||
// Move the contents of `src` into `list`, and left `src` empty
|
||||
static inline void ffListInitMove(FFlist* list, FFlist* src) {
|
||||
if (src) {
|
||||
list->capacity = src->capacity;
|
||||
list->length = src->length;
|
||||
list->data = src->data;
|
||||
ffListInit(src);
|
||||
} else {
|
||||
ffListInit(list);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void ffListDestroy(FFlist* list) {
|
||||
if (!list->data) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Avoid free-after-use. These 3 assignments are cheap so don't remove them
|
||||
list->capacity = list->length = 0;
|
||||
free(list->data);
|
||||
list->data = nullptr;
|
||||
}
|
||||
|
||||
static inline void ffListClear(FFlist* list) {
|
||||
list->length = 0;
|
||||
}
|
||||
|
||||
static inline void ffListReserve(FFlist* list, uint32_t elementSize, uint32_t newCapacity) {
|
||||
if (__builtin_expect(newCapacity <= list->capacity, false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
list->data = (uint8_t*) realloc(list->data, (size_t) newCapacity * elementSize);
|
||||
list->capacity = newCapacity;
|
||||
}
|
||||
|
||||
static inline void* ffListAdd(FFlist* list, uint32_t elementSize) {
|
||||
if (__builtin_expect(list->length == list->capacity, false)) {
|
||||
ffListReserve(list, elementSize, list->capacity == 0 ? FF_LIST_DEFAULT_ALLOC : list->capacity * 2);
|
||||
}
|
||||
|
||||
++list->length;
|
||||
return ffListGet(list, elementSize, list->length - 1);
|
||||
}
|
||||
|
||||
static inline void ffListRemoveAt(FFlist* list, uint32_t elementSize, uint32_t index) {
|
||||
assert(list->length > index);
|
||||
memmove(list->data + (index * elementSize), list->data + ((index + 1) * elementSize), (size_t) (list->length - index - 1) * elementSize);
|
||||
--list->length;
|
||||
}
|
||||
|
||||
static inline void ffListInsertAt(FFlist* list, uint32_t elementSize, uint32_t index, const void* element) {
|
||||
assert(list->length >= index);
|
||||
ffListAdd(list, elementSize);
|
||||
memmove(list->data + ((index + 1) * elementSize), list->data + (index * elementSize), (size_t) (list->length - index - 1) * elementSize);
|
||||
memcpy(list->data + (index * elementSize), element, elementSize);
|
||||
}
|
||||
|
||||
#define FF_LIST_FOR_EACH(itemType, itemVarName, listVar) \
|
||||
for (itemType* itemVarName = (itemType*) (listVar).data; \
|
||||
itemVarName - (itemType*) (listVar).data < (intptr_t) (listVar).length; \
|
||||
++itemVarName)
|
||||
|
||||
#define FF_LIST_AUTO_DESTROY [[gnu::cleanup(ffListDestroy)]] FFlist
|
||||
|
||||
#define FF_LIST_GET(itemType, listVar, index) \
|
||||
({ \
|
||||
assert((listVar).capacity > (index)); \
|
||||
(itemType*) (listVar).data + (index); \
|
||||
})
|
||||
|
||||
#define FF_LIST_ADD(itemType, listVar) (itemType*) ffListAdd(&(listVar), (uint32_t) sizeof(itemType))
|
||||
|
||||
#define FF_LIST_REMOVE_AT(itemType, listVar, index) \
|
||||
ffListRemoveAt(&(listVar), (uint32_t) sizeof(itemType), (index))
|
||||
|
||||
#define FF_LIST_INSERT_AT(itemType, listVar, index, pElement) \
|
||||
ffListInsertAt(&(listVar), (uint32_t) sizeof(itemType), (index), (pElement))
|
||||
|
||||
#define FF_LIST_FIRST(itemType, listVar) FF_LIST_GET(itemType, listVar, 0)
|
||||
#define FF_LIST_LAST(itemType, listVar) \
|
||||
({ \
|
||||
assert((listVar).length > 0); \
|
||||
FF_LIST_GET(itemType, listVar, ((listVar).length - 1)); \
|
||||
})
|
||||
|
||||
#define FF_LIST_CONTAINS(listVar, pCompElement, compFunc) \
|
||||
({ \
|
||||
typedef typeof(*(pCompElement)) compElementType; \
|
||||
typedef bool compFuncType(const compElementType*, const compElementType*); \
|
||||
static_assert(__builtin_types_compatible_p(typeof(compFunc), compFuncType), "Incompatible callback function"); \
|
||||
ffListContains(&(listVar), (uint32_t) sizeof(*(pCompElement)), (pCompElement), (bool (*)(const void*, const void*)) compFunc); \
|
||||
})
|
||||
|
||||
#define FF_LIST_SHIFT(listVar, pResult) \
|
||||
ffListShift(&(listVar), (uint32_t) sizeof(*(pResult)), (pResult))
|
||||
#define FF_LIST_POP(listVar, pResult) \
|
||||
ffListPop(&(listVar), (uint32_t) sizeof(*(pResult)), (pResult))
|
||||
@@ -0,0 +1,632 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include "common/memrchr.h"
|
||||
#include "common/arrutil.h"
|
||||
|
||||
#ifdef FF_USE_SYSTEM_YYJSON
|
||||
#include <yyjson.h>
|
||||
#else
|
||||
#include "3rdparty/yyjson/yyjson.h"
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
// #include <shlwapi.h>
|
||||
__stdcall char* StrStrIA(const char* lpFirst, const char* lpSrch);
|
||||
#define strcasestr StrStrIA
|
||||
#endif
|
||||
|
||||
#define FASTFETCH_STRBUF_DEFAULT_ALLOC 32
|
||||
|
||||
// static string (allocated == 0), chars points to a string literal
|
||||
// dynamic string (allocated > 0), chars points to a heap allocated buffer
|
||||
typedef struct FFstrbuf {
|
||||
uint32_t allocated;
|
||||
uint32_t length;
|
||||
char* chars;
|
||||
} FFstrbuf;
|
||||
|
||||
static inline void ffStrbufInit(FFstrbuf* strbuf);
|
||||
void ffStrbufInitA(FFstrbuf* strbuf, uint32_t allocate);
|
||||
void ffStrbufInitVF(FFstrbuf* strbuf, const char* format, va_list arguments);
|
||||
void ffStrbufInitMoveNS(FFstrbuf* strbuf, uint32_t length, char* heapStr);
|
||||
[[gnu::format(printf, 2, 3)]] void ffStrbufInitF(FFstrbuf* strbuf, const char* format, ...);
|
||||
[[gnu::format(printf, 1, 2)]] [[nodiscard]] FFstrbuf ffStrbufCreateF(const char* format, ...);
|
||||
|
||||
void ffStrbufEnsureFixedLengthFree(FFstrbuf* strbuf, uint32_t free);
|
||||
void ffStrbufEnsureFreeNoCheck(FFstrbuf* strbuf, uint32_t free);
|
||||
|
||||
static inline void ffStrbufAppend(FFstrbuf* __restrict strbuf, const FFstrbuf* __restrict value);
|
||||
void ffStrbufAppendTransformS(FFstrbuf* strbuf, const char* value, int (*transformFunc)(int));
|
||||
[[gnu::format(printf, 2, 3)]] void ffStrbufAppendF(FFstrbuf* strbuf, const char* format, ...);
|
||||
void ffStrbufAppendVF(FFstrbuf* strbuf, const char* format, va_list arguments);
|
||||
const char* ffStrbufAppendSUntilC(FFstrbuf* strbuf, const char* value, char until);
|
||||
|
||||
void ffStrbufPrependNS(FFstrbuf* strbuf, uint32_t length, const char* value);
|
||||
void ffStrbufPrependC(FFstrbuf* strbuf, char c);
|
||||
|
||||
void ffStrbufInsertNC(FFstrbuf* strbuf, uint32_t index, uint32_t num, char c);
|
||||
|
||||
// Clear the content of strbuf and set new value
|
||||
// NOTE: Unlike ffStrbufAppend*, ffStrbufSet* functions may NOT reserve extra space
|
||||
void ffStrbufSet(FFstrbuf* strbuf, const FFstrbuf* value);
|
||||
void ffStrbufSetNS(FFstrbuf* strbuf, uint32_t length, const char* value);
|
||||
[[gnu::format(printf, 2, 3)]] void ffStrbufSetF(FFstrbuf* strbuf, const char* format, ...);
|
||||
|
||||
void ffStrbufTrimLeft(FFstrbuf* strbuf, char c);
|
||||
void ffStrbufTrimRight(FFstrbuf* strbuf, char c);
|
||||
void ffStrbufTrimLeftSpace(FFstrbuf* strbuf);
|
||||
void ffStrbufTrimRightSpace(FFstrbuf* strbuf);
|
||||
|
||||
bool ffStrbufRemoveSubstr(FFstrbuf* strbuf, uint32_t startIndex, uint32_t endIndex);
|
||||
void ffStrbufRemoveS(FFstrbuf* strbuf, const char* str);
|
||||
void ffStrbufRemoveStrings(FFstrbuf* strbuf, uint32_t numStrings, const char* strings[]);
|
||||
|
||||
void ffStrbufReplaceAllC(FFstrbuf* strbuf, char find, char replace);
|
||||
|
||||
// Returns true if the strbuf is modified
|
||||
bool ffStrbufSubstrBefore(FFstrbuf* strbuf, uint32_t index);
|
||||
bool ffStrbufSubstrAfter(FFstrbuf* strbuf, uint32_t index); // Not including the index
|
||||
bool ffStrbufSubstrAfterFirstC(FFstrbuf* strbuf, char c);
|
||||
bool ffStrbufSubstrAfterFirstS(FFstrbuf* strbuf, const char* str);
|
||||
bool ffStrbufSubstrAfterLastC(FFstrbuf* strbuf, char c);
|
||||
bool ffStrbufSubstr(FFstrbuf* strbuf, uint32_t start, uint32_t end);
|
||||
|
||||
[[nodiscard]] uint32_t ffStrbufCountC(const FFstrbuf* strbuf, char c);
|
||||
|
||||
bool ffStrbufRemoveIgnCaseEndS(FFstrbuf* strbuf, const char* end);
|
||||
|
||||
bool ffStrbufEnsureEndsWithC(FFstrbuf* strbuf, char c);
|
||||
|
||||
void ffStrbufUpperCase(FFstrbuf* strbuf);
|
||||
void ffStrbufLowerCase(FFstrbuf* strbuf);
|
||||
|
||||
// Function alters the buffer to extract lines or delimited segments (replaces the delimiter with '\0')
|
||||
// so that buffer MUST be heap allocated (NOT a static string)
|
||||
// `lineptr` must be `nullptr` and `n` MUST be `0` for the first call
|
||||
// Caller MUST NOT free `*lineptr`
|
||||
bool ffStrbufGetdelim(char** lineptr, size_t* n, char delimiter, FFstrbuf* buffer);
|
||||
void ffStrbufGetdelimRestore(char** lineptr, size_t* n, char delimiter, FFstrbuf* buffer);
|
||||
|
||||
/**
|
||||
* @brief Read a line from a FFstrbuf.
|
||||
*
|
||||
* @details Behaves like getline(3) but reads from a FFstrbuf.
|
||||
*
|
||||
* @param[in,out] lineptr The pointer to a pointer that will be set to the start of the line
|
||||
(points to buffer's internal memory address to avoid memory allocation and copy).
|
||||
MUST NOT be freed by the caller, unlike `getline(3)`.
|
||||
* MUST be nullptr for the first call.
|
||||
* @param[in,out] n The pointer to the size of the buffer of lineptr.
|
||||
MUST be 0 for the first call.
|
||||
* @param[in] buffer The buffer to read from.
|
||||
MUST be heap allocated (NOT a static string).
|
||||
*
|
||||
* @return true if a line has been read, false if the end of the buffer has been reached.
|
||||
*/
|
||||
static inline bool ffStrbufGetline(char** lineptr, size_t* n, FFstrbuf* buffer) {
|
||||
return ffStrbufGetdelim(lineptr, n, '\n', buffer);
|
||||
}
|
||||
/**
|
||||
* @brief Restore the end of a line that was modified by ffStrbufGetline.
|
||||
* @warning This function should be called before breaking an ffStrbufGetline loop if `buffer` will be used later.
|
||||
*/
|
||||
static inline void ffStrbufGetlineRestore(char** lineptr, size_t* n, FFstrbuf* buffer) {
|
||||
ffStrbufGetdelimRestore(lineptr, n, '\n', buffer);
|
||||
}
|
||||
bool ffStrbufRemoveDupWhitespaces(FFstrbuf* strbuf);
|
||||
bool ffStrbufMatchSeparatedNS(const FFstrbuf* strbuf, uint32_t compLength, const char* comp, char separator);
|
||||
bool ffStrbufMatchSeparatedIgnCaseNS(const FFstrbuf* strbuf, uint32_t compLength, const char* comp, char separator);
|
||||
bool ffStrbufSeparatedContainNS(const FFstrbuf* strbuf, uint32_t compLength, const char* comp, char separator);
|
||||
bool ffStrbufSeparatedContainIgnCaseNS(const FFstrbuf* strbuf, uint32_t compLength, const char* comp, char separator);
|
||||
|
||||
int ffStrbufAppendUtf32CodePoint(FFstrbuf* strbuf, uint32_t codepoint);
|
||||
|
||||
void ffStrbufAppendSInt(FFstrbuf* strbuf, int64_t value);
|
||||
void ffStrbufAppendUInt(FFstrbuf* strbuf, uint64_t value);
|
||||
// Appends a double value to the string buffer with the specified precision (0~15).
|
||||
// if `precision < 0`, let yyjson decide the precision
|
||||
void ffStrbufAppendDouble(FFstrbuf* strbuf, double value, int8_t precision, bool trailingZeros);
|
||||
|
||||
[[nodiscard]] static inline FFstrbuf ffStrbufCreateA(uint32_t allocate) {
|
||||
FFstrbuf strbuf;
|
||||
ffStrbufInitA(&strbuf, allocate);
|
||||
return strbuf;
|
||||
}
|
||||
|
||||
static inline void ffStrbufInitCopy(FFstrbuf* __restrict strbuf, const FFstrbuf* __restrict src) {
|
||||
if (src->allocated == 0) { // static string
|
||||
*strbuf = *src;
|
||||
} else {
|
||||
ffStrbufInitA(strbuf, src->allocated);
|
||||
ffStrbufAppend(strbuf, src);
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline FFstrbuf ffStrbufCreateCopy(const FFstrbuf* src) {
|
||||
FFstrbuf strbuf;
|
||||
ffStrbufInitCopy(&strbuf, src);
|
||||
return strbuf;
|
||||
}
|
||||
|
||||
// Move the content of `src` into `strbuf`, and left `src` empty
|
||||
static inline void ffStrbufInitMove(FFstrbuf* strbuf, FFstrbuf* src) {
|
||||
if (src) {
|
||||
*strbuf = *src;
|
||||
ffStrbufInit(src);
|
||||
} else {
|
||||
ffStrbufInit(strbuf);
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline FFstrbuf ffStrbufCreateMove(FFstrbuf* src) {
|
||||
FFstrbuf strbuf;
|
||||
ffStrbufInitMove(&strbuf, src);
|
||||
return strbuf;
|
||||
}
|
||||
|
||||
static inline void ffStrbufInitMoveS(FFstrbuf* strbuf, char* heapStr) {
|
||||
ffStrbufInitMoveNS(strbuf, (uint32_t) strlen(heapStr), heapStr);
|
||||
}
|
||||
|
||||
// Despite the name, this function resets strbuf to the initial/unallocated state
|
||||
static inline void ffStrbufDestroy(FFstrbuf* strbuf) {
|
||||
if (strbuf->allocated > 0) {
|
||||
free(strbuf->chars);
|
||||
}
|
||||
|
||||
ffStrbufInit(strbuf);
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline uint32_t ffStrbufGetFree(const FFstrbuf* strbuf) {
|
||||
assert(strbuf != nullptr);
|
||||
if (strbuf->allocated == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return strbuf->allocated - strbuf->length - 1; // - 1 for the null byte
|
||||
}
|
||||
|
||||
static inline void ffStrbufEnsureFree(FFstrbuf* strbuf, uint32_t free) {
|
||||
if (__builtin_expect(free == 0, false)) {
|
||||
if (__builtin_expect(!(strbuf->allocated == 0 && strbuf->length > 0), true)) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (__builtin_expect(ffStrbufGetFree(strbuf) >= free, true)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ffStrbufEnsureFreeNoCheck(strbuf, free);
|
||||
}
|
||||
|
||||
|
||||
static inline void ffStrbufClear(FFstrbuf* strbuf) {
|
||||
assert(strbuf != nullptr);
|
||||
extern char* CHAR_NULL_PTR;
|
||||
|
||||
if (strbuf->allocated == 0) {
|
||||
strbuf->chars = CHAR_NULL_PTR;
|
||||
} else {
|
||||
strbuf->chars[0] = '\0';
|
||||
}
|
||||
|
||||
strbuf->length = 0;
|
||||
}
|
||||
|
||||
static inline void ffStrbufAppendC(FFstrbuf* strbuf, char c) {
|
||||
ffStrbufEnsureFree(strbuf, 1);
|
||||
strbuf->chars[strbuf->length++] = c;
|
||||
strbuf->chars[strbuf->length] = '\0';
|
||||
}
|
||||
|
||||
static inline void ffStrbufAppendNC(FFstrbuf* strbuf, uint32_t num, char c) {
|
||||
if (__builtin_expect(num == 0, false)) {
|
||||
return;
|
||||
}
|
||||
ffStrbufEnsureFree(strbuf, num);
|
||||
|
||||
memset(&strbuf->chars[strbuf->length], c, num);
|
||||
strbuf->length += num;
|
||||
strbuf->chars[strbuf->length] = '\0';
|
||||
}
|
||||
|
||||
static inline void ffStrbufAppendNS(FFstrbuf* strbuf, uint32_t length, const char* value) {
|
||||
if (__builtin_expect(value == nullptr || length == 0, false)) {
|
||||
return;
|
||||
}
|
||||
ffStrbufEnsureFree(strbuf, length);
|
||||
|
||||
memcpy(&strbuf->chars[strbuf->length], value, length);
|
||||
strbuf->length += length;
|
||||
strbuf->chars[strbuf->length] = '\0';
|
||||
}
|
||||
|
||||
static inline void ffStrbufAppend(FFstrbuf* __restrict strbuf, const FFstrbuf* __restrict value) {
|
||||
assert(value != strbuf);
|
||||
if (value == nullptr) {
|
||||
return;
|
||||
}
|
||||
ffStrbufAppendNS(strbuf, value->length, value->chars);
|
||||
}
|
||||
|
||||
static inline void ffStrbufRecalculateLength(FFstrbuf* strbuf) {
|
||||
strbuf->length = (uint32_t) strlen(strbuf->chars);
|
||||
}
|
||||
|
||||
static inline void ffStrbufSetS(FFstrbuf* strbuf, const char* value) {
|
||||
assert(strbuf != nullptr);
|
||||
|
||||
if (value == nullptr) {
|
||||
ffStrbufClear(strbuf);
|
||||
} else {
|
||||
ffStrbufSetNS(strbuf, (uint32_t) strlen(value), value);
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool ffStrbufSetJsonVal(FFstrbuf* strbuf, yyjson_val* jsonVal) {
|
||||
assert(strbuf != nullptr);
|
||||
|
||||
if (yyjson_is_str(jsonVal)) {
|
||||
ffStrbufSetNS(strbuf, (uint32_t) unsafe_yyjson_get_len(jsonVal), unsafe_yyjson_get_str(jsonVal));
|
||||
return true;
|
||||
}
|
||||
|
||||
ffStrbufClear(strbuf);
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void ffStrbufAppendS(FFstrbuf* strbuf, const char* value) {
|
||||
if (value == nullptr) {
|
||||
return;
|
||||
}
|
||||
ffStrbufAppendNS(strbuf, (uint32_t) strlen(value), value);
|
||||
}
|
||||
|
||||
static inline bool ffStrbufAppendJsonVal(FFstrbuf* strbuf, yyjson_val* jsonVal) {
|
||||
if (yyjson_is_str(jsonVal)) {
|
||||
ffStrbufAppendNS(strbuf, (uint32_t) unsafe_yyjson_get_len(jsonVal), unsafe_yyjson_get_str(jsonVal));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void ffStrbufInit(FFstrbuf* strbuf) {
|
||||
extern char* CHAR_NULL_PTR;
|
||||
strbuf->allocated = strbuf->length = 0;
|
||||
strbuf->chars = CHAR_NULL_PTR;
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline FFstrbuf ffStrbufCreate(void) {
|
||||
FFstrbuf strbuf;
|
||||
ffStrbufInit(&strbuf);
|
||||
return strbuf;
|
||||
}
|
||||
|
||||
static inline void ffStrbufInitStatic(FFstrbuf* strbuf, const char* str) {
|
||||
ffStrbufInit(strbuf);
|
||||
if (!str) {
|
||||
return;
|
||||
}
|
||||
|
||||
strbuf->allocated = 0;
|
||||
strbuf->length = (uint32_t) strlen(str);
|
||||
strbuf->chars = (char*) str;
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline FFstrbuf ffStrbufCreateStatic(const char* str) {
|
||||
FFstrbuf strbuf;
|
||||
ffStrbufInitStatic(&strbuf, str);
|
||||
return strbuf;
|
||||
}
|
||||
|
||||
static inline void ffStrbufSetStatic(FFstrbuf* strbuf, const char* value) {
|
||||
if (strbuf->allocated > 0) {
|
||||
free(strbuf->chars);
|
||||
}
|
||||
|
||||
if (value != nullptr) {
|
||||
ffStrbufInitStatic(strbuf, value);
|
||||
} else {
|
||||
ffStrbufInit(strbuf);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void ffStrbufInitNS(FFstrbuf* strbuf, uint32_t length, const char* str) {
|
||||
ffStrbufInit(strbuf);
|
||||
ffStrbufAppendNS(strbuf, length, str);
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline FFstrbuf ffStrbufCreateNS(uint32_t length, const char* str) {
|
||||
FFstrbuf strbuf;
|
||||
ffStrbufInitNS(&strbuf, length, str);
|
||||
return strbuf;
|
||||
}
|
||||
|
||||
static inline bool ffStrbufInitJsonVal(FFstrbuf* strbuf, yyjson_val* jsonVal) {
|
||||
ffStrbufInit(strbuf);
|
||||
return ffStrbufAppendJsonVal(strbuf, jsonVal);
|
||||
}
|
||||
|
||||
static inline void ffStrbufInitS(FFstrbuf* strbuf, const char* str) {
|
||||
ffStrbufInit(strbuf);
|
||||
ffStrbufAppendS(strbuf, str);
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline FFstrbuf ffStrbufCreateS(const char* str) {
|
||||
FFstrbuf strbuf;
|
||||
ffStrbufInitS(&strbuf, str);
|
||||
return strbuf;
|
||||
}
|
||||
|
||||
static inline void ffStrbufPrepend(FFstrbuf* strbuf, FFstrbuf* value) {
|
||||
if (value == nullptr) {
|
||||
return;
|
||||
}
|
||||
ffStrbufPrependNS(strbuf, value->length, value->chars);
|
||||
}
|
||||
|
||||
static inline void ffStrbufPrependS(FFstrbuf* strbuf, const char* value) {
|
||||
if (value == nullptr) {
|
||||
return;
|
||||
}
|
||||
ffStrbufPrependNS(strbuf, (uint32_t) strlen(value), value);
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline int ffStrbufComp(const FFstrbuf* strbuf, const FFstrbuf* comp) {
|
||||
uint32_t length = strbuf->length > comp->length ? comp->length : strbuf->length;
|
||||
return memcmp(strbuf->chars, comp->chars, length + 1);
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline bool ffStrbufEqual(const FFstrbuf* strbuf, const FFstrbuf* comp) {
|
||||
return ffStrbufComp(strbuf, comp) == 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline int ffStrbufCompS(const FFstrbuf* strbuf, const char* comp) {
|
||||
return strcmp(strbuf->chars, comp);
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline bool ffStrbufEqualS(const FFstrbuf* strbuf, const char* comp) {
|
||||
return ffStrbufCompS(strbuf, comp) == 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline int ffStrbufIgnCaseCompS(const FFstrbuf* strbuf, const char* comp) {
|
||||
return strcasecmp(strbuf->chars, comp);
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline bool ffStrbufIgnCaseEqualS(const FFstrbuf* strbuf, const char* comp) {
|
||||
return ffStrbufIgnCaseCompS(strbuf, comp) == 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline int ffStrbufIgnCaseComp(const FFstrbuf* strbuf, const FFstrbuf* comp) {
|
||||
return ffStrbufIgnCaseCompS(strbuf, comp->chars);
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline bool ffStrbufIgnCaseEqual(const FFstrbuf* strbuf, const FFstrbuf* comp) {
|
||||
return ffStrbufIgnCaseComp(strbuf, comp) == 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline bool ffStrbufContainC(const FFstrbuf* strbuf, char c) {
|
||||
return memchr(strbuf->chars, c, strbuf->length) != nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline bool ffStrbufContainS(const FFstrbuf* strbuf, const char* str) {
|
||||
return strstr(strbuf->chars, str) != nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline bool ffStrbufContain(const FFstrbuf* strbuf, const FFstrbuf* str) {
|
||||
return ffStrbufContainS(strbuf, str->chars);
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline bool ffStrbufContainIgnCaseS(const FFstrbuf* strbuf, const char* str) {
|
||||
return strcasestr(strbuf->chars, str) != nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline bool ffStrbufContainIgnCase(const FFstrbuf* strbuf, const FFstrbuf* str) {
|
||||
return ffStrbufContainIgnCaseS(strbuf, str->chars);
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline uint32_t ffStrbufNextIndexC(const FFstrbuf* strbuf, uint32_t start, char c) {
|
||||
assert(start <= strbuf->length);
|
||||
|
||||
const char* ptr = (const char*) memchr(strbuf->chars + start, c, strbuf->length - start);
|
||||
return ptr ? (uint32_t) (ptr - strbuf->chars) : strbuf->length;
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline uint32_t ffStrbufNextIndexS(const FFstrbuf* strbuf, uint32_t start, const char* str) {
|
||||
assert(start <= strbuf->length);
|
||||
|
||||
const char* ptr = strstr(strbuf->chars + start, str);
|
||||
return ptr ? (uint32_t) (ptr - strbuf->chars) : strbuf->length;
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline uint32_t ffStrbufPreviousIndexC(const FFstrbuf* strbuf, uint32_t start, char c) {
|
||||
assert(start <= strbuf->length);
|
||||
|
||||
const char* ptr = (const char*) memrchr(strbuf->chars, c, start + 1);
|
||||
return ptr ? (uint32_t) (ptr - strbuf->chars) : strbuf->length;
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline uint32_t ffStrbufFirstIndexC(const FFstrbuf* strbuf, char c) {
|
||||
return ffStrbufNextIndexC(strbuf, 0, c);
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline uint32_t ffStrbufFirstIndex(const FFstrbuf* strbuf, const FFstrbuf* searched) {
|
||||
return ffStrbufNextIndexS(strbuf, 0, searched->chars);
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline uint32_t ffStrbufFirstIndexS(const FFstrbuf* strbuf, const char* str) {
|
||||
return ffStrbufNextIndexS(strbuf, 0, str);
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline uint32_t ffStrbufLastIndexC(const FFstrbuf* strbuf, char c) {
|
||||
if (strbuf->length == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ffStrbufPreviousIndexC(strbuf, strbuf->length - 1, c);
|
||||
}
|
||||
|
||||
static inline bool ffStrbufSubstrBeforeFirstC(FFstrbuf* strbuf, char c) {
|
||||
return ffStrbufSubstrBefore(strbuf, ffStrbufFirstIndexC(strbuf, c));
|
||||
}
|
||||
|
||||
static inline bool ffStrbufSubstrBeforeLastC(FFstrbuf* strbuf, char c) {
|
||||
return ffStrbufSubstrBefore(strbuf, ffStrbufLastIndexC(strbuf, c));
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline bool ffStrbufStartsWithC(const FFstrbuf* strbuf, char c) {
|
||||
return strbuf->chars[0] == c;
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline bool ffStrbufStartsWithSN(const FFstrbuf* strbuf, const char* start, uint32_t length) {
|
||||
if (length > strbuf->length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return memcmp(strbuf->chars, start, length) == 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline bool ffStrbufStartsWithS(const FFstrbuf* strbuf, const char* start) {
|
||||
return ffStrbufStartsWithSN(strbuf, start, (uint32_t) strlen(start));
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline bool ffStrbufStartsWith(const FFstrbuf* strbuf, const FFstrbuf* start) {
|
||||
return ffStrbufStartsWithSN(strbuf, start->chars, start->length);
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline bool ffStrbufStartsWithIgnCaseNS(const FFstrbuf* strbuf, uint32_t length, const char* start) {
|
||||
if (length > strbuf->length) {
|
||||
return false;
|
||||
}
|
||||
return strncasecmp(strbuf->chars, start, length) == 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline bool ffStrbufStartsWithIgnCaseS(const FFstrbuf* strbuf, const char* start) {
|
||||
return ffStrbufStartsWithIgnCaseNS(strbuf, (uint32_t) strlen(start), start);
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline bool ffStrbufStartsWithIgnCase(const FFstrbuf* strbuf, const FFstrbuf* start) {
|
||||
return ffStrbufStartsWithIgnCaseNS(strbuf, start->length, start->chars);
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline bool ffStrbufEndsWithC(const FFstrbuf* strbuf, char c) {
|
||||
return strbuf->length == 0 ? false : strbuf->chars[strbuf->length - 1] == c;
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline bool ffStrbufEndsWithNS(const FFstrbuf* strbuf, uint32_t endLength, const char* end) {
|
||||
if (endLength > strbuf->length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return memcmp(strbuf->chars + strbuf->length - endLength, end, endLength) == 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline bool ffStrbufEndsWithS(const FFstrbuf* strbuf, const char* end) {
|
||||
return ffStrbufEndsWithNS(strbuf, (uint32_t) strlen(end), end);
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline bool ffStrbufEndsWithFn(const FFstrbuf* strbuf, int (*const fn)(int)) {
|
||||
return strbuf->length == 0 ? false : fn(strbuf->chars[strbuf->length - 1]);
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline bool ffStrbufEndsWith(const FFstrbuf* strbuf, const FFstrbuf* end) {
|
||||
return ffStrbufEndsWithNS(strbuf, end->length, end->chars);
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline bool ffStrbufEndsWithIgnCaseNS(const FFstrbuf* strbuf, uint32_t endLength, const char* end) {
|
||||
if (endLength > strbuf->length) {
|
||||
return false;
|
||||
}
|
||||
return strcasecmp(strbuf->chars + strbuf->length - endLength, end) == 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline bool ffStrbufEndsWithIgnCaseS(const FFstrbuf* strbuf, const char* end) {
|
||||
return ffStrbufEndsWithIgnCaseNS(strbuf, (uint32_t) strlen(end), end);
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline bool ffStrbufEndsWithIgnCase(const FFstrbuf* strbuf, const FFstrbuf* end) {
|
||||
return ffStrbufEndsWithIgnCaseNS(strbuf, end->length, end->chars);
|
||||
}
|
||||
|
||||
static inline void ffStrbufTrim(FFstrbuf* strbuf, char c) {
|
||||
ffStrbufTrimRight(strbuf, c);
|
||||
ffStrbufTrimLeft(strbuf, c);
|
||||
}
|
||||
|
||||
static inline void ffStrbufTrimSpace(FFstrbuf* strbuf) {
|
||||
ffStrbufTrimRightSpace(strbuf);
|
||||
ffStrbufTrimLeftSpace(strbuf);
|
||||
}
|
||||
|
||||
static inline bool ffStrbufMatchSeparatedS(const FFstrbuf* strbuf, const char* comp, char separator) {
|
||||
return ffStrbufMatchSeparatedNS(strbuf, (uint32_t) strlen(comp), comp, separator);
|
||||
}
|
||||
|
||||
static inline bool ffStrbufMatchSeparated(const FFstrbuf* strbuf, const FFstrbuf* comp, char separator) {
|
||||
return ffStrbufMatchSeparatedNS(strbuf, comp->length, comp->chars, separator);
|
||||
}
|
||||
|
||||
static inline bool ffStrbufMatchSeparatedIgnCaseS(const FFstrbuf* strbuf, const char* comp, char separator) {
|
||||
return ffStrbufMatchSeparatedIgnCaseNS(strbuf, (uint32_t) strlen(comp), comp, separator);
|
||||
}
|
||||
|
||||
static inline bool ffStrbufMatchSeparatedIgnCase(const FFstrbuf* strbuf, const FFstrbuf* comp, char separator) {
|
||||
return ffStrbufMatchSeparatedIgnCaseNS(strbuf, comp->length, comp->chars, separator);
|
||||
}
|
||||
|
||||
static inline bool ffStrbufSeparatedContainS(const FFstrbuf* strbuf, const char* comp, char separator) {
|
||||
return ffStrbufSeparatedContainNS(strbuf, (uint32_t) strlen(comp), comp, separator);
|
||||
}
|
||||
|
||||
static inline bool ffStrbufSeparatedContain(const FFstrbuf* strbuf, const FFstrbuf* comp, char separator) {
|
||||
return ffStrbufSeparatedContainNS(strbuf, comp->length, comp->chars, separator);
|
||||
}
|
||||
|
||||
static inline bool ffStrbufSeparatedContainIgnCaseS(const FFstrbuf* strbuf, const char* comp, char separator) {
|
||||
return ffStrbufSeparatedContainIgnCaseNS(strbuf, (uint32_t) strlen(comp), comp, separator);
|
||||
}
|
||||
|
||||
static inline bool ffStrbufSeparatedContainIgnCase(const FFstrbuf* strbuf, const FFstrbuf* comp, char separator) {
|
||||
return ffStrbufSeparatedContainIgnCaseNS(strbuf, comp->length, comp->chars, separator);
|
||||
}
|
||||
|
||||
static inline void ffStrbufWriteTo(const FFstrbuf* strbuf, FILE* file) {
|
||||
fwrite(strbuf->chars, sizeof(*strbuf->chars), strbuf->length, file);
|
||||
}
|
||||
|
||||
static inline void ffStrbufPutTo(const FFstrbuf* strbuf, FILE* file) {
|
||||
ffStrbufWriteTo(strbuf, file);
|
||||
fputc('\n', file);
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline double ffStrbufToDouble(const FFstrbuf* strbuf, double defaultValue) {
|
||||
char* str_end;
|
||||
double result = strtod(strbuf->chars, &str_end);
|
||||
return str_end == strbuf->chars ? defaultValue : result;
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline uint64_t ffStrbufToUInt(const FFstrbuf* strbuf, uint64_t defaultValue) {
|
||||
char* str_end;
|
||||
unsigned long long result = strtoull(strbuf->chars, &str_end, 10);
|
||||
return str_end == strbuf->chars ? defaultValue : (uint64_t) result;
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline int64_t ffStrbufToSInt(const FFstrbuf* strbuf, int64_t defaultValue) {
|
||||
char* str_end;
|
||||
long long result = strtoll(strbuf->chars, &str_end, 10);
|
||||
return str_end == strbuf->chars ? defaultValue : (int64_t) result;
|
||||
}
|
||||
|
||||
// Returns true if the strbuf is modified
|
||||
bool ffStrbufDecodeHexEscapeSequences(FFstrbuf* strbuf);
|
||||
|
||||
#define FF_STRBUF_AUTO_DESTROY [[gnu::cleanup(ffStrbufDestroy)]] FFstrbuf
|
||||
#define FF_STRBUF_STATIC(str) { .allocated = 0, .length = (uint32_t) sizeof(str) - 1, .chars = str }
|
||||
@@ -0,0 +1,225 @@
|
||||
#include "cf_helpers.h"
|
||||
|
||||
const char* ffCfNumGetInt64(CFTypeRef cf, int64_t* result) {
|
||||
if (CFGetTypeID(cf) == CFNumberGetTypeID()) {
|
||||
if (!CFNumberGetValue((CFNumberRef) cf, kCFNumberSInt64Type, result)) {
|
||||
return "Number type is not SInt64";
|
||||
}
|
||||
return nullptr;
|
||||
} else if (CFGetTypeID(cf) == CFDataGetTypeID()) {
|
||||
if (CFDataGetLength((CFDataRef) cf) != sizeof(int64_t)) {
|
||||
return "Data length is not sizeof(int64_t)";
|
||||
}
|
||||
CFDataGetBytes((CFDataRef) cf, CFRangeMake(0, sizeof(int64_t)), (uint8_t*) result);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return "TypeID is neither 'CFNumber' nor 'CFData'";
|
||||
}
|
||||
|
||||
const char* ffCfNumGetInt(CFTypeRef cf, int32_t* result) {
|
||||
if (CFGetTypeID(cf) == CFNumberGetTypeID()) {
|
||||
if (!CFNumberGetValue((CFNumberRef) cf, kCFNumberSInt32Type, result)) {
|
||||
return "Number type is not SInt32";
|
||||
}
|
||||
return nullptr;
|
||||
} else if (CFGetTypeID(cf) == CFDataGetTypeID()) {
|
||||
if (CFDataGetLength((CFDataRef) cf) != sizeof(*result)) {
|
||||
return "Data length is not sizeof(int32_t)";
|
||||
}
|
||||
CFDataGetBytes((CFDataRef) cf, CFRangeMake(0, sizeof(*result)), (uint8_t*) result);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return "TypeID is neither 'CFNumber' nor 'CFData'";
|
||||
}
|
||||
|
||||
const char* ffCfNumGetDouble(CFTypeRef cf, double* result) {
|
||||
if (CFGetTypeID(cf) == CFNumberGetTypeID()) {
|
||||
if (!CFNumberGetValue((CFNumberRef) cf, kCFNumberDoubleType, result) &&
|
||||
!CFNumberGetValue((CFNumberRef) cf, kCFNumberFloatType, result)) {
|
||||
return "Number type is not Double or Float";
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return "TypeID is neither 'CFNumber'";
|
||||
}
|
||||
|
||||
const char* ffCfDateGetEpoch(CFTypeRef cf, uint64_t* result) {
|
||||
if (CFGetTypeID(cf) != CFDateGetTypeID()) {
|
||||
return "TypeID is not 'CFDate'";
|
||||
}
|
||||
|
||||
CFAbsoluteTime absTime = CFDateGetAbsoluteTime((CFDateRef) cf);
|
||||
// Convert from seconds to milliseconds and add the difference between 1970 and 2001 in milliseconds
|
||||
*result = (uint64_t) ((absTime + 978307200 /*kCFAbsoluteTimeIntervalSince1970*/) * 1000);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char* ffCfStrGetString(CFTypeRef cf, FFstrbuf* result) {
|
||||
ffStrbufClear(result);
|
||||
if (!cf) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (CFGetTypeID(cf) == CFStringGetTypeID()) {
|
||||
CFStringRef cfStr = (CFStringRef) cf;
|
||||
|
||||
const char* cstr = CFStringGetCStringPtr(cfStr, kCFStringEncodingUTF8);
|
||||
if (cstr) {
|
||||
ffStrbufSetS(result, cstr);
|
||||
} else {
|
||||
uint32_t length = (uint32_t) CFStringGetLength(cfStr);
|
||||
if (length == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
ffStrbufEnsureFixedLengthFree(result, (uint32_t) CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8));
|
||||
if (!CFStringGetCString(cfStr, result->chars, result->allocated, kCFStringEncodingUTF8)) {
|
||||
return "CFStringGetCString() failed";
|
||||
}
|
||||
// CFStringGetCString ensures the buffer is NUL terminated
|
||||
// https://developer.apple.com/documentation/corefoundation/1542721-cfstringgetcstring
|
||||
result->length = (uint32_t) strnlen(result->chars, (uint32_t) result->allocated);
|
||||
}
|
||||
} else if (CFGetTypeID(cf) == CFDataGetTypeID()) {
|
||||
CFDataRef cfData = (CFDataRef) cf;
|
||||
uint32_t length = (uint32_t) CFDataGetLength(cfData);
|
||||
if (length == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
ffStrbufEnsureFixedLengthFree(result, length + 1);
|
||||
CFDataGetBytes(cfData, CFRangeMake(0, length), (uint8_t*) result->chars);
|
||||
result->length = (uint32_t) strnlen(result->chars, length);
|
||||
result->chars[result->length] = '\0';
|
||||
} else {
|
||||
return "TypeID is neither 'CFString' nor 'CFData'";
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char* ffCfDataGetDataAsString(CFTypeRef cf, FFstrbuf* result) {
|
||||
ffStrbufClear(result);
|
||||
if (!cf) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (CFGetTypeID(cf) == CFDataGetTypeID()) {
|
||||
CFDataRef cfData = (CFDataRef) cf;
|
||||
uint32_t length = (uint32_t) CFDataGetLength(cfData);
|
||||
if (length == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
ffStrbufEnsureFixedLengthFree(result, length + 1);
|
||||
CFDataGetBytes(cfData, CFRangeMake(0, length), (uint8_t*) result->chars);
|
||||
result->length = length;
|
||||
result->chars[result->length] = '\0';
|
||||
} else {
|
||||
return "TypeID is not 'CFData'";
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char* ffCfDictGetString(CFDictionaryRef dict, CFStringRef key, FFstrbuf* result) {
|
||||
CFTypeRef cf = (CFTypeRef) CFDictionaryGetValue(dict, key);
|
||||
if (cf == nullptr) {
|
||||
return "CFDictionaryGetValue() failed";
|
||||
}
|
||||
|
||||
return ffCfStrGetString(cf, result);
|
||||
}
|
||||
|
||||
const char* ffCfDictGetDataAsString(CFDictionaryRef dict, CFStringRef key, FFstrbuf* result) {
|
||||
CFTypeRef cf = (CFTypeRef) CFDictionaryGetValue(dict, key);
|
||||
if (cf == nullptr) {
|
||||
return "CFDictionaryGetValue() failed";
|
||||
}
|
||||
|
||||
return ffCfDataGetDataAsString(cf, result);
|
||||
}
|
||||
|
||||
const char* ffCfDictGetBool(CFDictionaryRef dict, CFStringRef key, bool* result) {
|
||||
CFBooleanRef cf = (CFBooleanRef) CFDictionaryGetValue(dict, key);
|
||||
if (cf == nullptr) {
|
||||
return "CFDictionaryGetValue() failed";
|
||||
}
|
||||
|
||||
if (CFGetTypeID(cf) != CFBooleanGetTypeID()) {
|
||||
return "TypeID is not 'CFBoolean'";
|
||||
}
|
||||
|
||||
*result = CFBooleanGetValue(cf);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char* ffCfDictGetInt(CFDictionaryRef dict, CFStringRef key, int* result) {
|
||||
CFTypeRef cf = (CFTypeRef) CFDictionaryGetValue(dict, key);
|
||||
if (cf == nullptr) {
|
||||
return "CFDictionaryGetValue() failed";
|
||||
}
|
||||
|
||||
return ffCfNumGetInt(cf, result);
|
||||
}
|
||||
|
||||
const char* ffCfDictGetInt64(CFDictionaryRef dict, CFStringRef key, int64_t* result) {
|
||||
CFTypeRef cf = (CFTypeRef) CFDictionaryGetValue(dict, key);
|
||||
if (cf == nullptr) {
|
||||
return "CFDictionaryGetValue() failed";
|
||||
}
|
||||
|
||||
return ffCfNumGetInt64(cf, result);
|
||||
}
|
||||
|
||||
const char* ffCfDictGetDouble(CFDictionaryRef dict, CFStringRef key, double* result) {
|
||||
CFTypeRef cf = (CFTypeRef) CFDictionaryGetValue(dict, key);
|
||||
if (cf == nullptr) {
|
||||
return "CFDictionaryGetValue() failed";
|
||||
}
|
||||
|
||||
return ffCfNumGetDouble(cf, result);
|
||||
}
|
||||
|
||||
const char* ffCfDictGetData(CFDictionaryRef dict, CFStringRef key, uint32_t offset, uint32_t size, uint8_t* result, uint32_t* length) {
|
||||
CFTypeRef cf = (CFTypeRef) CFDictionaryGetValue(dict, key);
|
||||
if (cf == nullptr) {
|
||||
return "CFDictionaryGetValue() failed";
|
||||
}
|
||||
|
||||
if (CFGetTypeID(cf) != CFDataGetTypeID()) {
|
||||
return "TypeID is not 'CFData'";
|
||||
}
|
||||
|
||||
CFIndex trueLength = CFDataGetLength((CFDataRef) cf);
|
||||
|
||||
if (trueLength < offset + size) {
|
||||
return "Data length is less than offset + size";
|
||||
}
|
||||
|
||||
if (length) {
|
||||
*length = (uint32_t) trueLength;
|
||||
}
|
||||
|
||||
CFDataGetBytes((CFDataRef) cf, CFRangeMake(offset, size), result);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char* ffCfDictGetDict(CFDictionaryRef dict, CFStringRef key, CFDictionaryRef* result) {
|
||||
CFDictionaryRef cf = (CFDictionaryRef) CFDictionaryGetValue(dict, key);
|
||||
if (cf == nullptr || CFGetTypeID(cf) != CFDictionaryGetTypeID()) {
|
||||
return "TypeID is not 'CFDictionary'";
|
||||
}
|
||||
|
||||
*result = cf;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char* ffCfDictGetDateAsEpoch(CFDictionaryRef dict, CFStringRef key, uint64_t* result) {
|
||||
CFTypeRef cf = (CFTypeRef) CFDictionaryGetValue(dict, key);
|
||||
if (cf == nullptr) {
|
||||
return "CFDictionaryGetValue() failed";
|
||||
}
|
||||
|
||||
return ffCfDateGetEpoch(cf, result);
|
||||
}
|
||||
@@ -4,34 +4,40 @@
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <IOKit/IOKitLib.h>
|
||||
|
||||
//Return error info if failed, NULL otherwise
|
||||
// Return error info if failed, nullptr otherwise
|
||||
const char* ffCfStrGetString(CFTypeRef cf, FFstrbuf* result);
|
||||
const char* ffCfNumGetInt(CFTypeRef cf, int32_t* result);
|
||||
const char* ffCfNumGetInt64(CFTypeRef cf, int64_t* result);
|
||||
const char* ffCfNumGetDouble(CFTypeRef cf, double* result);
|
||||
const char* ffCfDateGetEpoch(CFTypeRef cf, uint64_t* result);
|
||||
const char* ffCfDataGetDataAsString(CFTypeRef cf, FFstrbuf* result);
|
||||
const char* ffCfDictGetString(CFDictionaryRef dict, CFStringRef key, FFstrbuf* result);
|
||||
const char* ffCfDictGetBool(CFDictionaryRef dict, CFStringRef key, bool* result);
|
||||
const char* ffCfDictGetInt(CFDictionaryRef dict, CFStringRef key, int* result);
|
||||
const char* ffCfDictGetInt64(CFDictionaryRef dict, CFStringRef key, int64_t* result);
|
||||
const char* ffCfDictGetDouble(CFDictionaryRef dict, CFStringRef key, double* result);
|
||||
const char* ffCfDictGetData(CFDictionaryRef dict, CFStringRef key, uint32_t offset, uint32_t size, uint8_t* result, uint32_t* length);
|
||||
const char* ffCfDictGetDataAsString(CFDictionaryRef dict, CFStringRef key, FFstrbuf* result);
|
||||
const char* ffCfDictGetDict(CFDictionaryRef dict, CFStringRef key, CFDictionaryRef* result);
|
||||
const char* ffCfDictGetDateAsEpoch(CFDictionaryRef dict, CFStringRef key, uint64_t* result);
|
||||
|
||||
static inline CFNumberRef ffCfCreateInt(int value)
|
||||
{
|
||||
static inline CFNumberRef ffCfCreateInt(int value) {
|
||||
return CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &value);
|
||||
}
|
||||
|
||||
static inline void cfReleaseWrapper(void* type)
|
||||
{
|
||||
if (*(CFTypeRef*) type)
|
||||
static inline void cfReleaseWrapper(void* type) {
|
||||
assert(type);
|
||||
if (*(CFTypeRef*) type) {
|
||||
CFRelease(*(CFTypeRef*) type);
|
||||
}
|
||||
}
|
||||
|
||||
#define FF_CFTYPE_AUTO_RELEASE __attribute__((__cleanup__(cfReleaseWrapper)))
|
||||
#define FF_CFTYPE_AUTO_RELEASE [[gnu::cleanup(cfReleaseWrapper)]]
|
||||
|
||||
static inline void wrapIoObjectRelease(io_object_t* service)
|
||||
{
|
||||
static inline void wrapIoObjectRelease(io_object_t* service) {
|
||||
assert(service);
|
||||
if (*service)
|
||||
if (*service) {
|
||||
IOObjectRelease(*service);
|
||||
}
|
||||
}
|
||||
#define FF_IOOBJECT_AUTO_RELEASE __attribute__((__cleanup__(wrapIoObjectRelease)))
|
||||
#define FF_IOOBJECT_AUTO_RELEASE [[gnu::cleanup(wrapIoObjectRelease)]]
|
||||
@@ -1,8 +1,6 @@
|
||||
#include "osascript.h"
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <AppKit/AppKit.h>
|
||||
#import <CoreData/CoreData.h>
|
||||
|
||||
bool ffOsascript(const char* input, FFstrbuf* result)
|
||||
{
|
||||
@@ -0,0 +1,500 @@
|
||||
#include "smc_temps.h"
|
||||
#include "common/apple/cf_helpers.h"
|
||||
#include "common/strutil.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <IOKit/IOKitLib.h>
|
||||
|
||||
static const char kSmcCmdReadBytes = 5;
|
||||
static const char kSmcCmdReadKeyInfo = 9;
|
||||
static const uint32_t kKernelIndexSmc = 2;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char major;
|
||||
char minor;
|
||||
char build;
|
||||
char reserved[1];
|
||||
uint16_t release;
|
||||
} SmcKeyData_vers_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t version;
|
||||
uint16_t length;
|
||||
uint32_t cpuPLimit;
|
||||
uint32_t gpuPLimit;
|
||||
uint32_t memPLimit;
|
||||
} SmcKeyData_pLimitData_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t dataSize;
|
||||
uint32_t dataType;
|
||||
char dataAttributes;
|
||||
} SmcKeyData_keyInfo_t;
|
||||
|
||||
typedef unsigned char SmcBytes_t[32];
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t key;
|
||||
SmcKeyData_vers_t vers;
|
||||
SmcKeyData_pLimitData_t pLimitData;
|
||||
SmcKeyData_keyInfo_t keyInfo;
|
||||
char result;
|
||||
char status;
|
||||
char data8;
|
||||
uint32_t data32;
|
||||
SmcBytes_t bytes;
|
||||
} SmcKeyData_t;
|
||||
|
||||
typedef char UInt32Char_t[5];
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt32Char_t key;
|
||||
uint32_t dataSize;
|
||||
UInt32Char_t dataType;
|
||||
SmcBytes_t bytes;
|
||||
} SmcVal_t;
|
||||
|
||||
static uint32_t smcStrtoul(const char* str, int size, int base) {
|
||||
uint32_t total = 0;
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (base == 16) {
|
||||
total += (uint32_t) (str[i] << (size - 1 - i) * 8);
|
||||
} else {
|
||||
total += (uint32_t) ((unsigned char) (str[i]) << (size - 1 - i) * 8);
|
||||
}
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
static void smcUltostr(char* str, uint32_t val) {
|
||||
str[0] = (char) (val >> 24);
|
||||
str[1] = (char) (val >> 16);
|
||||
str[2] = (char) (val >> 8);
|
||||
str[3] = (char) val;
|
||||
str[4] = '\0';
|
||||
}
|
||||
|
||||
static const char* smcCall(io_connect_t conn, uint32_t selector, SmcKeyData_t* inputStructure, SmcKeyData_t* outputStructure) {
|
||||
size_t size = sizeof(SmcKeyData_t);
|
||||
|
||||
if (IOConnectCallStructMethod(conn, selector, inputStructure, size, outputStructure, &size) != kIOReturnSuccess) {
|
||||
return "IOConnectCallStructMethod(conn) failed";
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Provides key info, using a cache to dramatically improve the energy impact of smcFanControl
|
||||
static const char* smcGetKeyInfo(io_connect_t conn, const uint32_t key, SmcKeyData_keyInfo_t* key_info) {
|
||||
SmcKeyData_t inputStructure = { 0 };
|
||||
SmcKeyData_t outputStructure = { 0 };
|
||||
|
||||
inputStructure.key = key;
|
||||
inputStructure.data8 = kSmcCmdReadKeyInfo;
|
||||
|
||||
const char* error = smcCall(conn, kKernelIndexSmc, &inputStructure, &outputStructure);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
|
||||
*key_info = outputStructure.keyInfo;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static const char* smcReadSmcVal(io_connect_t conn, const UInt32Char_t key, SmcVal_t* val) {
|
||||
SmcKeyData_t inputStructure = { 0 };
|
||||
SmcKeyData_t outputStructure = { 0 };
|
||||
|
||||
inputStructure.key = smcStrtoul(key, 4, 16);
|
||||
strcpy(val->key, key);
|
||||
|
||||
const char* error = smcGetKeyInfo(conn, inputStructure.key, &outputStructure.keyInfo);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
|
||||
val->dataSize = outputStructure.keyInfo.dataSize;
|
||||
smcUltostr(val->dataType, outputStructure.keyInfo.dataType);
|
||||
inputStructure.keyInfo.dataSize = val->dataSize;
|
||||
inputStructure.data8 = kSmcCmdReadBytes;
|
||||
|
||||
error = smcCall(conn, kKernelIndexSmc, &inputStructure, &outputStructure);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
|
||||
memcpy(val->bytes, outputStructure.bytes, sizeof(outputStructure.bytes));
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static const char* smcOpen(io_connect_t* conn) {
|
||||
FF_IOOBJECT_AUTO_RELEASE io_object_t device = IOServiceGetMatchingService(MACH_PORT_NULL, IOServiceMatching("AppleSMC"));
|
||||
if (!device) {
|
||||
return "No SMC device found";
|
||||
}
|
||||
|
||||
if (IOServiceOpen(device, mach_task_self(), 0, conn) != kIOReturnSuccess) {
|
||||
return "IOServiceOpen() failed";
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static const char* smcReadValue(io_connect_t conn, const UInt32Char_t key, double* value) {
|
||||
SmcVal_t val = { 0 };
|
||||
const char* error = smcReadSmcVal(conn, key, &val);
|
||||
if (error != nullptr) {
|
||||
return error;
|
||||
}
|
||||
if (val.dataSize == 0) {
|
||||
return "Empty SMC result";
|
||||
}
|
||||
|
||||
switch (val.dataType[0]) {
|
||||
case 'u': // unsigned integer types
|
||||
if (val.dataType[1] == 'i') {
|
||||
switch (val.dataSize) {
|
||||
case 1:
|
||||
*value = *(uint8_t*) (val.bytes);
|
||||
break;
|
||||
case 2:
|
||||
*value = ntohs(*(uint16_t*) (val.bytes));
|
||||
break;
|
||||
case 4:
|
||||
*value = ntohl(*(uint32_t*) (val.bytes));
|
||||
break;
|
||||
case 8:
|
||||
*value = (double) ntohll(*(uint64_t*) (val.bytes));
|
||||
break;
|
||||
default:
|
||||
return "Unsupported SMC unsigned integer data size";
|
||||
}
|
||||
} else {
|
||||
return "Unsupported SMC unsigned data type";
|
||||
}
|
||||
break;
|
||||
|
||||
case 'f': // floating point types
|
||||
if (ffStrEquals(val.dataType, "flt ") && val.dataSize == 4) {
|
||||
*value = *(float*) (val.bytes);
|
||||
} else if (val.dataType[1] == 'p' && val.dataSize == 2) // fixed point types
|
||||
{
|
||||
if (ffStrEquals(val.dataType, "fp1f")) {
|
||||
*value = ntohs(*(uint16_t*) (val.bytes)) / 32768.0;
|
||||
} else if (ffStrEquals(val.dataType, "fp4c")) {
|
||||
*value = ntohs(*(uint16_t*) (val.bytes)) / 4096.0;
|
||||
} else if (ffStrEquals(val.dataType, "fp5b")) {
|
||||
*value = ntohs(*(uint16_t*) (val.bytes)) / 2048.0;
|
||||
} else if (ffStrEquals(val.dataType, "fp6a")) {
|
||||
*value = ntohs(*(uint16_t*) (val.bytes)) / 1024.0;
|
||||
} else if (ffStrEquals(val.dataType, "fp79")) {
|
||||
*value = ntohs(*(uint16_t*) (val.bytes)) / 512.0;
|
||||
} else if (ffStrEquals(val.dataType, "fp88")) {
|
||||
*value = ntohs(*(uint16_t*) (val.bytes)) / 256.0;
|
||||
} else if (ffStrEquals(val.dataType, "fpa6")) {
|
||||
*value = ntohs(*(uint16_t*) (val.bytes)) / 64.0;
|
||||
} else if (ffStrEquals(val.dataType, "fpc4")) {
|
||||
*value = ntohs(*(uint16_t*) (val.bytes)) / 16.0;
|
||||
} else if (ffStrEquals(val.dataType, "fpe2")) {
|
||||
*value = ntohs(*(uint16_t*) (val.bytes)) / 4.0;
|
||||
} else {
|
||||
return "Unsupported SMC floating point data type";
|
||||
}
|
||||
} else {
|
||||
return "Unsupported SMC floating point data type";
|
||||
}
|
||||
break;
|
||||
|
||||
case 's': // signed integer types
|
||||
if (val.dataType[1] == 'i') {
|
||||
switch (val.dataSize) {
|
||||
case 1:
|
||||
*value = *(int8_t*) (val.bytes);
|
||||
break;
|
||||
case 2:
|
||||
*value = ntohs(*(int16_t*) (val.bytes));
|
||||
break;
|
||||
case 4:
|
||||
*value = ntohl(*(int32_t*) (val.bytes));
|
||||
break;
|
||||
case 8:
|
||||
*value = (double) ntohll(*(int64_t*) (val.bytes));
|
||||
break;
|
||||
default:
|
||||
return "Unsupported SMC signed integer data size";
|
||||
}
|
||||
} else if (val.dataType[1] == 'p' && val.dataSize == 2) // signed fixed point types
|
||||
{
|
||||
if (ffStrEquals(val.dataType, "sp1e")) {
|
||||
*value = (int16_t) ntohs(*(int16_t*) (val.bytes)) / 16384.0;
|
||||
} else if (ffStrEquals(val.dataType, "sp3c")) {
|
||||
*value = (int16_t) ntohs(*(int16_t*) (val.bytes)) / 4096.0;
|
||||
} else if (ffStrEquals(val.dataType, "sp4b")) {
|
||||
*value = (int16_t) ntohs(*(int16_t*) (val.bytes)) / 2048.0;
|
||||
} else if (ffStrEquals(val.dataType, "sp5a")) {
|
||||
*value = (int16_t) ntohs(*(int16_t*) (val.bytes)) / 1024.0;
|
||||
} else if (ffStrEquals(val.dataType, "sp69")) {
|
||||
*value = (int16_t) ntohs(*(int16_t*) (val.bytes)) / 512.0;
|
||||
} else if (ffStrEquals(val.dataType, "sp78")) {
|
||||
*value = (int16_t) ntohs(*(int16_t*) (val.bytes)) / 256.0;
|
||||
} else if (ffStrEquals(val.dataType, "sp87")) {
|
||||
*value = (int16_t) ntohs(*(int16_t*) (val.bytes)) / 128.0;
|
||||
} else if (ffStrEquals(val.dataType, "sp96")) {
|
||||
*value = (int16_t) ntohs(*(int16_t*) (val.bytes)) / 64.0;
|
||||
} else if (ffStrEquals(val.dataType, "spb4")) {
|
||||
*value = (int16_t) ntohs(*(int16_t*) (val.bytes)) / 16.0;
|
||||
} else if (ffStrEquals(val.dataType, "spf0")) {
|
||||
*value = (int16_t) ntohs(*(int16_t*) (val.bytes)) / 1.0;
|
||||
} else {
|
||||
return "Unsupported SMC signed integer data type";
|
||||
}
|
||||
} else {
|
||||
return "Unsupported SMC signed data type";
|
||||
}
|
||||
break;
|
||||
|
||||
case '{': // special types like pwm
|
||||
if (ffStrEquals(val.dataType, "{pwm") && val.dataSize == 2) {
|
||||
*value = (double) ntohs(*(uint16_t*) (val.bytes)) * 100 / 65536.0;
|
||||
} else {
|
||||
return "Unsupported SMC special data type";
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return "Unsupported SMC data type";
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static bool detectTemp(io_connect_t conn, const char* sensor, double* sum) {
|
||||
double temp = 0;
|
||||
const char* error = smcReadValue(conn, sensor, &temp);
|
||||
if (error) {
|
||||
return false;
|
||||
}
|
||||
// https://github.com/exelban/stats/blob/14e29c4d60229c363cca9c9d25c30c87b7870830/Modules/Sensors/readers.swift#L124
|
||||
if (temp < 10 || temp > 120) {
|
||||
return false;
|
||||
}
|
||||
*sum += temp;
|
||||
return true;
|
||||
}
|
||||
|
||||
static io_connect_t conn;
|
||||
|
||||
const char* ffDetectSmcSpecificTemp(const char* sensor, double* result) {
|
||||
if (!conn) {
|
||||
if (smcOpen(&conn) != nullptr) {
|
||||
conn = (io_connect_t) -1;
|
||||
}
|
||||
}
|
||||
if (conn == (io_connect_t) -1) {
|
||||
return "Could not open SMC connection";
|
||||
}
|
||||
|
||||
if (!detectTemp(conn, sensor, result)) {
|
||||
return "Could not read SMC temperature";
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char* ffDetectSmcTemps(enum FFTempType type, double* result) {
|
||||
if (!conn) {
|
||||
if (smcOpen(&conn) != nullptr) {
|
||||
conn = (io_connect_t) -1;
|
||||
}
|
||||
}
|
||||
if (conn == (io_connect_t) -1) {
|
||||
return "Could not open SMC connection";
|
||||
}
|
||||
|
||||
uint32_t count = 0;
|
||||
*result = 0;
|
||||
|
||||
// https://github.com/exelban/stats/blob/master/Modules/Sensors/values.swift
|
||||
switch (type) {
|
||||
case FF_TEMP_CPU_X64:
|
||||
count += detectTemp(conn, "TC0D", result); // CPU diode
|
||||
count += detectTemp(conn, "TC0E", result); // CPU diode virtual
|
||||
count += detectTemp(conn, "TC0F", result); // CPU diode filtered
|
||||
count += detectTemp(conn, "TC0P", result); // CPU proximity
|
||||
break;
|
||||
|
||||
case FF_TEMP_CPU_M1X:
|
||||
count += detectTemp(conn, "Tp09", result); // CPU efficient core 1
|
||||
count += detectTemp(conn, "Tp0T", result); // CPU efficient core 2
|
||||
|
||||
count += detectTemp(conn, "Tp01", result); // CPU performance core 1
|
||||
count += detectTemp(conn, "Tp05", result); // CPU performance core 2
|
||||
count += detectTemp(conn, "Tp0D", result); // CPU performance core 3
|
||||
count += detectTemp(conn, "Tp0H", result); // CPU performance core 4
|
||||
count += detectTemp(conn, "Tp0L", result); // CPU performance core 5
|
||||
count += detectTemp(conn, "Tp0P", result); // CPU performance core 6
|
||||
count += detectTemp(conn, "Tp0X", result); // CPU performance core 7
|
||||
count += detectTemp(conn, "Tp0b", result); // CPU performance core 8
|
||||
break;
|
||||
|
||||
case FF_TEMP_CPU_M2X:
|
||||
count += detectTemp(conn, "Tp1h", result); // CPU efficiency core 1
|
||||
count += detectTemp(conn, "Tp1t", result); // CPU efficiency core 2
|
||||
count += detectTemp(conn, "Tp1p", result); // CPU efficiency core 3
|
||||
count += detectTemp(conn, "Tp1l", result); // CPU efficiency core 4
|
||||
|
||||
count += detectTemp(conn, "Tp01", result); // CPU performance core 1
|
||||
count += detectTemp(conn, "Tp05", result); // CPU performance core 2
|
||||
count += detectTemp(conn, "Tp09", result); // CPU performance core 3
|
||||
count += detectTemp(conn, "Tp0D", result); // CPU performance core 4
|
||||
count += detectTemp(conn, "Tp0X", result); // CPU performance core 5
|
||||
count += detectTemp(conn, "Tp0b", result); // CPU performance core 6
|
||||
count += detectTemp(conn, "Tp0f", result); // CPU performance core 7
|
||||
count += detectTemp(conn, "Tp0j", result); // CPU performance core 8
|
||||
break;
|
||||
|
||||
case FF_TEMP_CPU_M3X:
|
||||
count += detectTemp(conn, "Te05", result); // CPU efficiency core 1
|
||||
count += detectTemp(conn, "Te0L", result); // CPU efficiency core 2
|
||||
count += detectTemp(conn, "Te0P", result); // CPU efficiency core 3
|
||||
count += detectTemp(conn, "Te0S", result); // CPU efficiency core 4
|
||||
count += detectTemp(conn, "Tf04", result); // CPU performance core 1
|
||||
count += detectTemp(conn, "Tf09", result); // CPU performance core 2
|
||||
count += detectTemp(conn, "Tf0A", result); // CPU performance core 3
|
||||
count += detectTemp(conn, "Tf0B", result); // CPU performance core 4
|
||||
count += detectTemp(conn, "Tf0D", result); // CPU performance core 5
|
||||
count += detectTemp(conn, "Tf0E", result); // CPU performance core 6
|
||||
count += detectTemp(conn, "Tf44", result); // CPU performance core 7
|
||||
count += detectTemp(conn, "Tf49", result); // CPU performance core 8
|
||||
count += detectTemp(conn, "Tf4A", result); // CPU performance core 9
|
||||
count += detectTemp(conn, "Tf4B", result); // CPU performance core 10
|
||||
count += detectTemp(conn, "Tf4D", result); // CPU performance core 11
|
||||
count += detectTemp(conn, "Tf4E", result); // CPU performance core 12
|
||||
break;
|
||||
|
||||
case FF_TEMP_CPU_M4X:
|
||||
count += detectTemp(conn, "Te05", result); // CPU efficiency core 1
|
||||
count += detectTemp(conn, "Te0S", result); // CPU efficiency core 2
|
||||
count += detectTemp(conn, "Te09", result); // CPU efficiency core 3
|
||||
count += detectTemp(conn, "Te0H", result); // CPU efficiency core 4
|
||||
count += detectTemp(conn, "Tp01", result); // CPU performance core 1
|
||||
count += detectTemp(conn, "Tp05", result); // CPU performance core 2
|
||||
count += detectTemp(conn, "Tp09", result); // CPU performance core 3
|
||||
count += detectTemp(conn, "Tp0D", result); // CPU performance core 4
|
||||
count += detectTemp(conn, "Tp0V", result); // CPU performance core 5
|
||||
count += detectTemp(conn, "Tp0Y", result); // CPU performance core 6
|
||||
count += detectTemp(conn, "Tp0b", result); // CPU performance core 7
|
||||
count += detectTemp(conn, "Tp0e", result); // CPU performance core 8
|
||||
break;
|
||||
|
||||
case FF_TEMP_CPU_M5X:
|
||||
count += detectTemp(conn, "Tp00", result); // CPU super core 1
|
||||
count += detectTemp(conn, "Tp04", result); // CPU super core 2
|
||||
count += detectTemp(conn, "Tp08", result); // CPU super core 3
|
||||
count += detectTemp(conn, "Tp0C", result); // CPU super core 4
|
||||
count += detectTemp(conn, "Tp0G", result); // CPU super core 5
|
||||
count += detectTemp(conn, "Tp0K", result); // CPU super core 6
|
||||
count += detectTemp(conn, "Tp0O", result); // CPU performance core 1
|
||||
count += detectTemp(conn, "Tp0R", result); // CPU performance core 2
|
||||
count += detectTemp(conn, "Tp0U", result); // CPU performance core 3
|
||||
count += detectTemp(conn, "Tp0X", result); // CPU performance core 4
|
||||
count += detectTemp(conn, "Tp0a", result); // CPU performance core 5
|
||||
count += detectTemp(conn, "Tp0d", result); // CPU performance core 6
|
||||
count += detectTemp(conn, "Tp0g", result); // CPU performance core 7
|
||||
count += detectTemp(conn, "Tp0j", result); // CPU performance core 8
|
||||
count += detectTemp(conn, "Tp0m", result); // CPU performance core 9
|
||||
count += detectTemp(conn, "Tp0p", result); // CPU performance core 10
|
||||
count += detectTemp(conn, "Tp0u", result); // CPU performance core 11
|
||||
count += detectTemp(conn, "Tp0y", result); // CPU performance core 12
|
||||
break;
|
||||
|
||||
case FF_TEMP_GPU_INTEL:
|
||||
count += detectTemp(conn, "TCGC", result); // GPU Intel Graphics
|
||||
goto gpu_unknown;
|
||||
|
||||
case FF_TEMP_GPU_AMD:
|
||||
count += detectTemp(conn, "TGDD", result); // GPU AMD Radeon
|
||||
goto gpu_unknown;
|
||||
|
||||
case FF_TEMP_GPU_UNKNOWN: // Nvidia?
|
||||
gpu_unknown:
|
||||
count += detectTemp(conn, "TG0D", result); // GPU diode
|
||||
count += detectTemp(conn, "TG0P", result); // GPU proximity
|
||||
break;
|
||||
|
||||
case FF_TEMP_GPU_M1X:
|
||||
count += detectTemp(conn, "Tg05", result); // GPU 1
|
||||
count += detectTemp(conn, "Tg0D", result); // GPU 2
|
||||
count += detectTemp(conn, "Tg0L", result); // GPU 3
|
||||
count += detectTemp(conn, "Tg0T", result); // GPU 4
|
||||
break;
|
||||
|
||||
case FF_TEMP_GPU_M2X:
|
||||
count += detectTemp(conn, "Tg0f", result); // GPU 1
|
||||
count += detectTemp(conn, "Tg0j", result); // GPU 2
|
||||
break;
|
||||
|
||||
case FF_TEMP_GPU_M3X:
|
||||
count += detectTemp(conn, "Tf14", result); // GPU 1
|
||||
count += detectTemp(conn, "Tf18", result); // GPU 2
|
||||
count += detectTemp(conn, "Tf19", result); // GPU 3
|
||||
count += detectTemp(conn, "Tf1A", result); // GPU 4
|
||||
count += detectTemp(conn, "Tf24", result); // GPU 5
|
||||
count += detectTemp(conn, "Tf28", result); // GPU 6
|
||||
count += detectTemp(conn, "Tf29", result); // GPU 7
|
||||
count += detectTemp(conn, "Tf2A", result); // GPU 8
|
||||
break;
|
||||
|
||||
case FF_TEMP_GPU_M4X:
|
||||
count += detectTemp(conn, "Tg0G", result); // GPU 1 (Basic)
|
||||
count += detectTemp(conn, "Tg0H", result); // GPU 2 (Basic)
|
||||
count += detectTemp(conn, "Tg1U", result); // GPU 1 (Pro / Max)
|
||||
count += detectTemp(conn, "Tg1k", result); // GPU 2 (Pro / Max)
|
||||
count += detectTemp(conn, "Tg0K", result); // GPU 3
|
||||
count += detectTemp(conn, "Tg0L", result); // GPU 4
|
||||
count += detectTemp(conn, "Tg0d", result); // GPU 5
|
||||
count += detectTemp(conn, "Tg0e", result); // GPU 6
|
||||
count += detectTemp(conn, "Tg0j", result); // GPU 7
|
||||
count += detectTemp(conn, "Tg0k", result); // GPU 8
|
||||
break;
|
||||
|
||||
case FF_TEMP_GPU_M5X:
|
||||
count += detectTemp(conn, "Tg0U", result); // GPU 1
|
||||
count += detectTemp(conn, "Tg0X", result); // GPU 2
|
||||
count += detectTemp(conn, "Tg0d", result); // GPU 3
|
||||
count += detectTemp(conn, "Tg0g", result); // GPU 4
|
||||
count += detectTemp(conn, "Tg0j", result); // GPU 5
|
||||
count += detectTemp(conn, "Tg1Y", result); // GPU 6
|
||||
count += detectTemp(conn, "Tg1c", result); // GPU 7
|
||||
count += detectTemp(conn, "Tg1g", result); // GPU 8
|
||||
break;
|
||||
|
||||
case FF_TEMP_BATTERY:
|
||||
count += detectTemp(conn, "TB1T", result); // Battery
|
||||
count += detectTemp(conn, "TB2T", result); // Battery
|
||||
break;
|
||||
|
||||
case FF_TEMP_MEMORY:
|
||||
count += detectTemp(conn, "Tm02", result); // Memory 1
|
||||
count += detectTemp(conn, "Tm06", result); // Memory 2
|
||||
count += detectTemp(conn, "Tm08", result); // Memory 3
|
||||
count += detectTemp(conn, "Tm09", result); // Memory 4
|
||||
count += detectTemp(conn, "Tm0p", result); // Memory Proximity 1 (M4)
|
||||
count += detectTemp(conn, "Tm1p", result); // Memory Proximity 2 (M4)
|
||||
count += detectTemp(conn, "Tm2p", result); // Memory Proximity 3 (M4)
|
||||
break;
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
return "No temperatures detected";
|
||||
}
|
||||
|
||||
*result /= count;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
@@ -2,20 +2,19 @@
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
typedef struct FFTempValue
|
||||
{
|
||||
typedef struct FFTempValue {
|
||||
FFstrbuf name;
|
||||
FFstrbuf deviceClass;
|
||||
double value;
|
||||
} FFTempValue;
|
||||
|
||||
enum FFTempType
|
||||
{
|
||||
enum FFTempType: uint8_t {
|
||||
FF_TEMP_CPU_X64,
|
||||
FF_TEMP_CPU_M1X,
|
||||
FF_TEMP_CPU_M2X,
|
||||
FF_TEMP_CPU_M3X,
|
||||
FF_TEMP_CPU_M4X,
|
||||
FF_TEMP_CPU_M5X,
|
||||
|
||||
FF_TEMP_GPU_INTEL,
|
||||
FF_TEMP_GPU_AMD,
|
||||
@@ -24,10 +23,12 @@ enum FFTempType
|
||||
FF_TEMP_GPU_M2X,
|
||||
FF_TEMP_GPU_M3X,
|
||||
FF_TEMP_GPU_M4X,
|
||||
FF_TEMP_GPU_M5X,
|
||||
|
||||
FF_TEMP_BATTERY,
|
||||
|
||||
FF_TEMP_MEMORY,
|
||||
};
|
||||
|
||||
const char* ffDetectSmcSpecificTemp(const char* sensor, double* result);
|
||||
const char* ffDetectSmcTemps(enum FFTempType type, double* result);
|
||||
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
bool ffGetAppNameAndVersion(const char* exePath, FFstrbuf* retName, FFstrbuf* retVersion);
|
||||
@@ -0,0 +1,43 @@
|
||||
#include "common/apple/version.h"
|
||||
#include "common/strutil.h"
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#define APP_CONTENTS_MACOS ".app/Contents/MacOS"
|
||||
|
||||
bool ffGetAppNameAndVersion(const char* exePath, FFstrbuf* retName, FFstrbuf* retVersion) {
|
||||
char* lastSlash = strrchr(exePath, '/');
|
||||
if (!lastSlash) {
|
||||
return false;
|
||||
}
|
||||
if ((size_t) (lastSlash - exePath) > strlen("X" APP_CONTENTS_MACOS) && memcmp(lastSlash - strlen(APP_CONTENTS_MACOS), APP_CONTENTS_MACOS, strlen(APP_CONTENTS_MACOS)) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
lastSlash -= strlen("MacOS");
|
||||
char infoPlistPath[PATH_MAX];
|
||||
memcpy(infoPlistPath, exePath, (size_t) (lastSlash - exePath));
|
||||
memcpy(infoPlistPath + (lastSlash - exePath), "Info.plist", sizeof("Info.plist")); // X.app/Contents/Info.plist
|
||||
NSError* error;
|
||||
NSDictionary* dict = [NSDictionary dictionaryWithContentsOfURL:[NSURL fileURLWithPath:@(infoPlistPath)]
|
||||
error:&error];
|
||||
if (!dict) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (retName) {
|
||||
NSString* bundleName = dict[@"CFBundleDisplayName"] ?: dict[@"CFBundleName"];
|
||||
if (bundleName) {
|
||||
ffStrbufSetS(retName, bundleName.UTF8String);
|
||||
}
|
||||
}
|
||||
|
||||
if (retVersion) {
|
||||
NSString* bundleVersion = dict[@"CFBundleShortVersionString"];
|
||||
if (bundleVersion) {
|
||||
ffStrbufSetS(retVersion, bundleVersion.UTF8String);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#include "common/FFstrbuf.h"
|
||||
|
||||
// For ffRegReadValue(s)
|
||||
// If length is 0, data will be allocated with malloc() and must be freed by the caller
|
||||
// Otherwise, data must point to a buffer of at least length bytes, and the actual length of the data will be written to length.
|
||||
typedef struct FFArgBuffer {
|
||||
void* data;
|
||||
uint32_t length;
|
||||
} FFArgBuffer;
|
||||
|
||||
typedef enum FFArgType: uint8_t {
|
||||
FF_ARG_TYPE_NULL = 0,
|
||||
FF_ARG_TYPE_UINT,
|
||||
FF_ARG_TYPE_UINT64,
|
||||
FF_ARG_TYPE_UINT16,
|
||||
FF_ARG_TYPE_UINT8,
|
||||
FF_ARG_TYPE_INT,
|
||||
FF_ARG_TYPE_STRING,
|
||||
FF_ARG_TYPE_STRBUF,
|
||||
FF_ARG_TYPE_FLOAT,
|
||||
FF_ARG_TYPE_DOUBLE,
|
||||
FF_ARG_TYPE_LIST,
|
||||
FF_ARG_TYPE_BOOL,
|
||||
FF_ARG_TYPE_BUFFER,
|
||||
} FFArgType;
|
||||
|
||||
#define FF_ARG(variable, var_name) { _Generic((variable), \
|
||||
uint32_t: FF_ARG_TYPE_UINT, \
|
||||
uint64_t: FF_ARG_TYPE_UINT64, \
|
||||
uint16_t: FF_ARG_TYPE_UINT16, \
|
||||
uint8_t: FF_ARG_TYPE_UINT8, \
|
||||
int32_t: FF_ARG_TYPE_INT, \
|
||||
char*: FF_ARG_TYPE_STRING, \
|
||||
const char*: FF_ARG_TYPE_STRING, \
|
||||
FFstrbuf: FF_ARG_TYPE_STRBUF, \
|
||||
float: FF_ARG_TYPE_FLOAT, \
|
||||
double: FF_ARG_TYPE_DOUBLE, \
|
||||
FFlist: FF_ARG_TYPE_LIST, \
|
||||
bool: FF_ARG_TYPE_BOOL, \
|
||||
FFArgBuffer: FF_ARG_TYPE_BUFFER), \
|
||||
_Generic((variable), char*: (variable), const char*: (variable), default: &(variable)), \
|
||||
(var_name) }
|
||||
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef __has_builtin
|
||||
#if !__cplusplus && FF_SUPPORTS_COUNT_OF
|
||||
#define ARRAY_SIZE(x) _Countof(x)
|
||||
#elif __has_builtin(__is_array)
|
||||
#define ARRAY_SIZE(x) ({ static_assert(__is_array(typeof(x)), "Must be an array"); (uint32_t) (sizeof(x) / sizeof(*(x))); })
|
||||
#elif __has_builtin(__builtin_types_compatible_p)
|
||||
#define ARRAY_SIZE(x) ({ static_assert(!__builtin_types_compatible_p(typeof(x), typeof(&*(x))), "Must not be a pointer"); (uint32_t) (sizeof(x) / sizeof(*(x))); })
|
||||
#endif
|
||||
#endif
|
||||
#ifndef ARRAY_SIZE
|
||||
#define ARRAY_SIZE(x) ((uint32_t) (sizeof(x) / sizeof(*(x))))
|
||||
#endif
|
||||
@@ -2,9 +2,8 @@
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
void ffBase64EncodeRaw(uint32_t size, const char *str, uint32_t *out_size, char *output);
|
||||
static inline FFstrbuf ffBase64EncodeStrbuf(const FFstrbuf* in)
|
||||
{
|
||||
void ffBase64EncodeRaw(uint32_t size, const char* str, uint32_t* out_size, char* output);
|
||||
static inline FFstrbuf ffBase64EncodeStrbuf(const FFstrbuf* in) {
|
||||
FFstrbuf out = ffStrbufCreateA(10 + in->length * 4 / 3);
|
||||
ffBase64EncodeRaw(in->length, in->chars, &out.length, out.chars);
|
||||
assert(out.length < out.allocated);
|
||||
@@ -12,9 +11,8 @@ static inline FFstrbuf ffBase64EncodeStrbuf(const FFstrbuf* in)
|
||||
return out;
|
||||
}
|
||||
|
||||
bool ffBase64DecodeRaw(uint32_t size, const char *str, uint32_t *out_size, char *output);
|
||||
static inline FFstrbuf ffBase64DecodeStrbuf(const FFstrbuf* in)
|
||||
{
|
||||
bool ffBase64DecodeRaw(uint32_t size, const char* str, uint32_t* out_size, char* output);
|
||||
static inline FFstrbuf ffBase64DecodeStrbuf(const FFstrbuf* in) {
|
||||
FFstrbuf out = ffStrbufCreateA(10 + in->length * 3 / 4);
|
||||
ffBase64DecodeRaw(in->length, in->chars, &out.length, out.chars);
|
||||
assert(out.length < out.allocated);
|
||||
@@ -11,7 +11,7 @@
|
||||
* @param userdata User-provided data passed to the callback function
|
||||
* @param minLength Minimum length of strings to extract
|
||||
*
|
||||
* @return NULL on success, error message on failure.
|
||||
* @return nullptr on success, error message on failure.
|
||||
* @note This function won't return an error if no strings are found.
|
||||
* Always check if strings are correctly extracted after this function all.
|
||||
*/
|
||||
@@ -10,6 +10,16 @@
|
||||
#define FF_COLOR_MODE_HIDDEN "8;"
|
||||
#define FF_COLOR_MODE_STRIKETHROUGH "9;"
|
||||
|
||||
#define FF_COLOR_MODE_RESET_ "0"
|
||||
#define FF_COLOR_MODE_BOLD_ "1"
|
||||
#define FF_COLOR_MODE_DIM_ "2"
|
||||
#define FF_COLOR_MODE_ITALIC_ "3"
|
||||
#define FF_COLOR_MODE_UNDERLINE_ "4"
|
||||
#define FF_COLOR_MODE_BLINK_ "5"
|
||||
#define FF_COLOR_MODE_INVERSE_ "7"
|
||||
#define FF_COLOR_MODE_HIDDEN_ "8"
|
||||
#define FF_COLOR_MODE_STRIKETHROUGH_ "9"
|
||||
|
||||
#define FF_COLOR_FG_BLACK "30"
|
||||
#define FF_COLOR_FG_RED "31"
|
||||
#define FF_COLOR_FG_GREEN "32"
|
||||
|
||||
@@ -1,232 +0,0 @@
|
||||
#include "commandoption.h"
|
||||
#include "common/color.h"
|
||||
#include "common/printing.h"
|
||||
#include "common/time.h"
|
||||
#include "common/jsonconfig.h"
|
||||
#include "fastfetch_datatext.h"
|
||||
#include "modules/modules.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
bool ffParseModuleOptions(const char* key, const char* value)
|
||||
{
|
||||
if (!ffStrStartsWith(key, "--") || !ffCharIsEnglishAlphabet(key[2])) return false;
|
||||
if (value && !*value) value = NULL;
|
||||
for (FFModuleBaseInfo** modules = ffModuleInfos[toupper(key[2]) - 'A']; *modules; ++modules)
|
||||
{
|
||||
FFModuleBaseInfo* baseInfo = *modules;
|
||||
const char* subKey = ffOptionTestPrefix(key, baseInfo->name);
|
||||
if (subKey != NULL)
|
||||
{
|
||||
if (subKey[0] == '\0' || subKey[0] == '-') // Key is exactly the module name or has a leading '-'
|
||||
{
|
||||
fprintf(stderr, "Error: unknown module key %s\n", key);
|
||||
exit(477);
|
||||
}
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY moduleName = ffStrbufCreateS(baseInfo->name);
|
||||
ffStrbufLowerCase(&moduleName);
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY jsonKey = ffStrbufCreate();
|
||||
bool flag = false;
|
||||
for (const char* p = subKey; *p; ++p)
|
||||
{
|
||||
if (*p == '-')
|
||||
{
|
||||
if (flag)
|
||||
{
|
||||
fprintf(stderr, "Error: invalid double `-` in module key %s\n", key);
|
||||
exit(477);
|
||||
}
|
||||
flag = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!isalpha((unsigned char)*p) && !isdigit((unsigned char)*p))
|
||||
{
|
||||
fprintf(stderr, "Error: invalid character `%c` in module key %s\n", *p, key);
|
||||
exit(477);
|
||||
}
|
||||
|
||||
if (flag)
|
||||
{
|
||||
flag = false;
|
||||
ffStrbufAppendC(&jsonKey, (char) toupper((unsigned char) *p));
|
||||
}
|
||||
else
|
||||
ffStrbufAppendC(&jsonKey, *p);
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "Error: Unsupported module option: %s\n", key);
|
||||
fputs(" Support of module options has been removed. Please add the flag to the JSON config instead.\n", stderr);
|
||||
fprintf(stderr, " Example (demonstration only): `{ \"modules\": [ { \"type\": \"%s\", \"%s\": %s%s%s } ] }`\n", moduleName.chars, jsonKey.chars, value ? "\"" : "", value ? value : "true", value ? "\"" : "");
|
||||
fputs(" See <https://github.com/fastfetch-cli/fastfetch/wiki/Configuration> for more information.\n", stderr);
|
||||
exit(477);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ffPrepareCommandOption(FFdata* data)
|
||||
{
|
||||
if(ffStrbufSeparatedContainIgnCaseS(&data->structure, FF_CPUUSAGE_MODULE_NAME, ':'))
|
||||
ffPrepareCPUUsage();
|
||||
|
||||
if(ffStrbufSeparatedContainIgnCaseS(&data->structure, FF_DISKIO_MODULE_NAME, ':'))
|
||||
{
|
||||
__attribute__((__cleanup__(ffDestroyDiskIOOptions))) FFDiskIOOptions options;
|
||||
ffInitDiskIOOptions(&options);
|
||||
ffPrepareDiskIO(&options);
|
||||
}
|
||||
|
||||
if(ffStrbufSeparatedContainIgnCaseS(&data->structure, FF_NETIO_MODULE_NAME, ':'))
|
||||
{
|
||||
__attribute__((__cleanup__(ffDestroyNetIOOptions))) FFNetIOOptions options;
|
||||
ffInitNetIOOptions(&options);
|
||||
ffPrepareNetIO(&options);
|
||||
}
|
||||
|
||||
if(ffStrbufSeparatedContainIgnCaseS(&data->structure, FF_PUBLICIP_MODULE_NAME, ':'))
|
||||
{
|
||||
__attribute__((__cleanup__(ffDestroyPublicIpOptions))) FFPublicIPOptions options;
|
||||
ffInitPublicIpOptions(&options);
|
||||
ffPreparePublicIp(&options);
|
||||
}
|
||||
|
||||
if(ffStrbufSeparatedContainIgnCaseS(&data->structure, FF_WEATHER_MODULE_NAME, ':'))
|
||||
{
|
||||
__attribute__((__cleanup__(ffDestroyWeatherOptions))) FFWeatherOptions options;
|
||||
ffInitWeatherOptions(&options);
|
||||
ffPrepareWeather(&options);
|
||||
}
|
||||
}
|
||||
|
||||
static void genJsonConfig(FFModuleBaseInfo* baseInfo, void* options, yyjson_mut_doc* doc)
|
||||
{
|
||||
yyjson_mut_val* modules = yyjson_mut_obj_get(doc->root, "modules");
|
||||
if (!modules)
|
||||
modules = yyjson_mut_obj_add_arr(doc, doc->root, "modules");
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY type = ffStrbufCreateS(baseInfo->name);
|
||||
ffStrbufLowerCase(&type);
|
||||
|
||||
if (instance.state.fullConfig)
|
||||
{
|
||||
yyjson_mut_val* module = yyjson_mut_obj(doc);
|
||||
yyjson_mut_obj_add_strbuf(doc, module, "type", &type);
|
||||
|
||||
if (baseInfo->generateJsonConfig)
|
||||
baseInfo->generateJsonConfig(options, doc, module);
|
||||
|
||||
if (yyjson_mut_obj_size(module) > 1)
|
||||
yyjson_mut_arr_add_val(modules, module);
|
||||
else
|
||||
yyjson_mut_arr_add_strbuf(doc, modules, &type);
|
||||
}
|
||||
else
|
||||
{
|
||||
yyjson_mut_arr_add_strbuf(doc, modules, &type);
|
||||
}
|
||||
}
|
||||
|
||||
static void genJsonResult(FFModuleBaseInfo* baseInfo, void* options, yyjson_mut_doc* doc)
|
||||
{
|
||||
yyjson_mut_val* module = yyjson_mut_arr_add_obj(doc, doc->root);
|
||||
yyjson_mut_obj_add_str(doc, module, "type", baseInfo->name);
|
||||
if (baseInfo->generateJsonResult)
|
||||
baseInfo->generateJsonResult(options, doc, module);
|
||||
else
|
||||
yyjson_mut_obj_add_str(doc, module, "error", "Unsupported for JSON format");
|
||||
}
|
||||
|
||||
static void parseStructureCommand(
|
||||
const char* line,
|
||||
void (*fn)(FFModuleBaseInfo* baseInfo, void* options, yyjson_mut_doc* jsonDoc),
|
||||
yyjson_mut_doc* jsonDoc
|
||||
)
|
||||
{
|
||||
if(ffCharIsEnglishAlphabet(line[0]))
|
||||
{
|
||||
for (FFModuleBaseInfo** modules = ffModuleInfos[toupper(line[0]) - 'A']; *modules; ++modules)
|
||||
{
|
||||
FFModuleBaseInfo* baseInfo = *modules;
|
||||
if (ffStrEqualsIgnCase(line, baseInfo->name))
|
||||
{
|
||||
uint8_t optionBuf[FF_OPTION_MAX_SIZE];
|
||||
baseInfo->initOptions(optionBuf);
|
||||
if (__builtin_expect(jsonDoc != NULL, false))
|
||||
fn(baseInfo, optionBuf, jsonDoc);
|
||||
else
|
||||
baseInfo->printModule(optionBuf);
|
||||
baseInfo->destroyOptions(optionBuf);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ffPrintError(line, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "<no implementation provided>");
|
||||
}
|
||||
|
||||
void ffPrintCommandOption(FFdata* data, yyjson_mut_doc* jsonDoc)
|
||||
{
|
||||
//Parse the structure and call the modules
|
||||
int32_t thres = instance.config.display.stat;
|
||||
uint32_t startIndex = 0;
|
||||
while (startIndex < data->structure.length)
|
||||
{
|
||||
uint32_t colonIndex = ffStrbufNextIndexC(&data->structure, startIndex, ':');
|
||||
data->structure.chars[colonIndex] = '\0';
|
||||
|
||||
double ms = 0;
|
||||
if(thres >= 0)
|
||||
ms = ffTimeGetTick();
|
||||
|
||||
parseStructureCommand(data->structure.chars + startIndex, genJsonResult, jsonDoc);
|
||||
|
||||
if(thres >= 0)
|
||||
{
|
||||
ms = ffTimeGetTick() - ms;
|
||||
|
||||
if (jsonDoc)
|
||||
{
|
||||
yyjson_mut_val* moduleJson = yyjson_mut_arr_get_last(jsonDoc->root);
|
||||
yyjson_mut_obj_add_real(jsonDoc, moduleJson, "stat", ms);
|
||||
}
|
||||
else
|
||||
{
|
||||
char str[64];
|
||||
int len = snprintf(str, sizeof str, "%.3fms", ms);
|
||||
if (thres > 0)
|
||||
snprintf(str, sizeof str, "\e[%sm%.3fms\e[m", (ms <= thres ? FF_COLOR_FG_GREEN : ms <= 2 * thres ? FF_COLOR_FG_YELLOW : FF_COLOR_FG_RED), ms);
|
||||
printf("\e7\e[1A\e[9999999C\e[%dD%s\e8", len, str); // Save; Up 1; Right 9999999; Left <len>; Print <str>; Load
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
if (!jsonDoc && !instance.config.display.noBuffer) fflush(stdout);
|
||||
#endif
|
||||
|
||||
startIndex = colonIndex + 1;
|
||||
}
|
||||
}
|
||||
|
||||
void ffMigrateCommandOptionToJsonc(FFdata* data, yyjson_mut_doc* jsonDoc)
|
||||
{
|
||||
//If we don't have a custom structure, use the default one
|
||||
if(data->structure.length == 0)
|
||||
ffStrbufAppendS(&data->structure, FASTFETCH_DATATEXT_STRUCTURE); // Cannot use `ffStrbufSetStatic` here because we will modify the string
|
||||
|
||||
//Parse the structure and call the modules
|
||||
uint32_t startIndex = 0;
|
||||
while (startIndex < data->structure.length)
|
||||
{
|
||||
uint32_t colonIndex = ffStrbufNextIndexC(&data->structure, startIndex, ':');
|
||||
data->structure.chars[colonIndex] = '\0';
|
||||
|
||||
parseStructureCommand(data->structure.chars + startIndex, genJsonConfig, jsonDoc);
|
||||
|
||||
startIndex = colonIndex + 1;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
// Things only needed by fastfetch
|
||||
typedef struct FFdata
|
||||
{
|
||||
FFstrbuf structure;
|
||||
bool configLoaded;
|
||||
} FFdata;
|
||||
#include "common/ffdata.h"
|
||||
|
||||
void ffPrepareCommandOption(FFdata* data);
|
||||
void ffPrintCommandOption(FFdata* data, yyjson_mut_doc* jsonDoc);
|
||||
void ffMigrateCommandOptionToJsonc(FFdata* data, yyjson_mut_doc* jsonDoc);
|
||||
void ffPrintCommandOption(FFdata* data);
|
||||
void ffMigrateCommandOptionToJsonc(FFdata* data);
|
||||
bool ffParseModuleOptions(const char* key, const char* value);
|
||||
|
||||
+15
-14
@@ -1,13 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef FF_HAVE_DBUS
|
||||
#include <dbus/dbus.h>
|
||||
#include <dbus/dbus.h>
|
||||
|
||||
#include "util/FFstrbuf.h"
|
||||
#include "common/library.h"
|
||||
#include "common/FFstrbuf.h"
|
||||
#include "common/library.h"
|
||||
|
||||
typedef struct FFDBusLibrary
|
||||
{
|
||||
typedef struct FFDBusLibrary {
|
||||
FF_LIBRARY_SYMBOL(dbus_bus_get)
|
||||
FF_LIBRARY_SYMBOL(dbus_message_new_method_call)
|
||||
FF_LIBRARY_SYMBOL(dbus_message_append_args)
|
||||
@@ -19,27 +18,29 @@ typedef struct FFDBusLibrary
|
||||
FF_LIBRARY_SYMBOL(dbus_message_iter_next)
|
||||
FF_LIBRARY_SYMBOL(dbus_message_unref)
|
||||
FF_LIBRARY_SYMBOL(dbus_connection_send_with_reply_and_block)
|
||||
FF_LIBRARY_SYMBOL(dbus_connection_unref)
|
||||
} FFDBusLibrary;
|
||||
|
||||
typedef struct FFDBusData
|
||||
{
|
||||
typedef struct FFDBusData {
|
||||
const FFDBusLibrary* lib;
|
||||
DBusConnection* connection;
|
||||
} FFDBusData;
|
||||
|
||||
const char* ffDBusLoadData(DBusBusType busType, FFDBusData* data); //Returns an error message or NULL on success
|
||||
const char* ffDBusLoadData(DBusBusType busType, FFDBusData* data); // Returns an error message or nullptr on success
|
||||
bool ffDBusGetString(FFDBusData* dbus, DBusMessageIter* iter, FFstrbuf* result);
|
||||
bool ffDBusGetBool(FFDBusData* dbus, DBusMessageIter* iter, bool* result);
|
||||
bool ffDBusGetUint(FFDBusData* dbus, DBusMessageIter* iter, uint32_t* result);
|
||||
bool ffDBusGetUint(FFDBusData* dbus, DBusMessageIter* iter, uint64_t* result);
|
||||
DBusMessage* ffDBusGetMethodReply(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* method, const char* arg1, const char* arg2);
|
||||
DBusMessage* ffDBusGetProperty(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property);
|
||||
bool ffDBusGetPropertyString(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property, FFstrbuf* result);
|
||||
bool ffDBusGetInt(FFDBusData* dbus, DBusMessageIter* iter, int32_t* result);
|
||||
bool ffDBusGetPropertyUint(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property, uint32_t* result);
|
||||
bool ffDBusGetInt(FFDBusData* dbus, DBusMessageIter* iter, int64_t* result);
|
||||
bool ffDBusGetPropertyUint(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property, uint64_t* result);
|
||||
void ffDBusDestroyData(FFDBusData* data);
|
||||
|
||||
static inline DBusMessage* ffDBusGetAllProperties(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface)
|
||||
{
|
||||
return ffDBusGetMethodReply(dbus, busName, objectPath, "org.freedesktop.DBus.Properties", "GetAll", interface, NULL);
|
||||
static inline DBusMessage* ffDBusGetAllProperties(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface) {
|
||||
return ffDBusGetMethodReply(dbus, busName, objectPath, "org.freedesktop.DBus.Properties", "GetAll", interface, nullptr);
|
||||
}
|
||||
|
||||
#define FF_DBUS_AUTO_DESTROY_DATA [[gnu::cleanup(ffDBusDestroyData)]]
|
||||
|
||||
#endif // FF_HAVE_DBUS
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include "fastfetch.h"
|
||||
#include "common/time.h"
|
||||
|
||||
static inline const char* ffFindFileName(const char* file) {
|
||||
const char* lastSlash = __builtin_strrchr(file, '/');
|
||||
#ifdef _WIN32
|
||||
if (lastSlash == nullptr) {
|
||||
lastSlash = __builtin_strrchr(file, '\\');
|
||||
}
|
||||
#endif
|
||||
if (lastSlash != nullptr) {
|
||||
return lastSlash + 1;
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
#define FF_DEBUG_PRINT(file_, line_, format_, ...) \
|
||||
do { \
|
||||
if (instance.config.display.debugMode) \
|
||||
fprintf(stderr, "[%s%4d, %s] " format_ "\n", ffFindFileName(file_), line_, ffTimeToTimeStr(ffTimeGetNow()), ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#else
|
||||
#define FF_DEBUG_PRINT(file_, line_, format_, ...) \
|
||||
do { \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#define FF_DEBUG(format, ...) FF_DEBUG_PRINT(__FILE__, __LINE__, format, ##__VA_ARGS__)
|
||||
|
||||
#if _WIN32
|
||||
const char* ffDebugWin32Error(DWORD errorCode);
|
||||
const char* ffDebugNtStatus(NTSTATUS status);
|
||||
const char* ffDebugConfigRet(unsigned long /*CONFIGRET*/ ret);
|
||||
const char* ffDebugHResult(HRESULT hr);
|
||||
#endif
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
void ffDurationAppendNum(uint64_t totalSeconds, FFstrbuf* result);
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "util/FFstrbuf.h"
|
||||
#include "common/FFstrbuf.h"
|
||||
|
||||
void ffEdidGetVendorAndModel(const uint8_t edid[128], FFstrbuf* result);
|
||||
bool ffEdidGetName(const uint8_t edid[128], FFstrbuf* name);
|
||||
void ffEdidGetPreferredResolutionAndRefreshRate(const uint8_t edid[128], uint32_t* width, uint32_t* height, double* refreshRate);
|
||||
void ffEdidGetPhysicalResolution(const uint8_t edid[128], uint32_t* width, uint32_t* height);
|
||||
void ffEdidGetPhysicalSize(const uint8_t edid[128], uint32_t* width, uint32_t* height); // in mm
|
||||
void ffEdidGetSerialAndManufactureDate(const uint8_t edid[128], uint32_t* serial, uint16_t* year, uint16_t* week);
|
||||
void ffEdidGetManufactureDate(const uint8_t edid[128], uint16_t* year, uint16_t* week);
|
||||
bool ffEdidGetSerial(const uint8_t edid[128], FFstrbuf* result);
|
||||
bool ffEdidGetHdrCompatible(const uint8_t* edid, uint32_t length);
|
||||
bool ffEdidIsValid(const uint8_t edid[128], uint32_t length);
|
||||
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#if __BIG_ENDIAN__
|
||||
#define FF_READ_LE(x) _Generic((x), \
|
||||
uint16_t: __builtin_bswap16(x), \
|
||||
uint32_t: __builtin_bswap32(x), \
|
||||
uint64_t: __builtin_bswap64(x))
|
||||
#define FF_READ_BE(x) (x)
|
||||
#else
|
||||
#define FF_READ_LE(x) (x)
|
||||
#define FF_READ_BE(x) _Generic((x), \
|
||||
uint16_t: __builtin_bswap16(x), \
|
||||
uint32_t: __builtin_bswap32(x), \
|
||||
uint64_t: __builtin_bswap64(x))
|
||||
#endif
|
||||
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include "common/FFstrbuf.h"
|
||||
|
||||
typedef enum FFDataResultDocType: uint8_t {
|
||||
FF_RESULT_DOC_TYPE_DEFAULT = 0,
|
||||
FF_RESULT_DOC_TYPE_JSON,
|
||||
FF_RESULT_DOC_TYPE_CONFIG,
|
||||
FF_RESULT_DOC_TYPE_CONFIG_FULL,
|
||||
} FFDataResultDocType;
|
||||
|
||||
// FFdata aggregates configuration, generation parameters, and output state used by fastfetch.
|
||||
// It holds the parsed configuration document, a mutable JSON document for results, and related metadata.
|
||||
typedef struct FFdata {
|
||||
yyjson_doc* configDoc; // Parsed JSON configuration document
|
||||
yyjson_mut_doc* resultDoc; // Mutable JSON document for storing results
|
||||
FFstrbuf structure; // Custom output structure from command line
|
||||
FFstrbuf structureDisabled; // Disabled modules in the output structure from command line
|
||||
FFstrbuf genConfigPath; // Path to generate configuration file
|
||||
FFDataResultDocType docType; // Type of result document
|
||||
bool configLoaded;
|
||||
bool genConfigInteractive; // `--gen-config` entered the interactive CUI
|
||||
} FFdata;
|
||||
@@ -1,221 +0,0 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/font.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
void ffFontInit(FFfont* font)
|
||||
{
|
||||
// Ensure no memory allocates
|
||||
ffStrbufInit(&font->pretty);
|
||||
ffStrbufInit(&font->name);
|
||||
ffStrbufInit(&font->size);
|
||||
ffListInit(&font->styles, sizeof(FFstrbuf));
|
||||
}
|
||||
|
||||
static void strbufAppendNSExcludingC(FFstrbuf* strbuf, uint32_t length, const char* value, char exclude)
|
||||
{
|
||||
if(value == NULL || length == 0)
|
||||
return;
|
||||
|
||||
ffStrbufEnsureFree(strbuf, length);
|
||||
|
||||
for(uint32_t i = 0; i < length; i++)
|
||||
{
|
||||
if(value[i] != exclude)
|
||||
strbuf->chars[strbuf->length++] = value[i];
|
||||
}
|
||||
|
||||
strbuf->chars[strbuf->length] = '\0';
|
||||
}
|
||||
|
||||
static void fontInitPretty(FFfont* font)
|
||||
{
|
||||
ffStrbufAppend(&font->pretty, &font->name);
|
||||
|
||||
if(font->size.length == 0 && font->styles.length == 0)
|
||||
return;
|
||||
else if(font->pretty.length == 0)
|
||||
ffStrbufAppendS(&font->pretty, "default");
|
||||
|
||||
ffStrbufAppendS(&font->pretty, " (");
|
||||
|
||||
if(font->size.length > 0)
|
||||
{
|
||||
ffStrbufAppend(&font->pretty, &font->size);
|
||||
ffStrbufAppendS(&font->pretty, "pt");
|
||||
|
||||
if(font->styles.length > 0)
|
||||
ffStrbufAppendS(&font->pretty, ", ");
|
||||
}
|
||||
|
||||
for(uint32_t i = 0; i < font->styles.length; i++)
|
||||
{
|
||||
ffStrbufAppend(&font->pretty, FF_LIST_GET(FFstrbuf, font->styles, i));
|
||||
|
||||
if(i < font->styles.length - 1)
|
||||
ffStrbufAppendS(&font->pretty, ", ");
|
||||
}
|
||||
|
||||
ffStrbufAppendC(&font->pretty, ')');
|
||||
}
|
||||
|
||||
void ffFontInitQt(FFfont* font, const char* data)
|
||||
{
|
||||
ffFontInit(font);
|
||||
|
||||
//See https://doc.qt.io/qt-5/qfont.html#toString
|
||||
|
||||
//Family
|
||||
data = ffStrbufAppendSUntilC(&font->name, data, ',');
|
||||
ffStrbufTrim(&font->name, ' ');
|
||||
if (!data) goto exit;
|
||||
data++;
|
||||
|
||||
//Size
|
||||
data = ffStrbufAppendSUntilC(&font->size, data, ',');
|
||||
ffStrbufTrim(&font->size, ' ');
|
||||
if (!data) goto exit;
|
||||
data++;
|
||||
|
||||
//Style
|
||||
data = strrchr(data, ',');
|
||||
if (!data) goto exit;
|
||||
data++;
|
||||
if (isalpha(*data))
|
||||
{
|
||||
do
|
||||
{
|
||||
FFstrbuf* style = (FFstrbuf*) ffListAdd(&font->styles);
|
||||
ffStrbufInit(style);
|
||||
data = ffStrbufAppendSUntilC(style, data, ' ');
|
||||
if (data) data++;
|
||||
} while (data);
|
||||
}
|
||||
|
||||
exit:
|
||||
fontInitPretty(font);
|
||||
}
|
||||
|
||||
static void fontPangoParseWord(const char** data, FFfont* font, FFstrbuf* alternativeBuffer)
|
||||
{
|
||||
while(**data == ' ' || **data == '\t' || **data == ',')
|
||||
++(*data);
|
||||
|
||||
const char* wordStart = *data;
|
||||
|
||||
while(**data != ' ' && **data != '\t' && **data != ',' && **data != '\0' && **data != '`' && **data != '\\')
|
||||
++(*data);
|
||||
|
||||
uint32_t wordLength = (uint32_t) (*data - wordStart);
|
||||
if(wordLength == 0)
|
||||
return;
|
||||
|
||||
if(**data == '\0' || **data == '`' || **data == '\\')
|
||||
{
|
||||
ffStrbufAppendNS(&font->size, wordLength, wordStart);
|
||||
if(ffStrbufEndsWithS(&font->size, "px"))
|
||||
ffStrbufSubstrBefore(&font->size, font->size.length - 2);
|
||||
|
||||
double dummy;
|
||||
if(sscanf(font->size.chars, "%lf", &dummy) == 1)
|
||||
return;
|
||||
|
||||
ffStrbufClear(&font->size);
|
||||
}
|
||||
|
||||
if(
|
||||
strncasecmp(wordStart, "Ultra", 5) == 0 ||
|
||||
strncasecmp(wordStart, "Extra", 5) == 0 ||
|
||||
strncasecmp(wordStart, "Semi", 4) == 0 ||
|
||||
strncasecmp(wordStart, "Demi", 4) == 0 ||
|
||||
strncasecmp(wordStart, "Normal", wordLength) == 0 ||
|
||||
strncasecmp(wordStart, "Roman", wordLength) == 0 ||
|
||||
strncasecmp(wordStart, "Oblique", wordLength) == 0 ||
|
||||
strncasecmp(wordStart, "Italic", wordLength) == 0 ||
|
||||
strncasecmp(wordStart, "Thin", wordLength) == 0 ||
|
||||
strncasecmp(wordStart, "Light", wordLength) == 0 ||
|
||||
strncasecmp(wordStart, "Bold", wordLength) == 0 ||
|
||||
strncasecmp(wordStart, "Black", wordLength) == 0 ||
|
||||
strncasecmp(wordStart, "Condensed", wordLength) == 0 ||
|
||||
strncasecmp(wordStart, "Expanded", wordLength) == 0
|
||||
) {
|
||||
if(alternativeBuffer == NULL)
|
||||
{
|
||||
alternativeBuffer = (FFstrbuf*) ffListAdd(&font->styles);
|
||||
ffStrbufInit(alternativeBuffer);
|
||||
}
|
||||
|
||||
strbufAppendNSExcludingC(alternativeBuffer, wordLength, wordStart, '-');
|
||||
|
||||
if(
|
||||
strncasecmp(wordStart, "Ultra ", 6) == 0 ||
|
||||
strncasecmp(wordStart, "Extra ", 6) == 0 ||
|
||||
strncasecmp(wordStart, "Semi ", 5) == 0 ||
|
||||
strncasecmp(wordStart, "Demi ", 5) == 0
|
||||
) {
|
||||
fontPangoParseWord(data, font, alternativeBuffer);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if(alternativeBuffer != NULL)
|
||||
{
|
||||
strbufAppendNSExcludingC(alternativeBuffer, wordLength, wordStart, '-');
|
||||
return;
|
||||
}
|
||||
|
||||
if(font->name.length > 0)
|
||||
ffStrbufAppendC(&font->name, ' ');
|
||||
ffStrbufAppendNS(&font->name, wordLength, wordStart);
|
||||
}
|
||||
|
||||
void ffFontInitPango(FFfont* font, const char* data)
|
||||
{
|
||||
ffFontInit(font);
|
||||
|
||||
while(*data != '\0' && *data != '`' && *data != '\\')
|
||||
fontPangoParseWord(&data, font, NULL);
|
||||
|
||||
fontInitPretty(font);
|
||||
}
|
||||
|
||||
void ffFontInitValues(FFfont* font, const char* name, const char* size)
|
||||
{
|
||||
ffFontInit(font);
|
||||
|
||||
ffStrbufAppendS(&font->name, name);
|
||||
ffStrbufTrim(&font->name, '"');
|
||||
ffStrbufAppendS(&font->size, size);
|
||||
|
||||
fontInitPretty(font);
|
||||
}
|
||||
|
||||
void ffFontInitWithSpace(FFfont* font, const char* rawName)
|
||||
{
|
||||
const char* pspace = strrchr(rawName, ' ');
|
||||
if(pspace == NULL)
|
||||
{
|
||||
ffFontInitCopy(font, rawName);
|
||||
return;
|
||||
}
|
||||
|
||||
ffFontInit(font);
|
||||
|
||||
ffStrbufAppendNS(&font->name, (uint32_t)(pspace - rawName), rawName);
|
||||
ffStrbufAppendS(&font->size, pspace + 1);
|
||||
|
||||
fontInitPretty(font);
|
||||
}
|
||||
|
||||
void ffFontDestroy(FFfont* font)
|
||||
{
|
||||
ffStrbufDestroy(&font->pretty);
|
||||
ffStrbufDestroy(&font->name);
|
||||
ffStrbufDestroy(&font->size);
|
||||
|
||||
FF_LIST_FOR_EACH(FFstrbuf, str, font->styles)
|
||||
ffStrbufDestroy(str);
|
||||
ffListDestroy(&font->styles);
|
||||
}
|
||||
+8
-7
@@ -1,10 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "util/FFstrbuf.h"
|
||||
#include "util/FFlist.h"
|
||||
#include "common/FFstrbuf.h"
|
||||
#include "common/FFlist.h"
|
||||
|
||||
typedef struct FFfont
|
||||
{
|
||||
typedef struct FFfont {
|
||||
FFstrbuf pretty;
|
||||
FFstrbuf name;
|
||||
FFstrbuf size;
|
||||
@@ -15,10 +14,12 @@ void ffFontInit(FFfont* font);
|
||||
void ffFontInitQt(FFfont* font, const char* data);
|
||||
void ffFontInitPango(FFfont* font, const char* data);
|
||||
void ffFontInitValues(FFfont* font, const char* name, const char* size);
|
||||
void ffFontInitXlfd(FFfont* font, const char* xlfd);
|
||||
void ffFontInitXft(FFfont* font, const char* xft);
|
||||
void ffFontInitMoveValues(FFfont* font, FFstrbuf* name, FFstrbuf* size, FFstrbuf* style);
|
||||
void ffFontInitWithSpace(FFfont* font, const char* rawName);
|
||||
void ffFontDestroy(FFfont* font);
|
||||
|
||||
static inline void ffFontInitCopy(FFfont* font, const char* name)
|
||||
{
|
||||
ffFontInitValues(font, name, NULL);
|
||||
static inline void ffFontInitCopy(FFfont* font, const char* name) {
|
||||
ffFontInitValues(font, name, nullptr);
|
||||
}
|
||||
|
||||
@@ -1,413 +0,0 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/format.h"
|
||||
#include "common/parsing.h"
|
||||
#include "util/textModifier.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
void ffFormatAppendFormatArg(FFstrbuf* buffer, const FFformatarg* formatarg)
|
||||
{
|
||||
switch(formatarg->type)
|
||||
{
|
||||
case FF_FORMAT_ARG_TYPE_INT:
|
||||
ffStrbufAppendSInt(buffer, *(int32_t*)formatarg->value);
|
||||
break;
|
||||
case FF_FORMAT_ARG_TYPE_UINT:
|
||||
ffStrbufAppendUInt(buffer, *(uint32_t*)formatarg->value);
|
||||
break;
|
||||
case FF_FORMAT_ARG_TYPE_UINT64:
|
||||
ffStrbufAppendUInt(buffer, *(uint64_t*)formatarg->value);
|
||||
break;
|
||||
case FF_FORMAT_ARG_TYPE_UINT16:
|
||||
ffStrbufAppendUInt(buffer, *(uint16_t*)formatarg->value);
|
||||
break;
|
||||
case FF_FORMAT_ARG_TYPE_UINT8:
|
||||
ffStrbufAppendUInt(buffer, *(uint8_t*)formatarg->value);
|
||||
break;
|
||||
case FF_FORMAT_ARG_TYPE_STRING:
|
||||
ffStrbufAppendS(buffer, (const char*)formatarg->value);
|
||||
break;
|
||||
case FF_FORMAT_ARG_TYPE_STRBUF:
|
||||
ffStrbufAppend(buffer, (const FFstrbuf*)formatarg->value);
|
||||
break;
|
||||
case FF_FORMAT_ARG_TYPE_FLOAT:
|
||||
ffStrbufAppendDouble(buffer, *(float*)formatarg->value, instance.config.display.fractionNdigits, instance.config.display.fractionTrailingZeros != FF_FRACTION_TRAILING_ZEROS_TYPE_NEVER);
|
||||
break;
|
||||
case FF_FORMAT_ARG_TYPE_DOUBLE:
|
||||
ffStrbufAppendDouble(buffer, *(double*)formatarg->value, instance.config.display.fractionNdigits, instance.config.display.fractionTrailingZeros != FF_FRACTION_TRAILING_ZEROS_TYPE_NEVER);
|
||||
break;
|
||||
case FF_FORMAT_ARG_TYPE_BOOL:
|
||||
ffStrbufAppendS(buffer, *(bool*)formatarg->value ? "true" : "false");
|
||||
break;
|
||||
case FF_FORMAT_ARG_TYPE_LIST:
|
||||
{
|
||||
const FFlist* list = (const FFlist*) formatarg->value;
|
||||
for(uint32_t i = 0; i < list->length; i++)
|
||||
{
|
||||
ffStrbufAppend(buffer, FF_LIST_GET(FFstrbuf, *list, i));
|
||||
if(i < list->length - 1)
|
||||
ffStrbufAppendS(buffer, ", ");
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if(formatarg->type != FF_FORMAT_ARG_TYPE_NULL)
|
||||
fprintf(stderr, "Error: format string \"%s\": argument is not implemented: %i\n", buffer->chars, formatarg->type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief parses a string to a uint32_t
|
||||
*
|
||||
* If the string can't be parsed, or is < 1, uint32_t max is returned.
|
||||
*
|
||||
* @param placeholderValue the string to parse
|
||||
* @return uint32_t the parsed value
|
||||
*/
|
||||
static uint32_t getArgumentIndex(const char* placeholderValue, uint32_t numArgs, const FFformatarg* arguments)
|
||||
{
|
||||
char firstChar = placeholderValue[0];
|
||||
if (firstChar == '\0')
|
||||
return 0; // use arg counter
|
||||
|
||||
if (firstChar >= '0' && firstChar <= '9')
|
||||
{
|
||||
char* pEnd = NULL;
|
||||
uint32_t result = (uint32_t) strtoul(placeholderValue, &pEnd, 10);
|
||||
if (result > numArgs)
|
||||
return UINT32_MAX;
|
||||
if (*pEnd != '\0')
|
||||
return UINT32_MAX;
|
||||
return result;
|
||||
}
|
||||
else if (ffCharIsEnglishAlphabet(firstChar))
|
||||
{
|
||||
for (uint32_t i = 0; i < numArgs; ++i)
|
||||
{
|
||||
const FFformatarg* arg = &arguments[i];
|
||||
if (arg->name && strcasecmp(placeholderValue, arg->name) == 0)
|
||||
return i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return UINT32_MAX;
|
||||
}
|
||||
|
||||
static inline void appendInvalidPlaceholder(FFstrbuf* buffer, const char* start, const FFstrbuf* placeholderValue, uint32_t index, uint32_t formatStringLength)
|
||||
{
|
||||
ffStrbufAppendS(buffer, start);
|
||||
ffStrbufAppend(buffer, placeholderValue);
|
||||
|
||||
if(index < formatStringLength)
|
||||
ffStrbufAppendC(buffer, '}');
|
||||
}
|
||||
|
||||
static inline bool formatArgSet(const FFformatarg* arg)
|
||||
{
|
||||
return arg->value != NULL && (
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_DOUBLE && *(double*)arg->value > 0.0) ||
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_FLOAT && *(float*)arg->value > 0.0) ||
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_INT && *(int*)arg->value > 0) ||
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_STRBUF && ((FFstrbuf*)arg->value)->length > 0) ||
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_STRING && ffStrSet((char*)arg->value)) ||
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_UINT8 && *(uint8_t*)arg->value > 0) ||
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_UINT16 && *(uint16_t*)arg->value > 0) ||
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_UINT && *(uint32_t*)arg->value > 0) ||
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_BOOL && *(bool*)arg->value) ||
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_LIST && ((FFlist*)arg->value)->length > 0)
|
||||
);
|
||||
}
|
||||
|
||||
void ffParseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, uint32_t numArgs, const FFformatarg* arguments)
|
||||
{
|
||||
uint32_t argCounter = 0;
|
||||
|
||||
uint32_t numOpenIfs = 0;
|
||||
uint32_t numOpenNotIfs = 0;
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY placeholderValue = ffStrbufCreate();
|
||||
|
||||
for(uint32_t i = 0; i < formatstr->length; ++i)
|
||||
{
|
||||
// if we don't have a placeholder start just copy the chars over to output buffer
|
||||
if(formatstr->chars[i] != '{')
|
||||
{
|
||||
ffStrbufAppendC(buffer, formatstr->chars[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
// jump to next char, the start of the placeholder value
|
||||
++i;
|
||||
|
||||
// double {{ elvaluates to a single { and doesn't count as start
|
||||
if(formatstr->chars[i] == '{')
|
||||
{
|
||||
ffStrbufAppendC(buffer, '{');
|
||||
continue;
|
||||
}
|
||||
|
||||
ffStrbufClear(&placeholderValue);
|
||||
|
||||
{
|
||||
uint32_t iEnd = ffStrbufNextIndexC(formatstr, i, '}');
|
||||
ffStrbufAppendNS(&placeholderValue, iEnd - i, &formatstr->chars[i]);
|
||||
i = iEnd;
|
||||
}
|
||||
|
||||
char firstChar = placeholderValue.chars[0];
|
||||
|
||||
if (placeholderValue.length == 1)
|
||||
{
|
||||
// test if for stop, if so break the loop
|
||||
if (firstChar == '-')
|
||||
break;
|
||||
|
||||
// test for end of an if, if so do nothing
|
||||
if (firstChar == '?')
|
||||
{
|
||||
if(numOpenIfs == 0)
|
||||
appendInvalidPlaceholder(buffer, "{", &placeholderValue, i, formatstr->length);
|
||||
else
|
||||
--numOpenIfs;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// test for end of a not if, if so do nothing
|
||||
if (firstChar == '/')
|
||||
{
|
||||
if(numOpenNotIfs == 0)
|
||||
appendInvalidPlaceholder(buffer, "{", &placeholderValue, i, formatstr->length);
|
||||
else
|
||||
--numOpenNotIfs;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// test for end of a color, if so do nothing
|
||||
if (firstChar == '#')
|
||||
{
|
||||
if (!instance.config.display.pipe)
|
||||
ffStrbufAppendS(buffer, FASTFETCH_TEXT_MODIFIER_RESET);
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// test for if, if so evaluate it
|
||||
if (firstChar == '?')
|
||||
{
|
||||
ffStrbufSubstrAfter(&placeholderValue, 0);
|
||||
|
||||
uint32_t index = getArgumentIndex(placeholderValue.chars, numArgs, arguments);
|
||||
|
||||
// testing for an invalid index
|
||||
if (index > numArgs)
|
||||
{
|
||||
appendInvalidPlaceholder(buffer, "{?", &placeholderValue, i, formatstr->length);
|
||||
continue;
|
||||
}
|
||||
|
||||
// continue normally if an format arg is set and the value is > 0
|
||||
if (formatArgSet(&arguments[index - 1]))
|
||||
{
|
||||
++numOpenIfs;
|
||||
continue;
|
||||
}
|
||||
|
||||
// fastforward to the end of the if without printing the in between
|
||||
i = ffStrbufNextIndexS(formatstr, i, "{?}") + 2; // 2 is the length of "{?}" - 1 because the loop will increment it again directly after continue
|
||||
continue;
|
||||
}
|
||||
|
||||
// test for not if, if so evaluate it
|
||||
if (firstChar == '/')
|
||||
{
|
||||
ffStrbufSubstrAfter(&placeholderValue, 0);
|
||||
|
||||
uint32_t index = getArgumentIndex(placeholderValue.chars, numArgs, arguments);
|
||||
|
||||
// testing for an invalid index
|
||||
if (index > numArgs)
|
||||
{
|
||||
appendInvalidPlaceholder(buffer, "{/", &placeholderValue, i, formatstr->length);
|
||||
continue;
|
||||
}
|
||||
|
||||
//continue normally if an format arg is not set or the value is 0
|
||||
if (!formatArgSet(&arguments[index - 1]))
|
||||
{
|
||||
++numOpenNotIfs;
|
||||
continue;
|
||||
}
|
||||
|
||||
// fastforward to the end of the if without printing the in between
|
||||
i = ffStrbufNextIndexS(formatstr, i, "{/}") + 2; // 2 is the length of "{/}" - 1 because the loop will increment it again directly after continue
|
||||
continue;
|
||||
}
|
||||
|
||||
//test for color, if so evaluate it
|
||||
if (firstChar == '#')
|
||||
{
|
||||
if (!instance.config.display.pipe)
|
||||
{
|
||||
ffStrbufAppendS(buffer, "\e[");
|
||||
ffOptionParseColorNoClear(placeholderValue.chars + 1, buffer);
|
||||
ffStrbufAppendC(buffer, 'm');
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
//test for constant or env var, if so evaluate it
|
||||
if (firstChar == '$')
|
||||
{
|
||||
char* pend = NULL;
|
||||
int32_t indexSigned = (int32_t) strtol(placeholderValue.chars + 1, &pend, 10);
|
||||
if (pend == placeholderValue.chars + 1)
|
||||
{
|
||||
// treat placeholder as an environment variable
|
||||
char* envValue = getenv(placeholderValue.chars + 1);
|
||||
if (envValue)
|
||||
ffStrbufAppendS(buffer, envValue);
|
||||
else
|
||||
appendInvalidPlaceholder(buffer, "{", &placeholderValue, i, formatstr->length);
|
||||
}
|
||||
else
|
||||
{
|
||||
// treat placeholder as a constant
|
||||
uint32_t index = (uint32_t) (indexSigned < 0 ? (int32_t) instance.config.display.constants.length + indexSigned : indexSigned - 1);
|
||||
|
||||
if (*pend != '\0' || instance.config.display.constants.length <= index)
|
||||
appendInvalidPlaceholder(buffer, "{", &placeholderValue, i, formatstr->length);
|
||||
else
|
||||
{
|
||||
FFstrbuf* item = FF_LIST_GET(FFstrbuf, instance.config.display.constants, index);
|
||||
ffStrbufAppend(buffer, item);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
char* pSep = placeholderValue.chars;
|
||||
char cSep = '\0';
|
||||
while (*pSep && *pSep != ':' && *pSep != '<' && *pSep != '>' && *pSep != '~')
|
||||
++pSep;
|
||||
if (*pSep)
|
||||
{
|
||||
cSep = *pSep;
|
||||
*pSep = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
pSep = NULL;
|
||||
}
|
||||
|
||||
uint32_t index = getArgumentIndex(placeholderValue.chars, numArgs, arguments);
|
||||
|
||||
// test for invalid index
|
||||
if (index == 0)
|
||||
index = ++argCounter;
|
||||
|
||||
if (index > numArgs)
|
||||
{
|
||||
if (pSep) *pSep = cSep;
|
||||
appendInvalidPlaceholder(buffer, "{", &placeholderValue, i, formatstr->length);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!cSep)
|
||||
ffFormatAppendFormatArg(buffer, &arguments[index - 1]);
|
||||
else if (cSep == '~')
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY tempString = ffStrbufCreate();
|
||||
ffFormatAppendFormatArg(&tempString, &arguments[index - 1]);
|
||||
|
||||
char* pEnd = NULL;
|
||||
int32_t start = (int32_t) strtol(pSep + 1, &pEnd, 10);
|
||||
if (start < 0)
|
||||
start = (int32_t) tempString.length + start;
|
||||
if (start >= 0 && (uint32_t) start < tempString.length)
|
||||
{
|
||||
if (*pEnd == '\0')
|
||||
ffStrbufAppendNS(buffer, tempString.length - (uint32_t) start, &tempString.chars[start]);
|
||||
else if (*pEnd == ',')
|
||||
{
|
||||
int32_t end = (int32_t) strtol(pEnd + 1, &pEnd, 10);
|
||||
if (!*pEnd)
|
||||
{
|
||||
if (end < 0)
|
||||
end = (int32_t) tempString.length + end;
|
||||
if ((uint32_t) end > tempString.length)
|
||||
end = (int32_t) tempString.length;
|
||||
if (end > start)
|
||||
ffStrbufAppendNS(buffer, (uint32_t) (end - start), &tempString.chars[start]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (*pEnd)
|
||||
{
|
||||
*pSep = cSep;
|
||||
appendInvalidPlaceholder(buffer, "{", &placeholderValue, i, formatstr->length);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char* pEnd = NULL;
|
||||
int32_t truncLength = (int32_t) strtol(pSep + 1, &pEnd, 10);
|
||||
if (*pEnd != '\0')
|
||||
{
|
||||
*pSep = cSep;
|
||||
appendInvalidPlaceholder(buffer, "{", &placeholderValue, i, formatstr->length);
|
||||
continue;
|
||||
}
|
||||
|
||||
bool ellipsis = false;
|
||||
if (truncLength < 0)
|
||||
{
|
||||
ellipsis = true;
|
||||
truncLength = -truncLength;
|
||||
}
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY tempString = ffStrbufCreate();
|
||||
ffFormatAppendFormatArg(&tempString, &arguments[index - 1]);
|
||||
if (tempString.length == (uint32_t) truncLength)
|
||||
ffStrbufAppend(buffer, &tempString);
|
||||
else if (tempString.length > (uint32_t) truncLength)
|
||||
{
|
||||
if (cSep == ':')
|
||||
{
|
||||
ffStrbufSubstrBefore(&tempString, (uint32_t) truncLength);
|
||||
ffStrbufTrimRightSpace(&tempString);
|
||||
}
|
||||
else
|
||||
ffStrbufSubstrBefore(&tempString, (uint32_t) (!ellipsis? truncLength : truncLength - 1));
|
||||
ffStrbufAppend(buffer, &tempString);
|
||||
|
||||
if (ellipsis)
|
||||
ffStrbufAppendS(buffer, "…");
|
||||
}
|
||||
else if (cSep == ':')
|
||||
ffStrbufAppend(buffer, &tempString);
|
||||
else
|
||||
{
|
||||
if (cSep == '<')
|
||||
{
|
||||
ffStrbufAppend(buffer, &tempString);
|
||||
ffStrbufAppendNC(buffer, (uint32_t) truncLength - tempString.length, ' ');
|
||||
}
|
||||
else
|
||||
{
|
||||
ffStrbufAppendNC(buffer, (uint32_t) truncLength - tempString.length, ' ');
|
||||
ffStrbufAppend(buffer, &tempString);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!instance.config.display.pipe)
|
||||
ffStrbufAppendS(buffer, FASTFETCH_TEXT_MODIFIER_RESET);
|
||||
}
|
||||
+4
-36
@@ -1,46 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "util/FFstrbuf.h"
|
||||
#include "common/argType.h"
|
||||
|
||||
typedef enum __attribute__((__packed__)) FFformatArgType
|
||||
{
|
||||
FF_FORMAT_ARG_TYPE_NULL = 0,
|
||||
FF_FORMAT_ARG_TYPE_UINT,
|
||||
FF_FORMAT_ARG_TYPE_UINT64,
|
||||
FF_FORMAT_ARG_TYPE_UINT16,
|
||||
FF_FORMAT_ARG_TYPE_UINT8,
|
||||
FF_FORMAT_ARG_TYPE_INT,
|
||||
FF_FORMAT_ARG_TYPE_STRING,
|
||||
FF_FORMAT_ARG_TYPE_STRBUF,
|
||||
FF_FORMAT_ARG_TYPE_FLOAT,
|
||||
FF_FORMAT_ARG_TYPE_DOUBLE,
|
||||
FF_FORMAT_ARG_TYPE_LIST,
|
||||
FF_FORMAT_ARG_TYPE_BOOL
|
||||
} FFformatArgType;
|
||||
|
||||
#define FF_FORMAT_ARG(variable, var_name) { _Generic((variable), \
|
||||
uint32_t: FF_FORMAT_ARG_TYPE_UINT, \
|
||||
uint64_t: FF_FORMAT_ARG_TYPE_UINT64, \
|
||||
uint16_t: FF_FORMAT_ARG_TYPE_UINT16, \
|
||||
uint8_t: FF_FORMAT_ARG_TYPE_UINT8, \
|
||||
int32_t: FF_FORMAT_ARG_TYPE_INT, \
|
||||
char*: FF_FORMAT_ARG_TYPE_STRING, \
|
||||
const char*: FF_FORMAT_ARG_TYPE_STRING, \
|
||||
FFstrbuf: FF_FORMAT_ARG_TYPE_STRBUF, \
|
||||
float: FF_FORMAT_ARG_TYPE_FLOAT, \
|
||||
double: FF_FORMAT_ARG_TYPE_DOUBLE, \
|
||||
FFlist: FF_FORMAT_ARG_TYPE_LIST, \
|
||||
bool: FF_FORMAT_ARG_TYPE_BOOL \
|
||||
), _Generic((variable), char*: (variable), const char*: (variable), default: &(variable) ), (var_name) }
|
||||
|
||||
typedef struct FFformatarg
|
||||
{
|
||||
FFformatArgType type;
|
||||
typedef struct FFformatarg {
|
||||
FFArgType type;
|
||||
const void* value;
|
||||
const char* name; // argument name, must start with an alphabet
|
||||
} FFformatarg;
|
||||
|
||||
void ffFormatAppendFormatArg(FFstrbuf* buffer, const FFformatarg* formatarg);
|
||||
void ffParseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, uint32_t numArgs, const FFformatarg* arguments);
|
||||
bool ffParseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, uint32_t numArgs, const FFformatarg* arguments);
|
||||
#define FF_PARSE_FORMAT_STRING_CHECKED(buffer, formatstr, arguments) \
|
||||
ffParseFormatString((buffer), (formatstr), sizeof(arguments) / sizeof(*arguments), (arguments));
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
bool ffFreqAppendNum(uint32_t mhz, FFstrbuf* result);
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "common/ffdata.h"
|
||||
|
||||
// Runs the interactive config generation CUI.
|
||||
//
|
||||
// On success (the user saved the config), it sets `data->structure` to the user chosen
|
||||
// module structure and `instance.config.logo.type` to the user chosen logo type, creates
|
||||
// the result document and returns true. The caller is expected to call `writeConfigFile`.
|
||||
// Returns false if the user quits without saving.
|
||||
bool ffGenConfigInteractive(FFdata* data);
|
||||
@@ -5,20 +5,22 @@ extern "C" {
|
||||
#include <File.h>
|
||||
#include <AppFileInfo.h>
|
||||
|
||||
bool ffGetFileVersion(const char* filePath, FFstrbuf* version)
|
||||
{
|
||||
bool ffGetFileVersion(const char* filePath, FFstrbuf* version) {
|
||||
BFile f(filePath, B_READ_ONLY);
|
||||
if (f.InitCheck() != B_OK)
|
||||
if (f.InitCheck() != B_OK) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BAppFileInfo fileInfo(&f);
|
||||
if (f.InitCheck() != B_OK)
|
||||
if (f.InitCheck() != B_OK) {
|
||||
return false;
|
||||
}
|
||||
|
||||
version_info info;
|
||||
if (fileInfo.GetVersionInfo(&info, B_SYSTEM_VERSION_KIND) != B_OK)
|
||||
if (fileInfo.GetVersionInfo(&info, B_SYSTEM_VERSION_KIND) != B_OK) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ffStrbufSetF(version, "%d.%d.%d", (int)info.major, (int)info.middle, (int)info.minor);
|
||||
ffStrbufSetF(version, "%d.%d.%d", (int) info.major, (int) info.middle, (int) info.minor);
|
||||
return true;
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
#include "util/FFstrbuf.h"
|
||||
#include "common/FFstrbuf.h"
|
||||
|
||||
bool ffGetFileVersion(const char* filePath, FFstrbuf* version);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user