mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-13 02:42:09 +02:00
Compare commits
1615 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6f92524ada | |||
| b2ff1501aa | |||
| fbb4ab590f | |||
| e2cadf85f8 | |||
| b5c2c9ee7a | |||
| 1dabac9782 | |||
| 50983f83f5 | |||
| 5026be2d28 | |||
| 70aad5c320 | |||
| e74d21c0e5 | |||
| 90d8677b7a | |||
| 7a5d88270e | |||
| 5599335965 | |||
| e829589875 | |||
| 98acd516b8 | |||
| 584d792f5a | |||
| e6db860861 | |||
| f0ec3cb9ec | |||
| 0801e22dce | |||
| 5efd7b9ac4 | |||
| f2bae200d3 | |||
| fd14513aef | |||
| 6becc8f334 | |||
| 90359d227e | |||
| 6ff67e87eb | |||
| 0a83423731 | |||
| 5160644016 | |||
| d956bd2643 | |||
| 7a6a2ad530 | |||
| 21c76f31c4 | |||
| cb48c1277a | |||
| 3c18fd8920 | |||
| 83c6e809c6 | |||
| dc35fedd74 | |||
| 947923567f | |||
| 3d19388086 | |||
| 051f6643a6 | |||
| 47e01a7157 | |||
| a336145ed9 | |||
| ecc6b477dc | |||
| e0c6c462a6 | |||
| 3e607680e2 | |||
| 89347b7bee | |||
| c45ef08926 | |||
| 8d40b2cd0e | |||
| 14e318c273 | |||
| f50b478966 | |||
| 0cacedfc5d | |||
| 5283f10189 | |||
| c9c2526f08 | |||
| fba4bca46e | |||
| a95eb65faa | |||
| bcc7b630ae | |||
| a247a8d6ba | |||
| 620adc0ec6 | |||
| d5b3ae9056 | |||
| afe56a36c9 | |||
| 265b98311a | |||
| 89983a28b4 | |||
| c9918035ed | |||
| 225d1dd4d2 | |||
| 985fc991e8 | |||
| 8f3900a9df | |||
| d21ce9b10f | |||
| 1153d29099 | |||
| 75341e8172 | |||
| 2f5cbfb03a | |||
| 01d2d77efd | |||
| 1b2a61ed49 | |||
| 10584eb01a | |||
| d4ec500b1b | |||
| c7bec3d0c9 | |||
| ff6e982050 | |||
| 6a49ae60a1 | |||
| 27fb0c6c06 | |||
| 047b32e7d9 | |||
| eeb008f505 | |||
| 704834b370 | |||
| a3cb6608ce | |||
| 7640042905 | |||
| d601cc823c | |||
| 338cc1db40 | |||
| 6710967d19 | |||
| e4a5194115 | |||
| d151901049 | |||
| c9e9ec3a80 | |||
| 54912df237 | |||
| b09aa3240a | |||
| c9bc1f8306 | |||
| 7e98fa8626 | |||
| 3b2c189083 | |||
| c242001a77 | |||
| b21cfc127a | |||
| 3a5af1bbb3 | |||
| 68b98c1bd2 | |||
| 24ae7ec6e0 | |||
| e3590bc673 | |||
| 72dcc5223d | |||
| 4558af2e43 | |||
| ed259fad9c | |||
| b4e2997389 | |||
| d946a46d3f | |||
| 983bd50a09 | |||
| 4f0be4f72c | |||
| 58aa3e94e4 | |||
| 19ec59cca5 | |||
| 911780ba3c | |||
| 8b0d034a94 | |||
| 2a8235ae38 | |||
| 15a98a83cd | |||
| 1dc578badb | |||
| be698bd806 | |||
| 0cad657ce2 | |||
| 7991abab0b | |||
| b3e635a923 | |||
| 57b794cbd9 | |||
| 974dc96259 | |||
| db33d246cb | |||
| 5e5442426c | |||
| a55add190c | |||
| 5c381460ce | |||
| 4cf1d5bf94 | |||
| 4316ba988b | |||
| c6a9217c74 | |||
| 34d3021b80 | |||
| c57417e834 | |||
| 00f86c6346 | |||
| 0ab38bb4d7 | |||
| 7da45d6c2c | |||
| 3c7f02bee3 | |||
| 686a66e5f1 | |||
| c50d7bf974 | |||
| d70b3100f2 | |||
| d500bdff96 | |||
| 8de88adc0b | |||
| 4b3ed67877 | |||
| 11258c0d8d | |||
| 325aa536c4 | |||
| 31863baee2 | |||
| 0f08233581 | |||
| b28da1057c | |||
| 4fa3ca98a2 | |||
| 66f8a8cdd0 | |||
| 051423e75e | |||
| ae562ac962 | |||
| 772dd1e294 | |||
| 27212e8b98 | |||
| 629c2de253 | |||
| 9ef95e43a3 | |||
| 6a304dbb4d | |||
| 4355039329 | |||
| 5aebb400da | |||
| fbd8c0237f | |||
| 04c9d16c16 | |||
| 308408a962 | |||
| 19c5904561 | |||
| c0037c99e4 | |||
| b85c1c44b8 | |||
| 1c69d6c788 | |||
| b6b95581cd | |||
| 55c6374949 | |||
| 0a65867937 | |||
| 859f645fe5 | |||
| f1cc94207e | |||
| 70847857f7 | |||
| 2a34978487 | |||
| fde9379bb2 | |||
| e8e586ce7c | |||
| fb78d9bbb9 | |||
| a498e9e142 | |||
| d0d6f48751 | |||
| 0361a30c40 | |||
| d0c18c4679 | |||
| 8aca8a2229 | |||
| 0bbecb3b33 | |||
| 3f008c4b6d | |||
| 227eb707d2 | |||
| a5306d60ee | |||
| e3de39d3ab | |||
| f4666fcb0a | |||
| 85a554b60d | |||
| 1ea44417d0 | |||
| 0605cb754b | |||
| f889d919f8 | |||
| d670a9a584 | |||
| e51b8276cd | |||
| 67feba6171 | |||
| 922de3755b | |||
| 9da7bb3f30 | |||
| 46ebb52afa | |||
| 4f97692245 | |||
| 25a833207e | |||
| 8224f8c4c6 | |||
| c455718ada | |||
| 37b1d24575 | |||
| 449d121f19 | |||
| 9a51d203de | |||
| 0e92fc2289 | |||
| 54c649e76e | |||
| 45f8b86f13 | |||
| a8a1f98a8f | |||
| b8f14c964a | |||
| de964d3e77 | |||
| 4634606a36 | |||
| 5d306ed9f3 | |||
| ba1fc7a03e | |||
| 8b43605abf | |||
| 2ee5b3b7a5 | |||
| 302a588812 | |||
| 2a1330dea3 | |||
| 5472621ac0 | |||
| 9ad7ba7144 | |||
| 895d151e2e | |||
| 3ee15d0401 | |||
| 60ad6792ba | |||
| b878d3ccf6 | |||
| f93bd9e28b | |||
| 9c73f6b787 | |||
| 64b9f69fb1 | |||
| aca2c01c9e | |||
| 470d160346 | |||
| e225b496b1 | |||
| f470744e44 | |||
| 42fec6e61f | |||
| 883a535441 | |||
| 65b342cac7 | |||
| 1395abcf09 | |||
| e59d64513f | |||
| ed85b8249a | |||
| bddf1c67bf | |||
| 62ab091350 | |||
| 1588f58726 | |||
| 688a16c941 | |||
| 69b3a6871f | |||
| 0aac358e33 | |||
| 7f82f8d679 | |||
| 5fb96223a8 | |||
| e13c88cea6 | |||
| fbc76714f5 | |||
| c7adbc1309 | |||
| b27453d275 | |||
| aa0501b853 | |||
| 596c776463 | |||
| eb1738b1c6 | |||
| 0505926c75 | |||
| 581c6f547d | |||
| 3d5ef186ba | |||
| e3ea39afaa | |||
| 7f9269cff2 | |||
| bbcc040dc4 | |||
| 727a6988c2 | |||
| 7bbd2aee94 | |||
| b812f1dcb4 | |||
| fb2dca2eaf | |||
| a03eaed4e2 | |||
| ee705363c1 | |||
| c1fec9b411 | |||
| 19a9b18c69 | |||
| 38b3aae1e3 | |||
| 5d5663e2a7 | |||
| 973eb8127e | |||
| 2499cbdab8 | |||
| ec80a41871 | |||
| a829e85ef5 | |||
| a090bed6c0 | |||
| 76684e49ca | |||
| c1fc6e2762 | |||
| 437431a821 | |||
| 5749a8f7c1 | |||
| 54e271c985 | |||
| b042b90d9b | |||
| a99ca9a1a1 | |||
| f05d036023 | |||
| 5a55691358 | |||
| 4f0dd51761 | |||
| 0ca6f76e88 | |||
| 869f544bab | |||
| 4f67ed2b77 | |||
| 3f4926cbd5 | |||
| af93157a76 | |||
| 220a7d24bc | |||
| 3b541d3670 | |||
| 4bd6f2da89 | |||
| d5e00c3517 | |||
| 1b7a2c2ed5 | |||
| 11ad7a8a3d | |||
| 622f84c971 | |||
| 779a33349a | |||
| 135ca1eeba | |||
| 2dee7f5982 | |||
| 1513b8c0db | |||
| 693cc1e730 | |||
| e18980be9f | |||
| cf048bc723 | |||
| 3004d8c9dc | |||
| 6f66b87262 | |||
| 79cfa96616 | |||
| 952cacf3ff | |||
| 3cc6611614 | |||
| 457c2da67d | |||
| 13769e0e52 | |||
| b33e042cd4 | |||
| 2689a20889 | |||
| d769fd32f0 | |||
| 2c82c9a6dc | |||
| 3850130583 | |||
| 06262c078d | |||
| b64a234f8a | |||
| dfed3812ce | |||
| 1b594d9ed1 | |||
| d0f589bb3e | |||
| bc72f3cd64 | |||
| de8f1a86c6 | |||
| 4bae08c159 | |||
| 34cd81b4d9 | |||
| 8c127a175c | |||
| 5e3e2b6137 | |||
| 88a16d4c7d | |||
| 296674cfd6 | |||
| 875174e2e0 | |||
| 4393fa1a47 | |||
| 5ae2031bcf | |||
| 779266e61e | |||
| 8e8d283959 | |||
| 2cb7be67bd | |||
| 9bc5c99fc8 | |||
| 424fbfc9c9 | |||
| 3d2497f963 | |||
| 2e42bbb1a2 | |||
| 9879a95570 | |||
| d54f14a14c | |||
| cdcac06dbf | |||
| 6b81223002 | |||
| df986d36a2 | |||
| 173c9043e3 | |||
| 488986e42e | |||
| f2540f00a5 | |||
| 643aa7c156 | |||
| 0381d88e2d | |||
| 6a9fd7a84d | |||
| 2a491a8da9 | |||
| 983669019e | |||
| 553f90a7c4 | |||
| 00f5b84660 | |||
| b548c6405b | |||
| 6e190c6f7c | |||
| 661c174348 | |||
| 034f444fca | |||
| 1dd942a7b1 | |||
| 2f6613cb50 | |||
| 7c98450acc | |||
| 510d57e7dd | |||
| da797ecb33 | |||
| 7080449a8c | |||
| 2c51252396 | |||
| 5114051725 | |||
| 959371d1ea | |||
| f7ba00746b | |||
| 8387d8651e | |||
| af6b7dd81b | |||
| 89850535ae | |||
| 09a2f96cf0 | |||
| 8246c6e61d | |||
| cc490294e9 | |||
| 0a55071f88 | |||
| a57e334d73 | |||
| 174d885649 | |||
| 32d3edc690 | |||
| a7e93faac8 | |||
| 49921f5ed1 | |||
| 8849107260 | |||
| ad03c42a28 | |||
| 015ad4a307 | |||
| c0daeb16df | |||
| a0a46ab73f | |||
| bedd6a1d5d | |||
| 8ea2014baf | |||
| e59f4e7e45 | |||
| 0d3d881c24 | |||
| 230d2ac39d | |||
| c7e6e45078 | |||
| db88d413c3 | |||
| eaa4230bf5 | |||
| 145e09d164 | |||
| 01dbd0c266 | |||
| 11f3dc3ea0 | |||
| 87de3f1c4a | |||
| 03511bd014 | |||
| b0ad1294e4 | |||
| fcbeecb0d5 | |||
| b3c501516a | |||
| 9418138892 | |||
| 265254ddf7 | |||
| 946154dbac | |||
| 287ba33d12 | |||
| ca75b6b55b | |||
| 666b596f63 | |||
| 5b68cdc0dd | |||
| 0f47a27d09 | |||
| e6e189497d | |||
| 32d3b265bb | |||
| ca318431f5 | |||
| 8a52836afc | |||
| 9cf95620a9 | |||
| c72c6c4a27 | |||
| e289db184c | |||
| e7c9b80d85 | |||
| b8656d5e12 | |||
| c8486610f6 | |||
| d727f8acde | |||
| 8c64e0c275 | |||
| 40588e1a39 | |||
| 6c024d29ce | |||
| db6ad5a268 | |||
| 5096b4a81d | |||
| 5c64ce3b89 | |||
| 38a6d07c85 | |||
| 4632fe8cd9 | |||
| d8bfebfc0f | |||
| 48300429af | |||
| 218dffadd3 | |||
| f324794f54 | |||
| 6e3a329d3b | |||
| b2da8bac41 | |||
| 100e59fd49 | |||
| 5fdb0719f2 | |||
| d4368f56fd | |||
| 55c939a8ef | |||
| 0be2410925 | |||
| 0f824536f9 | |||
| 51c70bc44a | |||
| 47a0b8969f | |||
| 8df95224ed | |||
| 4481d983a9 | |||
| 24e8158116 | |||
| 5239223ad5 | |||
| 1d9a938ff3 | |||
| cd01d16eb9 | |||
| 8e856c3dd6 | |||
| b6dc436e03 | |||
| 3f80fafc09 | |||
| 8e922abf73 | |||
| 737b36e799 | |||
| f5ac85c4e3 | |||
| 0250d11d97 | |||
| e88472e9f6 | |||
| 2907a26adf | |||
| d337126c80 | |||
| 099fb1a43a | |||
| 6efe186df1 | |||
| f33f172734 | |||
| d6a1caa89f | |||
| ed5d7292ba | |||
| 4b0b6c9000 | |||
| 64d64d5050 | |||
| 1a996c3d67 | |||
| ee7231d87c | |||
| 371b3a2d75 | |||
| 007ded2883 | |||
| c32f2f2f2b | |||
| 98c94b01e5 | |||
| 0dda4efa8d | |||
| 877ed94187 | |||
| 484264027c | |||
| 5498b0b042 | |||
| 8f30d0cdd8 | |||
| 80f18e2473 | |||
| 1700d23c26 | |||
| 195675f078 | |||
| 0115b638de | |||
| 3d0653025e | |||
| 991d02e2c0 | |||
| cbab8d7f70 | |||
| 6e09157235 | |||
| 464a57b319 | |||
| d31d157b00 | |||
| 07231ffbbc | |||
| f9fa482b83 | |||
| 65ed48a1bc | |||
| 3068b5bcb2 | |||
| 9da97f5860 | |||
| fa065c1040 | |||
| 664017ba81 | |||
| 1d6fefd40b | |||
| fea4a9dfd5 | |||
| 183c8d7904 | |||
| e5b110375f | |||
| 6eed53217d | |||
| 254c4e5f50 | |||
| 01a917982c | |||
| a9cb178315 | |||
| ec4bd5d3a2 | |||
| 7f19cb1d21 | |||
| e60537512e | |||
| 431f570f05 | |||
| 482e5a5eff | |||
| c282384dab | |||
| 81bddbf182 | |||
| b8fc471678 | |||
| fd34811c81 | |||
| 67c5a6b7cc | |||
| 6b02e1a0ca | |||
| 92f1604e6a | |||
| f0cee064bd | |||
| 6bd933eba2 | |||
| f3e6d04c8e | |||
| d5846d94ca | |||
| 2a61d29be9 | |||
| 49cdacd5a9 | |||
| ce6d7e386d | |||
| fe1ad0da16 | |||
| 6157de60e6 | |||
| 61e71ed658 | |||
| 381cba2612 | |||
| 34b273186a | |||
| e3acd8c155 | |||
| 55f28ae8ff | |||
| 6f2748e208 | |||
| fb3eb9666e | |||
| 8d663300c7 | |||
| d29d99bd6d | |||
| bbdeb668d6 | |||
| 85578c6807 | |||
| 93871c1e98 | |||
| bcacaa9401 | |||
| d079e25a43 | |||
| b4306b944e | |||
| fd75f0b7e7 | |||
| 87c3459f5d | |||
| 051a043a4b | |||
| 913a3e79d4 | |||
| 59557e06fd | |||
| 6d0d916861 | |||
| a0a1c04011 | |||
| b59227e49f | |||
| c64e2c14c2 | |||
| 8c6cf2ccda | |||
| bd657328d2 | |||
| 45d6f21402 | |||
| 4d569db0fd | |||
| d46f9ab4dc | |||
| 3d4ce07892 | |||
| bb3689b348 | |||
| d5500ad4f7 | |||
| 9e4a55d285 | |||
| 999b9187a0 | |||
| 73095ef9e9 | |||
| f4fc9692eb | |||
| 59ebc745c0 | |||
| 09f3bd5a79 | |||
| 413d126bcc | |||
| 9eeb216b70 | |||
| f362fdb01d | |||
| 155d4e90ae | |||
| df9aec6e86 | |||
| d903ccb6f6 | |||
| 4b612461b8 | |||
| 38013450ae | |||
| ddb0c344f5 | |||
| 67e433750a | |||
| c4b024ec6c | |||
| e98c18a64b | |||
| acba1d29d9 | |||
| dd0f6354ef | |||
| 0e2d353500 | |||
| f9695f4148 | |||
| 8fdbadfbb2 | |||
| 5c43119836 | |||
| 545210e25e | |||
| 6f60423c60 | |||
| 6e6847a66b | |||
| 47c9fb9f6c | |||
| 5e5c144582 | |||
| ac330430bf | |||
| 52275b89dc | |||
| 50bb06535c | |||
| a8b0e77189 | |||
| b815464704 | |||
| 93ac3f1971 | |||
| 7c43e4b8e7 | |||
| d8e7588fc3 | |||
| 9ea5de5efc | |||
| 728759d38e | |||
| b0426828ab | |||
| 6de8153207 | |||
| 2c4b80a093 | |||
| c51903da35 | |||
| 8b7092e4d4 | |||
| c54b7fbd57 | |||
| 820854a2fa | |||
| ad4a71a2d5 | |||
| 22075e2d28 | |||
| a926c9cf7e | |||
| 60c735d1a4 | |||
| 9466ee3e51 | |||
| 126c1a10bb | |||
| 425e135bd8 | |||
| 0a675fec8c | |||
| 2c5b079b97 | |||
| 0be1a41b5c | |||
| 883e0450b0 | |||
| 2fc8a7e70b | |||
| be7f8f4117 | |||
| dd60e8aa75 | |||
| 851899397e | |||
| 60a30d888f | |||
| 999c8208b7 | |||
| 9143b6dbec | |||
| 16a706d3c5 | |||
| 58f436d8a2 | |||
| 47d1f2e673 | |||
| 8be4921bd0 | |||
| b22bcba220 | |||
| 5ee7ea46e7 | |||
| d93c934269 | |||
| 5c1ac33df2 | |||
| 0b3bf3c273 | |||
| 7fd98829b0 | |||
| 282271a65a | |||
| 9ef4b82cb9 | |||
| 10973dd9d1 | |||
| dfdffec1c9 | |||
| 2283700a99 | |||
| 7b647e09da | |||
| 54cb74c999 | |||
| 0f70cb408f | |||
| c80b1761dd | |||
| a1fde6f922 | |||
| 6a44515cf2 | |||
| cfcc4c8375 | |||
| ea60fd0a0d | |||
| a4e0275263 | |||
| 71779fa4b1 | |||
| 475099696f | |||
| 14670b6144 | |||
| 327b1b142e | |||
| 9d106c6672 | |||
| df0e13b198 | |||
| 6d0675820e | |||
| 08b0bac2b9 | |||
| d387800bda | |||
| 542ad5eab6 | |||
| 99f42d0953 | |||
| 3b316bdd3f | |||
| f011f8851e | |||
| 8f23a52f53 | |||
| 8f53d33f29 | |||
| e6fa269f52 | |||
| ca4a327de4 | |||
| f4e777f3d2 | |||
| 136f73ea0b | |||
| 28270541e6 | |||
| 8197eddea8 | |||
| 23bccc4802 | |||
| 873c7d93b6 | |||
| f4ee8667b1 | |||
| 50d3d4cdf4 | |||
| df048035b5 | |||
| 952989c1e8 | |||
| aa1237b0fd | |||
| b87983c86b | |||
| 779dbab647 | |||
| 47373998d5 | |||
| 11809e30b5 | |||
| 35253e085c | |||
| 112e83b7c3 | |||
| c74b34aa39 | |||
| b2e0034c34 | |||
| e3cdf9d9fd | |||
| 6cdb694e33 | |||
| 83016289e9 | |||
| f9562d7132 | |||
| 2f66bc2c95 | |||
| d7c848225c | |||
| 8404ae8e70 | |||
| d75f72c8fe | |||
| 9fa00081e3 | |||
| fca37b59c8 | |||
| 2fe7476c67 | |||
| 03cbd64d8a | |||
| f65aeed96f | |||
| b63f419cde | |||
| 99aa2f7b45 | |||
| b251c32c12 | |||
| 034e23d7e3 | |||
| bba912d42e | |||
| 597652c35a | |||
| 7f67846ad9 | |||
| bc2e292e22 | |||
| 75dc228120 | |||
| bc783f6efd | |||
| 85e1d2b40c | |||
| 3338189354 | |||
| d4c836fd25 | |||
| 6787f1eba8 | |||
| eedc277bcf | |||
| d4b32eaaec | |||
| 910f63f0ad | |||
| 9a0aa2ac72 | |||
| dce81055fe | |||
| 66a4fc1600 | |||
| 159a114bb7 | |||
| ac08b46e71 | |||
| ceb92dafd7 | |||
| 31eeb6dd08 | |||
| c021689a2b | |||
| 2ac2762c9f | |||
| 27dd097671 | |||
| c7bf471e29 | |||
| 298bc10e5f | |||
| 676485ef74 | |||
| fb6da20b0c | |||
| 0c81d3e894 | |||
| 5c1aa20042 | |||
| 46a27c4e39 | |||
| 128302596e | |||
| 7a15dee2be | |||
| 000bd37f1d | |||
| 707e0f930d | |||
| 7676a313c5 | |||
| 6e0d76a2fb | |||
| 4c7b7e4a4d | |||
| 4d34091573 | |||
| c971e28aca | |||
| c41a29a5c1 | |||
| 5c73125693 | |||
| cea48474a1 | |||
| 536f914f3e | |||
| 778856dd57 | |||
| 4a43144991 | |||
| ac96cfc748 | |||
| f18ffe3239 | |||
| 986bbeebb3 | |||
| b9d360af97 | |||
| ec1981c545 | |||
| f7e7d8e9f2 | |||
| ad9fc5845a | |||
| a6b169f3e2 | |||
| 8aff9939bc | |||
| 0b8f51188b | |||
| 3c99a82619 | |||
| d5f3ff1cfe | |||
| 011c033091 | |||
| 63bf22fb00 | |||
| f74973db65 | |||
| 85656fd515 | |||
| 23bf7a407b | |||
| e570cacbc9 | |||
| a96f79795b | |||
| 2d51d935c8 | |||
| 9d395f7235 | |||
| 5f16394916 | |||
| 6581c9d378 | |||
| 67ac7eef59 | |||
| b95e83e9e5 | |||
| e9d9b942fa | |||
| c95ad74ea2 | |||
| 85b0be5213 | |||
| da671d6cfe | |||
| 18af9ab902 | |||
| 558fbc20e2 | |||
| d9bbbd4fa8 | |||
| 292a809703 | |||
| fa13826043 | |||
| 7bc85b2397 | |||
| 1863d8377a | |||
| f9e17f44b1 | |||
| 02cc214dfc | |||
| 609fa14f4f | |||
| 7d6f92a446 | |||
| bc76ebfb3f | |||
| c2da7b19f9 | |||
| 41b024d3b1 | |||
| 9b62d17d8d | |||
| 1861d55f7d | |||
| 3b2a6e4a6e | |||
| 8ab7a8ba37 | |||
| 22a3ab4a81 | |||
| 44d6780545 | |||
| 5820c9bbff | |||
| 3ba486a5b8 | |||
| 2d2ba4c5b3 | |||
| 94ad782caa | |||
| b079e86c5e | |||
| 91ba03d988 | |||
| c440fdfca8 | |||
| af0c72aa61 | |||
| 8fa09ca093 | |||
| 6e731c80d0 | |||
| 45eae78980 | |||
| fb35a6e889 | |||
| 26d17250b6 | |||
| 9176797327 | |||
| 9d3f762c20 | |||
| fe71291769 | |||
| f35dc9f46a | |||
| a6209187ae | |||
| af2f97e0c9 | |||
| 0691112e5e | |||
| e61b31acab | |||
| 5d853f3b17 | |||
| 20e2f1e19d | |||
| ad28b3aac5 | |||
| eb0bbd0796 | |||
| da77a7936f | |||
| eac875b8b1 | |||
| 97d2096df8 | |||
| 6e3e717224 | |||
| aae182c889 | |||
| 5c7b9d223a | |||
| c80f8cf422 | |||
| b150e8d106 | |||
| bb897f03f0 | |||
| 517d80eadc | |||
| 36964d6b1d | |||
| 5e96ba8384 | |||
| 481affa50a | |||
| a33e296656 | |||
| 85a36ae7ef | |||
| 1eff343733 | |||
| acdbf6933c | |||
| ea53833466 | |||
| c491c11988 | |||
| dcaeab7e96 | |||
| bccd1cf960 | |||
| 5b030de20a | |||
| fa9b38eb2d | |||
| 716522e29a | |||
| 921e4a6c8d | |||
| 7d43118abb | |||
| d8bb36f119 | |||
| ae8b5bde65 | |||
| 3d8a071781 | |||
| 4cf912e535 | |||
| e1b5445783 | |||
| a04daf1fff | |||
| df0a4c0d46 | |||
| d70e160d72 | |||
| 8c52cd0d91 | |||
| 4622d7a300 | |||
| 09f7180dd5 | |||
| 6ae8b46f68 | |||
| 2d0ffb55b7 | |||
| 22a8cfdcfe | |||
| 63041aa24b | |||
| 242df5f2f0 | |||
| ec1bbd118f | |||
| fe624123dc | |||
| 8577be3d6d | |||
| d185dc74b8 | |||
| 54c09cab18 | |||
| dbe24c7508 | |||
| d23d4ef5a0 | |||
| daac1b783c | |||
| 2e98dd7710 | |||
| 9d6d2ca5a4 | |||
| e4a1a836fe | |||
| 1e3cabff2d | |||
| 008cf3b83d | |||
| 3daede53eb | |||
| 36d9b5a9bd | |||
| 1826e23c29 | |||
| 43b3998b9d | |||
| c55cc9c732 | |||
| 0244e5ebd7 | |||
| ea6805de82 | |||
| 9aba57cdea | |||
| 0dffd8debf | |||
| 032ba375b6 | |||
| 743bc07bad | |||
| 044e5496fd | |||
| 102b2d33c7 | |||
| afc144fa01 | |||
| ededa4d6dd | |||
| af4596b666 | |||
| 8c910089cc | |||
| e79af7ba79 | |||
| 960364bd47 | |||
| ea44231c78 | |||
| 60af0b9e39 | |||
| e4ecb9d069 | |||
| 3c648d84db | |||
| 45db4a5c3d | |||
| caf976bec2 | |||
| b3d855355e | |||
| 0a2eb49891 | |||
| ab2efa151a | |||
| 1aee3f81c5 | |||
| 4c7031cb12 | |||
| 81c96d0f11 | |||
| 4d8680ec2d | |||
| 039eb3a38a | |||
| d07a653404 | |||
| 76c0b7e457 | |||
| 1c0e532b79 | |||
| c79a9f1bff | |||
| 759069adfa | |||
| 66ff6adfb0 | |||
| 1dba19c49f | |||
| 2afd158d96 | |||
| 36c2ce6219 | |||
| 5f6432c150 | |||
| e9f0eca3dd | |||
| 998691847e | |||
| 64e5ef0df7 | |||
| cc1e876faf | |||
| 964a5aa8b4 | |||
| ad2601f097 | |||
| 7cae63ac05 | |||
| 0d26cfb218 | |||
| 3b6855b9da | |||
| 51414c5511 | |||
| 24f8ad7673 | |||
| e404dd62c0 | |||
| 21b315d548 | |||
| 14fa052257 | |||
| 5861012d95 | |||
| 4d9fbd93d2 | |||
| 1d99bd2e08 | |||
| 52eed51eb6 | |||
| e5237c14cb | |||
| 47d8ddad35 | |||
| 37ab01d5ee | |||
| 80f7a982e0 | |||
| cff3aed49c | |||
| 572d4ec8e9 | |||
| 5bceb29c79 | |||
| 8b153833b1 | |||
| adc92b5548 | |||
| 03e949ed30 | |||
| 6accb587af | |||
| 373e041e5e | |||
| 31bdd25a26 | |||
| 703ec597fa | |||
| 3b1314102f | |||
| d349b7f7fb | |||
| dabdb104e2 | |||
| 8d5ce7bcdb | |||
| 751568e9f3 | |||
| 430fe9fe9a | |||
| 8831c07d2b | |||
| e009bb1516 | |||
| 82e2790e1b | |||
| 64182539aa | |||
| c67fd169f8 | |||
| f58d0df336 | |||
| bd0c593871 | |||
| a032d37ad4 | |||
| a4861606b7 | |||
| 88fe34102e | |||
| 5346104ffa | |||
| 12371cdc84 | |||
| 3248afe91c | |||
| 1731ab2c5f | |||
| fcc8927917 | |||
| ccf4e2d2b5 | |||
| f2998a329d | |||
| 30365e8997 | |||
| 5b66938bf4 | |||
| 80c5600a7b | |||
| 65ce2eafed | |||
| d840c7a12d | |||
| 634e27bc42 | |||
| cc18315e84 | |||
| 83e2787b24 | |||
| ef5a9384da | |||
| 2d7e6c37ff | |||
| 92e8f23261 | |||
| e09f1d3647 | |||
| 6f01e33955 | |||
| 4b813cdf59 | |||
| 942c583c89 | |||
| 24a48c1fc0 | |||
| e2e95732e8 | |||
| d647f9e3f2 | |||
| 4895c68ca9 | |||
| f0b9800974 | |||
| be84549f4c | |||
| 0916258c87 | |||
| ad006b466c | |||
| efdf38a9ea | |||
| 10a202fe80 | |||
| 6e8aca0945 | |||
| 4cd08b82d4 | |||
| a2ebecdf6d | |||
| aa352a4427 | |||
| 10c97aea4b | |||
| e08cb24cb5 | |||
| bfbaecb533 | |||
| d915f415b1 | |||
| 1887e21ddc | |||
| 0b6c974126 | |||
| fdd8919e1c | |||
| 0c936cab27 | |||
| d17aae5d65 | |||
| 77e05b0c95 | |||
| 0f6e266fc3 | |||
| de779cf1ea | |||
| ecbb854e54 | |||
| da26a3497e | |||
| a6770581d3 | |||
| 07a685bb9a | |||
| 00fdb8a0c4 | |||
| 4e68c09f27 | |||
| b5a36b0825 | |||
| 231016264b | |||
| 0451852e34 | |||
| b9dfe1f858 | |||
| 51bbff4741 | |||
| 7c9b5c2c61 | |||
| fd450bcccc | |||
| 0cb6e40bac | |||
| 9c20c50c3d | |||
| aa9dd9c155 | |||
| 415c097489 | |||
| 109026211c | |||
| ed63ef1a28 | |||
| f54ac1c4e6 | |||
| 313084f91c | |||
| 59bd9927a4 | |||
| e2be34e23d | |||
| 3ca3687993 | |||
| c066446685 | |||
| ecb38e8d20 | |||
| c800077b73 | |||
| fcea3649e2 | |||
| eaaa2705d3 | |||
| a32b1c5887 | |||
| cfb5d204a1 | |||
| d6ae32374e | |||
| 451848f6fd | |||
| a7728f61fb | |||
| fb3028cafa | |||
| ea5b663b16 | |||
| 9659f8c7b1 | |||
| 3f64ef0876 | |||
| 8c6cb9405d | |||
| 8a754f5b89 | |||
| 5f965ac787 | |||
| bc8887fb42 | |||
| 2ff3595251 | |||
| 47a58ad7b5 | |||
| ec523e0274 | |||
| 87e410e0fc | |||
| cc43ed2351 | |||
| a28c4600f4 | |||
| 7ad73d3ba1 | |||
| f72ec8a99f | |||
| 6107241f4a | |||
| 68e8ddce6f | |||
| 1a57d82675 | |||
| c662416b33 | |||
| 79331d7fe5 | |||
| e887b56209 | |||
| 23b71cc907 | |||
| 4e45a2e3ba | |||
| 14115eb089 | |||
| 8f466735a8 | |||
| 7a7eac9edd | |||
| 65dc9bb166 | |||
| 57ef794864 | |||
| cd4739e4f7 | |||
| 3a667add01 | |||
| 6906094b8b | |||
| b8a239e379 | |||
| e30a64e97e | |||
| f2663a65cc | |||
| a0f5432903 | |||
| 20427a534e | |||
| 9789d1f5f1 | |||
| bf2152bac8 | |||
| accaaa7de5 | |||
| 322e5c5a48 | |||
| 6d7ad48edf | |||
| 6a62f909d4 | |||
| 3653836490 | |||
| f21013f646 | |||
| 8639e59019 | |||
| 33127388f0 | |||
| f54101e9f5 | |||
| d79b7a8944 | |||
| 2c7314dd8e | |||
| 729d9d5c47 | |||
| 1c72219a88 | |||
| 816d86aee8 | |||
| d6a80d7c85 | |||
| ef034b7adb | |||
| 4bbb13b44d | |||
| 4aff8a353b | |||
| 190974e079 | |||
| e95e1e3530 | |||
| 1d6119f858 | |||
| bf60429e36 | |||
| 31d0729cdd | |||
| 0879746e0f | |||
| 3f30fa8d4a | |||
| 53f31f2401 | |||
| 59e61f53e1 | |||
| 7a3bf2f77d | |||
| bd3a5fde07 | |||
| ecb1853d56 | |||
| bcf543e129 | |||
| 06fa8e7478 | |||
| f73137aef8 | |||
| d4f753a9f8 | |||
| 65bac0efc9 | |||
| a15b3661c3 | |||
| a011b55692 | |||
| 87eb2659de | |||
| 1a7f04fe0c | |||
| 7638d0b8b6 | |||
| b89e41c1d7 | |||
| 809f9310a5 | |||
| 9b7f236397 | |||
| 8f865cf823 | |||
| dedbd5b529 | |||
| 5f178880c7 | |||
| 74b809f68a | |||
| f0732d0056 | |||
| e6851eeabc | |||
| 9e2d6be31f | |||
| 7f846dadaf | |||
| 79bec5c220 | |||
| 8653a881fd | |||
| aaa6f32f15 | |||
| bbbf00e834 | |||
| 7bab4ef298 | |||
| 9db9a2c195 | |||
| cb16cd583b | |||
| 2abaf64c12 | |||
| 4e818c981a | |||
| 6c4961aaff | |||
| 7db781c508 | |||
| 7ced537e59 | |||
| f0e623c3de | |||
| 40d535ffba | |||
| 18bfc6bd11 | |||
| 6823b65615 | |||
| ad347a6083 | |||
| fff69ac7e2 | |||
| d41d31a6a7 | |||
| 9e6b0b03ea | |||
| dff3ca58ae | |||
| fc77e40ea9 | |||
| 869aa67d1f | |||
| fd447ab439 | |||
| 6cdf32dabc | |||
| 1c8eca1010 | |||
| 42b8182428 | |||
| e54398f7b3 | |||
| 27334f77cc | |||
| 6b0343a46c | |||
| 214540e7ef | |||
| 0c7a415f9b | |||
| 0048c1ca98 | |||
| df2ad48d13 | |||
| a81f897258 | |||
| e9db9ac87a | |||
| a198322d58 | |||
| 6e6086a8b4 | |||
| b3b31d693e | |||
| f6700f5272 | |||
| 58ec50fa7f | |||
| 15328345da | |||
| 0f16bf2698 | |||
| 46ecdd42b6 | |||
| 7663637ea9 | |||
| bf1fbd572a | |||
| e3f0319575 | |||
| f333ede1f7 | |||
| c0584cf465 | |||
| 00c05f14c7 | |||
| c008f66a76 | |||
| 57377019e6 | |||
| 2f555df690 | |||
| eb6b8778b3 | |||
| 09285338c5 | |||
| 20dd2fa28f | |||
| 7a21f44a3a | |||
| 1df591b46f | |||
| b3ef53ddc9 | |||
| e18199e8ec | |||
| 3923f11a45 | |||
| c223ace5eb | |||
| 9b399da872 | |||
| 1a5b1428dc | |||
| 5589293d76 | |||
| 714181175d | |||
| fd257ddde9 | |||
| 349e5b24fa | |||
| 73436824f9 | |||
| e5322cf165 | |||
| 564ddfc1b6 | |||
| 181dfb5cfc | |||
| 072a4bc412 | |||
| 914cd9219d | |||
| dbc4a815c5 | |||
| 5d97436c7d | |||
| 5f0c5a0351 | |||
| 7dc70b9730 | |||
| d288a698b0 | |||
| 38e2f8cf3e | |||
| 0b3f96610b | |||
| 3a649493ea | |||
| 8d7d33882f | |||
| f265307dc4 | |||
| e02d81d866 | |||
| a2742ce60b | |||
| 588a68ac4c | |||
| 0f916bb492 | |||
| 9faf664320 | |||
| 7fa971bc86 | |||
| b733bb628d | |||
| d7356a8323 | |||
| 26f4fac62b | |||
| 273d4205b5 | |||
| 1717b51807 | |||
| 7b5af1b133 | |||
| 45e5546c92 | |||
| 8f1b067953 | |||
| ad220546ba | |||
| 78af5cb8a8 | |||
| dc2f45626f | |||
| 4d408f55fa | |||
| 3f936e084d | |||
| 764d2b7fc9 | |||
| 11c07d6738 | |||
| 262a3eb59f | |||
| 0d09b89016 | |||
| d2156dfc1d | |||
| 2c599b5924 | |||
| 3d3216ba91 | |||
| d7a8623f90 | |||
| 582d5b6473 | |||
| 19b71d9ce0 | |||
| a88cb07dad | |||
| 4c02b8319b | |||
| ea8c68bab4 | |||
| d4d9bc90e6 | |||
| c0cb55ca9a | |||
| 8cb3ff7c2b | |||
| ef31e08d2d | |||
| f148dbacfb | |||
| 450ac7f2cd | |||
| 98f420ad3d | |||
| 27915127a8 | |||
| ea2f6470d8 | |||
| 9ade52ddc0 | |||
| 409b1f29a6 | |||
| f8c215775a | |||
| 0bf486fa67 | |||
| 4fecc76083 | |||
| 2bae720e00 | |||
| bfd76ae455 | |||
| cab5069be2 | |||
| 5aa5ab2c16 | |||
| 5515eea42d | |||
| eab26149e7 | |||
| d77fc9a9c3 | |||
| 0108a3ade0 | |||
| e79209c7bf | |||
| 399eee1963 | |||
| 4f2b3d740e | |||
| bc65c9f9c3 | |||
| 756593e160 | |||
| ed3e5b544f | |||
| 7b58c97ff3 | |||
| ab2cb9e0e4 | |||
| 889c8570f2 | |||
| 3ce12dfc47 | |||
| 020fdccaaf | |||
| f82a4a6d7d | |||
| 32f520bf3b | |||
| fc3cfff1d4 | |||
| 36df822ce6 | |||
| 4d565cb7ee | |||
| 580ad45459 | |||
| 9535aa885c | |||
| 6a65803929 | |||
| 602c3767e5 | |||
| 0b93feaa94 | |||
| 49e7612795 | |||
| 0e8b1fff8e | |||
| e4516dc548 | |||
| 936c478a9a | |||
| de72ea6ee6 | |||
| 53389850c2 | |||
| a10aa36b72 | |||
| f20ec0ef9f | |||
| b9c6830a14 | |||
| 94e4443464 | |||
| ec82b80f5a | |||
| e630167585 | |||
| 137b3f7010 | |||
| 571913ed44 | |||
| 76f9da4b78 | |||
| 72fbcf94ff | |||
| 9f7f57dfd8 | |||
| bd3c236480 | |||
| 14932466f7 | |||
| dbfa9dcc1f | |||
| cd56317186 | |||
| 6b40174656 | |||
| f1c3b5275f | |||
| 5dc5ac6d29 | |||
| 5b69bd77a6 | |||
| f19a1f40be | |||
| 15ed8504bf | |||
| 4191bd8865 | |||
| 00c426c98a | |||
| 2bb4407030 | |||
| 67edfd7f59 | |||
| a1985bd7e8 | |||
| bfc9384ce3 | |||
| 82674a7d14 | |||
| 0531afadb7 | |||
| 142d9c30e0 | |||
| c8a9f06b52 | |||
| 5f71ef71da | |||
| dbde798a56 | |||
| 8af1cde10b | |||
| 852d6dcdcb | |||
| c49fed470a | |||
| f7e0e70b2f | |||
| 44339971bd | |||
| d12edd02bf | |||
| 0dbcce84f8 | |||
| 0e2deb3534 | |||
| bbb46e7c66 | |||
| 25d23b020e | |||
| 2ee2c68db5 | |||
| e400ee4490 | |||
| bbd41e6c7a | |||
| f24f6756b1 | |||
| cedde7eced | |||
| ca08e07c37 | |||
| a72e3fed29 | |||
| d815f624db | |||
| 635f31eae1 | |||
| 8128db974b | |||
| a841489280 | |||
| 0e94658683 | |||
| 225bcbe89a | |||
| ae01d28094 | |||
| d14a398f17 | |||
| 1e82780de7 | |||
| 35681ec09f | |||
| 0940064759 | |||
| 959750de3d | |||
| 9e597aa253 | |||
| 4d7a06ac97 | |||
| f8868ae3c4 | |||
| 7afc27e52f | |||
| 1ece13c36f | |||
| c549c7c868 | |||
| cac0c27807 | |||
| 039b69f4a7 | |||
| 97ab892051 | |||
| 6cfe826cd7 | |||
| e89b326d57 | |||
| ef3f4d9fa8 | |||
| 89187e9758 | |||
| cf4b3c54cf | |||
| 719a5c999d | |||
| 7432fc7a19 | |||
| ed2b72e0cf | |||
| b5454c28bf | |||
| fc314e6ded | |||
| 479188ec3e | |||
| 70c1b477d0 | |||
| 0e236c7d6a | |||
| cdf82e91b2 | |||
| 476988f695 | |||
| 123d19bb69 | |||
| 099ddeea01 | |||
| eac718085e | |||
| 30953a31dc | |||
| 4f83dc8396 | |||
| dfeb5c49e1 | |||
| b054fec8d8 | |||
| c8cd51da84 | |||
| a6cd29057b | |||
| 62f1c5d059 | |||
| e249c1590a | |||
| e4a61c3572 | |||
| c749763f05 | |||
| bd316496a2 | |||
| 79810542af | |||
| f09aae6541 | |||
| 7609a24778 | |||
| eea74b085b | |||
| 4e49416394 | |||
| a389b89ff0 | |||
| ebc42b8f8b | |||
| ec941bcb33 | |||
| 91b7967677 | |||
| cb61fde75d | |||
| 20322c4fe4 | |||
| a7784f5a88 | |||
| 89aa4470aa | |||
| 14d3e3b1b3 | |||
| bc870197d7 | |||
| 9c26f9d988 | |||
| 7da0c76703 | |||
| 7ec32bf5d3 | |||
| bd2e1da3b4 | |||
| 88d2530460 | |||
| 286095a09a | |||
| f47a44f47a | |||
| 35504b33b1 | |||
| 56c0e9d068 | |||
| 46306d913f | |||
| 6917164271 | |||
| 39f0f9c483 | |||
| fb17273ec4 | |||
| 85c7f4c772 | |||
| 6e8e2e6c47 | |||
| 97ae9e9d28 | |||
| 94caa86998 | |||
| e66e78fcc5 | |||
| 6eddc6105f | |||
| 671842d316 | |||
| f3c8ecacbb | |||
| 2618465121 | |||
| 7f4dba8856 | |||
| e3f3699b26 | |||
| c3f7ed5247 | |||
| 01ada03c5c | |||
| 5c93d70341 | |||
| bbeddbe403 | |||
| 644843a70d | |||
| d403c035d0 | |||
| dd31e05fde | |||
| 99849ccd77 | |||
| 4674d6c2fc | |||
| f938847459 | |||
| f4d2b35260 | |||
| b83499d1ec | |||
| 2449681f30 | |||
| dd709461a5 | |||
| dbc576862e | |||
| a4d4b66679 | |||
| 6bcf3bab7c | |||
| 41dc49f170 | |||
| 2a29d3ed17 | |||
| 6c612cbd9a | |||
| e9cf1c0252 | |||
| 7da4e5b69a | |||
| ffd5b45b2c | |||
| 843a9811d0 | |||
| 6b066911dd | |||
| f4a691ebd6 | |||
| ec76f1c2d9 | |||
| dffbd4f0f0 | |||
| f7b6fb2d4f | |||
| 1b1d28f0ab | |||
| d469120e9b | |||
| 36a4d095ed | |||
| ad122e9569 | |||
| fc1c17932e | |||
| 2ba1fb0868 | |||
| 49e112eeae | |||
| c5c3cecb93 | |||
| 025dbecc4f | |||
| 85c49f6873 | |||
| adce9fc53d | |||
| c697f8ee80 | |||
| eddc01290a | |||
| 283e4f56e9 | |||
| e28126f40e | |||
| c12484ec6b | |||
| b1df0ef98a | |||
| a64dc74923 | |||
| 3e9ce54f63 | |||
| 1d47eb0c60 | |||
| 3e9678c899 | |||
| 4e54117238 | |||
| 44ddfc2a03 | |||
| eae92b6306 | |||
| b7c0c18497 | |||
| 61188b68a4 | |||
| 51c38a2b01 | |||
| 7b65316483 | |||
| 86abc05cd4 | |||
| 1d878215ae | |||
| a145700500 | |||
| f27f08a6e2 | |||
| 9bc1f2a116 | |||
| ed598eaa35 | |||
| 0ed54eddc4 | |||
| 2b55a14c16 | |||
| 53c781aa21 | |||
| 0649b6e755 | |||
| 9321241830 | |||
| c698080581 | |||
| ed7e186f4b | |||
| 5f23f2b027 | |||
| c543bcc29f | |||
| de312adb52 | |||
| af430bd405 | |||
| 1086c059b6 | |||
| f25bca3dab | |||
| e01d03f98d | |||
| 67465d266e | |||
| 08066a76f0 | |||
| a8821cf6f0 | |||
| 9c26a76c9d | |||
| 307fc61184 | |||
| c44bd6dbc1 | |||
| 184eafce20 | |||
| efc0322ed1 | |||
| b3c3614b6c | |||
| 693f8a33db | |||
| 44549e32d9 | |||
| a1e90ba35c | |||
| 46ed1b34cb | |||
| 23db257af9 | |||
| beb2e9608c | |||
| 055804a055 | |||
| f61ffdb149 | |||
| a0af3b0eb6 | |||
| 2021709d72 | |||
| 4d736fd5d0 | |||
| 02c450c218 | |||
| 071b2c6727 | |||
| 2004544528 | |||
| c783bb9d97 | |||
| 101d19a015 | |||
| 0d3500c66f | |||
| a848798e97 | |||
| 9d5481e83a | |||
| 05fe281141 | |||
| 3d27ecaba8 | |||
| e70f06087c | |||
| e2986b198f | |||
| e479b62c73 | |||
| e531278e62 | |||
| a8ca2ce825 | |||
| 92b1247683 | |||
| dd19fcfded | |||
| db35000e39 | |||
| 1ceb5c91ac | |||
| cddfc083c3 | |||
| f358e07b84 | |||
| 74b315a1d1 | |||
| 9d28df2922 | |||
| 016acb8e9e | |||
| e53f84bb27 | |||
| fd3215ed3b | |||
| be9272c2e9 | |||
| eb7ce05193 | |||
| 5c6bbbf677 | |||
| cf9af7023f | |||
| 370de39169 | |||
| 05f11c6c69 | |||
| a0169d83e5 | |||
| 37dd06590a | |||
| 8e9cb079b0 | |||
| a6c153da95 | |||
| b9c7324aa5 | |||
| c988777c79 | |||
| 0169507489 | |||
| 33be85c4bc | |||
| abd797a0bf | |||
| aa5b5f3caf | |||
| 6cc99423c9 | |||
| 43022c0129 | |||
| 6e11609432 | |||
| 2240264d02 | |||
| dbeaa342ba | |||
| 16af140f7a | |||
| 923faa63e5 | |||
| bc13b51b5a | |||
| 9122daa63a | |||
| 61b369ea19 | |||
| 22cfe4df1f | |||
| f65105d181 | |||
| f67a5f3879 | |||
| c1fb9525b8 | |||
| b95dd4ce17 | |||
| db6d2eb3a3 | |||
| 4dffbb0bb7 | |||
| 7248daaa48 | |||
| 0617b597f9 | |||
| e06aab6836 | |||
| d1cec7d1e5 | |||
| 56751e4581 | |||
| d3db1066e2 | |||
| 0c3a562ec6 | |||
| 1cda1eb653 | |||
| b44ab16dd1 | |||
| 558639086a | |||
| 48a436ee78 | |||
| 16239be51c | |||
| 3d902c1c86 | |||
| 0ec63d64fa | |||
| fea8e371e4 | |||
| 7cbe1c2359 | |||
| 4b4f92eb74 | |||
| df3dcb7ede | |||
| f14e84606f | |||
| 85bcf00cf8 | |||
| 11b5d6e138 | |||
| e3616d8b72 | |||
| 61bac93809 | |||
| 5d32a782a2 | |||
| 626badd3c8 | |||
| 12ed7a9812 | |||
| f533767569 | |||
| a8f165e5c9 | |||
| c5a9b9d428 | |||
| 41120ef582 | |||
| 4b2c4a8821 | |||
| ebb14afb26 | |||
| da5ab1c187 |
@@ -0,0 +1,17 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
end_of_line = lf
|
||||||
|
indent_style = space
|
||||||
|
tab_width = 4
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
[*.{md,fflogo}]
|
||||||
|
trim_trailing_whitespace = false
|
||||||
|
|
||||||
|
[*.{fflogo}]
|
||||||
|
insert_final_newline = false
|
||||||
|
|
||||||
|
[*.yml]
|
||||||
|
tab_width = 2
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
*.h linguist-language=c
|
||||||
|
*.c linguist-language=c
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
github: LinusDierheimer
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Create a report to help us improve
|
||||||
|
title: ''
|
||||||
|
labels: bug
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# General description of bug:
|
||||||
|
|
||||||
|
|
||||||
|
# Often helpful questions:
|
||||||
|
* Does the issue occur across multiple terminal emulators? [Y/N]
|
||||||
|
* Does the issue occur across multiple shells? (bash, zsh, fish, etc) [Y/N]
|
||||||
|
|
||||||
|
Output of `fastfetch --version`:
|
||||||
|
```
|
||||||
|
//paste here
|
||||||
|
```
|
||||||
|
|
||||||
|
Output of `fastfetch --load-config devinfo`:
|
||||||
|
```
|
||||||
|
//paste here
|
||||||
|
```
|
||||||
|
|
||||||
|
Output of `fastfetch --load-config devinfo-verbose`:
|
||||||
|
<!--
|
||||||
|
Note that this output will contain you public IP. If it is not relevant for the issue, feel free to remove it before uploading.
|
||||||
|
-->
|
||||||
|
```
|
||||||
|
//paste here
|
||||||
|
```
|
||||||
|
|
||||||
|
Output of `fastfetch --list-features`:
|
||||||
|
```
|
||||||
|
//paste here
|
||||||
|
```
|
||||||
|
|
||||||
|
<!--
|
||||||
|
If you get the following error: `Error: couldn't find config: [...]`, copy the files in [presets](../../presets/) to `/usr/share/fastfetch/presets/` or `~/.local/share/fastfetch/presets/`.
|
||||||
|
If this isn't possible (or too much work) for you, post the output of `fastfetch --show-errors --multithreading false --disable-linewrap false`.
|
||||||
|
-->
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for this project
|
||||||
|
title: ''
|
||||||
|
labels: enhancement
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Current state:
|
||||||
|
|
||||||
|
# Wanted state:
|
||||||
|
|
||||||
|
# Why the change is sensible:
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
name: Logo request
|
||||||
|
about: Request a new logo
|
||||||
|
title: ''
|
||||||
|
labels: logo request
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# OS
|
||||||
|
```
|
||||||
|
paste content of /etc/os-release here. If this file doesn't exist, describe a way to identify the distro.
|
||||||
|
```
|
||||||
|
|
||||||
|
# Ascii
|
||||||
|
```
|
||||||
|
paste ascii art here. If you leave this empty, i will try to find the logo myself.
|
||||||
|
```
|
||||||
@@ -0,0 +1,302 @@
|
|||||||
|
name: manage pushes
|
||||||
|
|
||||||
|
on:
|
||||||
|
- push
|
||||||
|
- pull_request
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
linux:
|
||||||
|
name: Linux
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
security-events: write
|
||||||
|
contents: read
|
||||||
|
outputs:
|
||||||
|
ffversion: ${{ steps.ffversion.outputs.ffversion }}
|
||||||
|
steps:
|
||||||
|
- name: checkout repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: install required packages
|
||||||
|
run: sudo apt-get update && sudo apt-get install -y libpci-dev libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev rpm librpm-dev libzstd-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libcjson-dev
|
||||||
|
|
||||||
|
- name: Initialize CodeQL
|
||||||
|
uses: github/codeql-action/init@v2
|
||||||
|
with:
|
||||||
|
languages: c
|
||||||
|
|
||||||
|
- name: configure project
|
||||||
|
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||||
|
|
||||||
|
- name: build project
|
||||||
|
run: cmake --build . --target package
|
||||||
|
|
||||||
|
- name: perform CodeQL analysis
|
||||||
|
uses: github/codeql-action/analyze@v2
|
||||||
|
|
||||||
|
- name: run fastfetch
|
||||||
|
run: time ./fastfetch --disable-linewrap false --hide-cursor false --show-errors true --load-config presets/all
|
||||||
|
|
||||||
|
- name: run flashfetch
|
||||||
|
run: time ./flashfetch
|
||||||
|
|
||||||
|
- name: run tests
|
||||||
|
run: ctest
|
||||||
|
|
||||||
|
- name: get fastfetch version
|
||||||
|
id: ffversion
|
||||||
|
run: echo "ffversion=$(./fastfetch --version-raw)" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: upload artifacts
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: fastfetch-linux
|
||||||
|
path: ./fastfetch-*.*
|
||||||
|
|
||||||
|
macos:
|
||||||
|
name: MacOS
|
||||||
|
runs-on: macos-latest
|
||||||
|
permissions:
|
||||||
|
security-events: write
|
||||||
|
contents: read
|
||||||
|
steps:
|
||||||
|
- name: checkout repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: install required packages
|
||||||
|
run: brew install vulkan-loader molten-vk imagemagick chafa
|
||||||
|
|
||||||
|
- name: Initialize CodeQL
|
||||||
|
uses: github/codeql-action/init@v2
|
||||||
|
with:
|
||||||
|
languages: c
|
||||||
|
|
||||||
|
- name: configure project
|
||||||
|
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
|
||||||
|
|
||||||
|
- name: build project
|
||||||
|
run: cmake --build . --target package
|
||||||
|
|
||||||
|
- name: perform CodeQL analysis
|
||||||
|
uses: github/codeql-action/analyze@v2
|
||||||
|
|
||||||
|
- name: run fastfetch
|
||||||
|
run: time ./fastfetch --disable-linewrap false --hide-cursor false --show-errors true --load-config presets/all
|
||||||
|
|
||||||
|
- name: run flashfetch
|
||||||
|
run: time ./flashfetch
|
||||||
|
|
||||||
|
- name: run tests
|
||||||
|
run: ctest
|
||||||
|
|
||||||
|
- name: upload artifacts
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: fastfetch-macos
|
||||||
|
path: ./fastfetch-*.*
|
||||||
|
|
||||||
|
freebsd:
|
||||||
|
name: FreeBSD
|
||||||
|
runs-on: macos-12
|
||||||
|
permissions:
|
||||||
|
security-events: write
|
||||||
|
contents: read
|
||||||
|
steps:
|
||||||
|
- name: checkout repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: run VM
|
||||||
|
uses: vmactions/freebsd-vm@v0
|
||||||
|
with:
|
||||||
|
prepare: |
|
||||||
|
pkg install -y cmake git pkgconf pciutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 glib dconf dbus sqlite3-tcl xfce4-conf ImageMagick6 ImageMagick7 chafa egl libosmesa opencl ocl-icd
|
||||||
|
run: |
|
||||||
|
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
|
||||||
|
cmake --build . --target package
|
||||||
|
time ./fastfetch --disable-linewrap false --hide-cursor false --show-errors true --load-config presets/all
|
||||||
|
time ./flashfetch
|
||||||
|
ctest
|
||||||
|
|
||||||
|
- name: upload artifacts
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: fastfetch-freebsd
|
||||||
|
path: ./fastfetch-*.*
|
||||||
|
|
||||||
|
windows:
|
||||||
|
name: Windows
|
||||||
|
runs-on: windows-latest
|
||||||
|
permissions:
|
||||||
|
security-events: write
|
||||||
|
contents: read
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: msys2 {0}
|
||||||
|
steps:
|
||||||
|
- name: checkout repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: setup-msys2
|
||||||
|
uses: msys2/setup-msys2@v2
|
||||||
|
with:
|
||||||
|
msystem: CLANG64
|
||||||
|
update: true
|
||||||
|
install: git zip mingw-w64-clang-x86_64-cmake mingw-w64-clang-x86_64-clang mingw-w64-clang-x86_64-cjson mingw-w64-clang-x86_64-vulkan-loader mingw-w64-clang-x86_64-opencl-icd
|
||||||
|
|
||||||
|
- name: print msys version
|
||||||
|
run: uname -a
|
||||||
|
|
||||||
|
# https://github.com/msys2/MINGW-packages/issues/13524#event-7555720785
|
||||||
|
- name: create OpenCL.pc
|
||||||
|
run: |
|
||||||
|
cat > /clang64/lib/pkgconfig/OpenCL.pc << EOF
|
||||||
|
prefix=/clang64
|
||||||
|
exec_prefix=${prefix}
|
||||||
|
libdir=${exec_prefix}/lib
|
||||||
|
includedir=${prefix}/include
|
||||||
|
|
||||||
|
Name: OpenCL
|
||||||
|
Description: Open Computing Language generic Installable Client Driver Loader
|
||||||
|
Version: 2022.09.30-1
|
||||||
|
Libs: -L${libdir} -lOpenCL.dll
|
||||||
|
Cflags: -I${includedir}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
- name: Initialize CodeQL
|
||||||
|
uses: github/codeql-action/init@v2
|
||||||
|
with:
|
||||||
|
languages: c, cpp
|
||||||
|
|
||||||
|
- name: configure project
|
||||||
|
run: env PKG_CONFIG_PATH=/clang64/lib/pkgconfig/:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
|
||||||
|
|
||||||
|
- name: build project
|
||||||
|
run: cmake --build .
|
||||||
|
|
||||||
|
- name: perform CodeQL analysis
|
||||||
|
uses: github/codeql-action/analyze@v2
|
||||||
|
|
||||||
|
- name: copy necessary dlls
|
||||||
|
run: cp /clang64/bin/{libcjson,libOpenCL,vulkan-1}.dll .
|
||||||
|
|
||||||
|
- name: run fastfetch
|
||||||
|
run: time ./fastfetch --disable-linewrap false --hide-cursor false --show-errors true --load-config presets/all
|
||||||
|
|
||||||
|
- name: run flashfetch
|
||||||
|
run: time ./flashfetch
|
||||||
|
|
||||||
|
- name: run tests
|
||||||
|
run: ctest
|
||||||
|
|
||||||
|
- name: create zip archive
|
||||||
|
run: zip fastfetch-windows.zip *.dll fastfetch.exe flashfetch.exe
|
||||||
|
|
||||||
|
- name: upload artifacts
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: fastfetch-windows
|
||||||
|
path: ./fastfetch-windows.zip
|
||||||
|
|
||||||
|
windows-old:
|
||||||
|
name: Windows-old
|
||||||
|
runs-on: windows-latest
|
||||||
|
permissions:
|
||||||
|
security-events: write
|
||||||
|
contents: read
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: msys2 {0}
|
||||||
|
steps:
|
||||||
|
- name: checkout repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: setup-msys2
|
||||||
|
uses: msys2/setup-msys2@v2
|
||||||
|
with:
|
||||||
|
msystem: MINGW64
|
||||||
|
update: true
|
||||||
|
install: git zip mingw-w64-x86_64-cmake mingw-w64-x86_64-gcc mingw-w64-x86_64-cjson mingw-w64-x86_64-vulkan-loader mingw-w64-x86_64-opencl-icd
|
||||||
|
|
||||||
|
- name: print msys version
|
||||||
|
run: uname -a
|
||||||
|
|
||||||
|
# https://github.com/msys2/MINGW-packages/issues/13524#event-7555720785
|
||||||
|
- name: create OpenCL.pc
|
||||||
|
run: |
|
||||||
|
cat > /mingw64/lib/pkgconfig/OpenCL.pc << EOF
|
||||||
|
prefix=/mingw64
|
||||||
|
exec_prefix=${prefix}
|
||||||
|
libdir=${exec_prefix}/lib
|
||||||
|
includedir=${prefix}/include
|
||||||
|
|
||||||
|
Name: OpenCL
|
||||||
|
Description: Open Computing Language generic Installable Client Driver Loader
|
||||||
|
Version: 2022.09.30-1
|
||||||
|
Libs: -L${libdir} -lOpenCL.dll
|
||||||
|
Cflags: -I${includedir}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
- name: Initialize CodeQL
|
||||||
|
uses: github/codeql-action/init@v2
|
||||||
|
with:
|
||||||
|
languages: c, cpp
|
||||||
|
|
||||||
|
- name: configure project
|
||||||
|
run: env PKG_CONFIG_PATH=/mingw64/lib/pkgconfig/:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_BUFFER=Off .
|
||||||
|
|
||||||
|
- name: build project
|
||||||
|
run: cmake --build .
|
||||||
|
|
||||||
|
- name: perform CodeQL analysis
|
||||||
|
uses: github/codeql-action/analyze@v2
|
||||||
|
|
||||||
|
- name: copy necessary dlls
|
||||||
|
run: cp /mingw64/bin/{libcjson,libOpenCL,vulkan-1}.dll .
|
||||||
|
|
||||||
|
- name: run fastfetch
|
||||||
|
run: time ./fastfetch --disable-linewrap false --hide-cursor false --show-errors true --load-config presets/all
|
||||||
|
|
||||||
|
- name: run flashfetch
|
||||||
|
run: time ./flashfetch
|
||||||
|
|
||||||
|
- name: run tests
|
||||||
|
run: ctest
|
||||||
|
|
||||||
|
- name: create zip archive
|
||||||
|
run: zip fastfetch-windows-old.zip *.dll fastfetch.exe flashfetch.exe
|
||||||
|
|
||||||
|
- name: upload artifacts
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: fastfetch-windows-old
|
||||||
|
path: ./fastfetch-windows-old.zip
|
||||||
|
|
||||||
|
release:
|
||||||
|
if: github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'LinusDierheimer/fastfetch'
|
||||||
|
name: Release
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs:
|
||||||
|
- linux
|
||||||
|
- macos
|
||||||
|
- freebsd
|
||||||
|
- windows
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
steps:
|
||||||
|
- name: download artifacts
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
|
||||||
|
- name: get latest release version
|
||||||
|
id: get_version_release
|
||||||
|
uses: pozetroninc/github-action-get-latest-release@master
|
||||||
|
with:
|
||||||
|
repository: ${{ github.repository }}
|
||||||
|
|
||||||
|
- name: create release
|
||||||
|
if: needs.linux.outputs.ffversion != steps.get_version_release.outputs.release
|
||||||
|
uses: ncipollo/release-action@v1
|
||||||
|
with:
|
||||||
|
tag: ${{ needs.linux.outputs.ffversion }}
|
||||||
|
commit: ${{ github.sha }}
|
||||||
|
artifactErrorsFailBuild: true
|
||||||
|
artifacts: fastfetch-linux/*,fastfetch-macos/*,fastfetch-freebsd/*,fastfetch-windows/*
|
||||||
+9
-3
@@ -1,3 +1,9 @@
|
|||||||
/.cache
|
**/build/
|
||||||
/.vscode
|
**/.vscode/
|
||||||
/build*
|
**/.cache/
|
||||||
|
**/.kdev4/
|
||||||
|
**/.DS_Store
|
||||||
|
/.vs
|
||||||
|
cscope.*
|
||||||
|
tags
|
||||||
|
fastfetch.kdev4
|
||||||
|
|||||||
+221
@@ -0,0 +1,221 @@
|
|||||||
|
# 1.8.1
|
||||||
|
|
||||||
|
Notable Changes:
|
||||||
|
|
||||||
|
* `Song` was used as an alias to `Media` module. It's removed to avoid confusion. All song related flags (`--song-key`, etc) should change to media (`--media-key`, etc). (@CarterLi)
|
||||||
|
|
||||||
|
Bugfixes:
|
||||||
|
|
||||||
|
* Mountpoint paths on linux get decoded correctly (#364)
|
||||||
|
* Color parsing once again works (@IanManske, #365)
|
||||||
|
* Using a custom key with a placeholder for the local ip module now does work correctly if multiple interfaces are present (#368)
|
||||||
|
|
||||||
|
# 1.8.0
|
||||||
|
|
||||||
|
This release introduces Windows support! Fastfetch now fully support all major desktop OSes (Linux, macOS, Windows and FreeBSD)
|
||||||
|
|
||||||
|
Notable Changes:
|
||||||
|
* Bios / Board / Chassis modules are splitted against Host module for performance reasons
|
||||||
|
* Caching is removed. Option `--nocache` is removed accordingly
|
||||||
|
|
||||||
|
Features:
|
||||||
|
* Windows (7 and newer) is officially and fully supported
|
||||||
|
* FreeBSD support is improved greatly (Bios, Cpu Temp, Cpu Usage, Disk, Host, Processes, Swap, Terminal / Shell, Uptime)
|
||||||
|
* Adds a new flag `--stat`, which prints time usage for individual modules
|
||||||
|
* Adds Wifi module which supports Windows and macOS
|
||||||
|
* Adds data source option for logo printing
|
||||||
|
* Detects Homebrew Cellar and Cask seperately
|
||||||
|
* Detects WSL version
|
||||||
|
* Detects disk based on mount point
|
||||||
|
* Exposes more chafa configs
|
||||||
|
* Improves performance for Cpu Usage, Public IP, Weather modules
|
||||||
|
* Improves performance for Kitty image protocol when both image width / height specified
|
||||||
|
* Improves performance for large file loading
|
||||||
|
* Improves performance for macOS WM and Host detection
|
||||||
|
* Improves shell and terminal detection on macOS
|
||||||
|
* Supports Deepin Terminal terminal font
|
||||||
|
* Supports GPU detection on Android
|
||||||
|
* Supports Kitty Terminal terminal font
|
||||||
|
* Supports bar output for percentage values
|
||||||
|
* Supports Bios module on macOS
|
||||||
|
* Supports eopkg package manager detection
|
||||||
|
* Supports iTerm image logo protocol
|
||||||
|
* Supports image logo printing on macOS
|
||||||
|
* Supports tcsh version detection
|
||||||
|
* Vulkan module on macOS no longer requires vulkan-loader to work
|
||||||
|
|
||||||
|
Logos:
|
||||||
|
* Alpine
|
||||||
|
* CRUX
|
||||||
|
* EndeavourOS
|
||||||
|
* Enso
|
||||||
|
* Garuda small
|
||||||
|
* Nobara
|
||||||
|
* OpenMandriva
|
||||||
|
* Parabola GNU/Linux-libre
|
||||||
|
* Rocky
|
||||||
|
* Rosa
|
||||||
|
* Solus
|
||||||
|
* Univalent
|
||||||
|
* Vanilla OS
|
||||||
|
|
||||||
|
Bugfixes:
|
||||||
|
* Fixes disk size detection on 32bit Linux (#337)
|
||||||
|
* Fixes cpu freq detection in WSL
|
||||||
|
* Fixes internal bug of FFstrbuf
|
||||||
|
* Fixes some memory leaks
|
||||||
|
* Fixes segfault if 0 is given as argument index
|
||||||
|
* Lots of code refactors
|
||||||
|
|
||||||
|
# 1.7.5
|
||||||
|
|
||||||
|
Fixes a crash on linux that could happen when getting zsh version (#285)
|
||||||
|
|
||||||
|
# 1.7.4
|
||||||
|
|
||||||
|
The last element in the default structure (currently the color blocks) is now printed again (#283)
|
||||||
|
|
||||||
|
# 1.7.3
|
||||||
|
|
||||||
|
A lot of small improvements for MacOS & BSD platforms.
|
||||||
|
|
||||||
|
Features:
|
||||||
|
* BSD is now officially supported (#228)
|
||||||
|
* MacPorts package manager support (@SladeGetz, #234)
|
||||||
|
* Battery support for MacOS (@CarterLi, #235)
|
||||||
|
* Processes, swap & terminal font support for MacOS(@CarterLi, #237)
|
||||||
|
* Media support for MacOS (@CarterLi, #242)
|
||||||
|
* Player support for MacOS (@CarterLi, #245)
|
||||||
|
* WM theme support for MacOS (@CarterLi, #246)
|
||||||
|
* CPU usage support for MacOS (@CarterLi, #247)
|
||||||
|
* Power Adapter module (@CarterLi, #249)
|
||||||
|
* Windows terminal font for WSL (@CarterLi, #254)
|
||||||
|
* Temps & Font support for MacOS (@CarterLi, #258)
|
||||||
|
* Terminal font support for Termux (@CarterLi, #263)
|
||||||
|
* Weather module (@CarterLi, #266)
|
||||||
|
|
||||||
|
Logos
|
||||||
|
* Crystal linux (@AloneER0, #239)
|
||||||
|
* FreeBSD (@draumaz, #244)
|
||||||
|
* New Ubuntu (@AloneER0, #259)
|
||||||
|
|
||||||
|
Bugfixes:
|
||||||
|
* Don't segfault in GPU code on Intel Macs (@CarterLi, #236)
|
||||||
|
* Don't use hardcoded size units in presets (@dr460nf1r3, #255)
|
||||||
|
* Don't crash with some format strings (#252)
|
||||||
|
* --logo-none keeps key color now (#264)
|
||||||
|
|
||||||
|
# 1.7.2
|
||||||
|
|
||||||
|
Fixes the bash completions
|
||||||
|
|
||||||
|
# 1.7.1
|
||||||
|
|
||||||
|
This release brings a lot of bug fixes and improvements for MacOS. Big thanks to @CarterLi for the help on this!
|
||||||
|
|
||||||
|
Features:
|
||||||
|
* The color of the title and the keys can now be configured individually, using `--color-keys` and `--color-title` respectively. Some distros have different defaults now, similar to neofetch
|
||||||
|
* Swap module, similar to the Memory module, but for swap. Add `Swap` to your structure to enable it (#225)
|
||||||
|
|
||||||
|
Logos:
|
||||||
|
* Slackware (#227)
|
||||||
|
|
||||||
|
Bugfixes:
|
||||||
|
* Used disk space is now calculated much more accurately
|
||||||
|
* On Linux, GPU names are no longer truncated, if they are longer than 32 characters (#224)
|
||||||
|
* On Linux, NVIDIA GPUs once again have a proper name
|
||||||
|
|
||||||
|
* On M1 platforms, showing the GPU name no longer crashes the program (#222)
|
||||||
|
* Brew package count does now work on M1 platforms too
|
||||||
|
* The Vulkan module now does work on MacOS too
|
||||||
|
* The OpenGL and OpenCL modules now work on MacOS too (@CarterLi, #226)
|
||||||
|
* The LocalIp module now works on MacOS too (@CarterLi, #232)
|
||||||
|
* Detecting custom WMs on MacOS does now work
|
||||||
|
|
||||||
|
Other:
|
||||||
|
* GitHub actions now builds a dmg file for MacOS, as you can see in the release page
|
||||||
|
|
||||||
|
# 1.7.0
|
||||||
|
|
||||||
|
This release brings support for MacOS!
|
||||||
|
The basics things are working, but it is far from feature parity with Linux.
|
||||||
|
I developed this in a VM, so bugs on real hardware are likely.
|
||||||
|
If you have a Mac and no idea what to do with your free time, i am very happy to accept pull requests / work on issues.
|
||||||
|
|
||||||
|
A lot of things were changed under the hood to make this possible, which should bring better performance and stability on all platforms.
|
||||||
|
|
||||||
|
Besides that, the following things have changed:
|
||||||
|
|
||||||
|
Features:
|
||||||
|
* The binary prefix used can now be configured, and is used consistently across all modules. Set `--binary-prefix` to `iec` (default), `si` or `jedec`.
|
||||||
|
* AMD GPUs now have a much better name, if the file `/usr/share/libdrm/amdgpu.ids` exists. For example my dedicated GPU, which was displayed as `AMD/ATI Radeon RX 5600 OEM/5600 XT / 5700/5700 XT`, is now `AMD Radeon RX 5600M`.
|
||||||
|
|
||||||
|
Logos:
|
||||||
|
* MacOS
|
||||||
|
* CachyOS small (@sirlucjan, #220)
|
||||||
|
* MSYS2 (#219)
|
||||||
|
|
||||||
|
Bugfixes:
|
||||||
|
* the `--file` option, which can be used to display the contents of a file as the logo, is now working again.
|
||||||
|
|
||||||
|
# 1.6.5
|
||||||
|
|
||||||
|
Fixes parsing quoted values in config files
|
||||||
|
|
||||||
|
# 1.6.4
|
||||||
|
|
||||||
|
Releasing this, so fedora can package fastfetch. Thanks to @jonathanspw for doing that!
|
||||||
|
|
||||||
|
Features:
|
||||||
|
* --set-keyless option (#215)
|
||||||
|
* Replace `\n`, `\t`, `\e` and `\\` in user provided strings, just like c would do it (#215)
|
||||||
|
* APK (Alpine Package Keeper) support (@mxkrsv, #216)
|
||||||
|
|
||||||
|
Logos:
|
||||||
|
* Alma Linux (@jonathanspw, #214)
|
||||||
|
|
||||||
|
Bugfixes:
|
||||||
|
* replace deprecated gethostbyname call with getaddrinfo (#217)
|
||||||
|
|
||||||
|
# 1.6.3
|
||||||
|
|
||||||
|
Fixes installing presets in their own directory (@ceamac, #212)
|
||||||
|
|
||||||
|
# 1.6.2
|
||||||
|
|
||||||
|
Releasing this, so void linux can package fastfetch.
|
||||||
|
|
||||||
|
Logos:
|
||||||
|
* Rosa linux (#206)
|
||||||
|
* KISS linux (@draumaz, #207)
|
||||||
|
* LangitKetujuh (@hervyqa, #208)
|
||||||
|
|
||||||
|
Bugfixes:
|
||||||
|
* Using musl as libc does work now (#210)
|
||||||
|
* XBPS packages are once again printed (#209)
|
||||||
|
* configured target dirs are applied to install directories too
|
||||||
|
* empty XDG_* env vars don't cause a crash anymore
|
||||||
|
|
||||||
|
# 1.6.1
|
||||||
|
|
||||||
|
Fixes build on android (#205)
|
||||||
|
|
||||||
|
# 1.6.0
|
||||||
|
|
||||||
|
Features:
|
||||||
|
* Detect QT on more DEs than just KDE Plasma. The [Plasma] category was therefore renamed to [QT]
|
||||||
|
* Alacritty font detection
|
||||||
|
* Load `/etc/fastfetch/config.conf` before user config
|
||||||
|
* Disk: print one decimal point if size < 100GB
|
||||||
|
* `--title-fqdn` option, to print fully qualified domain name instead of host name in title
|
||||||
|
|
||||||
|
Logos:
|
||||||
|
* updated old NixOS logo
|
||||||
|
|
||||||
|
Bugfixes:
|
||||||
|
* Correctly detect GTK on DEs that store their settings in dconf
|
||||||
|
* Correctly detect NixOS packages
|
||||||
|
* Mutter WM detected once again
|
||||||
|
* Show full NixOS version in OS output
|
||||||
|
* Don't segfault if an invalid structure is given
|
||||||
|
* WSL doesn't output GPU anymore, as the name is always meaningless
|
||||||
+807
@@ -0,0 +1,807 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
|
||||||
|
|
||||||
|
project(fastfetch
|
||||||
|
VERSION 1.8.1
|
||||||
|
LANGUAGES C
|
||||||
|
DESCRIPTION "Fast system information tool"
|
||||||
|
HOMEPAGE_URL "https://github.com/LinusDierheimer/fastfetch"
|
||||||
|
)
|
||||||
|
|
||||||
|
set(PROJECT_LICENSE "MIT license")
|
||||||
|
|
||||||
|
###################
|
||||||
|
# Target Platform #
|
||||||
|
###################
|
||||||
|
if(ANDROID)
|
||||||
|
set(LINUX FALSE)
|
||||||
|
elseif("${CMAKE_SYSTEM_NAME}" MATCHES ".*[Ll]inux.*")
|
||||||
|
set(LINUX TRUE CACHE BOOL "..." FORCE) # LINUX means GNU/Linux, not just the kernel
|
||||||
|
elseif("${CMAKE_SYSTEM_NAME}" MATCHES ".*[Bb][Ss][Dd].*")
|
||||||
|
set(BSD TRUE CACHE BOOL "..." FORCE)
|
||||||
|
elseif(NOT APPLE AND NOT WIN32)
|
||||||
|
message(FATAL_ERROR "Unsupported platform: ${CMAKE_SYSTEM_NAME}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
enable_language(CXX)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#############################
|
||||||
|
# Compile time dependencies #
|
||||||
|
#############################
|
||||||
|
|
||||||
|
set(THREADS_PREFER_PTHREAD_FLAG NOT WIN32)
|
||||||
|
find_package(Threads)
|
||||||
|
|
||||||
|
find_package(PkgConfig)
|
||||||
|
if(NOT PKG_CONFIG_FOUND)
|
||||||
|
message(WARNING "pkg-config not found, library detection might be limited")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include(CheckIncludeFile)
|
||||||
|
|
||||||
|
#####################
|
||||||
|
# Configure options #
|
||||||
|
#####################
|
||||||
|
|
||||||
|
include(CMakeDependentOption)
|
||||||
|
|
||||||
|
cmake_dependent_option(ENABLE_LIBPCI "Enable libpci" ON "LINUX OR BSD" OFF)
|
||||||
|
cmake_dependent_option(ENABLE_VULKAN "Enable vulkan" ON "LINUX OR APPLE OR BSD OR WIN32 OR ANDROID" OFF)
|
||||||
|
cmake_dependent_option(ENABLE_WAYLAND "Enable wayland-client" ON "LINUX OR BSD" OFF)
|
||||||
|
cmake_dependent_option(ENABLE_XCB_RANDR "Enable xcb-randr" ON "LINUX OR BSD" OFF)
|
||||||
|
cmake_dependent_option(ENABLE_XCB "Enable xcb" ON "LINUX OR BSD" OFF)
|
||||||
|
cmake_dependent_option(ENABLE_XRANDR "Enable xrandr" ON "LINUX OR BSD" OFF)
|
||||||
|
cmake_dependent_option(ENABLE_X11 "Enable x11" ON "LINUX OR BSD" OFF)
|
||||||
|
cmake_dependent_option(ENABLE_GIO "Enable gio-2.0" ON "LINUX OR BSD" OFF)
|
||||||
|
cmake_dependent_option(ENABLE_DCONF "Enable dconf" ON "LINUX OR BSD" OFF)
|
||||||
|
cmake_dependent_option(ENABLE_DBUS "Enable dbus-1" ON "LINUX OR BSD" OFF)
|
||||||
|
cmake_dependent_option(ENABLE_XFCONF "Enable libxfconf-0" ON "LINUX OR BSD" OFF)
|
||||||
|
cmake_dependent_option(ENABLE_SQLITE3 "Enable sqlite3" ON "LINUX OR BSD" OFF)
|
||||||
|
cmake_dependent_option(ENABLE_RPM "Enable rpm" ON "LINUX" OFF)
|
||||||
|
cmake_dependent_option(ENABLE_IMAGEMAGICK7 "Enable imagemagick 7" ON "LINUX OR BSD OR APPLE OR WIN32" OFF)
|
||||||
|
cmake_dependent_option(ENABLE_IMAGEMAGICK6 "Enable imagemagick 6" ON "LINUX OR BSD OR APPLE" OFF)
|
||||||
|
cmake_dependent_option(ENABLE_CHAFA "Enable chafa" ON "ENABLE_IMAGEMAGICK6 OR ENABLE_IMAGEMAGICK7" OFF)
|
||||||
|
cmake_dependent_option(ENABLE_ZLIB "Enable zlib" ON "ENABLE_IMAGEMAGICK6 OR ENABLE_IMAGEMAGICK7" OFF)
|
||||||
|
cmake_dependent_option(ENABLE_EGL "Enable egl" ON "LINUX OR BSD" OFF)
|
||||||
|
cmake_dependent_option(ENABLE_GLX "Enable glx" ON "LINUX OR BSD" OFF)
|
||||||
|
cmake_dependent_option(ENABLE_OSMESA "Enable osmesa" ON "LINUX OR BSD" OFF)
|
||||||
|
cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR BSD OR WIN32" OFF)
|
||||||
|
cmake_dependent_option(ENABLE_LIBCJSON "Enable libcjson" ON "LINUX OR WIN32" OFF)
|
||||||
|
cmake_dependent_option(ENABLE_FREETYPE "Enable freetype" ON "ANDROID" OFF)
|
||||||
|
cmake_dependent_option(ENABLE_THREADS "Enable multithreading" ON "Threads_FOUND AND NOT ANDROID" OFF)
|
||||||
|
cmake_dependent_option(ENABLE_BUFFER "Enable stdout buffer" ON "LINUX OR APPLE OR BSD OR WIN32 OR ANDROID" OFF)
|
||||||
|
cmake_dependent_option(USE_WIN_NTAPI "Allow using internal NTAPI" ON "WIN32" OFF)
|
||||||
|
cmake_dependent_option(USE_WIN_GPU_DXGI "Use DXGI to detect GPUs instead of WMI. Faster, but may ignore GPUs that only support DX9" ON "WIN32" OFF)
|
||||||
|
|
||||||
|
option(BUILD_TESTS "Build tests" OFF) # Also create test executables
|
||||||
|
option(SET_TWEAK "Add tweak to project version" ON) # This is set to off by github actions for release builds
|
||||||
|
|
||||||
|
####################
|
||||||
|
# Compiler options #
|
||||||
|
####################
|
||||||
|
|
||||||
|
if(NOT CMAKE_BUILD_TYPE)
|
||||||
|
set(CMAKE_BUILD_TYPE Release)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
|
||||||
|
if(ENABLE_THREADS)
|
||||||
|
if(CMAKE_USE_WIN32_THREADS_INIT)
|
||||||
|
message(STATUS "Threads type: Win32 thread")
|
||||||
|
elseif(CMAKE_USE_PTHREADS_INIT)
|
||||||
|
message(STATUS "Threads type: pthread")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
message(STATUS "Threads type: disabled")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(CMAKE_C_STANDARD 11)
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wconversion")
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wconversion -fno-exceptions -fno-rtti")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Used for dlopen finding dylibs installed by homebrew
|
||||||
|
# `/opt/homebrew/lib` is not on in dlopen search path by default
|
||||||
|
if(APPLE AND DEFINED ENV{HOMEBREW_PREFIX})
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath,$ENV{HOMEBREW_PREFIX}/lib")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(FASTFETCH_FLAGS_DEBUG "-fno-omit-frame-pointer")
|
||||||
|
if(NOT WIN32)
|
||||||
|
set(FASTFETCH_FLAGS_DEBUG "${FASTFETCH_FLAGS_DEBUG} -fsanitize=address -fsanitize=undefined")
|
||||||
|
endif()
|
||||||
|
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${FASTFETCH_FLAGS_DEBUG}")
|
||||||
|
set(CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} ${FASTFETCH_FLAGS_DEBUG} -rdynamic")
|
||||||
|
|
||||||
|
if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||||
|
include(CheckIPOSupported)
|
||||||
|
check_ipo_supported(RESULT IPO_SUPPORTED)
|
||||||
|
if(IPO_SUPPORTED)
|
||||||
|
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#######################
|
||||||
|
# Target FS structure #
|
||||||
|
#######################
|
||||||
|
|
||||||
|
if(NOT TARGET_DIR_ROOT)
|
||||||
|
if(NOT ANDROID)
|
||||||
|
set(TARGET_DIR_ROOT "")
|
||||||
|
else()
|
||||||
|
set(TARGET_DIR_ROOT "/data/data/com.termux/files/usr")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT TARGET_DIR_USR)
|
||||||
|
if(NOT ANDROID)
|
||||||
|
set(TARGET_DIR_USR "${TARGET_DIR_ROOT}/usr")
|
||||||
|
else()
|
||||||
|
set(TARGET_DIR_USR "${TARGET_DIR_ROOT}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT TARGET_DIR_HOME)
|
||||||
|
if(APPLE)
|
||||||
|
set(TARGET_DIR_HOME "${TARGET_DIR_ROOT}/Users")
|
||||||
|
elseif(ANDROID)
|
||||||
|
set(TARGET_DIR_HOME "/data/data/com.termux/files/home")
|
||||||
|
else()
|
||||||
|
set(TARGET_DIR_HOME "${TARGET_DIR_ROOT}/home")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT TARGET_DIR_ETC)
|
||||||
|
set(TARGET_DIR_ETC "${TARGET_DIR_ROOT}/etc")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#https://cmake.org/cmake/help/latest/variable/CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT.html
|
||||||
|
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||||
|
set(CMAKE_INSTALL_PREFIX "${TARGET_DIR_USR}" CACHE PATH "..." FORCE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT CMAKE_INSTALL_SYSCONFDIR)
|
||||||
|
set(CMAKE_INSTALL_SYSCONFDIR "${TARGET_DIR_ETC}" CACHE PATH "..." FORCE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#################
|
||||||
|
# Tweak version #
|
||||||
|
#################
|
||||||
|
|
||||||
|
if (SET_TWEAK AND EXISTS "${CMAKE_SOURCE_DIR}/.git")
|
||||||
|
execute_process(
|
||||||
|
COMMAND git describe --tags
|
||||||
|
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||||
|
OUTPUT_VARIABLE PROJECT_VERSION_TWEAK
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
)
|
||||||
|
string(REGEX MATCH "-[0-9]+" PROJECT_VERSION_TWEAK "${PROJECT_VERSION_TWEAK}")
|
||||||
|
endif()
|
||||||
|
if(PROJECT_VERSION_TWEAK)
|
||||||
|
string(REGEX MATCH "[0-9]+" PROJECT_VERSION_TWEAK_NUM "${PROJECT_VERSION_TWEAK}")
|
||||||
|
else()
|
||||||
|
set(PROJECT_VERSION_TWEAK_NUM 0)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#############
|
||||||
|
# Text data #
|
||||||
|
#############
|
||||||
|
|
||||||
|
function(fastfetch_load_text FILENAME OUTVAR)
|
||||||
|
file(READ "${FILENAME}" TEMP)
|
||||||
|
string(REGEX REPLACE "\n$" "" TEMP "${TEMP}") # Remove trailing newline
|
||||||
|
string(REPLACE "\n" "\\n" TEMP "${TEMP}") # Replace newlines with \n
|
||||||
|
string(REPLACE "\"" "\\\"" TEMP "${TEMP}") # Replace quotes with \"
|
||||||
|
string(REPLACE "$\\" "" TEMP "${TEMP}") # Remove $\, so we can unescape some things
|
||||||
|
set("${OUTVAR}" "${TEMP}" PARENT_SCOPE)
|
||||||
|
endfunction(fastfetch_load_text)
|
||||||
|
|
||||||
|
fastfetch_load_text(src/data/structure.txt DATATEXT_STRUCTURE)
|
||||||
|
fastfetch_load_text(src/data/config_system.txt DATATEXT_CONFIG_SYSTEM)
|
||||||
|
fastfetch_load_text(src/data/config_user.txt DATATEXT_CONFIG_USER)
|
||||||
|
fastfetch_load_text(src/data/modules.txt DATATEXT_MODULES)
|
||||||
|
fastfetch_load_text(src/data/help.txt DATATEXT_HELP)
|
||||||
|
fastfetch_load_text(src/data/help_color.txt DATATEXT_HELP_COLOR)
|
||||||
|
fastfetch_load_text(src/data/help_format.txt DATATEXT_HELP_FORMAT)
|
||||||
|
fastfetch_load_text(src/data/help_config.txt DATATEXT_HELP_CONFIG)
|
||||||
|
|
||||||
|
######################
|
||||||
|
# Configure config.h #
|
||||||
|
######################
|
||||||
|
|
||||||
|
configure_file(src/fastfetch_config.h.in fastfetch_config.h)
|
||||||
|
|
||||||
|
#######################
|
||||||
|
# libfastfetch target #
|
||||||
|
#######################
|
||||||
|
|
||||||
|
set(LIBFASTFETCH_SRC
|
||||||
|
src/common/bar.c
|
||||||
|
src/common/font.c
|
||||||
|
src/common/format.c
|
||||||
|
src/common/init.c
|
||||||
|
src/common/io.c
|
||||||
|
src/common/library.c
|
||||||
|
src/common/parsing.c
|
||||||
|
src/common/printing.c
|
||||||
|
src/common/properties.c
|
||||||
|
src/common/settings.c
|
||||||
|
src/detection/cpu/cpu.c
|
||||||
|
src/detection/cpuUsage/cpuUsage.c
|
||||||
|
src/detection/datetime.c
|
||||||
|
src/detection/disk/disk.c
|
||||||
|
src/detection/displayserver/displayserver.c
|
||||||
|
src/detection/font/font.c
|
||||||
|
src/detection/gpu/gpu.c
|
||||||
|
src/detection/host/host.c
|
||||||
|
src/detection/locale/locale.c
|
||||||
|
src/detection/media/media.c
|
||||||
|
src/detection/os/os.c
|
||||||
|
src/detection/packages/packages.c
|
||||||
|
src/detection/terminalfont/terminalfont.c
|
||||||
|
src/detection/terminalshell/terminalshell.c
|
||||||
|
src/detection/title.c
|
||||||
|
src/detection/vulkan.c
|
||||||
|
src/logo/builtin.c
|
||||||
|
src/logo/image/im6.c
|
||||||
|
src/logo/image/im7.c
|
||||||
|
src/logo/image/image.c
|
||||||
|
src/logo/logo.c
|
||||||
|
src/modules/battery.c
|
||||||
|
src/modules/bios.c
|
||||||
|
src/modules/board.c
|
||||||
|
src/modules/break.c
|
||||||
|
src/modules/chassis.c
|
||||||
|
src/modules/colors.c
|
||||||
|
src/modules/cpu.c
|
||||||
|
src/modules/cpuUsage.c
|
||||||
|
src/modules/cursor.c
|
||||||
|
src/modules/custom.c
|
||||||
|
src/modules/date.c
|
||||||
|
src/modules/datetime.c
|
||||||
|
src/modules/de.c
|
||||||
|
src/modules/disk.c
|
||||||
|
src/modules/font.c
|
||||||
|
src/modules/gpu.c
|
||||||
|
src/modules/host.c
|
||||||
|
src/modules/icons.c
|
||||||
|
src/modules/kernel.c
|
||||||
|
src/modules/locale.c
|
||||||
|
src/modules/localip.c
|
||||||
|
src/modules/memory.c
|
||||||
|
src/modules/opencl.c
|
||||||
|
src/modules/opengl.c
|
||||||
|
src/modules/os.c
|
||||||
|
src/modules/packages.c
|
||||||
|
src/modules/player.c
|
||||||
|
src/modules/poweradapter.c
|
||||||
|
src/modules/processes.c
|
||||||
|
src/modules/publicip.c
|
||||||
|
src/modules/resolution.c
|
||||||
|
src/modules/separator.c
|
||||||
|
src/modules/shell.c
|
||||||
|
src/modules/media.c
|
||||||
|
src/modules/terminal.c
|
||||||
|
src/modules/terminalfont.c
|
||||||
|
src/modules/theme.c
|
||||||
|
src/modules/time.c
|
||||||
|
src/modules/title.c
|
||||||
|
src/modules/uptime.c
|
||||||
|
src/modules/users.c
|
||||||
|
src/modules/vulkan.c
|
||||||
|
src/modules/weather.c
|
||||||
|
src/modules/wifi.c
|
||||||
|
src/modules/wm.c
|
||||||
|
src/modules/wmtheme.c
|
||||||
|
src/util/FFlist.c
|
||||||
|
src/util/FFstrbuf.c
|
||||||
|
src/util/FFvaluestore.c
|
||||||
|
)
|
||||||
|
|
||||||
|
if(LINUX)
|
||||||
|
list(APPEND LIBFASTFETCH_SRC
|
||||||
|
src/common/networking_linux.c
|
||||||
|
src/common/processing_linux.c
|
||||||
|
src/detection/battery/battery_linux.c
|
||||||
|
src/detection/bios/bios_linux.c
|
||||||
|
src/detection/board/board_linux.c
|
||||||
|
src/detection/chassis/chassis_linux.c
|
||||||
|
src/detection/cpu/cpu_linux.c
|
||||||
|
src/detection/cpuUsage/cpuUsage_linux.c
|
||||||
|
src/detection/cursor/cursor_linux.c
|
||||||
|
src/detection/disk/disk_linux.c
|
||||||
|
src/detection/displayserver/linux/displayserver_linux.c
|
||||||
|
src/detection/displayserver/linux/wayland.c
|
||||||
|
src/detection/displayserver/linux/wmde.c
|
||||||
|
src/detection/displayserver/linux/xcb.c
|
||||||
|
src/detection/displayserver/linux/xlib.c
|
||||||
|
src/detection/font/font_linux.c
|
||||||
|
src/detection/gpu/gpu_linux.c
|
||||||
|
src/detection/gtk.c
|
||||||
|
src/detection/host/host_linux.c
|
||||||
|
src/detection/localip/localip_linux.c
|
||||||
|
src/detection/media/media_linux.c
|
||||||
|
src/detection/memory/memory_linux.c
|
||||||
|
src/detection/opengl/opengl_linux.c
|
||||||
|
src/detection/os/os_linux.c
|
||||||
|
src/detection/packages/packages_linux.c
|
||||||
|
src/detection/poweradapter/poweradapter_nosupport.c
|
||||||
|
src/detection/processes/processes_linux.c
|
||||||
|
src/detection/qt.c
|
||||||
|
src/detection/swap/swap_linux.c
|
||||||
|
src/detection/temps/temps_linux.c
|
||||||
|
src/detection/terminalfont/terminalfont_linux.c
|
||||||
|
src/detection/terminalshell/terminalshell_linux.c
|
||||||
|
src/detection/uptime/uptime_linux.c
|
||||||
|
src/detection/users/users_linux.c
|
||||||
|
src/detection/wifi/wifi_linux.c
|
||||||
|
src/detection/wmtheme/wmtheme_linux.c
|
||||||
|
)
|
||||||
|
elseif(ANDROID)
|
||||||
|
list(APPEND LIBFASTFETCH_SRC
|
||||||
|
src/common/networking_linux.c
|
||||||
|
src/common/processing_linux.c
|
||||||
|
src/detection/battery/battery_nosupport.c
|
||||||
|
src/detection/bios/bios_nosupport.c
|
||||||
|
src/detection/board/board_nosupport.c
|
||||||
|
src/detection/chassis/chassis_nosupport.c
|
||||||
|
src/detection/cpu/cpu_linux.c
|
||||||
|
src/detection/cursor/cursor_nosupport.c
|
||||||
|
src/detection/cpuUsage/cpuUsage_linux.c
|
||||||
|
src/detection/disk/disk_linux.c
|
||||||
|
src/detection/displayserver/displayserver_nosupport.c
|
||||||
|
src/detection/font/font_nosupport.c
|
||||||
|
src/detection/gpu/gpu_nosupport.c
|
||||||
|
src/detection/host/host_android.c
|
||||||
|
src/detection/localip/localip_linux.c
|
||||||
|
src/detection/media/media_nosupport.c
|
||||||
|
src/detection/memory/memory_linux.c
|
||||||
|
src/detection/opengl/opengl_linux.c
|
||||||
|
src/detection/os/os_android.c
|
||||||
|
src/detection/packages/packages_linux.c
|
||||||
|
src/detection/poweradapter/poweradapter_nosupport.c
|
||||||
|
src/detection/processes/processes_linux.c
|
||||||
|
src/detection/swap/swap_linux.c
|
||||||
|
src/detection/temps/temps_linux.c
|
||||||
|
src/detection/terminalfont/terminalfont_android.c
|
||||||
|
src/detection/terminalshell/terminalshell_linux.c
|
||||||
|
src/detection/uptime/uptime_linux.c
|
||||||
|
src/detection/users/users_linux.c
|
||||||
|
src/detection/wifi/wifi_nosupport.c
|
||||||
|
src/detection/wmtheme/wmtheme_nosupport.c
|
||||||
|
)
|
||||||
|
elseif(BSD)
|
||||||
|
list(APPEND LIBFASTFETCH_SRC
|
||||||
|
src/common/networking_linux.c
|
||||||
|
src/common/processing_linux.c
|
||||||
|
src/common/sysctl.c
|
||||||
|
src/detection/battery/battery_nosupport.c
|
||||||
|
src/detection/bios/bios_bsd.c
|
||||||
|
src/detection/board/board_nosupport.c
|
||||||
|
src/detection/chassis/chassis_nosupport.c
|
||||||
|
src/detection/cpu/cpu_bsd.c
|
||||||
|
src/detection/cpuUsage/cpuUsage_bsd.c
|
||||||
|
src/detection/cursor/cursor_linux.c
|
||||||
|
src/detection/disk/disk_bsd.c
|
||||||
|
src/detection/displayserver/linux/displayserver_linux.c
|
||||||
|
src/detection/displayserver/linux/wayland.c
|
||||||
|
src/detection/displayserver/linux/wmde.c
|
||||||
|
src/detection/displayserver/linux/xcb.c
|
||||||
|
src/detection/displayserver/linux/xlib.c
|
||||||
|
src/detection/font/font_linux.c
|
||||||
|
src/detection/gpu/gpu_linux.c
|
||||||
|
src/detection/gtk.c
|
||||||
|
src/detection/host/host_bsd.c
|
||||||
|
src/detection/localip/localip_linux.c
|
||||||
|
src/detection/media/media_linux.c
|
||||||
|
src/detection/memory/memory_bsd.c
|
||||||
|
src/detection/opengl/opengl_linux.c
|
||||||
|
src/detection/os/os_linux.c
|
||||||
|
src/detection/packages/packages_linux.c
|
||||||
|
src/detection/poweradapter/poweradapter_nosupport.c
|
||||||
|
src/detection/processes/processes_bsd.c
|
||||||
|
src/detection/qt.c
|
||||||
|
src/detection/swap/swap_bsd.c
|
||||||
|
src/detection/temps/temps_linux.c
|
||||||
|
src/detection/terminalfont/terminalfont_linux.c
|
||||||
|
src/detection/terminalshell/terminalshell_linux.c
|
||||||
|
src/detection/uptime/uptime_bsd.c
|
||||||
|
src/detection/users/users_linux.c
|
||||||
|
src/detection/wifi/wifi_nosupport.c
|
||||||
|
src/detection/wmtheme/wmtheme_linux.c
|
||||||
|
)
|
||||||
|
elseif(APPLE)
|
||||||
|
list(APPEND LIBFASTFETCH_SRC
|
||||||
|
src/common/networking_linux.c
|
||||||
|
src/common/processing_linux.c
|
||||||
|
src/common/sysctl.c
|
||||||
|
src/detection/battery/battery_apple.c
|
||||||
|
src/detection/bios/bios_apple.c
|
||||||
|
src/detection/board/board_nosupport.c
|
||||||
|
src/detection/chassis/chassis_nosupport.c
|
||||||
|
src/detection/cpu/cpu_apple.c
|
||||||
|
src/detection/cpuUsage/cpuUsage_apple.c
|
||||||
|
src/detection/cursor/cursor_nosupport.c
|
||||||
|
src/detection/disk/disk_apple.m
|
||||||
|
src/detection/disk/disk_bsd.c
|
||||||
|
src/detection/displayserver/displayserver_apple.c
|
||||||
|
src/detection/font/font_apple.m
|
||||||
|
src/detection/gpu/gpu_apple.c
|
||||||
|
src/detection/host/host_apple.c
|
||||||
|
src/detection/localip/localip_linux.c
|
||||||
|
src/detection/media/media_apple.m
|
||||||
|
src/detection/memory/memory_apple.c
|
||||||
|
src/detection/opengl/opengl_apple.c
|
||||||
|
src/detection/os/os_apple.m
|
||||||
|
src/detection/packages/packages_apple.c
|
||||||
|
src/detection/poweradapter/poweradapter_apple.c
|
||||||
|
src/detection/processes/processes_bsd.c
|
||||||
|
src/detection/swap/swap_apple.c
|
||||||
|
src/detection/temps/temps_apple.c
|
||||||
|
src/detection/terminalfont/terminalfont_apple.m
|
||||||
|
src/detection/terminalshell/terminalshell_linux.c
|
||||||
|
src/detection/uptime/uptime_bsd.c
|
||||||
|
src/detection/users/users_linux.c
|
||||||
|
src/detection/wifi/wifi_apple.m
|
||||||
|
src/detection/wmtheme/wmtheme_apple.m
|
||||||
|
src/util/apple/cf_helpers.c
|
||||||
|
src/util/apple/osascript.m
|
||||||
|
)
|
||||||
|
elseif(WIN32)
|
||||||
|
list(APPEND LIBFASTFETCH_SRC
|
||||||
|
src/common/networking_windows.c
|
||||||
|
src/common/processing_windows.c
|
||||||
|
src/detection/battery/battery_windows.c
|
||||||
|
src/detection/bios/bios_windows.c
|
||||||
|
src/detection/board/board_windows.c
|
||||||
|
src/detection/chassis/chassis_nosupport.c
|
||||||
|
src/detection/cpu/cpu_windows.c
|
||||||
|
src/detection/cpuUsage/cpuUsage_windows.c
|
||||||
|
src/detection/cursor/cursor_windows.c
|
||||||
|
src/detection/disk/disk_windows.c
|
||||||
|
src/detection/displayserver/displayserver_windows.c
|
||||||
|
src/detection/font/font_windows.c
|
||||||
|
src/detection/gpu/gpu_windows.cpp
|
||||||
|
src/detection/host/host_windows.c
|
||||||
|
src/detection/localip/localip_windows.c
|
||||||
|
src/detection/media/media_nosupport.c
|
||||||
|
src/detection/memory/memory_windows.c
|
||||||
|
src/detection/opengl/opengl_windows.c
|
||||||
|
src/detection/os/os_windows.cpp
|
||||||
|
src/detection/packages/packages_windows.c
|
||||||
|
src/detection/poweradapter/poweradapter_nosupport.c
|
||||||
|
src/detection/processes/processes_windows.cpp
|
||||||
|
src/detection/swap/swap_windows.cpp
|
||||||
|
src/detection/terminalfont/terminalfont_windows.c
|
||||||
|
src/detection/terminalshell/terminalshell_windows.cpp
|
||||||
|
src/detection/uptime/uptime_windows.c
|
||||||
|
src/detection/users/users_windows.c
|
||||||
|
src/detection/wifi/wifi_windows.c
|
||||||
|
src/detection/wmtheme/wmtheme_windows.c
|
||||||
|
src/util/windows/getline.c
|
||||||
|
src/util/windows/pwd.c
|
||||||
|
src/util/windows/registry.c
|
||||||
|
src/util/windows/unicode.c
|
||||||
|
src/util/windows/utsname.c
|
||||||
|
src/util/windows/wmi.cpp
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_library(libfastfetch OBJECT
|
||||||
|
${LIBFASTFETCH_SRC}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE)
|
||||||
|
|
||||||
|
CHECK_INCLUDE_FILE("utmpx.h" HAVE_UTMPX_H)
|
||||||
|
if(HAVE_UTMPX_H)
|
||||||
|
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_UTMPX_H)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
function(ff_lib_enable VARNAME PKGCONFIG_NAMES CMAKE_NAME)
|
||||||
|
if(NOT ENABLE_${VARNAME})
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(PKG_CONFIG_FOUND)
|
||||||
|
pkg_search_module(${VARNAME} QUIET ${PKGCONFIG_NAMES})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT ${VARNAME}_FOUND)
|
||||||
|
find_package(${CMAKE_NAME} QUIET)
|
||||||
|
|
||||||
|
set(${VARNAME}_FOUND ${${CMAKE_NAME}_FOUND})
|
||||||
|
set(${VARNAME}_INCLUDE_DIRS ${${CMAKE_NAME}_INCLUDE_DIRS})
|
||||||
|
set(${VARNAME}_LIBRARIES ${${CMAKE_NAME}_LIBRARIES})
|
||||||
|
set(${VARNAME}_CFLAGS_OTHER ${${CMAKE_NAME}_CFLAGS_OTHER})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT ${VARNAME}_FOUND)
|
||||||
|
message(STATUS "Library: missing: ${VARNAME}")
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
message(STATUS "Library: found ${VARNAME}")
|
||||||
|
|
||||||
|
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_${VARNAME}=1)
|
||||||
|
target_include_directories(libfastfetch PRIVATE ${${VARNAME}_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
foreach(FLAG ${${VARNAME}_CFLAGS_OTHER})
|
||||||
|
if(FLAG MATCHES "-D.*")
|
||||||
|
string(SUBSTRING ${FLAG} 2 -1 FLAG)
|
||||||
|
target_compile_definitions(libfastfetch PRIVATE ${FLAG})
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
ff_lib_enable(LIBPCI
|
||||||
|
"libpci"
|
||||||
|
"Pci"
|
||||||
|
)
|
||||||
|
ff_lib_enable(VULKAN
|
||||||
|
"vulkan"
|
||||||
|
"Vulkan"
|
||||||
|
)
|
||||||
|
ff_lib_enable(WAYLAND
|
||||||
|
"wayland-client"
|
||||||
|
"WaylandClient"
|
||||||
|
)
|
||||||
|
ff_lib_enable(XCB_RANDR
|
||||||
|
"xcb-randr"
|
||||||
|
"XcbRandr"
|
||||||
|
)
|
||||||
|
ff_lib_enable(XCB
|
||||||
|
"xcb"
|
||||||
|
"Xcb"
|
||||||
|
)
|
||||||
|
ff_lib_enable(XRANDR
|
||||||
|
"xrandr"
|
||||||
|
"XRandr"
|
||||||
|
)
|
||||||
|
ff_lib_enable(X11
|
||||||
|
"x11"
|
||||||
|
"X11"
|
||||||
|
)
|
||||||
|
ff_lib_enable(GIO
|
||||||
|
"gio-2.0"
|
||||||
|
"GIO"
|
||||||
|
)
|
||||||
|
ff_lib_enable(DCONF
|
||||||
|
"dconf"
|
||||||
|
"DConf"
|
||||||
|
)
|
||||||
|
ff_lib_enable(DBUS
|
||||||
|
"dbus-1"
|
||||||
|
"DBus"
|
||||||
|
)
|
||||||
|
ff_lib_enable(XFCONF
|
||||||
|
"libxfconf-0"
|
||||||
|
"XFConf"
|
||||||
|
)
|
||||||
|
ff_lib_enable(SQLITE3
|
||||||
|
"sqlite3"
|
||||||
|
"SQLite3"
|
||||||
|
)
|
||||||
|
ff_lib_enable(RPM
|
||||||
|
"rpm"
|
||||||
|
"RPM"
|
||||||
|
)
|
||||||
|
ff_lib_enable(IMAGEMAGICK7
|
||||||
|
"MagickCore-7.Q16HDRI;MagickCore-7.Q16;MagickCore-7;/usr/lib/imagemagick7/pkgconfig/MagickCore-7.Q16HDRI.pc;/usr/lib/imagemagick7/pkgconfig/MagickCore-7.Q16.pc;/usr/lib/imagemagick7/pkgconfig/MagickCore-7.pc"
|
||||||
|
"ImageMagick7"
|
||||||
|
)
|
||||||
|
ff_lib_enable(IMAGEMAGICK6
|
||||||
|
"MagickCore-6.Q16HDRI;MagickCore-6.Q16;MagickCore-6;/usr/lib/imagemagick6/pkgconfig/MagickCore-6.Q16HDRI.pc;/usr/lib/imagemagick6/pkgconfig/MagickCore-6.Q16.pc;/usr/lib/imagemagick6/pkgconfig/MagickCore-6.pc"
|
||||||
|
"ImageMagick6"
|
||||||
|
)
|
||||||
|
ff_lib_enable(ZLIB
|
||||||
|
"zlib"
|
||||||
|
"ZLIB"
|
||||||
|
)
|
||||||
|
ff_lib_enable(CHAFA
|
||||||
|
"chafa>=1.10"
|
||||||
|
"Chafa"
|
||||||
|
)
|
||||||
|
ff_lib_enable(EGL
|
||||||
|
"egl"
|
||||||
|
"EGL"
|
||||||
|
)
|
||||||
|
ff_lib_enable(GLX
|
||||||
|
"glx"
|
||||||
|
"GLX"
|
||||||
|
)
|
||||||
|
ff_lib_enable(OSMESA
|
||||||
|
"osmesa"
|
||||||
|
"OSMesa"
|
||||||
|
)
|
||||||
|
ff_lib_enable(OPENCL
|
||||||
|
"OpenCL"
|
||||||
|
"OpenCL"
|
||||||
|
)
|
||||||
|
ff_lib_enable(LIBCJSON
|
||||||
|
"libcjson"
|
||||||
|
"CJson"
|
||||||
|
)
|
||||||
|
ff_lib_enable(FREETYPE
|
||||||
|
"freetype2"
|
||||||
|
"FreeType2"
|
||||||
|
)
|
||||||
|
|
||||||
|
if(ENABLE_THREADS)
|
||||||
|
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_THREADS)
|
||||||
|
if(CMAKE_USE_PTHREADS_INIT) #Threads::Threads is not set for WIN32
|
||||||
|
target_link_libraries(libfastfetch PRIVATE Threads::Threads)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
if(ENABLE_BUFFER)
|
||||||
|
target_compile_definitions(libfastfetch PRIVATE FF_ENABLE_BUFFER)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(APPLE)
|
||||||
|
target_link_libraries(libfastfetch
|
||||||
|
PRIVATE "-framework CoreFoundation"
|
||||||
|
PRIVATE "-framework IOKit"
|
||||||
|
PRIVATE "-framework OpenGL"
|
||||||
|
PRIVATE "-framework OpenCL"
|
||||||
|
PRIVATE "-framework Cocoa"
|
||||||
|
PRIVATE "-framework CoreWLAN"
|
||||||
|
PRIVATE "-weak_framework MediaRemote -F /System/Library/PrivateFrameworks"
|
||||||
|
)
|
||||||
|
elseif(WIN32)
|
||||||
|
target_link_libraries(libfastfetch
|
||||||
|
PRIVATE "dwmapi"
|
||||||
|
PRIVATE "gdi32"
|
||||||
|
PRIVATE "iphlpapi"
|
||||||
|
PRIVATE "ole32"
|
||||||
|
PRIVATE "oleaut32"
|
||||||
|
PRIVATE "opengl32"
|
||||||
|
PRIVATE "wbemuuid"
|
||||||
|
PRIVATE "ws2_32"
|
||||||
|
PRIVATE "ntdll"
|
||||||
|
PRIVATE "version"
|
||||||
|
PRIVATE "setupapi"
|
||||||
|
PRIVATE "dxgi"
|
||||||
|
PRIVATE "wtsapi32"
|
||||||
|
PRIVATE "powrprof"
|
||||||
|
)
|
||||||
|
if(USE_WIN_NTAPI)
|
||||||
|
target_compile_definitions(libfastfetch PRIVATE FF_USE_WIN_NTAPI)
|
||||||
|
endif()
|
||||||
|
if(USE_WIN_GPU_DXGI)
|
||||||
|
target_compile_definitions(libfastfetch PRIVATE FF_USE_WIN_GPU_DXGI)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_include_directories(libfastfetch
|
||||||
|
PUBLIC ${PROJECT_BINARY_DIR}
|
||||||
|
PUBLIC ${PROJECT_SOURCE_DIR}/src
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(libfastfetch
|
||||||
|
PRIVATE ${CMAKE_DL_LIBS}
|
||||||
|
)
|
||||||
|
|
||||||
|
######################
|
||||||
|
# Executable targets #
|
||||||
|
######################
|
||||||
|
|
||||||
|
add_executable(fastfetch
|
||||||
|
src/fastfetch.c
|
||||||
|
)
|
||||||
|
target_compile_definitions(fastfetch
|
||||||
|
PRIVATE FASTFETCH_TARGET_BINARY_NAME=fastfetch
|
||||||
|
)
|
||||||
|
target_link_libraries(fastfetch
|
||||||
|
PRIVATE libfastfetch
|
||||||
|
)
|
||||||
|
|
||||||
|
add_executable(flashfetch
|
||||||
|
src/flashfetch.c
|
||||||
|
)
|
||||||
|
target_compile_definitions(flashfetch
|
||||||
|
PRIVATE FASTFETCH_TARGET_BINARY_NAME=flashfetch
|
||||||
|
)
|
||||||
|
target_link_libraries(flashfetch
|
||||||
|
PRIVATE libfastfetch
|
||||||
|
)
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
set(TARGET_NAME fastfetch)
|
||||||
|
target_sources(fastfetch
|
||||||
|
PRIVATE src/util/windows/version.rc
|
||||||
|
)
|
||||||
|
|
||||||
|
set(TARGET_NAME flashfetch)
|
||||||
|
target_sources(flashfetch
|
||||||
|
PRIVATE src/util/windows/version.rc
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
###################
|
||||||
|
# Testing targets #
|
||||||
|
###################
|
||||||
|
|
||||||
|
if (BUILD_TESTS)
|
||||||
|
add_executable(fastfetch-test-strbuf
|
||||||
|
tests/strbuf.c
|
||||||
|
)
|
||||||
|
target_link_libraries(fastfetch-test-strbuf
|
||||||
|
PRIVATE libfastfetch
|
||||||
|
)
|
||||||
|
|
||||||
|
add_executable(fastfetch-test-list
|
||||||
|
tests/list.c
|
||||||
|
)
|
||||||
|
target_link_libraries(fastfetch-test-list
|
||||||
|
PRIVATE libfastfetch
|
||||||
|
)
|
||||||
|
|
||||||
|
enable_testing()
|
||||||
|
add_test(NAME test-strbuf COMMAND fastfetch-test-strbuf)
|
||||||
|
add_test(NAME test-list COMMAND fastfetch-test-list)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
##################
|
||||||
|
# install target #
|
||||||
|
##################
|
||||||
|
|
||||||
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
|
install(
|
||||||
|
TARGETS fastfetch flashfetch
|
||||||
|
DESTINATION "${CMAKE_INSTALL_BINDIR}"
|
||||||
|
)
|
||||||
|
|
||||||
|
install(
|
||||||
|
FILES "${CMAKE_SOURCE_DIR}/src/data/config_system.txt"
|
||||||
|
DESTINATION "${CMAKE_INSTALL_SYSCONFDIR}/${CMAKE_PROJECT_NAME}"
|
||||||
|
RENAME "config.conf"
|
||||||
|
)
|
||||||
|
|
||||||
|
install(
|
||||||
|
FILES "${CMAKE_SOURCE_DIR}/completions/bash"
|
||||||
|
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/bash-completion/completions"
|
||||||
|
RENAME "${CMAKE_PROJECT_NAME}"
|
||||||
|
)
|
||||||
|
|
||||||
|
install(
|
||||||
|
DIRECTORY "${CMAKE_SOURCE_DIR}/presets"
|
||||||
|
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/${CMAKE_PROJECT_NAME}"
|
||||||
|
)
|
||||||
|
|
||||||
|
install(
|
||||||
|
FILES "${CMAKE_SOURCE_DIR}/LICENSE"
|
||||||
|
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/licenses/${CMAKE_PROJECT_NAME}"
|
||||||
|
)
|
||||||
|
|
||||||
|
##################
|
||||||
|
# package target #
|
||||||
|
##################
|
||||||
|
|
||||||
|
set(CPACK_GENERATOR "TGZ;ZIP")
|
||||||
|
|
||||||
|
if(LINUX)
|
||||||
|
set(CPACK_GENERATOR "${CPACK_GENERATOR};DEB;RPM")
|
||||||
|
|
||||||
|
set(CPACK_DEBIAN_PACKAGE_SECTION, "utils")
|
||||||
|
set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
|
||||||
|
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6")
|
||||||
|
|
||||||
|
set(CPACK_RPM_PACKAGE_LICENSE "MIT")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(CPACK_SET_DESTDIR ON)
|
||||||
|
|
||||||
|
set(CPACK_PACKAGE_CONTACT "Linus Dierheimer <Linus@Dierheimer.de>")
|
||||||
|
set(CPACK_PACKAGE_DESCRIPTION "\
|
||||||
|
fastfetch is a neofetch-like tool for fetching system information and displaying them in a pretty way. \
|
||||||
|
It is written in c to achieve much better performance.\
|
||||||
|
")
|
||||||
|
|
||||||
|
include(CPack)
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
# Development help
|
||||||
|
|
||||||
|
This file is not an official documentation!
|
||||||
|
Here i just add things that are easy to forget.
|
||||||
|
|
||||||
|
## Features i am planning to implement
|
||||||
|
|
||||||
|
### Specific
|
||||||
|
|
||||||
|
- [ ] Split the project in different libs / executables, all linking static by default:
|
||||||
|
- `libffdetect`: contains all the detection stuff. To be used by anything that needs system information
|
||||||
|
- `libffprint`: contains the printing functions, logos, format etc
|
||||||
|
- `fastfetch` and `flashfetch`: Executables, that initialize the config of libffprint. Fist one at runtime, second one at compile time
|
||||||
|
- [ ] Make LocalIP module more configurable
|
||||||
|
- [ ] Automatic migrate old config files to newer versions
|
||||||
|
- [ ] ZSH completions
|
||||||
|
- [ ] Fish completions
|
||||||
|
- [ ] Make CPU usage detection much faster and more accurate
|
||||||
|
- [ ] Detect CPU usage in a common detection methode and expose it both to the cpuUsage module and the cpu format string
|
||||||
|
- [ ] Per session caching
|
||||||
|
|
||||||
|
### General
|
||||||
|
- More presets
|
||||||
|
- More logos
|
||||||
|
- More package managers
|
||||||
|
- More DE detections
|
||||||
|
- More WM theme detections
|
||||||
|
- More terminal font detections
|
||||||
|
- Performance optimizations
|
||||||
|
- More module specific options
|
||||||
|
- Better error handling, especially the messages shown when using --show-errors
|
||||||
|
- Using package managers libraries for package count detection instead own. E.g. using libalpm instead of counting files in /var/lib/pacman/local
|
||||||
|
- Better documentation (especially default config file and the various --help options. Colored output?)
|
||||||
|
- General feature parity with neofetch, to demonstrate supremity of c
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2021 Linus Dierheimer
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
@@ -1,29 +1,160 @@
|
|||||||
# Fastfetch Benchmark Data
|
# Fastfetch
|
||||||
|
|
||||||
This branch stores continuous performance benchmark data for Fastfetch on Linux, macOS, and Windows.
|
Fastfetch is a [neofetch](https://github.com/dylanaraps/neofetch)-like tool for fetching system information and displaying them in a pretty way. It is written in pure c, with performance and customizability in mind. Currently, Linux, Android, FreeBSD, MacOS and Windows 7+ are supported.
|
||||||
|
|
||||||
The data is generated and updated automatically by GitHub Actions. Please do not edit generated benchmark files manually.
|
<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" />
|
||||||
|
<img src="screenshots/example4.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" />
|
||||||
|
<img src="screenshots/example2.png" width="48%" align="top" />
|
||||||
|
<img src="screenshots/example3.png" width="48%" align="top" />
|
||||||
|
<img src="screenshots/example5.png" height="15%" align="top" />
|
||||||
|
|
||||||
## Benchmark Dashboard
|
## Customization
|
||||||
|
|
||||||
<https://fastfetch-cli.github.io/fastfetch/dev/bench/>
|
With customization and speed being two competing goals, this project actually builds two executables.
|
||||||
|
The main one being `fastfetch`, which can be very greatly configured via flags. These flags can be made persistent in `~/.config/fastfetch/config.conf`. To view the available options run `fastfetch --help`.
|
||||||
|
The second executable being built is called `flashfetch`, which is configured at compile time to eliminate any possible overhead. Configuration of it can be very easily done in [`src/flashfetch.c`](src/flashfetch.c).
|
||||||
|
At the moment the performance difference is measurable, but too small to be human recognizable. But the leap will get bigger with more and more options coming, and on slow machines this might actually make a difference.
|
||||||
|
|
||||||
## Metrics
|
There are some premade config files in [`presets`](presets), including the ones used for the screenshots above. You can load them using `--load-config <filename>`. They may also serve as a good example for format arguments.
|
||||||
|
|
||||||
The benchmark data includes:
|
## Dependencies
|
||||||
|
|
||||||
- Execution time for each Fastfetch module, measured in milliseconds;
|
Fastfetch dynamically loads needed libraries if they are available. On Linux, its only hard dependencies are `libc` (any implementation of the c standard library), `libdl` and [`libpthread`](https://man7.org/linux/man-pages/man7/pthreads.7.html) (if built with multithreading support). They are all shipped with [`glibc`](https://www.gnu.org/software/libc/), which is already installed on most linux distributions.
|
||||||
- Total Fastfetch process execution time, measured in milliseconds.
|
|
||||||
|
|
||||||
All metrics use the “smaller is better” comparison mode.
|
|
||||||
|
|
||||||
## Update Workflow
|
The following libraries are used if present at runtime:
|
||||||
|
|
||||||
Benchmark data is generated from the `dev` branch CI workflow and updated after all platform build jobs have completed.
|
### Linux and FreeBSD
|
||||||
|
|
||||||
Related workflow files:
|
* [`libpci`](https://github.com/pciutils/pciutils): GPU output.
|
||||||
|
* [`libvulkan`](https://www.vulkan.org/): Vulkan module & fallback for GPU output.
|
||||||
|
* [`libxcb-randr`](https://xcb.freedesktop.org/),
|
||||||
|
[`libXrandr`](https://gitlab.freedesktop.org/xorg/lib/libxrandr),
|
||||||
|
[`libxcb`](https://xcb.freedesktop.org/),
|
||||||
|
[`libX11`](https://gitlab.freedesktop.org/xorg/lib/libx11): At least one of them sould be present in X11 sessions for better resolution detection and faster WM detection. The `*randr` ones provide multi monitor support The `libxcb*` ones usually have better performance.
|
||||||
|
* [`libwayland-client`](https://wayland.freedesktop.org/): Better resolution performance and output in wayland sessions. Supports different refresh rates per monitor.
|
||||||
|
* [`libGIO`](https://developer.gnome.org/gio/unstable/): Needed for values that are only stored GSettings.
|
||||||
|
* [`libDConf`](https://developer.gnome.org/dconf/unstable/): Needed for values that are only stored in DConf + Fallback for GSettings.
|
||||||
|
* [`libmagickcore` (ImageMagick)](https://www.imagemagick.org/): Images in terminal using sixel or kitty graphics protocol.
|
||||||
|
* [`libchafa`](https://github.com/hpjansson/chafa): Image output as ascii art.
|
||||||
|
* [`libZ`](https://www.zlib.net/): Faster image output when using kitty graphics protocol.
|
||||||
|
* [`libDBus`](https://www.freedesktop.org/wiki/Software/dbus): Needed for detecting current media player and song.
|
||||||
|
* [`libEGL`](https://www.khronos.org/registry/EGL/),
|
||||||
|
[`libGLX`](https://dri.freedesktop.org/wiki/GLX/),
|
||||||
|
[`libOSMesa`](https://docs.mesa3d.org/osmesa.html): At least one of them is needed by the OpenGL module for gl context creation.
|
||||||
|
* [`libOpenCL`](https://www.khronos.org/opencl/): OpenCL module
|
||||||
|
* [`libXFConf`](https://gitlab.xfce.org/xfce/xfconf): Needed for XFWM theme and XFCE Terminal font.
|
||||||
|
* [`libsqlite3`](https://www.sqlite.org/index.html): Needed for pkg & rpm package count.
|
||||||
|
* [`librpm`](http://rpm.org/): Slower fallback for rpm package count. Needed on openSUSE.
|
||||||
|
* [`libcJSON`](https://github.com/DaveGamble/cJSON): Needed for Windows Terminal font ( WSL ).
|
||||||
|
|
||||||
- `.github/workflows/build-benchmark.yml`
|
### macOS
|
||||||
- `.github/workflows/ci.yml`
|
|
||||||
|
|
||||||
Commit information and dates are recorded automatically by the Continuous Benchmark Action.
|
* [`MediaRemote`](https://iphonedev.wiki/index.php/MediaRemote.framework): Need for Media detection. It's a private framework provided by newer macOS system.
|
||||||
|
* [`MoltenVK`](https://github.com/KhronosGroup/MoltenVK): Vulkan driver for macOS. [`molten-vk`](https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/molten-vk.rb)
|
||||||
|
* [`libmagickcore` (ImageMagick)](https://www.imagemagick.org/): Images in terminal using sixel graphics protocol. [`imagemagick`](https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/imagemagick.rb)
|
||||||
|
* [`libchafa`](https://github.com/hpjansson/chafa): Image output as ascii art. [`chafa`](https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/chafa.rb)
|
||||||
|
|
||||||
|
For the image logo, iTerm with iterm image protocol should work. Apple Terminal is not supported.
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
|
||||||
|
* [`wlanapi`](https://learn.microsoft.com/en-us/windows/win32/api/wlanapi/): A system dll which isn't supported by Windows Server by default. Used for Wifi info detection.
|
||||||
|
* [`libcJSON`](https://github.com/DaveGamble/cJSON): Used for Windows Terminal font detection. [`cjson`](https://github.com/msys2/MINGW-packages/tree/master/mingw-w64-cjson)
|
||||||
|
* [`libvulkan`](https://www.vulkan.org/): Vulkan module. Usually has been provided by GPU drivers. [`vulkan-loader`](https://github.com/msys2/MINGW-packages/tree/master/mingw-w64-vulkan-loader) [`vulkan-headers`](https://github.com/msys2/MINGW-packages/tree/master/mingw-w64-vulkan-headers)
|
||||||
|
* [`libOpenCL`](https://www.khronos.org/opencl/): OpenCL module. [`opencl-icd`](https://github.com/msys2/MINGW-packages/tree/master/mingw-w64-opencl-icd)
|
||||||
|
|
||||||
|
Note: In Windows 7, 8 and 8.1, [ConEmu](https://conemu.github.io/en/AnsiEscapeCodes.html) is required to run fastfetch due to [the lack of ASCII escape code native support](https://en.wikipedia.org/wiki/ANSI_escape_code#DOS,_OS/2,_and_Windows). In addition, special build `fastfetch-windows-old` in [Github Actions](https://github.com/LinusDierheimer/fastfetch/actions) is provided to support these old systems, which
|
||||||
|
|
||||||
|
1. Build with the ancient MSVCRT C runtime library, instead of the modern [UCRT](https://learn.microsoft.com/en-us/cpp/windows/universal-crt-deployment) C runtime library
|
||||||
|
2. Disable stdout application buffer, which seems to problematic for ConEmu.
|
||||||
|
|
||||||
|
For the image logo, only chafa is supported due to [the design flaw of ConPTY](https://github.com/microsoft/terminal/issues/1173). In addition, chafa support is not built by default due to the massive dependencies of imagemagick. You must built it yourself.
|
||||||
|
|
||||||
|
### Android
|
||||||
|
|
||||||
|
* [`freetype`](https://www.freetype.org/): Used for Termux font detection. [`freetype`](https://github.com/termux/termux-packages/tree/master/packages/freetype)
|
||||||
|
* [`libvulkan`](https://www.vulkan.org/): Vulkan module, also used for GPU detection. Usually has been provided by Android system. [`vulkan-loader-android`](https://github.com/termux/termux-packages/tree/master/packages/vulkan-loader-android) [`vulkan-headers`](https://github.com/termux/termux-packages/tree/master/packages/vulkan-headers)
|
||||||
|
|
||||||
|
## Support status
|
||||||
|
All categories not listed here should work without needing a specific implementation.
|
||||||
|
|
||||||
|
##### Available Modules
|
||||||
|
```
|
||||||
|
Title, Separator, OS, Host, Bios, Board, Kernel, Uptime, Processes, Packages, Shell, Resolution, DE, WM, WMTheme, Theme, Icons, Font, Cursor, Terminal, Terminal Font, CPU, CPUUsage, GPU, Memory, Swap, Disk, Battery, Power Adapter, Player, Media, Vulkan, OpenGL, OpenCL, LocalIP, PublicIP, Wifi, DateTime, Date, Time, Locale, Colors, Break, Custom
|
||||||
|
```
|
||||||
|
|
||||||
|
##### Logos
|
||||||
|
```
|
||||||
|
AlmaLinux, Alpine, Android, Arch, Arco, Artix, Bedrock, CachyOS, CentOS, CRUX, Crystal, Debian, Devuan, Deepin, Endeavour, Enso, Fedora, FreeBSD, Garuda, Gentoo, KDE Neon, KISS, Kubuntu, LangitKetujuh, Linux, MacOS, Manjaro, Mint, MSYS2, NixOS, Nobara, OpenSUSE, OpenSUSE Tumbleweed, OpenSUSE LEAP, Parabola, Pop!_OS, RebornOS, RedstarOS, Rocky, Rosa, Slackware, Solus, Ubuntu, Vanilla, Void, Windows 11, Windows 8, Windows, Zorin
|
||||||
|
```
|
||||||
|
* Most of the logos have a small variant. Access it by appending _small to the logo name.
|
||||||
|
* Some logos have an old variant. Access it by appending _old to the logo name.
|
||||||
|
* To disable the logo, use `--logo none`.
|
||||||
|
* Get a list of all available logos with `fastfetch --print-logos`.
|
||||||
|
* Printing images as logo is supported using Sixel / Kitty / iTerm graphics protocol or chafas image to text conversion.
|
||||||
|
|
||||||
|
##### Package managers
|
||||||
|
```
|
||||||
|
Pacman, dpkg, rpm, emerge, eopkg, xbps, nix, Flatpak, Snap, apk, pkg, brew, MacPorts, scoop, Chocolatey
|
||||||
|
```
|
||||||
|
|
||||||
|
##### WM themes
|
||||||
|
```
|
||||||
|
KWin, Mutter, Muffin, Marco, XFWM, Openbox (LXDE, LXQT & without DE), Quartz Compositor (macOS), DWM (Windows)
|
||||||
|
```
|
||||||
|
|
||||||
|
##### DE versions
|
||||||
|
```
|
||||||
|
KDE Plasma, Gnome, Cinnamon, Mate, XFCE4, LXQt
|
||||||
|
```
|
||||||
|
|
||||||
|
##### Terminal fonts
|
||||||
|
```
|
||||||
|
Konsole, Gnome Terminal, Tilix, XFCE4 Terminal, Alacritty, Kitty, LXTerminal, Deepin Terminal, iTerm2, Apple Terminal, Warp, TTY, Windows Terminal, Termux, mintty, ConEmu
|
||||||
|
```
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
fastfetch uses [`cmake`](https://cmake.org/) for building. [`pkg-config`](https://www.freedesktop.org/wiki/Software/pkg-config/) is recommended for better library detection. The simplest steps to build the fastfetch and flashfetch binaries are:
|
||||||
|
```bash
|
||||||
|
mkdir -p build
|
||||||
|
cd build
|
||||||
|
cmake ..
|
||||||
|
cmake --build . --target fastfetch --target flashfetch
|
||||||
|
```
|
||||||
|
|
||||||
|
If the build process fails to find the headers for a library listed in [dependencies](#dependencies), fastfetch will simply build without support for that specific feature. This means, it won't look for it at runtime and just act like it isn't available.
|
||||||
|
|
||||||
|
### Building on Windows
|
||||||
|
|
||||||
|
Currently GCC or clang is required (MSVC is not supported). MSYS2 with CLANG64 subsystem (or CLANGARM64 if needed) is suggested (and tested) to build fastfetch. If you need Windows 7 / 8.x support, using MINGW64 is suggested.
|
||||||
|
|
||||||
|
1. Install [MSYS2](https://www.msys2.org/#installation)
|
||||||
|
1. Open `MSYS2 CLANG64` (not `MSYS2 / MSYS`, which targets cygwin C runtime)
|
||||||
|
1. Install dependencies
|
||||||
|
```bash
|
||||||
|
pacman -Syu mingw-w64-clang-x86_64-cmake mingw-w64-clang-x86_64-pkgconf mingw-w64-clang-x86_64-clang mingw-w64-clang-x86_64-cjson mingw-w64-clang-x86_64-vulkan-loader mingw-w64-clang-x86_64-opencl-icd
|
||||||
|
```
|
||||||
|
1. Follow building instructions of Linux
|
||||||
|
|
||||||
|
## Packaging
|
||||||
|
|
||||||
|
### Repositories
|
||||||
|
|
||||||
|
[](https://repology.org/project/fastfetch/versions)
|
||||||
|
|
||||||
|
### Manual
|
||||||
|
|
||||||
|
* DEB / RPM package: `cmake --build . --target package`
|
||||||
|
* Install directly: `cmake --install . --prefix /usr/local`
|
||||||
|
|
||||||
|
## FAQ
|
||||||
|
|
||||||
|
Q: Why do you need a very performant version of neofetch?
|
||||||
|
> I like putting neofetch in my ~/.bashrc to have a system overwiew whenever I use the terminal, but the slow speed annoyed me, so I created this. Also neofetch didn't output everything correctly (e.g Font is displayed as "[Plasma], Noto Sans, 10 [GTK2/3]") and writing my own tool gave me the possibility to fine tune it to run perfectly on at least my configuration.
|
||||||
|
|
||||||
|
Q: It does not display [*] correctly for me, what can I do?
|
||||||
|
> This is most likely because your system is not implemented (yet). At the moment I am focusing more on making the core app better, than adding more configurations. Feel free to open a pull request if you want to add support for your configuration
|
||||||
|
|||||||
@@ -0,0 +1,414 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
__fastfetch_complete_help()
|
||||||
|
{
|
||||||
|
local __ff_helps=(
|
||||||
|
"color"
|
||||||
|
"format"
|
||||||
|
"load-config"
|
||||||
|
"os-format"
|
||||||
|
"host-format"
|
||||||
|
"kernel-format"
|
||||||
|
"uptime-format"
|
||||||
|
"processes-format"
|
||||||
|
"packages-format"
|
||||||
|
"shell-format"
|
||||||
|
"resolution-format"
|
||||||
|
"de-format"
|
||||||
|
"wm-format"
|
||||||
|
"wm-theme-format"
|
||||||
|
"theme-format"
|
||||||
|
"icons-format"
|
||||||
|
"font-format"
|
||||||
|
"cursor-format"
|
||||||
|
"terminal-format"
|
||||||
|
"terminal-font-format"
|
||||||
|
"cpu-format"
|
||||||
|
"cpu-usage-format"
|
||||||
|
"gpu-format"
|
||||||
|
"memory-format"
|
||||||
|
"swap-format"
|
||||||
|
"disk-format"
|
||||||
|
"battery-format"
|
||||||
|
"poweradapter-format"
|
||||||
|
"locale-format"
|
||||||
|
"local-ip-format"
|
||||||
|
"public-ip-format"
|
||||||
|
"player-format"
|
||||||
|
"media-format"
|
||||||
|
"datetime-format"
|
||||||
|
"date-format"
|
||||||
|
"time-format"
|
||||||
|
"vulkan-format"
|
||||||
|
"opengl-format"
|
||||||
|
"opencl-format"
|
||||||
|
)
|
||||||
|
COMPREPLY=($(compgen -W "${__ff_helps[*]}" -- "$CURRENT_WORD"))
|
||||||
|
}
|
||||||
|
|
||||||
|
__fastfetch_complete_bool()
|
||||||
|
{
|
||||||
|
COMPREPLY=($(compgen -W "true false" -- "$CURRENT_WORD"))
|
||||||
|
}
|
||||||
|
|
||||||
|
__fastfetch_complete_string()
|
||||||
|
{
|
||||||
|
if [[ $CURRENT_WORD != "" ]]; then
|
||||||
|
COMPREPLY=("$CURRENT_WORD")
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
__fastfetch_complete_path()
|
||||||
|
{
|
||||||
|
COMPREPLY=($(compgen -A file -- "$CURRENT_WORD"))
|
||||||
|
}
|
||||||
|
|
||||||
|
__fastfetch_complete_logo()
|
||||||
|
{
|
||||||
|
COMPREPLY=($(compgen -W "$(fastfetch --list-logos-autocompletion)" -- "$CURRENT_WORD"))
|
||||||
|
}
|
||||||
|
|
||||||
|
__fastfetch_complete_logo_type()
|
||||||
|
{
|
||||||
|
local __ff_logo_types=(
|
||||||
|
"auto"
|
||||||
|
"builtin"
|
||||||
|
"file"
|
||||||
|
"raw"
|
||||||
|
"sixel"
|
||||||
|
"kitty"
|
||||||
|
"chafa"
|
||||||
|
)
|
||||||
|
COMPREPLY=($(compgen -W "${__ff_logo_types[*]}" -- "$CURRENT_WORD"))
|
||||||
|
}
|
||||||
|
|
||||||
|
__fastfetch_complete_binary_prefix()
|
||||||
|
{
|
||||||
|
local __ff_binary_prefixes=(
|
||||||
|
"iec"
|
||||||
|
"si"
|
||||||
|
"jedec"
|
||||||
|
)
|
||||||
|
COMPREPLY=($(compgen -W "${__ff_binary_prefixes[*]}" -- "$CURRENT_WORD"))
|
||||||
|
}
|
||||||
|
|
||||||
|
__fastfetch_complete_gl()
|
||||||
|
{
|
||||||
|
local __ff_gl_types=(
|
||||||
|
"auto"
|
||||||
|
"egl"
|
||||||
|
"glx"
|
||||||
|
"osmesa"
|
||||||
|
)
|
||||||
|
COMPREPLY=($(compgen -W "${__ff_gl_types[*]}" -- "$CURRENT_WORD"))
|
||||||
|
}
|
||||||
|
|
||||||
|
__fastfetch_complete_option()
|
||||||
|
{
|
||||||
|
local FF_OPTIONS_ALL=(
|
||||||
|
"${FF_OPTIONS_BOOL[@]}"
|
||||||
|
"${FF_OPTIONS_STRING[@]}"
|
||||||
|
"${FF_OPTIONS_PATH[@]}"
|
||||||
|
"${FF_OPTIONS_LOGO[@]}"
|
||||||
|
"${FF_OPTIONS_LOGO_TYPE[@]}"
|
||||||
|
"${FF_OPTIONS_BINARY_PREFIX[@]}"
|
||||||
|
"${FF_OPTIONS_GL[@]}"
|
||||||
|
)
|
||||||
|
|
||||||
|
if [[ $WORD_COUND -lt 3 ]]; then
|
||||||
|
FF_OPTIONS_ALL+=(
|
||||||
|
"${FF_OPTIONS_SINGLE[@]}"
|
||||||
|
"${FF_OPTIONS_HELP[@]}"
|
||||||
|
)
|
||||||
|
fi
|
||||||
|
|
||||||
|
for ff_word in ${COMP_WORDS[@]}; do
|
||||||
|
if [[ $ff_word == $CURRENT_WORD ]]; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
|
||||||
|
FF_OPTIONS_ALL=("${FF_OPTIONS_ALL[@]/$ff_word}")
|
||||||
|
done
|
||||||
|
|
||||||
|
COMPREPLY=($(compgen -W "${FF_OPTIONS_ALL[*]}" -- "$CURRENT_WORD"))
|
||||||
|
}
|
||||||
|
|
||||||
|
__fastfetch_previous_matches()
|
||||||
|
{
|
||||||
|
for ff_option in "$@"; do
|
||||||
|
if [[ $ff_option == "$PREVIOUS_WORD" ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
__fastfetch_completion()
|
||||||
|
{
|
||||||
|
local CURRENT_WORD="${COMP_WORDS[$COMP_CWORD]}"
|
||||||
|
local PREVIOUS_WORD="${COMP_WORDS[$COMP_CWORD - 1]}"
|
||||||
|
local WORD_COUND="${#COMP_WORDS[@]}"
|
||||||
|
|
||||||
|
local FF_OPTIONS_SINGLE=(
|
||||||
|
"-v"
|
||||||
|
"--version"
|
||||||
|
"--list-logos"
|
||||||
|
"--list-modules"
|
||||||
|
"--list-presets"
|
||||||
|
"--list-features"
|
||||||
|
"--print-logos"
|
||||||
|
"--print-config-system"
|
||||||
|
"--print-config-user"
|
||||||
|
"--print-structure"
|
||||||
|
)
|
||||||
|
|
||||||
|
local FF_OPTIONS_HELP=(
|
||||||
|
"-h"
|
||||||
|
"--help"
|
||||||
|
)
|
||||||
|
|
||||||
|
local FF_OPTIONS_BOOL=(
|
||||||
|
"-r"
|
||||||
|
"--show-errors"
|
||||||
|
"--logo-print-remaining"
|
||||||
|
"--multithreading"
|
||||||
|
"--stat"
|
||||||
|
"--allow-slow-operations"
|
||||||
|
"--disable-linewrap"
|
||||||
|
"--hide-cursor"
|
||||||
|
"--cpu-temp"
|
||||||
|
"--gpu-temp"
|
||||||
|
"--battery-temp"
|
||||||
|
"--localip-show-ipv4"
|
||||||
|
"--localip-show-ipv6"
|
||||||
|
"--localip-show-loop"
|
||||||
|
"--localip-name-prefix"
|
||||||
|
"--escape-bedrock"
|
||||||
|
"--pipe"
|
||||||
|
"--title-fqdn"
|
||||||
|
"--escape-bedrock"
|
||||||
|
"--disk-show-removable"
|
||||||
|
"--disk-show-hidden"
|
||||||
|
)
|
||||||
|
|
||||||
|
local FF_OPTIONS_STRING=(
|
||||||
|
"--logo-type"
|
||||||
|
"--logo-padding"
|
||||||
|
"--logo-padding-left"
|
||||||
|
"--logo-padding-right"
|
||||||
|
"--logo-color-1"
|
||||||
|
"--logo-color-2"
|
||||||
|
"--logo-color-3"
|
||||||
|
"--logo-color-4"
|
||||||
|
"--logo-color-5"
|
||||||
|
"--logo-color-6"
|
||||||
|
"--logo-color-7"
|
||||||
|
"--logo-color-8"
|
||||||
|
"--logo-width"
|
||||||
|
"--logo-height"
|
||||||
|
"--logo-color-9"
|
||||||
|
"-c"
|
||||||
|
"--color"
|
||||||
|
"--color-keys"
|
||||||
|
"--color-title"
|
||||||
|
"--separator"
|
||||||
|
"-s"
|
||||||
|
"--structure"
|
||||||
|
"--set"
|
||||||
|
"--set-keyless"
|
||||||
|
"--player-name"
|
||||||
|
"--percent-type"
|
||||||
|
"--public-ip-url"
|
||||||
|
"--public-ip-timeout"
|
||||||
|
"--weather-output-format"
|
||||||
|
"--weather-timeout"
|
||||||
|
"--os-key"
|
||||||
|
"--os-format"
|
||||||
|
"--os-error"
|
||||||
|
"--host-key"
|
||||||
|
"--host-format"
|
||||||
|
"--host-error"
|
||||||
|
"--kernel-key"
|
||||||
|
"--kernel-format"
|
||||||
|
"--kernel-error"
|
||||||
|
"--uptime-key"
|
||||||
|
"--uptime-format"
|
||||||
|
"--uptime-error"
|
||||||
|
"--processes-key"
|
||||||
|
"--processes-format"
|
||||||
|
"--processes-error"
|
||||||
|
"--packages-key"
|
||||||
|
"--packages-format"
|
||||||
|
"--packages-error"
|
||||||
|
"--shell-key"
|
||||||
|
"--shell-format"
|
||||||
|
"--shell-error"
|
||||||
|
"--resolution-key"
|
||||||
|
"--resolution-format"
|
||||||
|
"--resolution-error"
|
||||||
|
"--de-key"
|
||||||
|
"--de-format"
|
||||||
|
"--de-error"
|
||||||
|
"--wm-key"
|
||||||
|
"--wm-format"
|
||||||
|
"--wm-error"
|
||||||
|
"--wm-theme-key"
|
||||||
|
"--wm-theme-format"
|
||||||
|
"--wm-theme-error"
|
||||||
|
"--theme-key"
|
||||||
|
"--theme-format"
|
||||||
|
"--theme-error"
|
||||||
|
"--icons-key"
|
||||||
|
"--icons-format"
|
||||||
|
"--icons-error"
|
||||||
|
"--font-key"
|
||||||
|
"--font-format"
|
||||||
|
"--font-error"
|
||||||
|
"--cursor-key"
|
||||||
|
"--cursor-format"
|
||||||
|
"--cursor-error"
|
||||||
|
"--terminal-key"
|
||||||
|
"--terminal-format"
|
||||||
|
"--terminal-error"
|
||||||
|
"--terminal-font-key"
|
||||||
|
"--terminal-font-format"
|
||||||
|
"--terminal-font-error"
|
||||||
|
"--cpu-key"
|
||||||
|
"--cpu-format"
|
||||||
|
"--cpu-error"
|
||||||
|
"--cpu-useage-key"
|
||||||
|
"--cpu-useage-format"
|
||||||
|
"--cpu-useage-error"
|
||||||
|
"--gpu-key"
|
||||||
|
"--gpu-format"
|
||||||
|
"--gpu-error"
|
||||||
|
"--memory-key"
|
||||||
|
"--memory-format"
|
||||||
|
"--memory-error"
|
||||||
|
"--swap-key"
|
||||||
|
"--swap-format"
|
||||||
|
"--swap-error"
|
||||||
|
"--disk-key"
|
||||||
|
"--disk-format"
|
||||||
|
"--disk-error"
|
||||||
|
"--battery-key"
|
||||||
|
"--battery-format"
|
||||||
|
"--battery-error"
|
||||||
|
"--poweradapter-key"
|
||||||
|
"--poweradapter-format"
|
||||||
|
"--poweradapter-error"
|
||||||
|
"--locale-key"
|
||||||
|
"--locale-format"
|
||||||
|
"--locale-error"
|
||||||
|
"--local-ip-key"
|
||||||
|
"--local-ip-format"
|
||||||
|
"--local-ip-error"
|
||||||
|
"--public-ip-key"
|
||||||
|
"--public-ip-format"
|
||||||
|
"--public-ip-error"
|
||||||
|
"--wifi-key"
|
||||||
|
"--wifi-format"
|
||||||
|
"--wifi-error"
|
||||||
|
"--weather-key"
|
||||||
|
"--weather-format"
|
||||||
|
"--weather-error"
|
||||||
|
"--player-key"
|
||||||
|
"--player-format"
|
||||||
|
"--player-error"
|
||||||
|
"--media-key"
|
||||||
|
"--media-format"
|
||||||
|
"--media-error"
|
||||||
|
"--datetime-key"
|
||||||
|
"--datetime-format"
|
||||||
|
"--datetime-error"
|
||||||
|
"--date-key"
|
||||||
|
"--date-format"
|
||||||
|
"--date-error"
|
||||||
|
"--time-key"
|
||||||
|
"--time-format"
|
||||||
|
"--time-error"
|
||||||
|
"--vulkan-key"
|
||||||
|
"--vulkan-format"
|
||||||
|
"--vulkan-error"
|
||||||
|
"--opengl-key"
|
||||||
|
"--opengl-format"
|
||||||
|
"--opengl-error"
|
||||||
|
"--opencl-key"
|
||||||
|
"--opencl-format"
|
||||||
|
"--opencl-error"
|
||||||
|
"--users-key"
|
||||||
|
"--users-format"
|
||||||
|
"--users-error"
|
||||||
|
)
|
||||||
|
|
||||||
|
local FF_OPTIONS_PATH=(
|
||||||
|
"--load-config"
|
||||||
|
"--os-file"
|
||||||
|
"--lib-pci"
|
||||||
|
"--lib-vulkan"
|
||||||
|
"--lib-wayland"
|
||||||
|
"--lib-xcb-randr"
|
||||||
|
"--lib-xcb"
|
||||||
|
"--lib-xrandr"
|
||||||
|
"--lib-X11"
|
||||||
|
"--lib-gio"
|
||||||
|
"--lib-dconf"
|
||||||
|
"--lib-dbus"
|
||||||
|
"--lib-xfconf"
|
||||||
|
"--lib-sqlite3"
|
||||||
|
"--lib-rpm"
|
||||||
|
"--lib-imagemagick"
|
||||||
|
"--lib-z"
|
||||||
|
"--lib-chafa"
|
||||||
|
"--lib-egl"
|
||||||
|
"--lib-glx"
|
||||||
|
"--lib-osmesa"
|
||||||
|
"--lib-opencl"
|
||||||
|
"--battery-dir"
|
||||||
|
)
|
||||||
|
|
||||||
|
local FF_OPTIONS_LOGO=(
|
||||||
|
"-l"
|
||||||
|
"--logo"
|
||||||
|
)
|
||||||
|
|
||||||
|
local FF_OPTIONS_LOGO_TYPE=(
|
||||||
|
"--logo-type"
|
||||||
|
)
|
||||||
|
|
||||||
|
local FF_OPTIONS_BINARY_PREFIX=(
|
||||||
|
"--binary-prefix"
|
||||||
|
)
|
||||||
|
|
||||||
|
local FF_OPTIONS_GL=(
|
||||||
|
"--gl"
|
||||||
|
)
|
||||||
|
|
||||||
|
if __fastfetch_previous_matches "${FF_OPTIONS_SINGLE[@]}"; then
|
||||||
|
return
|
||||||
|
elif [[ $WORD_COUND -gt 3 && ( ${COMP_WORDS[$COMP_CWORD - 2]} == "--help" || ${COMP_WORDS[$COMP_CWORD - 2]} == "-h" ) ]]; then
|
||||||
|
return
|
||||||
|
elif [[ $CURRENT_WORD == "-"* ]]; then
|
||||||
|
__fastfetch_complete_option
|
||||||
|
elif __fastfetch_previous_matches "${FF_OPTIONS_HELP[@]}"; then
|
||||||
|
__fastfetch_complete_help
|
||||||
|
elif __fastfetch_previous_matches "${FF_OPTIONS_BOOL[@]}"; then
|
||||||
|
__fastfetch_complete_bool
|
||||||
|
elif __fastfetch_previous_matches "${FF_OPTIONS_STRING[@]}"; then
|
||||||
|
__fastfetch_complete_string
|
||||||
|
elif __fastfetch_previous_matches "${FF_OPTIONS_PATH[@]}"; then
|
||||||
|
__fastfetch_complete_path
|
||||||
|
elif __fastfetch_previous_matches "${FF_OPTIONS_LOGO[@]}"; then
|
||||||
|
__fastfetch_complete_logo
|
||||||
|
elif __fastfetch_previous_matches "${FF_OPTIONS_LOGO_TYPE[@]}"; then
|
||||||
|
__fastfetch_complete_logo_type
|
||||||
|
elif __fastfetch_previous_matches "${FF_OPTIONS_BINARY_PREFIX[@]}"; then
|
||||||
|
__fastfetch_complete_binary_prefix
|
||||||
|
elif __fastfetch_previous_matches "${FF_OPTIONS_GL[@]}"; then
|
||||||
|
__fastfetch_complete_gl
|
||||||
|
else
|
||||||
|
__fastfetch_complete_option
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
complete -F __fastfetch_completion fastfetch
|
||||||
-69572
File diff suppressed because it is too large
Load Diff
@@ -1,405 +0,0 @@
|
|||||||
<!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 @@
|
|||||||
|
--structure Title:Separator:OS:Host:Bios:Board:Chassis:Kernel:Uptime:Processes:Packages:Shell:Resolution:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:CPUUsage:GPU:Memory:Swap:Disk:Battery:PowerAdapter:Player:Media:PublicIP:LocalIP:Wifi:DateTime:Locale:Vulkan:OpenGL:OpenCL:Users:Weather:Break:Colors
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
--logo arch
|
||||||
|
--os-format "Arch Linux ({12})"
|
||||||
|
--packages-format "{} (pacman)"
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
--disable-linewrap false
|
||||||
|
--multithreading false
|
||||||
|
--show-errors
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
--load-config devinfo
|
||||||
|
--load-config all
|
||||||
|
--load-config verbose
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
# Load with --load-config examples/1
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# Load with --load-config examples/2
|
||||||
|
# Note that you must replace the image path to an existing image to display it.
|
||||||
|
|
||||||
|
--kitty /home/linus/Bilder/Gentoo.png
|
||||||
|
--logo-width 28
|
||||||
|
|
||||||
|
--separator " "
|
||||||
|
|
||||||
|
--set-keyless HardwareStart=┌───────── \e[1mHardware Information\e[0m ─────────┐
|
||||||
|
--set-keyless SoftwareStart=├───────── \e[1mSoftware Information\e[0m ─────────┤
|
||||||
|
--set-keyless InformationEnd=└────────────────────────────────────────┘
|
||||||
|
--set-keyless Colors= \e[38m \e[37m \e[36m \e[35m \e[34m \e[33m \e[32m \e[31m
|
||||||
|
--structure HardwareStart:Host:CPU:GPU:SoftwareStart:OS:Kernel:WM:Shell:Terminal:TerminalFont:Packages:InformationEnd:Colors
|
||||||
|
|
||||||
|
--host-key " "
|
||||||
|
--cpu-key " "
|
||||||
|
--gpu-key " "
|
||||||
|
--os-key " "
|
||||||
|
--kernel-key " "
|
||||||
|
--wm-key " "
|
||||||
|
--shell-key " "
|
||||||
|
--terminal-key " "
|
||||||
|
--terminal-font-key " "
|
||||||
|
--packages-key " "
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
# Load with --load-config example/3
|
||||||
|
|
||||||
|
--logo debian_small
|
||||||
|
--structure Vulkan:OpenGL:OpenCL:Memory:Disk:LocalIP
|
||||||
|
--binary-prefix si
|
||||||
|
--localip-show-loop false
|
||||||
|
--disk-folders /:/home:/boot:/efi
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
# Load with --load-config examples/4
|
||||||
|
|
||||||
|
--color blue
|
||||||
|
--logo arch_small
|
||||||
|
--logo-padding-right 1
|
||||||
|
--separator " "
|
||||||
|
--structure Date:Time:Break:Player:Media
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
# Load with --load-config examples/5
|
||||||
|
|
||||||
|
--logo none
|
||||||
|
--color reset_magenta
|
||||||
|
--structure Theme:Icons:Font:Cursor
|
||||||
|
--theme-key T
|
||||||
|
--theme-format {7}
|
||||||
|
--icons-key I
|
||||||
|
--icons-format {5}
|
||||||
|
--font-key F
|
||||||
|
--cursor-key C
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
--structure Host:Resolution:CPU:GPU:Memory:Disk:Battery
|
||||||
|
--memory-format "{?2}{2}{?}"
|
||||||
|
--disk-format "{?2}{2}{?}"
|
||||||
|
--battery-format "{?1}{1} {?}{?2}{2} {?}{?3}({3}){?}"
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
--structure "Title:Separator:OS:Host:Kernel:Uptime:Packages:Shell:Resolution:DE:WM:WMTheme:Theme:Icons:Terminal:TerminalFont:CPU:GPU:Memory:Break:Colors"
|
||||||
|
--host-format "{/2}{-}{/}{2}{?3} {3}{?}"
|
||||||
|
--os-format "{3} {12}"
|
||||||
|
--resolution-format "{}x{}"
|
||||||
|
--de-format "{2} {3}"
|
||||||
|
--theme-format "{?1}{1}{?3} {3}{?} [Plasma], {?}{7}"
|
||||||
|
--terminal-font-format "{/2}{-}{/}{2}{?3} {3}{?}"
|
||||||
|
--memory-format "{/1}{-}{/}{/2}{-}{/}{} / {}"
|
||||||
|
--gpu-key "GPU"
|
||||||
|
--resolution-key "Resolution"
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
--structure Title:Separator:OS:Host:Kernel:Uptime:Battery:Break:Packages:Shell:Resolution:Terminal:Break:CPU:GPU:Memory:Break:Colors
|
||||||
|
--host-format "{/2}{-}{/}{2}{?3} {3}{?}"
|
||||||
|
--battery-format "{/4}{-}{/}{4}%{?5} [{5}]{?}"
|
||||||
|
--resolution-key "Resolution"
|
||||||
|
--gpu-key "GPU"
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
--structure OS:Kernel:Shell:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
--os-format System: {}; Name: {}; Pretty name: {}; ID: {}; ID like: {}; Variant: {}; Variant ID: {}; Version: {}; Version ID: {}; Version codename: {}; Build ID: {}; Architecture: {}
|
||||||
|
--host-format Family: product_family: {}; product_name: {}; product_version: {}; product_sku: {}; sys_vendor: {}
|
||||||
|
--kernel-format Sysname: {}; Release: {}; Version: {}
|
||||||
|
--uptime-format Days: {}; Hours: {}; Minutes: {}; Seconds: {}
|
||||||
|
--processes-format Count: {}
|
||||||
|
--packages-format All: {}; pacman: {}; pacman branch: {}; dpkg: {}; rpm: {}; emerge: {}; eopkg: {}; xbps: {}; apk: {}; flatpak: {}; snap: {}; brew: {}; brew-cask: {}; port: {}; scoop: {}; choco: {}
|
||||||
|
--shell-format Process name: {}; Process path: {}; Process exe: {}; Process version: {}; User path: {}; User exe: {}; User version: {}
|
||||||
|
--resolution-format Width: {}; Height: {}; Refresh rate: {}
|
||||||
|
--de-format Process name: {}; Pretty name: {}; Version: {}
|
||||||
|
--wm-format Process name: {}; Pretty name: {}; Protocol: {}
|
||||||
|
--wm-theme-format Name: {}
|
||||||
|
--theme-format Plasma: {}; Plasma colors: {}; Plasma colors pretty: {}; GTK2: {}; GTK3: {}; GTK4: {}; GTK: {}
|
||||||
|
--icons-format Plasma: {}; GTK2: {}; GTK3: {}; GTK4: {}; GTK: {}
|
||||||
|
--font-format Font1: {}; Font2: {}; Font3: {}; Font4: {}
|
||||||
|
--cursor-format Theme: {}; Size: {}
|
||||||
|
--terminal-format Process: {}; Path: {}; Exe: {}
|
||||||
|
--terminal-font-format Pretty: {}; Name: {}; Size: {}; Styles: {}
|
||||||
|
--cpu-format Name: {}, Vendor: {}, CoresPhysical: {}, CoresLogical: {}, CoresOnline: {}, FrequencyMin: {}, FrequencyMax: {}, Temperature: {}
|
||||||
|
--cpu-usage-format Percentage: {}
|
||||||
|
--gpu-format Vendor: {}; Name: {}; Driver: {}; Temperature: {}; CoreCount: {}
|
||||||
|
--memory-format Used: {}; Total: {}; Percentage: {}
|
||||||
|
--disk-format SizeUsed: {}; SizeTotal: {}; SizePercentage: {}; FilesUsed: {}; FilesTotal: {}; FilesPercentage: {}; Removable: {}; Hidden: {}; Filesystem: {}; Name: {}
|
||||||
|
--battery-format Manufactor: {}; Model: {}; Technology: {}; Capacity: {}; Status: {}
|
||||||
|
--poweradapter-format Watts: {}; Name: {}; Manufactor: {}; Model: {}; Description: {}
|
||||||
|
--player-format Pretty: {}; Name: {}; Bus: {}; Url: {}
|
||||||
|
--media-format Pretty: {}; Name: {}; Artist: {}; Album: {}
|
||||||
|
--datetime-format year: {}; yearShort: {}; month: {}; monthPretty: {}; monthName: {}; monthNameShort: {}; weekNumber: {}; weekday: {}; weekdayShort: {}; dayInYear: {}; dayInMonth: {}; dayInWeek: {}; hour: {}; hourPretty: {}; hour12: {}; hour12Pretty: {}; minute: {}; minutePretty: {}; second: {}; secondPretty: {}
|
||||||
|
--vulkan-format driver: {}; Api Version: {}; Conformance Version: {}
|
||||||
|
--opengl-format version: {}; renderer: {}; vendor: {}
|
||||||
|
--opencl-format version: {}; device: {}; vendor: {}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
mkdir -p build/
|
||||||
|
cd build/
|
||||||
|
|
||||||
|
if [ -z "${CMAKE_BUILD_TYPE}" ]; then
|
||||||
|
CMAKE_BUILD_TYPE=Release
|
||||||
|
fi
|
||||||
|
cmake "-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}" ..
|
||||||
|
|
||||||
|
if [ -z "$OSTYPE" ] || [ "$OSTYPE" = "linux-gnu" ]; then
|
||||||
|
cmake_build_args="-j$(nproc)"
|
||||||
|
elif [ "$OSTYPE" = "darwin" ]; then
|
||||||
|
cmake_build_args="-j$(sysctl -n hw.ncpu)"
|
||||||
|
else
|
||||||
|
cmake_build_args=""
|
||||||
|
fi
|
||||||
|
cmake --build . --target fastfetch ${cmake_build_args}
|
||||||
|
|
||||||
|
./fastfetch "$@"
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 68 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 70 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 5.3 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 133 KiB |
@@ -0,0 +1,49 @@
|
|||||||
|
#include "util/textModifier.h"
|
||||||
|
#include "bar.h"
|
||||||
|
|
||||||
|
// green, yellow, red: print the color on nth (0~9) block
|
||||||
|
// set its value == 10 means the color will not be printed
|
||||||
|
void ffAppendPercentBar(FFinstance* instance, FFstrbuf* buffer, uint8_t percent, uint8_t green, uint8_t yellow, uint8_t red)
|
||||||
|
{
|
||||||
|
assert(green <= 10 && yellow <= 10 && red <= 10);
|
||||||
|
|
||||||
|
// [ 0%, 5%) prints 0 blocks
|
||||||
|
// [ 5%, 15%) prints 1 block;
|
||||||
|
// ...
|
||||||
|
// [85%, 95%) prints 9 blocks;
|
||||||
|
// [95%,100%] prints 10 blocks
|
||||||
|
percent = (uint8_t)(percent + 5) / 10;
|
||||||
|
assert(percent <= 10);
|
||||||
|
|
||||||
|
if(!instance->config.pipe)
|
||||||
|
ffStrbufAppendS(buffer, "\033[97m[ ");
|
||||||
|
else
|
||||||
|
ffStrbufAppendS(buffer, "[ ");
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < percent; ++i)
|
||||||
|
{
|
||||||
|
if(!instance->config.pipe)
|
||||||
|
{
|
||||||
|
if (i == green)
|
||||||
|
ffStrbufAppendS(buffer, "\033[32m");
|
||||||
|
else if (i == yellow)
|
||||||
|
ffStrbufAppendS(buffer, "\033[93m");
|
||||||
|
else if (i == red)
|
||||||
|
ffStrbufAppendS(buffer, "\033[91m");
|
||||||
|
}
|
||||||
|
ffStrbufAppendS(buffer, "■");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (percent < 10)
|
||||||
|
{
|
||||||
|
if(!instance->config.pipe)
|
||||||
|
ffStrbufAppendS(buffer, "\033[97m");
|
||||||
|
for (uint8_t i = percent; i < 10; ++i)
|
||||||
|
ffStrbufAppendS(buffer, "-");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!instance->config.pipe)
|
||||||
|
ffStrbufAppendS(buffer, "\033[97m ]" FASTFETCH_TEXT_MODIFIER_RESET);
|
||||||
|
else
|
||||||
|
ffStrbufAppendS(buffer, " ]");
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef FF_INCLUDED_common_bar
|
||||||
|
#define FF_INCLUDED_common_bar
|
||||||
|
|
||||||
|
#include "fastfetch.h"
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
FF_PERCENTAGE_TYPE_NUM_BIT = 1,
|
||||||
|
FF_PERCENTAGE_TYPE_BAR_BIT = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
void ffAppendPercentBar(FFinstance* instance, FFstrbuf* buffer, uint8_t percent, uint8_t green, uint8_t yellow, uint8_t red);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,233 @@
|
|||||||
|
#include "fastfetch.h"
|
||||||
|
#include "common/font.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static void fontInit(FFfont* font)
|
||||||
|
{
|
||||||
|
ffStrbufInit(&font->pretty);
|
||||||
|
ffStrbufInit(&font->name);
|
||||||
|
ffStrbufInitA(&font->size, 4);
|
||||||
|
ffListInitA(&font->styles, sizeof(FFstrbuf), 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
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, ffListGet(&font->styles, i));
|
||||||
|
|
||||||
|
if(i < font->styles.length - 1)
|
||||||
|
ffStrbufAppendS(&font->pretty, ", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
ffStrbufAppendC(&font->pretty, ')');
|
||||||
|
}
|
||||||
|
|
||||||
|
void ffFontInitQt(FFfont* font, const char* data)
|
||||||
|
{
|
||||||
|
fontInit(font);
|
||||||
|
|
||||||
|
//See https://doc.qt.io/qt-5/qfont.html#toString
|
||||||
|
|
||||||
|
//Family
|
||||||
|
while(*data != ',' && *data != '\0')
|
||||||
|
{
|
||||||
|
ffStrbufAppendC(&font->name, *data);
|
||||||
|
++data;
|
||||||
|
}
|
||||||
|
if(*data != '\0')
|
||||||
|
++data;
|
||||||
|
ffStrbufTrim(&font->name, ' ');
|
||||||
|
|
||||||
|
//Size
|
||||||
|
while(*data != ',' && *data != '\0')
|
||||||
|
{
|
||||||
|
ffStrbufAppendC(&font->size, *data);
|
||||||
|
++data;
|
||||||
|
}
|
||||||
|
if(*data != '\0')
|
||||||
|
++data;
|
||||||
|
ffStrbufTrim(&font->size, ' ');
|
||||||
|
|
||||||
|
#define FF_FONT_QT_SKIP_VALUE \
|
||||||
|
while(*data != ',' && *data != '\0') \
|
||||||
|
++data; \
|
||||||
|
if(*data != '\0') \
|
||||||
|
++data;
|
||||||
|
|
||||||
|
FF_FONT_QT_SKIP_VALUE //Pixel size
|
||||||
|
FF_FONT_QT_SKIP_VALUE //Style hint
|
||||||
|
FF_FONT_QT_SKIP_VALUE //Font weight
|
||||||
|
FF_FONT_QT_SKIP_VALUE //Font style
|
||||||
|
FF_FONT_QT_SKIP_VALUE //Underline
|
||||||
|
FF_FONT_QT_SKIP_VALUE //Strike out
|
||||||
|
FF_FONT_QT_SKIP_VALUE //Fixed pitch
|
||||||
|
FF_FONT_QT_SKIP_VALUE //Always 0
|
||||||
|
|
||||||
|
#undef FF_FONT_QT_SKIP_VALUE
|
||||||
|
|
||||||
|
while(*data != '\0')
|
||||||
|
{
|
||||||
|
while(*data == ' ')
|
||||||
|
++data;
|
||||||
|
|
||||||
|
if(*data == '\0')
|
||||||
|
break;
|
||||||
|
|
||||||
|
FFstrbuf* style = ffListAdd(&font->styles);
|
||||||
|
ffStrbufInit(style);
|
||||||
|
while(*data != ' ' && *data != '\0')
|
||||||
|
{
|
||||||
|
ffStrbufAppendC(style, *data);
|
||||||
|
++data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = ffListAdd(&font->styles);
|
||||||
|
ffStrbufInit(alternativeBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
ffStrbufAppendNSExludingC(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)
|
||||||
|
{
|
||||||
|
ffStrbufAppendNSExludingC(alternativeBuffer, wordLength, wordStart, '-');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(font->name.length > 0)
|
||||||
|
ffStrbufAppendC(&font->name, ' ');
|
||||||
|
ffStrbufAppendNS(&font->name, wordLength, wordStart);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ffFontInitPango(FFfont* font, const char* data)
|
||||||
|
{
|
||||||
|
fontInit(font);
|
||||||
|
|
||||||
|
while(*data != '\0' && *data != '`' && *data != '\\')
|
||||||
|
fontPangoParseWord(&data, font, NULL);
|
||||||
|
|
||||||
|
fontInitPretty(font);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ffFontInitValues(FFfont* font, const char* name, const char* size)
|
||||||
|
{
|
||||||
|
fontInit(font);
|
||||||
|
|
||||||
|
ffStrbufAppendS(&font->name, name);
|
||||||
|
ffStrbufAppendS(&font->size, size);
|
||||||
|
|
||||||
|
fontInitPretty(font);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ffFontInitCopy(FFfont* font, const char* name)
|
||||||
|
{
|
||||||
|
ffFontInitValues(font, name, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ffFontInitWithSpace(FFfont* font, const char* rawName)
|
||||||
|
{
|
||||||
|
const char* pspace = strrchr(rawName, ' ');
|
||||||
|
if(pspace == NULL)
|
||||||
|
{
|
||||||
|
ffFontInitCopy(font, rawName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fontInit(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);
|
||||||
|
|
||||||
|
for(uint32_t i = 0; i < font->styles.length; i++)
|
||||||
|
ffStrbufDestroy(ffListGet(&font->styles, i));
|
||||||
|
ffListDestroy(&font->styles);
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef FF_INCLUDED_common_font
|
||||||
|
#define FF_INCLUDED_common_font
|
||||||
|
|
||||||
|
#include "util/FFstrbuf.h"
|
||||||
|
#include "util/FFlist.h"
|
||||||
|
|
||||||
|
typedef struct FFfont
|
||||||
|
{
|
||||||
|
FFstrbuf pretty;
|
||||||
|
FFstrbuf name;
|
||||||
|
FFstrbuf size;
|
||||||
|
FFlist styles;
|
||||||
|
} FFfont;
|
||||||
|
|
||||||
|
void ffFontInitQt(FFfont* font, const char* data);
|
||||||
|
void ffFontInitPango(FFfont* font, const char* data);
|
||||||
|
void ffFontInitCopy(FFfont* font, const char* name);
|
||||||
|
void ffFontInitValues(FFfont* font, const char* name, const char* size);
|
||||||
|
void ffFontInitWithSpace(FFfont* font, const char* rawName);
|
||||||
|
void ffFontDestroy(FFfont* font);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,274 @@
|
|||||||
|
#include "fastfetch.h"
|
||||||
|
#include "common/format.h"
|
||||||
|
#include "common/parsing.h"
|
||||||
|
#include "util/textModifier.h"
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
void ffFormatAppendFormatArg(FFstrbuf* buffer, const FFformatarg* formatarg)
|
||||||
|
{
|
||||||
|
if(formatarg->type == FF_FORMAT_ARG_TYPE_INT)
|
||||||
|
ffStrbufAppendF(buffer, "%i", *(int*)formatarg->value);
|
||||||
|
else if(formatarg->type == FF_FORMAT_ARG_TYPE_UINT)
|
||||||
|
ffStrbufAppendF(buffer, "%" PRIu32, *(uint32_t*)formatarg->value);
|
||||||
|
else if(formatarg->type == FF_FORMAT_ARG_TYPE_UINT16)
|
||||||
|
ffStrbufAppendF(buffer, "%" PRIu16, *(uint16_t*)formatarg->value);
|
||||||
|
else if(formatarg->type == FF_FORMAT_ARG_TYPE_UINT8)
|
||||||
|
ffStrbufAppendF(buffer, "%" PRIu8, *(uint8_t*)formatarg->value);
|
||||||
|
else if(formatarg->type == FF_FORMAT_ARG_TYPE_STRING)
|
||||||
|
ffStrbufAppendS(buffer, (const char*)formatarg->value);
|
||||||
|
else if(formatarg->type == FF_FORMAT_ARG_TYPE_STRBUF)
|
||||||
|
ffStrbufAppend(buffer, (FFstrbuf*)formatarg->value);
|
||||||
|
else if(formatarg->type == FF_FORMAT_ARG_TYPE_DOUBLE)
|
||||||
|
ffStrbufAppendF(buffer, "%g", *(double*)formatarg->value);
|
||||||
|
else if(formatarg->type == FF_FORMAT_ARG_TYPE_BOOL)
|
||||||
|
ffStrbufAppendS(buffer, formatarg->value != NULL ? "true" : "false");
|
||||||
|
else if(formatarg->type == FF_FORMAT_ARG_TYPE_LIST)
|
||||||
|
{
|
||||||
|
const FFlist* list = formatarg->value;
|
||||||
|
for(uint32_t i = 0; i < list->length; i++)
|
||||||
|
{
|
||||||
|
ffStrbufAppend(buffer, ffListGet(list, i));
|
||||||
|
if(i < list->length - 1)
|
||||||
|
ffStrbufAppendS(buffer, ", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(formatarg->type != FF_FORMAT_ARG_TYPE_NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error: format string \"%s\": argument is not implemented: %i\n", buffer->chars, formatarg->type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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 inline uint32_t getArgumentIndex(const FFstrbuf* placeholderValue)
|
||||||
|
{
|
||||||
|
uint32_t result = UINT32_MAX;
|
||||||
|
|
||||||
|
if(placeholderValue->chars[0] != '-')
|
||||||
|
sscanf(placeholderValue->chars, "%u", &result);
|
||||||
|
|
||||||
|
return result == 0 ? UINT32_MAX : result;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 void appendEmptyPlaceholder(FFstrbuf* buffer, const char* placeholder, uint32_t* argCounter, uint32_t numArgs, const FFformatarg* arguments)
|
||||||
|
{
|
||||||
|
if(*argCounter >= numArgs)
|
||||||
|
ffStrbufAppendS(buffer, placeholder);
|
||||||
|
else
|
||||||
|
ffFormatAppendFormatArg(buffer, arguments + *argCounter);
|
||||||
|
|
||||||
|
(*argCounter)++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool formatArgSet(const FFformatarg* arg)
|
||||||
|
{
|
||||||
|
return arg->value != NULL && (
|
||||||
|
(arg->type == FF_FORMAT_ARG_TYPE_DOUBLE && *(double*)arg->value > 0.0) || //Also is false for NaN
|
||||||
|
(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(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 && arg->value != NULL)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
uint32_t numOpenColors = 0;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we have an { at the end handle it as {}
|
||||||
|
if(i == formatstr->length - 1)
|
||||||
|
{
|
||||||
|
appendEmptyPlaceholder(buffer, "{", &argCounter, numArgs, arguments);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// placeholder is {}
|
||||||
|
if(formatstr->chars[i] == '}')
|
||||||
|
{
|
||||||
|
appendEmptyPlaceholder(buffer, "{}", &argCounter, numArgs, arguments);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
FFstrbuf placeholderValue;
|
||||||
|
ffStrbufInit(&placeholderValue);
|
||||||
|
|
||||||
|
while(i < formatstr->length && formatstr->chars[i] != '}')
|
||||||
|
ffStrbufAppendC(&placeholderValue, formatstr->chars[i++]);
|
||||||
|
|
||||||
|
// test if for stop, if so break the loop
|
||||||
|
if(placeholderValue.length == 1 && placeholderValue.chars[0] == '-')
|
||||||
|
{
|
||||||
|
ffStrbufDestroy(&placeholderValue);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// test for end of an if, if so do nothing
|
||||||
|
if(placeholderValue.length == 1 && placeholderValue.chars[0] == '?')
|
||||||
|
{
|
||||||
|
if(numOpenIfs == 0)
|
||||||
|
appendInvalidPlaceholder(buffer, "{", &placeholderValue, i, formatstr->length);
|
||||||
|
else
|
||||||
|
--numOpenIfs;
|
||||||
|
|
||||||
|
ffStrbufDestroy(&placeholderValue);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// test for end of a not if, if so do nothing
|
||||||
|
if(placeholderValue.length == 1 && placeholderValue.chars[0] == '/')
|
||||||
|
{
|
||||||
|
if(numOpenNotIfs == 0)
|
||||||
|
appendInvalidPlaceholder(buffer, "{", &placeholderValue, i, formatstr->length);
|
||||||
|
else
|
||||||
|
--numOpenNotIfs;
|
||||||
|
|
||||||
|
ffStrbufDestroy(&placeholderValue);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// test for end of a color, if so do nothing
|
||||||
|
if(placeholderValue.length == 1 && placeholderValue.chars[0] == '#')
|
||||||
|
{
|
||||||
|
if(numOpenColors == 0)
|
||||||
|
appendInvalidPlaceholder(buffer, "{", &placeholderValue, i, formatstr->length);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ffStrbufAppendS(buffer, FASTFETCH_TEXT_MODIFIER_RESET);
|
||||||
|
--numOpenColors;
|
||||||
|
}
|
||||||
|
|
||||||
|
ffStrbufDestroy(&placeholderValue);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// test for if, if so evaluate it
|
||||||
|
if(placeholderValue.chars[0] == '?')
|
||||||
|
{
|
||||||
|
ffStrbufSubstrAfter(&placeholderValue, 0);
|
||||||
|
|
||||||
|
uint32_t index = getArgumentIndex(&placeholderValue);
|
||||||
|
|
||||||
|
// testing for an invalid index
|
||||||
|
if(index > numArgs)
|
||||||
|
{
|
||||||
|
appendInvalidPlaceholder(buffer, "{?", &placeholderValue, i, formatstr->length);
|
||||||
|
ffStrbufDestroy(&placeholderValue);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// continue normally if an format arg is set and the value is > 0
|
||||||
|
if(formatArgSet(&arguments[index - 1]))
|
||||||
|
{
|
||||||
|
++numOpenIfs;
|
||||||
|
ffStrbufDestroy(&placeholderValue);
|
||||||
|
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 increament it again directly after continue
|
||||||
|
ffStrbufDestroy(&placeholderValue);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// test for not if, if so evaluate it
|
||||||
|
if(placeholderValue.chars[0] == '/')
|
||||||
|
{
|
||||||
|
ffStrbufSubstrAfter(&placeholderValue, 0);
|
||||||
|
|
||||||
|
uint32_t index = getArgumentIndex(&placeholderValue);
|
||||||
|
|
||||||
|
// testing for an invalid index
|
||||||
|
if(index > numArgs)
|
||||||
|
{
|
||||||
|
appendInvalidPlaceholder(buffer, "{/", &placeholderValue, i, formatstr->length);
|
||||||
|
ffStrbufDestroy(&placeholderValue);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//continue normally if an format arg is not set or the value is 0
|
||||||
|
if(!formatArgSet(&arguments[index - 1]))
|
||||||
|
{
|
||||||
|
++numOpenNotIfs;
|
||||||
|
ffStrbufDestroy(&placeholderValue);
|
||||||
|
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 increament it again directly after continue
|
||||||
|
ffStrbufDestroy(&placeholderValue);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//test for color, if so evaluate it
|
||||||
|
if(placeholderValue.chars[0] == '#')
|
||||||
|
{
|
||||||
|
++numOpenColors;
|
||||||
|
ffStrbufSubstrAfter(&placeholderValue, 0);
|
||||||
|
ffStrbufAppendS(buffer, "\033[");
|
||||||
|
ffStrbufAppend(buffer, &placeholderValue);
|
||||||
|
ffStrbufAppendC(buffer, 'm');
|
||||||
|
ffStrbufDestroy(&placeholderValue);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t index = getArgumentIndex(&placeholderValue);
|
||||||
|
|
||||||
|
// test for invalid index
|
||||||
|
if(index > numArgs)
|
||||||
|
{
|
||||||
|
appendInvalidPlaceholder(buffer, "{", &placeholderValue, i, formatstr->length);
|
||||||
|
ffStrbufDestroy(&placeholderValue);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ffFormatAppendFormatArg(buffer, &arguments[index - 1]);
|
||||||
|
|
||||||
|
ffStrbufDestroy(&placeholderValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
ffStrbufTrimRight(buffer, ' ');
|
||||||
|
|
||||||
|
ffStrbufAppendS(buffer, FASTFETCH_TEXT_MODIFIER_RESET);
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef FF_INCLUDED_common_format
|
||||||
|
#define FF_INCLUDED_common_format
|
||||||
|
|
||||||
|
typedef enum FFformatargtype
|
||||||
|
{
|
||||||
|
FF_FORMAT_ARG_TYPE_NULL = 0,
|
||||||
|
FF_FORMAT_ARG_TYPE_UINT,
|
||||||
|
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_DOUBLE,
|
||||||
|
FF_FORMAT_ARG_TYPE_LIST,
|
||||||
|
FF_FORMAT_ARG_TYPE_BOOL
|
||||||
|
} FFformatargtype;
|
||||||
|
|
||||||
|
typedef struct FFformatarg
|
||||||
|
{
|
||||||
|
FFformatargtype type;
|
||||||
|
const void* value;
|
||||||
|
} FFformatarg;
|
||||||
|
|
||||||
|
void ffFormatAppendFormatArg(FFstrbuf* buffer, const FFformatarg* formatarg);
|
||||||
|
void ffParseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, uint32_t numArgs, const FFformatarg* arguments);
|
||||||
|
|
||||||
|
#define FF_FORMAT_ARG_VALUE_BOOL(xpr) ((xpr) ? (const void*) 1 : NULL)
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,559 @@
|
|||||||
|
#include "fastfetch.h"
|
||||||
|
#include "common/parsing.h"
|
||||||
|
#include "common/thread.h"
|
||||||
|
#include "detection/qt.h"
|
||||||
|
#include "detection/gtk.h"
|
||||||
|
#include "detection/displayserver/displayserver.h"
|
||||||
|
#include "util/textModifier.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <wincon.h>
|
||||||
|
#include <locale.h>
|
||||||
|
#else
|
||||||
|
#include <signal.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void initConfigDirs(FFstate* state)
|
||||||
|
{
|
||||||
|
ffListInit(&state->configDirs, sizeof(FFstrbuf));
|
||||||
|
|
||||||
|
#if !(defined(_WIN32) || defined(__APPLE__) || defined(__ANDROID__))
|
||||||
|
|
||||||
|
const char* xdgConfigHome = getenv("XDG_CONFIG_HOME");
|
||||||
|
if(ffStrSet(xdgConfigHome))
|
||||||
|
{
|
||||||
|
FFstrbuf* buffer = (FFstrbuf*) ffListAdd(&state->configDirs);
|
||||||
|
ffStrbufInitA(buffer, 64);
|
||||||
|
ffStrbufAppendS(buffer, xdgConfigHome);
|
||||||
|
ffStrbufEnsureEndsWithC(buffer, '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define FF_ENSURE_ONLY_ONCE_IN_LIST(element) \
|
||||||
|
if(ffListFirstIndexComp(&state->configDirs, element, (bool(*)(const void*, const void*))ffStrbufEqual) < state->configDirs.length - 1) \
|
||||||
|
{ \
|
||||||
|
ffStrbufDestroy(ffListGet(&state->configDirs, state->configDirs.length - 1)); \
|
||||||
|
--state->configDirs.length; \
|
||||||
|
}
|
||||||
|
|
||||||
|
FFstrbuf* userConfigHome = ffListAdd(&state->configDirs);
|
||||||
|
ffStrbufInitA(userConfigHome, 64);
|
||||||
|
ffStrbufAppendS(userConfigHome, state->passwd->pw_dir);
|
||||||
|
ffStrbufAppendS(userConfigHome, "/.config/");
|
||||||
|
FF_ENSURE_ONLY_ONCE_IN_LIST(userConfigHome)
|
||||||
|
|
||||||
|
FFstrbuf* userHome = ffListAdd(&state->configDirs);
|
||||||
|
ffStrbufInitA(userHome, 64);
|
||||||
|
ffStrbufAppendS(userHome, state->passwd->pw_dir);
|
||||||
|
ffStrbufEnsureEndsWithC(userHome, '/');
|
||||||
|
FF_ENSURE_ONLY_ONCE_IN_LIST(userHome)
|
||||||
|
|
||||||
|
#if !(defined(_WIN32) || defined(__APPLE__) || defined(__ANDROID__))
|
||||||
|
|
||||||
|
FFstrbuf xdgConfigDirs;
|
||||||
|
ffStrbufInitA(&xdgConfigDirs, 64);
|
||||||
|
ffStrbufAppendS(&xdgConfigDirs, getenv("XDG_CONFIG_DIRS"));
|
||||||
|
|
||||||
|
uint32_t startIndex = 0;
|
||||||
|
while (startIndex < xdgConfigDirs.length)
|
||||||
|
{
|
||||||
|
uint32_t colonIndex = ffStrbufNextIndexC(&xdgConfigDirs, startIndex, ':');
|
||||||
|
xdgConfigDirs.chars[colonIndex] = '\0';
|
||||||
|
|
||||||
|
if(!ffStrSet(xdgConfigDirs.chars + startIndex))
|
||||||
|
{
|
||||||
|
startIndex = colonIndex + 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
FFstrbuf* buffer = (FFstrbuf*) ffListAdd(&state->configDirs);
|
||||||
|
ffStrbufInitA(buffer, 64);
|
||||||
|
ffStrbufAppendS(buffer, xdgConfigDirs.chars + startIndex);
|
||||||
|
ffStrbufEnsureEndsWithC(buffer, '/');
|
||||||
|
FF_ENSURE_ONLY_ONCE_IN_LIST(buffer);
|
||||||
|
|
||||||
|
startIndex = colonIndex + 1;
|
||||||
|
}
|
||||||
|
ffStrbufDestroy(&xdgConfigDirs);
|
||||||
|
|
||||||
|
FFstrbuf* systemConfigHome = ffListAdd(&state->configDirs);
|
||||||
|
ffStrbufInitA(systemConfigHome, 64);
|
||||||
|
ffStrbufAppendS(systemConfigHome, FASTFETCH_TARGET_DIR_ETC"/xdg/");
|
||||||
|
FF_ENSURE_ONLY_ONCE_IN_LIST(systemConfigHome)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
FFstrbuf* systemConfig = ffListAdd(&state->configDirs);
|
||||||
|
ffStrbufInitA(systemConfig, 64);
|
||||||
|
ffStrbufAppendS(systemConfig, FASTFETCH_TARGET_DIR_ETC"/");
|
||||||
|
FF_ENSURE_ONLY_ONCE_IN_LIST(systemConfig)
|
||||||
|
|
||||||
|
#undef FF_ENSURE_ONLY_ONCE_IN_LIST
|
||||||
|
}
|
||||||
|
|
||||||
|
static void initState(FFstate* state)
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
//https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/setlocale-wsetlocale?source=recommendations&view=msvc-170#utf-8-support
|
||||||
|
setlocale(LC_ALL, ".UTF8");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
state->logoWidth = 0;
|
||||||
|
state->logoHeight = 0;
|
||||||
|
state->keysHeight = 0;
|
||||||
|
#ifndef WIN32
|
||||||
|
state->passwd = getpwuid(getuid());
|
||||||
|
#else
|
||||||
|
state->passwd = ffGetPasswd();
|
||||||
|
#endif
|
||||||
|
uname(&state->utsname);
|
||||||
|
|
||||||
|
initConfigDirs(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void initModuleArg(FFModuleArgs* args)
|
||||||
|
{
|
||||||
|
ffStrbufInit(&args->key);
|
||||||
|
ffStrbufInit(&args->outputFormat);
|
||||||
|
ffStrbufInit(&args->errorFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void defaultConfig(FFinstance* instance)
|
||||||
|
{
|
||||||
|
ffStrbufInitA(&instance->config.logo.source, 0);
|
||||||
|
instance->config.logo.type = FF_LOGO_TYPE_AUTO;
|
||||||
|
for(uint8_t i = 0; i < (uint8_t) FASTFETCH_LOGO_MAX_COLORS; ++i)
|
||||||
|
ffStrbufInit(&instance->config.logo.colors[i]);
|
||||||
|
instance->config.logo.width = 0;
|
||||||
|
instance->config.logo.height = 0; //preserve aspect ratio
|
||||||
|
instance->config.logo.paddingLeft = 0;
|
||||||
|
instance->config.logo.paddingRight = 4;
|
||||||
|
instance->config.logo.printRemaining = true;
|
||||||
|
instance->config.logo.preserveAspectRadio = false;
|
||||||
|
|
||||||
|
instance->config.logo.chafaFgOnly = false;
|
||||||
|
ffStrbufInitS(&instance->config.logo.chafaSymbols, "block+border+space-wide-inverted"); // Chafa default
|
||||||
|
instance->config.logo.chafaCanvasMode = UINT32_MAX;
|
||||||
|
instance->config.logo.chafaColorSpace = UINT32_MAX;
|
||||||
|
instance->config.logo.chafaDitherMode = UINT32_MAX;
|
||||||
|
|
||||||
|
ffStrbufInit(&instance->config.colorKeys);
|
||||||
|
ffStrbufInit(&instance->config.colorTitle);
|
||||||
|
|
||||||
|
ffStrbufInit(&instance->config.separator);
|
||||||
|
ffStrbufAppendS(&instance->config.separator, ": ");
|
||||||
|
|
||||||
|
instance->config.showErrors = false;
|
||||||
|
instance->config.recache = false;
|
||||||
|
instance->config.allowSlowOperations = false;
|
||||||
|
instance->config.disableLinewrap = true;
|
||||||
|
instance->config.hideCursor = true;
|
||||||
|
instance->config.escapeBedrock = true;
|
||||||
|
instance->config.binaryPrefixType = FF_BINARY_PREFIX_TYPE_IEC;
|
||||||
|
instance->config.glType = FF_GL_TYPE_AUTO;
|
||||||
|
instance->config.pipe = false;
|
||||||
|
instance->config.multithreading = true;
|
||||||
|
instance->config.stat = false;
|
||||||
|
|
||||||
|
initModuleArg(&instance->config.os);
|
||||||
|
initModuleArg(&instance->config.host);
|
||||||
|
initModuleArg(&instance->config.bios);
|
||||||
|
initModuleArg(&instance->config.board);
|
||||||
|
initModuleArg(&instance->config.chassis);
|
||||||
|
initModuleArg(&instance->config.kernel);
|
||||||
|
initModuleArg(&instance->config.uptime);
|
||||||
|
initModuleArg(&instance->config.processes);
|
||||||
|
initModuleArg(&instance->config.packages);
|
||||||
|
initModuleArg(&instance->config.shell);
|
||||||
|
initModuleArg(&instance->config.resolution);
|
||||||
|
initModuleArg(&instance->config.de);
|
||||||
|
initModuleArg(&instance->config.wm);
|
||||||
|
initModuleArg(&instance->config.wmTheme);
|
||||||
|
initModuleArg(&instance->config.theme);
|
||||||
|
initModuleArg(&instance->config.icons);
|
||||||
|
initModuleArg(&instance->config.font);
|
||||||
|
initModuleArg(&instance->config.cursor);
|
||||||
|
initModuleArg(&instance->config.terminal);
|
||||||
|
initModuleArg(&instance->config.terminalFont);
|
||||||
|
initModuleArg(&instance->config.cpu);
|
||||||
|
initModuleArg(&instance->config.cpuUsage);
|
||||||
|
initModuleArg(&instance->config.gpu);
|
||||||
|
initModuleArg(&instance->config.memory);
|
||||||
|
initModuleArg(&instance->config.swap);
|
||||||
|
initModuleArg(&instance->config.disk);
|
||||||
|
initModuleArg(&instance->config.battery);
|
||||||
|
initModuleArg(&instance->config.powerAdapter);
|
||||||
|
initModuleArg(&instance->config.locale);
|
||||||
|
initModuleArg(&instance->config.localIP);
|
||||||
|
initModuleArg(&instance->config.publicIP);
|
||||||
|
initModuleArg(&instance->config.weather);
|
||||||
|
initModuleArg(&instance->config.wifi);
|
||||||
|
initModuleArg(&instance->config.player);
|
||||||
|
initModuleArg(&instance->config.media);
|
||||||
|
initModuleArg(&instance->config.dateTime);
|
||||||
|
initModuleArg(&instance->config.date);
|
||||||
|
initModuleArg(&instance->config.time);
|
||||||
|
initModuleArg(&instance->config.vulkan);
|
||||||
|
initModuleArg(&instance->config.openGL);
|
||||||
|
initModuleArg(&instance->config.openCL);
|
||||||
|
initModuleArg(&instance->config.users);
|
||||||
|
|
||||||
|
ffStrbufInitA(&instance->config.libPCI, 0);
|
||||||
|
ffStrbufInitA(&instance->config.libVulkan, 0);
|
||||||
|
ffStrbufInitA(&instance->config.libWayland, 0);
|
||||||
|
ffStrbufInitA(&instance->config.libXcbRandr, 0);
|
||||||
|
ffStrbufInitA(&instance->config.libXcb, 0);
|
||||||
|
ffStrbufInitA(&instance->config.libXrandr, 0);
|
||||||
|
ffStrbufInitA(&instance->config.libX11, 0);
|
||||||
|
ffStrbufInitA(&instance->config.libGIO, 0);
|
||||||
|
ffStrbufInitA(&instance->config.libDConf, 0);
|
||||||
|
ffStrbufInitA(&instance->config.libDBus, 0);
|
||||||
|
ffStrbufInitA(&instance->config.libXFConf, 0);
|
||||||
|
ffStrbufInitA(&instance->config.libSQLite3, 0);
|
||||||
|
ffStrbufInitA(&instance->config.librpm, 0);
|
||||||
|
ffStrbufInitA(&instance->config.libImageMagick, 0);
|
||||||
|
ffStrbufInitA(&instance->config.libZ, 0);
|
||||||
|
ffStrbufInitA(&instance->config.libChafa, 0);
|
||||||
|
ffStrbufInitA(&instance->config.libEGL, 0);
|
||||||
|
ffStrbufInitA(&instance->config.libGLX, 0);
|
||||||
|
ffStrbufInitA(&instance->config.libOSMesa, 0);
|
||||||
|
ffStrbufInitA(&instance->config.libOpenCL, 0);
|
||||||
|
ffStrbufInitA(&instance->config.libcJSON, 0);
|
||||||
|
ffStrbufInitA(&instance->config.libfreetype, 0);
|
||||||
|
ffStrbufInit(&instance->config.libwlanapi);
|
||||||
|
|
||||||
|
instance->config.cpuTemp = false;
|
||||||
|
instance->config.gpuTemp = false;
|
||||||
|
instance->config.batteryTemp = false;
|
||||||
|
|
||||||
|
instance->config.titleFQDN = false;
|
||||||
|
|
||||||
|
ffStrbufInitA(&instance->config.diskFolders, 0);
|
||||||
|
instance->config.diskShowRemovable = true;
|
||||||
|
instance->config.diskShowHidden = false;
|
||||||
|
|
||||||
|
ffStrbufInitA(&instance->config.batteryDir, 0);
|
||||||
|
|
||||||
|
ffStrbufInitA(&instance->config.separatorString, 0);
|
||||||
|
|
||||||
|
instance->config.localIpShowIpV4 = true;
|
||||||
|
instance->config.localIpShowIpV6 = false;
|
||||||
|
instance->config.localIpShowLoop = false;
|
||||||
|
ffStrbufInit(&instance->config.localIpNamePrefix);
|
||||||
|
|
||||||
|
instance->config.publicIpTimeout = 0;
|
||||||
|
ffStrbufInit(&instance->config.publicIpUrl);
|
||||||
|
|
||||||
|
instance->config.weatherTimeout = 0;
|
||||||
|
ffStrbufInitS(&instance->config.weatherOutputFormat, "%t+-+%C+(%l)");
|
||||||
|
|
||||||
|
ffStrbufInitA(&instance->config.osFile, 0);
|
||||||
|
|
||||||
|
ffStrbufInitA(&instance->config.playerName, 0);
|
||||||
|
|
||||||
|
instance->config.percentType = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ffInitInstance(FFinstance* instance)
|
||||||
|
{
|
||||||
|
initState(&instance->state);
|
||||||
|
defaultConfig(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef FF_HAVE_THREADS
|
||||||
|
|
||||||
|
FF_THREAD_ENTRY_DECL_WRAPPER(ffConnectDisplayServer, FFinstance*)
|
||||||
|
|
||||||
|
#if !(defined(__APPLE__) || defined(_WIN32))
|
||||||
|
|
||||||
|
#define FF_DETECT_QT_GTK 1
|
||||||
|
|
||||||
|
FF_THREAD_ENTRY_DECL_WRAPPER(ffDetectQt, FFinstance*)
|
||||||
|
FF_THREAD_ENTRY_DECL_WRAPPER(ffDetectGTK2, FFinstance*)
|
||||||
|
FF_THREAD_ENTRY_DECL_WRAPPER(ffDetectGTK3, FFinstance*)
|
||||||
|
FF_THREAD_ENTRY_DECL_WRAPPER(ffDetectGTK4, FFinstance*)
|
||||||
|
|
||||||
|
#endif //!(defined(__APPLE__) || defined(_WIN32))
|
||||||
|
|
||||||
|
#endif //FF_HAVE_THREADS
|
||||||
|
|
||||||
|
void startDetectionThreads(FFinstance* instance)
|
||||||
|
{
|
||||||
|
#ifdef FF_HAVE_THREADS
|
||||||
|
ffThreadDetach(ffThreadCreate(ffConnectDisplayServerThreadMain, instance));
|
||||||
|
|
||||||
|
#ifdef FF_DETECT_QT_GTK
|
||||||
|
ffThreadDetach(ffThreadCreate(ffDetectQtThreadMain, instance));
|
||||||
|
ffThreadDetach(ffThreadCreate(ffDetectGTK2ThreadMain, instance));
|
||||||
|
ffThreadDetach(ffThreadCreate(ffDetectGTK3ThreadMain, instance));
|
||||||
|
ffThreadDetach(ffThreadCreate(ffDetectGTK4ThreadMain, instance));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
FF_UNUSED(instance);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static volatile bool ffDisableLinewrap = true;
|
||||||
|
static volatile bool ffHideCursor = true;
|
||||||
|
|
||||||
|
static void resetConsole()
|
||||||
|
{
|
||||||
|
if(ffDisableLinewrap)
|
||||||
|
fputs("\033[?7h", stdout);
|
||||||
|
|
||||||
|
if(ffHideCursor)
|
||||||
|
fputs("\033[?25h", stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
BOOL WINAPI consoleHandler(DWORD signal)
|
||||||
|
{
|
||||||
|
FF_UNUSED(signal);
|
||||||
|
resetConsole();
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static void exitSignalHandler(int signal)
|
||||||
|
{
|
||||||
|
FF_UNUSED(signal);
|
||||||
|
resetConsole();
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void ffStart(FFinstance* instance)
|
||||||
|
{
|
||||||
|
if(instance->config.multithreading)
|
||||||
|
startDetectionThreads(instance);
|
||||||
|
|
||||||
|
ffDisableLinewrap = instance->config.disableLinewrap && !instance->config.pipe;
|
||||||
|
ffHideCursor = instance->config.hideCursor && !instance->config.pipe;
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#ifdef FF_ENABLE_BUFFER
|
||||||
|
setvbuf(stdout, NULL, _IOFBF, 4096);
|
||||||
|
#endif
|
||||||
|
SetConsoleCtrlHandler(consoleHandler, TRUE);
|
||||||
|
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
DWORD mode = 0;
|
||||||
|
GetConsoleMode(hStdout, &mode);
|
||||||
|
SetConsoleMode(hStdout, mode | ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
|
||||||
|
SetConsoleOutputCP(CP_UTF8);
|
||||||
|
#else
|
||||||
|
#ifndef FF_ENABLE_BUFFER
|
||||||
|
setvbuf(stdout, NULL, _IONBF, 0);
|
||||||
|
#endif
|
||||||
|
struct sigaction action = { .sa_handler = exitSignalHandler };
|
||||||
|
sigaction(SIGINT, &action, NULL);
|
||||||
|
sigaction(SIGTERM, &action, NULL);
|
||||||
|
sigaction(SIGQUIT, &action, NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//reset everything to default before we start printing
|
||||||
|
if(!instance->config.pipe)
|
||||||
|
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
|
||||||
|
|
||||||
|
if(ffHideCursor)
|
||||||
|
fputs("\033[?25l", stdout);
|
||||||
|
|
||||||
|
if(ffDisableLinewrap)
|
||||||
|
fputs("\033[?7l", stdout);
|
||||||
|
|
||||||
|
ffLogoPrint(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ffFinish(FFinstance* instance)
|
||||||
|
{
|
||||||
|
if(instance->config.logo.printRemaining)
|
||||||
|
ffLogoPrintRemaining(instance);
|
||||||
|
|
||||||
|
resetConsole();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void destroyModuleArg(FFModuleArgs* args)
|
||||||
|
{
|
||||||
|
ffStrbufDestroy(&args->key);
|
||||||
|
ffStrbufDestroy(&args->outputFormat);
|
||||||
|
ffStrbufDestroy(&args->errorFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void destroyConfig(FFinstance* instance)
|
||||||
|
{
|
||||||
|
ffStrbufDestroy(&instance->config.logo.source);
|
||||||
|
ffStrbufDestroy(&instance->config.logo.chafaSymbols);
|
||||||
|
for(uint8_t i = 0; i < (uint8_t) FASTFETCH_LOGO_MAX_COLORS; ++i)
|
||||||
|
ffStrbufDestroy(&instance->config.logo.colors[i]);
|
||||||
|
ffStrbufDestroy(&instance->config.colorKeys);
|
||||||
|
ffStrbufDestroy(&instance->config.colorTitle);
|
||||||
|
ffStrbufDestroy(&instance->config.separator);
|
||||||
|
|
||||||
|
destroyModuleArg(&instance->config.os);
|
||||||
|
destroyModuleArg(&instance->config.host);
|
||||||
|
destroyModuleArg(&instance->config.bios);
|
||||||
|
destroyModuleArg(&instance->config.board);
|
||||||
|
destroyModuleArg(&instance->config.kernel);
|
||||||
|
destroyModuleArg(&instance->config.uptime);
|
||||||
|
destroyModuleArg(&instance->config.processes);
|
||||||
|
destroyModuleArg(&instance->config.packages);
|
||||||
|
destroyModuleArg(&instance->config.shell);
|
||||||
|
destroyModuleArg(&instance->config.resolution);
|
||||||
|
destroyModuleArg(&instance->config.de);
|
||||||
|
destroyModuleArg(&instance->config.wm);
|
||||||
|
destroyModuleArg(&instance->config.wmTheme);
|
||||||
|
destroyModuleArg(&instance->config.theme);
|
||||||
|
destroyModuleArg(&instance->config.icons);
|
||||||
|
destroyModuleArg(&instance->config.font);
|
||||||
|
destroyModuleArg(&instance->config.cursor);
|
||||||
|
destroyModuleArg(&instance->config.terminal);
|
||||||
|
destroyModuleArg(&instance->config.terminalFont);
|
||||||
|
destroyModuleArg(&instance->config.cpu);
|
||||||
|
destroyModuleArg(&instance->config.cpuUsage);
|
||||||
|
destroyModuleArg(&instance->config.gpu);
|
||||||
|
destroyModuleArg(&instance->config.memory);
|
||||||
|
destroyModuleArg(&instance->config.swap);
|
||||||
|
destroyModuleArg(&instance->config.disk);
|
||||||
|
destroyModuleArg(&instance->config.battery);
|
||||||
|
destroyModuleArg(&instance->config.powerAdapter);
|
||||||
|
destroyModuleArg(&instance->config.locale);
|
||||||
|
destroyModuleArg(&instance->config.localIP);
|
||||||
|
destroyModuleArg(&instance->config.publicIP);
|
||||||
|
destroyModuleArg(&instance->config.weather);
|
||||||
|
destroyModuleArg(&instance->config.wifi);
|
||||||
|
destroyModuleArg(&instance->config.player);
|
||||||
|
destroyModuleArg(&instance->config.media);
|
||||||
|
destroyModuleArg(&instance->config.dateTime);
|
||||||
|
destroyModuleArg(&instance->config.date);
|
||||||
|
destroyModuleArg(&instance->config.time);
|
||||||
|
destroyModuleArg(&instance->config.vulkan);
|
||||||
|
destroyModuleArg(&instance->config.openGL);
|
||||||
|
destroyModuleArg(&instance->config.openCL);
|
||||||
|
destroyModuleArg(&instance->config.users);
|
||||||
|
|
||||||
|
ffStrbufDestroy(&instance->config.libPCI);
|
||||||
|
ffStrbufDestroy(&instance->config.libVulkan);
|
||||||
|
ffStrbufDestroy(&instance->config.libWayland);
|
||||||
|
ffStrbufDestroy(&instance->config.libXcbRandr);
|
||||||
|
ffStrbufDestroy(&instance->config.libXcb);
|
||||||
|
ffStrbufDestroy(&instance->config.libXrandr);
|
||||||
|
ffStrbufDestroy(&instance->config.libX11);
|
||||||
|
ffStrbufDestroy(&instance->config.libGIO);
|
||||||
|
ffStrbufDestroy(&instance->config.libDConf);
|
||||||
|
ffStrbufDestroy(&instance->config.libDBus);
|
||||||
|
ffStrbufDestroy(&instance->config.libXFConf);
|
||||||
|
ffStrbufDestroy(&instance->config.libSQLite3);
|
||||||
|
ffStrbufDestroy(&instance->config.librpm);
|
||||||
|
ffStrbufDestroy(&instance->config.libImageMagick);
|
||||||
|
ffStrbufDestroy(&instance->config.libZ);
|
||||||
|
ffStrbufDestroy(&instance->config.libChafa);
|
||||||
|
ffStrbufDestroy(&instance->config.libEGL);
|
||||||
|
ffStrbufDestroy(&instance->config.libGLX);
|
||||||
|
ffStrbufDestroy(&instance->config.libOSMesa);
|
||||||
|
ffStrbufDestroy(&instance->config.libOpenCL);
|
||||||
|
ffStrbufDestroy(&instance->config.libcJSON);
|
||||||
|
ffStrbufDestroy(&instance->config.libfreetype);
|
||||||
|
ffStrbufDestroy(&instance->config.libwlanapi);
|
||||||
|
|
||||||
|
ffStrbufDestroy(&instance->config.diskFolders);
|
||||||
|
ffStrbufDestroy(&instance->config.batteryDir);
|
||||||
|
ffStrbufDestroy(&instance->config.separatorString);
|
||||||
|
ffStrbufDestroy(&instance->config.localIpNamePrefix);
|
||||||
|
ffStrbufDestroy(&instance->config.publicIpUrl);
|
||||||
|
ffStrbufDestroy(&instance->config.weatherOutputFormat);
|
||||||
|
ffStrbufDestroy(&instance->config.osFile);
|
||||||
|
ffStrbufDestroy(&instance->config.playerName);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void destroyState(FFinstance* instance)
|
||||||
|
{
|
||||||
|
for(uint32_t i = 0; i < instance->state.configDirs.length; ++i)
|
||||||
|
ffStrbufDestroy((FFstrbuf*)ffListGet(&instance->state.configDirs, i));
|
||||||
|
ffListDestroy(&instance->state.configDirs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ffDestroyInstance(FFinstance* instance)
|
||||||
|
{
|
||||||
|
destroyConfig(instance);
|
||||||
|
destroyState(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Must be in a file compiled with the libfastfetch target, because the FF_HAVE* macros are not defined for the executable targets
|
||||||
|
void ffListFeatures()
|
||||||
|
{
|
||||||
|
fputs(
|
||||||
|
#ifdef FF_HAVE_LIBPCI
|
||||||
|
"libpci\n"
|
||||||
|
#endif
|
||||||
|
#ifdef FF_HAVE_VULKAN
|
||||||
|
"vulkan\n"
|
||||||
|
#endif
|
||||||
|
#ifdef FF_HAVE_WAYLAND
|
||||||
|
"wayland\n"
|
||||||
|
#endif
|
||||||
|
#ifdef FF_HAVE_XCB_RANDR
|
||||||
|
"xcb-randr\n"
|
||||||
|
#endif
|
||||||
|
#ifdef FF_HAVE_XCB
|
||||||
|
"xcb\n"
|
||||||
|
#endif
|
||||||
|
#ifdef FF_HAVE_XRANDR
|
||||||
|
"xrandr\n"
|
||||||
|
#endif
|
||||||
|
#ifdef FF_HAVE_X11
|
||||||
|
"x11\n"
|
||||||
|
#endif
|
||||||
|
#ifdef FF_HAVE_GIO
|
||||||
|
"gio\n"
|
||||||
|
#endif
|
||||||
|
#ifdef FF_HAVE_DCONF
|
||||||
|
"dconf\n"
|
||||||
|
#endif
|
||||||
|
#ifdef FF_HAVE_DBUS
|
||||||
|
"dbus\n"
|
||||||
|
#endif
|
||||||
|
#ifdef FF_HAVE_IMAGEMAGICK7
|
||||||
|
"imagemagick7\n"
|
||||||
|
#endif
|
||||||
|
#ifdef FF_HAVE_IMAGEMAGICK6
|
||||||
|
"imagemagick6\n"
|
||||||
|
#endif
|
||||||
|
#ifdef FF_HAVE_CHAFA
|
||||||
|
"chafa\n"
|
||||||
|
#endif
|
||||||
|
#ifdef FF_HAVE_ZLIB
|
||||||
|
"zlib\n"
|
||||||
|
#endif
|
||||||
|
#ifdef FF_HAVE_XFCONF
|
||||||
|
"xfconf\n"
|
||||||
|
#endif
|
||||||
|
#ifdef FF_HAVE_SQLITE3
|
||||||
|
"sqlite3\n"
|
||||||
|
#endif
|
||||||
|
#ifdef FF_HAVE_RPM
|
||||||
|
"rpm\n"
|
||||||
|
#endif
|
||||||
|
#ifdef FF_HAVE_EGL
|
||||||
|
"egl\n"
|
||||||
|
#endif
|
||||||
|
#ifdef FF_HAVE_GLX
|
||||||
|
"glx\n"
|
||||||
|
#endif
|
||||||
|
#ifdef FF_HAVE_OSMESA
|
||||||
|
"osmesa\n"
|
||||||
|
#endif
|
||||||
|
#ifdef FF_HAVE_OPENCL
|
||||||
|
"opencl\n"
|
||||||
|
#endif
|
||||||
|
#ifdef FF_HAVE_LIBCJSON
|
||||||
|
"libcjson\n"
|
||||||
|
#endif
|
||||||
|
#ifdef FF_HAVE_FREETYPE
|
||||||
|
"freetype"
|
||||||
|
#endif
|
||||||
|
""
|
||||||
|
, stdout);
|
||||||
|
}
|
||||||
+285
@@ -0,0 +1,285 @@
|
|||||||
|
#include "fastfetch.h"
|
||||||
|
#include "common/io.h"
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <fileapi.h>
|
||||||
|
#else
|
||||||
|
#include <termios.h>
|
||||||
|
#include <poll.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void createSubfolders(const char* fileName)
|
||||||
|
{
|
||||||
|
FFstrbuf path;
|
||||||
|
ffStrbufInit(&path);
|
||||||
|
|
||||||
|
while(*fileName != '\0')
|
||||||
|
{
|
||||||
|
ffStrbufAppendC(&path, *fileName);
|
||||||
|
if(*fileName == '/')
|
||||||
|
{
|
||||||
|
mkdir(path.chars
|
||||||
|
#ifndef WIN32
|
||||||
|
, S_IRWXU | S_IRGRP | S_IROTH
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
}
|
||||||
|
++fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
ffStrbufDestroy(&path);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ffWriteFDBuffer(int fd, const FFstrbuf* content)
|
||||||
|
{
|
||||||
|
return write(fd, content->chars, content->length) != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ffWriteFileData(const char* fileName, size_t dataSize, const void* data)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
HANDLE handle = CreateFileA(fileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
if(handle == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
createSubfolders(fileName);
|
||||||
|
handle = CreateFileA(fileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
if(handle == INVALID_HANDLE_VALUE)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD written;
|
||||||
|
bool ret = !!WriteFile(handle, data, (DWORD)dataSize, &written, NULL);
|
||||||
|
|
||||||
|
CloseHandle(handle);
|
||||||
|
#else
|
||||||
|
int openFlagsModes = O_WRONLY | O_CREAT | O_TRUNC;
|
||||||
|
int openFlagsRights = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
|
||||||
|
|
||||||
|
int fd = open(fileName, openFlagsModes, openFlagsRights);
|
||||||
|
if(fd == -1)
|
||||||
|
{
|
||||||
|
createSubfolders(fileName);
|
||||||
|
fd = open(fileName, openFlagsModes, openFlagsRights);
|
||||||
|
if(fd == -1)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ret = write(fd, data, dataSize) != -1;
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ffWriteFileBuffer(const char* fileName, const FFstrbuf* buffer)
|
||||||
|
{
|
||||||
|
return ffWriteFileData(fileName, buffer->length, buffer->chars);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
bool ffAppendHandleBuffer(HANDLE handle, FFstrbuf* buffer)
|
||||||
|
{
|
||||||
|
DWORD readed = 0;
|
||||||
|
|
||||||
|
LARGE_INTEGER fileSize;
|
||||||
|
if(!GetFileSizeEx(handle, &fileSize))
|
||||||
|
fileSize.QuadPart = 0;
|
||||||
|
|
||||||
|
ffStrbufEnsureFree(buffer, fileSize.QuadPart > 0 ? (uint32_t)fileSize.QuadPart : 31);
|
||||||
|
uint32_t free = ffStrbufGetFree(buffer);
|
||||||
|
|
||||||
|
bool success;
|
||||||
|
while(
|
||||||
|
(success = !!ReadFile(handle, buffer->chars + buffer->length, free, &readed, NULL)) &&
|
||||||
|
(uint32_t) readed == free
|
||||||
|
) {
|
||||||
|
buffer->length += (uint32_t) readed;
|
||||||
|
ffStrbufEnsureFree(buffer, buffer->allocated - 1); // Doubles capacity every round. -1 for the null byte.
|
||||||
|
free = ffStrbufGetFree(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(readed > 0)
|
||||||
|
buffer->length += (uint32_t) readed;
|
||||||
|
|
||||||
|
buffer->chars[buffer->length] = '\0';
|
||||||
|
|
||||||
|
ffStrbufTrimRight(buffer, '\n');
|
||||||
|
ffStrbufTrimRight(buffer, ' ');
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool ffAppendFDBuffer(int fd, FFstrbuf* buffer)
|
||||||
|
{
|
||||||
|
ssize_t readed = 0;
|
||||||
|
|
||||||
|
struct stat fileInfo;
|
||||||
|
if(fstat(fd, &fileInfo) != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ffStrbufEnsureFree(buffer, fileInfo.st_size > 0 ? (uint32_t)fileInfo.st_size : 31);
|
||||||
|
uint32_t free = ffStrbufGetFree(buffer);
|
||||||
|
|
||||||
|
while(
|
||||||
|
(readed = read(fd, buffer->chars + buffer->length, free)) > 0 &&
|
||||||
|
(uint32_t) readed == free
|
||||||
|
) {
|
||||||
|
buffer->length += (uint32_t) readed;
|
||||||
|
ffStrbufEnsureFree(buffer, buffer->allocated - 1); // Doubles capacity every round. -1 for the null byte.
|
||||||
|
free = ffStrbufGetFree(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// In case of failure, read returns -1. We don't want to substract the length of the buffer.
|
||||||
|
if(readed > 0)
|
||||||
|
buffer->length += (uint32_t) readed;
|
||||||
|
|
||||||
|
buffer->chars[buffer->length] = '\0';
|
||||||
|
|
||||||
|
ffStrbufTrimRight(buffer, '\n');
|
||||||
|
ffStrbufTrimRight(buffer, ' ');
|
||||||
|
|
||||||
|
return readed >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t ffReadFileData(const char* fileName, size_t dataSize, void* data)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
HANDLE handle = CreateFileA(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
if(handle == INVALID_HANDLE_VALUE)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
DWORD readed;
|
||||||
|
if(!ReadFile(handle, data, (DWORD)dataSize, &readed, NULL))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return (ssize_t)readed;
|
||||||
|
#else
|
||||||
|
int fd = open(fileName, O_RDONLY);
|
||||||
|
if(fd == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ssize_t readed = read(fd, data, dataSize);
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
return readed;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
HANDLE handle = CreateFileA(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
if(handle == INVALID_HANDLE_VALUE)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool ret = ffAppendHandleBuffer(handle, buffer);
|
||||||
|
|
||||||
|
CloseHandle(handle);
|
||||||
|
#else
|
||||||
|
int fd = open(fileName, O_RDONLY);
|
||||||
|
if(fd == -1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool ret = ffAppendFDBuffer(fd, buffer);
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ffReadFileBuffer(const char* fileName, FFstrbuf* buffer)
|
||||||
|
{
|
||||||
|
ffStrbufClear(buffer);
|
||||||
|
return ffAppendFileBuffer(fileName, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not thread safe!
|
||||||
|
void ffSuppressIO(bool suppress)
|
||||||
|
{
|
||||||
|
static bool init = false;
|
||||||
|
static int origOut = -1;
|
||||||
|
static int origErr = -1;
|
||||||
|
static int nullFile = -1;
|
||||||
|
|
||||||
|
if(!init)
|
||||||
|
{
|
||||||
|
if(!suppress)
|
||||||
|
return;
|
||||||
|
|
||||||
|
origOut = dup(STDOUT_FILENO);
|
||||||
|
origErr = dup(STDERR_FILENO);
|
||||||
|
nullFile = open("/dev/null", O_WRONLY);
|
||||||
|
init = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(nullFile == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fflush(stdout);
|
||||||
|
fflush(stderr);
|
||||||
|
|
||||||
|
dup2(suppress ? nullFile : origOut, STDOUT_FILENO);
|
||||||
|
dup2(suppress ? nullFile : origErr, STDERR_FILENO);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ffFileExists(const char* fileName, mode_t mode)
|
||||||
|
{
|
||||||
|
struct stat fileStat;
|
||||||
|
return stat(fileName, &fileStat) == 0 && ((fileStat.st_mode & S_IFMT) == mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ffGetTerminalResponse(const char* request, const char* format, ...)
|
||||||
|
{
|
||||||
|
#ifndef WIN32
|
||||||
|
struct termios oldTerm, newTerm;
|
||||||
|
if(tcgetattr(STDIN_FILENO, &oldTerm) == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
newTerm = oldTerm;
|
||||||
|
newTerm.c_lflag &= (tcflag_t) ~(ICANON | ECHO);
|
||||||
|
if(tcsetattr(STDIN_FILENO, TCSANOW, &newTerm) == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fputs(request, stdout);
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
struct pollfd pfd;
|
||||||
|
pfd.fd = STDIN_FILENO;
|
||||||
|
pfd.events = POLLIN;
|
||||||
|
pfd.revents = 0;
|
||||||
|
|
||||||
|
//Give the terminal 35ms to respond
|
||||||
|
if(poll(&pfd, 1, 35) <= 0)
|
||||||
|
{
|
||||||
|
tcsetattr(STDIN_FILENO, TCSANOW, &oldTerm);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char buffer[512];
|
||||||
|
ssize_t readed = read(STDIN_FILENO, buffer, sizeof(buffer) - 1);
|
||||||
|
|
||||||
|
tcsetattr(STDIN_FILENO, TCSANOW, &oldTerm);
|
||||||
|
|
||||||
|
if(readed <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
buffer[readed] = '\0';
|
||||||
|
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
vsscanf(buffer, format, args);
|
||||||
|
va_end(args);
|
||||||
|
#else
|
||||||
|
//Unimplemented
|
||||||
|
FF_UNUSED(request, format);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef FF_INCLUDED_common_io
|
||||||
|
#define FF_INCLUDED_common_io
|
||||||
|
|
||||||
|
#include "fastfetch.h"
|
||||||
|
|
||||||
|
#include <sys/stat.h> //mode_t, fstat, stat
|
||||||
|
|
||||||
|
bool ffWriteFDBuffer(int fd, const FFstrbuf* content);
|
||||||
|
bool ffWriteFileData(const char* fileName, size_t dataSize, const void* data);
|
||||||
|
bool ffWriteFileBuffer(const char* fileName, const FFstrbuf* buffer);
|
||||||
|
|
||||||
|
bool ffAppendFDBuffer(int fd, FFstrbuf* buffer);
|
||||||
|
ssize_t ffReadFileData(const char* fileName, size_t dataSize, void* data);
|
||||||
|
bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer);
|
||||||
|
bool ffReadFileBuffer(const char* fileName, FFstrbuf* buffer);
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
bool ffAppendHandleBuffer(HANDLE handle, FFstrbuf* buffer);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool ffFileExists(const char* fileName, mode_t mode);
|
||||||
|
|
||||||
|
// Not thread safe!
|
||||||
|
void ffSuppressIO(bool suppress);
|
||||||
|
|
||||||
|
FF_C_SCANF(2, 3) void ffGetTerminalResponse(const char* request, const char* format, ...);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
#include "fastfetch.h"
|
||||||
|
#include "common/library.h"
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
//Clang doesn't define __SANITIZE_ADDRESS__ but defines __has_feature(address_sanitizer)
|
||||||
|
#if defined(__has_feature)
|
||||||
|
#if __has_feature(address_sanitizer)
|
||||||
|
#define __SANITIZE_ADDRESS__
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef FF_DLOPEN_FLAGS
|
||||||
|
#ifdef __SANITIZE_ADDRESS__
|
||||||
|
#define FF_DLOPEN_FLAGS RTLD_LAZY | RTLD_NODELETE
|
||||||
|
#else
|
||||||
|
#define FF_DLOPEN_FLAGS RTLD_LAZY
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void* libraryLoad(const char* path, int maxVersion)
|
||||||
|
{
|
||||||
|
void* result = dlopen(path, FF_DLOPEN_FLAGS);
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
// libX.dll.1 never exists on Windows, while libX-1.dll may exist
|
||||||
|
FF_UNUSED(maxVersion)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
if(result != NULL || maxVersion < 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
FFstrbuf pathbuf;
|
||||||
|
ffStrbufInitA(&pathbuf, 64);
|
||||||
|
ffStrbufAppendS(&pathbuf, path);
|
||||||
|
ffStrbufAppendC(&pathbuf, '.');
|
||||||
|
|
||||||
|
for(int i = maxVersion; i >= 0; --i)
|
||||||
|
{
|
||||||
|
uint32_t originalLength = pathbuf.length;
|
||||||
|
ffStrbufAppendF(&pathbuf, "%i", i);
|
||||||
|
|
||||||
|
result = dlopen(pathbuf.chars, FF_DLOPEN_FLAGS);
|
||||||
|
if(result != NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
ffStrbufSubstrBefore(&pathbuf, originalLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
ffStrbufDestroy(&pathbuf);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* ffLibraryLoad(const FFstrbuf* userProvidedName, ...)
|
||||||
|
{
|
||||||
|
if(userProvidedName != NULL && userProvidedName->length > 0)
|
||||||
|
return dlopen(userProvidedName->chars, FF_DLOPEN_FLAGS);
|
||||||
|
|
||||||
|
va_list defaultNames;
|
||||||
|
va_start(defaultNames, userProvidedName);
|
||||||
|
|
||||||
|
void* result = NULL;
|
||||||
|
|
||||||
|
while(result == NULL)
|
||||||
|
{
|
||||||
|
const char* path = va_arg(defaultNames, const char*);
|
||||||
|
if(path == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
int maxVersion = va_arg(defaultNames, int);
|
||||||
|
result = libraryLoad(path, maxVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end(defaultNames);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef FF_INCLUDED_common_library
|
||||||
|
#define FF_INCLUDED_common_library
|
||||||
|
|
||||||
|
#include "fastfetch.h"
|
||||||
|
#include "util/FFcheckmacros.h"
|
||||||
|
|
||||||
|
#if defined(_WIN32) //We don't force MSYS using LoadLibrary because dlopen also searches $LD_LIBRARY_PATH
|
||||||
|
#include <libloaderapi.h>
|
||||||
|
#define FF_DLOPEN_FLAGS 0
|
||||||
|
FF_C_NODISCARD static inline void* dlopen(const char* path, int mode) { FF_UNUSED(mode); return LoadLibraryA(path); }
|
||||||
|
FF_C_NODISCARD static inline void* dlsym(void* handle, const char* symbol) { return GetProcAddress((HMODULE)handle, symbol); }
|
||||||
|
static inline int dlclose(void* handle) { return !FreeLibrary((HMODULE)handle); }
|
||||||
|
#else
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define FF_LIBRARY_EXTENSION ".dll"
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
#define FF_LIBRARY_EXTENSION ".dylib"
|
||||||
|
#else
|
||||||
|
#define FF_LIBRARY_EXTENSION ".so"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define FF_LIBRARY_SYMBOL(symbolName) \
|
||||||
|
__typeof__(&symbolName) ff ## symbolName;
|
||||||
|
|
||||||
|
#define FF_LIBRARY_LOAD(libraryObjectName, userLibraryName, returnValue, ...) \
|
||||||
|
void* libraryObjectName = ffLibraryLoad(userLibraryName, __VA_ARGS__, NULL);\
|
||||||
|
if(libraryObjectName == NULL) \
|
||||||
|
return returnValue;
|
||||||
|
|
||||||
|
#define FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, symbolMapping, symbolName, returnValue) \
|
||||||
|
symbolMapping = dlsym(library, #symbolName); \
|
||||||
|
if(symbolMapping == NULL) \
|
||||||
|
{ \
|
||||||
|
dlclose(library); \
|
||||||
|
return returnValue; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FF_LIBRARY_LOAD_SYMBOL(library, symbolName, returnValue) \
|
||||||
|
__typeof__(&symbolName) FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, ff ## symbolName, symbolName, returnValue);
|
||||||
|
|
||||||
|
#define FF_LIBRARY_LOAD_SYMBOL_LAZY(library, symbolName) \
|
||||||
|
__typeof__(&symbolName) ff ## symbolName = dlsym(library, #symbolName);
|
||||||
|
|
||||||
|
#define FF_LIBRARY_LOAD_SYMBOL_MESSAGE(library, symbolName) \
|
||||||
|
__typeof__(&symbolName) FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, ff ## symbolName, symbolName, "dlsym " #symbolName " failed");
|
||||||
|
|
||||||
|
#define FF_LIBRARY_LOAD_SYMBOL_VAR(library, varName, symbolName, returnValue) \
|
||||||
|
FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, varName.ff ## symbolName, symbolName, returnValue);
|
||||||
|
|
||||||
|
#define FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(library, varName, symbolName) \
|
||||||
|
FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, varName.ff ## symbolName, symbolName, "dlsym " #symbolName " failed");
|
||||||
|
|
||||||
|
#define FF_LIBRARY_LOAD_SYMBOL_PTR(library, varName, symbolName, returnValue) \
|
||||||
|
FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, varName->ff ## symbolName, symbolName, returnValue);
|
||||||
|
|
||||||
|
void* ffLibraryLoad(const FFstrbuf* userProvidedName, ...);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef FF_INCLUDED_common_networking
|
||||||
|
#define FF_INCLUDED_common_networking
|
||||||
|
|
||||||
|
#include "common/thread.h"
|
||||||
|
#include "util/FFstrbuf.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <minwindef.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct FFNetworkingState {
|
||||||
|
#ifdef _WIN32
|
||||||
|
uintptr_t sockfd;
|
||||||
|
OVERLAPPED overlapped;
|
||||||
|
#else
|
||||||
|
int sockfd;
|
||||||
|
FFstrbuf host;
|
||||||
|
FFstrbuf command;
|
||||||
|
|
||||||
|
#ifdef FF_HAVE_THREADS
|
||||||
|
FFThreadType thread;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
} FFNetworkingState;
|
||||||
|
|
||||||
|
bool ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, const char* path, const char* headers);
|
||||||
|
bool ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer, uint32_t timeout);
|
||||||
|
|
||||||
|
static inline bool ffNetworkingGetHttp(const char* host, const char* path, uint32_t timeout, const char* headers, FFstrbuf* buffer)
|
||||||
|
{
|
||||||
|
FFNetworkingState state;
|
||||||
|
if(ffNetworkingSendHttpRequest(&state, host, path, headers))
|
||||||
|
return ffNetworkingRecvHttpResponse(&state, buffer, timeout);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
#include "fastfetch.h"
|
||||||
|
#include "common/networking.h"
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
|
||||||
|
static void connectAndSend(FFNetworkingState* state)
|
||||||
|
{
|
||||||
|
struct addrinfo hints = {
|
||||||
|
.ai_family = AF_INET,
|
||||||
|
.ai_socktype = SOCK_STREAM,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct addrinfo* addr;
|
||||||
|
|
||||||
|
if(getaddrinfo(state->host.chars, "80", &hints, &addr) != 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
state->sockfd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
|
||||||
|
if(state->sockfd == -1)
|
||||||
|
{
|
||||||
|
freeaddrinfo(addr);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(connect(state->sockfd, addr->ai_addr, addr->ai_addrlen) == -1)
|
||||||
|
{
|
||||||
|
close(state->sockfd);
|
||||||
|
freeaddrinfo(addr);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
freeaddrinfo(addr);
|
||||||
|
|
||||||
|
if(send(state->sockfd, state->command.chars, state->command.length, 0) < 0)
|
||||||
|
{
|
||||||
|
close(state->sockfd);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
error:
|
||||||
|
state->sockfd = -1;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
ffStrbufDestroy(&state->host);
|
||||||
|
ffStrbufDestroy(&state->command);
|
||||||
|
}
|
||||||
|
|
||||||
|
FF_THREAD_ENTRY_DECL_WRAPPER(connectAndSend, FFNetworkingState*);
|
||||||
|
|
||||||
|
bool ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, const char* path, const char* headers)
|
||||||
|
{
|
||||||
|
ffStrbufInitS(&state->host, host);
|
||||||
|
|
||||||
|
ffStrbufInitA(&state->command, 64);
|
||||||
|
ffStrbufAppendS(&state->command, "GET ");
|
||||||
|
ffStrbufAppendS(&state->command, path);
|
||||||
|
ffStrbufAppendS(&state->command, " HTTP/1.1\nHost: ");
|
||||||
|
ffStrbufAppendS(&state->command, host);
|
||||||
|
ffStrbufAppendS(&state->command, "\r\n");
|
||||||
|
ffStrbufAppendS(&state->command, headers);
|
||||||
|
ffStrbufAppendS(&state->command, "\r\n");
|
||||||
|
|
||||||
|
#ifdef FF_HAVE_THREADS
|
||||||
|
state->thread = ffThreadCreate(connectAndSendThreadMain, state);
|
||||||
|
return !!state->thread;
|
||||||
|
#else
|
||||||
|
connectAndSend(state);
|
||||||
|
return state->sockfd != -1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer, uint32_t timeout)
|
||||||
|
{
|
||||||
|
#ifdef FF_HAVE_THREADS
|
||||||
|
ffThreadJoin(state->thread);
|
||||||
|
#endif
|
||||||
|
if(state->sockfd == -1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(timeout > 0)
|
||||||
|
{
|
||||||
|
struct timeval timev;
|
||||||
|
timev.tv_sec = 0;
|
||||||
|
timev.tv_usec = (__typeof__(timev.tv_usec)) (timeout * 1000); //milliseconds to microseconds
|
||||||
|
setsockopt(state->sockfd, SOL_SOCKET, SO_RCVTIMEO, &timev, sizeof(timev));
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t received = recv(state->sockfd, buffer->chars + buffer->length, ffStrbufGetFree(buffer), 0);
|
||||||
|
|
||||||
|
if(received > 0)
|
||||||
|
{
|
||||||
|
buffer->length += (uint32_t) received;
|
||||||
|
buffer->chars[buffer->length] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
close(state->sockfd);
|
||||||
|
return ffStrbufStartsWithS(buffer, "HTTP/1.1 200 OK\r\n");
|
||||||
|
}
|
||||||
@@ -0,0 +1,125 @@
|
|||||||
|
#include <mswsock.h>
|
||||||
|
#include <ws2tcpip.h>
|
||||||
|
|
||||||
|
//Must be included after <mswsock.h>
|
||||||
|
#include "fastfetch.h"
|
||||||
|
#include "common/networking.h"
|
||||||
|
|
||||||
|
static LPFN_CONNECTEX ConnectEx;
|
||||||
|
|
||||||
|
static BOOL WINAPI initWsaData(PINIT_ONCE once, PVOID param, PVOID* context)
|
||||||
|
{
|
||||||
|
(void)once;
|
||||||
|
(void)param;
|
||||||
|
static WSADATA wsaData;
|
||||||
|
*context = &wsaData;
|
||||||
|
if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if(LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
//Dummy socket needed for WSAIoctl
|
||||||
|
SOCKET sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
if(sockfd == INVALID_SOCKET)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
DWORD dwBytes;
|
||||||
|
GUID guid = WSAID_CONNECTEX;
|
||||||
|
if(WSAIoctl(sockfd, SIO_GET_EXTENSION_FUNCTION_POINTER,
|
||||||
|
&guid, sizeof(guid),
|
||||||
|
&ConnectEx, sizeof(ConnectEx),
|
||||||
|
&dwBytes, NULL, NULL) != 0)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return closesocket(sockfd) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, const char* path, const char* headers)
|
||||||
|
{
|
||||||
|
static INIT_ONCE once = INIT_ONCE_STATIC_INIT;
|
||||||
|
WSADATA* pData;
|
||||||
|
if(!InitOnceExecuteOnce(&once, initWsaData, NULL, (LPVOID*) &pData))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
memset(state, 0, sizeof(*state));
|
||||||
|
|
||||||
|
struct addrinfo hints = {
|
||||||
|
.ai_family = AF_INET,
|
||||||
|
.ai_socktype = SOCK_STREAM,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct addrinfo* addr;
|
||||||
|
|
||||||
|
if(getaddrinfo(host, "80", &hints, &addr) != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
state->sockfd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
|
||||||
|
if(state->sockfd == INVALID_SOCKET)
|
||||||
|
{
|
||||||
|
freeaddrinfo(addr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
//ConnectEx requires the socket to be initially bound
|
||||||
|
struct sockaddr_in addr = {
|
||||||
|
.sin_family = AF_INET,
|
||||||
|
.sin_addr.s_addr = INADDR_ANY,
|
||||||
|
.sin_port = 0,
|
||||||
|
};
|
||||||
|
if(bind(state->sockfd, (SOCKADDR *)&addr, sizeof(addr)) != 0)
|
||||||
|
{
|
||||||
|
printf("bind %d\n", WSAGetLastError());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FF_STRBUF_AUTO_DESTROY command;
|
||||||
|
ffStrbufInitA(&command, 64);
|
||||||
|
ffStrbufAppendS(&command, "GET ");
|
||||||
|
ffStrbufAppendS(&command, path);
|
||||||
|
ffStrbufAppendS(&command, " HTTP/1.1\nHost: ");
|
||||||
|
ffStrbufAppendS(&command, host);
|
||||||
|
ffStrbufAppendS(&command, "\r\n");
|
||||||
|
ffStrbufAppendS(&command, headers);
|
||||||
|
ffStrbufAppendS(&command, "\r\n");
|
||||||
|
|
||||||
|
BOOL result = ConnectEx(state->sockfd, addr->ai_addr, (int)addr->ai_addrlen, command.chars, command.length, NULL, &state->overlapped);
|
||||||
|
freeaddrinfo(addr);
|
||||||
|
|
||||||
|
if(!result && WSAGetLastError() != WSA_IO_PENDING)
|
||||||
|
{
|
||||||
|
closesocket(state->sockfd);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer, uint32_t timeout)
|
||||||
|
{
|
||||||
|
DWORD transfer, flags;
|
||||||
|
if (!WSAGetOverlappedResult(state->sockfd, &state->overlapped, &transfer, TRUE, &flags))
|
||||||
|
{
|
||||||
|
closesocket(state->sockfd);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(timeout > 0)
|
||||||
|
{
|
||||||
|
//https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt
|
||||||
|
setsockopt(state->sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout));
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t received = recv(state->sockfd, buffer->chars + buffer->length, (int)ffStrbufGetFree(buffer), 0);
|
||||||
|
|
||||||
|
if(received > 0)
|
||||||
|
{
|
||||||
|
buffer->length += (uint32_t) received;
|
||||||
|
buffer->chars[buffer->length] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
closesocket(state->sockfd);
|
||||||
|
return ffStrbufStartsWithS(buffer, "HTTP/1.1 200 OK\r\n");
|
||||||
|
}
|
||||||
@@ -0,0 +1,177 @@
|
|||||||
|
#include "fastfetch.h"
|
||||||
|
#include "common/parsing.h"
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
bool ffStrSet(const char* str)
|
||||||
|
{
|
||||||
|
if(str == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
while(isspace(*str))
|
||||||
|
str++;
|
||||||
|
|
||||||
|
return *str != '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
void ffParseSemver(FFstrbuf* buffer, const FFstrbuf* major, const FFstrbuf* minor, const FFstrbuf* patch)
|
||||||
|
{
|
||||||
|
if(major->length > 0)
|
||||||
|
ffStrbufAppend(buffer, major);
|
||||||
|
else if(minor->length > 0 || patch->length > 0)
|
||||||
|
ffStrbufAppendC(buffer, '1');
|
||||||
|
|
||||||
|
if(minor->length == 0 && patch->length == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ffStrbufAppendC(buffer, '.');
|
||||||
|
|
||||||
|
if(minor->length > 0)
|
||||||
|
ffStrbufAppend(buffer, minor);
|
||||||
|
else if(patch->length > 0)
|
||||||
|
ffStrbufAppendC(buffer, '0');
|
||||||
|
|
||||||
|
if(patch->length == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ffStrbufAppendC(buffer, '.');
|
||||||
|
|
||||||
|
ffStrbufAppend(buffer, patch);
|
||||||
|
}
|
||||||
|
|
||||||
|
int8_t ffVersionCompare(const FFVersion* version1, const FFVersion* version2)
|
||||||
|
{
|
||||||
|
if(version1->major != version2->major)
|
||||||
|
return version1->major > version2->major ? 1 : -1;
|
||||||
|
|
||||||
|
if(version1->minor != version2->minor)
|
||||||
|
return version1->minor > version2->minor ? 1 : -1;
|
||||||
|
|
||||||
|
if(version1->patch != version2->patch)
|
||||||
|
return version1->patch > version2->patch ? 1 : -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ffVersionToPretty(const FFVersion* version, FFstrbuf* pretty)
|
||||||
|
{
|
||||||
|
if(version->major > 0 || version->minor > 0 || version->patch > 0)
|
||||||
|
ffStrbufAppendF(pretty, "%u", version->major);
|
||||||
|
|
||||||
|
if(version->minor > 0 || version->patch > 0)
|
||||||
|
ffStrbufAppendF(pretty, ".%u", version->minor);
|
||||||
|
|
||||||
|
if(version->patch > 0)
|
||||||
|
ffStrbufAppendF(pretty, ".%u", version->patch);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void parseSize(FFstrbuf* result, uint64_t bytes, uint32_t base, uint8_t prefixesLength, const char** prefixes)
|
||||||
|
{
|
||||||
|
long double size = (long double) bytes;
|
||||||
|
uint8_t counter = 0;
|
||||||
|
|
||||||
|
while(size > base && counter < prefixesLength - 1)
|
||||||
|
{
|
||||||
|
size /= base;
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(counter == 0)
|
||||||
|
ffStrbufAppendF(result, "%"PRIu64" %s", bytes, prefixes[0]);
|
||||||
|
else if(counter < 3 || (counter == 3 && size < 100.0))
|
||||||
|
ffStrbufAppendF(result, "%.2Lf %s", size, prefixes[counter]);
|
||||||
|
else
|
||||||
|
ffStrbufAppendF(result, "%.0Lf %s", size, prefixes[counter]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ffParseSize(uint64_t bytes, FFBinaryPrefixType binaryPrefix, FFstrbuf* result)
|
||||||
|
{
|
||||||
|
if(binaryPrefix == FF_BINARY_PREFIX_TYPE_IEC)
|
||||||
|
parseSize(result, bytes, 1024, 5, (const char*[]) {"B", "KiB", "MiB", "GiB", "TiB"});
|
||||||
|
else if(binaryPrefix == FF_BINARY_PREFIX_TYPE_SI)
|
||||||
|
parseSize(result, bytes, 1000, 5, (const char*[]) {"B", "kB", "MB", "GB", "TB"});
|
||||||
|
else if(binaryPrefix == FF_BINARY_PREFIX_TYPE_JEDEC)
|
||||||
|
parseSize(result, bytes, 1024, 5, (const char*[]) {"B", "KB", "MB", "GB", "TB"});
|
||||||
|
else
|
||||||
|
parseSize(result, bytes, 1024, 1, (const char*[]) {"B"});
|
||||||
|
}
|
||||||
|
|
||||||
|
void ffParseGTK(FFstrbuf* buffer, const FFstrbuf* gtk2, const FFstrbuf* gtk3, const FFstrbuf* gtk4)
|
||||||
|
{
|
||||||
|
if(gtk2->length > 0 && gtk3->length > 0 && gtk4->length > 0)
|
||||||
|
{
|
||||||
|
if((ffStrbufIgnCaseComp(gtk2, gtk3) == 0) && (ffStrbufIgnCaseComp(gtk2, gtk4) == 0))
|
||||||
|
{
|
||||||
|
ffStrbufAppend(buffer, gtk4);
|
||||||
|
ffStrbufAppendS(buffer, " [GTK2/3/4]");
|
||||||
|
}
|
||||||
|
else if(ffStrbufIgnCaseComp(gtk2, gtk3) == 0)
|
||||||
|
{
|
||||||
|
ffStrbufAppend(buffer, gtk3);
|
||||||
|
ffStrbufAppendS(buffer, " [GTK2/3], ");
|
||||||
|
ffStrbufAppend(buffer, gtk4);
|
||||||
|
ffStrbufAppendS(buffer, " [GTK4]");
|
||||||
|
}
|
||||||
|
else if(ffStrbufIgnCaseComp(gtk3, gtk4) == 0)
|
||||||
|
{
|
||||||
|
ffStrbufAppend(buffer, gtk2);
|
||||||
|
ffStrbufAppendS(buffer, " [GTK2], ");
|
||||||
|
ffStrbufAppend(buffer, gtk4);
|
||||||
|
ffStrbufAppendS(buffer, " [GTK3/4]");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ffStrbufAppend(buffer, gtk2);
|
||||||
|
ffStrbufAppendS(buffer, " [GTK2], ");
|
||||||
|
ffStrbufAppend(buffer, gtk3);
|
||||||
|
ffStrbufAppendS(buffer, " [GTK3], ");
|
||||||
|
ffStrbufAppend(buffer, gtk4);
|
||||||
|
ffStrbufAppendS(buffer, " [GTK4]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(gtk2->length > 0 && gtk3->length > 0)
|
||||||
|
{
|
||||||
|
if(ffStrbufIgnCaseComp(gtk2, gtk3) == 0)
|
||||||
|
{
|
||||||
|
ffStrbufAppend(buffer, gtk3);
|
||||||
|
ffStrbufAppendS(buffer, " [GTK2/3]");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ffStrbufAppend(buffer, gtk2);
|
||||||
|
ffStrbufAppendS(buffer, " [GTK2], ");
|
||||||
|
ffStrbufAppend(buffer, gtk3);
|
||||||
|
ffStrbufAppendS(buffer, " [GTK3]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(gtk3->length > 0 && gtk4->length > 0)
|
||||||
|
{
|
||||||
|
if(ffStrbufIgnCaseComp(gtk3, gtk4) == 0)
|
||||||
|
{
|
||||||
|
ffStrbufAppend(buffer, gtk4);
|
||||||
|
ffStrbufAppendS(buffer, " [GTK3/4]");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ffStrbufAppend(buffer, gtk3);
|
||||||
|
ffStrbufAppendS(buffer, " [GTK3], ");
|
||||||
|
ffStrbufAppend(buffer, gtk4);
|
||||||
|
ffStrbufAppendS(buffer, " [GTK4]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(gtk2->length > 0)
|
||||||
|
{
|
||||||
|
ffStrbufAppend(buffer, gtk2);
|
||||||
|
ffStrbufAppendS(buffer, " [GTK2]");
|
||||||
|
}
|
||||||
|
else if(gtk3->length > 0)
|
||||||
|
{
|
||||||
|
ffStrbufAppend(buffer, gtk3);
|
||||||
|
ffStrbufAppendS(buffer, " [GTK3]");
|
||||||
|
}
|
||||||
|
else if(gtk4->length > 0)
|
||||||
|
{
|
||||||
|
ffStrbufAppend(buffer, gtk4);
|
||||||
|
ffStrbufAppendS(buffer, " [GTK4]");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef FF_INCLUDED_parsing_h
|
||||||
|
#define FF_INCLUDED_parsing_h
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef struct FFVersion
|
||||||
|
{
|
||||||
|
uint32_t major;
|
||||||
|
uint32_t minor;
|
||||||
|
uint32_t patch;
|
||||||
|
} FFVersion;
|
||||||
|
|
||||||
|
#define FF_VERSION_INIT ((FFVersion) {0})
|
||||||
|
|
||||||
|
bool ffStrSet(const char* str);
|
||||||
|
void ffParseSemver(FFstrbuf* buffer, const FFstrbuf* major, const FFstrbuf* minor, const FFstrbuf* patch);
|
||||||
|
void ffParseGTK(FFstrbuf* buffer, const FFstrbuf* gtk2, const FFstrbuf* gtk3, const FFstrbuf* gtk4);
|
||||||
|
|
||||||
|
void ffVersionToPretty(const FFVersion* version, FFstrbuf* pretty);
|
||||||
|
int8_t ffVersionCompare(const FFVersion* version1, const FFVersion* version2);
|
||||||
|
|
||||||
|
void ffParseSize(uint64_t bytes, FFBinaryPrefixType binaryPrefix, FFstrbuf* result);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,171 @@
|
|||||||
|
#include "fastfetch.h"
|
||||||
|
#include "common/printing.h"
|
||||||
|
#include "util/textModifier.h"
|
||||||
|
|
||||||
|
void ffPrintLogoAndKey(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat)
|
||||||
|
{
|
||||||
|
ffLogoPrintLine(instance);
|
||||||
|
|
||||||
|
//This is used by --set-keyless, in this case we wan't neither the module name nor the separator
|
||||||
|
if(moduleName == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(!instance->config.pipe)
|
||||||
|
{
|
||||||
|
fputs(FASTFETCH_TEXT_MODIFIER_RESET FASTFETCH_TEXT_MODIFIER_BOLT, stdout);
|
||||||
|
ffPrintColor(&instance->config.colorKeys);
|
||||||
|
}
|
||||||
|
|
||||||
|
//NULL check is required for modules with custom keys, e.g. disk with the folder path
|
||||||
|
if(customKeyFormat == NULL || customKeyFormat->length == 0)
|
||||||
|
{
|
||||||
|
fputs(moduleName, stdout);
|
||||||
|
|
||||||
|
if(moduleIndex > 0)
|
||||||
|
printf(" %hhu", moduleIndex);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FFstrbuf key;
|
||||||
|
ffStrbufInit(&key);
|
||||||
|
ffParseFormatString(&key, customKeyFormat, 1, (FFformatarg[]){
|
||||||
|
{FF_FORMAT_ARG_TYPE_UINT8, &moduleIndex}
|
||||||
|
});
|
||||||
|
ffPrintUserString(key.chars);
|
||||||
|
ffStrbufDestroy(&key);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!instance->config.pipe)
|
||||||
|
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
|
||||||
|
|
||||||
|
ffStrbufWriteTo(&instance->config.separator, stdout);
|
||||||
|
|
||||||
|
if(!instance->config.pipe)
|
||||||
|
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ffPrintFormatString(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat, const FFstrbuf* format, uint32_t numArgs, const FFformatarg* arguments)
|
||||||
|
{
|
||||||
|
FFstrbuf buffer;
|
||||||
|
ffStrbufInitA(&buffer, 256);
|
||||||
|
|
||||||
|
ffParseFormatString(&buffer, format, numArgs, arguments);
|
||||||
|
|
||||||
|
if(buffer.length > 0)
|
||||||
|
{
|
||||||
|
ffPrintLogoAndKey(instance, moduleName, moduleIndex, customKeyFormat);
|
||||||
|
ffPrintUserString(buffer.chars);
|
||||||
|
putchar('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
ffStrbufDestroy(&buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ffPrintFormat(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, uint32_t numArgs, const FFformatarg* arguments)
|
||||||
|
{
|
||||||
|
ffPrintFormatString(instance, moduleName, moduleIndex, &moduleArgs->key, &moduleArgs->outputFormat, numArgs, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void printError(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat, const FFstrbuf* customErrorFormat, const char* message, va_list arguments)
|
||||||
|
{
|
||||||
|
bool hasCustomErrorFormat = customErrorFormat != NULL && customErrorFormat->length > 0;
|
||||||
|
if(!hasCustomErrorFormat && !instance->config.showErrors)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(hasCustomErrorFormat)
|
||||||
|
{
|
||||||
|
FFstrbuf error;
|
||||||
|
ffStrbufInit(&error);
|
||||||
|
ffStrbufAppendVF(&error, message, arguments);
|
||||||
|
|
||||||
|
ffPrintFormatString(instance, moduleName, moduleIndex, customKeyFormat, customErrorFormat, 1, (FFformatarg[]) {
|
||||||
|
{FF_FORMAT_ARG_TYPE_STRBUF, &error}
|
||||||
|
});
|
||||||
|
|
||||||
|
ffStrbufDestroy(&error);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ffPrintLogoAndKey(instance, moduleName, moduleIndex, customKeyFormat);
|
||||||
|
|
||||||
|
if(!instance->config.pipe)
|
||||||
|
fputs(FASTFETCH_TEXT_MODIFIER_ERROR, stdout);
|
||||||
|
|
||||||
|
vprintf(message, arguments);
|
||||||
|
|
||||||
|
if(!instance->config.pipe)
|
||||||
|
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
|
||||||
|
|
||||||
|
putchar('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ffPrintErrorString(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat, const FFstrbuf* customErrorFormat, const char* message, ...)
|
||||||
|
{
|
||||||
|
va_list arguments;
|
||||||
|
va_start(arguments, message);
|
||||||
|
printError(instance, moduleName, moduleIndex, customKeyFormat, customErrorFormat, message, arguments);
|
||||||
|
va_end(arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ffPrintError(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, const char* message, ...)
|
||||||
|
{
|
||||||
|
va_list arguments;
|
||||||
|
va_start(arguments, message);
|
||||||
|
printError(instance, moduleName, moduleIndex, &moduleArgs->key, &moduleArgs->errorFormat, message, arguments);
|
||||||
|
va_end(arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ffPrintColor(const FFstrbuf* colorValue)
|
||||||
|
{
|
||||||
|
//If the color is not set, this would reset in \033[m, which resets everything.
|
||||||
|
//So we only print it, if the main color is at least one char.
|
||||||
|
if(colorValue->length == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fputs("\033[", stdout);
|
||||||
|
ffStrbufWriteTo(colorValue, stdout);
|
||||||
|
fputc('m', stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ffPrintCharTimes(char c, uint32_t times)
|
||||||
|
{
|
||||||
|
char str[32];
|
||||||
|
memset(str, c, sizeof(str)); //2 instructions when compiling with AVX2 enabled
|
||||||
|
for(uint32_t i = sizeof(str); i <= times; i += sizeof(str))
|
||||||
|
fwrite(str, 1, sizeof(str), stdout);
|
||||||
|
uint32_t remaining = times % sizeof(str);
|
||||||
|
if(remaining > 0)
|
||||||
|
fwrite(str, 1, remaining, stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ffPrintUserString(const char* value)
|
||||||
|
{
|
||||||
|
while(*value != '\0')
|
||||||
|
{
|
||||||
|
if(*value != '\\')
|
||||||
|
{
|
||||||
|
putchar(*value);
|
||||||
|
++value;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
++value;
|
||||||
|
|
||||||
|
if(*value == 'n')
|
||||||
|
putchar('\n');
|
||||||
|
else if(*value == 't')
|
||||||
|
putchar('\t');
|
||||||
|
else if(*value == 'e')
|
||||||
|
putchar('\e');
|
||||||
|
else if(*value == '\\')
|
||||||
|
putchar('\\');
|
||||||
|
else
|
||||||
|
{
|
||||||
|
putchar('\\');
|
||||||
|
putchar(*value);
|
||||||
|
}
|
||||||
|
|
||||||
|
++value;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef FF_INCLUDED_common_printing
|
||||||
|
#define FF_INCLUDED_common_printing
|
||||||
|
|
||||||
|
#include "fastfetch.h"
|
||||||
|
#include "common/format.h"
|
||||||
|
|
||||||
|
void ffPrintLogoAndKey(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat);
|
||||||
|
void ffPrintFormatString(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat, const FFstrbuf* format, uint32_t numArgs, const FFformatarg* arguments);
|
||||||
|
void ffPrintFormat(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, uint32_t numArgs, const FFformatarg* arguments);
|
||||||
|
FF_C_PRINTF(6, 7) void ffPrintErrorString(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat, const FFstrbuf* customErrorFormat, const char* message, ...);
|
||||||
|
FF_C_PRINTF(5, 6) void ffPrintError(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, const char* message, ...);
|
||||||
|
void ffPrintColor(const FFstrbuf* colorValue);
|
||||||
|
void ffPrintCharTimes(char c, uint32_t times);
|
||||||
|
void ffPrintUserString(const char* str);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef FF_INCLUDED_common_processing
|
||||||
|
#define FF_INCLUDED_common_processing
|
||||||
|
|
||||||
|
#include "util/FFstrbuf.h"
|
||||||
|
|
||||||
|
const char* ffProcessAppendStdOut(FFstrbuf* buffer, char* const argv[]);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
#include "fastfetch.h"
|
||||||
|
#include "common/processing.h"
|
||||||
|
#include "common/io.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
const char* ffProcessAppendStdOut(FFstrbuf* buffer, char* const argv[])
|
||||||
|
{
|
||||||
|
int pipes[2];
|
||||||
|
|
||||||
|
if(pipe(pipes) == -1)
|
||||||
|
return "pipe() failed";
|
||||||
|
|
||||||
|
pid_t childPid = fork();
|
||||||
|
if(childPid == -1)
|
||||||
|
return "fork() failed";
|
||||||
|
|
||||||
|
//Child
|
||||||
|
if(childPid == 0)
|
||||||
|
{
|
||||||
|
dup2(pipes[1], STDOUT_FILENO);
|
||||||
|
close(pipes[0]);
|
||||||
|
close(pipes[1]);
|
||||||
|
close(STDERR_FILENO);
|
||||||
|
execvp(argv[0], argv);
|
||||||
|
exit(901);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Parent
|
||||||
|
close(pipes[1]);
|
||||||
|
waitpid(childPid, NULL, 0);
|
||||||
|
ffAppendFDBuffer(pipes[0], buffer);
|
||||||
|
close(pipes[0]);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
#include "fastfetch.h"
|
||||||
|
#include "common/processing.h"
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN 1
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
//We can't use this native version yet because we still use POSIX path ( eg /usr/bin/fish ) at a lot of places.
|
||||||
|
const char* ffProcessAppendStdOut(FFstrbuf* buffer, char* const argv[])
|
||||||
|
{
|
||||||
|
SECURITY_ATTRIBUTES saAttr = {
|
||||||
|
.nLength = sizeof(SECURITY_ATTRIBUTES),
|
||||||
|
.lpSecurityDescriptor = NULL,
|
||||||
|
.bInheritHandle = TRUE,
|
||||||
|
};
|
||||||
|
|
||||||
|
HANDLE hChildStdoutRead, hChildStdoutWrite;
|
||||||
|
if (!CreatePipe(&hChildStdoutRead, &hChildStdoutWrite, &saAttr, 0))
|
||||||
|
return "CreatePipe() failed";
|
||||||
|
|
||||||
|
if (!SetHandleInformation(hChildStdoutRead, HANDLE_FLAG_INHERIT, 0))
|
||||||
|
return "SetHandleInformation(hChildStdoutRead) failed";
|
||||||
|
|
||||||
|
PROCESS_INFORMATION piProcInfo = {0};
|
||||||
|
STARTUPINFOA siStartInfo = {
|
||||||
|
.cb = sizeof(siStartInfo),
|
||||||
|
.dwFlags = STARTF_USESTDHANDLES,
|
||||||
|
.hStdOutput = hChildStdoutWrite,
|
||||||
|
};
|
||||||
|
|
||||||
|
BOOL success;
|
||||||
|
|
||||||
|
{
|
||||||
|
FF_STRBUF_AUTO_DESTROY cmdline;
|
||||||
|
ffStrbufInitF(&cmdline, "\"%s\"", argv[0]);
|
||||||
|
for(char* const* parg = &argv[1]; *parg; ++parg)
|
||||||
|
{
|
||||||
|
ffStrbufAppendC(&cmdline, ' ');
|
||||||
|
ffStrbufAppendS(&cmdline, *parg);
|
||||||
|
}
|
||||||
|
|
||||||
|
success = CreateProcessA(
|
||||||
|
NULL, // application name
|
||||||
|
cmdline.chars, // command line
|
||||||
|
NULL, // process security attributes
|
||||||
|
NULL, // primary thread security attributes
|
||||||
|
TRUE, // handles are inherited
|
||||||
|
0, // creation flags
|
||||||
|
NULL, // use parent's environment
|
||||||
|
NULL, // use parent's current directory
|
||||||
|
&siStartInfo, // STARTUPINFO pointer
|
||||||
|
&piProcInfo // receives PROCESS_INFORMATION
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseHandle(hChildStdoutWrite);
|
||||||
|
if(!success)
|
||||||
|
{
|
||||||
|
CloseHandle(hChildStdoutRead);
|
||||||
|
return "CreateProcessA() failed";
|
||||||
|
}
|
||||||
|
|
||||||
|
char str[1024];
|
||||||
|
DWORD nRead;
|
||||||
|
while(ReadFile(hChildStdoutRead, str, sizeof(str), &nRead, NULL) && nRead > 0)
|
||||||
|
ffStrbufAppendNS(buffer, nRead, str);
|
||||||
|
|
||||||
|
CloseHandle(hChildStdoutRead);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
@@ -0,0 +1,210 @@
|
|||||||
|
#include "fastfetch.h"
|
||||||
|
#include "common/properties.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include "util/windows/getline.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static bool parsePropLinePointer(const char** line, const char* start, FFstrbuf* buffer)
|
||||||
|
{
|
||||||
|
if(**line == '\0')
|
||||||
|
return false;
|
||||||
|
|
||||||
|
//Skip any amount of whitespace at the begin of line
|
||||||
|
while(**line == ' ' || **line == '\t')
|
||||||
|
++(*line);
|
||||||
|
|
||||||
|
while(*start != '\0')
|
||||||
|
{
|
||||||
|
// Any amount of whitespace in the format string matches any amount of whitespace in the line, even none
|
||||||
|
if(*start == ' ' || *start == '\t')
|
||||||
|
{
|
||||||
|
while(*start == ' ' || *start == '\t')
|
||||||
|
++start;
|
||||||
|
|
||||||
|
while(**line == ' ' || **line == '\t')
|
||||||
|
++(*line);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Line doesn't match start, skip it
|
||||||
|
if(**line != *start || **line == '\0')
|
||||||
|
return false;
|
||||||
|
|
||||||
|
//Line and start match, continue testing
|
||||||
|
++(*line);
|
||||||
|
++start;
|
||||||
|
}
|
||||||
|
|
||||||
|
char valueEnd = '\n';
|
||||||
|
|
||||||
|
//Allow faster parsing of XML
|
||||||
|
if(*(*line - 1) == '>')
|
||||||
|
valueEnd = '<';
|
||||||
|
|
||||||
|
//Skip any amount of whitespace at the begin of the value
|
||||||
|
while(**line == ' ' || **line == '\t')
|
||||||
|
++(*line);
|
||||||
|
|
||||||
|
//Allow faster parsing of quotet values
|
||||||
|
if(**line == '"' || **line == '\'')
|
||||||
|
{
|
||||||
|
valueEnd = **line;
|
||||||
|
++(*line);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Copy the value to the buffer
|
||||||
|
while(**line != valueEnd && **line != '\n' && **line != '\0')
|
||||||
|
{
|
||||||
|
ffStrbufAppendC(buffer, **line);
|
||||||
|
++(*line);
|
||||||
|
}
|
||||||
|
|
||||||
|
ffStrbufTrimRight(buffer, ' ');
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ffParsePropLine(const char* line, const char* start, FFstrbuf* buffer)
|
||||||
|
{
|
||||||
|
return parsePropLinePointer(&line, start, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ffParsePropLines(const char* lines, const char* start, FFstrbuf* buffer)
|
||||||
|
{
|
||||||
|
while(!parsePropLinePointer(&lines, start, buffer))
|
||||||
|
{
|
||||||
|
while(*lines != '\0' && *lines != '\n')
|
||||||
|
++lines;
|
||||||
|
|
||||||
|
if(*lines == '\0')
|
||||||
|
return false;
|
||||||
|
|
||||||
|
//Skip '\n'
|
||||||
|
++lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The following functions return true if the file was found, independently if start was found
|
||||||
|
// Buffers which already contain content are not overwritten
|
||||||
|
// The last occurence of start in the first file will be the one used
|
||||||
|
|
||||||
|
bool ffParsePropFileValues(const char* filename, uint32_t numQueries, FFpropquery* queries)
|
||||||
|
{
|
||||||
|
FILE* file = fopen(filename, "r");
|
||||||
|
if(file == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool valueStorage[4];
|
||||||
|
bool* unsetValues;
|
||||||
|
|
||||||
|
if(numQueries > sizeof(valueStorage) / sizeof(valueStorage[0]))
|
||||||
|
unsetValues = malloc(sizeof(bool) * numQueries);
|
||||||
|
else
|
||||||
|
unsetValues = valueStorage;
|
||||||
|
|
||||||
|
bool allSet = true;
|
||||||
|
for(uint32_t i = 0; i < numQueries; i++)
|
||||||
|
{
|
||||||
|
if((unsetValues[i] = queries[i].buffer->length == 0))
|
||||||
|
allSet = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(allSet)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
char* line = NULL;
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
|
while (getline(&line, &len, file) != -1)
|
||||||
|
{
|
||||||
|
for(uint32_t i = 0; i < numQueries; i++)
|
||||||
|
{
|
||||||
|
if(!unsetValues[i])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
uint32_t currentLength = queries[i].buffer->length;
|
||||||
|
queries[i].buffer->length = 0;
|
||||||
|
if(!ffParsePropLine(line, queries[i].start, queries[i].buffer))
|
||||||
|
queries[i].buffer->length = currentLength;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(line != NULL)
|
||||||
|
free(line);
|
||||||
|
|
||||||
|
done:
|
||||||
|
fclose(file);
|
||||||
|
if(unsetValues != valueStorage)
|
||||||
|
free(unsetValues);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ffParsePropFile(const char* filename, const char* start, FFstrbuf* buffer)
|
||||||
|
{
|
||||||
|
return ffParsePropFileValues(filename, 1, (FFpropquery[]){{start, buffer}});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ffParsePropFileHomeValues(const FFinstance* instance, const char* relativeFile, uint32_t numQueries, FFpropquery* queries)
|
||||||
|
{
|
||||||
|
FFstrbuf absolutePath;
|
||||||
|
ffStrbufInitA(&absolutePath, 64);
|
||||||
|
ffStrbufAppendS(&absolutePath, instance->state.passwd->pw_dir);
|
||||||
|
ffStrbufAppendC(&absolutePath, '/');
|
||||||
|
ffStrbufAppendS(&absolutePath, relativeFile);
|
||||||
|
|
||||||
|
bool result = ffParsePropFileValues(absolutePath.chars, numQueries, queries);
|
||||||
|
|
||||||
|
ffStrbufDestroy(&absolutePath);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ffParsePropFileHome(const FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer)
|
||||||
|
{
|
||||||
|
return ffParsePropFileHomeValues(instance, relativeFile, 1, (FFpropquery[]){{start, buffer}});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ffParsePropFileConfigValues(const FFinstance* instance, const char* relativeFile, uint32_t numQueries, FFpropquery* queries)
|
||||||
|
{
|
||||||
|
bool foundAFile = false;
|
||||||
|
|
||||||
|
FFstrbuf baseDir;
|
||||||
|
ffStrbufInitA(&baseDir, 64);
|
||||||
|
|
||||||
|
for(uint32_t i = 0; i < instance->state.configDirs.length; i++)
|
||||||
|
{
|
||||||
|
//We need to copy the config dir each time, because it used by multiple threads, so we can't directly write to it.
|
||||||
|
ffStrbufSet(&baseDir, ffListGet(&instance->state.configDirs, i));
|
||||||
|
ffStrbufAppendS(&baseDir, relativeFile);
|
||||||
|
|
||||||
|
if(ffParsePropFileValues(baseDir.chars, numQueries, queries))
|
||||||
|
foundAFile = true;
|
||||||
|
|
||||||
|
bool allSet = true;
|
||||||
|
for(uint32_t k = 0; k < numQueries; k++)
|
||||||
|
{
|
||||||
|
if(queries[k].buffer->length == 0)
|
||||||
|
{
|
||||||
|
allSet = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(allSet)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ffStrbufDestroy(&baseDir);
|
||||||
|
|
||||||
|
return foundAFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ffParsePropFileConfig(const FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer)
|
||||||
|
{
|
||||||
|
return ffParsePropFileConfigValues(instance, relativeFile, 1, (FFpropquery[]){{start, buffer}});
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef FF_INCLUDED_common_properties
|
||||||
|
#define FF_INCLUDED_common_properties
|
||||||
|
|
||||||
|
#include "fastfetch.h"
|
||||||
|
|
||||||
|
typedef struct FFpropquery
|
||||||
|
{
|
||||||
|
const char* start;
|
||||||
|
FFstrbuf* buffer;
|
||||||
|
} FFpropquery;
|
||||||
|
|
||||||
|
bool ffParsePropLine(const char* line, const char* start, FFstrbuf* buffer);
|
||||||
|
bool ffParsePropLines(const char* lines, const char* start, FFstrbuf* buffer);
|
||||||
|
bool ffParsePropFileValues(const char* filename, uint32_t numQueries, FFpropquery* queries);
|
||||||
|
bool ffParsePropFile(const char* filename, const char* start, FFstrbuf* buffer);
|
||||||
|
bool ffParsePropFileHomeValues(const FFinstance* instance, const char* relativeFile, uint32_t numQueries, FFpropquery* queries);
|
||||||
|
bool ffParsePropFileHome(const FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer);
|
||||||
|
bool ffParsePropFileConfigValues(const FFinstance* instance, const char* relativeFile, uint32_t numQueries, FFpropquery* queries);
|
||||||
|
bool ffParsePropFileConfig(const FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,359 @@
|
|||||||
|
#include "fastfetch.h"
|
||||||
|
#include "common/settings.h"
|
||||||
|
#include "common/library.h"
|
||||||
|
#include "common/thread.h"
|
||||||
|
#include "common/io.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
typedef enum FFInitState
|
||||||
|
{
|
||||||
|
FF_INITSTATE_UNINITIALIZED = 0,
|
||||||
|
FF_INITSTATE_SUCCESSFUL = 1,
|
||||||
|
FF_INITSTATE_FAILED = 2
|
||||||
|
} FFInitState;
|
||||||
|
|
||||||
|
#define FF_LIBRARY_DATA_LOAD_INIT(dataObject, userLibraryName, ...) \
|
||||||
|
static dataObject data; \
|
||||||
|
static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER; \
|
||||||
|
static FFInitState initState = FF_INITSTATE_UNINITIALIZED; \
|
||||||
|
ffThreadMutexLock(&mutex); \
|
||||||
|
if(initState != FF_INITSTATE_UNINITIALIZED) {\
|
||||||
|
ffThreadMutexUnlock(&mutex); \
|
||||||
|
return initState == FF_INITSTATE_SUCCESSFUL ? &data : NULL; \
|
||||||
|
} \
|
||||||
|
initState = FF_INITSTATE_SUCCESSFUL; \
|
||||||
|
void* libraryHandle = ffLibraryLoad(&userLibraryName, __VA_ARGS__, NULL); \
|
||||||
|
if(libraryHandle == NULL) { \
|
||||||
|
initState = FF_INITSTATE_FAILED; \
|
||||||
|
ffThreadMutexUnlock(&mutex); \
|
||||||
|
return NULL; \
|
||||||
|
} \
|
||||||
|
|
||||||
|
#define FF_LIBRARY_DATA_LOAD_SYMBOL(symbolName) \
|
||||||
|
data.ff ## symbolName = dlsym(libraryHandle, #symbolName); \
|
||||||
|
if(data.ff ## symbolName == NULL) { \
|
||||||
|
dlclose(libraryHandle); \
|
||||||
|
initState = FF_INITSTATE_FAILED; \
|
||||||
|
ffThreadMutexUnlock(&mutex); \
|
||||||
|
return NULL; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FF_LIBRARY_DATA_LOAD_RETURN \
|
||||||
|
initState = FF_INITSTATE_SUCCESSFUL; \
|
||||||
|
ffThreadMutexUnlock(&mutex); \
|
||||||
|
return &data;
|
||||||
|
|
||||||
|
#define FF_LIBRARY_DATA_LOAD_ERROR \
|
||||||
|
{ \
|
||||||
|
dlclose(libraryHandle); \
|
||||||
|
initState = FF_INITSTATE_FAILED; \
|
||||||
|
ffThreadMutexUnlock(&mutex); \
|
||||||
|
return NULL; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef FF_HAVE_GIO
|
||||||
|
#include <gio/gio.h>
|
||||||
|
|
||||||
|
typedef struct GVariantGetters
|
||||||
|
{
|
||||||
|
FF_LIBRARY_SYMBOL(g_variant_get_string)
|
||||||
|
FF_LIBRARY_SYMBOL(g_variant_get_boolean)
|
||||||
|
FF_LIBRARY_SYMBOL(g_variant_get_int32)
|
||||||
|
} GVariantGetters;
|
||||||
|
|
||||||
|
static FFvariant getGVariantValue(GVariant* variant, FFvarianttype type, const GVariantGetters* variantGetters)
|
||||||
|
{
|
||||||
|
if(variant == NULL)
|
||||||
|
return FF_VARIANT_NULL;
|
||||||
|
else if(type == FF_VARIANT_TYPE_STRING)
|
||||||
|
return (FFvariant) {.strValue = variantGetters->ffg_variant_get_string(variant, NULL)};
|
||||||
|
else if(type == FF_VARIANT_TYPE_BOOL)
|
||||||
|
return (FFvariant) {.boolValue = (bool) variantGetters->ffg_variant_get_boolean(variant), .boolValueSet = true};
|
||||||
|
else if(type == FF_VARIANT_TYPE_INT)
|
||||||
|
return (FFvariant) {.intValue = variantGetters->ffg_variant_get_int32(variant)};
|
||||||
|
else
|
||||||
|
return FF_VARIANT_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct GSettingsData
|
||||||
|
{
|
||||||
|
FF_LIBRARY_SYMBOL(g_settings_schema_source_lookup)
|
||||||
|
FF_LIBRARY_SYMBOL(g_settings_schema_has_key)
|
||||||
|
FF_LIBRARY_SYMBOL(g_settings_new_full)
|
||||||
|
FF_LIBRARY_SYMBOL(g_settings_get_value)
|
||||||
|
FF_LIBRARY_SYMBOL(g_settings_get_user_value)
|
||||||
|
FF_LIBRARY_SYMBOL(g_settings_get_default_value)
|
||||||
|
FF_LIBRARY_SYMBOL(g_settings_schema_source_get_default)
|
||||||
|
GSettingsSchemaSource* schemaSource;
|
||||||
|
GVariantGetters variantGetters;
|
||||||
|
} GSettingsData;
|
||||||
|
|
||||||
|
static const GSettingsData* getGSettingsData(const FFinstance* instance)
|
||||||
|
{
|
||||||
|
FF_LIBRARY_DATA_LOAD_INIT(GSettingsData, instance->config.libGIO, "libgio-2.0" FF_LIBRARY_EXTENSION, 1);
|
||||||
|
|
||||||
|
FF_LIBRARY_DATA_LOAD_SYMBOL(g_settings_schema_source_lookup)
|
||||||
|
FF_LIBRARY_DATA_LOAD_SYMBOL(g_settings_schema_has_key)
|
||||||
|
FF_LIBRARY_DATA_LOAD_SYMBOL(g_settings_new_full)
|
||||||
|
FF_LIBRARY_DATA_LOAD_SYMBOL(g_settings_get_value)
|
||||||
|
FF_LIBRARY_DATA_LOAD_SYMBOL(g_settings_get_user_value)
|
||||||
|
FF_LIBRARY_DATA_LOAD_SYMBOL(g_settings_get_default_value)
|
||||||
|
FF_LIBRARY_DATA_LOAD_SYMBOL(g_settings_schema_source_get_default)
|
||||||
|
|
||||||
|
#define data data.variantGetters
|
||||||
|
FF_LIBRARY_DATA_LOAD_SYMBOL(g_variant_get_string)
|
||||||
|
FF_LIBRARY_DATA_LOAD_SYMBOL(g_variant_get_boolean)
|
||||||
|
FF_LIBRARY_DATA_LOAD_SYMBOL(g_variant_get_int32)
|
||||||
|
#undef data
|
||||||
|
|
||||||
|
data.schemaSource = data.ffg_settings_schema_source_get_default();
|
||||||
|
if(data.schemaSource == NULL)
|
||||||
|
FF_LIBRARY_DATA_LOAD_ERROR
|
||||||
|
|
||||||
|
FF_LIBRARY_DATA_LOAD_RETURN
|
||||||
|
}
|
||||||
|
|
||||||
|
FFvariant ffSettingsGetGSettings(const FFinstance* instance, const char* schemaName, const char* path, const char* key, FFvarianttype type)
|
||||||
|
{
|
||||||
|
const GSettingsData* data = getGSettingsData(instance);
|
||||||
|
if(data == NULL)
|
||||||
|
return FF_VARIANT_NULL;
|
||||||
|
|
||||||
|
GSettingsSchema* schema = data->ffg_settings_schema_source_lookup(data->schemaSource, schemaName, true);
|
||||||
|
if(schema == NULL)
|
||||||
|
return FF_VARIANT_NULL;
|
||||||
|
|
||||||
|
if(data->ffg_settings_schema_has_key(schema, key) == false)
|
||||||
|
return FF_VARIANT_NULL;
|
||||||
|
|
||||||
|
GSettings* settings = data->ffg_settings_new_full(schema, NULL, path);
|
||||||
|
if(settings == NULL)
|
||||||
|
return FF_VARIANT_NULL;
|
||||||
|
|
||||||
|
GVariant* variant = data->ffg_settings_get_value(settings, key);
|
||||||
|
if(variant != NULL)
|
||||||
|
return getGVariantValue(variant, type, &data->variantGetters);
|
||||||
|
|
||||||
|
variant = data->ffg_settings_get_user_value(settings, key);
|
||||||
|
if(variant != NULL)
|
||||||
|
return getGVariantValue(variant, type, &data->variantGetters);
|
||||||
|
|
||||||
|
variant = data->ffg_settings_get_default_value(settings, key);
|
||||||
|
return getGVariantValue(variant, type, &data->variantGetters);
|
||||||
|
}
|
||||||
|
#else //FF_HAVE_GIO
|
||||||
|
FFvariant ffSettingsGetGSettings(const FFinstance* instance, const char* schemaName, const char* path, const char* key, FFvarianttype type)
|
||||||
|
{
|
||||||
|
FF_UNUSED(instance, schemaName, path, key, type)
|
||||||
|
return FF_VARIANT_NULL;
|
||||||
|
}
|
||||||
|
#endif //FF_HAVE_GIO
|
||||||
|
|
||||||
|
#ifdef FF_HAVE_DCONF
|
||||||
|
#include <dconf.h>
|
||||||
|
|
||||||
|
typedef struct DConfData
|
||||||
|
{
|
||||||
|
FF_LIBRARY_SYMBOL(dconf_client_read_full)
|
||||||
|
FF_LIBRARY_SYMBOL(dconf_client_new)
|
||||||
|
GVariantGetters variantGetters;
|
||||||
|
DConfClient* client;
|
||||||
|
} DConfData;
|
||||||
|
|
||||||
|
static const DConfData* getDConfData(const FFinstance* instance)
|
||||||
|
{
|
||||||
|
FF_LIBRARY_DATA_LOAD_INIT(DConfData, instance->config.libDConf, "libdconf" FF_LIBRARY_EXTENSION, 2);
|
||||||
|
|
||||||
|
FF_LIBRARY_DATA_LOAD_SYMBOL(dconf_client_read_full)
|
||||||
|
FF_LIBRARY_DATA_LOAD_SYMBOL(dconf_client_new)
|
||||||
|
|
||||||
|
#define data data.variantGetters
|
||||||
|
FF_LIBRARY_DATA_LOAD_SYMBOL(g_variant_get_string)
|
||||||
|
FF_LIBRARY_DATA_LOAD_SYMBOL(g_variant_get_boolean)
|
||||||
|
FF_LIBRARY_DATA_LOAD_SYMBOL(g_variant_get_int32)
|
||||||
|
#undef data
|
||||||
|
|
||||||
|
data.client = data.ffdconf_client_new();
|
||||||
|
if(data.client == NULL)
|
||||||
|
FF_LIBRARY_DATA_LOAD_ERROR
|
||||||
|
|
||||||
|
FF_LIBRARY_DATA_LOAD_RETURN
|
||||||
|
}
|
||||||
|
|
||||||
|
FFvariant ffSettingsGetDConf(const FFinstance* instance, const char* key, FFvarianttype type)
|
||||||
|
{
|
||||||
|
const DConfData* data = getDConfData(instance);
|
||||||
|
if(data == NULL)
|
||||||
|
return FF_VARIANT_NULL;
|
||||||
|
|
||||||
|
GVariant* variant = data->ffdconf_client_read_full(data->client, key, DCONF_READ_FLAGS_NONE, NULL);
|
||||||
|
if(variant != NULL)
|
||||||
|
return getGVariantValue(variant, type, &data->variantGetters);
|
||||||
|
|
||||||
|
variant = data->ffdconf_client_read_full(data->client, key, DCONF_READ_USER_VALUE, NULL);
|
||||||
|
if(variant != NULL)
|
||||||
|
return getGVariantValue(variant, type, &data->variantGetters);
|
||||||
|
|
||||||
|
variant = data->ffdconf_client_read_full(data->client, key, DCONF_READ_DEFAULT_VALUE, NULL);
|
||||||
|
return getGVariantValue(variant, type, &data->variantGetters);
|
||||||
|
}
|
||||||
|
#else //FF_HAVE_DCONF
|
||||||
|
FFvariant ffSettingsGetDConf(const FFinstance* instance, const char* key, FFvarianttype type)
|
||||||
|
{
|
||||||
|
FF_UNUSED(instance, key, type)
|
||||||
|
return FF_VARIANT_NULL;
|
||||||
|
}
|
||||||
|
#endif //FF_HAVE_DCONF
|
||||||
|
|
||||||
|
FFvariant ffSettingsGet(const FFinstance* instance, const char* dconfKey, const char* gsettingsSchemaName, const char* gsettingsPath, const char* gsettingsKey, FFvarianttype type)
|
||||||
|
{
|
||||||
|
FFvariant gsettings = ffSettingsGetGSettings(instance, gsettingsSchemaName, gsettingsPath, gsettingsKey, type);
|
||||||
|
|
||||||
|
if(
|
||||||
|
(type == FF_VARIANT_TYPE_BOOL && gsettings.boolValueSet) ||
|
||||||
|
(type != FF_VARIANT_TYPE_BOOL && gsettings.strValue != NULL)
|
||||||
|
) return gsettings;
|
||||||
|
|
||||||
|
return ffSettingsGetDConf(instance, dconfKey, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef FF_HAVE_XFCONF
|
||||||
|
#include <xfconf/xfconf.h>
|
||||||
|
|
||||||
|
typedef struct XFConfData
|
||||||
|
{
|
||||||
|
FF_LIBRARY_SYMBOL(xfconf_channel_get)
|
||||||
|
FF_LIBRARY_SYMBOL(xfconf_channel_has_property)
|
||||||
|
FF_LIBRARY_SYMBOL(xfconf_channel_get_string)
|
||||||
|
FF_LIBRARY_SYMBOL(xfconf_channel_get_bool)
|
||||||
|
FF_LIBRARY_SYMBOL(xfconf_channel_get_int)
|
||||||
|
FF_LIBRARY_SYMBOL(xfconf_init)
|
||||||
|
} XFConfData;
|
||||||
|
|
||||||
|
static const XFConfData* getXFConfData(const FFinstance* instance)
|
||||||
|
{
|
||||||
|
FF_LIBRARY_DATA_LOAD_INIT(XFConfData, instance->config.libXFConf, "libxfconf-0" FF_LIBRARY_EXTENSION, 4);
|
||||||
|
|
||||||
|
FF_LIBRARY_DATA_LOAD_SYMBOL(xfconf_channel_get)
|
||||||
|
FF_LIBRARY_DATA_LOAD_SYMBOL(xfconf_channel_has_property)
|
||||||
|
FF_LIBRARY_DATA_LOAD_SYMBOL(xfconf_channel_get_string)
|
||||||
|
FF_LIBRARY_DATA_LOAD_SYMBOL(xfconf_channel_get_bool)
|
||||||
|
FF_LIBRARY_DATA_LOAD_SYMBOL(xfconf_channel_get_int)
|
||||||
|
FF_LIBRARY_DATA_LOAD_SYMBOL(xfconf_init)
|
||||||
|
|
||||||
|
if(data.ffxfconf_init(NULL) == false)
|
||||||
|
FF_LIBRARY_DATA_LOAD_ERROR
|
||||||
|
|
||||||
|
FF_LIBRARY_DATA_LOAD_RETURN
|
||||||
|
}
|
||||||
|
|
||||||
|
FFvariant ffSettingsGetXFConf(const FFinstance* instance, const char* channelName, const char* propertyName, FFvarianttype type)
|
||||||
|
{
|
||||||
|
const XFConfData* data = getXFConfData(instance);
|
||||||
|
if(data == NULL)
|
||||||
|
return FF_VARIANT_NULL;
|
||||||
|
|
||||||
|
XfconfChannel* channel = data->ffxfconf_channel_get(channelName); // Never fails according to documentation but rather returns an empty channel
|
||||||
|
|
||||||
|
if(!data->ffxfconf_channel_has_property(channel, propertyName))
|
||||||
|
return FF_VARIANT_NULL;
|
||||||
|
|
||||||
|
if(type == FF_VARIANT_TYPE_INT)
|
||||||
|
return (FFvariant) {.intValue = data->ffxfconf_channel_get_int(channel, propertyName, 0)};
|
||||||
|
|
||||||
|
if(type == FF_VARIANT_TYPE_STRING)
|
||||||
|
return (FFvariant) {.strValue = data->ffxfconf_channel_get_string(channel, propertyName, NULL)};
|
||||||
|
|
||||||
|
if(type == FF_VARIANT_TYPE_BOOL)
|
||||||
|
return (FFvariant) {.boolValue = data->ffxfconf_channel_get_bool(channel, propertyName, false), .boolValueSet = true};
|
||||||
|
|
||||||
|
return FF_VARIANT_NULL;
|
||||||
|
}
|
||||||
|
#else //FF_HAVE_XFCONF
|
||||||
|
FFvariant ffSettingsGetXFConf(const FFinstance* instance, const char* channelName, const char* propertyName, FFvarianttype type)
|
||||||
|
{
|
||||||
|
FF_UNUSED(instance, channelName, propertyName, type)
|
||||||
|
return FF_VARIANT_NULL;
|
||||||
|
}
|
||||||
|
#endif //FF_HAVE_XFCONF
|
||||||
|
|
||||||
|
#ifdef FF_HAVE_SQLITE3
|
||||||
|
#include <sqlite3.h>
|
||||||
|
|
||||||
|
typedef struct SQLiteData
|
||||||
|
{
|
||||||
|
FF_LIBRARY_SYMBOL(sqlite3_open_v2)
|
||||||
|
FF_LIBRARY_SYMBOL(sqlite3_prepare_v2)
|
||||||
|
FF_LIBRARY_SYMBOL(sqlite3_step)
|
||||||
|
FF_LIBRARY_SYMBOL(sqlite3_data_count)
|
||||||
|
FF_LIBRARY_SYMBOL(sqlite3_column_int)
|
||||||
|
FF_LIBRARY_SYMBOL(sqlite3_finalize)
|
||||||
|
FF_LIBRARY_SYMBOL(sqlite3_close)
|
||||||
|
} SQLiteData;
|
||||||
|
|
||||||
|
static const SQLiteData* getSQLiteData(const FFinstance* instance)
|
||||||
|
{
|
||||||
|
FF_LIBRARY_DATA_LOAD_INIT(SQLiteData, instance->config.libSQLite3, "libsqlite3" FF_LIBRARY_EXTENSION, 1);
|
||||||
|
|
||||||
|
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_open_v2)
|
||||||
|
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_prepare_v2)
|
||||||
|
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_step)
|
||||||
|
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_data_count)
|
||||||
|
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_column_int)
|
||||||
|
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_finalize)
|
||||||
|
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_close)
|
||||||
|
|
||||||
|
FF_LIBRARY_DATA_LOAD_RETURN
|
||||||
|
}
|
||||||
|
|
||||||
|
int ffSettingsGetSQLite3Int(const FFinstance* instance, const char* dbPath, const char* query)
|
||||||
|
{
|
||||||
|
if(!ffFileExists(dbPath, S_IFREG))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
const SQLiteData* data = getSQLiteData(instance);
|
||||||
|
if(data == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
sqlite3* db;
|
||||||
|
if(data->ffsqlite3_open_v2(dbPath, &db, SQLITE_OPEN_READONLY, NULL) != SQLITE_OK)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
sqlite3_stmt* stmt;
|
||||||
|
if(data->ffsqlite3_prepare_v2(db, query, (int) strlen(query), &stmt, NULL) != SQLITE_OK)
|
||||||
|
{
|
||||||
|
data->ffsqlite3_close(db);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(data->ffsqlite3_step(stmt) != SQLITE_ROW || data->ffsqlite3_data_count(stmt) < 1)
|
||||||
|
{
|
||||||
|
data->ffsqlite3_finalize(stmt);
|
||||||
|
data->ffsqlite3_close(db);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int result = data->ffsqlite3_column_int(stmt, 0);
|
||||||
|
|
||||||
|
data->ffsqlite3_finalize(stmt);
|
||||||
|
data->ffsqlite3_close(db);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#else //FF_HAVE_SQLITE3
|
||||||
|
int ffSettingsGetSQLite3Int(const FFinstance* instance, const char* dbPath, const char* query)
|
||||||
|
{
|
||||||
|
FF_UNUSED(instance, dbPath, query)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif //FF_HAVE_SQLITE3
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
#include <sys/system_properties.h>
|
||||||
|
void ffSettingsGetAndroidProperty(const char* propName, FFstrbuf* result) {
|
||||||
|
ffStrbufEnsureFree(result, PROP_VALUE_MAX);
|
||||||
|
result->length += (uint32_t) __system_property_get(propName, result->chars + result->length);
|
||||||
|
result->chars[result->length] = '\0';
|
||||||
|
}
|
||||||
|
#endif //__ANDROID__
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef FF_INCLUDED_common_settings
|
||||||
|
#define FF_INCLUDED_common_settings
|
||||||
|
|
||||||
|
#include "fastfetch.h"
|
||||||
|
|
||||||
|
typedef enum FFvarianttype
|
||||||
|
{
|
||||||
|
FF_VARIANT_TYPE_STRING,
|
||||||
|
FF_VARIANT_TYPE_BOOL,
|
||||||
|
FF_VARIANT_TYPE_INT
|
||||||
|
} FFvarianttype;
|
||||||
|
|
||||||
|
typedef union FFvariant
|
||||||
|
{
|
||||||
|
const char* strValue;
|
||||||
|
int32_t intValue;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
bool boolValueSet;
|
||||||
|
bool boolValue;
|
||||||
|
};
|
||||||
|
} FFvariant;
|
||||||
|
|
||||||
|
#define FF_VARIANT_NULL ((FFvariant){.strValue = NULL})
|
||||||
|
|
||||||
|
FFvariant ffSettingsGetDConf(const FFinstance* instance, const char* key, FFvarianttype type);
|
||||||
|
FFvariant ffSettingsGetGSettings(const FFinstance* instance, const char* schemaName, const char* path, const char* key, FFvarianttype type);
|
||||||
|
FFvariant ffSettingsGet(const FFinstance* instance, const char* dconfKey, const char* gsettingsSchemaName, const char* gsettingsPath, const char* gsettingsKey, FFvarianttype type);
|
||||||
|
FFvariant ffSettingsGetXFConf(const FFinstance* instance, const char* channelName, const char* propertyName, FFvarianttype type);
|
||||||
|
|
||||||
|
int ffSettingsGetSQLite3Int(const FFinstance* instance, const char* dbPath, const char* query);
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
void ffSettingsGetAndroidProperty(const char* propName, FFstrbuf* result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
#include "sysctl.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
const char* ffSysctlGetString(const char* propName, FFstrbuf* result)
|
||||||
|
{
|
||||||
|
size_t neededLength;
|
||||||
|
if(sysctlbyname(propName, NULL, &neededLength, NULL, 0) != 0 || neededLength == 1) //neededLength is 1 for empty strings, because of the null terminator
|
||||||
|
return "sysctlbyname() failed";
|
||||||
|
|
||||||
|
ffStrbufEnsureFree(result, (uint32_t) neededLength - 1);
|
||||||
|
|
||||||
|
if(sysctlbyname(propName, result->chars + result->length, &neededLength, NULL, 0) == 0)
|
||||||
|
result->length += (uint32_t) neededLength - 1;
|
||||||
|
|
||||||
|
result->chars[result->length] = '\0';
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ffSysctlGetInt(const char* propName, int defaultValue)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
size_t neededLength = sizeof(result);
|
||||||
|
if(sysctlbyname(propName, &result, &neededLength, NULL, 0) != 0)
|
||||||
|
return defaultValue;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t ffSysctlGetInt64(const char* propName, int64_t defaultValue)
|
||||||
|
{
|
||||||
|
int64_t result;
|
||||||
|
size_t neededLength = sizeof(result);
|
||||||
|
if(sysctlbyname(propName, &result, &neededLength, NULL, 0) != 0)
|
||||||
|
return defaultValue;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* ffSysctlGetData(int* request, u_int requestLength, size_t* resultLength)
|
||||||
|
{
|
||||||
|
if(sysctl(request, requestLength, NULL, resultLength, NULL, 0) != 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
void* data = malloc(*resultLength);
|
||||||
|
if(data == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if(sysctl(request, requestLength, data, resultLength, NULL, 0) != 0)
|
||||||
|
{
|
||||||
|
free(data);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef FF_INCLUDED_common_sysctl
|
||||||
|
#define FF_INCLUDED_common_sysctl
|
||||||
|
|
||||||
|
#include "fastfetch.h"
|
||||||
|
#include "util/FFcheckmacros.h"
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
|
||||||
|
const char* ffSysctlGetString(const char* propName, FFstrbuf* result);
|
||||||
|
FF_C_NODISCARD int ffSysctlGetInt(const char* propName, int defaultValue);
|
||||||
|
FF_C_NODISCARD int64_t ffSysctlGetInt64(const char* propName, int64_t defaultValue);
|
||||||
|
FF_C_NODISCARD void* ffSysctlGetData(int* request, u_int requestLength, size_t* resultLength);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef FF_INCLUDED_common_thread
|
||||||
|
#define FF_INCLUDED_common_thread
|
||||||
|
|
||||||
|
#include "fastfetch.h"
|
||||||
|
|
||||||
|
#ifdef FF_HAVE_THREADS
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#include <handleapi.h>
|
||||||
|
#include <synchapi.h>
|
||||||
|
#include <process.h>
|
||||||
|
#define FF_THREAD_MUTEX_INITIALIZER SRWLOCK_INIT
|
||||||
|
typedef SRWLOCK FFThreadMutex;
|
||||||
|
typedef HANDLE FFThreadType;
|
||||||
|
static inline void ffThreadMutexLock(FFThreadMutex* mutex) { AcquireSRWLockExclusive(mutex); }
|
||||||
|
static inline void ffThreadMutexUnlock(FFThreadMutex* mutex) { ReleaseSRWLockExclusive(mutex); }
|
||||||
|
static inline FFThreadType ffThreadCreate(unsigned (__stdcall* func)(void*), void* data) {
|
||||||
|
return (FFThreadType)_beginthreadex(NULL, 0, func, data, 0, NULL);
|
||||||
|
}
|
||||||
|
#define FF_THREAD_ENTRY_DECL_WRAPPER(fn, paramType) static __stdcall unsigned fn ## ThreadMain (void* data) { fn((paramType)data); return 0; }
|
||||||
|
static inline void ffThreadDetach(FFThreadType thread) { CloseHandle(thread); }
|
||||||
|
static inline void ffThreadJoin(FFThreadType thread) { WaitForSingleObject(thread, INFINITE); }
|
||||||
|
#else
|
||||||
|
#include <pthread.h>
|
||||||
|
#define FF_THREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
|
||||||
|
typedef pthread_mutex_t FFThreadMutex;
|
||||||
|
typedef pthread_t FFThreadType;
|
||||||
|
static inline void ffThreadMutexLock(FFThreadMutex* mutex) { pthread_mutex_lock(mutex); }
|
||||||
|
static inline void ffThreadMutexUnlock(FFThreadMutex* mutex) { pthread_mutex_unlock(mutex); }
|
||||||
|
static inline FFThreadType ffThreadCreate(void* (* func)(void*), void* data) {
|
||||||
|
FFThreadType newThread = 0;
|
||||||
|
pthread_create(&newThread, NULL, func, data);
|
||||||
|
return newThread;
|
||||||
|
}
|
||||||
|
#define FF_THREAD_ENTRY_DECL_WRAPPER(fn, paramType) static void* fn ## ThreadMain (void* data) { fn((paramType)data); return NULL; }
|
||||||
|
static inline void ffThreadDetach(FFThreadType thread) { pthread_detach(thread); }
|
||||||
|
static inline void ffThreadJoin(FFThreadType thread) { pthread_join(thread, NULL); }
|
||||||
|
#endif
|
||||||
|
#else //FF_HAVE_THREADS
|
||||||
|
#define FF_THREAD_MUTEX_INITIALIZER 0
|
||||||
|
typedef char FFThreadMutex;
|
||||||
|
static inline void ffThreadMutexLock(FFThreadMutex* mutex) { FF_UNUSED(mutex) }
|
||||||
|
static inline void ffThreadMutexUnlock(FFThreadMutex* mutex) { FF_UNUSED(mutex) }
|
||||||
|
#define FF_THREAD_ENTRY_DECL_WRAPPER(fn, paramType)
|
||||||
|
#endif //FF_HAVE_THREADS
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef FF_INCLUDED_common_time
|
||||||
|
#define FF_INCLUDED_common_time
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <synchapi.h>
|
||||||
|
#include <profileapi.h>
|
||||||
|
#else
|
||||||
|
#include <time.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline uint64_t ffTimeGetTick() //In msec
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
LARGE_INTEGER frequency;
|
||||||
|
QueryPerformanceFrequency(&frequency);
|
||||||
|
LARGE_INTEGER start;
|
||||||
|
QueryPerformanceCounter(&start);
|
||||||
|
return (uint64_t)(start.QuadPart * 1000 / frequency.QuadPart);
|
||||||
|
#else
|
||||||
|
struct timespec timeNow;
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &timeNow);
|
||||||
|
return (uint64_t)((timeNow.tv_sec * 1000) + (timeNow.tv_nsec / 1000000));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ffTimeSleep(uint32_t msec)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
SleepEx(msec, TRUE);
|
||||||
|
#else
|
||||||
|
nanosleep(&(struct timespec){ msec / 1000, (msec % 1000) * 1000000 }, NULL);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
# Fastfetch system configuration
|
||||||
|
# This file sets the default config for all users of the system.
|
||||||
|
|
||||||
|
# For more information about how configuration files work,
|
||||||
|
# see ~/.config/fastfetch/config.conf, generated during first run.
|
||||||
|
# All options that can be put there (or passed as argument) can be put here too.
|
||||||
|
|
||||||
|
# Use fastfetch --print-config-system > /etc/fastfetch/config.conf
|
||||||
|
# to overwrite this file with the current default file.
|
||||||
|
|
||||||
|
# User config option
|
||||||
|
# Sets if fastfetch should load user provided configuration.
|
||||||
|
# If this is off, fastfetch ignores the user config file and any passed arguments
|
||||||
|
# Must be true or false
|
||||||
|
# Default is true.
|
||||||
|
#--load-user-config true
|
||||||
@@ -0,0 +1,367 @@
|
|||||||
|
# Fastfetch configuration
|
||||||
|
# Write every argument in different lines.
|
||||||
|
# Direct arguments will overwrite the corresponding ones in this file.
|
||||||
|
# Argument keys are not case sensitive.
|
||||||
|
# Whitespaces are trimmed at the beginning and the end.
|
||||||
|
# Empty lines or lines starting with # are ignored.
|
||||||
|
|
||||||
|
# This file was shipped with $" FASTFETCH_PROJECT_VERSION $".
|
||||||
|
# Use fastfetch --print-config-user > ~/.config/fastfetch/config.conf to overwrite this file with the current defaults
|
||||||
|
|
||||||
|
# Below some often usefull options are listed. Uncomment and modify them so they take affect.
|
||||||
|
# Note that there are a lot more options than the ones listed here, take a look at "fastfetch --help".
|
||||||
|
# Of course all of them can be made persistent here too.
|
||||||
|
|
||||||
|
# Config option:
|
||||||
|
# Load additional config files.
|
||||||
|
# Some are shipped with fastfetch, list them with "fastfetch --list-presets".
|
||||||
|
# Must be a path to a config file or the name of a shipped preset.
|
||||||
|
# The config file is completly loaded before continuing in the current file, so the placement of this option matters, as later options overwrite already set ones.
|
||||||
|
# Can be used multiple times to load multiple config files / presets.
|
||||||
|
#--load-config /path/to/config.txt
|
||||||
|
|
||||||
|
# Structure option:
|
||||||
|
# Sets the modules to use and their order.
|
||||||
|
# Must be a list of module names, separated by colons.
|
||||||
|
# List available modules with "fastfetch --list-modules".
|
||||||
|
# Get the default structure with "fastfetch --print-structure".
|
||||||
|
#--structure $" FASTFETCH_DATATEXT_STRUCTURE $"
|
||||||
|
|
||||||
|
# Multithreading option:
|
||||||
|
# Sets if fastfetch should use multiple threads to detect the values.
|
||||||
|
# Must be true or false.
|
||||||
|
# Default is true.
|
||||||
|
#--multithreading true
|
||||||
|
|
||||||
|
# Print stat option:
|
||||||
|
# Sets if fastfetch should print time usage (in ms) for individual modules
|
||||||
|
# If true, it will also enable --show-errors
|
||||||
|
# Must be true or false.
|
||||||
|
# Default is false.
|
||||||
|
#--stat true
|
||||||
|
|
||||||
|
# Slow operations option:
|
||||||
|
# Sets if fastfetch is allowed to use known slow operations to detect more / better values.
|
||||||
|
# Must be true or false.
|
||||||
|
# Default is false.
|
||||||
|
#--allow-slow-operations false
|
||||||
|
|
||||||
|
# Linewrap option:
|
||||||
|
# Sets if fastfetch should disable linewrap during the run.
|
||||||
|
# Must be true or false.
|
||||||
|
# Default is true.
|
||||||
|
#--disable-linewrap true
|
||||||
|
|
||||||
|
# Cursor option:
|
||||||
|
# Sets if fastfetch should hide the console cursor during the run.
|
||||||
|
# Must be true or false.
|
||||||
|
# Default is true.
|
||||||
|
#--hide-cursor true
|
||||||
|
|
||||||
|
# Logo option:
|
||||||
|
# Sets the logo to use.
|
||||||
|
# List available logos with "fastfetch --list-logos".
|
||||||
|
# Print available logos with "fastfetch --print-logos".
|
||||||
|
# Must be the name of an available logo or a path to a text file containing a custom logo.
|
||||||
|
# Default is the current distribution.
|
||||||
|
#--logo arch
|
||||||
|
|
||||||
|
# Logo type option:
|
||||||
|
# Sets the logo type to use.
|
||||||
|
# Must be auto, builtin, file, file-raw, data, data-raw, sixel, kitty or chafa.
|
||||||
|
# Default is auto.
|
||||||
|
#--logo-type auto
|
||||||
|
|
||||||
|
# Logo width option:
|
||||||
|
# Sets the width of the logo (in characters) if the logo is an image.
|
||||||
|
# Must be a positive integer.
|
||||||
|
# Default is 65.
|
||||||
|
#--logo-width 65
|
||||||
|
|
||||||
|
# Logo height option:
|
||||||
|
# Sets the height of the logo (in characters) if the logo is an image.
|
||||||
|
# Must be a positive integer.
|
||||||
|
# Default is 0 (keeps aspect ration).
|
||||||
|
#--logo-height 0
|
||||||
|
|
||||||
|
# Logo color options:
|
||||||
|
# Overwrite a color in the logo. Also works for user provided logos.
|
||||||
|
# In the user logo, they replace $[1-9]. Use $$ to print a single $ sign.
|
||||||
|
# Must be linux console color codes or the name of a color.
|
||||||
|
# Default is the one specified by the logo.
|
||||||
|
# Use "fastfetch --help color" to learn more and see examples.
|
||||||
|
# Valid index range is [1-9].
|
||||||
|
#--logo-color-1 red
|
||||||
|
#--logo-color-2 32
|
||||||
|
# [...]
|
||||||
|
#--logo-color-9 yellow
|
||||||
|
|
||||||
|
# Logo padding option:
|
||||||
|
# Adds a padding to the left and the right side of the logo.
|
||||||
|
# Must be a positive integer.
|
||||||
|
# Default is 0.
|
||||||
|
#--logo-padding 0
|
||||||
|
|
||||||
|
# Logo padding left option:
|
||||||
|
# Adds a padding to the left side of the logo.
|
||||||
|
# Must be a positive integer.
|
||||||
|
# Default is 0.
|
||||||
|
#--logo-padding-left 0
|
||||||
|
|
||||||
|
# Logo padding right option:
|
||||||
|
# Adds a padding to the right side of the logo.
|
||||||
|
# Must be a positive integer.
|
||||||
|
# Default is 0.
|
||||||
|
#--logo-padding-right 0
|
||||||
|
|
||||||
|
# Logo print remaining option:
|
||||||
|
# Sets if the remaining logo should be printed, it is has more lines than modules to show.
|
||||||
|
# Must be true or false.
|
||||||
|
# Default is true.
|
||||||
|
#--logo-print-remaining true
|
||||||
|
|
||||||
|
# Color keys option:
|
||||||
|
# Sets the color of the keys.
|
||||||
|
# Must be linux console color codes or the name of a color.
|
||||||
|
# Default is the key color of the logo.
|
||||||
|
# Use "fastfetch --help color" to learn more and see examples.
|
||||||
|
#--color-keys magenta
|
||||||
|
|
||||||
|
# Color title option:
|
||||||
|
# Sets the color of the title.
|
||||||
|
# Must be linux console color codes or the name of a color.
|
||||||
|
# Default is the title color of the logo.
|
||||||
|
# Use "fastfetch --help color" to learn more and see examples.
|
||||||
|
#--color-title magenta
|
||||||
|
|
||||||
|
# Binary prefix option:
|
||||||
|
# Sets the binary prefix to use.
|
||||||
|
# Must be a IEC, SI or JEDEC.
|
||||||
|
# Default is IEC.
|
||||||
|
#--binary-prefix IEC
|
||||||
|
|
||||||
|
# Title FQDN option:
|
||||||
|
# Sets if the title should use the fully qualified domain name.
|
||||||
|
# Must be true or false.
|
||||||
|
# Default is false.
|
||||||
|
#--title-fqdn false
|
||||||
|
|
||||||
|
# Separator option:
|
||||||
|
# Sets the string placed between a key and its value.
|
||||||
|
# Can be any string.
|
||||||
|
# Default is ": ".
|
||||||
|
#--separator ": "
|
||||||
|
|
||||||
|
# Separator string option:
|
||||||
|
# Sets the string printed by the "separator" module (usually between title and rest of output)
|
||||||
|
# Must be any string. It is repated / cut to fit perfectly.
|
||||||
|
# Default is "-"
|
||||||
|
#--separator-string -
|
||||||
|
|
||||||
|
# Public IP URL option:
|
||||||
|
# Sets the URL of public IP detection server to be used.
|
||||||
|
# Only HTTP protocol is supported, and the value should not contain "http://" prefix.
|
||||||
|
# Default is "ipinfo.io/ip".
|
||||||
|
#--public-ip-url "ipinfo.io/ip"
|
||||||
|
|
||||||
|
# Public IP timeout option:
|
||||||
|
# Sets the time to wait for the public ip server to respond.
|
||||||
|
# Must be a positive integer.
|
||||||
|
# Default is 0 (disabled).
|
||||||
|
#--public-ip-timeout 0
|
||||||
|
|
||||||
|
# Weather output format option:
|
||||||
|
# Sets the weather format to be used. It must be URI encoded.
|
||||||
|
# See: https://github.com/chubin/wttr.in#one-line-output
|
||||||
|
# Default is "%t+-+%C+(%l)".
|
||||||
|
#--weather-output-format "%t+-+%C+(%l)"
|
||||||
|
|
||||||
|
# Weather timeout option:
|
||||||
|
# Sets the time to wait for the weather server (wttr.in) to respond.
|
||||||
|
# Must be a positive integer.
|
||||||
|
# Default is 0 (disabled).
|
||||||
|
#--weather-timeout 0
|
||||||
|
|
||||||
|
# OS file option
|
||||||
|
# Sets the path to the file containing the operating system information.
|
||||||
|
# Should be a valid path to an existing file.
|
||||||
|
# Default is /etc/os-release.
|
||||||
|
#--os-file /etc/os-release
|
||||||
|
|
||||||
|
# Player name option
|
||||||
|
# Sets the name of the player. This is also used in song detection
|
||||||
|
# Must be the exact name of the player or a dbus address (e.g. org.mpris.MediaPlayer2.spotify)
|
||||||
|
# Default is the first match starting with org.mpris.MediaPlayer2.
|
||||||
|
#--player-name spotify
|
||||||
|
|
||||||
|
# Escape bedrock option
|
||||||
|
# Sets if fastfetch should escape the bedrock jail, if it detectes that it is running in one
|
||||||
|
# Must be true or false.
|
||||||
|
# Default is true.
|
||||||
|
#--escape-bedrock true
|
||||||
|
|
||||||
|
# GL option
|
||||||
|
# Sets with opengl context creation library to use
|
||||||
|
# Must be either auto, egl, glx or osmesa
|
||||||
|
# Default is auto.
|
||||||
|
#--gl auto
|
||||||
|
|
||||||
|
# Percentage output type option
|
||||||
|
# Applies to all modules that prints percentage values. Currently memory, swap, disk, battery and CPU usage are supported.
|
||||||
|
# Only works with default format ( without --module-format option ).
|
||||||
|
# 0: prints none; 1: prints percent number only; 2: prints bar only; 3: prints both percent number and bar
|
||||||
|
#--percent-type 1
|
||||||
|
|
||||||
|
# Key options:
|
||||||
|
# Sets the displayed key of a module
|
||||||
|
# Can be any string. Some of theme take an argument like a format string. See "fastfetch --help format" for help.
|
||||||
|
#--os-key OS
|
||||||
|
#--host-key Host
|
||||||
|
#--chassis-key Chassis
|
||||||
|
#--kernel-key Kernel
|
||||||
|
#--uptime-key Uptime
|
||||||
|
#--processes-key Processes
|
||||||
|
#--packages-key Packages
|
||||||
|
#--shell-key Shell
|
||||||
|
#--resolution-key Resolution {1}
|
||||||
|
#--de-key DE
|
||||||
|
#--wm-key WM
|
||||||
|
#--wm-theme-key WM Theme
|
||||||
|
#--theme-key Theme
|
||||||
|
#--icons-key Icons
|
||||||
|
#--font-key Font
|
||||||
|
#--cursor-key Cursor
|
||||||
|
#--terminal-key Terminal
|
||||||
|
#--terminal-font-key Terminal Font
|
||||||
|
#--cpu-key CPU
|
||||||
|
#--cpu-usage-key CPU Usage
|
||||||
|
#--gpu-key GPU {1}
|
||||||
|
#--memory-key Memory
|
||||||
|
#--swap-key Swap
|
||||||
|
#--disk-key Disk ({1})
|
||||||
|
#--battery-key Battery {1}
|
||||||
|
#--poweradapter-key Power Adapter {1}
|
||||||
|
#--locale-key Locale
|
||||||
|
#--local-ip-key Local IP ({1})
|
||||||
|
#--public-ip-key Public IP
|
||||||
|
#--wifi-key Wifi
|
||||||
|
#--weather-key Weather
|
||||||
|
#--player-key Media Player
|
||||||
|
#--media-key Media
|
||||||
|
#--datetime-key Date Time
|
||||||
|
#--vulkan-key Vulkan
|
||||||
|
#--opengl-key OpenGL
|
||||||
|
#--opencl-key OpenCL
|
||||||
|
#--users-key Users
|
||||||
|
|
||||||
|
# Format options:
|
||||||
|
# Sets the format string for module values.
|
||||||
|
# For information on format strings, see "fastfetch --help format".
|
||||||
|
# To see the parameter they take and their default value, see "fastfetch --help *-format", e.g. "fastfetch --help os-format".
|
||||||
|
# An empty format string (As they are currently below) will behave as if it was not set.
|
||||||
|
#--os-format
|
||||||
|
#--host-format
|
||||||
|
#--chassis-format
|
||||||
|
#--kernel-format
|
||||||
|
#--uptime-format
|
||||||
|
#--processes-format
|
||||||
|
#--packages-format
|
||||||
|
#--shell-format
|
||||||
|
#--resolution-format
|
||||||
|
#--de-format
|
||||||
|
#--wm-format
|
||||||
|
#--wm-theme-format
|
||||||
|
#--theme-format
|
||||||
|
#--icons-format
|
||||||
|
#--font-format
|
||||||
|
#--cursor-format
|
||||||
|
#--terminal-format
|
||||||
|
#--terminal-font-format
|
||||||
|
#--cpu-format
|
||||||
|
#--cpu-usage-format
|
||||||
|
#--gpu-format
|
||||||
|
#--memory-format
|
||||||
|
#--swap-format
|
||||||
|
#--disk-format
|
||||||
|
#--battery-format
|
||||||
|
#--poweradapter-format
|
||||||
|
#--locale-format
|
||||||
|
#--local-ip-format
|
||||||
|
#--public-ip-format
|
||||||
|
#--weather-format
|
||||||
|
#--player-format
|
||||||
|
#--media-format
|
||||||
|
#--datetime-format
|
||||||
|
#--vulkan-format
|
||||||
|
#--opengl-format
|
||||||
|
#--opencl-format
|
||||||
|
#--users-format
|
||||||
|
|
||||||
|
# Error options:
|
||||||
|
# Sets the format string to use if an error occured
|
||||||
|
# For information on format strings, see "fastfetch --help format".
|
||||||
|
# Each of them take the error as first and only argument.
|
||||||
|
# If one of them is set, the module will appear, even if --show-errors is not given.
|
||||||
|
#--os-error
|
||||||
|
#--host-error
|
||||||
|
#--chassis-error
|
||||||
|
#--kernel-error
|
||||||
|
#--uptime-error
|
||||||
|
#--processes-error
|
||||||
|
#--packages-error
|
||||||
|
#--shell-error
|
||||||
|
#--resolution-error
|
||||||
|
#--de-error
|
||||||
|
#--wm-error
|
||||||
|
#--wm-theme-error
|
||||||
|
#--theme-error
|
||||||
|
#--icons-error
|
||||||
|
#--font-error
|
||||||
|
#--cursor-error
|
||||||
|
#--terminal-error
|
||||||
|
#--terminal-font-error
|
||||||
|
#--cpu-error
|
||||||
|
#--cpu-usage-error
|
||||||
|
#--gpu-error
|
||||||
|
#--memory-error
|
||||||
|
#--swap-error
|
||||||
|
#--disk-error
|
||||||
|
#--battery-error
|
||||||
|
#--poweradapter-error
|
||||||
|
#--locale-error
|
||||||
|
#--local-ip-error
|
||||||
|
#--public-ip-error
|
||||||
|
#--weather-error
|
||||||
|
#--player-error
|
||||||
|
#--media-error
|
||||||
|
#--datetime-error
|
||||||
|
#--vulkan-error
|
||||||
|
#--opengl-error
|
||||||
|
#--opencl-error
|
||||||
|
#--users-error
|
||||||
|
|
||||||
|
# Library options:
|
||||||
|
# Sets an user specific path to a library to load.
|
||||||
|
# Must be a valid path to a library.
|
||||||
|
#--lib-PCI /usr/lib/libpci.so
|
||||||
|
#--lib-vulkan /usr/lib/libvulkan.so (libMoltenVK.dylib on macOS)
|
||||||
|
#--lib-wayland /usr/lib/libwayland-client.so
|
||||||
|
#--lib-xcb-randr /usr/lib/libxcb-randr.so
|
||||||
|
#--lib-xcb /usr/lib/libxcb.so
|
||||||
|
#--lib-Xrandr /usr/lib/libXrandr.so
|
||||||
|
#--lib-X11 /usr/lib/libX11.so
|
||||||
|
#--lib-gio /usr/lib/libgio-2.0.so
|
||||||
|
#--lib-DConf /usr/lib/libdconf.so
|
||||||
|
#--lib-DBus /usr/lib/libdbus-1.so
|
||||||
|
#--lib-XFConf /usr/lib/libxfconf-0.so
|
||||||
|
#--lib-sqlite3 /usr/lib/libsqlite3.so
|
||||||
|
#--lib-rpm /usr/lib/librpm.so
|
||||||
|
#--lib-imagemagick /usr/lib/libMagickCore-7.Q16HDRI.so
|
||||||
|
#--lib-z /usr/lib/libz.so
|
||||||
|
#--lib-chafa /usr/lib/libchafa.so
|
||||||
|
#--lib-egl /usr/lib/libEGL.so
|
||||||
|
#--lib-glx /usr/lib/libGLX.so
|
||||||
|
#--lib-osmesa /usr/lib/libOSMesa.so
|
||||||
|
#--lib-opencl /usr/lib/libOpenCL.so
|
||||||
|
#--lib-cjson /usr/lib/libcjson.so
|
||||||
|
#--lib-freetype /data/data/com.termux/files/usr/lib
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
Usage: fastfetch <options>
|
||||||
|
|
||||||
|
Informative options:
|
||||||
|
-h,--help: Show this message
|
||||||
|
-h,--help <command>: Show help for a specific command
|
||||||
|
-v,--version: Show the version of fastfetch
|
||||||
|
--list-logos: List available logos
|
||||||
|
--list-modules: List available modules
|
||||||
|
--list-presets: List presets fastfetch knows about; they can be loaded with --load-config (+)
|
||||||
|
--list-features: List the supported features fastfetch was compiled with (mainly for development)
|
||||||
|
--print-logos: Print available logos
|
||||||
|
--print-config-system: Print the default system config
|
||||||
|
--print-config-user: Print the default user config
|
||||||
|
--print-structure: Print the default structure
|
||||||
|
|
||||||
|
General options:
|
||||||
|
--load-config <file>: Load a config file or preset (+)
|
||||||
|
--multithreading <?value>: Use multiple threads to detect values
|
||||||
|
--stat <?value>: Show time usage (in ms) for individual modules
|
||||||
|
--allow-slow-operations <?value>: Allow operations that are usually very slow for more detailed output
|
||||||
|
--escape-bedrock <?value>: On Bedrock Linux, whether to escape the bedrock jail
|
||||||
|
--pipe <?value>: Disable logo and all escape sequences
|
||||||
|
|
||||||
|
Logo options:
|
||||||
|
-l,--logo <logo>: Set the logo; if default, the name of a builtin logo or a path to a file
|
||||||
|
--logo-type <type>: Set the type of the logo given; must be auto, builtin, file, file-raw, data, data-raw, sixel, kitty, iterm or chafa
|
||||||
|
--logo-width <width>: Set the width of the logo (in characters), if it is an image. Required for iTerm image protocol
|
||||||
|
--logo-height <height>: Set the height of the logo (in characters), if it is an image. Required for iTerm image protocol
|
||||||
|
--logo-preserve-aspect-radio <?value>: Set if the logo should fill the specified width and height as much as possible without stretching. Supported by iTerm image protocol
|
||||||
|
--logo-color-[1-9] <color>: Overwrite a color in the logo
|
||||||
|
--logo-padding <padding>: Set the padding on the left and the right of the logo
|
||||||
|
--logo-padding-left <padding>: Set the padding on the left of the logo
|
||||||
|
--logo-padding-right <padding>: Set the padding on the right of the logo
|
||||||
|
--logo-print-remaining <?value>: Whether to print the remaining logo, if it has more lines than modules to display
|
||||||
|
--file <file>: Short for --logo-type file --logo <file>
|
||||||
|
--file-raw <file>: Short for --logo-type file-raw --logo <file>
|
||||||
|
--data <data>: Short for --logo-type data --logo <data>
|
||||||
|
--data-raw <data>: Short for --logo-type data-raw --logo <data>
|
||||||
|
--sixel <file>: Short for --logo-type sixel --logo <file>
|
||||||
|
--kitty <file>: Short for --logo-type kitty --logo <file>
|
||||||
|
--iterm <file>: Short for --logo-type iterm --logo <file>
|
||||||
|
--chafa <file>: Short for --logo-type chafa --logo <file>
|
||||||
|
--chafa-fg-only <?value>: Produce character-cell output using foreground colors only. See chafa document for detail
|
||||||
|
--chafa-symbols <str>: Specify character symbols to employ in final output. See chafa document for detail
|
||||||
|
--chafa-canvas-mode <value>: Determine how colors are used in the output. This value maps the int value of enum ChafaCanvasMode. See chafa document for detail
|
||||||
|
--chafa-color-space <value>: Set color space used for quantization. 0 for RGB; 1 for DIN99d. See chafa document for detail
|
||||||
|
--chafa-dither-mode <value>: Set output dither mode (No effect with 24-bit color). This value maps the int value of enum ChafaDitherMode. See chafa document for detail
|
||||||
|
|
||||||
|
Display options:
|
||||||
|
-s,--structure <structure>: Set the structure of the fetch. Must be a colon separated list of keys. Use "fastfetch --list-modules" to see the ones available.
|
||||||
|
--color-keys <color>: Set the color of the keys
|
||||||
|
--color-title <color>: Set the color of the title
|
||||||
|
-c,--color <color>: Set the color of both the keys and title
|
||||||
|
--separator <str>: Set the separator between key and value. Default is a colon with a space
|
||||||
|
--set <key=value>: Hard set the value of a key
|
||||||
|
--set-keyless <key=value>: Hard set the value of a key, but don't print the key or the separator
|
||||||
|
--show-errors <?value>: Print occurring errors
|
||||||
|
--disable-linewrap <?value>: Whether to disable line wrap during the run
|
||||||
|
--hide-cursor <?value>: Whether to hide the cursor during the run
|
||||||
|
--binary-prefix <value>: Set the binary prefix to used. Must be IEC, SI or JEDEC. Default is IEC.
|
||||||
|
|
||||||
|
General module options:
|
||||||
|
--<module>-format <format>: Set the format string to use for each specific module.
|
||||||
|
To see how a format string works, use fastfetch --help format.
|
||||||
|
To see help about a specific format string, use fastfetch --help <module>-format.
|
||||||
|
|
||||||
|
--<module>-key <key>: Set the key to use for each specific module.
|
||||||
|
For modules which print multiple lines, the string is parsed as a format string with the index as first character.
|
||||||
|
|
||||||
|
--<module>-error <format>: Set the error format string to use for each specific module.
|
||||||
|
The error is given as the first and only argument.
|
||||||
|
Setting this for a module will cause it to appear, even if --show-errors is not given.
|
||||||
|
|
||||||
|
Library options: Set the path of a library to load
|
||||||
|
--lib-PCI <path>
|
||||||
|
--lib-vulkan <path>
|
||||||
|
--lib-wayland <path>
|
||||||
|
--lib-xcb-randr <path>
|
||||||
|
--lib-xcb <path>
|
||||||
|
--lib-Xrandr <path>
|
||||||
|
--lib-X11 <path>
|
||||||
|
--lib-gio <path>
|
||||||
|
--lib-DConf <path>
|
||||||
|
--lib-DBus <path>
|
||||||
|
--lib-XFConf <path>
|
||||||
|
--lib-sqlite3 <path>
|
||||||
|
--lib-rpm <path>
|
||||||
|
--lib-imagemagick <path>
|
||||||
|
--lib-z <path>
|
||||||
|
--lib-chafa <path>
|
||||||
|
--lib-egl <path>
|
||||||
|
--lib-glx <path>
|
||||||
|
--lib-osmesa <path>
|
||||||
|
--lib-opencl <path>
|
||||||
|
--lib-cjson <path>
|
||||||
|
|
||||||
|
Module specific options:
|
||||||
|
--title-fqdn <?value>: Set if the title should use fully qualified domain name. Default is false
|
||||||
|
--separator-string <str>: Set the string printed by the separator module
|
||||||
|
--os-file <path>: Set the path to the file containing OS information
|
||||||
|
--disk-folders <folders>: A colon (semicolon on Windows) separated list of folder paths for the disk output. Default is "/:/home" ("C:\\;D:\\ ..." on Windows)
|
||||||
|
--disk-show-removable <?value>: Set if removable volume should be printed. Default is true
|
||||||
|
--disk-show-hidden <?value>: Set if hidden volumes should be printed. Default is false
|
||||||
|
--battery-dir <folder>: The directory where the battery folders are. Standard: /sys/class/power_supply/
|
||||||
|
--cpu-temp <?value>: Detect and display CPU temperature if supported. Default is false
|
||||||
|
--gpu-temp <?value>: Detect and display GPU temperature if supported. Default is false
|
||||||
|
--battery-temp <?value>: Detect and display Battery temperature if supported. Default is false
|
||||||
|
--localip-show-ipv4 <?value>: Show IPv4 addresses in local ip module. Default is true
|
||||||
|
--localip-show-ipv6 <?value>: Show IPv6 addresses in local ip module. Default is false
|
||||||
|
--localip-show-loop <?value>: Show loop back addresses (127.0.0.1) in local ip module. Default is false
|
||||||
|
--localip-name-prefix <str>: Show IPs with given name prefix only. Default is empty
|
||||||
|
--public-ip-timeout: Time in milliseconds to wait for the public ip server to respond. Default is disabled (0)
|
||||||
|
--public-ip-url: The URL of public IP detection server to be used.
|
||||||
|
--weather-timeout: Time in milliseconds to wait for the weather server to respond. Default is disabled (0)
|
||||||
|
--weather-output-format: The output weather format to be used. It must be URI encoded.
|
||||||
|
--player-name: The name of the player to use
|
||||||
|
--gl <value>: Set the OpenGL context creation library to use. Must be auto, egl, glx or osmesa. Default is auto
|
||||||
|
--percent-type <value>: Set the percentage output type. 1 for percentage number, 2 for bar, 3 for both. Default is 1
|
||||||
|
|
||||||
|
Parsing is not case sensitive. E.g. "--lib-PCI" is equal to "--Lib-Pci"
|
||||||
|
If a value starts with a ?, it is optional. "true" will be used if not set.
|
||||||
|
A (+) at the end indicates that more help can be printed with --help <option>
|
||||||
|
All options can be made permanent in $XDG_CONFIG_HOME/fastfetch/config.conf
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
usage: fastfetch --color <color>
|
||||||
|
|
||||||
|
<color> must be a color encoding for linux terminals. It is inserted between "ESC[" and "m".
|
||||||
|
Infos about them can be found here: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters.
|
||||||
|
Examples:
|
||||||
|
--color 35: sets the color to pink
|
||||||
|
--color 4;92: sets the color to bright Green with underline
|
||||||
|
--color 5;104: blinking text on a blue background
|
||||||
|
If no color is set, the main color of the logo will be used.
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
usage: fastfetch --load-config <file>
|
||||||
|
|
||||||
|
Loads a config file. A config file contains one flag per line. Empty lines or lines starting with # are ignored.
|
||||||
|
If the file is relative it looks in the following order:
|
||||||
|
- relative to the current working directory
|
||||||
|
- relative to ~/.local/share/fastfetch/presets/
|
||||||
|
- relative to /usr/share/fastfetch/presets/
|
||||||
|
Fastfetch provides some default presets. List them with --print-available-presets.
|
||||||
|
Note that this will only print presets fastfetch knows about and not every possible one.
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
A format string is a string that contains placeholders for values.
|
||||||
|
These placeholders begin with a '{', containing the index of the value, and end with a '}'.
|
||||||
|
For example the format string "Values: {1} ({2})", with the values "First" and "My second val", will produce
|
||||||
|
The format string can contain placeholders in any order and have multiple occurences.
|
||||||
|
To include spaces when setting from the command line, surround the whole string with double quotes (").
|
||||||
|
|
||||||
|
If the value index is missing, meaning the placeholder is "{}", an internal counter sets the value index.
|
||||||
|
This means that the format string "Values: {1} ({2})" is equivalent to "Values: {} ({})".
|
||||||
|
Note that this counter only counts empty placeholders, so the format string "{2} {} {}" will contain the second v
|
||||||
|
|
||||||
|
To make formatting easier, a double open curly brace ("{{") will be printed as a single open curly brace and not
|
||||||
|
If a value index is misformatted or wants a non-existing value, it will be printed as is, with the curly braces aro
|
||||||
|
If the last placeholder isn't closed, it will be treated like it was at the end of the format string.
|
||||||
|
|
||||||
|
To only print something if a variable is set, use "{?<index>} ... {?}".
|
||||||
|
For example, to only print a second value if it is set, use "{?2} Second value: {2}{?}".
|
||||||
|
If a "{?}" is found without an opener, it is printed as is.
|
||||||
|
|
||||||
|
To only print something if a variable is not set, do the same as with if, just replace every '?' with a '!'.
|
||||||
|
For example to print a fallback for a second value if it is not set, use "{?2}{2}{?}{/2}Second value fallback{/}"
|
||||||
|
|
||||||
|
To stop formatting at any point in the format string, use "{-}".
|
||||||
|
|
||||||
|
To print something with color, start a placeholder with a '#' and then the linux terminal color encoding.
|
||||||
|
"\\033[" at the start, and an 'm' at the end is automatically added, so don't do that.
|
||||||
|
A "{#}" is equivalent to a "{#0}" and resets everything to normal.
|
||||||
|
For example to print something pink and underline, use "{#4;35}...{#}".
|
||||||
|
Information about what the numbers mean can be found here: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Sele
|
||||||
|
Which escape codes are supported and how they look is defined by your terminal.
|
||||||
|
|
||||||
|
If a format string evaluates to an empty value, the whole line in the output will be discarded.
|
||||||
|
You can therefore use --host-format " " to disable host output.
|
||||||
|
Note that --host-format "" would evaluate as not set, and therefore use the built-in host format
|
||||||
|
|
||||||
|
Format string is also the way to go to set a fixed value - just use one without placeholders.
|
||||||
|
For example when running in headless mode, you could use "--resolution-format "Preferred".
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
Battery
|
||||||
|
Bios
|
||||||
|
Board
|
||||||
|
Break
|
||||||
|
Chassis
|
||||||
|
Colors
|
||||||
|
CPU
|
||||||
|
CPUUsage
|
||||||
|
Cursor
|
||||||
|
Date
|
||||||
|
Datetime
|
||||||
|
DE
|
||||||
|
Disk
|
||||||
|
Font
|
||||||
|
GPU
|
||||||
|
Host
|
||||||
|
Icons
|
||||||
|
Kernel
|
||||||
|
Locale
|
||||||
|
LocalIP
|
||||||
|
Media
|
||||||
|
Memory
|
||||||
|
OpenGL
|
||||||
|
OS
|
||||||
|
Packages
|
||||||
|
Player
|
||||||
|
PowerAdapter
|
||||||
|
Processes
|
||||||
|
PublicIP
|
||||||
|
Resolution
|
||||||
|
Separator
|
||||||
|
Shell
|
||||||
|
Swap
|
||||||
|
Terminal
|
||||||
|
TerminalFont
|
||||||
|
Theme
|
||||||
|
Time
|
||||||
|
Title
|
||||||
|
Uptime
|
||||||
|
Vulkan
|
||||||
|
Weather
|
||||||
|
Wifi
|
||||||
|
WM
|
||||||
|
WMTheme
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Title:Separator:OS:Host:Kernel:Uptime:Packages:Shell:Resolution:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:GPU:Memory:Disk:Battery:PowerAdapter:Locale:Break:Colors
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef FF_INCLUDED_detection_battery_battery
|
||||||
|
#define FF_INCLUDED_detection_battery_battery
|
||||||
|
|
||||||
|
#include "fastfetch.h"
|
||||||
|
|
||||||
|
#define FF_BATTERY_TEMP_UNSET (0/0.0)
|
||||||
|
|
||||||
|
typedef struct BatteryResult
|
||||||
|
{
|
||||||
|
FFstrbuf manufacturer;
|
||||||
|
FFstrbuf modelName;
|
||||||
|
FFstrbuf technology;
|
||||||
|
double capacity;
|
||||||
|
FFstrbuf status;
|
||||||
|
double temperature;
|
||||||
|
} BatteryResult;
|
||||||
|
|
||||||
|
const char* ffDetectBatteryImpl(FFinstance* instance, FFlist* results);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
#include "fastfetch.h"
|
||||||
|
#include "battery.h"
|
||||||
|
#include "util/apple/cf_helpers.h"
|
||||||
|
#include "detection/temps/temps_apple.h"
|
||||||
|
|
||||||
|
#include <IOKit/IOKitLib.h>
|
||||||
|
|
||||||
|
static double detectBatteryTemp()
|
||||||
|
{
|
||||||
|
FF_LIST_AUTO_DESTROY temps;
|
||||||
|
ffListInit(&temps, sizeof(FFTempValue));
|
||||||
|
|
||||||
|
ffDetectCoreTemps(FF_TEMP_BATTERY, &temps);
|
||||||
|
|
||||||
|
if(temps.length == 0)
|
||||||
|
return FF_BATTERY_TEMP_UNSET;
|
||||||
|
|
||||||
|
double result = 0;
|
||||||
|
for(uint32_t i = 0; i < temps.length; ++i)
|
||||||
|
{
|
||||||
|
FFTempValue* tempValue = (FFTempValue*)ffListGet(&temps, i);
|
||||||
|
result += tempValue->value;
|
||||||
|
//TODO: do we really need this?
|
||||||
|
ffStrbufDestroy(&tempValue->name);
|
||||||
|
ffStrbufDestroy(&tempValue->deviceClass);
|
||||||
|
}
|
||||||
|
result /= temps.length;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* ffDetectBatteryImpl(FFinstance* instance, FFlist* results)
|
||||||
|
{
|
||||||
|
FF_UNUSED(instance);
|
||||||
|
|
||||||
|
CFMutableDictionaryRef matchDict = IOServiceMatching("AppleSmartBattery");
|
||||||
|
if (matchDict == NULL)
|
||||||
|
return "IOServiceMatching(\"AppleSmartBattery\") failed";
|
||||||
|
|
||||||
|
io_iterator_t iterator;
|
||||||
|
if(IOServiceGetMatchingServices(MACH_PORT_NULL, matchDict, &iterator) != kIOReturnSuccess)
|
||||||
|
return "IOServiceGetMatchingServices() failed";
|
||||||
|
|
||||||
|
io_registry_entry_t registryEntry;
|
||||||
|
while((registryEntry = IOIteratorNext(iterator)) != 0)
|
||||||
|
{
|
||||||
|
CFMutableDictionaryRef properties;
|
||||||
|
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
|
||||||
|
{
|
||||||
|
IOObjectRelease(registryEntry);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool boolValue;
|
||||||
|
const char* error;
|
||||||
|
|
||||||
|
BatteryResult* battery = ffListAdd(results);
|
||||||
|
battery->capacity = 0.0/0.0;
|
||||||
|
int currentCapacity, maxCapacity;
|
||||||
|
|
||||||
|
if ((error = ffCfDictGetInt(properties, CFSTR("MaxCapacity"), &maxCapacity)))
|
||||||
|
return error;
|
||||||
|
if (maxCapacity <= 0)
|
||||||
|
return "Querying MaxCapacity failed";
|
||||||
|
|
||||||
|
if ((error = ffCfDictGetInt(properties, CFSTR("CurrentCapacity"), ¤tCapacity)))
|
||||||
|
return error;
|
||||||
|
if(currentCapacity <= 0)
|
||||||
|
return "Querying CurrentCapacity failed";
|
||||||
|
|
||||||
|
battery->capacity = currentCapacity * 100.0 / maxCapacity;
|
||||||
|
|
||||||
|
ffStrbufInit(&battery->manufacturer);
|
||||||
|
ffStrbufInit(&battery->modelName);
|
||||||
|
ffStrbufInit(&battery->technology);
|
||||||
|
if (!ffCfDictGetBool(properties, CFSTR("built-in"), &boolValue) && boolValue)
|
||||||
|
{
|
||||||
|
ffStrbufAppendS(&battery->manufacturer, "Apple Inc.");
|
||||||
|
ffStrbufAppendS(&battery->modelName, "Builtin");
|
||||||
|
ffStrbufAppendS(&battery->technology, "Lithium");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ffStrbufAppendS(&battery->manufacturer, "Unknown");
|
||||||
|
ffStrbufAppendS(&battery->modelName, "Unknown");
|
||||||
|
ffStrbufAppendS(&battery->technology, "Unknown");
|
||||||
|
}
|
||||||
|
|
||||||
|
ffStrbufInit(&battery->status);
|
||||||
|
if (!ffCfDictGetBool(properties, CFSTR("FullyCharged"), &boolValue) && boolValue)
|
||||||
|
ffStrbufAppendS(&battery->status, "Fully charged");
|
||||||
|
else if (!ffCfDictGetBool(properties, CFSTR("IsCharging"), &boolValue) && boolValue)
|
||||||
|
ffStrbufAppendS(&battery->status, "Charging");
|
||||||
|
else
|
||||||
|
ffStrbufAppendS(&battery->status, "");
|
||||||
|
|
||||||
|
if(instance->config.batteryTemp)
|
||||||
|
battery->temperature = detectBatteryTemp();
|
||||||
|
else
|
||||||
|
battery->temperature = FF_BATTERY_TEMP_UNSET;
|
||||||
|
|
||||||
|
CFRelease(properties);
|
||||||
|
IOObjectRelease(registryEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
IOObjectRelease(iterator);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
#include "fastfetch.h"
|
||||||
|
#include "common/io.h"
|
||||||
|
#include "battery.h"
|
||||||
|
|
||||||
|
#include <dirent.h>
|
||||||
|
|
||||||
|
static void parseBattery(FFstrbuf* dir, FFlist* results)
|
||||||
|
{
|
||||||
|
uint32_t dirLength = dir->length;
|
||||||
|
|
||||||
|
FFstrbuf testBatteryBuffer;
|
||||||
|
ffStrbufInit(&testBatteryBuffer);
|
||||||
|
|
||||||
|
//type must exist and be "Battery"
|
||||||
|
ffStrbufAppendS(dir, "/type");
|
||||||
|
ffReadFileBuffer(dir->chars, &testBatteryBuffer);
|
||||||
|
ffStrbufSubstrBefore(dir, dirLength);
|
||||||
|
|
||||||
|
if(ffStrbufIgnCaseCompS(&testBatteryBuffer, "Battery") != 0)
|
||||||
|
{
|
||||||
|
ffStrbufDestroy(&testBatteryBuffer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//scope may not exist or must not be "Device"
|
||||||
|
ffStrbufAppendS(dir, "/scope");
|
||||||
|
ffReadFileBuffer(dir->chars, &testBatteryBuffer);
|
||||||
|
ffStrbufSubstrBefore(dir, dirLength);
|
||||||
|
|
||||||
|
if(ffStrbufIgnCaseCompS(&testBatteryBuffer, "Device") == 0)
|
||||||
|
{
|
||||||
|
ffStrbufDestroy(&testBatteryBuffer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BatteryResult* result = ffListAdd(results);
|
||||||
|
|
||||||
|
//capacity must exist and be not empty
|
||||||
|
ffStrbufAppendS(dir, "/capacity");
|
||||||
|
bool available = ffReadFileBuffer(dir->chars, &testBatteryBuffer);
|
||||||
|
ffStrbufSubstrBefore(dir, dirLength);
|
||||||
|
if(available)
|
||||||
|
result->capacity = ffStrbufToDouble(&testBatteryBuffer);
|
||||||
|
ffStrbufDestroy(&testBatteryBuffer);
|
||||||
|
if(!available)
|
||||||
|
{
|
||||||
|
result->capacity = 0.0/0.0;
|
||||||
|
--results->length;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//At this point, we have a battery. Try to get as much values as possible.
|
||||||
|
|
||||||
|
ffStrbufInit(&result->manufacturer);
|
||||||
|
ffStrbufAppendS(dir, "/manufacturer");
|
||||||
|
ffReadFileBuffer(dir->chars, &result->manufacturer);
|
||||||
|
ffStrbufSubstrBefore(dir, dirLength);
|
||||||
|
|
||||||
|
ffStrbufInit(&result->modelName);
|
||||||
|
ffStrbufAppendS(dir, "/model_name");
|
||||||
|
ffReadFileBuffer(dir->chars, &result->modelName);
|
||||||
|
ffStrbufSubstrBefore(dir, dirLength);
|
||||||
|
|
||||||
|
ffStrbufInit(&result->technology);
|
||||||
|
ffStrbufAppendS(dir, "/technology");
|
||||||
|
ffReadFileBuffer(dir->chars, &result->technology);
|
||||||
|
ffStrbufSubstrBefore(dir, dirLength);
|
||||||
|
|
||||||
|
ffStrbufInit(&result->status);
|
||||||
|
ffStrbufAppendS(dir, "/status");
|
||||||
|
ffReadFileBuffer(dir->chars, &result->status);
|
||||||
|
ffStrbufSubstrBefore(dir, dirLength);
|
||||||
|
|
||||||
|
result->temperature = FF_BATTERY_TEMP_UNSET;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* ffDetectBatteryImpl(FFinstance* instance, FFlist* results) {
|
||||||
|
FFstrbuf baseDir;
|
||||||
|
ffStrbufInitA(&baseDir, 64);
|
||||||
|
if(instance->config.batteryDir.length > 0)
|
||||||
|
{
|
||||||
|
ffStrbufAppend(&baseDir, &instance->config.batteryDir);
|
||||||
|
ffStrbufEnsureEndsWithC(&baseDir, '/');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ffStrbufAppendS(&baseDir, "/sys/class/power_supply/");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t baseDirLength = baseDir.length;
|
||||||
|
|
||||||
|
DIR* dirp = opendir(baseDir.chars);
|
||||||
|
if(dirp == NULL)
|
||||||
|
{
|
||||||
|
ffStrbufDestroy(&baseDir);
|
||||||
|
return "opendir(batteryDir) == NULL";
|
||||||
|
}
|
||||||
|
|
||||||
|
struct dirent* entry;
|
||||||
|
while((entry = readdir(dirp)) != NULL)
|
||||||
|
{
|
||||||
|
ffStrbufAppendS(&baseDir, entry->d_name);
|
||||||
|
parseBattery(&baseDir, results);
|
||||||
|
ffStrbufSubstrBefore(&baseDir, baseDirLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(dirp);
|
||||||
|
|
||||||
|
if(results->length == 0) {
|
||||||
|
ffStrbufDestroy(&baseDir);
|
||||||
|
return "batteryDir doesn't contain any battery folder";
|
||||||
|
}
|
||||||
|
|
||||||
|
ffStrbufDestroy(&baseDir);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
#include "fastfetch.h"
|
||||||
|
#include "battery.h"
|
||||||
|
|
||||||
|
const char* ffDetectBatteryImpl(FFinstance* instance, FFlist* results)
|
||||||
|
{
|
||||||
|
FF_UNUSED(instance, results)
|
||||||
|
return "Not supported on this platform";
|
||||||
|
}
|
||||||
@@ -0,0 +1,158 @@
|
|||||||
|
#include "battery.h"
|
||||||
|
#include "util/windows/unicode.h"
|
||||||
|
#include "util/mallocHelper.h"
|
||||||
|
|
||||||
|
#include <setupapi.h>
|
||||||
|
#include <batclass.h>
|
||||||
|
#include <devguid.h>
|
||||||
|
#include <winternl.h>
|
||||||
|
#include <powrprof.h>
|
||||||
|
|
||||||
|
static inline void wrapCloseHandle(HANDLE* handle)
|
||||||
|
{
|
||||||
|
if(*handle)
|
||||||
|
CloseHandle(*handle);
|
||||||
|
}
|
||||||
|
static inline void wrapSetupDiDestroyDeviceInfoList(HDEVINFO* hdev)
|
||||||
|
{
|
||||||
|
if(*hdev)
|
||||||
|
SetupDiDestroyDeviceInfoList(*hdev);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* ffDetectBatteryImpl(FFinstance* instance, FFlist* results)
|
||||||
|
{
|
||||||
|
if(instance->config.allowSlowOperations)
|
||||||
|
{
|
||||||
|
//https://learn.microsoft.com/en-us/windows/win32/power/enumerating-battery-devices
|
||||||
|
HDEVINFO hdev __attribute__((__cleanup__(wrapSetupDiDestroyDeviceInfoList))) =
|
||||||
|
SetupDiGetClassDevs(&GUID_DEVCLASS_BATTERY, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
|
||||||
|
if(hdev == INVALID_HANDLE_VALUE)
|
||||||
|
return "SetupDiGetClassDevs(&GUID_DEVCLASS_BATTERY) failed";
|
||||||
|
|
||||||
|
for(DWORD idev = 0;; idev++)
|
||||||
|
{
|
||||||
|
SP_DEVICE_INTERFACE_DATA did = { .cbSize = sizeof(did) };
|
||||||
|
if(!SetupDiEnumDeviceInterfaces(hdev, NULL, &GUID_DEVCLASS_BATTERY, idev, &did))
|
||||||
|
break;
|
||||||
|
|
||||||
|
DWORD cbRequired = 0;
|
||||||
|
SetupDiGetDeviceInterfaceDetailW(hdev, &did, NULL, 0, &cbRequired, NULL); //Fail with not enough buffer
|
||||||
|
SP_DEVICE_INTERFACE_DETAIL_DATA_W* FF_AUTO_FREE pdidd = (SP_DEVICE_INTERFACE_DETAIL_DATA_W*)malloc(cbRequired);
|
||||||
|
if(!pdidd)
|
||||||
|
break; //Out of memory
|
||||||
|
|
||||||
|
pdidd->cbSize = sizeof(*pdidd);
|
||||||
|
if(!SetupDiGetDeviceInterfaceDetailW(hdev, &did, pdidd, cbRequired, &cbRequired, NULL))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
HANDLE __attribute__((__cleanup__(wrapCloseHandle))) hBattery =
|
||||||
|
CreateFileW(pdidd->DevicePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
|
||||||
|
if(hBattery == INVALID_HANDLE_VALUE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
BATTERY_QUERY_INFORMATION bqi = { .InformationLevel = BatteryInformation };
|
||||||
|
|
||||||
|
DWORD dwWait = 0;
|
||||||
|
DWORD dwOut;
|
||||||
|
|
||||||
|
if(!DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_TAG, &dwWait, sizeof(dwWait), &bqi.BatteryTag, sizeof(bqi.BatteryTag), &dwOut, NULL) && bqi.BatteryTag)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
BATTERY_INFORMATION bi = {0};
|
||||||
|
if(!DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), &bi, sizeof(bi), &dwOut, NULL))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(!(bi.Capabilities & BATTERY_SYSTEM_BATTERY))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
BatteryResult* battery = (BatteryResult*)ffListAdd(results);
|
||||||
|
|
||||||
|
if(memcmp(bi.Chemistry, "PbAc", 4) == 0)
|
||||||
|
ffStrbufInitS(&battery->technology, "Lead Acid");
|
||||||
|
else if(memcmp(bi.Chemistry, "LION", 4) == 0 || memcmp(bi.Chemistry, "Li-I", 4) == 0)
|
||||||
|
ffStrbufInitS(&battery->technology, "Lithium Ion");
|
||||||
|
else if(memcmp(bi.Chemistry, "NiCd", 4) == 0)
|
||||||
|
ffStrbufInitS(&battery->technology, "Nickel Cadmium");
|
||||||
|
else if(memcmp(bi.Chemistry, "NiMH", 4) == 0)
|
||||||
|
ffStrbufInitS(&battery->technology, "Nickel Metal Hydride");
|
||||||
|
else if(memcmp(bi.Chemistry, "NiZn", 4) == 0)
|
||||||
|
ffStrbufInitS(&battery->technology, "Nickel Zinc");
|
||||||
|
else if(memcmp(bi.Chemistry, "RAM\0", 4) == 0)
|
||||||
|
ffStrbufInitS(&battery->technology, "Rechargeable Alkaline-Manganese");
|
||||||
|
else
|
||||||
|
ffStrbufInitS(&battery->technology, "Unknown");
|
||||||
|
|
||||||
|
{
|
||||||
|
ffStrbufInit(&battery->modelName);
|
||||||
|
bqi.InformationLevel = BatteryDeviceName;
|
||||||
|
wchar_t name[64];
|
||||||
|
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), name, sizeof(name), &dwOut, NULL))
|
||||||
|
ffStrbufSetWS(&battery->modelName, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
ffStrbufInit(&battery->manufacturer);
|
||||||
|
bqi.InformationLevel = BatteryManufactureName;
|
||||||
|
wchar_t name[64];
|
||||||
|
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), name, sizeof(name), &dwOut, NULL))
|
||||||
|
ffStrbufSetWS(&battery->manufacturer, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
battery->temperature = 0.0/0.0;
|
||||||
|
if(instance->config.batteryTemp)
|
||||||
|
{
|
||||||
|
bqi.InformationLevel = BatteryTemperature;
|
||||||
|
ULONG temp;
|
||||||
|
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), &temp, sizeof(temp), &dwOut, NULL))
|
||||||
|
battery->temperature = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
BATTERY_STATUS bs;
|
||||||
|
BATTERY_WAIT_STATUS bws = { .BatteryTag = bqi.BatteryTag };
|
||||||
|
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_STATUS, &bws, sizeof(bws), &bs, sizeof(bs), &dwOut, NULL) && bs.Capacity != BATTERY_UNKNOWN_CAPACITY)
|
||||||
|
battery->capacity = bs.Capacity * 100.0 / bi.FullChargedCapacity;
|
||||||
|
else
|
||||||
|
battery->capacity = 0;
|
||||||
|
|
||||||
|
ffStrbufInit(&battery->status);
|
||||||
|
if(bs.PowerState & BATTERY_POWER_ON_LINE)
|
||||||
|
ffStrbufAppendS(&battery->status, "AC Connected, ");
|
||||||
|
if(bs.PowerState & BATTERY_DISCHARGING)
|
||||||
|
ffStrbufAppendS(&battery->status, "Discharging, ");
|
||||||
|
if(bs.PowerState & BATTERY_CHARGING)
|
||||||
|
ffStrbufAppendS(&battery->status, "Charging");
|
||||||
|
if(bs.PowerState & BATTERY_CRITICAL)
|
||||||
|
ffStrbufAppendS(&battery->status, "Critical, ");
|
||||||
|
ffStrbufTrimRight(&battery->status, ' ');
|
||||||
|
ffStrbufTrimRight(&battery->status, ',');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SYSTEM_BATTERY_STATE info;
|
||||||
|
if (NT_SUCCESS(CallNtPowerInformation(SystemBatteryState, NULL, 0, &info, sizeof(info))) && info.BatteryPresent)
|
||||||
|
{
|
||||||
|
BatteryResult* battery = (BatteryResult*)ffListAdd(results);
|
||||||
|
ffStrbufInit(&battery->modelName);
|
||||||
|
ffStrbufInit(&battery->manufacturer);
|
||||||
|
ffStrbufInit(&battery->technology);
|
||||||
|
ffStrbufInit(&battery->status);
|
||||||
|
battery->temperature = 0.0/0.0;
|
||||||
|
|
||||||
|
battery->capacity = info.RemainingCapacity * 100.0 / info.MaxCapacity;
|
||||||
|
if(info.AcOnLine)
|
||||||
|
{
|
||||||
|
ffStrbufAppendS(&battery->status, "AC Connected");
|
||||||
|
if(info.Charging)
|
||||||
|
ffStrbufAppendS(&battery->status, ", Charging");
|
||||||
|
}
|
||||||
|
else if(info.Discharging)
|
||||||
|
ffStrbufAppendS(&battery->status, "Discharging");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef FF_INCLUDED_detection_bios_bios
|
||||||
|
#define FF_INCLUDED_detection_bios_bios
|
||||||
|
|
||||||
|
#include "fastfetch.h"
|
||||||
|
|
||||||
|
typedef struct FFBiosResult
|
||||||
|
{
|
||||||
|
FFstrbuf biosDate;
|
||||||
|
FFstrbuf biosRelease;
|
||||||
|
FFstrbuf biosVendor;
|
||||||
|
FFstrbuf biosVersion;
|
||||||
|
FFstrbuf error;
|
||||||
|
} FFBiosResult;
|
||||||
|
|
||||||
|
void ffDetectBios(FFBiosResult* bios);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
#include "bios.h"
|
||||||
|
#include "util/apple/cf_helpers.h"
|
||||||
|
|
||||||
|
#include <IOKit/IOKitLib.h>
|
||||||
|
|
||||||
|
void ffDetectBios(FFBiosResult* bios)
|
||||||
|
{
|
||||||
|
ffStrbufInit(&bios->error);
|
||||||
|
ffStrbufInit(&bios->biosDate);
|
||||||
|
ffStrbufInit(&bios->biosRelease);
|
||||||
|
ffStrbufInit(&bios->biosVendor);
|
||||||
|
ffStrbufInit(&bios->biosVersion);
|
||||||
|
|
||||||
|
io_registry_entry_t registryEntry;
|
||||||
|
|
||||||
|
#ifndef __aarch64__
|
||||||
|
|
||||||
|
//https://github.com/osquery/osquery/blob/master/osquery/tables/system/darwin/smbios_tables.cpp
|
||||||
|
//For Intel
|
||||||
|
if((registryEntry = IORegistryEntryFromPath(MACH_PORT_NULL, "IODeviceTree:/rom")))
|
||||||
|
{
|
||||||
|
CFMutableDictionaryRef properties;
|
||||||
|
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
|
||||||
|
{
|
||||||
|
IOObjectRelease(registryEntry);
|
||||||
|
ffStrbufAppendS(&bios->error, "IORegistryEntryCreateCFProperties(registryEntry) failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ffCfDictGetString(properties, CFSTR("vendor"), &bios->biosVendor);
|
||||||
|
ffCfDictGetString(properties, CFSTR("version"), &bios->biosVersion);
|
||||||
|
ffCfDictGetString(properties, CFSTR("release-date"), &bios->biosDate);
|
||||||
|
if(!ffStrbufContainC(&bios->biosDate, '-'))
|
||||||
|
ffStrbufAppendS(&bios->biosRelease, "Efi-");
|
||||||
|
ffStrbufAppend(&bios->biosRelease, &bios->biosVersion);
|
||||||
|
|
||||||
|
CFRelease(properties);
|
||||||
|
IOObjectRelease(registryEntry);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
//For arm64
|
||||||
|
if((registryEntry = IORegistryEntryFromPath(MACH_PORT_NULL, "IODeviceTree:/")))
|
||||||
|
{
|
||||||
|
CFMutableDictionaryRef properties;
|
||||||
|
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) == kIOReturnSuccess)
|
||||||
|
{
|
||||||
|
ffCfDictGetString(properties, CFSTR("manufacturer"), &bios->biosVendor);
|
||||||
|
CFRelease(properties);
|
||||||
|
}
|
||||||
|
IOObjectRelease(registryEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
if((registryEntry = IORegistryEntryFromPath(MACH_PORT_NULL, "IODeviceTree:/chosen")))
|
||||||
|
{
|
||||||
|
CFMutableDictionaryRef properties;
|
||||||
|
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) == kIOReturnSuccess)
|
||||||
|
{
|
||||||
|
ffCfDictGetString(properties, CFSTR("system-firmware-version"), &bios->biosRelease);
|
||||||
|
ffStrbufAppend(&bios->biosVersion, &bios->biosRelease);
|
||||||
|
ffStrbufSubstrAfterFirstC(&bios->biosVersion, '-');
|
||||||
|
CFRelease(properties);
|
||||||
|
}
|
||||||
|
IOObjectRelease(registryEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
#include "bios.h"
|
||||||
|
|
||||||
|
#include <kenv.h>
|
||||||
|
|
||||||
|
static void kenvLookup(const char* name, FFstrbuf* result)
|
||||||
|
{
|
||||||
|
ffStrbufEnsureFree(result, 255);
|
||||||
|
int len = kenv(KENV_GET, name, result->chars, 256);
|
||||||
|
if(len > 0)
|
||||||
|
result->length = (uint32_t) len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ffDetectBios(FFBiosResult* bios)
|
||||||
|
{
|
||||||
|
ffStrbufInit(&bios->error);
|
||||||
|
ffStrbufInit(&bios->biosDate);
|
||||||
|
ffStrbufInit(&bios->biosRelease);
|
||||||
|
ffStrbufInit(&bios->biosVendor);
|
||||||
|
ffStrbufInit(&bios->biosVersion);
|
||||||
|
|
||||||
|
//https://wiki.ghostbsd.org/index.php/Kenv
|
||||||
|
kenvLookup("smbios.bios.reldate", &bios->biosDate);
|
||||||
|
kenvLookup("smbios.system.product", &bios->biosRelease);
|
||||||
|
kenvLookup("smbios.bios.vendor", &bios->biosVendor);
|
||||||
|
kenvLookup("smbios.bios.version", &bios->biosVersion);
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
#include "bios.h"
|
||||||
|
#include "common/io.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
static bool hostValueSet(FFstrbuf* value)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
value->length > 0 &&
|
||||||
|
ffStrbufStartsWithIgnCaseS(value, "To be filled") != true &&
|
||||||
|
ffStrbufStartsWithIgnCaseS(value, "To be set") != true &&
|
||||||
|
ffStrbufStartsWithIgnCaseS(value, "OEM") != true &&
|
||||||
|
ffStrbufStartsWithIgnCaseS(value, "O.E.M.") != true &&
|
||||||
|
ffStrbufIgnCaseCompS(value, "None") != 0 &&
|
||||||
|
ffStrbufIgnCaseCompS(value, "System Product") != 0 &&
|
||||||
|
ffStrbufIgnCaseCompS(value, "System Product Name") != 0 &&
|
||||||
|
ffStrbufIgnCaseCompS(value, "System Product Version") != 0 &&
|
||||||
|
ffStrbufIgnCaseCompS(value, "System Name") != 0 &&
|
||||||
|
ffStrbufIgnCaseCompS(value, "System Version") != 0 &&
|
||||||
|
ffStrbufIgnCaseCompS(value, "Default string") != 0 &&
|
||||||
|
ffStrbufIgnCaseCompS(value, "Undefined") != 0 &&
|
||||||
|
ffStrbufIgnCaseCompS(value, "Not Specified") != 0 &&
|
||||||
|
ffStrbufIgnCaseCompS(value, "Not Applicable") != 0 &&
|
||||||
|
ffStrbufIgnCaseCompS(value, "INVALID") != 0 &&
|
||||||
|
ffStrbufIgnCaseCompS(value, "Type1ProductConfigId") != 0 &&
|
||||||
|
ffStrbufIgnCaseCompS(value, "All Series") != 0
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void getHostValue(const char* devicesPath, const char* classPath, FFstrbuf* buffer)
|
||||||
|
{
|
||||||
|
ffReadFileBuffer(devicesPath, buffer);
|
||||||
|
if(hostValueSet(buffer))
|
||||||
|
return;
|
||||||
|
|
||||||
|
ffReadFileBuffer(classPath, buffer);
|
||||||
|
if(hostValueSet(buffer))
|
||||||
|
return;
|
||||||
|
|
||||||
|
ffStrbufClear(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ffDetectBios(FFBiosResult* bios)
|
||||||
|
{
|
||||||
|
ffStrbufInit(&bios->error);
|
||||||
|
|
||||||
|
ffStrbufInit(&bios->biosDate);
|
||||||
|
getHostValue("/sys/devices/virtual/dmi/id/bios_date", "/sys/class/dmi/id/bios_date", &bios->biosDate);
|
||||||
|
|
||||||
|
ffStrbufInit(&bios->biosRelease);
|
||||||
|
getHostValue("/sys/devices/virtual/dmi/id/bios_release", "/sys/class/dmi/id/bios_release", &bios->biosRelease);
|
||||||
|
|
||||||
|
ffStrbufInit(&bios->biosVendor);
|
||||||
|
getHostValue("/sys/devices/virtual/dmi/id/bios_vendor", "/sys/class/dmi/id/bios_vendor", &bios->biosVendor);
|
||||||
|
|
||||||
|
ffStrbufInit(&bios->biosVersion);
|
||||||
|
getHostValue("/sys/devices/virtual/dmi/id/bios_version", "/sys/class/dmi/id/bios_version", &bios->biosVersion);
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
#include "bios.h"
|
||||||
|
|
||||||
|
void ffDetectBios(FFBiosResult* bios)
|
||||||
|
{
|
||||||
|
ffStrbufInitS(&bios->error, "Not supported on this platform");
|
||||||
|
|
||||||
|
ffStrbufInit(&bios->biosDate);
|
||||||
|
ffStrbufInit(&bios->biosRelease);
|
||||||
|
ffStrbufInit(&bios->biosVendor);
|
||||||
|
ffStrbufInit(&bios->biosVersion);
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
#include "bios.h"
|
||||||
|
#include "util/windows/registry.h"
|
||||||
|
|
||||||
|
void ffDetectBios(FFBiosResult* bios)
|
||||||
|
{
|
||||||
|
ffStrbufInit(&bios->error);
|
||||||
|
|
||||||
|
ffStrbufInit(&bios->biosDate);
|
||||||
|
ffStrbufInit(&bios->biosRelease);
|
||||||
|
ffStrbufInit(&bios->biosVendor);
|
||||||
|
ffStrbufInit(&bios->biosVersion);
|
||||||
|
|
||||||
|
FF_HKEY_AUTO_DESTROY hKey = NULL;
|
||||||
|
if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\BIOS", &hKey, &bios->error))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(!ffRegReadStrbuf(hKey, L"BIOSVersion", &bios->biosRelease, &bios->error))
|
||||||
|
return;
|
||||||
|
ffRegReadStrbuf(hKey, L"BIOSVendor", &bios->biosVendor, NULL);
|
||||||
|
ffRegReadStrbuf(hKey, L"BIOSReleaseDate", &bios->biosDate, NULL);
|
||||||
|
|
||||||
|
uint32_t major, minor;
|
||||||
|
if(
|
||||||
|
ffRegReadUint(hKey, L"BiosMajorRelease", &major, NULL) &&
|
||||||
|
ffRegReadUint(hKey, L"BiosMinorRelease", &minor, NULL)
|
||||||
|
)
|
||||||
|
ffStrbufAppendF(&bios->biosVersion, "%u.%u", (unsigned)major, (unsigned)minor);
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef FF_INCLUDED_detection_board_board
|
||||||
|
#define FF_INCLUDED_detection_board_board
|
||||||
|
|
||||||
|
#include "fastfetch.h"
|
||||||
|
|
||||||
|
typedef struct FFBoardResult
|
||||||
|
{
|
||||||
|
FFstrbuf boardName;
|
||||||
|
FFstrbuf boardVendor;
|
||||||
|
FFstrbuf boardVersion;
|
||||||
|
FFstrbuf error;
|
||||||
|
} FFBoardResult;
|
||||||
|
|
||||||
|
void ffDetectBoard(FFBoardResult* result);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
#include "board.h"
|
||||||
|
#include "common/io.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
static bool hostValueSet(FFstrbuf* value)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
value->length > 0 &&
|
||||||
|
ffStrbufStartsWithIgnCaseS(value, "To be filled") != true &&
|
||||||
|
ffStrbufStartsWithIgnCaseS(value, "To be set") != true &&
|
||||||
|
ffStrbufStartsWithIgnCaseS(value, "OEM") != true &&
|
||||||
|
ffStrbufStartsWithIgnCaseS(value, "O.E.M.") != true &&
|
||||||
|
ffStrbufIgnCaseCompS(value, "None") != 0 &&
|
||||||
|
ffStrbufIgnCaseCompS(value, "System Product") != 0 &&
|
||||||
|
ffStrbufIgnCaseCompS(value, "System Product Name") != 0 &&
|
||||||
|
ffStrbufIgnCaseCompS(value, "System Product Version") != 0 &&
|
||||||
|
ffStrbufIgnCaseCompS(value, "System Name") != 0 &&
|
||||||
|
ffStrbufIgnCaseCompS(value, "System Version") != 0 &&
|
||||||
|
ffStrbufIgnCaseCompS(value, "Default string") != 0 &&
|
||||||
|
ffStrbufIgnCaseCompS(value, "Undefined") != 0 &&
|
||||||
|
ffStrbufIgnCaseCompS(value, "Not Specified") != 0 &&
|
||||||
|
ffStrbufIgnCaseCompS(value, "Not Applicable") != 0 &&
|
||||||
|
ffStrbufIgnCaseCompS(value, "INVALID") != 0 &&
|
||||||
|
ffStrbufIgnCaseCompS(value, "Type1ProductConfigId") != 0 &&
|
||||||
|
ffStrbufIgnCaseCompS(value, "All Series") != 0
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void getHostValue(const char* devicesPath, const char* classPath, FFstrbuf* buffer)
|
||||||
|
{
|
||||||
|
ffReadFileBuffer(devicesPath, buffer);
|
||||||
|
if(hostValueSet(buffer))
|
||||||
|
return;
|
||||||
|
|
||||||
|
ffReadFileBuffer(classPath, buffer);
|
||||||
|
if(hostValueSet(buffer))
|
||||||
|
return;
|
||||||
|
|
||||||
|
ffStrbufClear(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ffDetectBoard(FFBoardResult* board)
|
||||||
|
{
|
||||||
|
ffStrbufInit(&board->error);
|
||||||
|
|
||||||
|
ffStrbufInit(&board->boardName);
|
||||||
|
getHostValue("/sys/devices/virtual/dmi/id/board_name", "/sys/class/dmi/id/board_name", &board->boardName);
|
||||||
|
|
||||||
|
ffStrbufInit(&board->boardVendor);
|
||||||
|
getHostValue("/sys/devices/virtual/dmi/id/board_vendor", "/sys/class/dmi/id/board_vendor", &board->boardVendor);
|
||||||
|
|
||||||
|
ffStrbufInit(&board->boardVersion);
|
||||||
|
getHostValue("/sys/devices/virtual/dmi/id/board_version", "/sys/class/dmi/id/board_version", &board->boardVersion);
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
#include "board.h"
|
||||||
|
|
||||||
|
void ffDetectBoard(FFBoardResult* board)
|
||||||
|
{
|
||||||
|
ffStrbufInitS(&board->error, "Not supported on this platform");
|
||||||
|
|
||||||
|
ffStrbufInit(&board->boardName);
|
||||||
|
ffStrbufInit(&board->boardVendor);
|
||||||
|
ffStrbufInit(&board->boardVersion);
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
#include "board.h"
|
||||||
|
#include "util/windows/registry.h"
|
||||||
|
|
||||||
|
void ffDetectBoard(FFBoardResult* board)
|
||||||
|
{
|
||||||
|
ffStrbufInit(&board->error);
|
||||||
|
|
||||||
|
ffStrbufInit(&board->boardName);
|
||||||
|
ffStrbufInit(&board->boardVendor);
|
||||||
|
ffStrbufInit(&board->boardVersion);
|
||||||
|
|
||||||
|
FF_HKEY_AUTO_DESTROY hKey = NULL;
|
||||||
|
|
||||||
|
if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\BIOS", &hKey, &board->error))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(!ffRegReadStrbuf(hKey, L"BaseBoardProduct", &board->boardName, &board->error))
|
||||||
|
return;
|
||||||
|
ffRegReadStrbuf(hKey, L"BaseBoardManufacturer", &board->boardVendor, NULL);
|
||||||
|
ffRegReadStrbuf(hKey, L"BaseBoardVersion", &board->boardVersion, NULL);
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef FF_INCLUDED_detection_chassis_chassis
|
||||||
|
#define FF_INCLUDED_detection_chassis_chassis
|
||||||
|
|
||||||
|
#include "fastfetch.h"
|
||||||
|
|
||||||
|
typedef struct FFChassisResult
|
||||||
|
{
|
||||||
|
FFstrbuf chassisType;
|
||||||
|
FFstrbuf chassisVendor;
|
||||||
|
FFstrbuf chassisVersion;
|
||||||
|
FFstrbuf error;
|
||||||
|
} FFChassisResult;
|
||||||
|
|
||||||
|
void ffDetectChassis(FFChassisResult* result);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
#include "chassis.h"
|
||||||
|
#include "common/io.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
static bool hostValueSet(FFstrbuf* value)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
value->length > 0 &&
|
||||||
|
ffStrbufStartsWithIgnCaseS(value, "To be filled") != true &&
|
||||||
|
ffStrbufStartsWithIgnCaseS(value, "To be set") != true &&
|
||||||
|
ffStrbufStartsWithIgnCaseS(value, "OEM") != true &&
|
||||||
|
ffStrbufStartsWithIgnCaseS(value, "O.E.M.") != true &&
|
||||||
|
ffStrbufIgnCaseCompS(value, "None") != 0 &&
|
||||||
|
ffStrbufIgnCaseCompS(value, "System Product") != 0 &&
|
||||||
|
ffStrbufIgnCaseCompS(value, "System Product Name") != 0 &&
|
||||||
|
ffStrbufIgnCaseCompS(value, "System Product Version") != 0 &&
|
||||||
|
ffStrbufIgnCaseCompS(value, "System Name") != 0 &&
|
||||||
|
ffStrbufIgnCaseCompS(value, "System Version") != 0 &&
|
||||||
|
ffStrbufIgnCaseCompS(value, "Default string") != 0 &&
|
||||||
|
ffStrbufIgnCaseCompS(value, "Undefined") != 0 &&
|
||||||
|
ffStrbufIgnCaseCompS(value, "Not Specified") != 0 &&
|
||||||
|
ffStrbufIgnCaseCompS(value, "Not Applicable") != 0 &&
|
||||||
|
ffStrbufIgnCaseCompS(value, "INVALID") != 0 &&
|
||||||
|
ffStrbufIgnCaseCompS(value, "Type1ProductConfigId") != 0 &&
|
||||||
|
ffStrbufIgnCaseCompS(value, "All Series") != 0
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void getHostValue(const char* devicesPath, const char* classPath, FFstrbuf* buffer)
|
||||||
|
{
|
||||||
|
ffReadFileBuffer(devicesPath, buffer);
|
||||||
|
if(hostValueSet(buffer))
|
||||||
|
return;
|
||||||
|
|
||||||
|
ffReadFileBuffer(classPath, buffer);
|
||||||
|
if(hostValueSet(buffer))
|
||||||
|
return;
|
||||||
|
|
||||||
|
ffStrbufClear(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ffDetectChassis(FFChassisResult* result)
|
||||||
|
{
|
||||||
|
ffStrbufInit(&result->error);
|
||||||
|
|
||||||
|
ffStrbufInit(&result->chassisType);
|
||||||
|
getHostValue("/sys/devices/virtual/dmi/id/chassis_type", "/sys/class/dmi/id/chassis_type", &result->chassisType);
|
||||||
|
|
||||||
|
ffStrbufInit(&result->chassisVendor);
|
||||||
|
getHostValue("/sys/devices/virtual/dmi/id/chassis_vendor", "/sys/class/dmi/id/chassis_vendor", &result->chassisVendor);
|
||||||
|
|
||||||
|
ffStrbufInit(&result->chassisVersion);
|
||||||
|
getHostValue("/sys/devices/virtual/dmi/id/chassis_version", "/sys/class/dmi/id/chassis_version", &result->chassisVersion);
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
#include "chassis.h"
|
||||||
|
|
||||||
|
void ffDetectChassis(FFChassisResult* result)
|
||||||
|
{
|
||||||
|
ffStrbufInitS(&result->error, "Not supported on this platform");
|
||||||
|
|
||||||
|
ffStrbufInit(&result->chassisType);
|
||||||
|
ffStrbufInit(&result->chassisVendor);
|
||||||
|
ffStrbufInit(&result->chassisVersion);
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
#include "cpu.h"
|
||||||
|
#include "detection/internal.h"
|
||||||
|
|
||||||
|
void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu);
|
||||||
|
static void detectCPU(const FFinstance* instance, FFCPUResult* cpu)
|
||||||
|
{
|
||||||
|
ffStrbufInit(&cpu->name);
|
||||||
|
ffStrbufInit(&cpu->vendor);
|
||||||
|
|
||||||
|
ffDetectCPUImpl(instance, cpu);
|
||||||
|
|
||||||
|
const char* removeStrings[] = {
|
||||||
|
" CPU", " FPU", " APU", " Processor",
|
||||||
|
" Dual-Core", " Quad-Core", " Six-Core", " Eight-Core", " Ten-Core",
|
||||||
|
" 2-Core", " 4-Core", " 6-Core", " 8-Core", " 10-Core", " 12-Core", " 14-Core", " 16-Core",
|
||||||
|
" with Radeon Graphics"
|
||||||
|
};
|
||||||
|
ffStrbufRemoveStringsA(&cpu->name, sizeof(removeStrings) / sizeof(removeStrings[0]), removeStrings);
|
||||||
|
ffStrbufSubstrBeforeFirstC(&cpu->name, '@'); //Cut the speed output in the name as we append our own
|
||||||
|
ffStrbufTrimRight(&cpu->name, ' '); //If we removed the @ in previous step there was most likely a space before it
|
||||||
|
}
|
||||||
|
|
||||||
|
const FFCPUResult* ffDetectCPU(const FFinstance* instance)
|
||||||
|
{
|
||||||
|
FF_DETECTION_INTERNAL_GUARD(FFCPUResult,
|
||||||
|
detectCPU(instance, &result);
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef FF_INCLUDED_detection_cpu_cpu
|
||||||
|
#define FF_INCLUDED_detection_cpu_cpu
|
||||||
|
|
||||||
|
#include "fastfetch.h"
|
||||||
|
|
||||||
|
#define FF_CPU_TEMP_UNSET (0/0.0)
|
||||||
|
|
||||||
|
typedef struct FFCPUResult
|
||||||
|
{
|
||||||
|
FFstrbuf name;
|
||||||
|
FFstrbuf vendor;
|
||||||
|
|
||||||
|
uint16_t coresPhysical;
|
||||||
|
uint16_t coresLogical;
|
||||||
|
uint16_t coresOnline;
|
||||||
|
|
||||||
|
double frequencyMin;
|
||||||
|
double frequencyMax;
|
||||||
|
|
||||||
|
double temperature;
|
||||||
|
} FFCPUResult;
|
||||||
|
|
||||||
|
const FFCPUResult* ffDetectCPU(const FFinstance* instance);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
#include "cpu.h"
|
||||||
|
#include "common/sysctl.h"
|
||||||
|
#include "detection/temps/temps_apple.h"
|
||||||
|
|
||||||
|
static double getFrequency(const char* propName)
|
||||||
|
{
|
||||||
|
double herz = (double) ffSysctlGetInt64(propName, 0);
|
||||||
|
if(herz <= 0.0)
|
||||||
|
return herz;
|
||||||
|
|
||||||
|
herz /= 1000.0; //to KHz
|
||||||
|
herz /= 1000.0; //to MHz
|
||||||
|
return herz / 1000.0; //to GHz
|
||||||
|
}
|
||||||
|
|
||||||
|
static double detectCpuTemp(const FFstrbuf* cpuName)
|
||||||
|
{
|
||||||
|
FF_LIST_AUTO_DESTROY temps;
|
||||||
|
ffListInit(&temps, sizeof(FFTempValue));
|
||||||
|
|
||||||
|
if(ffStrbufStartsWithS(cpuName, "Apple M1"))
|
||||||
|
ffDetectCoreTemps(FF_TEMP_CPU_M1X, &temps);
|
||||||
|
else if(ffStrbufStartsWithS(cpuName, "Apple M2"))
|
||||||
|
ffDetectCoreTemps(FF_TEMP_CPU_M2X, &temps);
|
||||||
|
else //TODO: PPC?
|
||||||
|
ffDetectCoreTemps(FF_TEMP_CPU_X64, &temps);
|
||||||
|
|
||||||
|
if(temps.length == 0)
|
||||||
|
return FF_CPU_TEMP_UNSET;
|
||||||
|
|
||||||
|
double result = 0;
|
||||||
|
for(uint32_t i = 0; i < temps.length; ++i)
|
||||||
|
{
|
||||||
|
FFTempValue* tempValue = (FFTempValue*)ffListGet(&temps, i);
|
||||||
|
result += tempValue->value;
|
||||||
|
//TODO: do we really need this?
|
||||||
|
ffStrbufDestroy(&tempValue->name);
|
||||||
|
ffStrbufDestroy(&tempValue->deviceClass);
|
||||||
|
}
|
||||||
|
result /= temps.length;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu)
|
||||||
|
{
|
||||||
|
FF_UNUSED(instance);
|
||||||
|
|
||||||
|
ffSysctlGetString("machdep.cpu.brand_string", &cpu->name);
|
||||||
|
ffSysctlGetString("machdep.cpu.vendor", &cpu->vendor);
|
||||||
|
|
||||||
|
cpu->coresPhysical = (uint16_t) ffSysctlGetInt("hw.physicalcpu_max", 1);
|
||||||
|
if(cpu->coresPhysical == 1)
|
||||||
|
cpu->coresPhysical = (uint16_t) ffSysctlGetInt("hw.physicalcpu", 1);
|
||||||
|
|
||||||
|
cpu->coresLogical = (uint16_t) ffSysctlGetInt("hw.logicalcpu_max", 1);
|
||||||
|
if(cpu->coresLogical == 1)
|
||||||
|
cpu->coresLogical = (uint16_t) ffSysctlGetInt("hw.ncpu", 1);
|
||||||
|
|
||||||
|
cpu->coresOnline = (uint16_t) ffSysctlGetInt("hw.logicalcpu", 1);
|
||||||
|
if(cpu->coresOnline == 1)
|
||||||
|
cpu->coresOnline = (uint16_t) ffSysctlGetInt("hw.activecpu", 1);
|
||||||
|
|
||||||
|
cpu->frequencyMin = getFrequency("hw.cpufrequency_min");
|
||||||
|
cpu->frequencyMax = getFrequency("hw.cpufrequency_max");
|
||||||
|
if(cpu->frequencyMax == 0.0)
|
||||||
|
cpu->frequencyMax = getFrequency("hw.cpufrequency");
|
||||||
|
|
||||||
|
if (instance->config.cpuTemp)
|
||||||
|
cpu->temperature = detectCpuTemp(&cpu->name);
|
||||||
|
else
|
||||||
|
cpu->temperature = FF_CPU_TEMP_UNSET;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
#include "cpu.h"
|
||||||
|
#include "common/sysctl.h"
|
||||||
|
|
||||||
|
void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu)
|
||||||
|
{
|
||||||
|
FF_UNUSED(instance);
|
||||||
|
|
||||||
|
if (instance->config.cpuTemp)
|
||||||
|
{
|
||||||
|
FFstrbuf cpuTemp;
|
||||||
|
ffStrbufInit(&cpuTemp);
|
||||||
|
if(ffSysctlGetString("temperature", &cpuTemp))
|
||||||
|
cpu->temperature = FF_CPU_TEMP_UNSET;
|
||||||
|
else
|
||||||
|
cpu->temperature = ffStrbufToDouble(&cpuTemp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
cpu->temperature = FF_CPU_TEMP_UNSET;
|
||||||
|
|
||||||
|
ffSysctlGetString("hw.model", &cpu->name);
|
||||||
|
|
||||||
|
cpu->coresPhysical = (uint16_t) ffSysctlGetInt("hw.ncpu", 1);
|
||||||
|
cpu->coresLogical = cpu->coresPhysical;
|
||||||
|
cpu->coresOnline = cpu->coresPhysical;
|
||||||
|
|
||||||
|
cpu->frequencyMin = ffSysctlGetInt("hw.clockrate", 0) / 1000.0;
|
||||||
|
cpu->frequencyMax = cpu->frequencyMin;
|
||||||
|
}
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
#include "cpu.h"
|
||||||
|
#include "common/io.h"
|
||||||
|
#include "common/properties.h"
|
||||||
|
#include "detection/temps/temps_linux.h"
|
||||||
|
|
||||||
|
#include <sys/sysinfo.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
static void parseCpuInfo(FFCPUResult* cpu, FFstrbuf* physicalCoresBuffer, FFstrbuf* cpuMHz)
|
||||||
|
{
|
||||||
|
FILE* cpuinfo = fopen("/proc/cpuinfo", "r");
|
||||||
|
if(cpuinfo == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
char* line = NULL;
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
|
while(getline(&line, &len, cpuinfo) != -1)
|
||||||
|
{
|
||||||
|
//Stop after the first CPU
|
||||||
|
if(cpu->name.length > 0 && (*line == '\0' || *line == '\n'))
|
||||||
|
break;
|
||||||
|
|
||||||
|
(void)(
|
||||||
|
ffParsePropLine(line, "model name :", &cpu->name) ||
|
||||||
|
ffParsePropLine(line, "vendor_id :", &cpu->vendor) ||
|
||||||
|
ffParsePropLine(line, "cpu cores :", physicalCoresBuffer) ||
|
||||||
|
ffParsePropLine(line, "cpu MHz :", cpuMHz) ||
|
||||||
|
(cpu->name.length == 0 && ffParsePropLine(line, "Hardware :", &cpu->name)) //For Android devices
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(line != NULL)
|
||||||
|
free(line);
|
||||||
|
|
||||||
|
fclose(cpuinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
static double getGHz(const char* file)
|
||||||
|
{
|
||||||
|
FFstrbuf content;
|
||||||
|
ffStrbufInit(&content);
|
||||||
|
if(ffAppendFileBuffer(file, &content))
|
||||||
|
{
|
||||||
|
double herz = ffStrbufToDouble(&content);
|
||||||
|
ffStrbufDestroy(&content);
|
||||||
|
|
||||||
|
//ffStrbufToDouble failed
|
||||||
|
if(herz != herz)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
herz /= 1000.0; //to MHz
|
||||||
|
return herz / 1000.0; //to GHz
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static double getFrequency(const char* info, const char* scaling)
|
||||||
|
{
|
||||||
|
double frequency = getGHz(info);
|
||||||
|
if(frequency > 0.0)
|
||||||
|
return frequency;
|
||||||
|
|
||||||
|
return getGHz(scaling);
|
||||||
|
}
|
||||||
|
|
||||||
|
static double detectCPUTemp(const FFinstance* instance)
|
||||||
|
{
|
||||||
|
const FFTempsResult* temps = ffDetectTemps(instance);
|
||||||
|
|
||||||
|
for(uint32_t i = 0; i < temps->values.length; i++)
|
||||||
|
{
|
||||||
|
FFTempValue* value = ffListGet(&temps->values, i);
|
||||||
|
|
||||||
|
if(
|
||||||
|
ffStrbufFirstIndexS(&value->name, "cpu") < value->name.length ||
|
||||||
|
ffStrbufCompS(&value->name, "k10temp") == 0 ||
|
||||||
|
ffStrbufCompS(&value->name, "coretemp") == 0
|
||||||
|
) return value->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FF_CPU_TEMP_UNSET;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu)
|
||||||
|
{
|
||||||
|
if(instance->config.cpuTemp)
|
||||||
|
cpu->temperature = detectCPUTemp(instance);
|
||||||
|
else
|
||||||
|
cpu->temperature = FF_CPU_TEMP_UNSET;
|
||||||
|
|
||||||
|
FFstrbuf physicalCoresBuffer;
|
||||||
|
ffStrbufInit(&physicalCoresBuffer);
|
||||||
|
|
||||||
|
FFstrbuf cpuMHz;
|
||||||
|
ffStrbufInit(&cpuMHz);
|
||||||
|
|
||||||
|
parseCpuInfo(cpu, &physicalCoresBuffer, &cpuMHz);
|
||||||
|
|
||||||
|
cpu->coresPhysical = ffStrbufToUInt16(&physicalCoresBuffer, 1);
|
||||||
|
|
||||||
|
cpu->coresLogical = (uint16_t) get_nprocs_conf();
|
||||||
|
cpu->coresOnline = (uint16_t) get_nprocs();
|
||||||
|
|
||||||
|
#define BP "/sys/devices/system/cpu/cpufreq/policy0/"
|
||||||
|
if(ffFileExists(BP, S_IFDIR))
|
||||||
|
{
|
||||||
|
cpu->frequencyMin = getFrequency(BP"cpuinfo_min_freq", BP"scaling_min_freq");
|
||||||
|
cpu->frequencyMax = getFrequency(BP"cpuinfo_max_freq", BP"scaling_max_freq");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cpu->frequencyMin = cpu->frequencyMax = ffStrbufToDouble(&cpuMHz) / 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
ffStrbufDestroy(&physicalCoresBuffer);
|
||||||
|
ffStrbufDestroy(&cpuMHz);
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
#include "cpu.h"
|
||||||
|
#include "util/windows/registry.h"
|
||||||
|
#include "util/mallocHelper.h"
|
||||||
|
|
||||||
|
void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu)
|
||||||
|
{
|
||||||
|
FF_UNUSED(instance);
|
||||||
|
|
||||||
|
cpu->temperature = FF_CPU_TEMP_UNSET;
|
||||||
|
cpu->coresPhysical = cpu->coresLogical = cpu->coresOnline = 0;
|
||||||
|
cpu->frequencyMax = cpu->frequencyMin = 0;
|
||||||
|
ffStrbufInit(&cpu->name);
|
||||||
|
ffStrbufInit(&cpu->vendor);
|
||||||
|
|
||||||
|
{
|
||||||
|
DWORD length = 0;
|
||||||
|
GetLogicalProcessorInformationEx(RelationProcessorCore, NULL, &length);
|
||||||
|
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* FF_AUTO_FREE
|
||||||
|
pLogicalInfo = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)malloc(length);
|
||||||
|
|
||||||
|
if(pLogicalInfo && GetLogicalProcessorInformationEx(RelationProcessorCore, pLogicalInfo, &length))
|
||||||
|
{
|
||||||
|
for(
|
||||||
|
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* ptr = pLogicalInfo;
|
||||||
|
(uint8_t*)ptr < ((uint8_t*)pLogicalInfo) + length;
|
||||||
|
ptr = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)(((uint8_t*)ptr) + ptr->Size)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if(ptr->Relationship == RelationProcessorCore)
|
||||||
|
++cpu->coresPhysical;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cpu->coresOnline = (uint16_t)GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
|
||||||
|
cpu->coresLogical = (uint16_t)GetMaximumProcessorCount(ALL_PROCESSOR_GROUPS);
|
||||||
|
|
||||||
|
FF_HKEY_AUTO_DESTROY hKey;
|
||||||
|
if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", &hKey, NULL))
|
||||||
|
return;
|
||||||
|
|
||||||
|
{
|
||||||
|
uint32_t mhz;
|
||||||
|
if(ffRegReadUint(hKey, L"~MHz", &mhz, NULL))
|
||||||
|
cpu->frequencyMax = mhz / 1000.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ffRegReadStrbuf(hKey, L"ProcessorNameString", &cpu->name, NULL);
|
||||||
|
ffRegReadStrbuf(hKey, L"VendorIdentifier", &cpu->vendor, NULL);
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
#include "fastfetch.h"
|
||||||
|
#include "cpuUsage.h"
|
||||||
|
|
||||||
|
#include "common/time.h"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// We need to use uint64_t because sizeof(long) == 4 on Windows
|
||||||
|
const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll);
|
||||||
|
|
||||||
|
static uint64_t inUseAll1, totalAll1;
|
||||||
|
|
||||||
|
void ffPrepareCPUUsage()
|
||||||
|
{
|
||||||
|
ffGetCpuUsageInfo(&inUseAll1, &totalAll1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* ffGetCpuUsageResult(double* result)
|
||||||
|
{
|
||||||
|
const char* error = NULL;
|
||||||
|
if(inUseAll1 == 0 && totalAll1 == 0)
|
||||||
|
{
|
||||||
|
error = ffGetCpuUsageInfo(&inUseAll1, &totalAll1);
|
||||||
|
if(error)
|
||||||
|
return error;
|
||||||
|
ffTimeSleep(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
uint64_t inUseAll2, totalAll2;
|
||||||
|
error = ffGetCpuUsageInfo(&inUseAll2, &totalAll2);
|
||||||
|
if(error)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
if(inUseAll2 != inUseAll1)
|
||||||
|
{
|
||||||
|
*result = (double)(inUseAll2 - inUseAll1) / (double)(totalAll2 - totalAll1) * 100;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ffTimeSleep(200);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef FF_INCLUDED_detection_cpu_cpuUsage
|
||||||
|
#define FF_INCLUDED_detection_cpu_cpuUsage
|
||||||
|
|
||||||
|
const char* ffGetCpuUsageResult(double* result);
|
||||||
|
|
||||||
|
#endif
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user