diff --git a/CHANGELOG.md b/CHANGELOG.md index a377afe..694eb96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +# Unreleased + +* Improved shell completion + - Complete on package names + - Various usability tweaks + - Completion files are now distributed in git, not in the compiled binary +* Updated deps + - Notably needed to compile with Rust >= 1.80 + # 0.7.0 2024-03-04 Feature release: Multi-term search, config file, and many goodies diff --git a/Cargo.lock b/Cargo.lock index b34d367..ac83d7e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,63 +3,64 @@ version = 3 [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] [[package]] name = "anstream" -version = "0.6.13" +version = "0.6.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.6" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" [[package]] name = "anstyle-parse" -version = "0.2.3" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.2" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" dependencies = [ "windows-sys", ] [[package]] name = "anstyle-wincon" -version = "3.0.2" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" dependencies = [ "anstyle", "windows-sys", @@ -67,9 +68,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.80" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" +checksum = "10f00e1f6e58a40e807377c75c6a7f97bf9044fab57816f2414e6f5f4499d7b8" [[package]] name = "assert_cmd" @@ -97,15 +98,15 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "bstr" -version = "1.9.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706" +checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c" dependencies = [ "memchr", "regex-automata", @@ -169,33 +170,33 @@ checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" [[package]] name = "crc32fast" -version = "1.4.0" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", ] [[package]] name = "crossbeam-channel" -version = "0.5.12" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.19" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "deranged" @@ -232,6 +233,9 @@ dependencies = [ "flate2", "libc", "log", + "predicates", + "predicates-core", + "predicates-tree", "regex", "rev_lines", "serde", @@ -242,18 +246,18 @@ dependencies = [ [[package]] name = "env_filter" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a009aa4810eb158359dda09d0c87378e4bbb89b5a801f016885a4707ba24f7ea" +checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" dependencies = [ "log", ] [[package]] name = "env_logger" -version = "0.11.2" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c012a26a7f605efc424dd53697843a72be7dc86ad2d01f7814337794a12231d" +checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" dependencies = [ "anstream", "anstyle", @@ -269,19 +273,28 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "flate2" -version = "1.0.28" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" dependencies = [ "crc32fast", "miniz_oxide", ] +[[package]] +name = "float-cmp" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" +dependencies = [ + "num-traits", +] + [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "heck" @@ -291,47 +304,59 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "indexmap" -version = "2.2.5" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" dependencies = [ "equivalent", "hashbrown", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "libc" -version = "0.2.153" +version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" [[package]] name = "log" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "memchr" -version = "2.7.1" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" dependencies = [ - "adler", + "adler2", ] +[[package]] +name = "normalize-line-endings" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" + [[package]] name = "num-conv" version = "0.1.0" @@ -340,9 +365,9 @@ checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] name = "num-traits" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] @@ -370,7 +395,10 @@ checksum = "68b87bfd4605926cdfefc1c3b5f8fe560e3feca9d5552cf68c466d3d8236c7e8" dependencies = [ "anstyle", "difflib", + "float-cmp", + "normalize-line-endings", "predicates-core", + "regex", ] [[package]] @@ -391,27 +419,27 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.78" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.35" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] [[package]] name = "regex" -version = "1.10.3" +version = "1.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" dependencies = [ "aho-corasick", "memchr", @@ -421,9 +449,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", @@ -432,9 +460,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "rev_lines" @@ -447,24 +475,24 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "serde" -version = "1.0.197" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.197" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", @@ -473,20 +501,21 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.114" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] [[package]] name = "serde_spanned" -version = "0.6.5" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" +checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" dependencies = [ "serde", ] @@ -499,9 +528,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "2.0.52" +version = "2.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" dependencies = [ "proc-macro2", "quote", @@ -516,18 +545,18 @@ checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" [[package]] name = "thiserror" -version = "1.0.57" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.57" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", @@ -536,9 +565,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.34" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa", @@ -559,9 +588,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ "num-conv", "time-core", @@ -569,9 +598,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.10" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a9aad4a3066010876e8dcf5a8a06e70a558751117a145c6ce2b82c2e2054290" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" dependencies = [ "serde", "serde_spanned", @@ -581,18 +610,18 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.5" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.22.6" +version = "0.22.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c1b5fd4128cc8d3e0cb74d4ed9a9cc7c7284becd4df68f5f940e1ad123606f6" +checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" dependencies = [ "indexmap", "serde", @@ -609,9 +638,9 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "utf8parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "wait-timeout" @@ -633,13 +662,14 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", + "windows_i686_gnullvm", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", @@ -648,51 +678,57 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" -version = "0.52.4" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.5" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8" +checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" dependencies = [ "memchr", ] diff --git a/Cargo.toml b/Cargo.toml index be6ad63..6e50dbf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,13 +22,13 @@ missing_const_for_fn = "warn" anyhow = "1.0.32" atoi = "2.0.0" clap = { version = "~4.4.11", features = ["cargo", "derive"] } -clap_complete = "~4.4.4" +clap_complete = { version = "~4.4.4", optional = true } crossbeam-channel = "0.5.0" env_logger = { version = "0.11.0", default-features = false, features = ["auto-color"] } flate2 = "1.0.28" libc = { version = "0.2.126", default-features = false } log = "0.4.11" -regex = { version = "1.10.0", default_features = false, features = ["std", "perf-inline", "perf-literal", "unicode-case"] } +regex = { version = "1.10.0", default-features = false, features = ["std", "perf-inline", "perf-literal", "unicode-case"] } rev_lines = "0.3.0" serde = { version = "1.0.184", features = ["derive"] } serde_json = "1.0.89" @@ -49,6 +49,9 @@ path = "benches/exec_compare.rs" # Experimental features, may require nightly compiler. # Currently only benchmarking. unstable = [] +# Generate shell completions at runtime instead of using static version. +# Only intended for developers. +clap_complete = ["dep:clap_complete"] [profile.release] debug = false diff --git a/README.md b/README.md index 0a081c1..81f8e67 100644 --- a/README.md +++ b/README.md @@ -87,8 +87,8 @@ Stats-specific arguments: ### Other commands -* `complete` generates shell completions -* `accuracy` helps analizing predictions accuracy +* `complete`: shell completion helper +* `accuracy`: analize predictions accuracy ### Configuration file @@ -130,11 +130,13 @@ you might need to pass `--locked` to `cargo install`, to use explicitly tested d cargo test cargo install -f --path . -#### Shell completion +#### Misc files - emlop complete bash > /usr/share/bash-completion/completions/emlop - emlop complete zsh > /usr/share/zsh/site-functions/_emlop - emlop complete fish > /usr/share/fish/vendor_completions.d/emlop.fish +Cargo only installs the binary, which is all you really need, but you may want to manualy install +some files fetched from [github](https://github.com/vincentdephily/emlop) or the [crates.io +page](https://crates.io/crates/emlop): [bash completion](completion.bash), [zsh +completion](completion.zsh), [fish completion](completion.fish), and [example config +file](emlop.toml). ## Contributing diff --git a/completion.bash b/completion.bash new file mode 100644 index 0000000..bdaf7be --- /dev/null +++ b/completion.bash @@ -0,0 +1,283 @@ +_emlop() { + local i cur prev opts cmd + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + cmd="emlop" + opts="" + + i=0 + for w in ${COMP_WORDS[@]}; do + found=$(compgen -W 'accuracy log predict stats' -- "${w}") + case ${found} in + "") + ;; + *) + if [[ $i == $COMP_CWORD ]]; then + COMPREPLY=($found) + return 0 + else + cmd="emlop__$found" + break + fi + ;; + esac + let i=$i+1 + done + + case "${cmd}" in + emlop) + opts="log predict stats accuracy -f -t -H -o -F -v -h -V --from --to --header --duration --date --utc --color --output --logfile --help --version" + if [[ ${cur} == -* ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + --from|--to|-f|-t) + COMPREPLY=($(compgen -W "1h 1d 1w 1m 1h $(date -Is)" "${cur}")) + ;; + --header|-H) + COMPREPLY=($(compgen -W "yes no" "${cur}")) + ;; + --duration) + COMPREPLY=($(compgen -W "hms secs hmsfixed human" "${cur}")) + ;; + --date) + COMPREPLY=($(compgen -W "ymd ymdhms ymdhmso rfc3339 rfc2822 compact unix" "${cur}")) + ;; + --utc) + COMPREPLY=($(compgen -W "yes no" "${cur}")) + ;; + --color) + COMPREPLY=($(compgen -W "yes no auto" "${cur}")) + ;; + --output|-o) + COMPREPLY=($(compgen -W "tab columns auto" "${cur}")) + ;; + --logfile|-F) + COMPREPLY=($(compgen -f "${cur}")) + ;; + *) + COMPREPLY=($(compgen -W "${opts}" -- "${cur}")) + ;; + esac + return 0 + ;; + emlop__accuracy) + opts="[search]... -e -s -n -f -t -H -o -F -v -h --exact --show --last --avg --limit --from --to --header --duration --date --utc --color --output --logfile --help" + if [[ ${cur} == -* ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + --from|--to|-f|-t) + COMPREPLY=($(compgen -W "1h 1d 1w 1m 1h $(date -Is)" "${cur}")) + ;; + --header|-H) + COMPREPLY=($(compgen -W "yes no" "${cur}")) + ;; + --duration) + COMPREPLY=($(compgen -W "hms secs hmsfixed human" "${cur}")) + ;; + --date) + COMPREPLY=($(compgen -W "ymd ymdhms ymdhmso rfc3339 rfc2822 compact unix" "${cur}")) + ;; + --utc) + COMPREPLY=($(compgen -W "yes no" "${cur}")) + ;; + --color) + COMPREPLY=($(compgen -W "yes no auto" "${cur}")) + ;; + --output|-o) + COMPREPLY=($(compgen -W "tab columns auto" "${cur}")) + ;; + --logfile|-F) + COMPREPLY=($(compgen -f "${cur}")) + ;; + --show|-s) + COMPREPLY=($(compgen -W "mta" "${cur}")) + ;; + --last|-n) + COMPREPLY=($(compgen -W "1 5 10 20 100" "${cur}")) + ;; + --avg) + COMPREPLY=($(compgen -W "arith median weighted-arith weighted-median" "${cur}")) + ;; + --limit) + COMPREPLY=($(compgen -W "1 5 20 999" "${cur}")) + ;; + *) + if [[ -z "${cur}" ]]; then + COMPREPLY=($(compgen -W "${opts}" -- "${cur}")) + else + COMPREPLY=($(emlop complete -- "${cur}")) + fi + ;; + esac + return 0 + ;; + emlop__log) + opts=" [search]... -N -n -s -e -f -t -H -o -F -v -h --starttime --first --last --show --exact --from --to --header --duration --date --utc --color --output --logfile --help" + if [[ ${cur} == -* ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + --from|--to|-f|-t) + COMPREPLY=($(compgen -W "1h 1d 1w 1m 1h $(date -Is)" "${cur}")) + ;; + --header|-H) + COMPREPLY=($(compgen -W "yes no ${opts}" "${cur}")) + ;; + --duration) + COMPREPLY=($(compgen -W "hms secs hmsfixed human" "${cur}")) + ;; + --date) + COMPREPLY=($(compgen -W "ymd ymdhms ymdhmso rfc3339 rfc2822 compact unix" "${cur}")) + ;; + --utc) + COMPREPLY=($(compgen -W "yes no" "${cur}")) + ;; + --color) + COMPREPLY=($(compgen -W "yes no auto" "${cur}")) + ;; + --output|-o) + COMPREPLY=($(compgen -W "tab columns auto" "${cur}")) + ;; + --logfile|-F) + COMPREPLY=($(compgen -f "${cur}")) + ;; + --starttime) + COMPREPLY=($(compgen -W "yes no" "${cur}")) + ;; + --first|-N|--last|-n) + COMPREPLY=($(compgen -W "1 5 10 20 100" "${cur}")) + ;; + --show|-s) + COMPREPLY=($(compgen -W "musa" "${cur}")) + ;; + *) + if [[ -z "${cur}" ]]; then + COMPREPLY=($(compgen -W "${opts}" -- "${cur}")) + else + COMPREPLY=($(emlop complete -- "${cur}")) + fi + ;; + esac + return 0 + ;; + emlop__predict) + opts="-s -N -n -f -t -H -o -F -v -h --show --first --last --tmpdir --resume --unknown --avg --limit --from --to --header --duration --date --utc --color --output --logfile --help" + if [[ ${cur} == -* ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + --from|--to|-f|-t) + COMPREPLY=($(compgen -W "1h 1d 1w 1m 1h $(date -Is)" "${cur}")) + ;; + --header|-H) + COMPREPLY=($(compgen -W "yes no" "${cur}")) + ;; + --duration) + COMPREPLY=($(compgen -W "hms secs hmsfixed human" "${cur}")) + ;; + --date) + COMPREPLY=($(compgen -W "ymd ymdhms ymdhmso rfc3339 rfc2822 compact unix" "${cur}")) + ;; + --utc) + COMPREPLY=($(compgen -W "yes no" "${cur}")) + ;; + --color) + COMPREPLY=($(compgen -W "yes no auto" "${cur}")) + ;; + --output|-o) + COMPREPLY=($(compgen -W "tab columns auto" "${cur}")) + ;; + --logfile|-F) + COMPREPLY=($(compgen -f "${cur}")) + ;; + --show|-s) + COMPREPLY=($(compgen -W "emta" "${cur}")) + ;; + --first|-N|--last|-n) + COMPREPLY=($(compgen -W "1 5 10 20 100" "${cur}")) + ;; + --tmpdir) + COMPREPLY=($(compgen -d "${cur}")) + ;; + --resume) + COMPREPLY=($(compgen -W "auto either main backup no" -- "${cur}")) + ;; + --unknown) + COMPREPLY=($(compgen -W "0 5 10 20 60" "${cur}")) + ;; + --avg) + COMPREPLY=($(compgen -W "arith median weighted-arith weighted-median" "${cur}")) + ;; + --limit) + COMPREPLY=($(compgen -W "1 5 20 999" "${cur}")) + ;; + *) + COMPREPLY=($(compgen -W "${opts}" -- "${cur}")) + ;; + esac + return 0 + ;; + emlop__stats) + opts="[search]... -s -g -e -f -t -H -o -F -v -h --show --groupby --exact --avg --limit --from --to --header --duration --date --utc --color --output --logfile --help" + if [[ ${cur} == -* ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + --from|--to|-f|-t) + COMPREPLY=($(compgen -W "1h 1d 1w 1m 1h $(date -Is)" "${cur}")) + ;; + --header|-H) + COMPREPLY=($(compgen -W "yes no" "${cur}")) + ;; + --duration) + COMPREPLY=($(compgen -W "hms secs hmsfixed human" "${cur}")) + ;; + --date) + COMPREPLY=($(compgen -W "ymd ymdhms ymdhmso rfc3339 rfc2822 compact unix" "${cur}")) + ;; + --utc) + COMPREPLY=($(compgen -W "yes no" "${cur}")) + ;; + --color) + COMPREPLY=($(compgen -W "yes no auto" "${cur}")) + ;; + --output|-o) + COMPREPLY=($(compgen -W "tab columns auto" "${cur}")) + ;; + --logfile|-F) + COMPREPLY=($(compgen -f "${cur}")) + ;; + --show|-s) + COMPREPLY=($(compgen -W "ptsa" "${cur}")) + ;; + --groupby|-g) + COMPREPLY=($(compgen -W "year month week day none" "${cur}")) + ;; + --avg) + COMPREPLY=($(compgen -W "arith median weighted-arith weighted-median" "${cur}")) + ;; + --limit) + COMPREPLY=($(compgen -W "1 5 20 999" "${cur}")) + ;; + *) + if [[ -z "${cur}" ]]; then + COMPREPLY=($(compgen -W "${opts}" -- "${cur}")) + else + COMPREPLY=($(emlop complete -- "${cur}")) + fi + ;; + esac + return 0 + ;; + esac +} + +complete -F _emlop -o nosort -o bashdefault -o default emlop diff --git a/completion.fish b/completion.fish new file mode 100644 index 0000000..16d5ae0 --- /dev/null +++ b/completion.fish @@ -0,0 +1,49 @@ +complete -c emlop -e +complete -c emlop -f +complete -c emlop -s f -l from -d 'Only parse log entries after ' -x -a "{1y 'One year ago',1m 'One month ago',1w 'One week ago',1d 'One day ago',1h 'One hour ago',(date -Is) 'Exact date'}" +complete -c emlop -s t -l to -d 'Only parse log entries before ' -x -a "{1y 'One year ago',1m 'One month ago',1w 'One week ago',1d 'One day ago',1h 'One hour ago',(date -Is) 'Exact date'}" +complete -c emlop -s H -l header -d 'Show table header' -f -a "yes no" +complete -c emlop -l duration -d 'Output durations in different formats' -x -a "hms hmsfixed human secs" +complete -c emlop -l date -d 'Output dates in different formats' -x -a "ymd ymdhms ymdhmso rfc3339 rfc2822 compact unix" +complete -c emlop -l utc -d 'Parse/display dates in UTC instead of local time' -f -a "yes no" +complete -c emlop -l color -d 'Enable color (yes/no/auto)' -f -a "{yes Enabled,no Disabled,auto 'Enabled on terminal'}" +complete -c emlop -s o -l output -d 'Ouput format' -x -a "columns tab auto" +complete -c emlop -s F -l logfile -d 'Location of emerge log file' -r -F +complete -c emlop -s v -x -a "{ 'Show warnings',v 'Show info',vv 'Show debug',vvv 'Show trace'}" -d 'Increase verbosity' +complete -c emlop -s h -d 'Print short help' +complete -c emlop -l help -d 'Print long help' +complete -c emlop -n "__fish_use_subcommand" -s V -l version -d 'Print version' + +complete -c emlop -n "__fish_use_subcommand" -f -a "log" -d 'Show log of sucessful merges, unmerges and syncs' +complete -c emlop -n "__fish_use_subcommand" -f -a "predict" -d 'Predict merge times for current or pretended merges' +complete -c emlop -n "__fish_use_subcommand" -f -a "stats" -d 'Show statistics about syncs, per-package (un)merges, and total (un)merges' +complete -c emlop -n "__fish_use_subcommand" -f -a "accuracy" -d 'Compare actual merge time against predicted merge time' + +complete -c emlop -n "__fish_seen_subcommand_from log" -l starttime -d 'Display start time instead of end time' -f -a "yes no" +complete -c emlop -n "__fish_seen_subcommand_from log" -s N -l first -d 'Show only the first entries' -f -a "{ 'Show only first entry',5 'Show only first 5 entries',10 'Show only first 10 entries'}" +complete -c emlop -n "__fish_seen_subcommand_from log" -s n -l last -d 'Show only the last entries' -f -a "{ 'Show only last entry',5 'Show only last 5 entries',10 'Show only last 10 entries'}" +complete -c emlop -n "__fish_seen_subcommand_from log" -s s -l show -d 'Show (m)erges, (u)nmerges, (s)yncs, and/or (a)ll' -x -a "musa" +complete -c emlop -n "__fish_seen_subcommand_from log" -s e -l exact -d 'Match using plain string' +complete -c emlop -n "__fish_seen_subcommand_from log" -a "(emlop complete '$1')" + +complete -c emlop -n "__fish_seen_subcommand_from predict" -s s -l show -d 'Show (e)emerge processes, (m)erges, (t)otal, and/or (a)ll' -x -a "emta" +complete -c emlop -n "__fish_seen_subcommand_from predict" -s N -l first -d 'Show only the first entries' -f -a "{ 'Show only first entry',5 'Show only first 5 entries',10 'Show only first 10 entries'}" +complete -c emlop -n "__fish_seen_subcommand_from predict" -s n -l last -d 'Show only the last entries' -f -a "{ 'Show only last entry',5 'Show only last 5 entries',10 'Show only last 10 entries'}" +complete -c emlop -n "__fish_seen_subcommand_from predict" -l tmpdir -d 'Location of portage tmpdir' -x -a "(__fish_complete_directories '$1')" +complete -c emlop -n "__fish_seen_subcommand_from predict" -l resume -d 'Use main, backup, either, or no portage resume list' -f -a "{auto '',either '',main '',backup '',no ''}" +complete -c emlop -n "__fish_seen_subcommand_from predict" -l unknown -d 'Assume unkown packages take seconds to merge' -x -a "0 5 10 20 60" +complete -c emlop -n "__fish_seen_subcommand_from predict" -l avg -d 'Select function used to predict durations' -x -a "arith median weighted-arith weighted-median" +complete -c emlop -n "__fish_seen_subcommand_from predict" -l limit -d 'Use the last merge times to predict durations' -x -a "1 5 20 999" + +complete -c emlop -n "__fish_seen_subcommand_from stats" -s s -l show -d 'Show (p)ackages, (t)otals, (s)yncs, and/or (a)ll' -x -a "ptsa" +complete -c emlop -n "__fish_seen_subcommand_from stats" -s g -l groupby -d 'Group by (y)ear, (m)onth, (w)eek, (d)ay, (n)one' -x -a "year month week day none" +complete -c emlop -n "__fish_seen_subcommand_from stats" -l avg -d 'Select function used to predict durations' -x -a "arith median weighted-arith weighted-median" +complete -c emlop -n "__fish_seen_subcommand_from stats" -l limit -d 'Use the last merge times to predict durations' -x -a "1 5 20 999" +complete -c emlop -n "__fish_seen_subcommand_from stats" -s e -l exact -d 'Match using plain string' +complete -c emlop -n "__fish_seen_subcommand_from stats" -a "(emlop complete '$1')" + +complete -c emlop -n "__fish_seen_subcommand_from accuracy" -s s -l show -d 'Show (m)erges, (t)otals, and/or (a)ll' -x -a "mta" +complete -c emlop -n "__fish_seen_subcommand_from accuracy" -s n -l last -d 'Show only the last entries' -x -a "{ 'Show only last entry',5 'Show only last 5 entries',10 'Show only last 10 entries'}" +complete -c emlop -n "__fish_seen_subcommand_from accuracy" -l avg -d 'Select function used to predict durations' -x -a "arith median weighted-arith weighted-median" +complete -c emlop -n "__fish_seen_subcommand_from accuracy" -l limit -d 'Use the last merge times to predict durations' -x -a "1 5 20 999" +complete -c emlop -n "__fish_seen_subcommand_from accuracy" -s e -l exact -d 'Match using plain string' diff --git a/completion.zsh b/completion.zsh new file mode 100644 index 0000000..ff8928b --- /dev/null +++ b/completion.zsh @@ -0,0 +1,194 @@ +#compdef emlop + +_emlop() { + typeset -A opt_args + local context curcontext="$curcontext" state line + + _arguments -s -S -C \ +'-f+[Only parse log entries after ]:date: ' \ +'--from=[Only parse log entries after ]:date: ' \ +'-t+[Only parse log entries before ]:date: ' \ +'--to=[Only parse log entries before ]:date: ' \ +'-H+[Show table header]' \ +'--header=[Show table header]' \ +'--duration=[Output durations in different formats]:format: ' \ +'--date=[Output dates in different formats]:format: ' \ +'--utc=[Parse/display dates in UTC instead of local time]' \ +'--color=[Enable color (yes/no/auto)]' \ +'-o+[Ouput format (columns/tab/auto)]:format: ' \ +'--output=[Ouput format (columns/tab/auto)]:format: ' \ +'-F+[Location of emerge log file]:file: ' \ +'--logfile=[Location of emerge log file]:file: ' \ +'*-v[Increase verbosity (can be given multiple times)]' \ +'-h[Print help (see more with '\''--help'\'')]' \ +'--help[Print help (see more with '\''--help'\'')]' \ +'-V[Print version]' \ +'--version[Print version]' \ +":: :_emlop_commands" \ +"*::: :->emlop" + case $state in + (emlop) + words=($line[1] "${words[@]}") + (( CURRENT += 1 )) + curcontext="${curcontext%:*:*}:emlop-command-$line[1]:" + case $line[1] in + (log) + _arguments -s -S -C \ +'--starttime=[Display start time instead of end time]' \ +'-N+[Show only the first entries]' \ +'--first=[Show only the first entries]' \ +'-n+[Show only the last entries]' \ +'--last=[Show only the last entries]' \ +'-s+[Show (m)erges, (u)nmerges, (s)yncs, and/or (a)ll]:m,u,s,a: ' \ +'--show=[Show (m)erges, (u)nmerges, (s)yncs, and/or (a)ll]:m,u,s,a: ' \ +'-f+[Only parse log entries after ]:date: ' \ +'--from=[Only parse log entries after ]:date: ' \ +'-t+[Only parse log entries before ]:date: ' \ +'--to=[Only parse log entries before ]:date: ' \ +'-H+[Show table header]' \ +'--header=[Show table header]' \ +'--duration=[Output durations in different formats]:format: ' \ +'--date=[Output dates in different formats]:format: ' \ +'--utc=[Parse/display dates in UTC instead of local time]' \ +'--color=[Enable color (yes/no/auto)]' \ +'-o+[Ouput format (columns/tab/auto)]:format: ' \ +'--output=[Ouput format (columns/tab/auto)]:format: ' \ +'-F+[Location of emerge log file]:file: ' \ +'--logfile=[Location of emerge log file]:file: ' \ +'-e[Match using plain string]' \ +'--exact[Match using plain string]' \ +'*-v[Increase verbosity (can be given multiple times)]' \ +'-h[Print help (see more with '\''--help'\'')]' \ +'--help[Print help (see more with '\''--help'\'')]' \ +'*::search:($(emlop complete))' + ;; + (predict) + _arguments -s -S -C \ +'-s+[Show (e)emerge processes, (m)erges, (t)otal, and/or (a)ll]:e,m,t,a: ' \ +'--show=[Show (e)emerge processes, (m)erges, (t)otal, and/or (a)ll]:e,m,t,a: ' \ +'-N+[Show only the first entries]' \ +'--first=[Show only the first entries]' \ +'-n+[Show only the last entries]' \ +'--last=[Show only the last entries]' \ +'*--tmpdir=[Location of portage tmpdir]:dir:_files' \ +'--resume=[Use main, backup, either, or no portage resume list]' \ +'--unknown=[Assume unkown packages take seconds to merge]:secs: ' \ +'--avg=[Select function used to predict durations]:fn: ' \ +'--limit=[Use the last merge times to predict durations]:num: ' \ +'-f+[Only parse log entries after ]:date: ' \ +'--from=[Only parse log entries after ]:date: ' \ +'-t+[Only parse log entries before ]:date: ' \ +'--to=[Only parse log entries before ]:date: ' \ +'-H+[Show table header]' \ +'--header=[Show table header]' \ +'--duration=[Output durations in different formats]:format: ' \ +'--date=[Output dates in different formats]:format: ' \ +'--utc=[Parse/display dates in UTC instead of local time]' \ +'--color=[Enable color (yes/no/auto)]' \ +'-o+[Ouput format (columns/tab/auto)]:format: ' \ +'--output=[Ouput format (columns/tab/auto)]:format: ' \ +'-F+[Location of emerge log file]:file: ' \ +'--logfile=[Location of emerge log file]:file: ' \ +'*-v[Increase verbosity (can be given multiple times)]' \ +'-h[Print help (see more with '\''--help'\'')]' \ +'--help[Print help (see more with '\''--help'\'')]' + ;; + (stats) + _arguments -s -S -C \ +'-s+[Show (p)ackages, (t)otals, (s)yncs, and/or (a)ll]:p,t,s,a: ' \ +'--show=[Show (p)ackages, (t)otals, (s)yncs, and/or (a)ll]:p,t,s,a: ' \ +'-g+[Group by (y)ear, (m)onth, (w)eek, (d)ay, (n)one]:y,m,w,d,n: ' \ +'--groupby=[Group by (y)ear, (m)onth, (w)eek, (d)ay, (n)one]:y,m,w,d,n: ' \ +'--avg=[Select function used to predict durations]:fn: ' \ +'--limit=[Use the last merge times to predict durations]:num: ' \ +'-f+[Only parse log entries after ]:date: ' \ +'--from=[Only parse log entries after ]:date: ' \ +'-t+[Only parse log entries before ]:date: ' \ +'--to=[Only parse log entries before ]:date: ' \ +'-H+[Show table header]' \ +'--header=[Show table header]' \ +'--duration=[Output durations in different formats]:format: ' \ +'--date=[Output dates in different formats]:format: ' \ +'--utc=[Parse/display dates in UTC instead of local time]' \ +'--color=[Enable color (yes/no/auto)]' \ +'-o+[Ouput format (columns/tab/auto)]:format: ' \ +'--output=[Ouput format (columns/tab/auto)]:format: ' \ +'-F+[Location of emerge log file]:file: ' \ +'--logfile=[Location of emerge log file]:file: ' \ +'-e[Match using plain string]' \ +'--exact[Match using plain string]' \ +'*-v[Increase verbosity (can be given multiple times)]' \ +'-h[Print help (see more with '\''--help'\'')]' \ +'--help[Print help (see more with '\''--help'\'')]' \ +'*::search:($(emlop complete))' + ;; + (accuracy) + _arguments -s -S -C \ +'-s+[Show (m)erges, (t)otals, and/or (a)ll]:m,t,a: ' \ +'--show=[Show (m)erges, (t)otals, and/or (a)ll]:m,t,a: ' \ +'-n+[Show only the last entries]' \ +'--last=[Show only the last entries]' \ +'--avg=[Select function used to predict durations]:fn: ' \ +'--limit=[Use the last merge times to predict durations]:num: ' \ +'-f+[Only parse log entries after ]:date: ' \ +'--from=[Only parse log entries after ]:date: ' \ +'-t+[Only parse log entries before ]:date: ' \ +'--to=[Only parse log entries before ]:date: ' \ +'-H+[Show table header]' \ +'--header=[Show table header]' \ +'--duration=[Output durations in different formats]:format: ' \ +'--date=[Output dates in different formats]:format: ' \ +'--utc=[Parse/display dates in UTC instead of local time]' \ +'--color=[Enable color (yes/no/auto)]' \ +'-o+[Ouput format (columns/tab/auto)]:format: ' \ +'--output=[Ouput format (columns/tab/auto)]:format: ' \ +'-F+[Location of emerge log file]:file: ' \ +'--logfile=[Location of emerge log file]:file: ' \ +'-e[Match using plain string]' \ +'--exact[Match using plain string]' \ +'*-v[Increase verbosity (can be given multiple times)]' \ +'-h[Print help (see more with '\''--help'\'')]' \ +'--help[Print help (see more with '\''--help'\'')]' \ +'*::search:($(emlop complete))' + ;; + esac + ;; + esac +} + +(( $+functions[_emlop_commands] )) || +_emlop_commands() { + local commands; commands=( +'log:Show log of sucessful merges, unmerges and syncs' \ +'predict:Predict merge times for current or pretended merges' \ +'stats:Show statistics about syncs, per-package (un)merges, and total (un)merges' \ +'accuracy:Compare actual merge time against predicted merge time' \ + ) + _describe -t commands 'emlop commands' commands "$@" +} +(( $+functions[_emlop__accuracy_commands] )) || +_emlop__accuracy_commands() { + local commands; commands=() + _describe -t commands 'emlop accuracy commands' commands "$@" +} +(( $+functions[_emlop__log_commands] )) || +_emlop__log_commands() { + local commands; commands=() + _describe -t commands 'emlop log commands' commands "$@" +} +(( $+functions[_emlop__predict_commands] )) || +_emlop__predict_commands() { + local commands; commands=() + _describe -t commands 'emlop predict commands' commands "$@" +} +(( $+functions[_emlop__stats_commands] )) || +_emlop__stats_commands() { + local commands; commands=() + _describe -t commands 'emlop stats commands' commands "$@" +} + +if [ "$funcstack[1]" = "_emlop" ]; then + _emlop "$@" +else + compdef _emlop emlop +fi diff --git a/docs/COMPARISON.md b/docs/COMPARISON.md index c47b0e9..3a12e94 100644 --- a/docs/COMPARISON.md +++ b/docs/COMPARISON.md @@ -160,12 +160,12 @@ the terminal emulator). Genlop is noticably slow for basic tasks, and can be pro ## misc -| | genlop | qlop | emlop | -|:---------------------------|:------------:|:------:|:-----------------:| -| Shell completion | bash | none | bash/zsh/fish/... | -| Complete package name | yes | n/a | no | -| Configuration file | no | no | yes | -| Read compressed emerge.log | yes | no | yes | -| Unittests | no | yes | yes | -| Documentation and help | ok | good | good | -| Development activity | unmaintained | active | active | +| | genlop | qlop | emlop | +|:---------------------------|:------------:|:------:|:-------------:| +| Shell completion | bash | none | bash/zsh/fish | +| Complete package name | yes | n/a | yes | +| Configuration file | no | no | yes | +| Read compressed emerge.log | yes | no | yes | +| Unittests | no | yes | yes | +| Documentation and help | ok | good | good | +| Development activity | unmaintained | active | active | diff --git a/src/commands.rs b/src/commands.rs index 3599f01..8e2179d 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -1,5 +1,5 @@ use crate::{datetime::*, parse::*, table::*, *}; -use std::{collections::{BTreeMap, HashMap}, +use std::{collections::{BTreeMap, HashMap, HashSet}, io::{stdin, IsTerminal}}; /// Straightforward display of merge events @@ -480,9 +480,28 @@ pub fn cmd_accuracy(gc: &Conf, sc: &ConfAccuracy) -> Result { Ok(found) } -pub fn cmd_complete(sc: &ConfComplete) -> Result { - let mut cli = build_cli_nocomplete(); - clap_complete::generate(sc.shell, &mut cli, "emlop", &mut std::io::stdout()); +pub fn cmd_complete(gc: &Conf, sc: &ConfComplete) -> Result { + // Generate standard clap completions + #[cfg(feature = "clap_complete")] + if let Some(s) = &sc.shell { + let mut cli = build_cli(); + let shell = clap_complete::Shell::from_str(s).expect("Unsupported shell"); + clap_complete::generate(shell, &mut cli, "emlop", &mut std::io::stdout()); + return Ok(true); + } + // Look for (un)merged matching packages in the log and print each once + let term: Vec<_> = sc.pkg.iter().cloned().collect(); + let hist = get_hist(&gc.logfile, gc.from, gc.to, Show::m(), &term, false)?; + let mut pkgs: HashSet = HashSet::new(); + for p in hist { + if let Hist::MergeStart { .. } = p { + let e = p.ebuild(); + if !pkgs.contains(e) { + println!("{}", e); + pkgs.insert(e.to_string()); + } + } + } Ok(true) } diff --git a/src/config.rs b/src/config.rs index ded973a..ac5890f 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,3 +1,6 @@ +/// Runtime config +/// +/// Order of precedance is command line (clap), config file (toml), default. mod cli; mod toml; mod types; @@ -7,19 +10,17 @@ use crate::{config::toml::Toml, parse::AnsiStr, *}; use clap::ArgMatches; use std::{io::IsTerminal, path::PathBuf}; - +/// Global config, one enum variant per command pub enum Configs { Log(Conf, ConfLog), Stats(Conf, ConfStats), Predict(Conf, ConfPred), Accuracy(Conf, ConfAccuracy), - Complete(ConfComplete), + Complete(Conf, ConfComplete), } - -/// Global config +/// Common config /// -/// Colors use `prefix/suffix()` instead of `paint()` because `paint()` doesn't handle `'{:>9}'` -/// alignments properly. +/// Using raw `set/clear` ANSI colors instead of some `paint()` method to simplify alignment. pub struct Conf { pub pkg: AnsiStr, pub merge: AnsiStr, @@ -72,7 +73,9 @@ pub struct ConfAccuracy { pub lim: u16, } pub struct ConfComplete { - pub shell: clap_complete::Shell, + #[cfg(feature = "clap_complete")] + pub shell: Option, + pub pkg: Option, } impl Configs { @@ -95,7 +98,7 @@ impl Configs { Some(("stats", sub)) => Self::Stats(conf, ConfStats::try_new(sub, &toml)?), Some(("predict", sub)) => Self::Predict(conf, ConfPred::try_new(sub, &toml)?), Some(("accuracy", sub)) => Self::Accuracy(conf, ConfAccuracy::try_new(sub, &toml)?), - Some(("complete", sub)) => Self::Complete(ConfComplete::try_new(sub)?), + Some(("complete", sub)) => Self::Complete(conf, ConfComplete::try_new(sub)?), _ => unreachable!("clap should have exited already"), }) } @@ -139,7 +142,6 @@ macro_rules! sel { } } - impl Conf { pub fn try_new(cli: &ArgMatches, toml: &Toml) -> Result { let isterm = std::io::stdout().is_terminal(); @@ -156,8 +158,8 @@ impl Conf { unmerge: AnsiStr::from(if color { "\x1B[1;31m" } else { "<<< " }), dur: AnsiStr::from(if color { "\x1B[1;35m" } else { "" }), cnt: AnsiStr::from(if color { "\x1B[2;33m" } else { "" }), - clr: AnsiStr::from(if color { "\x1B[0m" } else { "" }), - lineend: if color { b"\x1B[0m\n" } else { b"\n" }, + clr: AnsiStr::from(if color { "\x1B[m" } else { "" }), + lineend: if color { b"\x1B[m\n" } else { b"\n" }, header: sel!(cli, toml, header, (), false)?, dur_t: sel!(cli, toml, duration, (), DurationStyle::Hms)?, date_offset: offset, @@ -226,6 +228,8 @@ impl ConfAccuracy { impl ConfComplete { fn try_new(cli: &ArgMatches) -> Result { - Ok(Self { shell: *cli.get_one("shell").unwrap() }) + Ok(Self { #[cfg(feature = "clap_complete")] + shell: cli.get_one("shell").cloned(), + pkg: cli.get_one("pkg").cloned() }) } } diff --git a/src/config/cli.rs b/src/config/cli.rs index 6243e06..63ef855 100644 --- a/src/config/cli.rs +++ b/src/config/cli.rs @@ -2,7 +2,7 @@ use clap::{builder::styling, crate_version, value_parser, Arg, ArgAction::*, Com use std::path::PathBuf; /// Generate cli argument parser without the `complete` subcommand. -pub fn build_cli_nocomplete() -> Command { +pub fn build_cli() -> Command { //////////////////////////////////////////////////////////// // Filter arguments //////////////////////////////////////////////////////////// @@ -284,6 +284,19 @@ pub fn build_cli_nocomplete() -> Command { -v: show warnings\n \ -vv: show info\n \ -vvv: show debug"); + #[cfg(feature = "clap_complete")] + let shell = + Arg::new("shell").long("shell") + .help("Write generated (development) completion script to stdout") + .num_args(1) + .display_order(34); + let h = "List matching packages from emerge.log\n\ + Uses the same semantics as `log ` filtering. \ + An empty search lists everything."; + let onepkg = Arg::new("pkg").help(h.split_once('\n').unwrap().0) + .long_help(h) + .num_args(1) + .display_order(35); //////////////////////////////////////////////////////////// // Subcommands @@ -335,6 +348,11 @@ pub fn build_cli_nocomplete() -> Command { .arg(last) .arg(avg) .arg(limit); + #[cfg(feature = "clap_complete")] + let cmd_complete = + Command::new("complete").about("Shell completion helper").arg(shell).arg(onepkg); + #[cfg(not(feature = "clap_complete"))] + let cmd_complete = Command::new("complete").about("Shell completion helper").arg(onepkg); //////////////////////////////////////////////////////////// // Main command @@ -345,8 +363,9 @@ pub fn build_cli_nocomplete() -> Command { concat!("Commands and long args can be abbreviated (eg `emlop l -ss --head -f1w`)\n\ Commands have their own -h / --help\n\ Exit code is 0 if sucessful, 1 if search found nothing, 2 in case of other errors\n\ - Config can be set in $HOME/.config/emlop.toml, see example in /usr/share/doc/emlop-", - crate_version!()); + Config can be set in $HOME/.config/emlop.toml\n\ + See readme, changelog, and sample config in /usr/share/doc/emlop-", + crate_version!(), "/"); let styles = styling::Styles::styled().header(styling::AnsiColor::Blue.on_default() | styling::Effects::BOLD) @@ -377,22 +396,9 @@ pub fn build_cli_nocomplete() -> Command { .subcommand(cmd_pred) .subcommand(cmd_stats) .subcommand(cmd_accuracy) + .subcommand(cmd_complete) } -/// Generate cli argument parser. -pub fn build_cli() -> Command { - let labout = "Write shell completion script to stdout\n\n\ - You should redirect the output to a file that will be sourced by your shell\n\ - For example: `emlop complete bash > ~/.bash_completion.d/emlop`\n\ - To apply the changes, either restart you shell or `source` the generated file"; - let shell = Arg::new("shell").help("Target shell") - .required(true) - .value_parser(value_parser!(clap_complete::Shell)); - let cmd = Command::new("complete").about("Generate shell completion script") - .long_about(labout) - .arg(shell); - build_cli_nocomplete().subcommand(cmd) -} #[cfg(test)] mod test { diff --git a/src/main.rs b/src/main.rs index 9f51af7..9012528 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,7 +17,7 @@ fn main() { Ok(Configs::Stats(gc, sc)) => commands::cmd_stats(&gc, &sc), Ok(Configs::Predict(gc, sc)) => commands::cmd_predict(&gc, &sc), Ok(Configs::Accuracy(gc, sc)) => commands::cmd_accuracy(&gc, &sc), - Ok(Configs::Complete(sc)) => commands::cmd_complete(&sc), + Ok(Configs::Complete(gc, sc)) => commands::cmd_complete(&gc, &sc), Err(e) => Err(e), }; match res { diff --git a/src/parse/history.rs b/src/parse/history.rs index 4f6e583..81cdab1 100644 --- a/src/parse/history.rs +++ b/src/parse/history.rs @@ -168,7 +168,7 @@ fn filter_ts(min: Option, max: Option) -> Result<(i64, i64), Error> { fmt_utctime(b)) }, } - Ok((min.unwrap_or(std::i64::MIN), max.unwrap_or(std::i64::MAX))) + Ok((min.unwrap_or(i64::MIN), max.unwrap_or(i64::MAX))) } /// Matches package/repo depending on options. @@ -484,7 +484,7 @@ mod tests { #[test] /// Filtering by timestamp fn parse_hist_filter_ts() { - let (umin, umax, fmin, fmax) = (std::i64::MIN, std::i64::MAX, 1517609348, 1520891098); + let (umin, umax, fmin, fmax) = (i64::MIN, i64::MAX, 1517609348, 1520891098); #[rustfmt::skip] let t = vec![(Some(umin), None, 889, 832, 832, 832, 326, 150), (Some(fmin), None, 889, 832, 832, 832, 326, 150), diff --git a/src/table.rs b/src/table.rs index 3fc1292..a4d3947 100644 --- a/src/table.rs +++ b/src/table.rs @@ -53,17 +53,17 @@ impl<'a, const N: usize> Table<'a, N> { last: usize::MAX } } /// Specify column alignment - pub fn align_left(mut self, col: usize) -> Self { + pub const fn align_left(mut self, col: usize) -> Self { self.aligns[col] = Align::Left; self } /// Specify column left margin (1st printted column never has a left margin) - pub fn margin(mut self, col: usize, margin: &'static str) -> Self { + pub const fn margin(mut self, col: usize, margin: &'static str) -> Self { self.margins[col] = margin; self } /// Specify column left margin (1st printted column never has a left margin) - pub fn last(mut self, last: usize) -> Self { + pub const fn last(mut self, last: usize) -> Self { self.last = last; self } @@ -249,8 +249,8 @@ mod test { let mut t = Table::<2>::new(&conf).align_left(0); t.row([&[&"123"], &[&1]]); t.row([&[&conf.merge, &1, &conf.dur, &2, &conf.cnt, &3, &conf.clr], &[&1]]); - let res = "123 1\x1B[0m\n\ - \x1B[1;32m1\x1B[1;35m2\x1B[2;33m3\x1B[0m 1\x1B[0m\n"; + let res = "123 1\x1B[m\n\ + \x1B[1;32m1\x1B[1;35m2\x1B[2;33m3\x1B[m 1\x1B[m\n"; let (l1, l2) = res.split_once('\n').expect("two lines"); assert_eq!(Ansi::strip(l1, 100), "123 1"); assert_eq!(Ansi::strip(l1, 100), Ansi::strip(l2, 100));