Compare commits
1089 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4b253aa4cf | |||
| d7b84bed9f | |||
| 298d091e2e | |||
| ebe30394f2 | |||
| 4c7d479e93 | |||
| d6d204ae5f | |||
| ed23eb0fde | |||
| fbbfc7f73c | |||
| e0b2db17c2 | |||
| f360e10050 | |||
| c15f55762d | |||
| 7edc715cba | |||
| 27f76599bc | |||
| e8bde5a394 | |||
| 3b820f1145 | |||
| c1444c0822 | |||
| b424c525cc | |||
| f640102b0e | |||
| d9e79a5376 | |||
| 734ee38641 | |||
| e651633c54 | |||
| 6d4bd06ffe | |||
| 2af07fee4f | |||
| 6f4bdafb0c | |||
| a71f2142bb | |||
| 1e9ec5424a | |||
| 068cbafe3d | |||
| 4ce618c33c | |||
| 10b997608b | |||
| 5edab414d8 | |||
| 6e904047f9 | |||
| fdb0cfb4df | |||
| 58999995f1 | |||
| f4a58036fa | |||
| 65e2331979 | |||
| 622a5c267b | |||
| c746cde61e | |||
| 68977be256 | |||
| f28805fb94 | |||
| df793c20fd | |||
| a4e4e9c495 | |||
| b1ccd2e2c0 | |||
| 9a2687768f | |||
| ab7b0571f3 | |||
| 14286e8c0f | |||
| 6b41b85d4d | |||
| cc7724dec4 | |||
| c832c7d794 | |||
| 52f36d29dc | |||
| 9b6dafe715 | |||
| d4ecbc6638 | |||
| 1c93d68e7b | |||
| c1d92206f5 | |||
| 7bef5008c2 | |||
| 3ef3cca76b | |||
| a1d8e3e598 | |||
| dd77ebe11e | |||
| 27efc94b09 | |||
| b6abc6e326 | |||
| f13a502123 | |||
| f77f617bc2 | |||
| 6ae9e0b332 | |||
| 8a054706b5 | |||
| 6e1d656a60 | |||
| 53430b9827 | |||
| 026424ab8c | |||
| 9c0fc63ee9 | |||
| cdff99339e | |||
| b739d94f23 | |||
| e076097a7c | |||
| 3cee8f5475 | |||
| 83ea189d81 | |||
| dcf04aa4fe | |||
| 67ab7c0779 | |||
| 2b5511997c | |||
| 53c6a0ec9f | |||
| 1a710e4094 | |||
| 5a90d8b545 | |||
| f794053f99 | |||
| 670cf6fe90 | |||
| 46ed8aa87c | |||
| 387b8298bd | |||
| c4aa55d522 | |||
| c3861954dc | |||
| ebfbf108a2 | |||
| 66ed9adcda | |||
| eb02206c05 | |||
| cd0b74b0de | |||
| 6ca3b76a42 | |||
| 84a03e80de | |||
| a74f813df1 | |||
| 99fc4e76ec | |||
| 7145f5252d | |||
| 9dab23b5fc | |||
| 09ff8d35bc | |||
| ee903d2d07 | |||
| b2f978aa7c | |||
| 76d957a144 | |||
| a0acfeed56 | |||
| b1f63ab822 | |||
| 54ea9c2386 | |||
| ccdb5c54d0 | |||
| b8393051e4 | |||
| 94a8e0339e | |||
| a67ba713f5 | |||
| 8ffbae80b8 | |||
| db17f95ce8 | |||
| c6365755c7 | |||
| ef2a5110fe | |||
| 7f97725d7f | |||
| af03c74fba | |||
| bc8a7a03c3 | |||
| d4c361ae12 | |||
| 8f932ac3d6 | |||
| 4cc5f35b04 | |||
| 476b0495e0 | |||
| 85098a6627 | |||
| d9a022ffff | |||
| 8db1534ef3 | |||
| 0aa7d646a7 | |||
| 599c06e981 | |||
| 078cb6e5b7 | |||
| 5cc17bc306 | |||
| ef18c8e3f7 | |||
| 012c7552eb | |||
| 0fd63084dc | |||
| 0b12e73eef | |||
| 4daf3016f8 | |||
| 9f8e256bb4 | |||
| 1bbcd9ad0d | |||
| b1c0a2dc1e | |||
| 2a092de8d8 | |||
| bb57714ac9 | |||
| 137039f868 | |||
| e7af38aa11 | |||
| d0bab2ca22 | |||
| 2621c48f92 | |||
| 959540f17c | |||
| 3e2c344417 | |||
| a307977ec1 | |||
| f3db4e49b6 | |||
| 30f9bcbd22 | |||
| a98c71aab4 | |||
| 0d722ebe0b | |||
| 3caa92c567 | |||
| ae6d921f23 | |||
| d692fe91fb | |||
| 822496808d | |||
| 8533dc234b | |||
| 2193fb531f | |||
| c069d14af5 | |||
| 02abc07bc1 | |||
| 34c33dd42f | |||
| dcc22f3bd7 | |||
| 4247d15672 | |||
| 39d8ebc3c9 | |||
| 8e3b6280af | |||
| 4a781d8471 | |||
| 9f93ca8019 | |||
| 4890cb641c | |||
| 90bb004940 | |||
| 70df34caf9 | |||
| c04b421f26 | |||
| e292470ade | |||
| c0d3dc30e1 | |||
| 01df2ae3e4 | |||
| f8174a67d7 | |||
| 53265f6b7f | |||
| f245492679 | |||
| 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 |
@@ -10,7 +10,7 @@ trim_trailing_whitespace = true
|
||||
[*.{md,fflogo}]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.{txt,fflogo}]
|
||||
[*.{fflogo}]
|
||||
insert_final_newline = false
|
||||
|
||||
[*.yml]
|
||||
|
||||
@@ -1 +1 @@
|
||||
custom: paypal.me/linusdierheimer
|
||||
github: LinusDierheimer
|
||||
|
||||
@@ -7,6 +7,13 @@ 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
|
||||
@@ -18,6 +25,9 @@ Output of `fastfetch --load-config devinfo`:
|
||||
```
|
||||
|
||||
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
|
||||
```
|
||||
@@ -27,9 +37,7 @@ 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 to much work) for you, post the output of `fastfetch --show-errors --recache --multithreading false --disable-linewrap false`.
|
||||
|
||||
Often helpful questions:
|
||||
* Does the issue occur across multiple terminal emulators?
|
||||
* Does the issue occur across multiple shells? (bash, zsh, fish, etc)
|
||||
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,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.
|
||||
```
|
||||
@@ -1,37 +0,0 @@
|
||||
name: manage pull requests
|
||||
|
||||
on: pull_request
|
||||
|
||||
jobs:
|
||||
check:
|
||||
name: manage pull request
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
security-events: write
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- 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 rpm librpm-dev libzstd-dev
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
|
||||
- name: configure project
|
||||
run: cmake -DBUILD_TESTS=On .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . -j$(nproc) --target package
|
||||
|
||||
- name: run fastfetch
|
||||
run: ./fastfetch --recache --disable-linewrap false --hide-cursor false --show-errors true
|
||||
|
||||
- name: run flashfetch
|
||||
run: ./flashfetch
|
||||
|
||||
- name: run tests
|
||||
run: ctest
|
||||
|
||||
- name: perform CodeQL analysis
|
||||
uses: github/codeql-action/analyze@v1
|
||||
@@ -1,49 +1,226 @@
|
||||
name: manage pushes
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
- push
|
||||
- pull_request
|
||||
|
||||
jobs:
|
||||
manage:
|
||||
name: manage push
|
||||
linux:
|
||||
name: Linux
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
security-events: write
|
||||
contents: read
|
||||
outputs:
|
||||
ffversion: ${{ steps.ffversion.outputs.ffversion }}
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v2
|
||||
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 rpm librpm-dev libzstd-dev
|
||||
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 libnm-dev
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: c
|
||||
|
||||
- name: configure project
|
||||
# We reuse the build binary only for the releases.
|
||||
# We set tweak version to off, because it is wrong, as git tag will happen after this step. Releases don't have a tweak, so this is ok.
|
||||
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
|
||||
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . -j$(nproc) --target package
|
||||
run: cmake --build . --target package
|
||||
|
||||
- name: perform CodeQL analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
|
||||
- name: list features
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
- name: run fastfetch
|
||||
run: ./fastfetch --recache --disable-linewrap false --hide-cursor false --show-errors true
|
||||
run: time ./fastfetch --disable-linewrap false --hide-cursor false --show-errors true --load-config presets/all
|
||||
|
||||
- name: run flashfetch
|
||||
run: ./flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
- name: run tests
|
||||
run: ctest
|
||||
|
||||
- name: perform CodeQL analysis
|
||||
uses: github/codeql-action/analyze@v1
|
||||
|
||||
- name: get fastfetch version
|
||||
id: get_version_fastfetch
|
||||
run: echo "::set-output name=release::$(./fastfetch --version-raw)"
|
||||
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: list features
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
- 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
|
||||
./fastfetch --list-features
|
||||
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: list features
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
- 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-$(./fastfetch --version-raw)-Windows.zip *.dll fastfetch.exe flashfetch.exe
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: fastfetch-windows
|
||||
path: ./fastfetch-*-Windows.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
|
||||
@@ -52,9 +229,10 @@ jobs:
|
||||
repository: ${{ github.repository }}
|
||||
|
||||
- name: create release
|
||||
if: steps.get_version_fastfetch.outputs.release != steps.get_version_release.outputs.release
|
||||
if: needs.linux.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
uses: ncipollo/release-action@v1
|
||||
with:
|
||||
tag: ${{ steps.get_version_fastfetch.outputs.release }}
|
||||
tag: ${{ needs.linux.outputs.ffversion }}
|
||||
commit: ${{ github.sha }}
|
||||
artifacts: ./fastfetch-*.*
|
||||
artifactErrorsFailBuild: true
|
||||
artifacts: fastfetch-linux/*,fastfetch-macos/*,fastfetch-freebsd/*,fastfetch-windows/*
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
**/.vscode/
|
||||
**/.cache/
|
||||
**/.kdev4/
|
||||
**/.DS_Store
|
||||
/.vs
|
||||
cscope.*
|
||||
tags
|
||||
fastfetch.kdev4
|
||||
**/*.deb
|
||||
packaging/deb/fastfetch
|
||||
|
||||
@@ -0,0 +1,284 @@
|
||||
# 1.9.1
|
||||
|
||||
Bugfixes:
|
||||
|
||||
* Fix builds on s390x (@jonathanspw, #402)
|
||||
* Fix zero refresh rate on some monitors (macOS)
|
||||
* Fix default formatting of Wifi module
|
||||
|
||||
# 1.9.0
|
||||
|
||||
Notable Changes:
|
||||
* fastfetch no longer creates a sample config file silently. Use `--gen-config` to generate one.
|
||||
* fastfetch now search for user config file in the order of `fastfetch --list-config-paths`
|
||||
* Unknown disks are hidden by default.
|
||||
* `Resolution` module is renamed to `Display`. (#393)
|
||||
|
||||
Features:
|
||||
* `--logo-padding-top` option (@CarterLi, #372)
|
||||
* Raw image file as logo support (@CarterLi)
|
||||
* Look for config files in `$APPDATA` ([RoamingAppData](https://superuser.com/questions/21458/why-are-there-directories-called-local-locallow-and-roaming-under-users-user#answer-21462)) (Windows)
|
||||
* Look for config files in `~/Library/Preferences` (macOS)
|
||||
* Add `--list-config-paths` option which list search paths of config files
|
||||
* Add `--list-data-paths` option which list search paths for presets and logos
|
||||
* Add `Brightness` module support
|
||||
* Add `Battery` module support for FreeBSD
|
||||
* Add `--disk-show-unknown` option for Disk module
|
||||
* Add `--disk-show-subvolumes` option for Disk module
|
||||
* Add `--gpu-hide-integrated` option (#379)
|
||||
* Add `--gpu-hide-discrete` option (#379)
|
||||
* Detect terminal version when available
|
||||
* Support `WezTerm` terminal font detection (requires [`wezterm` executable](https://wezfurlong.org/wezterm/cli/general.html) being available)
|
||||
* Add `--shell-version` and `--terminal-version` options to disable shell / terminal version detection
|
||||
* Enhance `--percent-type` to allow hiding other texts (#387)
|
||||
* Add Wifi module support for Linux
|
||||
* Detect scaled resolutions (Windows, macOS)
|
||||
* Optimise font module printing (Windows)
|
||||
* Detect pacman package count inside MSYS2 environment (Windows)
|
||||
* Add Wifi / Battery module support for Android
|
||||
* Disk name support for Linux
|
||||
|
||||
Logos:
|
||||
* Raspbian (@IamNoRobot, #373)
|
||||
|
||||
Bugfixes:
|
||||
* `--logo-type` now does accept `iterm` too (@CarterLi, #374)
|
||||
* Fix mintty terminal font detection (Windows)
|
||||
* Fix bug that line buffering doesn't work properly (Windows)
|
||||
* Fix rpm package count detection (Linux)
|
||||
* Fix cpu temp detection (Linux)
|
||||
|
||||
Other:
|
||||
* Fixed a Typo in iterm error message (@jessebot, #376)
|
||||
* Don't try to load config file in `/etc` (Windows)
|
||||
|
||||
# 1.8.2
|
||||
|
||||
Bugfixes:
|
||||
|
||||
* Fix memleaks Users module (Windows)
|
||||
* Fix shell detection when installed with scoop (Windows)
|
||||
* Don't use libcJSON as wlanapi's dll name (Windows)
|
||||
* Align artifact names to other platforms (Windows)
|
||||
|
||||
# 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
|
||||
@@ -11,12 +11,6 @@ Here i just add things that are easy to forget.
|
||||
- `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
|
||||
- [ ] Support for printing images as ascii art logos (using imlib2 and libcaca probably)
|
||||
- [ ] Better OS output for all possible combinations of /etc/os-release variables.
|
||||
- [ ] Expose temperatures to CPU format string
|
||||
- [ ] Expose temperatures to GPU format string
|
||||
- [ ] Fallback GPU detection using GL (multi GPU suport somehow possible?)
|
||||
- [ ] Find wayland compositor by looking at \${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY:-wayland-0}
|
||||
- [ ] Make LocalIP module more configurable
|
||||
- [ ] Automatic migrate old config files to newer versions
|
||||
- [ ] ZSH completions
|
||||
|
||||
@@ -1,103 +1,161 @@
|
||||
# fastfetch
|
||||
# Fastfetch
|
||||
|
||||
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 c to achieve much better performance, in return only Linux and Android are supported. It also uses mechanisms like multithreading and caching to finish as fast as possible.
|
||||
|
||||
The output on my personal machine with default configurations looks like this:
|
||||
<img src="screenshots/example.png" alt="example output" width="100%"/>
|
||||
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 mainly in C, with performance and customizability in mind. Currently, Linux, Android, FreeBSD, MacOS and Windows 7+ are supported.
|
||||
|
||||
<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" />
|
||||
|
||||
There are [screenshots on different platforms](https://github.com/LinusDierheimer/fastfetch/wiki)
|
||||
|
||||
## Customization
|
||||
|
||||
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.
|
||||
|
||||
There are some presets defined for fastfech in [`presets`](presets), you can can load them with `--load-config`. They may also serve as a good example for format arguments.
|
||||
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 `$XDG_CONFIG_HOME/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.
|
||||
|
||||
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.
|
||||
|
||||
Logos can be heavily customized to. See the [logo documentation](doc/logo.md) for more information.
|
||||
|
||||
## Dependencies
|
||||
|
||||
Fastfetch dynamically loads needed libraries if they are available. Therefore its only hard dependencies are `libc` (any implementation of the c standard library), `libdl` and `libpthread`. They are all shipped with [`glibc`](https://www.gnu.org/software/libc/), which is already installed on most linux distributions, so you probably don't have to worry about it.
|
||||
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.
|
||||
|
||||
The following libraries are used if present at runtime:
|
||||
* [`libpci`](https://github.com/pciutils/pciutils): GPU output.
|
||||
* [`libvulkan`](https://www.vulkan.org/): 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.
|
||||
* [`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.
|
||||
* [`libXFConf`](https://gitlab.xfce.org/xfce/xfconf): Needed for XFWM theme and XFCE Terminal font.
|
||||
* [`librpm`](http://rpm.org/): Needed for rpm package count.
|
||||
|
||||
### Linux and FreeBSD
|
||||
|
||||
* [`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 display 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 display 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 ).
|
||||
* [`libnm`](https://networkmanager.dev/docs/libnm/latest/): Used for Wifi detection on Linux.
|
||||
|
||||
### macOS
|
||||
|
||||
* [`MediaRemote`](https://iphonedev.wiki/index.php/MediaRemote.framework): Need for Media detection. It's a private framework provided by newer macOS system.
|
||||
* [`DisplayServices`](https://developer.apple.com/forums/thread/666383#663154022): Need for screen brightness 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, as fastfetch for Windows targets [UCRT](https://learn.microsoft.com/en-us/cpp/windows/universal-crt-deployment) C runtime library, [it must be installed manually](https://support.microsoft.com/en-us/topic/update-for-universal-c-runtime-in-windows-c0514201-7fe6-95a3-b0a5-287930f3560c) as UCRT is only pre-installed in Windows 10 and later.
|
||||
|
||||
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)
|
||||
* [`termux-api`](https://github.com/termux/termux-api-package): Used for Wifi / Battery detection. Read [the official doc](https://wiki.termux.com/wiki/Termux:API) for detail or if you hang on these modules (IMPORTANT). [`termux-api`](https://github.com/termux/termux-packages/tree/master/packages/termux-api)
|
||||
|
||||
## Support status
|
||||
All categories not listed here should work without needing a specific implementation.
|
||||
|
||||
##### Available Modules
|
||||
```
|
||||
Title, Separator, OS, Host, Kernel, Uptime, Processes, Packages, Shell, Resolution, DE, WM, WMTheme, Theme, Icons, Font, Cursor, Terminal, Terminal Font, CPU, CPUUsage, GPU, Memory, Disk, Battery, Player, Song, LocalIP, PublicIP, DateTime, Date, Time, Locale, Colors, Break, Custom
|
||||
Battery, Bios, Board, Break, Brightness, Colors, Command, CPU, CPUUsage, Cursor, Custom, Date, DateTime, DE, Disk, Display, Font, GPU, Host, Icons, Kernel, Locale, LocalIP, Media, Memory, OpenCL, OpenGL, Packages, Player, Power Adapter, Processes, PublicIP, Separator OS, Shell, Swap, Terminal, Terminal Font, Theme, Time, Title, Uptime, Vulkan, Wifi, WM, WMTheme
|
||||
```
|
||||
|
||||
##### Logos
|
||||
##### Builtin logos
|
||||
```
|
||||
Android, Arch, Arco, Artix, CachyOS, CentOS, Debian, Endeavour, Fedora, Garuda, Gentoo, KDE Neon, Linux, Manjaro, Mint, NixOS, OpenSUSE, OpenSUSE Tumbleweed, OpenSUSE LEAP, Pop!_OS, RebornOS, Ubuntu, Void, Zorin
|
||||
AlmaLinux, Alpine, Android, Arch, Arco, Artix, Bedrock, CachyOS, CentOS, CRUX, Crystal, Debian, Deepin, Devuan, Endeavour, Enso, Fedora, FreeBSD, Garuda, Gentoo, KDE Neon, KISS, Kubuntu, LangitKetujuh, Linux, MacOS, Manjaro, Mint, MSYS2, NixOS, Nobara, OpenSUSE, OpenSUSE LEAP, OpenSUSE Tumbleweed, Parabola, Pop!_OS, Raspbian, RebornOS, RedstarOS, Rocky, Rosa, Slackware, Solus, Ubuntu, Vanilla, Void, Windows, Windows 11, Windows 8, 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.
|
||||
* Unknown/unsupported logos will be replaced with a generic linux logo when running fastfetch.
|
||||
* Get a list of all available logos with `fastfetch --print-logos`.
|
||||
* Printing images as logo is supported using Sixel or Kitty graphics protocol.
|
||||
|
||||
##### Package managers
|
||||
```
|
||||
Pacman, dpkg, rpm, emerge, xbps, nix, Flatpak, Snap
|
||||
apk, brew, Chocolatey, dpkg, emerge, eopkg, Flatpak, MacPorts, nix, Pacman, pkg, rpm, scoop, Snap, xbps
|
||||
```
|
||||
|
||||
##### WM themes
|
||||
```
|
||||
KWin, Mutter, Muffin, Marco, XFWM, Openbox (LXDE, LXQT & without DE)
|
||||
DWM (Windows), KWin, Marco, Muffin, Mutter, Openbox (LXDE, LXQT & without DE), Quartz Compositor (macOS), XFWM
|
||||
```
|
||||
|
||||
##### DE versions
|
||||
```
|
||||
KDE Plasma, Gnome, Cinnamon, Mate, XFCE4, LXQt
|
||||
Budgie, Cinnamon, Gnome, KDE Plasma, LXQt, Mate, XFCE4
|
||||
```
|
||||
|
||||
##### Terminal fonts
|
||||
```
|
||||
konsole, gnome-terminal-server, tilix, xfce4-terminal, lxterminal, TTY
|
||||
Alacritty, Apple Terminal, ConEmu, Deepin Terminal, Gnome Terminal, iTerm2, Kitty, Konsole, LXTerminal, mintty, Termux, Tilix, TTY, Warp, WezTerm, Windows Terminal, XFCE4 Terminal
|
||||
```
|
||||
|
||||
## Building
|
||||
|
||||
fastfetch uses [`cmake`](https://cmake.org/) and [`pkg-config`](https://www.freedesktop.org/wiki/Software/pkg-config/) for building. The simplest steps to build the fastfetch and flashfetch binaries are:
|
||||
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 . -j$(nproc) --target fastfetch --target flashfetch
|
||||
cmake --build . --target fastfetch --target flashfetch
|
||||
```
|
||||
|
||||
If pkg-config 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.
|
||||
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
|
||||
```
|
||||
|
||||
Follow the building instructions of Linux next.
|
||||
|
||||
## Packaging
|
||||
|
||||
* [AUR](https://aur.archlinux.org/packages/fastfetch-git/): Packaged by me. Will install the fastfetch binary, bash completion and the presets. Git version
|
||||
* [Manjaro Repositories](https://gitlab.manjaro.org/packages/community/fastfetch): Packaged by a manjaro maintainer. Usually a bit outdated.
|
||||
* [Gentoo (Guru)](https://github.com/gentoo/guru/tree/master/app-misc/fastfetch): Packed by some other guy. May be out of date some times.
|
||||
* DEB / RPM: Run `cmake -B build && cmake --build build --target package` to build the packages in build.
|
||||
* Manually:
|
||||
* Build: Follow the [build instructions](#building).
|
||||
* Install: `sudo cmake --install build --prefix /usr/local`
|
||||
### 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.
|
||||
> 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
|
||||
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
|
||||
|
||||
@@ -9,28 +9,39 @@ __fastfetch_complete_help()
|
||||
"os-format"
|
||||
"host-format"
|
||||
"kernel-format"
|
||||
"uptime-format"
|
||||
"processes-format"
|
||||
"packages-format"
|
||||
"shell-format"
|
||||
"resolution-format"
|
||||
"display-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"))
|
||||
}
|
||||
@@ -57,6 +68,41 @@ __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=(
|
||||
@@ -64,6 +110,9 @@ __fastfetch_complete_option()
|
||||
"${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
|
||||
@@ -108,8 +157,11 @@ __fastfetch_completion()
|
||||
"--list-presets"
|
||||
"--list-features"
|
||||
"--print-logos"
|
||||
"--print-config"
|
||||
"--print-config-system"
|
||||
"--print-config-user"
|
||||
"--print-structure"
|
||||
"--gen-config"
|
||||
"--gen-config-force"
|
||||
)
|
||||
|
||||
local FF_OPTIONS_HELP=(
|
||||
@@ -119,17 +171,33 @@ __fastfetch_completion()
|
||||
|
||||
local FF_OPTIONS_BOOL=(
|
||||
"-r"
|
||||
"--recache"
|
||||
"--nocache"
|
||||
"--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"
|
||||
"--shell-version"
|
||||
"--terminal-version"
|
||||
"--disk-folders"
|
||||
"--disk-show-removable"
|
||||
"--disk-show-hidden"
|
||||
"--disk-show-subvolumes"
|
||||
"--gpu-hide-integrated"
|
||||
"--gpu-hide-discrete"
|
||||
"--disk-show-unknown"
|
||||
)
|
||||
|
||||
local FF_OPTIONS_STRING=(
|
||||
@@ -137,6 +205,7 @@ __fastfetch_completion()
|
||||
"--logo-padding"
|
||||
"--logo-padding-left"
|
||||
"--logo-padding-right"
|
||||
"--logo-padding-top"
|
||||
"--logo-color-1"
|
||||
"--logo-color-2"
|
||||
"--logo-color-3"
|
||||
@@ -145,97 +214,167 @@ __fastfetch_completion()
|
||||
"--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"
|
||||
"--os-format"
|
||||
"--set-keyless"
|
||||
"--player-name"
|
||||
"--percent-type"
|
||||
"--public-ip-url"
|
||||
"--public-ip-timeout"
|
||||
"--weather-output-format"
|
||||
"--weather-timeout"
|
||||
"--os-key"
|
||||
"--host-format"
|
||||
"--os-format"
|
||||
"--os-error"
|
||||
"--host-key"
|
||||
"--kernel-format"
|
||||
"--host-format"
|
||||
"--host-error"
|
||||
"--kernel-key"
|
||||
"--uptime-format"
|
||||
"--kernel-format"
|
||||
"--kernel-error"
|
||||
"--uptime-key"
|
||||
"--processes-format"
|
||||
"--uptime-format"
|
||||
"--uptime-error"
|
||||
"--processes-key"
|
||||
"--packages-format"
|
||||
"--processes-format"
|
||||
"--processes-error"
|
||||
"--packages-key"
|
||||
"--shell-format"
|
||||
"--packages-format"
|
||||
"--packages-error"
|
||||
"--shell-key"
|
||||
"--resolution-format"
|
||||
"--resolution-key"
|
||||
"--de-format"
|
||||
"--shell-format"
|
||||
"--shell-error"
|
||||
"--display-key"
|
||||
"--display-format"
|
||||
"--display-error"
|
||||
"--de-key"
|
||||
"--wm-format"
|
||||
"--de-format"
|
||||
"--de-error"
|
||||
"--wm-key"
|
||||
"--wm-theme-format"
|
||||
"--wm-format"
|
||||
"--wm-error"
|
||||
"--wm-theme-key"
|
||||
"--theme-format"
|
||||
"--wm-theme-format"
|
||||
"--wm-theme-error"
|
||||
"--theme-key"
|
||||
"--icons-format"
|
||||
"--theme-format"
|
||||
"--theme-error"
|
||||
"--icons-key"
|
||||
"--font-format"
|
||||
"--icons-format"
|
||||
"--icons-error"
|
||||
"--font-key"
|
||||
"--cursor-format"
|
||||
"--font-format"
|
||||
"--font-error"
|
||||
"--cursor-key"
|
||||
"--terminal-format"
|
||||
"--cursor-format"
|
||||
"--cursor-error"
|
||||
"--terminal-key"
|
||||
"--terminal-font-format"
|
||||
"--terminal-format"
|
||||
"--terminal-error"
|
||||
"--terminal-font-key"
|
||||
"--cpu-format"
|
||||
"--terminal-font-format"
|
||||
"--terminal-font-error"
|
||||
"--cpu-key"
|
||||
"--cpu-usage-format"
|
||||
"--cpu-usage-key"
|
||||
"--gpu-format"
|
||||
"--cpu-format"
|
||||
"--cpu-error"
|
||||
"--cpu-useage-key"
|
||||
"--cpu-useage-format"
|
||||
"--cpu-useage-error"
|
||||
"--gpu-key"
|
||||
"--memory-format"
|
||||
"--gpu-format"
|
||||
"--gpu-error"
|
||||
"--memory-key"
|
||||
"--memory-format"
|
||||
"--memory-error"
|
||||
"--swap-key"
|
||||
"--swap-format"
|
||||
"--swap-error"
|
||||
"--disk-key"
|
||||
"--disk-format"
|
||||
"--disk-key"
|
||||
"--battery-format"
|
||||
"--disk-error"
|
||||
"--battery-key"
|
||||
"--locale-format"
|
||||
"--battery-format"
|
||||
"--battery-error"
|
||||
"--poweradapter-key"
|
||||
"--poweradapter-format"
|
||||
"--poweradapter-error"
|
||||
"--locale-key"
|
||||
"--disk-folders"
|
||||
"--disk-key"
|
||||
"--local-ip-format"
|
||||
"--locale-format"
|
||||
"--locale-error"
|
||||
"--local-ip-key"
|
||||
"--public-ip-format"
|
||||
"--local-ip-format"
|
||||
"--local-ip-error"
|
||||
"--public-ip-key"
|
||||
"--player-format"
|
||||
"--public-ip-format"
|
||||
"--public-ip-error"
|
||||
"--wifi-key"
|
||||
"--wifi-format"
|
||||
"--wifi-error"
|
||||
"--weather-key"
|
||||
"--weather-format"
|
||||
"--weather-error"
|
||||
"--player-key"
|
||||
"--song-format"
|
||||
"--song-key"
|
||||
"--player-format"
|
||||
"--player-error"
|
||||
"--media-key"
|
||||
"--media-format"
|
||||
"--media-error"
|
||||
"--datetime-key"
|
||||
"--datetime-format"
|
||||
"--date-format"
|
||||
"--datetime-error"
|
||||
"--date-key"
|
||||
"--time-format"
|
||||
"--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-pci"
|
||||
"--lib-vulkan"
|
||||
"--lib-wayland"
|
||||
"--lib-xcb-randr"
|
||||
"--lib-xcb"
|
||||
"--lib-Xrandr"
|
||||
"--lib-xrandr"
|
||||
"--lib-X11"
|
||||
"--lib-gio"
|
||||
"--lib-DConf"
|
||||
"--lib-DBus"
|
||||
"--lib-XFConf"
|
||||
"--lib-RPM"
|
||||
"--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"
|
||||
"--load-config"
|
||||
)
|
||||
|
||||
local FF_OPTIONS_LOGO=(
|
||||
@@ -243,6 +382,18 @@ __fastfetch_completion()
|
||||
"--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
|
||||
@@ -259,6 +410,12 @@ __fastfetch_completion()
|
||||
__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
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
# Logo options
|
||||
|
||||
## General
|
||||
|
||||
| Option | Default | Description |
|
||||
|--------|---------|-------------|
|
||||
| `--logo`, `-l` | `""` | The logo source, interpreted depending on type |
|
||||
| `--logo-type` | `auto` | The logo type. See the following categories for possible values |
|
||||
| `--<type>` | `""` | Short for `--logo-type <type> --logo <value>` |
|
||||
| `--logo-padding` | `""` | Sets the padding left and right of the logo |
|
||||
| `--logo-padding-left` | `0` | Sets the padding left of the logo |
|
||||
| `--logo-padding-right` | `4` | Sets the padding right of the logo |
|
||||
| `--logo-padding-top` | `0` | Sets the padding top of the logo |
|
||||
|
||||
All filesytem paths can be:
|
||||
* Absolute
|
||||
* Relative to the current working directory
|
||||
* Relative to any of the directories listed by `fastfetch --list-data-paths` + `/logos`
|
||||
For example, the file `~/.local/share/fastfetch/logos/shrek` can simply be referenced as `shrek`.
|
||||
|
||||
## Text
|
||||
|
||||
| Option | Default | Description |
|
||||
|--------|---------|-------------|
|
||||
| `--logo-color-[1-9]` | `""` | Overrides a color for logos that support it |
|
||||
| `--logo-print-remaining` | `true` | Print the remaining logo, if it is higher than the keys |
|
||||
|
||||
* Color placeholders are in the form `$[1-9]`. To print a `$`, use `$$`.
|
||||
* If a color placeholder value is not set, the placeholder is simply discarded.
|
||||
|
||||
## Image
|
||||
|
||||
| Option | Default | Description |
|
||||
|--------|---------|-------------|
|
||||
| `--logo-width` | `""` | Sets the width of the logo for logos that support it |
|
||||
| `--logo-height` | `""` | Sets the height of the logo for logos that support it |
|
||||
|
||||
* If one of the height / width options is set, but the other not, the aspect ratio is preserved.
|
||||
* If neither height nor width is set, the original size is used.
|
||||
|
||||
# Logo types
|
||||
|
||||
## auto
|
||||
|
||||
Trys to detect the logo type depending on the value of `--logo`, in the following order:
|
||||
* If the value is empty / not set, an autodected builtin logo is displayed.
|
||||
* If the value is the name of a builtin logo, it is displayed.
|
||||
* If the value is the path to an image file, and the terminal emulator is known to support an image protocol, the image is displayed.
|
||||
* If the value is the path to a text file, the content is displayed.
|
||||
* The autodetected builtin logo is displayed.
|
||||
|
||||
## builtin
|
||||
|
||||
The value of `--logo` is interpreted as the name of a builtin logo.
|
||||
* If the value is empty / not set, it is autodetected.
|
||||
* Use `--list-logos` to get a list of all available logos.
|
||||
* Use `--print-logos` to see all available logos.
|
||||
* All builtin logos set default values for `--logo-color-[1-9]`.
|
||||
* Use `none` to disable the logo, but keep key colors from the detected logo.
|
||||
|
||||
## file
|
||||
|
||||
The value of `--logo` is interpreted as the path to a file. The content of the file is displayed.
|
||||
* If the file can't be read, the autodetected builtin logo is displayed.
|
||||
|
||||
## file-raw
|
||||
|
||||
The value of `--logo` is interpreted as the path to a file. The content of the file is displayed.
|
||||
* No color placeholder replacement is done.
|
||||
* If the file can't be read, the autodetected builtin logo is displayed.
|
||||
|
||||
## data
|
||||
|
||||
The value of `--logo` is interpreted as the logo and directly displayed.
|
||||
* If the value is empty / not set, the autodetected builtin logo is displayed.
|
||||
|
||||
## data-raw
|
||||
|
||||
The value of `--logo` is interpreted as the logo and directly displayed.
|
||||
* No color placeholder replacement is done.
|
||||
* If the value is empty / not set, the autodetected builtin logo is displayed.
|
||||
|
||||
## sixel
|
||||
|
||||
The value of `--logo` is interpreted as the path to an image file. It is displayed using the sixel graphics protocol.
|
||||
* `fastfetch` must be compiled with the `imagemagick6` or `imagemagick7` feature.
|
||||
|
||||
## kitty
|
||||
|
||||
The value of `--logo` is interpreted as the path to an image file. It is displayed using the kitty graphics protocol.
|
||||
* If the file is a png file, and both `--logo-width` and `--logo-height` are specified, the image is directly send to the terminal emulator.
|
||||
* Otherwise `fastfetch` must be compiled with the `imagemagick6` or `imagemagick7` feature.
|
||||
|
||||
## iterm
|
||||
|
||||
The value of `--logo` is interpreted as the path to an image file. It is displayed using the iTerm graphics protocol.
|
||||
* Both `--logo-width` and `--logo-height` must be specified.
|
||||
|
||||
## chafa
|
||||
|
||||
The value of `--logo` is interpreted as the path to an image file. It is converted to an ascii logo using `libchafa`.
|
||||
* `fastfetch` must be compiled with the `chafa` feature.
|
||||
* `fastfetch` must be compiled with the `imagemagick6` or `imagemagick7` feature.
|
||||
* Use `--chafa-fg-only` to set weather to render foreground only.
|
||||
* Use `--chafa-symbols` to set the symbols.
|
||||
* Use `--chafa-canvas-mode` to set the canvas mode.
|
||||
* Use `--chafa-color-space` to set the color space.
|
||||
* Use `--chafa-dither-mode` to set the dither mode.
|
||||
* See the [chafa documentation](https://hpjansson.org/chafa/man/) for more information.
|
||||
|
||||
## raw
|
||||
|
||||
The value of `--logo` is interpreted as the path to a binary file. It is printed as-is.
|
||||
* Both `--logo-width` and `--logo-height` must be specified.
|
||||
* Use this to display a pre converted image file.
|
||||
* If the file can't be read, the autodetected builtin logo is displayed.
|
||||
@@ -1 +1 @@
|
||||
--structure Title:Separator:OS:Host:Kernel:Uptime:Processes:Packages:Shell:Resolution:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:GPU:Memory:Disk:Battery:Player:Song:PublicIP:LocalIP:DateTime:Locale:Break:Colors
|
||||
--structure Title:Separator:OS:Host:Bios:Board:Chassis:Kernel:Uptime:Processes:Packages:Shell:Display:Brightness: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
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
--disable-linewrap false
|
||||
--multithreading false
|
||||
--show-errors true
|
||||
--recache
|
||||
--show-errors
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
--load-config verbose
|
||||
--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
|
||||
@@ -1,4 +1,4 @@
|
||||
--structure Host:Resolution:CPU:GPU:Memory:Disk:Battery
|
||||
--memory-format "{?2}{2}MiB{?}"
|
||||
--disk-format "{?2}{2}GB{?}"
|
||||
--structure Host:Display:CPU:GPU:Memory:Disk:Battery
|
||||
--memory-format "{?2}{2}{?}"
|
||||
--disk-format "{?2}{2}{?}"
|
||||
--battery-format "{?1}{1} {?}{?2}{2} {?}{?3}({3}){?}"
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
--structure "Title:Separator:OS:Host:Kernel:Uptime:Packages:Shell:Resolution:DE:WM:WMTheme:Theme:Icons:Terminal:TerminalFont:CPU:GPU:Memory:Break:Colors"
|
||||
--structure "Title:Separator:OS:Host:Kernel:Uptime:Packages:Shell:Display: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{}"
|
||||
--display-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}{-}{/}{}MiB / {}MiB"
|
||||
--memory-format "{/1}{-}{/}{/2}{-}{/}{} / {}"
|
||||
--gpu-key "GPU"
|
||||
--resolution-key "Resolution"
|
||||
--display-key "Display"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
--structure Title:Separator:OS:Host:Kernel:Uptime:Battery:Break:Packages:Shell:Resolution:Terminal:Break:CPU:GPU:Memory:Break:Colors
|
||||
--structure Title:Separator:OS:Host:Kernel:Uptime:Battery:Break:Packages:Shell:Display:Terminal:Break:CPU:GPU:Memory:Break:Colors
|
||||
--host-format "{/2}{-}{/}{2}{?3} {3}{?}"
|
||||
--battery-format "{/4}{-}{/}{4}%{?5} [{5}]{?}"
|
||||
--resolution-key "Resolution"
|
||||
--display-key "Display"
|
||||
--gpu-key "GPU"
|
||||
|
||||
@@ -1,28 +1,30 @@
|
||||
--load-config all
|
||||
|
||||
--os-format "System: {}; Name: {}; Pretty name: {}; ID: {}; ID like: {}; Variant: {}; Variant ID: {}; Version: {}; Version ID: {}; Version codename: {}; Build ID: {}; Architecture: {}"
|
||||
--host-format "Family: {}; Name: {}; Version: {}"
|
||||
--kernel-format "Sysname: {}; Release: {}; Version: {}"
|
||||
--uptime-format "Days: {}; Hours: {}; Minutes: {}; Seconds: {}"
|
||||
--processes-format "Count: {}"
|
||||
--packages-format "All: {}; pacman: {}; pacman branch: {}; dpkg: {}; rpm: {}; emerge: {}; xbps: {}; flatpak: {}; snap: {}"
|
||||
--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 "Plasma raw: {}; Plasma name: {}; Plasma size: {}; Plasma styles: {}; Plasma pretty: {}; GTK2 raw: {}; GTK2 name: {}; GTK2 size: {}; GTK2 styles: {}; GTK2 pretty: {}; GTK3 raw: {}; GTK3 name: {}; GTK3 size: {}; GTK3 styles: {}; GTK3 pretty: {}; GTK4 raw: {}; GTK4 name: {}; GTK4 size: {}; GTK4 styles: {}; GTK4 pretty: {}; GTK: {}"
|
||||
--cursor-format "Theme: {}; Size: {}"
|
||||
--terminal-format "Process: {}; Path: {}; Exe: {}"
|
||||
--terminal-font-format "Raw: {}; Name: {}; Size: {}; Styles: {}; Pretty: {}"
|
||||
--cpu-format "Name: {}; Pretty: {}; Vendor: {}; Logical online: {}; Logical configured: {}; Physical: {}; Cores: {}; bios: {}; scaling max: {}; scaling min: {}; info max: {}; info min: {}; cpuinfo: {}; frequency: {}"
|
||||
--cpu-usage-format "Percentage: {}"
|
||||
--gpu-format "Vendor: {}; Vendor pretty: {}; Name: {}; Name pretty: {}; Driver: {}"
|
||||
--memory-format "Used: {}; Total: {}; Percentage: {}"
|
||||
--disk-format "Used: {}; Total: {}; Files: {}; Percentage: {}"
|
||||
--battery-format "Manufactor: {}; Model: {}; Technology: {}; Capacaty: {}; Status: {}"
|
||||
--player-format "Name: {}"
|
||||
--song-format "Song: {}; Artist: {}; Album: {}"
|
||||
--datetime-format "year: {}; yearShort: {}; month: {}; monthPretty: {}; monthName: {}; monthNameShort: {}; weekNumber: {}; weekday: {}; weekdayShort: {}; dayInYear: {}; dayInMonth: {}; dayInWeek: {}; hour: {}; hourPretty: {}; hour12: {}; hour12Pretty: {}; minute: {}; minutePretty: {}; second: {}; secondPretty: {}"
|
||||
--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: {}
|
||||
--display-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: {}
|
||||
|
||||
@@ -1,6 +1,22 @@
|
||||
#!/bin/env sh
|
||||
#!/usr/bin/env sh
|
||||
|
||||
set -e
|
||||
|
||||
mkdir -p build/
|
||||
cd build/
|
||||
cmake ..
|
||||
cmake --build . --target fastfetch -j$(nproc)
|
||||
|
||||
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 "$@"
|
||||
|
||||
|
Before Width: | Height: | Size: 208 KiB |
|
After Width: | Height: | Size: 68 KiB |
|
After Width: | Height: | Size: 70 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 39 KiB |
|
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,17 @@
|
||||
#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,
|
||||
FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT = 4,
|
||||
};
|
||||
|
||||
void ffAppendPercentBar(FFinstance* instance, FFstrbuf* buffer, uint8_t percent, uint8_t green, uint8_t yellow, uint8_t red);
|
||||
|
||||
#endif
|
||||
@@ -1,203 +0,0 @@
|
||||
#include "fastfetch.h"
|
||||
|
||||
#define FF_CACHE_VALUE_EXTENSION "ffcv"
|
||||
#define FF_CACHE_SPLIT_EXTENSION "ffcs"
|
||||
|
||||
static void getCacheFilePath(FFinstance* instance, const char* moduleName, const char* extension, FFstrbuf* buffer)
|
||||
{
|
||||
ffStrbufAppend(buffer, &instance->state.cacheDir);
|
||||
ffStrbufAppendS(buffer, moduleName);
|
||||
|
||||
if(extension != NULL)
|
||||
{
|
||||
ffStrbufAppendC(buffer, '.');
|
||||
ffStrbufAppendS(buffer, extension);
|
||||
}
|
||||
}
|
||||
|
||||
static void readCacheFile(FFinstance* instance, const char* moduleName, const char* extension, FFstrbuf* buffer)
|
||||
{
|
||||
FFstrbuf path;
|
||||
ffStrbufInitA(&path, 64);
|
||||
getCacheFilePath(instance, moduleName, extension, &path);
|
||||
ffAppendFileContent(path.chars, buffer);
|
||||
ffStrbufDestroy(&path);
|
||||
}
|
||||
|
||||
static void writeCacheFile(FFinstance* instance, const char* moduleName, const char* extension, FFstrbuf* content)
|
||||
{
|
||||
FFstrbuf path;
|
||||
ffStrbufInitA(&path, 64);
|
||||
getCacheFilePath(instance, moduleName, extension, &path);
|
||||
ffWriteFileContent(path.chars, content);
|
||||
ffStrbufDestroy(&path);
|
||||
}
|
||||
|
||||
void ffCacheValidate(FFinstance* instance)
|
||||
{
|
||||
if(instance->config.recache)
|
||||
return;
|
||||
|
||||
FFstrbuf content;
|
||||
ffStrbufInit(&content);
|
||||
readCacheFile(instance, "cacheversion", "ffv", &content);
|
||||
|
||||
bool isSameVersion = ffStrbufCompS(&content, FASTFETCH_PROJECT_VERSION) == 0;
|
||||
ffStrbufDestroy(&content);
|
||||
if(isSameVersion)
|
||||
return;
|
||||
|
||||
instance->config.recache = true;
|
||||
|
||||
FFstrbuf version;
|
||||
ffStrbufInitA(&version, sizeof(FASTFETCH_PROJECT_VERSION));
|
||||
ffStrbufAppendS(&version, FASTFETCH_PROJECT_VERSION);
|
||||
writeCacheFile(instance, "cacheversion", "ffv", &version);
|
||||
ffStrbufDestroy(&version);
|
||||
}
|
||||
|
||||
void ffCacheOpenWrite(FFinstance* instance, const char* moduleName, FFcache* cache)
|
||||
{
|
||||
FFstrbuf cacheFileValue;
|
||||
ffStrbufInitA(&cacheFileValue, 64);
|
||||
getCacheFilePath(instance, moduleName, FF_CACHE_VALUE_EXTENSION, &cacheFileValue);
|
||||
cache->value = fopen(cacheFileValue.chars, "w");
|
||||
ffStrbufDestroy(&cacheFileValue);
|
||||
|
||||
FFstrbuf cacheFileSplit;
|
||||
ffStrbufInitA(&cacheFileSplit, 64);
|
||||
getCacheFilePath(instance, moduleName, FF_CACHE_SPLIT_EXTENSION, &cacheFileSplit);
|
||||
cache->split = fopen(cacheFileSplit.chars, "w");
|
||||
ffStrbufDestroy(&cacheFileSplit);
|
||||
}
|
||||
|
||||
void ffCacheClose(FFcache* cache)
|
||||
{
|
||||
if(cache->value != NULL)
|
||||
fclose(cache->value);
|
||||
|
||||
if(cache->split != NULL)
|
||||
fclose(cache->split);
|
||||
}
|
||||
|
||||
static bool printCachedValue(FFinstance* instance, const char* moduleName, const FFstrbuf* customKeyFormat)
|
||||
{
|
||||
FFstrbuf content;
|
||||
ffStrbufInitA(&content, 512);
|
||||
readCacheFile(instance, moduleName, FF_CACHE_VALUE_EXTENSION, &content);
|
||||
|
||||
ffStrbufTrimRight(&content, '\0'); //Strbuf always appends a '\0' at the end. We want the last null byte to be at the position of the length
|
||||
|
||||
if(content.length == 0)
|
||||
return false;
|
||||
|
||||
uint8_t moduleCounter = 1;
|
||||
|
||||
uint32_t startIndex = 0;
|
||||
while(startIndex < content.length)
|
||||
{
|
||||
uint32_t nullByteIndex = ffStrbufNextIndexC(&content, startIndex, '\0');
|
||||
uint8_t moduleIndex = (moduleCounter == 1 && nullByteIndex == content.length) ? 0 : moduleCounter;
|
||||
ffPrintLogoAndKey(instance, moduleName, moduleIndex, customKeyFormat);
|
||||
puts(content.chars + startIndex);
|
||||
startIndex = nullByteIndex + 1;
|
||||
++moduleCounter;
|
||||
}
|
||||
|
||||
ffStrbufDestroy(&content);
|
||||
|
||||
return moduleCounter > 1;
|
||||
}
|
||||
|
||||
static bool printCachedFormat(FFinstance* instance, const char* moduleName, const FFstrbuf* customKeyFormat, const FFstrbuf* formatString, uint32_t numArgs)
|
||||
{
|
||||
FFstrbuf content;
|
||||
ffStrbufInitA(&content, 512);
|
||||
readCacheFile(instance, moduleName, FF_CACHE_SPLIT_EXTENSION, &content);
|
||||
|
||||
ffStrbufTrimRight(&content, '\0'); //Strbuf always appends a '\0' at the end. We want the last null byte to be at the position of the length
|
||||
|
||||
if(content.length == 0)
|
||||
return false;
|
||||
|
||||
uint8_t moduleCounter = 1;
|
||||
|
||||
FFformatarg* arguments = calloc(numArgs, sizeof(FFformatarg));
|
||||
uint32_t argumentCounter = 0;
|
||||
|
||||
uint32_t startIndex = 0;
|
||||
while(startIndex < content.length)
|
||||
{
|
||||
arguments[argumentCounter].type = FF_FORMAT_ARG_TYPE_STRING;
|
||||
arguments[argumentCounter].value = &content.chars[startIndex];
|
||||
++argumentCounter;
|
||||
|
||||
uint32_t nullByteIndex = ffStrbufNextIndexC(&content, startIndex, '\0');
|
||||
|
||||
if(argumentCounter == numArgs)
|
||||
{
|
||||
uint8_t moduleIndex = (moduleCounter == 1 && nullByteIndex == content.length) ? 0 : moduleCounter;
|
||||
ffPrintFormatString(instance, moduleName, moduleIndex, customKeyFormat, formatString, NULL, numArgs, arguments);
|
||||
++moduleCounter;
|
||||
argumentCounter = 0;
|
||||
}
|
||||
|
||||
startIndex = nullByteIndex + 1;
|
||||
}
|
||||
|
||||
free(arguments);
|
||||
ffStrbufDestroy(&content);
|
||||
|
||||
return moduleCounter > 1;
|
||||
}
|
||||
|
||||
bool ffPrintFromCache(FFinstance* instance, const char* moduleName, const FFstrbuf* customKeyFormat, const FFstrbuf* formatString, uint32_t numArgs)
|
||||
{
|
||||
if(instance->config.recache)
|
||||
return false;
|
||||
|
||||
if(formatString == NULL || formatString->length == 0)
|
||||
return printCachedValue(instance, moduleName, customKeyFormat);
|
||||
else
|
||||
return printCachedFormat(instance, moduleName, customKeyFormat, formatString, numArgs);
|
||||
}
|
||||
|
||||
void ffPrintAndAppendToCache(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat, FFcache* cache, const FFstrbuf* value, const FFstrbuf* formatString, uint32_t numArgs, const FFformatarg* arguments)
|
||||
{
|
||||
if(formatString == NULL || formatString->length == 0)
|
||||
{
|
||||
ffPrintLogoAndKey(instance, moduleName, moduleIndex, customKeyFormat);
|
||||
ffStrbufPutTo(value, stdout);
|
||||
}
|
||||
else
|
||||
{
|
||||
ffPrintFormatString(instance, moduleName, moduleIndex, customKeyFormat, formatString, NULL, numArgs, arguments);
|
||||
}
|
||||
|
||||
if(cache->value != NULL)
|
||||
{
|
||||
ffStrbufWriteTo(value, cache->value);
|
||||
fputc('\0', cache->value);
|
||||
}
|
||||
|
||||
if(cache->split == NULL)
|
||||
return;
|
||||
|
||||
for(uint32_t i = 0; i < numArgs; i++)
|
||||
{
|
||||
FFstrbuf buffer;
|
||||
ffStrbufInitA(&buffer, 64);
|
||||
ffFormatAppendFormatArg(&buffer, &arguments[i]);
|
||||
ffStrbufWriteTo(&buffer, cache->split);
|
||||
ffStrbufDestroy(&buffer);
|
||||
fputc('\0', cache->split);
|
||||
}
|
||||
}
|
||||
|
||||
void ffPrintAndWriteToCache(FFinstance* instance, const char* moduleName, const FFstrbuf* customKeyFormat, const FFstrbuf* value, const FFstrbuf* formatString, uint32_t numArgs, const FFformatarg* arguments)
|
||||
{
|
||||
FFcache cache;
|
||||
ffCacheOpenWrite(instance, moduleName, &cache);
|
||||
ffPrintAndAppendToCache(instance, moduleName, 0, customKeyFormat, &cache, value, formatString, numArgs, arguments);
|
||||
ffCacheClose(&cache);
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/font.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@@ -188,10 +189,35 @@ void ffFontInitPango(FFfont* font, const char* data)
|
||||
fontInitPretty(font);
|
||||
}
|
||||
|
||||
void ffFontInitCopy(FFfont* font, const char* name)
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -1,21 +1,30 @@
|
||||
#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, "%u", *(uint32_t*)formatarg->value);
|
||||
ffStrbufAppendF(buffer, "%" PRIu32, *(uint32_t*)formatarg->value);
|
||||
else if(formatarg->type == FF_FORMAT_ARG_TYPE_UINT16)
|
||||
ffStrbufAppendF(buffer, "%hu", *(uint16_t*)formatarg->value);
|
||||
ffStrbufAppendF(buffer, "%" PRIu16, *(uint16_t*)formatarg->value);
|
||||
else if(formatarg->type == FF_FORMAT_ARG_TYPE_UINT8)
|
||||
ffStrbufAppendF(buffer, "%hhu", *(uint8_t*)formatarg->value);
|
||||
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_FLOAT)
|
||||
ffStrbufAppendF(buffer, "%f", *(float*)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;
|
||||
@@ -32,15 +41,14 @@ void ffFormatAppendFormatArg(FFstrbuf* buffer, const FFformatarg* formatarg)
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool placeholderValueIsForError(const FFstrbuf* placeholderValue)
|
||||
{
|
||||
return
|
||||
ffStrbufIgnCaseCompS(placeholderValue, "e") == 0 ||
|
||||
ffStrbufIgnCaseCompS(placeholderValue, "error") == 0 ||
|
||||
ffStrbufIgnCaseCompS(placeholderValue, "0") == 0
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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;
|
||||
@@ -48,7 +56,7 @@ static inline uint32_t getArgumentIndex(const FFstrbuf* placeholderValue)
|
||||
if(placeholderValue->chars[0] != '-')
|
||||
sscanf(placeholderValue->chars, "%u", &result);
|
||||
|
||||
return 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)
|
||||
@@ -62,26 +70,29 @@ static inline void appendInvalidPlaceholder(FFstrbuf* buffer, const char* start,
|
||||
|
||||
static inline void appendEmptyPlaceholder(FFstrbuf* buffer, const char* placeholder, uint32_t* argCounter, uint32_t numArgs, const FFformatarg* arguments)
|
||||
{
|
||||
if(*argCounter > numArgs)
|
||||
if(*argCounter >= numArgs)
|
||||
ffStrbufAppendS(buffer, placeholder);
|
||||
else
|
||||
ffFormatAppendFormatArg(buffer, &arguments[(*argCounter)++]);
|
||||
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) ||
|
||||
(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 && *(const char*)arg->value != '\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_UINT && *(uint32_t*)arg->value > 0) ||
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_BOOL && arg->value != NULL)
|
||||
);
|
||||
}
|
||||
|
||||
void ffParseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, const FFstrbuf* error, uint32_t numArgs, const FFformatarg* arguments)
|
||||
void ffParseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, uint32_t numArgs, const FFformatarg* arguments)
|
||||
{
|
||||
uint32_t argCounter = 0;
|
||||
|
||||
@@ -128,13 +139,6 @@ void ffParseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, const FFst
|
||||
while(i < formatstr->length && formatstr->chars[i] != '}')
|
||||
ffStrbufAppendC(&placeholderValue, formatstr->chars[i++]);
|
||||
|
||||
// test for error, if so print it
|
||||
if(placeholderValueIsForError(&placeholderValue)) {
|
||||
ffStrbufAppend(buffer, error);
|
||||
ffStrbufDestroy(&placeholderValue);
|
||||
continue;
|
||||
}
|
||||
|
||||
// test if for stop, if so break the loop
|
||||
if(placeholderValue.length == 1 && placeholderValue.chars[0] == '-')
|
||||
{
|
||||
@@ -186,14 +190,6 @@ void ffParseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, const FFst
|
||||
{
|
||||
ffStrbufSubstrAfter(&placeholderValue, 0);
|
||||
|
||||
// continue if an error is set
|
||||
if(placeholderValueIsForError(&placeholderValue) && error != NULL && error->length > 0)
|
||||
{
|
||||
++numOpenIfs;
|
||||
ffStrbufDestroy(&placeholderValue);
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t index = getArgumentIndex(&placeholderValue);
|
||||
|
||||
// testing for an invalid index
|
||||
@@ -223,14 +219,6 @@ void ffParseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, const FFst
|
||||
{
|
||||
ffStrbufSubstrAfter(&placeholderValue, 0);
|
||||
|
||||
//continue if an error os not set
|
||||
if(placeholderValueIsForError(&placeholderValue) && (error == NULL || error->length == 0))
|
||||
{
|
||||
++numOpenNotIfs;
|
||||
ffStrbufDestroy(&placeholderValue);
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t index = getArgumentIndex(&placeholderValue);
|
||||
|
||||
// testing for an invalid index
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
#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_FLOAT,
|
||||
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
|
||||
@@ -1,191 +1,120 @@
|
||||
#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>
|
||||
#include <signal.h>
|
||||
|
||||
static bool strbufEqualsAdapter(const void* first, const void* second)
|
||||
{
|
||||
return ffStrbufComp(second, first) == 0;
|
||||
}
|
||||
|
||||
static void initConfigDirs(FFstate* state)
|
||||
{
|
||||
ffListInit(&state->configDirs, sizeof(FFstrbuf));
|
||||
|
||||
const char* xdgConfigHome = getenv("XDG_CONFIG_HOME");
|
||||
if(xdgConfigHome != NULL)
|
||||
{
|
||||
FFstrbuf* buffer = (FFstrbuf*) ffListAdd(&state->configDirs);
|
||||
ffStrbufInitA(buffer, 64);
|
||||
ffStrbufAppendS(buffer, xdgConfigHome);
|
||||
ffStrbufTrimRight(buffer, '/');
|
||||
}
|
||||
|
||||
FFstrbuf xdgConfigDirs;
|
||||
ffStrbufInitA(&xdgConfigDirs, 64);
|
||||
ffStrbufAppendS(&xdgConfigDirs, getenv("XDG_CONFIG_DIRS"));
|
||||
|
||||
#define FF_ENSURE_ONLY_ONCE_IN_LIST(element) \
|
||||
if(ffListFirstIndexComp(&state->configDirs, element, strbufEqualsAdapter) < 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);
|
||||
FF_ENSURE_ONLY_ONCE_IN_LIST(userHome)
|
||||
|
||||
uint32_t startIndex = 0;
|
||||
while (startIndex < xdgConfigDirs.length)
|
||||
{
|
||||
uint32_t colonIndex = ffStrbufNextIndexC(&xdgConfigDirs, startIndex, ':');
|
||||
xdgConfigDirs.chars[colonIndex] = '\0';
|
||||
|
||||
FFstrbuf* buffer = (FFstrbuf*) ffListAdd(&state->configDirs);
|
||||
ffStrbufInitA(buffer, 64);
|
||||
ffStrbufAppendS(buffer, xdgConfigDirs.chars + startIndex);
|
||||
ffStrbufTrimRight(buffer, '/');
|
||||
FF_ENSURE_ONLY_ONCE_IN_LIST(buffer);
|
||||
|
||||
startIndex = colonIndex + 1;
|
||||
}
|
||||
|
||||
FFstrbuf* systemConfigHome = ffListAdd(&state->configDirs);
|
||||
ffStrbufInitA(systemConfigHome, 64);
|
||||
ffStrbufAppendS(systemConfigHome, FASTFETCH_TARGET_DIR_ROOT"/etc/xdg");
|
||||
FF_ENSURE_ONLY_ONCE_IN_LIST(systemConfigHome)
|
||||
|
||||
FFstrbuf* systemConfig = ffListAdd(&state->configDirs);
|
||||
ffStrbufInitA(systemConfig, 64);
|
||||
ffStrbufAppendS(systemConfig, FASTFETCH_TARGET_DIR_ROOT"/etc");
|
||||
FF_ENSURE_ONLY_ONCE_IN_LIST(systemConfig)
|
||||
|
||||
#undef FF_ENSURE_ONLY_ONCE_IN_LIST
|
||||
}
|
||||
|
||||
static void initCacheDir(FFstate* state)
|
||||
{
|
||||
ffStrbufInitA(&state->cacheDir, 64);
|
||||
|
||||
ffStrbufAppendS(&state->cacheDir, getenv("XDG_CACHE_HOME"));
|
||||
|
||||
if(state->cacheDir.length == 0)
|
||||
{
|
||||
ffStrbufAppendS(&state->cacheDir, state->passwd->pw_dir);
|
||||
ffStrbufAppendS(&state->cacheDir, "/.cache/");
|
||||
}
|
||||
else if(!ffStrbufEndsWithC(&state->cacheDir, '/'))
|
||||
ffStrbufAppendC(&state->cacheDir, '/');
|
||||
|
||||
mkdir(state->cacheDir.chars, S_IRWXU | S_IXGRP | S_IRGRP | S_IXOTH | S_IROTH); //I hope everybody has a cache folder, but who knows
|
||||
|
||||
ffStrbufAppendS(&state->cacheDir, "fastfetch/");
|
||||
mkdir(state->cacheDir.chars, S_IRWXU | S_IRGRP | S_IROTH);
|
||||
}
|
||||
#ifdef _WIN32
|
||||
#include <wincon.h>
|
||||
#include <locale.h>
|
||||
#include <shlobj.h>
|
||||
#include "util/windows/unicode.h"
|
||||
#else
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
static void initState(FFstate* state)
|
||||
{
|
||||
state->logoWidth = 0;
|
||||
state->logoHeight = 0;
|
||||
state->keysHeight = 0;
|
||||
state->passwd = getpwuid(getuid());
|
||||
uname(&state->utsname);
|
||||
sysinfo(&state->sysinfo);
|
||||
|
||||
initConfigDirs(state);
|
||||
initCacheDir(state);
|
||||
ffPlatformInit(&state->platform);
|
||||
}
|
||||
|
||||
static void initModuleArg(FFModuleArgs* args)
|
||||
{
|
||||
ffStrbufInit(&args->key);
|
||||
ffStrbufInit(&args->outputFormat);
|
||||
ffStrbufInit(&args->errorFormat);
|
||||
}
|
||||
|
||||
static void defaultConfig(FFinstance* instance)
|
||||
{
|
||||
ffStrbufInit(&instance->config.logoSource);
|
||||
instance->config.logoType = FF_LOGO_TYPE_AUTO;
|
||||
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.logoColors[i]);
|
||||
instance->config.logoWidth = 65;
|
||||
instance->config.logoPaddingLeft = 0;
|
||||
instance->config.logoPaddingRight = 4;
|
||||
instance->config.logoPrintRemaining = true;
|
||||
ffStrbufInit(&instance->config.logo.colors[i]);
|
||||
instance->config.logo.width = 0;
|
||||
instance->config.logo.height = 0; //preserve aspect ratio
|
||||
instance->config.logo.paddingTop = 0;
|
||||
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.mainColor);
|
||||
ffStrbufInit(&instance->config.separator);
|
||||
ffStrbufAppendS(&instance->config.separator, ": ");
|
||||
|
||||
instance->config.showErrors = false;
|
||||
instance->config.recache = false;
|
||||
instance->config.cacheSave = true;
|
||||
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;
|
||||
|
||||
ffStrbufInitA(&instance->config.osFormat, 0);
|
||||
ffStrbufInitA(&instance->config.osKey, 0);
|
||||
ffStrbufInitA(&instance->config.hostFormat, 0);
|
||||
ffStrbufInitA(&instance->config.hostKey, 0);
|
||||
ffStrbufInitA(&instance->config.kernelFormat, 0);
|
||||
ffStrbufInitA(&instance->config.kernelKey, 0);
|
||||
ffStrbufInitA(&instance->config.uptimeFormat, 0);
|
||||
ffStrbufInitA(&instance->config.uptimeKey, 0);
|
||||
ffStrbufInitA(&instance->config.processesFormat, 0);
|
||||
ffStrbufInitA(&instance->config.processesKey, 0);
|
||||
ffStrbufInitA(&instance->config.packagesFormat, 0);
|
||||
ffStrbufInitA(&instance->config.packagesKey, 0);
|
||||
ffStrbufInitA(&instance->config.shellFormat, 0);
|
||||
ffStrbufInitA(&instance->config.shellKey, 0);
|
||||
ffStrbufInitA(&instance->config.resolutionFormat, 0);
|
||||
ffStrbufInitA(&instance->config.resolutionKey, 0);
|
||||
ffStrbufInitA(&instance->config.deFormat, 0);
|
||||
ffStrbufInitA(&instance->config.deKey, 0);
|
||||
ffStrbufInitA(&instance->config.wmFormat, 0);
|
||||
ffStrbufInitA(&instance->config.wmKey, 0);
|
||||
ffStrbufInitA(&instance->config.wmThemeFormat, 0);
|
||||
ffStrbufInitA(&instance->config.wmThemeKey, 0);
|
||||
ffStrbufInitA(&instance->config.themeFormat, 0);
|
||||
ffStrbufInitA(&instance->config.themeKey, 0);
|
||||
ffStrbufInitA(&instance->config.iconsFormat, 0);
|
||||
ffStrbufInitA(&instance->config.iconsKey, 0);
|
||||
ffStrbufInitA(&instance->config.fontFormat, 0);
|
||||
ffStrbufInitA(&instance->config.fontKey, 0);
|
||||
ffStrbufInitA(&instance->config.cursorKey, 0);
|
||||
ffStrbufInitA(&instance->config.cursorFormat, 0);
|
||||
ffStrbufInitA(&instance->config.terminalFormat, 0);
|
||||
ffStrbufInitA(&instance->config.terminalKey, 0);
|
||||
ffStrbufInitA(&instance->config.termFontFormat, 0);
|
||||
ffStrbufInitA(&instance->config.termFontKey, 0);
|
||||
ffStrbufInitA(&instance->config.cpuFormat, 0);
|
||||
ffStrbufInitA(&instance->config.cpuKey, 0);
|
||||
ffStrbufInitA(&instance->config.cpuUsageFormat, 0);
|
||||
ffStrbufInitA(&instance->config.cpuUsageKey, 0);
|
||||
ffStrbufInitA(&instance->config.gpuFormat, 0);
|
||||
ffStrbufInitA(&instance->config.gpuKey, 0);
|
||||
ffStrbufInitA(&instance->config.memoryFormat, 0);
|
||||
ffStrbufInitA(&instance->config.memoryKey, 0);
|
||||
ffStrbufInitA(&instance->config.diskFormat, 0);
|
||||
ffStrbufInitA(&instance->config.diskKey, 0);
|
||||
ffStrbufInitA(&instance->config.batteryFormat, 0);
|
||||
ffStrbufInitA(&instance->config.batteryKey, 0);
|
||||
ffStrbufInitA(&instance->config.localeFormat, 0);
|
||||
ffStrbufInitA(&instance->config.localeKey, 0);
|
||||
ffStrbufInitA(&instance->config.localIpKey, 0);
|
||||
ffStrbufInitA(&instance->config.localIpFormat, 0);
|
||||
ffStrbufInitA(&instance->config.publicIpKey, 0);
|
||||
ffStrbufInitA(&instance->config.publicIpFormat, 0);
|
||||
ffStrbufInitA(&instance->config.playerKey, 0);
|
||||
ffStrbufInitA(&instance->config.playerFormat, 0);
|
||||
ffStrbufInitA(&instance->config.songKey, 0);
|
||||
ffStrbufInitA(&instance->config.songFormat, 0);
|
||||
ffStrbufInitA(&instance->config.dateTimeKey, 0);
|
||||
ffStrbufInitA(&instance->config.dateTimeFormat, 0);
|
||||
ffStrbufInitA(&instance->config.dateKey, 0);
|
||||
ffStrbufInitA(&instance->config.dateFormat, 0);
|
||||
ffStrbufInitA(&instance->config.timeKey, 0);
|
||||
ffStrbufInitA(&instance->config.timeFormat, 0);
|
||||
initModuleArg(&instance->config.os);
|
||||
initModuleArg(&instance->config.host);
|
||||
initModuleArg(&instance->config.bios);
|
||||
initModuleArg(&instance->config.board);
|
||||
initModuleArg(&instance->config.brightness);
|
||||
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.display);
|
||||
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);
|
||||
@@ -198,11 +127,37 @@ static void defaultConfig(FFinstance* instance)
|
||||
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);
|
||||
ffStrbufInit(&instance->config.libnm);
|
||||
|
||||
instance->config.cpuTemp = false;
|
||||
instance->config.gpuTemp = false;
|
||||
instance->config.batteryTemp = false;
|
||||
|
||||
instance->config.gpuHideIntegrated = false;
|
||||
instance->config.gpuHideDiscrete = false;
|
||||
|
||||
instance->config.shellVersion = true;
|
||||
instance->config.terminalVersion = true;
|
||||
|
||||
instance->config.titleFQDN = false;
|
||||
|
||||
ffStrbufInitA(&instance->config.diskFolders, 0);
|
||||
instance->config.diskShowRemovable = true;
|
||||
instance->config.diskShowHidden = false;
|
||||
instance->config.diskShowUnknown = false;
|
||||
instance->config.diskShowSubvolumes = false;
|
||||
|
||||
ffStrbufInitA(&instance->config.batteryDir, 0);
|
||||
|
||||
@@ -211,70 +166,270 @@ static void defaultConfig(FFinstance* instance)
|
||||
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;
|
||||
|
||||
ffStrbufInitS(&instance->config.commandShell,
|
||||
#ifdef _WIN32
|
||||
"cmd"
|
||||
#elif defined(__FreeBSD__)
|
||||
"csh"
|
||||
#else
|
||||
"bash"
|
||||
#endif
|
||||
);
|
||||
ffListInit(&instance->config.commandKeys, sizeof(FFstrbuf));
|
||||
ffListInit(&instance->config.commandTexts, sizeof(FFstrbuf));
|
||||
}
|
||||
|
||||
void ffInitInstance(FFinstance* instance)
|
||||
{
|
||||
#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
|
||||
|
||||
initState(&instance->state);
|
||||
defaultConfig(instance);
|
||||
}
|
||||
|
||||
static void resetConsole(bool disableLinewrap, bool hideCursor)
|
||||
{
|
||||
if(disableLinewrap)
|
||||
fputs("\033[?7h", stdout);
|
||||
#ifdef FF_HAVE_THREADS
|
||||
|
||||
if(hideCursor)
|
||||
fputs("\033[?25h", stdout);
|
||||
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);
|
||||
|
||||
#if defined(_WIN32) && defined(FF_ENABLE_BUFFER)
|
||||
fflush(stdout);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
BOOL WINAPI consoleHandler(DWORD signal)
|
||||
{
|
||||
FF_UNUSED(signal);
|
||||
resetConsole();
|
||||
exit(0);
|
||||
}
|
||||
#else
|
||||
static void exitSignalHandler(int signal)
|
||||
{
|
||||
FF_UNUSED(signal);
|
||||
resetConsole(ffDisableLinewrap, ffHideCursor);
|
||||
resetConsole();
|
||||
exit(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
void ffStart(FFinstance* instance)
|
||||
{
|
||||
ffDisableLinewrap = instance->config.disableLinewrap;
|
||||
ffHideCursor = instance->config.hideCursor;
|
||||
if(instance->config.multithreading)
|
||||
startDetectionThreads(instance);
|
||||
|
||||
struct sigaction action = {};
|
||||
action.sa_handler = exitSignalHandler;
|
||||
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);
|
||||
|
||||
//We do the cache validation here, so we can skip it if --recache is given
|
||||
ffCacheValidate(instance);
|
||||
#endif
|
||||
|
||||
//reset everything to default before we start printing
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
|
||||
if(!instance->config.pipe)
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
|
||||
|
||||
if(instance->config.hideCursor)
|
||||
if(ffHideCursor)
|
||||
fputs("\033[?25l", stdout);
|
||||
|
||||
if(instance->config.disableLinewrap)
|
||||
if(ffDisableLinewrap)
|
||||
fputs("\033[?7l", stdout);
|
||||
|
||||
ffPrintLogo(instance);
|
||||
ffLogoPrint(instance);
|
||||
}
|
||||
|
||||
void ffFinish(FFinstance* instance)
|
||||
{
|
||||
ffPrintRemainingLogo(instance);
|
||||
resetConsole(instance->config.disableLinewrap, instance->config.hideCursor);
|
||||
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.display);
|
||||
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.libnm);
|
||||
|
||||
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);
|
||||
|
||||
ffStrbufDestroy(&instance->config.commandShell);
|
||||
FF_LIST_FOR_EACH(FFstrbuf, item, instance->config.commandKeys)
|
||||
ffStrbufDestroy(item);
|
||||
ffListDestroy(&instance->config.commandKeys);
|
||||
FF_LIST_FOR_EACH(FFstrbuf, item, instance->config.commandTexts)
|
||||
ffStrbufDestroy(item);
|
||||
ffListDestroy(&instance->config.commandTexts);
|
||||
}
|
||||
|
||||
static void destroyState(FFinstance* instance)
|
||||
{
|
||||
ffPlatformDestroy(&instance->state.platform);
|
||||
}
|
||||
|
||||
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
|
||||
@@ -317,14 +472,41 @@ void ffListFeatures()
|
||||
#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
|
||||
"librpm\n"
|
||||
"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\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_LIBNM
|
||||
"libnm\n"
|
||||
#endif
|
||||
""
|
||||
, stdout);
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/io.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <malloc.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <termios.h>
|
||||
|
||||
bool ffWriteFDContent(int fd, const FFstrbuf* content)
|
||||
{
|
||||
return write(fd, content->chars, content->length) != -1;
|
||||
}
|
||||
#ifdef _WIN32
|
||||
#include <fileapi.h>
|
||||
#else
|
||||
#include <termios.h>
|
||||
#include <poll.h>
|
||||
#endif
|
||||
|
||||
static void createSubfolders(const char* fileName)
|
||||
{
|
||||
@@ -21,15 +20,41 @@ static void createSubfolders(const char* fileName)
|
||||
{
|
||||
ffStrbufAppendC(&path, *fileName);
|
||||
if(*fileName == '/')
|
||||
mkdir(path.chars, S_IRWXU | S_IRGRP | S_IROTH);
|
||||
{
|
||||
mkdir(path.chars
|
||||
#ifndef WIN32
|
||||
, S_IRWXU | S_IRGRP | S_IROTH
|
||||
#endif
|
||||
);
|
||||
}
|
||||
++fileName;
|
||||
}
|
||||
|
||||
ffStrbufDestroy(&path);
|
||||
}
|
||||
|
||||
bool ffWriteFileContent(const char* fileName, const FFstrbuf* content)
|
||||
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;
|
||||
|
||||
@@ -42,18 +67,64 @@ bool ffWriteFileContent(const char* fileName, const FFstrbuf* content)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ret = ffWriteFDContent(fd, content);
|
||||
bool ret = write(fd, data, dataSize) != -1;
|
||||
|
||||
close(fd);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ffAppendFDContent(int fd, FFstrbuf* buffer)
|
||||
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;
|
||||
|
||||
ffStrbufEnsureFree(buffer, 31); // 32 - 1 for the null terminator
|
||||
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(
|
||||
@@ -61,7 +132,7 @@ void ffAppendFDContent(int fd, FFstrbuf* buffer)
|
||||
(uint32_t) readed == free
|
||||
) {
|
||||
buffer->length += (uint32_t) readed;
|
||||
ffStrbufEnsureCapacity(buffer, (buffer->allocated * 2) - 1); // -1 for null terminator
|
||||
ffStrbufEnsureFree(buffer, buffer->allocated - 1); // Doubles capacity every round. -1 for the null byte.
|
||||
free = ffStrbufGetFree(buffer);
|
||||
}
|
||||
|
||||
@@ -73,24 +144,62 @@ void ffAppendFDContent(int fd, FFstrbuf* buffer)
|
||||
|
||||
ffStrbufTrimRight(buffer, '\n');
|
||||
ffStrbufTrimRight(buffer, ' ');
|
||||
|
||||
return readed >= 0;
|
||||
}
|
||||
|
||||
bool ffAppendFileContent(const char* fileName, FFstrbuf* buffer)
|
||||
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;
|
||||
|
||||
ffAppendFDContent(fd, buffer);
|
||||
bool ret = ffAppendFDBuffer(fd, buffer);
|
||||
|
||||
close(fd);
|
||||
return true;
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ffGetFileContent(const char* fileName, FFstrbuf* buffer)
|
||||
bool ffReadFileBuffer(const char* fileName, FFstrbuf* buffer)
|
||||
{
|
||||
ffStrbufClear(buffer);
|
||||
return ffAppendFileContent(fileName, buffer);
|
||||
return ffAppendFileBuffer(fileName, buffer);
|
||||
}
|
||||
|
||||
// Not thread safe!
|
||||
@@ -128,34 +237,49 @@ bool ffFileExists(const char* fileName, mode_t mode)
|
||||
return stat(fileName, &fileStat) == 0 && ((fileStat.st_mode & S_IFMT) == mode);
|
||||
}
|
||||
|
||||
void ffGetTerminalResponse(const char* request, char end, const char* format, ...)
|
||||
void ffGetTerminalResponse(const char* request, const char* format, ...)
|
||||
{
|
||||
#ifndef WIN32
|
||||
struct termios oldTerm, newTerm;
|
||||
tcgetattr(STDIN_FILENO, &oldTerm);
|
||||
if(tcgetattr(STDIN_FILENO, &oldTerm) == -1)
|
||||
return;
|
||||
|
||||
newTerm = oldTerm;
|
||||
newTerm.c_lflag &= (tcflag_t) ~(ICANON | ECHO);
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &newTerm);
|
||||
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];
|
||||
int pos = 0;
|
||||
while((size_t) pos < sizeof(buffer) - 1)
|
||||
{
|
||||
char c = (char) getc(stdin);
|
||||
if(c == '\0')
|
||||
break;
|
||||
buffer[pos++] = c;
|
||||
if(c == end)
|
||||
break;
|
||||
}
|
||||
buffer[pos] = '\0';
|
||||
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
|
||||
@@ -1,11 +1,35 @@
|
||||
#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, RTLD_LAZY);
|
||||
if(result != NULL)
|
||||
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;
|
||||
@@ -18,7 +42,7 @@ static void* libraryLoad(const char* path, int maxVersion)
|
||||
uint32_t originalLength = pathbuf.length;
|
||||
ffStrbufAppendF(&pathbuf, "%i", i);
|
||||
|
||||
result = dlopen(pathbuf.chars, RTLD_LAZY);
|
||||
result = dlopen(pathbuf.chars, FF_DLOPEN_FLAGS);
|
||||
if(result != NULL)
|
||||
break;
|
||||
|
||||
@@ -26,13 +50,16 @@ static void* libraryLoad(const char* path, int maxVersion)
|
||||
}
|
||||
|
||||
ffStrbufDestroy(&pathbuf);
|
||||
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void* ffLibraryLoad(const FFstrbuf* userProvidedName, ...)
|
||||
{
|
||||
if(userProvidedName->length > 0)
|
||||
return dlopen(userProvidedName->chars, RTLD_LAZY);
|
||||
if(userProvidedName != NULL && userProvidedName->length > 0)
|
||||
return dlopen(userProvidedName->chars, FF_DLOPEN_FLAGS);
|
||||
|
||||
va_list defaultNames;
|
||||
va_start(defaultNames, userProvidedName);
|
||||
|
||||
@@ -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
|
||||
@@ -1,69 +0,0 @@
|
||||
#include "fastfetch.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
|
||||
void ffNetworkingGetHttp(const char* host, const char* path, uint32_t timeout, FFstrbuf* buffer)
|
||||
{
|
||||
struct addrinfo hints = {0};
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_protocol = 0;
|
||||
|
||||
struct addrinfo* addr;
|
||||
|
||||
if(getaddrinfo(host, "80", &hints, &addr) != 0)
|
||||
return;
|
||||
|
||||
int sock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
|
||||
if(sock == -1)
|
||||
{
|
||||
freeaddrinfo(addr);
|
||||
return;
|
||||
}
|
||||
|
||||
if(timeout > 0)
|
||||
{
|
||||
struct timeval timev;
|
||||
timev.tv_sec = 0;
|
||||
timev.tv_usec = timeout * 1000; //milliseconds to microseconds
|
||||
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timev, sizeof(timev));
|
||||
}
|
||||
|
||||
if(connect(sock, addr->ai_addr, addr->ai_addrlen) == -1)
|
||||
{
|
||||
close(sock);
|
||||
freeaddrinfo(addr);
|
||||
return;
|
||||
}
|
||||
|
||||
freeaddrinfo(addr);
|
||||
|
||||
FFstrbuf command;
|
||||
ffStrbufInitA(&command, 64);
|
||||
ffStrbufAppendS(&command, "GET ");
|
||||
ffStrbufAppendS(&command, path);
|
||||
ffStrbufAppendS(&command, " HTTP/1.1\nHost: ");
|
||||
ffStrbufAppendS(&command, host);
|
||||
ffStrbufAppendS(&command, "\r\n\r\n");
|
||||
|
||||
if(send(sock, command.chars, command.length, 0) == -1)
|
||||
{
|
||||
ffStrbufDestroy(&command);
|
||||
close(sock);
|
||||
return;
|
||||
}
|
||||
|
||||
ssize_t received = recv(sock, buffer->chars + buffer->length, ffStrbufGetFree(buffer), 0);
|
||||
|
||||
if(received > 0)
|
||||
{
|
||||
buffer->length += (uint32_t) received;
|
||||
buffer->chars[buffer->length] = '\0';
|
||||
}
|
||||
|
||||
ffStrbufDestroy(&command);
|
||||
close(sock);
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
@@ -1,18 +1,7 @@
|
||||
#include "fastfetch.h"
|
||||
|
||||
bool ffStrSet(const char* str)
|
||||
{
|
||||
if(str == NULL)
|
||||
return false;
|
||||
|
||||
while(*str != '\0')
|
||||
{
|
||||
if(*str != ' ' && *str != '\t' && *str != '\n' && *str != '\r')
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#include "common/parsing.h"
|
||||
#include <ctype.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
void ffParseSemver(FFstrbuf* buffer, const FFstrbuf* major, const FFstrbuf* minor, const FFstrbuf* patch)
|
||||
{
|
||||
@@ -39,6 +28,63 @@ void ffParseSemver(FFstrbuf* buffer, const FFstrbuf* major, const FFstrbuf* mino
|
||||
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)
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
#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})
|
||||
|
||||
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
|
||||
@@ -1,55 +1,128 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/printing.h"
|
||||
#include "util/textModifier.h"
|
||||
|
||||
void ffPrintError(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat, const FFstrbuf* formatString, uint32_t numFormatArgs, const char* message, ...)
|
||||
void ffPrintLogoAndKey(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat)
|
||||
{
|
||||
if(!instance->config.showErrors)
|
||||
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;
|
||||
|
||||
va_list arguments;
|
||||
va_start(arguments, message);
|
||||
|
||||
if(formatString == NULL || formatString->length == 0)
|
||||
if(!instance->config.pipe)
|
||||
{
|
||||
ffPrintLogoAndKey(instance, moduleName, moduleIndex, customKeyFormat);
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_ERROR, stdout);
|
||||
vprintf(message, arguments);
|
||||
puts(FASTFETCH_TEXT_MODIFIER_RESET);
|
||||
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
|
||||
{
|
||||
FF_STRBUF_CREATE(error);
|
||||
ffStrbufAppendVF(&error, message, arguments);
|
||||
|
||||
// calloc sets all to 0 and FF_FORMAT_ARG_TYPE_NULL also has value 0 so we don't need to explictly set it
|
||||
FFformatarg* nullArgs = calloc(numFormatArgs, sizeof(FFformatarg));
|
||||
|
||||
ffPrintFormatString(instance, moduleName, moduleIndex, customKeyFormat, formatString, &error, numFormatArgs, nullArgs);
|
||||
|
||||
free(nullArgs);
|
||||
ffStrbufDestroy(&error);
|
||||
FFstrbuf key;
|
||||
ffStrbufInit(&key);
|
||||
ffParseFormatString(&key, customKeyFormat, 1, (FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_UINT8, &moduleIndex}
|
||||
});
|
||||
ffPrintUserString(key.chars);
|
||||
ffStrbufDestroy(&key);
|
||||
}
|
||||
|
||||
va_end(arguments);
|
||||
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* formatString, const FFstrbuf* error, uint32_t numArgs, const FFformatarg* arguments)
|
||||
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, formatString, error, numArgs, arguments);
|
||||
ffParseFormatString(&buffer, format, numArgs, arguments);
|
||||
|
||||
if(buffer.length > 0)
|
||||
{
|
||||
ffPrintLogoAndKey(instance, moduleName, moduleIndex, customKeyFormat);
|
||||
ffStrbufPutTo(&buffer, stdout);
|
||||
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);
|
||||
@@ -57,6 +130,45 @@ void ffPrintColor(const FFstrbuf* colorValue)
|
||||
|
||||
void ffPrintCharTimes(char c, uint32_t times)
|
||||
{
|
||||
for(uint32_t i = 0; i < times; i++)
|
||||
putchar(c);
|
||||
if(times == 0)
|
||||
return;
|
||||
|
||||
char str[32];
|
||||
memset(str, c, sizeof(str)); //2 instructions when compiling with AVX2 enabled
|
||||
for(uint32_t i = sizeof(str); i <= times; i += (uint32_t)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
|
||||
@@ -1,19 +1,21 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/processing.h"
|
||||
#include "common/io.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
void ffProcessAppendStdOut(FFstrbuf* buffer, char* const argv[])
|
||||
const char* ffProcessAppendStdOut(FFstrbuf* buffer, char* const argv[])
|
||||
{
|
||||
int pipes[2];
|
||||
|
||||
if(pipe(pipes) == -1)
|
||||
return;
|
||||
return "pipe() failed";
|
||||
|
||||
pid_t childPid = fork();
|
||||
if(childPid == -1)
|
||||
return;
|
||||
return "fork() failed";
|
||||
|
||||
//Child
|
||||
if(childPid == 0)
|
||||
@@ -29,6 +31,8 @@ void ffProcessAppendStdOut(FFstrbuf* buffer, char* const argv[])
|
||||
//Parent
|
||||
close(pipes[1]);
|
||||
waitpid(childPid, NULL, 0);
|
||||
ffAppendFDContent(pipes[0], buffer);
|
||||
bool ok = ffAppendFDBuffer(pipes[0], buffer);
|
||||
close(pipes[0]);
|
||||
|
||||
return ok ? NULL : "ffAppendFDBuffer() failed";
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/processing.h"
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#include <Windows.h>
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -1,4 +1,10 @@
|
||||
#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)
|
||||
{
|
||||
@@ -86,27 +92,30 @@ bool ffParsePropLines(const char* lines, const char* start, FFstrbuf* buffer)
|
||||
// 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
|
||||
// The *Values methods always return true, if all properties were already found before, without testing if the file exists
|
||||
|
||||
bool ffParsePropFileValues(const char* filename, uint32_t numQueries, FFpropquery* queries)
|
||||
{
|
||||
bool* searchedValues = malloc(sizeof(bool) * numQueries);
|
||||
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((searchedValues[i] = queries[i].buffer->length == 0))
|
||||
if((unsetValues[i] = queries[i].buffer->length == 0))
|
||||
allSet = false;
|
||||
}
|
||||
|
||||
if(allSet)
|
||||
{
|
||||
free(searchedValues);
|
||||
return true;
|
||||
}
|
||||
|
||||
FILE* file = fopen(filename, "r");
|
||||
if(file == NULL)
|
||||
return false;
|
||||
goto done;
|
||||
|
||||
char* line = NULL;
|
||||
size_t len = 0;
|
||||
@@ -115,7 +124,7 @@ bool ffParsePropFileValues(const char* filename, uint32_t numQueries, FFpropquer
|
||||
{
|
||||
for(uint32_t i = 0; i < numQueries; i++)
|
||||
{
|
||||
if(!searchedValues[i])
|
||||
if(!unsetValues[i])
|
||||
continue;
|
||||
|
||||
uint32_t currentLength = queries[i].buffer->length;
|
||||
@@ -125,26 +134,21 @@ bool ffParsePropFileValues(const char* filename, uint32_t numQueries, FFpropquer
|
||||
}
|
||||
}
|
||||
|
||||
free(searchedValues);
|
||||
|
||||
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);
|
||||
ffStrbufAppend(&absolutePath, &instance->state.platform.homeDir);
|
||||
ffStrbufAppendC(&absolutePath, '/');
|
||||
ffStrbufAppendS(&absolutePath, relativeFile);
|
||||
|
||||
@@ -155,30 +159,22 @@ bool ffParsePropFileHomeValues(const FFinstance* instance, const char* relativeF
|
||||
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 ffParsePropFileListValues(const FFlist* list, const char* relativeFile, uint32_t numQueries, FFpropquery* queries)
|
||||
{
|
||||
bool foundAFile = false;
|
||||
|
||||
for(uint32_t i = 0; i < instance->state.configDirs.length; i++)
|
||||
FFstrbuf baseDir;
|
||||
ffStrbufInitA(&baseDir, 64);
|
||||
|
||||
for(uint32_t i = 0; i < list->length; i++)
|
||||
{
|
||||
FFstrbuf* baseDir = (FFstrbuf*) ffListGet(&instance->state.configDirs, i);
|
||||
uint32_t baseDirLength = baseDir->length;
|
||||
//We need to copy the dir each time, because it used by multiple threads, so we can't directly write to it.
|
||||
ffStrbufSet(&baseDir, ffListGet(list, i));
|
||||
ffStrbufAppendS(&baseDir, relativeFile);
|
||||
|
||||
if(*relativeFile != '/')
|
||||
ffStrbufAppendC(baseDir, '/');
|
||||
|
||||
ffStrbufAppendS(baseDir, relativeFile);
|
||||
|
||||
if(ffParsePropFileValues(baseDir->chars, numQueries, queries))
|
||||
if(ffParsePropFileValues(baseDir.chars, numQueries, queries))
|
||||
foundAFile = true;
|
||||
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
|
||||
bool allSet = true;
|
||||
for(uint32_t k = 0; k < numQueries; k++)
|
||||
{
|
||||
@@ -193,10 +189,7 @@ bool ffParsePropFileConfigValues(const FFinstance* instance, const char* relativ
|
||||
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,55 @@
|
||||
#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 ffParsePropFileHomeValues(const FFinstance* instance, const char* relativeFile, uint32_t numQueries, FFpropquery* queries);
|
||||
bool ffParsePropFileListValues(const FFlist* list, const char* relativeFile, uint32_t numQueries, FFpropquery* queries);
|
||||
|
||||
static inline bool ffParsePropFile(const char* filename, const char* start, FFstrbuf* buffer)
|
||||
{
|
||||
return ffParsePropFileValues(filename, 1, (FFpropquery[]){{start, buffer}});
|
||||
}
|
||||
|
||||
static inline bool ffParsePropFileHome(const FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer)
|
||||
{
|
||||
return ffParsePropFileHomeValues(instance, relativeFile, 1, (FFpropquery[]){{start, buffer}});
|
||||
}
|
||||
|
||||
static inline bool ffParsePropFileList(const FFlist* list, const char* relativeFile, const char* start, FFstrbuf* buffer)
|
||||
{
|
||||
return ffParsePropFileListValues(list, relativeFile, 1, (FFpropquery[]){{start, buffer}});
|
||||
}
|
||||
|
||||
static inline bool ffParsePropFileConfigValues(const FFinstance* instance, const char* relativeFile, uint32_t numQueries, FFpropquery* queries)
|
||||
{
|
||||
return ffParsePropFileListValues(&instance->state.platform.configDirs, relativeFile, numQueries, queries);
|
||||
}
|
||||
|
||||
static inline bool ffParsePropFileConfig(const FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer)
|
||||
{
|
||||
return ffParsePropFileConfigValues(instance, relativeFile, 1, (FFpropquery[]){{start, buffer}});
|
||||
}
|
||||
|
||||
static inline bool ffParsePropFileDataValues(const FFinstance* instance, const char* relativeFile, uint32_t numQueries, FFpropquery* queries)
|
||||
{
|
||||
return ffParsePropFileListValues(&instance->state.platform.dataDirs, relativeFile, numQueries, queries);
|
||||
}
|
||||
|
||||
static inline bool ffParsePropFileData(const FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer)
|
||||
{
|
||||
return ffParsePropFileDataValues(instance, relativeFile, 1, (FFpropquery[]){{start, buffer}});
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,21 +1,32 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/settings.h"
|
||||
#include "common/library.h"
|
||||
#include "common/thread.h"
|
||||
#include "common/io.h"
|
||||
|
||||
#include <pthread.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 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; \
|
||||
static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER; \
|
||||
static FFInitState initState = FF_INITSTATE_UNINITIALIZED; \
|
||||
pthread_mutex_lock(&mutex); \
|
||||
ffThreadMutexLock(&mutex); \
|
||||
if(initState != FF_INITSTATE_UNINITIALIZED) {\
|
||||
pthread_mutex_unlock(&mutex); \
|
||||
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; \
|
||||
pthread_mutex_unlock(&mutex); \
|
||||
ffThreadMutexUnlock(&mutex); \
|
||||
return NULL; \
|
||||
} \
|
||||
|
||||
@@ -24,20 +35,20 @@
|
||||
if(data.ff ## symbolName == NULL) { \
|
||||
dlclose(libraryHandle); \
|
||||
initState = FF_INITSTATE_FAILED; \
|
||||
pthread_mutex_unlock(&mutex); \
|
||||
ffThreadMutexUnlock(&mutex); \
|
||||
return NULL; \
|
||||
}
|
||||
|
||||
#define FF_LIBRARY_DATA_LOAD_RETURN \
|
||||
initState = FF_INITSTATE_SUCCESSFUL; \
|
||||
pthread_mutex_unlock(&mutex); \
|
||||
ffThreadMutexUnlock(&mutex); \
|
||||
return &data;
|
||||
|
||||
#define FF_LIBRARY_DATA_LOAD_ERROR \
|
||||
{ \
|
||||
dlclose(libraryHandle); \
|
||||
initState = FF_INITSTATE_FAILED; \
|
||||
pthread_mutex_unlock(&mutex); \
|
||||
ffThreadMutexUnlock(&mutex); \
|
||||
return NULL; \
|
||||
}
|
||||
|
||||
@@ -78,9 +89,9 @@ typedef struct GSettingsData
|
||||
GVariantGetters variantGetters;
|
||||
} GSettingsData;
|
||||
|
||||
static const GSettingsData* getGSettingsData(FFinstance* instance)
|
||||
static const GSettingsData* getGSettingsData(const FFinstance* instance)
|
||||
{
|
||||
FF_LIBRARY_DATA_LOAD_INIT(GSettingsData, instance->config.libGIO, "libgio-2.0.so", 1);
|
||||
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)
|
||||
@@ -103,7 +114,7 @@ static const GSettingsData* getGSettingsData(FFinstance* instance)
|
||||
FF_LIBRARY_DATA_LOAD_RETURN
|
||||
}
|
||||
|
||||
FFvariant ffSettingsGetGSettings(FFinstance* instance, const char* schemaName, const char* path, const char* key, FFvarianttype type)
|
||||
FFvariant ffSettingsGetGSettings(const FFinstance* instance, const char* schemaName, const char* path, const char* key, FFvarianttype type)
|
||||
{
|
||||
const GSettingsData* data = getGSettingsData(instance);
|
||||
if(data == NULL)
|
||||
@@ -132,7 +143,7 @@ FFvariant ffSettingsGetGSettings(FFinstance* instance, const char* schemaName, c
|
||||
return getGVariantValue(variant, type, &data->variantGetters);
|
||||
}
|
||||
#else //FF_HAVE_GIO
|
||||
FFvariant ffSettingsGetGSettings(FFinstance* instance, const char* schemaName, const char* path, const char* key, FFvarianttype type)
|
||||
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;
|
||||
@@ -150,9 +161,9 @@ typedef struct DConfData
|
||||
DConfClient* client;
|
||||
} DConfData;
|
||||
|
||||
static const DConfData* getDConfData(FFinstance* instance)
|
||||
static const DConfData* getDConfData(const FFinstance* instance)
|
||||
{
|
||||
FF_LIBRARY_DATA_LOAD_INIT(DConfData, instance->config.libDConf, "libdconf.so", 2);
|
||||
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)
|
||||
@@ -170,7 +181,7 @@ static const DConfData* getDConfData(FFinstance* instance)
|
||||
FF_LIBRARY_DATA_LOAD_RETURN
|
||||
}
|
||||
|
||||
FFvariant ffSettingsGetDConf(FFinstance* instance, const char* key, FFvarianttype type)
|
||||
FFvariant ffSettingsGetDConf(const FFinstance* instance, const char* key, FFvarianttype type)
|
||||
{
|
||||
const DConfData* data = getDConfData(instance);
|
||||
if(data == NULL)
|
||||
@@ -188,14 +199,14 @@ FFvariant ffSettingsGetDConf(FFinstance* instance, const char* key, FFvarianttyp
|
||||
return getGVariantValue(variant, type, &data->variantGetters);
|
||||
}
|
||||
#else //FF_HAVE_DCONF
|
||||
FFvariant ffSettingsGetDConf(FFinstance* instance, const char* key, FFvarianttype type)
|
||||
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(FFinstance* instance, const char* dconfKey, const char* gsettingsSchemaName, const char* gsettingsPath, const char* gsettingsKey, FFvarianttype type)
|
||||
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);
|
||||
|
||||
@@ -220,9 +231,9 @@ typedef struct XFConfData
|
||||
FF_LIBRARY_SYMBOL(xfconf_init)
|
||||
} XFConfData;
|
||||
|
||||
static const XFConfData* getXFConfData(FFinstance* instance)
|
||||
static const XFConfData* getXFConfData(const FFinstance* instance)
|
||||
{
|
||||
FF_LIBRARY_DATA_LOAD_INIT(XFConfData, instance->config.libXFConf, "libxfconf-0.so", 4);
|
||||
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)
|
||||
@@ -237,7 +248,7 @@ static const XFConfData* getXFConfData(FFinstance* instance)
|
||||
FF_LIBRARY_DATA_LOAD_RETURN
|
||||
}
|
||||
|
||||
FFvariant ffSettingsGetXFConf(FFinstance* instance, const char* channelName, const char* propertyName, FFvarianttype type)
|
||||
FFvariant ffSettingsGetXFConf(const FFinstance* instance, const char* channelName, const char* propertyName, FFvarianttype type)
|
||||
{
|
||||
const XFConfData* data = getXFConfData(instance);
|
||||
if(data == NULL)
|
||||
@@ -260,19 +271,89 @@ FFvariant ffSettingsGetXFConf(FFinstance* instance, const char* channelName, con
|
||||
return FF_VARIANT_NULL;
|
||||
}
|
||||
#else //FF_HAVE_XFCONF
|
||||
FFvariant ffSettingsGetXFConf(FFinstance* instance, const char* channelName, const char* propertyName, FFvarianttype type)
|
||||
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>
|
||||
bool ffSettingsGetAndroidProperty(const char* propName, FFstrbuf* result) {
|
||||
uint32_t originalLength = result->length;
|
||||
void ffSettingsGetAndroidProperty(const char* propName, FFstrbuf* result) {
|
||||
ffStrbufEnsureFree(result, PROP_VALUE_MAX);
|
||||
result->length += (uint32_t) __system_property_get(propName, result->chars + result->length);
|
||||
return result->length > originalLength;
|
||||
result->chars[result->length] = '\0';
|
||||
}
|
||||
#endif
|
||||
#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
|
||||
@@ -1,72 +0,0 @@
|
||||
#include "fastfetch.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
static inline void* detectPlasmaThreadMain(void* instance)
|
||||
{
|
||||
ffDetectPlasma((FFinstance*)instance);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void* detectGTK2ThreadMain(void* instance)
|
||||
{
|
||||
ffDetectGTK2((FFinstance*)instance);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void* detectGTK3ThreadMain(void* instance)
|
||||
{
|
||||
ffDetectGTK3((FFinstance*)instance);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void* detectGTK4ThreadMain(void* instance)
|
||||
{
|
||||
ffDetectGTK4((FFinstance*)instance);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void* connectDisplayServerThreadMain(void* instance)
|
||||
{
|
||||
ffConnectDisplayServer((FFinstance*)instance);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void* startThreadsThreadMain(void* instance)
|
||||
{
|
||||
pthread_t dsThread;
|
||||
pthread_create(&dsThread, NULL, connectDisplayServerThreadMain, instance);
|
||||
pthread_detach(dsThread);
|
||||
|
||||
pthread_t gtk2Thread;
|
||||
pthread_create(>k2Thread, NULL, detectGTK2ThreadMain, instance);
|
||||
pthread_detach(gtk2Thread);
|
||||
|
||||
pthread_t gtk3Thread;
|
||||
pthread_create(>k3Thread, NULL, detectGTK3ThreadMain, instance);
|
||||
pthread_detach(gtk3Thread);
|
||||
|
||||
pthread_t gtk4Thread;
|
||||
pthread_create(>k4Thread, NULL, detectGTK4ThreadMain, instance);
|
||||
pthread_detach(gtk4Thread);
|
||||
|
||||
pthread_t plasmaThread;
|
||||
pthread_create(&plasmaThread, NULL, detectPlasmaThreadMain, instance);
|
||||
pthread_detach(plasmaThread);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ffStartDetectionThreads(FFinstance* instance)
|
||||
{
|
||||
//Android needs none of the things that are detected here
|
||||
//And using gsettings sometimes hangs the program in android for some unknown reason,
|
||||
//and since we don't need it we just never call it.
|
||||
#ifdef __ANDROID__
|
||||
return;
|
||||
#endif
|
||||
|
||||
pthread_t startThreadsThread;
|
||||
pthread_create(&startThreadsThread, NULL, startThreadsThreadMain, instance);
|
||||
pthread_detach(startThreadsThread);
|
||||
}
|
||||
@@ -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
|
||||
@@ -5,8 +5,8 @@
|
||||
# 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 > ~/.config/fastfetch/config.conf to overwrite this with the current defaults
|
||||
# This file was shipped with $" FASTFETCH_PROJECT_VERSION $".
|
||||
# Use fastfetch --gen-config-force 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".
|
||||
@@ -16,7 +16,7 @@
|
||||
# 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.
|
||||
# The config file is completely 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
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
# 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$"
|
||||
#--structure $" FASTFETCH_DATATEXT_STRUCTURE $"
|
||||
|
||||
# Multithreading option:
|
||||
# Sets if fastfetch should use multiple threads to detect the values.
|
||||
@@ -33,6 +33,13 @@
|
||||
# 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.
|
||||
@@ -61,16 +68,22 @@
|
||||
|
||||
# Logo type option:
|
||||
# Sets the logo type to use.
|
||||
# Must be auto, builtin, file, raw, sixel or kitty.
|
||||
# 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 logos (in characters) if the logo is an image.
|
||||
# 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.
|
||||
@@ -101,18 +114,43 @@
|
||||
# Default is 0.
|
||||
#--logo-padding-right 0
|
||||
|
||||
# Logo padding top option:
|
||||
# Adds a padding to the top side of the logo.
|
||||
# Must be a positive integer.
|
||||
# Default is 0.
|
||||
#--logo-padding-top 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 option:
|
||||
# Color keys option:
|
||||
# Sets the color of the keys.
|
||||
# Must be linux console color codes or the name of a color.
|
||||
# Default is the primary color of the logo.
|
||||
# Default is the key color of the logo.
|
||||
# Use "fastfetch --help color" to learn more and see examples.
|
||||
#--color magenta
|
||||
#--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.
|
||||
@@ -126,16 +164,33 @@
|
||||
# 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.
|
||||
# Note that you might need to run fastfetch with --recache once for it to take affect.
|
||||
# Default is /etc/os-release.
|
||||
#--os-file /etc/os-release
|
||||
|
||||
@@ -145,17 +200,72 @@
|
||||
# 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
|
||||
|
||||
# GPU hide options
|
||||
# Sets weather to hide certain gpu types
|
||||
# Must be either true or false
|
||||
# Default is false.
|
||||
#--gpu-hide-integrated
|
||||
#--gpu-hide-discrete
|
||||
|
||||
# Shell option
|
||||
# Sets if shell version should be detected and printed
|
||||
# Must be either true or false
|
||||
# Default is true.
|
||||
#--shell-version true
|
||||
|
||||
# Terminal option
|
||||
# Sets if terminal version should be detected and printed
|
||||
# Must be either true or false
|
||||
# Default is true.
|
||||
#--terminal-version true
|
||||
|
||||
# Disk show options
|
||||
# Sets if certain types of disk should be printed
|
||||
# Must be either true or false
|
||||
# Default is false except for --disk-show-removable.
|
||||
#--disk-show-removable true
|
||||
#--disk-show-hidden false
|
||||
#--disk-show-subvolumes false
|
||||
#--disk-show-unknown false
|
||||
|
||||
# Disk option
|
||||
# A colon (semicolon on Windows) separated list of folder paths for the disk output
|
||||
# This option override `--disk-show-*` options above
|
||||
# Must be a string
|
||||
# Default is "/:/home" ("C:\\;D:\\ ..." on Windows).
|
||||
#--disk-folders /:/home
|
||||
|
||||
# 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; 6: prints bar and hide other texts
|
||||
#--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}
|
||||
#--display-key Display {1}
|
||||
#--brightness-key Brightness ({1})
|
||||
#--de-key DE
|
||||
#--wm-key WM
|
||||
#--wm-theme-key WM Theme
|
||||
@@ -169,14 +279,22 @@
|
||||
#--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
|
||||
#--song-key Song
|
||||
#--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.
|
||||
@@ -185,12 +303,14 @@
|
||||
# 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
|
||||
#--display-format
|
||||
#--brightness-format
|
||||
#--de-format
|
||||
#--wm-format
|
||||
#--wm-theme-format
|
||||
@@ -204,20 +324,71 @@
|
||||
#--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
|
||||
#--song-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
|
||||
#--display-error
|
||||
#--brightness-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
|
||||
#--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
|
||||
@@ -227,6 +398,14 @@
|
||||
#--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
|
||||
@@ -1,112 +1,80 @@
|
||||
Usage: fastfetch <options>
|
||||
|
||||
Informative options:
|
||||
-h,--help: shows this message and exits
|
||||
-h,--help <command>: shows help for a specific command and exits
|
||||
-v,--version: prints the version of fastfetch and exits
|
||||
--list-logos: list available logos and exits
|
||||
--list-modules: lists available modules and exits
|
||||
--list-presets: list presets fastfetch knows about and exits. They can be loaded with --load-config. (+)
|
||||
--list-features: list the supported features fastfetch was compiled with and exits. Mainly for development.
|
||||
--print-logos: show available logos and exits
|
||||
--print-config: prints the default config and exits
|
||||
--print-structure: prints the default stucture and exits
|
||||
-h,--help: Show this message
|
||||
-h,--help <command>: Show help for a specific command
|
||||
-v,--version: Show the version of fastfetch
|
||||
--list-config-paths: List search paths of config files
|
||||
--list-data-paths: List search paths of presets and logos
|
||||
--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
|
||||
--gen-config: Generate a sample config file in the default path
|
||||
--gen-config-force: Generate a sample config file in the default path. Overwrite the existing one
|
||||
|
||||
General options:
|
||||
-r,--recache <?value>: generate new cached values
|
||||
--nocache <?value>: don't use cached values, but also don't overwrite existing ones
|
||||
--load-config <file>: load a config file or a preset (+)
|
||||
--multithreading <?value>: use multiple threads to detect values
|
||||
--allow-slow-operations <?value>: allow operations that are usually very slow for more detailed output
|
||||
--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 to use. The type is specified by --logo-type. 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, raw, sixel or kitty.
|
||||
--logo-width <width>: set the width of the logo (in characters), if it is an image
|
||||
--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>: weather to print the remaining logo, if it has more lines than modules to display
|
||||
--sixel <file>: short for --logo-type sixel --logo <file>
|
||||
--kitty <file>: short for --logo-type kitty --logo <file>
|
||||
--file <file>: short for --logo-type file --logo <file>
|
||||
--raw <file>: short for --logo-type raw --logo <file>
|
||||
-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-padding-top <padding>: Set the padding on the top 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>: sets the structure of the fetch. Must be a colon separated list of keys. Use "fastfetch --list-modules" to see the ones available.
|
||||
-c,--color <color>: sets the color of the keys. Must be a linux console color code or the name of a color (+)
|
||||
--separator <str>: sets the separator between key and value. Default is a colon with a space
|
||||
--set <key=value>: hard set the value of a key
|
||||
--show-errors <?value>: print occuring errors
|
||||
--disable-linewrap <?value>: weather to disable linewrap during the run
|
||||
--hide-cursor <?value>: weather to hide the cursor during the run
|
||||
-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.
|
||||
|
||||
Format options: Provide the format string for custom output. Use fastfetch --help *-format for specific help.
|
||||
--os-format <format>
|
||||
--host-format <format>
|
||||
--kernel-format <format>
|
||||
--uptime-format <format>
|
||||
--processes-format <format>
|
||||
--packages-format <format>
|
||||
--shell-format <format>
|
||||
--resolution-format <format>
|
||||
--de-format <format>
|
||||
--wm-format <format>
|
||||
--wm-theme-format <format>
|
||||
--theme-format <format>
|
||||
--icons-format <format>
|
||||
--font-format <format>
|
||||
--cursor-format <format>
|
||||
--terminal-format <format>
|
||||
--terminal-font-format <format>
|
||||
--cpu-format <format>
|
||||
--cpu-usage-format <format>
|
||||
--gpu-format <format>
|
||||
--memory-format <format>
|
||||
--disk-format <format>
|
||||
--battery-format <format>
|
||||
--locale-format <format>
|
||||
--local-ip-format <format>
|
||||
--public-ip-format <format>
|
||||
--player-format <format>
|
||||
--song-format <format>
|
||||
--datetime-format <format>
|
||||
--time-format <format>
|
||||
--date-format <format>
|
||||
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.
|
||||
|
||||
Key options: Provide a custom key for an output
|
||||
--os-key <key>
|
||||
--host-key <key>
|
||||
--kernel-key <key>
|
||||
--uptime-key <key>
|
||||
--processes-key <key>
|
||||
--packages-key <key>
|
||||
--shell-key <key>
|
||||
--resolution-key <key>: takes the resolution index as argument
|
||||
--de-key <key>
|
||||
--wm-key <key>
|
||||
--wm-theme-key <key>
|
||||
--theme-key <key>
|
||||
--icons-key <key>
|
||||
--font-key <key>
|
||||
--cursor-key <key>
|
||||
--terminal-key <key>
|
||||
--terminal-font-key <key>
|
||||
--cpu-key <key>
|
||||
--cpu-usage-key <key>
|
||||
--gpu-key <key>: takes the gpu index as format argument
|
||||
--memory-key <key>
|
||||
--disk-key <key>: takes the mount path as format argument
|
||||
--battery-key <key>: takes the battery index as format argument
|
||||
--locale-key <key>
|
||||
--local-ip-key <key>: takes the name of this network interface as format argument
|
||||
--public-ip-key <key>
|
||||
--player-key <key>
|
||||
--song-key <key>
|
||||
--datetime-key <key>
|
||||
--time-key <key>
|
||||
--date-key <key>
|
||||
--<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>
|
||||
@@ -120,20 +88,48 @@ Library options: Set the path of a library to load
|
||||
--lib-DConf <path>
|
||||
--lib-DBus <path>
|
||||
--lib-XFConf <path>
|
||||
--lib-RPM <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:
|
||||
--separator-string <str>: Set the string printed by the separator module
|
||||
--os-file <path>: Set the path to the file containing OS informations
|
||||
--disk-folders <folders>: A colon separated list of folder paths for the disk output. Default is "/:/home"
|
||||
--battery-dir <folder>: The directory where the battery folders are. Standard: /sys/class/power_supply/
|
||||
--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
|
||||
--public-ip-timeout: Time in milliseconds to wait for the public ip server to respond. Default is disabled (0)
|
||||
--player-name: The name of the player to use
|
||||
--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
|
||||
--shell-version <?value>: Set if shell version should be detected and printed
|
||||
--terminal-version <?value>: Set if terminal version should be detected and printed
|
||||
--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
|
||||
--disk-show-subvolumes <?value>: Set if subvolumes should be printed. Default is false
|
||||
--disk-show-unknown <?value>: Set if unknown (unable to detect sizes) 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
|
||||
--gpu-hide-integrated <?value>: Hide integrated GPU if supported. Default is false
|
||||
--gpu-hide-discrete <?value>: Hide discrete GPU 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, 6 for bar only. Default is 1
|
||||
--command-shell <str>: Set the shell program to execute the command text. Default is cmd for Windows, csh for FreeBSD, bash for others
|
||||
--command-key <str>: Set the module key to display, can be specified mulitple times
|
||||
--command-text <str>: Set the command text to be executed, can be specified mulitple times
|
||||
|
||||
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.
|
||||
|
||||
@@ -19,24 +19,18 @@ 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{/}"
|
||||
|
||||
There is a special variable set if an error occured during detection. You can access it with "{e}", "{error}" o
|
||||
You can use ifs and not ifs with it like with an index. For example use "{?e}some text{?}", to print a text if an
|
||||
|
||||
To stop formatting at any point in the format string, use "{-}".
|
||||
For example to print an error instead of the normal output if it occured, prefix the format string with "{?e}{e}{-
|
||||
|
||||
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}...{#}".
|
||||
If not in a format string, fastfetch wraps errors with "{#1;31}error{#}", so you might want to do that to if you
|
||||
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
|
||||
This can be used to print nothing if an error occured: prefix the format string with "{?e}{-}{?}...".
|
||||
|
||||
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".
|
||||
For example when running in headless mode, you could use "--display-format Preferred".
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
Battery
|
||||
Bios
|
||||
Board
|
||||
Break
|
||||
Chassis
|
||||
Colors
|
||||
CPU
|
||||
CPUUsage
|
||||
@@ -8,6 +11,7 @@ Date
|
||||
Datetime
|
||||
DE
|
||||
Disk
|
||||
Display
|
||||
Font
|
||||
GPU
|
||||
Host
|
||||
@@ -15,21 +19,26 @@ Icons
|
||||
Kernel
|
||||
Locale
|
||||
LocalIP
|
||||
Media
|
||||
Memory
|
||||
OpenGL
|
||||
OS
|
||||
Packages
|
||||
Player
|
||||
PowerAdapter
|
||||
Processes
|
||||
PublicIP
|
||||
Resolution
|
||||
Separator
|
||||
Shell
|
||||
Song
|
||||
Swap
|
||||
Terminal
|
||||
TerminalFont
|
||||
Theme
|
||||
Time
|
||||
Title
|
||||
Uptime
|
||||
Vulkan
|
||||
Weather
|
||||
Wifi
|
||||
WM
|
||||
WMTheme
|
||||
|
||||
@@ -1 +1 @@
|
||||
Title:Separator:OS:Host:Kernel:Uptime:Packages:Shell:Resolution:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:GPU:Memory:Disk:Battery:Locale:Break:Colors
|
||||
Title:Separator:OS:Host:Kernel:Uptime:Packages:Shell:Display: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,38 @@
|
||||
#include "fastfetch.h"
|
||||
#include "battery.h"
|
||||
|
||||
#include "common/processing.h"
|
||||
#include "common/properties.h"
|
||||
|
||||
const char* ffDetectBatteryImpl(FF_MAYBE_UNUSED FFinstance* instance, FFlist* results)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY buffer;
|
||||
ffStrbufInit(&buffer);
|
||||
|
||||
if(ffProcessAppendStdOut(&buffer, (char* const[]){
|
||||
FASTFETCH_TARGET_DIR_ROOT "/libexec/termux-api",
|
||||
"BatteryStatus"
|
||||
}))
|
||||
return "Starting `" FASTFETCH_TARGET_DIR_ROOT "/libexec/termux-api" " BatteryStatus` failed";
|
||||
|
||||
BatteryResult* battery = ffListAdd(results);
|
||||
battery->temperature = FF_BATTERY_TEMP_UNSET;
|
||||
ffStrbufInit(&battery->manufacturer);
|
||||
ffStrbufInit(&battery->modelName);
|
||||
ffStrbufInit(&battery->status);
|
||||
ffStrbufInit(&battery->technology);
|
||||
|
||||
if(ffParsePropLines(buffer.chars, "\"percentage\": ", &battery->status))
|
||||
{
|
||||
battery->capacity = ffStrbufToDouble(&battery->status);
|
||||
ffStrbufClear(&battery->status);
|
||||
}
|
||||
|
||||
if(ffParsePropLines(buffer.chars, "\"status\": ", &battery->status))
|
||||
{
|
||||
ffStrbufTrimRight(&battery->status, ',');
|
||||
ffStrbufTrim(&battery->status, '"');
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -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,59 @@
|
||||
#include "fastfetch.h"
|
||||
#include "battery.h"
|
||||
|
||||
#include <dev/acpica/acpiio.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
const char* ffDetectBatteryImpl(FF_MAYBE_UNUSED FFinstance* instance, FFlist* results)
|
||||
{
|
||||
//https://www.freebsd.org/cgi/man.cgi?acpi_battery(4)
|
||||
//https://gitlab.xfce.org/panel-plugins/xfce4-battery-plugin/-/blob/master/panel-plugin/libacpi.c
|
||||
|
||||
int acpifd = open("/dev/acpi", O_RDONLY);
|
||||
if(acpifd < 0)
|
||||
return "open(\"/dev/acpi\", O_RDONLY) failed";
|
||||
|
||||
int units = ioctl(acpifd, ACPIIO_BATT_GET_UNITS, 0);
|
||||
if(units < 0)
|
||||
{
|
||||
close(acpifd);
|
||||
return "No acpiio battery units found";
|
||||
}
|
||||
|
||||
for(int i = 0; i < units; ++i)
|
||||
{
|
||||
union acpi_battery_ioctl_arg battio;
|
||||
battio.unit = i;
|
||||
|
||||
if(ioctl(acpifd, ACPIIO_BATT_GET_BATTINFO, &battio) < 0 || (battio.battinfo.state & ACPI_BATT_STAT_NOT_PRESENT))
|
||||
continue;
|
||||
|
||||
BatteryResult* battery = ffListAdd(results);
|
||||
battery->temperature = FF_BATTERY_TEMP_UNSET;
|
||||
ffStrbufInit(&battery->manufacturer);
|
||||
ffStrbufInit(&battery->modelName);
|
||||
ffStrbufInit(&battery->status);
|
||||
ffStrbufInit(&battery->technology);
|
||||
|
||||
battery->capacity = battio.battinfo.cap;
|
||||
if(battio.battinfo.state & ACPI_BATT_STAT_INVALID)
|
||||
{
|
||||
ffStrbufAppendS(&battery->status, "Invalid");
|
||||
}
|
||||
else
|
||||
{
|
||||
if(battio.battinfo.state & ACPI_BATT_STAT_DISCHARG)
|
||||
ffStrbufAppendS(&battery->status, "Discharging, ");
|
||||
else if(battio.battinfo.state & ACPI_BATT_STAT_CHARGING)
|
||||
ffStrbufAppendS(&battery->status, "Charging, ");
|
||||
if(battio.battinfo.state & ACPI_BATT_STAT_CRITICAL)
|
||||
ffStrbufAppendS(&battery->status, "Ctritical");
|
||||
ffStrbufTrimRight(&battery->status, ' ');
|
||||
ffStrbufTrimRight(&battery->status, ',');
|
||||
}
|
||||
}
|
||||
close(acpifd);
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
#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)
|
||||
{
|
||||
if(strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
|
||||
continue;
|
||||
|
||||
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,17 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef FF_INCLUDED_detection_brightness_brightness
|
||||
#define FF_INCLUDED_detection_brightness_brightness
|
||||
|
||||
#include "fastfetch.h"
|
||||
#include "util/FFlist.h"
|
||||
|
||||
typedef struct FFBrightnessResult
|
||||
{
|
||||
FFstrbuf name;
|
||||
float value;
|
||||
} FFBrightnessResult;
|
||||
|
||||
const char* ffDetectBrightness(FFlist* result); // list of FFBrightnessResult
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,33 @@
|
||||
#include "brightness.h"
|
||||
|
||||
#include <CoreGraphics/CoreGraphics.h>
|
||||
|
||||
extern int DisplayServicesGetBrightness(CGDirectDisplayID display, float *brightness) __attribute__((weak_import));
|
||||
|
||||
const char* ffDetectBrightness(FFlist* result)
|
||||
{
|
||||
if(DisplayServicesGetBrightness == NULL)
|
||||
return "DisplayServices function DisplayServicesGetBrightness is not available";
|
||||
|
||||
CGDirectDisplayID screens[128];
|
||||
uint32_t screenCount;
|
||||
if(CGGetOnlineDisplayList(sizeof(screens) / sizeof(screens[0]), screens, &screenCount) != kCGErrorSuccess)
|
||||
return "CGGetOnlineDisplayList() failed";
|
||||
|
||||
for(uint32_t i = 0; i < screenCount; i++)
|
||||
{
|
||||
CGDirectDisplayID screen = screens[i];
|
||||
float brightness;
|
||||
if(DisplayServicesGetBrightness(screen, &brightness) != kCGErrorSuccess)
|
||||
continue;
|
||||
|
||||
FFBrightnessResult* display = (FFBrightnessResult*) ffListAdd(result);
|
||||
if(CGDisplayIsBuiltin(screen))
|
||||
ffStrbufInitS(&display->name, "built-in");
|
||||
else
|
||||
ffStrbufInitF(&display->name, "external-%u", (unsigned) screen);
|
||||
display->value = brightness * 100;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
#include "brightness.h"
|
||||
#include "common/io.h"
|
||||
|
||||
#include <dirent.h>
|
||||
|
||||
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFlist* result)
|
||||
{
|
||||
//https://www.kernel.org/doc/Documentation/ABI/stable/sysfs-class-backlight
|
||||
const char* backlightDirPath = "/sys/class/backlight/";
|
||||
|
||||
DIR* dirp = opendir(backlightDirPath);
|
||||
if(dirp == NULL)
|
||||
return "Failed to open `/sys/class/backlight/`";
|
||||
|
||||
FFstrbuf backlightDir;
|
||||
ffStrbufInitA(&backlightDir, 64);
|
||||
ffStrbufAppendS(&backlightDir, backlightDirPath);
|
||||
|
||||
uint32_t backlightDirLength = backlightDir.length;
|
||||
|
||||
FFstrbuf buffer;
|
||||
ffStrbufInit(&buffer);
|
||||
|
||||
struct dirent* entry;
|
||||
while((entry = readdir(dirp)) != NULL)
|
||||
{
|
||||
if(strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
|
||||
continue;
|
||||
|
||||
ffStrbufAppendS(&backlightDir, entry->d_name);
|
||||
ffStrbufAppendS(&backlightDir, "/actual_brightness");
|
||||
if(ffReadFileBuffer(backlightDir.chars, &buffer))
|
||||
{
|
||||
double actualBrightness = ffStrbufToDouble(&buffer);
|
||||
ffStrbufSubstrBefore(&backlightDir, backlightDirLength);
|
||||
ffStrbufAppendS(&backlightDir, entry->d_name);
|
||||
ffStrbufAppendS(&backlightDir, "/max_brightness");
|
||||
if(ffReadFileBuffer(backlightDir.chars, &buffer))
|
||||
{
|
||||
FFBrightnessResult* display = (FFBrightnessResult*) ffListAdd(result);
|
||||
ffStrbufInitS(&display->name, entry->d_name);
|
||||
double maxBrightness = ffStrbufToDouble(&buffer);
|
||||
display->value = (float) (actualBrightness * 100 / maxBrightness);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
closedir(dirp);
|
||||
ffStrbufDestroy(&backlightDir);
|
||||
ffStrbufDestroy(&buffer);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#include "brightness.h"
|
||||
|
||||
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFlist* result)
|
||||
{
|
||||
return "Not supported on this platform";
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
extern "C"
|
||||
{
|
||||
#include "brightness.h"
|
||||
}
|
||||
#include "util/windows/wmi.hpp"
|
||||
|
||||
extern "C"
|
||||
const char* ffDetectBrightness(FFlist* result)
|
||||
{
|
||||
FFWmiQuery query(L"SELECT CurrentBrightness, InstanceName FROM WmiMonitorBrightness WHERE Active = true", nullptr, FFWmiNamespace::WMI);
|
||||
if(!query)
|
||||
return "Query WMI service failed";
|
||||
|
||||
while(FFWmiRecord record = query.next())
|
||||
{
|
||||
FFBrightnessResult* display = (FFBrightnessResult*) ffListAdd(result);
|
||||
ffStrbufInit(&display->name);
|
||||
record.getString(L"InstanceName", &display->name);
|
||||
ffStrbufSubstrAfterFirstC(&display->name, '\\');
|
||||
ffStrbufSubstrBeforeFirstC(&display->name, '\\');
|
||||
|
||||
uint64_t brightness;
|
||||
record.getUnsigned(L"CurrentBrightness", &brightness);
|
||||
display->value = (float) brightness;
|
||||
}
|
||||
return 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;
|
||||
}
|
||||