diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml index 5b7e83ac6844932ca5d227f2f30756d5108ee9f4..d12326fe5edbecf94abb3ab0d1de3de467110e19 100644 --- a/.github/workflows/audit.yml +++ b/.github/workflows/audit.yml @@ -1,49 +1,26 @@ name: Security audit - -permissions: - contents: read - on: pull_request: paths: - '**/Cargo.toml' - '**/Cargo.lock' push: - branches: - - main - -env: - RUST_BACKTRACE: 1 - CARGO_TERM_COLOR: always - CLICOLOR: 1 - + paths: + - '**/Cargo.toml' + - '**/Cargo.lock' + schedule: + - cron: '3 3 3 * *' +permissions: + contents: read jobs: security_audit: permissions: issues: write # to create issues (actions-rs/audit-check) checks: write # to create check (actions-rs/audit-check) runs-on: ubuntu-latest - # Prevent sudden announcement of a new advisory from failing ci: - continue-on-error: true steps: - name: Checkout repository uses: actions/checkout@v3 - uses: actions-rs/audit-check@v1 with: token: ${{ secrets.GITHUB_TOKEN }} - - cargo_deny: - permissions: - issues: write # to create issues (actions-rs/audit-check) - checks: write # to create check (actions-rs/audit-check) - runs-on: ubuntu-latest - strategy: - matrix: - checks: - - bans licenses sources - steps: - - uses: actions/checkout@v3 - - uses: EmbarkStudios/cargo-deny-action@v1 - with: - command: check ${{ matrix.checks }} - rust-version: stable diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5d88fb8b029766762394e2e78c1f607ec8b4866b..63eec09e0982591ba8d99ec594898f2e74706157 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,7 +13,7 @@ jobs: permissions: contents: none name: CI - needs: [test, check, docs, rustfmt, clippy, cffconvert] + needs: [test, check, docs, rustfmt, clippy] runs-on: ubuntu-latest steps: - name: Done @@ -187,15 +187,3 @@ jobs: run: make clippy-full - name: Lint (release) run: make clippy-release - cffconvert: - name: cffconvert - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@v3 - with: - persist-credentials: false - - name: CFF validation - uses: citation-file-format/cffconvert-github-action@2.0.0 - with: - args: --validate diff --git a/BUILD.gn b/BUILD.gn index 207b380fca290156441421b784c32f47e904dd88..8f3b110b1fac9b22b6dba44b84971f2fa2525911 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -20,7 +20,7 @@ ohos_cargo_crate("lib") { sources = [ "src/lib.rs" ] edition = "2021" - cargo_pkg_version = "4.1.13" + cargo_pkg_version = "4.1.4" cargo_pkg_name = "clap" cargo_pkg_description = "A simple to use, efficient, and full-featured Command Line Argument Parser" deps = [ @@ -49,7 +49,7 @@ ohos_cargo_crate("stdio_fixture") { sources = [ "src/bin/stdio-fixture.rs" ] edition = "2021" - cargo_pkg_version = "4.1.13" + cargo_pkg_version = "4.1.4" cargo_pkg_name = "clap" cargo_pkg_description = "A simple to use, efficient, and full-featured Command Line Argument Parser" deps = [ diff --git a/CHANGELOG.md b/CHANGELOG.md index 913d9440aef68ba48d5efaf869b029e16d4f5b3c..bdcf3ad26058945698f969b7ed5deb02fb54cfdc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,65 +18,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] - ReleaseDate -## [4.1.13] - 2023-03-18 - -### Performance - -- Reduce repeated alloc calls when building a `Command` -- Reduce duplicate dependencies for faster builds - -## [4.1.12] - 2023-03-18 - -### Internal - -- *(derive)* Update to `syn` v2 - -### Performance - -- *(derive)* Faster build times by dropping `proc-macro-error` dependency - -## [4.1.11] - 2023-03-17 - -### Internal - -- Update `bitflags` - -## [4.1.10] - 2023-03-17 - -### Fixes - -- *(help)* On Windows, avoid underlined text artifacts - -## [4.1.9] - 2023-03-16 - -### Fixes - -- *(assert)* Improve the assert when using the wrong action with `get_count` / `get_flag` - -## [4.1.8] - 2023-02-27 - -### Fixes - -- *(derive)* Don't `deny` lints on the users behalf - -## [4.1.7] - 2023-02-27 - -### Fixes - -- *(derive)* Hide some nightly clippy warnings - -## [4.1.6] - 2023-02-15 - -### Fixes - -- *(help)* Don't show long help for `--help` just because hidden possible values include a description - -## [4.1.5] - 2023-02-15 - -### Fixes - -- *(help)* Don't show long help for `--help` just because a hidden arg has a possible value with a description - ## [4.1.4] - 2023-01-24 ### Fixes @@ -4178,16 +4119,7 @@ Minimum version of Rust is now v1.13.0 (Stable) * **arg** allow lifetimes other than 'static in arguments ([9e8c1fb9](https://github.com/clap-rs/clap/commit/9e8c1fb9406f8448873ca58bab07fe905f1551e5)) -[Unreleased]: https://github.com/clap-rs/clap/compare/v4.1.13...HEAD -[4.1.13]: https://github.com/clap-rs/clap/compare/v4.1.12...v4.1.13 -[4.1.12]: https://github.com/clap-rs/clap/compare/v4.1.11...v4.1.12 -[4.1.11]: https://github.com/clap-rs/clap/compare/v4.1.10...v4.1.11 -[4.1.10]: https://github.com/clap-rs/clap/compare/v4.1.9...v4.1.10 -[4.1.9]: https://github.com/clap-rs/clap/compare/v4.1.8...v4.1.9 -[4.1.8]: https://github.com/clap-rs/clap/compare/v4.1.7...v4.1.8 -[4.1.7]: https://github.com/clap-rs/clap/compare/v4.1.6...v4.1.7 -[4.1.6]: https://github.com/clap-rs/clap/compare/v4.1.5...v4.1.6 -[4.1.5]: https://github.com/clap-rs/clap/compare/v4.1.4...v4.1.5 +[Unreleased]: https://github.com/clap-rs/clap/compare/v4.1.4...HEAD [4.1.4]: https://github.com/clap-rs/clap/compare/v4.1.3...v4.1.4 [4.1.3]: https://github.com/clap-rs/clap/compare/v4.1.2...v4.1.3 [4.1.2]: https://github.com/clap-rs/clap/compare/v4.1.1...v4.1.2 diff --git a/CITATION.cff b/CITATION.cff deleted file mode 100644 index 888945012ce49ed9e67a0e21c9a5981913e300c8..0000000000000000000000000000000000000000 --- a/CITATION.cff +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Parser settings. -cff-version: 1.2.0 -message: Please cite this crate using these information. - -# Version information. -date-released: 2023-03-18 -version: 4.1.13 - -# Project information. -abstract: A full featured, fast Command Line Argument Parser for Rust -authors: - - alias: kbknapp - family-names: Knapp - given-names: Kevin B. - - name: The Clap Community -license: - - Apache-2.0 - - MIT -repository-artifact: https://crates.io/crates/clap -repository-code: https://github.com/clap-rs/clap -title: clap -url: https://docs.rs/clap diff --git a/Cargo.lock b/Cargo.lock index 8032cdf403351c13d2b536399488789f2cf2ad6d..5cbab71b17413bcbea6e63502cfcb68fd5e3dbf0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.19.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" +checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" dependencies = [ "gimli", ] @@ -23,46 +23,6 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" -[[package]] -name = "anstream" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd0982309face56a044e935a18bbffcddeb1ce72e69a3ecc3bafb56d4e959f37" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-wincon", - "concolor-override", - "concolor-query", - "is-terminal", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453bc2a7b261f8c4d1ce5b2c6c222d648d00988d30315e4911fbddc4ddf8983c" - -[[package]] -name = "anstyle-parse" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7d1bb534e9efed14f3e5f44e7dd1a4f709384023a4165199a4241e18dff0116" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-wincon" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3127af6145b149f3287bb9a0d10ad9c5692dba8c53ad48285e5bec4063834fa" -dependencies = [ - "anstyle", - "windows-sys 0.45.0", -] - [[package]] name = "atty" version = "0.2.14" @@ -82,9 +42,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.67" +version = "0.3.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" +checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7" dependencies = [ "addr2line", "cc", @@ -95,15 +55,6 @@ dependencies = [ "rustc-demangle", ] -[[package]] -name = "basic-toml" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e819b667739967cd44d308b8c7b71305d8bb0729ac44a248aa08f33d01950b4" -dependencies = [ - "serde", -] - [[package]] name = "bitflags" version = "1.3.2" @@ -175,12 +126,12 @@ dependencies = [ [[package]] name = "clap" -version = "4.1.13" +version = "4.1.4" dependencies = [ "backtrace", "bitflags", "clap_derive", - "clap_lex 0.3.3", + "clap_lex 0.3.1", "humantime", "is-terminal", "once_cell", @@ -202,17 +153,17 @@ dependencies = [ name = "clap_bench" version = "0.0.0" dependencies = [ - "clap 4.1.13", + "clap 4.1.4", "criterion", "lazy_static", ] [[package]] name = "clap_complete" -version = "4.1.5" +version = "4.1.1" dependencies = [ - "clap 4.1.13", - "clap_lex 0.3.3", + "clap 4.1.4", + "clap_lex 0.3.1", "is_executable", "os_str_bytes", "pathdiff", @@ -224,21 +175,22 @@ dependencies = [ [[package]] name = "clap_complete_fig" -version = "4.1.2" +version = "4.1.0" dependencies = [ - "clap 4.1.13", + "clap 4.1.4", "clap_complete", "snapbox", ] [[package]] name = "clap_derive" -version = "4.1.12" +version = "4.1.0" dependencies = [ "heck", + "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.8", + "syn", ] [[package]] @@ -252,34 +204,36 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.3.3" +version = "0.3.1" dependencies = [ "os_str_bytes", ] [[package]] name = "clap_mangen" -version = "0.2.10" +version = "0.2.7" dependencies = [ - "clap 4.1.13", + "clap 4.1.4", "roff", "snapbox", ] [[package]] -name = "concolor-override" -version = "1.0.0" +name = "concolor" +version = "0.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a855d4a1978dc52fb0536a04d384c2c0c1aa273597f08b77c8c4d3b2eec6037f" +checksum = "318d6c16e73b3a900eb212ad6a82fc7d298c5ab8184c7a9998646455bc474a16" +dependencies = [ + "bitflags", + "concolor-query", + "is-terminal", +] [[package]] name = "concolor-query" -version = "0.3.3" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d11d52c3d7ca2e6d0040212be9e4dbbcd78b6447f535b6b561f449427944cf" -dependencies = [ - "windows-sys 0.45.0", -] +checksum = "82a90734b3d5dcf656e7624cca6bce9c3a90ee11f900e80141a7427ccfb3d317" [[package]] name = "criterion" @@ -401,9 +355,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.27.2" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" +checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" [[package]] name = "glob" @@ -440,9 +394,12 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.1" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] [[package]] name = "humantime" @@ -477,19 +434,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46112a93252b123d31a119a8d1a1ac19deac4fac6e0e8b0df58f0d4e5870e63c" dependencies = [ "libc", - "windows-sys 0.42.0", + "windows-sys", ] [[package]] name = "is-terminal" -version = "0.4.4" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b6b32576413a8e69b90e952e4a026476040d81017b80445deda5f2d3921857" +checksum = "927609f78c2913a6f6ac3c27a4fe87f43e2a35367c0c4b0f8265e8f49a104330" dependencies = [ - "hermit-abi 0.3.1", + "hermit-abi 0.2.6", "io-lifetimes", "rustix", - "windows-sys 0.45.0", + "windows-sys", ] [[package]] @@ -569,13 +526,22 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.6.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc" dependencies = [ "adler", ] +[[package]] +name = "nom8" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8" +dependencies = [ + "memchr", +] + [[package]] name = "normalize-line-endings" version = "0.3.0" @@ -603,9 +569,9 @@ dependencies = [ [[package]] name = "object" -version = "0.30.3" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" +checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" dependencies = [ "memchr", ] @@ -672,20 +638,44 @@ dependencies = [ "plotters-backend", ] +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + [[package]] name = "proc-macro2" -version = "1.0.53" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba466839c78239c09faf015484e5cc04860f88242cff4d03eb038f04b4699b73" +checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.26" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" dependencies = [ "proc-macro2", ] @@ -752,14 +742,14 @@ dependencies = [ "io-lifetimes", "libc", "linux-raw-sys", - "windows-sys 0.42.0", + "windows-sys", ] [[package]] name = "rustversion" -version = "1.0.12" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06" +checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8" [[package]] name = "ryu" @@ -784,22 +774,22 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "serde" -version = "1.0.158" +version = "1.0.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771d4d9c4163ee138805e12c710dd365e4f44be8be0503cb1bb9eb989425d9c9" +checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.158" +version = "1.0.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e801c1712f48475582b7696ac71e0ca34ebb30e09338425384269d9717c62cad" +checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852" dependencies = [ "proc-macro2", "quote", - "syn 2.0.8", + "syn", ] [[package]] @@ -813,15 +803,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_spanned" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0efd8caf556a6cebd3b285caf480045fcc1ac04f6bd786b09a6f11af30c4fcf4" -dependencies = [ - "serde", -] - [[package]] name = "shlex" version = "1.1.0" @@ -836,30 +817,26 @@ checksum = "62ac7f900db32bf3fd12e0117dd3dc4da74bc52ebaac97f39668446d89694803" [[package]] name = "snapbox" -version = "0.4.10" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9615402f9cff539301119bdf2c2f328739cf2b45c2116666618fb6ac399f75bb" +checksum = "34eced5a65e76d5a00047986a83c65f80dc666faa27b5138f331659e2ca6bcf5" dependencies = [ - "anstream", - "anstyle", - "escargot", + "concolor", "libc", "normalize-line-endings", "os_pipe", "similar", "snapbox-macros", "wait-timeout", - "windows-sys 0.45.0", + "windows-sys", + "yansi", ] [[package]] name = "snapbox-macros" -version = "0.3.3" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8e40c667388ed1cb5060f545d0013bf0a23efdfa6c5c3e9ef592de391cd860f" -dependencies = [ - "anstream", -] +checksum = "485e65c1203eb37244465e857d15a26d3a85a5410648ccb53b18bd44cb3a7336" [[package]] name = "static_assertions" @@ -875,20 +852,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.8" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcc02725fd69ab9f26eab07fad303e2497fad6fb9eba4f96c4d1687bdf704ad9" +checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" dependencies = [ "proc-macro2", "quote", @@ -911,7 +877,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb20089a8ba2b69debd491f8d2d023761cbf196e999218c591fa1e7e15a21907" dependencies = [ "rustix", - "windows-sys 0.42.0", + "windows-sys", ] [[package]] @@ -930,49 +896,59 @@ dependencies = [ "serde_json", ] +[[package]] +name = "toml" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" +dependencies = [ + "serde", +] + [[package]] name = "toml_datetime" -version = "0.6.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622" +checksum = "808b51e57d0ef8f71115d8f3a01e7d3750d01c79cac4b3eda910f4389fdf92fd" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.19.4" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a1eb0622d28f4b9c90adc4ea4b2b46b47663fde9ac5fafcb14a1369d5508825" +checksum = "a34cc558345efd7e88b9eda9626df2138b80bb46a7606f695e751c892bc7dac6" dependencies = [ "indexmap", + "itertools", + "nom8", "serde", - "serde_spanned", "toml_datetime", - "winnow", ] [[package]] name = "trybuild" -version = "1.0.77" +version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44da5a6f2164c8e14d3bbc0657d69c5966af9f5f6930d4f600b1f5c4a673413" +checksum = "ed01de3de062db82c0920b5cabe804f88d599a3f217932292597c678c903754d" dependencies = [ - "basic-toml", "glob", "once_cell", "serde", "serde_derive", "serde_json", "termcolor", + "toml", ] [[package]] name = "trycmd" -version = "0.14.15" +version = "0.14.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32564b3f936a9ebedf5cc07dcf1e7e661204766d35f92c03bf347b099d84e783" +checksum = "8a050cd97463d2f8df73e65b122dadb7f04ea31f0bd53a1306ea915cbb156849" dependencies = [ + "escargot", "glob", "humantime", "humantime-serde", @@ -1035,9 +1011,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.8" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" [[package]] name = "unicode-width" @@ -1051,12 +1027,6 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" -[[package]] -name = "utf8parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" - [[package]] name = "version_check" version = "0.9.4" @@ -1104,7 +1074,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 1.0.109", + "syn", "wasm-bindgen-shared", ] @@ -1126,7 +1096,7 @@ checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -1193,77 +1163,50 @@ dependencies = [ "windows_x86_64_msvc", ] -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.42.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" +checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" [[package]] name = "windows_aarch64_msvc" -version = "0.42.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" +checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" [[package]] name = "windows_i686_gnu" -version = "0.42.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" +checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" [[package]] name = "windows_i686_msvc" -version = "0.42.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" +checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" [[package]] name = "windows_x86_64_gnu" -version = "0.42.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" +checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" +checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" [[package]] name = "windows_x86_64_msvc" -version = "0.42.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" +checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" [[package]] -name = "winnow" -version = "0.3.3" +name = "yansi" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faf09497b8f8b5ac5d3bb4d05c0a99be20f26fd3d5f2db7b0716e946d5103658" -dependencies = [ - "memchr", -] +checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" diff --git a/Cargo.toml b/Cargo.toml index efce9d36544399507bed5e82432c1bb4e4f638c9..7fc4c57de4d274291cb1c4afc8b54bb7c28447ad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ include = [ [package] name = "clap" -version = "4.1.13" +version = "4.1.4" description = "A simple to use, efficient, and full-featured Command Line Argument Parser" repository = "https://github.com/clap-rs/clap" categories = ["command-line-interface"] @@ -57,8 +57,6 @@ pre-release-replacements = [ {file="CHANGELOG.md", search="ReleaseDate", replace="{{date}}", min=1}, {file="CHANGELOG.md", search="", replace="\n## [Unreleased] - ReleaseDate\n", exactly=1}, {file="CHANGELOG.md", search="", replace="\n[Unreleased]: https://github.com/clap-rs/clap/compare/{{tag_name}}...HEAD", exactly=1}, - {file="CITATION.cff", search="^date-released: ....-..-..", replace="date-released: {{date}}"}, - {file="CITATION.cff", search="^version: .+\\..+\\..+", replace="version: {{version}}"}, ] [features] @@ -99,25 +97,25 @@ unstable-v5 = ["clap_derive?/unstable-v5", "deprecated"] bench = false [dependencies] -clap_derive = { path = "./clap_derive", version = "=4.1.12", optional = true } +clap_derive = { path = "./clap_derive", version = "=4.1.0", optional = true } clap_lex = { path = "./clap_lex", version = "0.3.0" } -bitflags = "1.2.0" -unicase = { version = "2.6.0", optional = true } -strsim = { version = "0.10.0", optional = true } +bitflags = "1.2" +unicase = { version = "2.6", optional = true } +strsim = { version = "0.10", optional = true } is-terminal = { version = "0.4.1", optional = true } termcolor = { version = "1.1.1", optional = true } terminal_size = { version = "0.2.1", optional = true } -backtrace = { version = "0.3.67", optional = true } +backtrace = { version = "0.3", optional = true } unicode-width = { version = "0.1.9", optional = true } once_cell = { version = "1.12.0", optional = true } [dev-dependencies] -trybuild = "1.0.77" -rustversion = "1.0.12" +trybuild = "1.0.73" +rustversion = "1" # Cutting out `filesystem` feature -trycmd = { version = "0.14.15", default-features = false, features = ["color-auto", "diff", "examples"] } -humantime = "2.1.0" -snapbox = "0.4.10" +trycmd = { version = "0.14.9", default-features = false, features = ["color-auto", "diff", "examples"] } +humantime = "2" +snapbox = "0.4" shlex = "1.1.0" static_assertions = "1.1.0" unic-emoji-char = "0.9.0" diff --git a/README.OpenSource b/README.OpenSource index e0abba69876825cc77a60b145c0a4db0a3ca7a37..a099ac5a239ace78a15c066f96da792e7a148f3c 100644 --- a/README.OpenSource +++ b/README.OpenSource @@ -3,7 +3,7 @@ "Name": "clap", "License": "Apache license 2.0, MIT", "License File": "LICENSE-MIT, LICENSE-APACHE", - "Version Number": "v4.1.13", + "Version Number": "v4.1.4", "Owner": "fangting12@huawei.com", "Upstream URL": "https://github.com/clap-rs/clap", "Description": "A command-line argument parsing library for Rust that supports subcommands and complex argument parsing." diff --git a/clap_bench/Cargo.toml b/clap_bench/Cargo.toml index 6ea656c92a9ab0fa9daf370c71fb3e272693242b..d53d23a36a1829f516134929b2f1305b5349af3d 100644 --- a/clap_bench/Cargo.toml +++ b/clap_bench/Cargo.toml @@ -14,7 +14,7 @@ release = false [dev-dependencies] clap = { path = "../", version = "4.0.0", default-features = false, features = ["std", "help"] } criterion = "0.4.0" -lazy_static = "1.4.0" +lazy_static = "1" [[bench]] harness = false diff --git a/clap_complete/CHANGELOG.md b/clap_complete/CHANGELOG.md index 14a6504a6e3f6cd5fbe8a546ab766d52adc4e9b2..55d489584c88ed54bfa9713b18817c746e04f5e7 100644 --- a/clap_complete/CHANGELOG.md +++ b/clap_complete/CHANGELOG.md @@ -7,22 +7,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] - ReleaseDate -## [4.1.5] - 2023-03-16 - -## [4.1.4] - 2023-02-27 - -### Features - -- *(zsh)* Allow sourcing completion - -## [4.1.3] - 2023-02-23 - -### Fixes - -- *(zsh)* Improve handling of multi-valued arguments - -## [4.1.2] - 2023-02-15 - ## [4.1.1] - 2023-01-23 ### Fixes @@ -125,11 +109,7 @@ MSRV changed to 1.64.0 ## [3.0.1] - 2022-01-03 -[Unreleased]: https://github.com/clap-rs/clap/compare/clap_complete-v4.1.5...HEAD -[4.1.5]: https://github.com/clap-rs/clap/compare/clap_complete-v4.1.4...clap_complete-v4.1.5 -[4.1.4]: https://github.com/clap-rs/clap/compare/clap_complete-v4.1.3...clap_complete-v4.1.4 -[4.1.3]: https://github.com/clap-rs/clap/compare/clap_complete-v4.1.2...clap_complete-v4.1.3 -[4.1.2]: https://github.com/clap-rs/clap/compare/clap_complete-v4.1.1...clap_complete-v4.1.2 +[Unreleased]: https://github.com/clap-rs/clap/compare/clap_complete-v4.1.1...HEAD [4.1.1]: https://github.com/clap-rs/clap/compare/clap_complete-v4.1.0...clap_complete-v4.1.1 [4.1.0]: https://github.com/clap-rs/clap/compare/clap_complete-v4.0.7...clap_complete-v4.1.0 [4.0.7]: https://github.com/clap-rs/clap/compare/clap_complete-v4.0.6...clap_complete-v4.0.7 diff --git a/clap_complete/Cargo.toml b/clap_complete/Cargo.toml index a8c41616bb49e730a399416bdab448b605679ddd..94a18d324367a3d5ed1cef5c107a0cc4857c951f 100644 --- a/clap_complete/Cargo.toml +++ b/clap_complete/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clap_complete" -version = "4.1.5" +version = "4.1.1" description = "Generate shell completion scripts for your clap::Command" repository = "https://github.com/clap-rs/clap/tree/master/clap_complete" categories = ["command-line-interface"] @@ -35,15 +35,15 @@ bench = false clap = { path = "../", version = "4.1.0", default-features = false, features = ["std"] } clap_lex = { path = "../clap_lex", version = "0.3.0", optional = true } is_executable = { version = "1.0.1", optional = true } -os_str_bytes = { version = "6.0.0", default-features = false, features = ["raw_os_str"], optional = true } +os_str_bytes = { version = "6.0", default-features = false, features = ["raw_os_str"], optional = true } pathdiff = { version = "0.2.1", optional = true } shlex = { version = "1.1.0", optional = true } unicode-xid = { version = "0.2.2", optional = true } [dev-dependencies] -snapbox = { version = "0.4.10", features = ["diff"] } +snapbox = { version = "0.4", features = ["diff"] } # Cutting out `filesystem` feature -trycmd = { version = "0.14.15", default-features = false, features = ["color-auto", "diff", "examples"] } +trycmd = { version = "0.14.6", default-features = false, features = ["color-auto", "diff", "examples"] } clap = { path = "../", version = "4.0.0", default-features = false, features = ["std", "derive", "help"] } [[example]] diff --git a/clap_complete/README.md b/clap_complete/README.md index 75233b61f4226e45e6003a998ba80f9f01b08dd9..e500809f78470a44e3e188ca90c855a04cfcb3a2 100644 --- a/clap_complete/README.md +++ b/clap_complete/README.md @@ -5,16 +5,16 @@ [![Crates.io](https://img.shields.io/crates/v/clap_complete?style=flat-square)](https://crates.io/crates/clap_complete) [![Crates.io](https://img.shields.io/crates/d/clap_complete?style=flat-square)](https://crates.io/crates/clap_complete) -[![License](https://img.shields.io/badge/license-Apache%202.0-blue?style=flat-square)](https://github.com/clap-rs/clap/blob/clap_complete-v4.1.5/LICENSE-APACHE) -[![License](https://img.shields.io/badge/license-MIT-blue?style=flat-square)](https://github.com/clap-rs/clap/blob/clap_complete-v4.1.5/LICENSE-MIT) +[![License](https://img.shields.io/badge/license-Apache%202.0-blue?style=flat-square)](https://github.com/clap-rs/clap/blob/clap_complete-v4.1.1/LICENSE-APACHE) +[![License](https://img.shields.io/badge/license-MIT-blue?style=flat-square)](https://github.com/clap-rs/clap/blob/clap_complete-v4.1.1/LICENSE-MIT) Dual-licensed under [Apache 2.0](LICENSE-APACHE) or [MIT](LICENSE-MIT). 1. [About](#about) 2. [API Reference](https://docs.rs/clap_complete) 3. [Questions & Discussions](https://github.com/clap-rs/clap/discussions) -4. [CONTRIBUTING](https://github.com/clap-rs/clap/blob/clap_complete-v4.1.5/clap_complete/CONTRIBUTING.md) -5. [Sponsors](https://github.com/clap-rs/clap/blob/clap_complete-v4.1.5/README.md#sponsors) +4. [CONTRIBUTING](https://github.com/clap-rs/clap/blob/clap_complete-v4.1.1/clap_complete/CONTRIBUTING.md) +5. [Sponsors](https://github.com/clap-rs/clap/blob/clap_complete-v4.1.1/README.md#sponsors) ## About diff --git a/clap_complete/examples/completion-derive.rs b/clap_complete/examples/completion-derive.rs index 6b90f0a58adf20c4f07ba2b4afefd05437518547..8eeebf89d469ce04f8ea062d58d308b2c6f7acad 100644 --- a/clap_complete/examples/completion-derive.rs +++ b/clap_complete/examples/completion-derive.rs @@ -24,7 +24,7 @@ struct Opt { // If provided, outputs the completion file for given shell #[arg(long = "generate", value_enum)] generator: Option, - #[command(subcommand)] + #[clap(subcommand)] command: Option, } @@ -75,9 +75,9 @@ fn main() { if let Some(generator) = opt.generator { let mut cmd = Opt::command(); - eprintln!("Generating completion file for {generator:?}..."); + eprintln!("Generating completion file for {:?}...", generator); print_completions(generator, &mut cmd); } else { - println!("{opt:#?}"); + println!("{:#?}", opt); } } diff --git a/clap_complete/examples/completion.rs b/clap_complete/examples/completion.rs index 70487b3b91fb09585b7b483d5f990343364b65b7..0455d4f9c1f9bf33b0dc284f37c8a2cbcbf0ab35 100644 --- a/clap_complete/examples/completion.rs +++ b/clap_complete/examples/completion.rs @@ -103,7 +103,7 @@ fn main() { if let Some(generator) = matches.get_one::("generator") { let mut cmd = build_cli(); - eprintln!("Generating completion file for {generator}..."); + eprintln!("Generating completion file for {}...", generator); print_completions(*generator, &mut cmd); } } diff --git a/clap_complete/src/shells/bash.rs b/clap_complete/src/shells/bash.rs index b66634098f6eecbfc77795a3978ec79b9593b00a..df9557611ec8b6c04c6b1a013e7f9d0bf9746c62 100644 --- a/clap_complete/src/shells/bash.rs +++ b/clap_complete/src/shells/bash.rs @@ -10,7 +10,7 @@ pub struct Bash; impl Generator for Bash { fn file_name(&self, name: &str) -> String { - format!("{name}.bash") + format!("{}.bash", name) } fn generate(&self, cmd: &Command, buf: &mut dyn Write) { @@ -114,6 +114,9 @@ fn all_subcommands(cmd: &Command) -> String { "{parent_fn_name},{name}) cmd=\"{fn_name}\" ;;", + parent_fn_name = parent_fn_name, + name = name, + fn_name = fn_name, )); } @@ -218,10 +221,10 @@ fn all_options_for_path(cmd: &Command, path: &str) -> String { let mut opts = String::new(); for short in utils::shorts_and_visible_aliases(p) { - write!(&mut opts, "-{short} ").unwrap(); + write!(&mut opts, "-{} ", short).unwrap(); } for long in utils::longs_and_visible_aliases(p) { - write!(&mut opts, "--{long} ").unwrap(); + write!(&mut opts, "--{} ", long).unwrap(); } for pos in p.get_positionals() { if let Some(vals) = utils::possible_values(pos) { @@ -229,11 +232,11 @@ fn all_options_for_path(cmd: &Command, path: &str) -> String { write!(&mut opts, "{} ", value.get_name()).unwrap(); } } else { - write!(&mut opts, "{pos} ").unwrap(); + write!(&mut opts, "{} ", pos).unwrap(); } } for (sc, _) in utils::subcommands(p) { - write!(&mut opts, "{sc} ").unwrap(); + write!(&mut opts, "{} ", sc).unwrap(); } opts.pop(); diff --git a/clap_complete/src/shells/elvish.rs b/clap_complete/src/shells/elvish.rs index 48a0f852bbf36d79d0110e49ec879bda9fc66079..07da28348021d4413d8e00729e6535af15775177 100644 --- a/clap_complete/src/shells/elvish.rs +++ b/clap_complete/src/shells/elvish.rs @@ -12,7 +12,7 @@ pub struct Elvish; impl Generator for Elvish { fn file_name(&self, name: &str) -> String { - format!("{name}.elv") + format!("{}.elv", name) } fn generate(&self, cmd: &Command, buf: &mut dyn Write) { @@ -46,6 +46,8 @@ set edit:completion:arg-completer[{bin_name}] = {{|@words| $completions[$command] }} "#, + bin_name = bin_name, + subcommands_cases = subcommands_cases ); w!(buf, result.as_bytes()); @@ -81,7 +83,7 @@ fn generate_inner(p: &Command, previous_command_name: &str) -> String { let tooltip = get_tooltip(option.get_help(), shorts[0]); for short in shorts { completions.push_str(&preamble); - completions.push_str(format!("-{short} '{tooltip}'").as_str()); + completions.push_str(format!("-{} '{}'", short, tooltip).as_str()); } } @@ -89,7 +91,7 @@ fn generate_inner(p: &Command, previous_command_name: &str) -> String { let tooltip = get_tooltip(option.get_help(), longs[0]); for long in longs { completions.push_str(&preamble); - completions.push_str(format!("--{long} '{tooltip}'").as_str()); + completions.push_str(format!("--{} '{}'", long, tooltip).as_str()); } } } @@ -99,7 +101,7 @@ fn generate_inner(p: &Command, previous_command_name: &str) -> String { let tooltip = get_tooltip(flag.get_help(), shorts[0]); for short in shorts { completions.push_str(&preamble); - completions.push_str(format!("-{short} '{tooltip}'").as_str()); + completions.push_str(format!("-{} '{}'", short, tooltip).as_str()); } } @@ -107,7 +109,7 @@ fn generate_inner(p: &Command, previous_command_name: &str) -> String { let tooltip = get_tooltip(flag.get_help(), longs[0]); for long in longs { completions.push_str(&preamble); - completions.push_str(format!("--{long} '{tooltip}'").as_str()); + completions.push_str(format!("--{} '{}'", long, tooltip).as_str()); } } } @@ -117,7 +119,7 @@ fn generate_inner(p: &Command, previous_command_name: &str) -> String { let tooltip = get_tooltip(subcommand.get_about(), data); completions.push_str(&preamble); - completions.push_str(format!("{data} '{tooltip}'").as_str()); + completions.push_str(format!("{} '{}'", data, tooltip).as_str()); } let mut subcommands_cases = format!( diff --git a/clap_complete/src/shells/fish.rs b/clap_complete/src/shells/fish.rs index 77a72f7ebde826b28aa5a9b0098689cd356da4c4..fd2f3a4f80abb9752ba865e782e9c23a82629bff 100644 --- a/clap_complete/src/shells/fish.rs +++ b/clap_complete/src/shells/fish.rs @@ -12,7 +12,7 @@ pub struct Fish; impl Generator for Fish { fn file_name(&self, name: &str) -> String { - format!("{name}.fish") + format!("{}.fish", name) } fn generate(&self, cmd: &Command, buf: &mut dyn Write) { @@ -56,7 +56,7 @@ fn gen_fish_inner( // -n "__fish_use_subcommand" # complete for command "myprog" // -n "__fish_seen_subcommand_from subcmd1" # complete for command "myprog subcmd1" - let mut basic_template = format!("complete -c {root_command}"); + let mut basic_template = format!("complete -c {}", root_command); if parent_commands.is_empty() { if cmd.has_subcommands() { @@ -68,10 +68,10 @@ fn gen_fish_inner( " -n \"{}\"", parent_commands .iter() - .map(|command| format!("__fish_seen_subcommand_from {command}")) + .map(|command| format!("__fish_seen_subcommand_from {}", command)) .chain( cmd.get_subcommands() - .map(|command| format!("not __fish_seen_subcommand_from {command}")) + .map(|command| format!("not __fish_seen_subcommand_from {}", command)) ) .collect::>() .join("; and ") @@ -87,7 +87,7 @@ fn gen_fish_inner( if let Some(shorts) = option.get_short_and_visible_aliases() { for short in shorts { - template.push_str(format!(" -s {short}").as_str()); + template.push_str(format!(" -s {}", short).as_str()); } } @@ -113,7 +113,7 @@ fn gen_fish_inner( if let Some(shorts) = flag.get_short_and_visible_aliases() { for short in shorts { - template.push_str(format!(" -s {short}").as_str()); + template.push_str(format!(" -s {}", short).as_str()); } } diff --git a/clap_complete/src/shells/powershell.rs b/clap_complete/src/shells/powershell.rs index 92467d53c8490b873177dba1e70c7cbdb3f24e54..0d3a2a55f734a4d105791c1cc023c347641002ec 100644 --- a/clap_complete/src/shells/powershell.rs +++ b/clap_complete/src/shells/powershell.rs @@ -12,7 +12,7 @@ pub struct PowerShell; impl Generator for PowerShell { fn file_name(&self, name: &str) -> String { - format!("_{name}.ps1") + format!("_{}.ps1", name) } fn generate(&self, cmd: &Command, buf: &mut dyn Write) { diff --git a/clap_complete/src/shells/shell.rs b/clap_complete/src/shells/shell.rs index 52cb2e9b741ee5e39e4ec9a1400c91cbbcc97e0a..4ae4a79ce9ffeecdf1a0ef2ec523738342682f66 100644 --- a/clap_complete/src/shells/shell.rs +++ b/clap_complete/src/shells/shell.rs @@ -42,7 +42,7 @@ impl FromStr for Shell { return Ok(*variant); } } - Err(format!("invalid variant: {s}")) + Err(format!("invalid variant: {}", s)) } } diff --git a/clap_complete/src/shells/zsh.rs b/clap_complete/src/shells/zsh.rs index a41eb8856e2b2d73693a0cd606d41c61098a8c47..15a9ed126dc97d2a2ec22f47d554f62c9a4c3b78 100644 --- a/clap_complete/src/shells/zsh.rs +++ b/clap_complete/src/shells/zsh.rs @@ -11,7 +11,7 @@ pub struct Zsh; impl Generator for Zsh { fn file_name(&self, name: &str) -> String { - format!("_{name}") + format!("_{}", name) } fn generate(&self, cmd: &Command, buf: &mut dyn Write) { @@ -43,11 +43,7 @@ _{name}() {{ {subcommand_details} -if [ \"$funcstack[1]\" = \"_{name}\" ]; then - _{name} \"$@\" -else - compdef _{name} {name} -fi +_{name} \"$@\" ", name = bin_name, initial_args = get_args_of(cmd, None), @@ -115,8 +111,8 @@ _{bin_name_underscore}_commands() {{ all_subcommands.sort(); all_subcommands.dedup(); - for (_, ref bin_name) in &all_subcommands { - debug!("subcommand_details:iter: bin_name={bin_name}"); + for &(_, ref bin_name) in &all_subcommands { + debug!("subcommand_details:iter: bin_name={}", bin_name); ret.push(format!( "\ @@ -227,12 +223,14 @@ fn get_subcommands_of(parent: &Command) -> String { let subcommand_names = utils::subcommands(parent); let mut all_subcommands = vec![]; - for (ref name, ref bin_name) in &subcommand_names { + for &(ref name, ref bin_name) in &subcommand_names { debug!( - "get_subcommands_of:iter: parent={}, name={name}, bin_name={bin_name}", + "get_subcommands_of:iter: parent={}, name={}, bin_name={}", parent.get_name(), + name, + bin_name, ); - let mut segments = vec![format!("({name})")]; + let mut segments = vec![format!("({})", name)]; let subcommand_args = get_args_of( parser_of(parent, bin_name).expect(INTERNAL_ERROR_MSG), Some(parent), @@ -460,8 +458,8 @@ fn write_opts_of(p: &Command, p_global: Option<&Command>) -> String { Some(val) => val[0].to_string(), }; let vc = match value_completion(o) { - Some(val) => format!(":{vn}:{val}"), - None => format!(":{vn}: "), + Some(val) => format!(":{}:{}", vn, val), + None => format!(":{}: ", vn), }; let vc = vc.repeat(o.get_num_args().expect("built").min_values()); @@ -504,11 +502,11 @@ fn arg_conflicts(cmd: &Command, arg: &Arg, app_global: Option<&Command>) -> Stri fn push_conflicts(conflicts: &[&Arg], res: &mut Vec) { for conflict in conflicts { if let Some(s) = conflict.get_short() { - res.push(format!("-{s}")); + res.push(format!("-{}", s)); } if let Some(l) = conflict.get_long() { - res.push(format!("--{l}")); + res.push(format!("--{}", l)); } } } @@ -570,7 +568,13 @@ fn write_flags_of(p: &Command, p_global: Option<&Command>) -> String { if let Some(short_aliases) = f.get_visible_short_aliases() { for alias in short_aliases { - let s = format!("'{conflicts}{multiple}-{alias}[{help}]' \\",); + let s = format!( + "'{conflicts}{multiple}-{arg}[{help}]' \\", + multiple = multiple, + conflicts = conflicts, + arg = alias, + help = help + ); debug!("write_flags_of:iter: Wrote...{}", &*s); @@ -618,46 +622,18 @@ fn write_positionals_of(p: &Command) -> String { let mut ret = vec![]; - // Completions for commands that end with two Vec arguments require special care. - // - You can have two Vec args separated with a custom value terminator. - // - You can have two Vec args with the second one set to last (raw sets last) - // which will require a '--' separator to be used before the second argument - // on the command-line. - // - // We use the '-S' _arguments option to disable completion after '--'. Thus, the - // completion for the second argument in scenario (B) does not need to be emitted - // because it is implicitly handled by the '-S' option. - // We only need to emit the first catch-all. - // - // Have we already emitted a catch-all multi-valued positional argument - // without a custom value terminator? - let mut catch_all_emitted = false; - for arg in p.get_positionals() { debug!("write_positionals_of:iter: arg={}", arg.get_id()); let num_args = arg.get_num_args().expect("built"); - let is_multi_valued = num_args.max_values() > 1; - - if catch_all_emitted && (arg.is_last_set() || is_multi_valued) { - // This is the final argument and it also takes multiple arguments. - // We've already emitted a catch-all positional argument so we don't need - // to emit anything for this argument because it is implicitly handled by - // the use of the '-S' _arguments option. - continue; - } - let cardinality_value; - let cardinality = if is_multi_valued { + let cardinality = if num_args.max_values() > 1 { match arg.get_value_terminator() { Some(terminator) => { cardinality_value = format!("*{}:", escape_value(terminator)); cardinality_value.as_str() } - None => { - catch_all_emitted = true; - "*:" - } + None => "*:", } } else if !arg.is_required_set() { ":" diff --git a/clap_complete/tests/bash.rs b/clap_complete/tests/bash.rs index a331da84a5b044702fd4ebdf8f97414350a5fd4e..d01651f26cd018142198b38490333374025e7f74 100644 --- a/clap_complete/tests/bash.rs +++ b/clap_complete/tests/bash.rs @@ -111,15 +111,3 @@ fn register_minimal() { .action_env("SNAPSHOTS") .matches_path("tests/snapshots/register_minimal.bash", buf); } - -#[test] -fn two_multi_valued_arguments() { - let name = "my-app"; - let cmd = common::two_multi_valued_arguments_command(name); - common::assert_matches_path( - "tests/snapshots/two_multi_valued_arguments.bash", - clap_complete::shells::Bash, - cmd, - name, - ); -} diff --git a/clap_complete/tests/common.rs b/clap_complete/tests/common.rs index eef2e71a0bbbef0663110d34136d21f3ea2702fb..3f8cb437764d2bc3e4ba7a3f12836451c7083867 100644 --- a/clap_complete/tests/common.rs +++ b/clap_complete/tests/common.rs @@ -261,20 +261,6 @@ pub fn value_terminator_command(name: &'static str) -> clap::Command { ) } -pub fn two_multi_valued_arguments_command(name: &'static str) -> clap::Command { - clap::Command::new(name) - .arg( - clap::Arg::new("first") - .help("first multi-valued argument") - .num_args(1..), - ) - .arg( - clap::Arg::new("second") - .help("second multi-valued argument") - .raw(true), - ) -} - pub fn assert_matches_path( expected_path: impl AsRef, gen: impl clap_complete::Generator, diff --git a/clap_complete/tests/elvish.rs b/clap_complete/tests/elvish.rs index c2a82fc97c6f3c6315ace34aaf544343de28ddf1..26075a67ac19da3fd14eae4da0835235d3a78914 100644 --- a/clap_complete/tests/elvish.rs +++ b/clap_complete/tests/elvish.rs @@ -95,15 +95,3 @@ fn value_terminator() { name, ); } - -#[test] -fn two_multi_valued_arguments() { - let name = "my-app"; - let cmd = common::two_multi_valued_arguments_command(name); - common::assert_matches_path( - "tests/snapshots/two_multi_valued_arguments.elvish", - clap_complete::shells::Elvish, - cmd, - name, - ); -} diff --git a/clap_complete/tests/fish.rs b/clap_complete/tests/fish.rs index b5bfae1508775e81c5d1f2d9bac6abb7b02122fd..9393ed699aaf49ec12b24e88481f9712da5c8f60 100644 --- a/clap_complete/tests/fish.rs +++ b/clap_complete/tests/fish.rs @@ -95,15 +95,3 @@ fn value_terminator() { name, ); } - -#[test] -fn two_multi_valued_arguments() { - let name = "my-app"; - let cmd = common::two_multi_valued_arguments_command(name); - common::assert_matches_path( - "tests/snapshots/two_multi_valued_arguments.fish", - clap_complete::shells::Fish, - cmd, - name, - ); -} diff --git a/clap_complete/tests/powershell.rs b/clap_complete/tests/powershell.rs index 2de4a05efd625e68aa2fe7a3594896f73044a7d0..1f18618b7d22b326b3f6540ce0e4772086af00d7 100644 --- a/clap_complete/tests/powershell.rs +++ b/clap_complete/tests/powershell.rs @@ -95,15 +95,3 @@ fn value_terminator() { name, ); } - -#[test] -fn two_multi_valued_arguments() { - let name = "my-app"; - let cmd = common::two_multi_valued_arguments_command(name); - common::assert_matches_path( - "tests/snapshots/two_multi_valued_arguments.ps1", - clap_complete::shells::PowerShell, - cmd, - name, - ); -} diff --git a/clap_complete/tests/snapshots/aliases.zsh b/clap_complete/tests/snapshots/aliases.zsh index 63764e56191d14eef487dd667ae8f170bb456c12..403bbfe864dcd8994cb8ca7bf088d431d4f8ac1f 100644 --- a/clap_complete/tests/snapshots/aliases.zsh +++ b/clap_complete/tests/snapshots/aliases.zsh @@ -37,8 +37,4 @@ _my-app_commands() { _describe -t commands 'my-app commands' commands "$@" } -if [ "$funcstack[1]" = "_my-app" ]; then - _my-app "$@" -else - compdef _my-app my-app -fi +_my-app "$@" diff --git a/clap_complete/tests/snapshots/basic.zsh b/clap_complete/tests/snapshots/basic.zsh index 408bb7e4b8d4ed33d04c69c71a13aa038e050f22..217ed938643ff4c1aa7794e1d645e23339497ec0 100644 --- a/clap_complete/tests/snapshots/basic.zsh +++ b/clap_complete/tests/snapshots/basic.zsh @@ -97,8 +97,4 @@ _my-app__test_commands() { _describe -t commands 'my-app test commands' commands "$@" } -if [ "$funcstack[1]" = "_my-app" ]; then - _my-app "$@" -else - compdef _my-app my-app -fi +_my-app "$@" diff --git a/clap_complete/tests/snapshots/feature_sample.zsh b/clap_complete/tests/snapshots/feature_sample.zsh index 72b85e11fff3fe9af5a7bac5a75f872a6eba93c3..3b4a7b64b534e33e0b489d2e92b7396dfcdb8da2 100644 --- a/clap_complete/tests/snapshots/feature_sample.zsh +++ b/clap_complete/tests/snapshots/feature_sample.zsh @@ -104,8 +104,4 @@ _my-app__test_commands() { _describe -t commands 'my-app test commands' commands "$@" } -if [ "$funcstack[1]" = "_my-app" ]; then - _my-app "$@" -else - compdef _my-app my-app -fi +_my-app "$@" diff --git a/clap_complete/tests/snapshots/quoting.zsh b/clap_complete/tests/snapshots/quoting.zsh index 95ed7eb697d04a136980080fd40732e5c9076c99..4afe4438a726583270c24be26f76b9be4932c3f9 100644 --- a/clap_complete/tests/snapshots/quoting.zsh +++ b/clap_complete/tests/snapshots/quoting.zsh @@ -211,8 +211,4 @@ _my-app__help__help_commands() { _describe -t commands 'my-app help help commands' commands "$@" } -if [ "$funcstack[1]" = "_my-app" ]; then - _my-app "$@" -else - compdef _my-app my-app -fi +_my-app "$@" diff --git a/clap_complete/tests/snapshots/special_commands.zsh b/clap_complete/tests/snapshots/special_commands.zsh index 67d04bdae4b901f5624b556e5bf7f2ca69605cc9..42023be705c6cb64ab2a154acea9a47a363c8b45 100644 --- a/clap_complete/tests/snapshots/special_commands.zsh +++ b/clap_complete/tests/snapshots/special_commands.zsh @@ -178,8 +178,4 @@ _my-app__test_commands() { _describe -t commands 'my-app test commands' commands "$@" } -if [ "$funcstack[1]" = "_my-app" ]; then - _my-app "$@" -else - compdef _my-app my-app -fi +_my-app "$@" diff --git a/clap_complete/tests/snapshots/sub_subcommands.zsh b/clap_complete/tests/snapshots/sub_subcommands.zsh index 720e72f12784bdcc159620e96eaf51ea601574d8..7a14feb555985c9b191a1171367345d50f75a9b8 100644 --- a/clap_complete/tests/snapshots/sub_subcommands.zsh +++ b/clap_complete/tests/snapshots/sub_subcommands.zsh @@ -224,8 +224,4 @@ _my-app__test_commands() { _describe -t commands 'my-app test commands' commands "$@" } -if [ "$funcstack[1]" = "_my-app" ]; then - _my-app "$@" -else - compdef _my-app my-app -fi +_my-app "$@" diff --git a/clap_complete/tests/snapshots/two_multi_valued_arguments.bash b/clap_complete/tests/snapshots/two_multi_valued_arguments.bash deleted file mode 100644 index 4e6e33c4558e8fcf4b21c6f231733e95e27c7215..0000000000000000000000000000000000000000 --- a/clap_complete/tests/snapshots/two_multi_valued_arguments.bash +++ /dev/null @@ -1,38 +0,0 @@ -_my-app() { - local i cur prev opts cmd - COMPREPLY=() - cur="${COMP_WORDS[COMP_CWORD]}" - prev="${COMP_WORDS[COMP_CWORD-1]}" - cmd="" - opts="" - - for i in ${COMP_WORDS[@]} - do - case "${cmd},${i}" in - ",$1") - cmd="my__app" - ;; - *) - ;; - esac - done - - case "${cmd}" in - my__app) - opts="-h --help [first]... [second]..." - if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then - COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) - return 0 - fi - case "${prev}" in - *) - COMPREPLY=() - ;; - esac - COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) - return 0 - ;; - esac -} - -complete -F _my-app -o bashdefault -o default my-app diff --git a/clap_complete/tests/snapshots/two_multi_valued_arguments.elvish b/clap_complete/tests/snapshots/two_multi_valued_arguments.elvish deleted file mode 100644 index 89b26e0005a03e6897e2dabe4adaf0457f65a596..0000000000000000000000000000000000000000 --- a/clap_complete/tests/snapshots/two_multi_valued_arguments.elvish +++ /dev/null @@ -1,26 +0,0 @@ - -use builtin; -use str; - -set edit:completion:arg-completer[my-app] = {|@words| - fn spaces {|n| - builtin:repeat $n ' ' | str:join '' - } - fn cand {|text desc| - edit:complex-candidate $text &display=$text' '(spaces (- 14 (wcswidth $text)))$desc - } - var command = 'my-app' - for word $words[1..-1] { - if (str:has-prefix $word '-') { - break - } - set command = $command';'$word - } - var completions = [ - &'my-app'= { - cand -h 'Print help' - cand --help 'Print help' - } - ] - $completions[$command] -} diff --git a/clap_complete/tests/snapshots/two_multi_valued_arguments.fish b/clap_complete/tests/snapshots/two_multi_valued_arguments.fish deleted file mode 100644 index a33c671acf51aa624924ff5dbf2970bd2ac4ba49..0000000000000000000000000000000000000000 --- a/clap_complete/tests/snapshots/two_multi_valued_arguments.fish +++ /dev/null @@ -1 +0,0 @@ -complete -c my-app -s h -l help -d 'Print help' diff --git a/clap_complete/tests/snapshots/two_multi_valued_arguments.ps1 b/clap_complete/tests/snapshots/two_multi_valued_arguments.ps1 deleted file mode 100644 index 30262afe031daaf910c85e7efdb694ef67e9f941..0000000000000000000000000000000000000000 --- a/clap_complete/tests/snapshots/two_multi_valued_arguments.ps1 +++ /dev/null @@ -1,32 +0,0 @@ - -using namespace System.Management.Automation -using namespace System.Management.Automation.Language - -Register-ArgumentCompleter -Native -CommandName 'my-app' -ScriptBlock { - param($wordToComplete, $commandAst, $cursorPosition) - - $commandElements = $commandAst.CommandElements - $command = @( - 'my-app' - for ($i = 1; $i -lt $commandElements.Count; $i++) { - $element = $commandElements[$i] - if ($element -isnot [StringConstantExpressionAst] -or - $element.StringConstantType -ne [StringConstantType]::BareWord -or - $element.Value.StartsWith('-') -or - $element.Value -eq $wordToComplete) { - break - } - $element.Value - }) -join ';' - - $completions = @(switch ($command) { - 'my-app' { - [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help') - [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help') - break - } - }) - - $completions.Where{ $_.CompletionText -like "$wordToComplete*" } | - Sort-Object -Property ListItemText -} diff --git a/clap_complete/tests/snapshots/two_multi_valued_arguments.zsh b/clap_complete/tests/snapshots/two_multi_valued_arguments.zsh deleted file mode 100644 index a20088ea2a097f64fd43923d9b8d2b291bc02616..0000000000000000000000000000000000000000 --- a/clap_complete/tests/snapshots/two_multi_valued_arguments.zsh +++ /dev/null @@ -1,34 +0,0 @@ -#compdef my-app - -autoload -U is-at-least - -_my-app() { - typeset -A opt_args - typeset -a _arguments_options - local ret=1 - - if is-at-least 5.2; then - _arguments_options=(-s -S -C) - else - _arguments_options=(-s -C) - fi - - local context curcontext="$curcontext" state line - _arguments "${_arguments_options[@]}" \ -'-h[Print help]' \ -'--help[Print help]' \ -'*::first -- first multi-valued argument:' \ -&& ret=0 -} - -(( $+functions[_my-app_commands] )) || -_my-app_commands() { - local commands; commands=() - _describe -t commands 'my-app commands' commands "$@" -} - -if [ "$funcstack[1]" = "_my-app" ]; then - _my-app "$@" -else - compdef _my-app my-app -fi diff --git a/clap_complete/tests/snapshots/value_hint.zsh b/clap_complete/tests/snapshots/value_hint.zsh index c3a97f754b59a89cd5b914f0be40511e34baafec..15892dd7f087e4fd7ee92415d52f5482a53a1ced 100644 --- a/clap_complete/tests/snapshots/value_hint.zsh +++ b/clap_complete/tests/snapshots/value_hint.zsh @@ -47,8 +47,4 @@ _my-app_commands() { _describe -t commands 'my-app commands' commands "$@" } -if [ "$funcstack[1]" = "_my-app" ]; then - _my-app "$@" -else - compdef _my-app my-app -fi +_my-app "$@" diff --git a/clap_complete/tests/snapshots/value_terminator.zsh b/clap_complete/tests/snapshots/value_terminator.zsh index fe819420f82501ee48ec5660d405a93f2cd369e1..656d8ea182ed4a52d46652e61cc4b885b9d7449c 100644 --- a/clap_complete/tests/snapshots/value_terminator.zsh +++ b/clap_complete/tests/snapshots/value_terminator.zsh @@ -27,8 +27,4 @@ _my-app_commands() { _describe -t commands 'my-app commands' commands "$@" } -if [ "$funcstack[1]" = "_my-app" ]; then - _my-app "$@" -else - compdef _my-app my-app -fi +_my-app "$@" diff --git a/clap_complete/tests/zsh.rs b/clap_complete/tests/zsh.rs index f90a7b80ce0a9c742131799f20aa79da8390473a..57040bde465899790df6b675bb6bc9acbb8e3318 100644 --- a/clap_complete/tests/zsh.rs +++ b/clap_complete/tests/zsh.rs @@ -95,15 +95,3 @@ fn value_terminator() { name, ); } - -#[test] -fn two_multi_valued_arguments() { - let name = "my-app"; - let cmd = common::two_multi_valued_arguments_command(name); - common::assert_matches_path( - "tests/snapshots/two_multi_valued_arguments.zsh", - clap_complete::shells::Zsh, - cmd, - name, - ); -} diff --git a/clap_complete_fig/CHANGELOG.md b/clap_complete_fig/CHANGELOG.md index 6685284918bcc1761fb2538206f36c143c109635..5b331afc96bf6d0099941332cd662ec521afcf38 100644 --- a/clap_complete_fig/CHANGELOG.md +++ b/clap_complete_fig/CHANGELOG.md @@ -7,10 +7,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] - ReleaseDate -## [4.1.2] - 2023-03-16 - -## [4.1.1] - 2023-02-15 - ## [4.1.0] - 2023-01-13 ### Compatibility @@ -67,9 +63,7 @@ MSRV changed to 1.64.0 ## [3.0.1] - 2022-01-03 -[Unreleased]: https://github.com/clap-rs/clap/compare/clap_complete_fig-v4.1.2...HEAD -[4.1.2]: https://github.com/clap-rs/clap/compare/clap_complete_fig-v4.1.1...clap_complete_fig-v4.1.2 -[4.1.1]: https://github.com/clap-rs/clap/compare/clap_complete_fig-v4.1.0...clap_complete_fig-v4.1.1 +[Unreleased]: https://github.com/clap-rs/clap/compare/clap_complete_fig-v4.1.0...HEAD [4.1.0]: https://github.com/clap-rs/clap/compare/clap_complete_fig-v4.0.2...clap_complete_fig-v4.1.0 [4.0.2]: https://github.com/clap-rs/clap/compare/clap_complete_fig-v4.0.1...clap_complete_fig-v4.0.2 [4.0.1]: https://github.com/clap-rs/clap/compare/clap_complete_fig-v4.0.0...clap_complete_fig-v4.0.1 diff --git a/clap_complete_fig/Cargo.toml b/clap_complete_fig/Cargo.toml index de9659eb697a3cf46f5489851e2fad11d807047f..be90f65e9abc54fcb38a25b09f695879a5585124 100644 --- a/clap_complete_fig/Cargo.toml +++ b/clap_complete_fig/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clap_complete_fig" -version = "4.1.2" +version = "4.1.0" description = "A generator library used with clap for Fig completion scripts" repository = "https://github.com/clap-rs/clap/tree/master/clap_complete_fig" categories = ["command-line-interface"] @@ -35,5 +35,5 @@ clap = { path = "../", version = "4.0.0", default-features = false, features = [ clap_complete = { path = "../clap_complete", version = "4.0.0" } [dev-dependencies] -snapbox = { version = "0.4.10", features = ["diff"] } +snapbox = { version = "0.4", features = ["diff"] } clap = { path = "../", version = "4.0.0", default-features = false, features = ["std", "help"] } diff --git a/clap_complete_fig/src/fig.rs b/clap_complete_fig/src/fig.rs index 07fb8a136c83b416a04b1d3688771523154b6036..6a81afaf6f5bdf5581605a77b74ffa8871bc6f57 100644 --- a/clap_complete_fig/src/fig.rs +++ b/clap_complete_fig/src/fig.rs @@ -11,7 +11,7 @@ pub struct Fig; impl Generator for Fig { fn file_name(&self, name: &str) -> String { - format!("{name}.ts") + format!("{}.ts", name) } fn generate(&self, cmd: &Command, buf: &mut dyn std::io::Write) { @@ -267,11 +267,11 @@ fn gen_options(cmd: &Command, indent: usize) -> String { let mut flags = vec![]; if let Some(shorts) = flag.get_short_and_visible_aliases() { - flags.extend(shorts.iter().map(|s| format!("-{s}"))); + flags.extend(shorts.iter().map(|s| format!("-{}", s))); } if let Some(longs) = flag.get_long_and_visible_aliases() { - flags.extend(longs.iter().map(|s| format!("--{s}"))); + flags.extend(longs.iter().map(|s| format!("--{}", s))); } if flags.len() > 1 { diff --git a/clap_derive/BUILD.gn b/clap_derive/BUILD.gn index c9e7955fd37dd15ef4305cf7ada9297659c872fb..f9328ca7d307fd33d43008f417b8e52a1c620cac 100644 --- a/clap_derive/BUILD.gn +++ b/clap_derive/BUILD.gn @@ -14,20 +14,20 @@ import("//build/ohos.gni") ohos_cargo_crate("lib") { - crate_name = "clap_derive" - crate_type = "proc-macro" - crate_root = "src/lib.rs" + crate_name = "clap_derive" + crate_type = "proc-macro" + crate_root = "src/lib.rs" - sources = [ "src/lib.rs" ] - edition = "2021" - cargo_pkg_version = "4.1.12" - cargo_pkg_name = "clap_derive" - cargo_pkg_description = - "Parse command line argument by defining a struct, derive crate." - deps = [ - "//third_party/rust/crates/heck:lib", - "//third_party/rust/crates/proc-macro2:lib", - "//third_party/rust/crates/quote:lib", - "//third_party/rust/crates/syn:lib", - ] + sources = ["src/lib.rs"] + edition = "2021" + cargo_pkg_version = "4.1.0" + cargo_pkg_name = "clap_derive" + cargo_pkg_description = "Parse command line argument by defining a struct, derive crate." + deps = [ + "//third_party/rust/crates/heck:lib", + "//third_party/rust/crates/proc-macro2:lib", + "//third_party/rust/crates/proc-macro-error:lib", + "//third_party/rust/crates/quote:lib", + "//third_party/rust/crates/syn:lib", + ] } diff --git a/clap_derive/Cargo.toml b/clap_derive/Cargo.toml index 782859a24e9bb3b2e6e9c8d7c65652739db9f6a4..7f721079ea82ce144267a92e2d732bbf0bda4d2f 100644 --- a/clap_derive/Cargo.toml +++ b/clap_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clap_derive" -version = "4.1.12" +version = "4.1.0" description = "Parse command line argument by defining a struct, derive crate." repository = "https://github.com/clap-rs/clap/tree/master/clap_derive" categories = ["command-line-interface", "development-tools::procedural-macro-helpers"] @@ -29,10 +29,11 @@ proc-macro = true bench = false [dependencies] -syn = { version = "2.0.8", features = ["full"] } +syn = { version = "1.0.74", features = ["full"] } quote = "1.0.9" proc-macro2 = "1.0.42" heck = "0.4.0" +proc-macro-error = "1" [features] default = [] diff --git a/clap_derive/src/attr.rs b/clap_derive/src/attr.rs index 3bc9ac0140d0e4f33f199f85077ab4a3c8d44fe1..e282a8f94eddec3b362a171a2659dbe4a292c46c 100644 --- a/clap_derive/src/attr.rs +++ b/clap_derive/src/attr.rs @@ -1,6 +1,8 @@ use std::iter::FromIterator; use proc_macro2::TokenStream; +use proc_macro_error::abort; +use proc_macro_error::ResultExt; use quote::quote; use quote::ToTokens; use syn::spanned::Spanned; @@ -22,44 +24,49 @@ pub struct ClapAttr { } impl ClapAttr { - pub fn parse_all(all_attrs: &[Attribute]) -> Result, syn::Error> { - let mut parsed = Vec::new(); - for attr in all_attrs { - let kind = if attr.path().is_ident("clap") { - Sp::new(AttrKind::Clap, attr.path().span()) - } else if attr.path().is_ident("structopt") { - Sp::new(AttrKind::StructOpt, attr.path().span()) - } else if attr.path().is_ident("command") { - Sp::new(AttrKind::Command, attr.path().span()) - } else if attr.path().is_ident("group") { - Sp::new(AttrKind::Group, attr.path().span()) - } else if attr.path().is_ident("arg") { - Sp::new(AttrKind::Arg, attr.path().span()) - } else if attr.path().is_ident("value") { - Sp::new(AttrKind::Value, attr.path().span()) - } else { - continue; - }; - for mut attr in - attr.parse_args_with(Punctuated::::parse_terminated)? - { - attr.kind = kind; - parsed.push(attr); - } - } - Ok(parsed) + pub fn parse_all(all_attrs: &[Attribute]) -> Vec { + all_attrs + .iter() + .filter_map(|attr| { + let kind = if attr.path.is_ident("clap") { + Some(Sp::new(AttrKind::Clap, attr.path.span())) + } else if attr.path.is_ident("structopt") { + Some(Sp::new(AttrKind::StructOpt, attr.path.span())) + } else if attr.path.is_ident("command") { + Some(Sp::new(AttrKind::Command, attr.path.span())) + } else if attr.path.is_ident("group") { + Some(Sp::new(AttrKind::Group, attr.path.span())) + } else if attr.path.is_ident("arg") { + Some(Sp::new(AttrKind::Arg, attr.path.span())) + } else if attr.path.is_ident("value") { + Some(Sp::new(AttrKind::Value, attr.path.span())) + } else { + None + }; + kind.map(|k| (k, attr)) + }) + .flat_map(|(k, attr)| { + attr.parse_args_with(Punctuated::::parse_terminated) + .unwrap_or_abort() + .into_iter() + .map(move |mut a| { + a.kind = k; + a + }) + }) + .collect() } - pub fn value_or_abort(&self) -> Result<&AttrValue, syn::Error> { + pub fn value_or_abort(&self) -> &AttrValue { self.value .as_ref() - .ok_or_else(|| format_err!(self.name, "attribute `{}` requires a value", self.name)) + .unwrap_or_else(|| abort!(self.name, "attribute `{}` requires a value", self.name)) } - pub fn lit_str_or_abort(&self) -> Result<&LitStr, syn::Error> { - let value = self.value_or_abort()?; + pub fn lit_str_or_abort(&self) -> &LitStr { + let value = self.value_or_abort(); match value { - AttrValue::LitStr(tokens) => Ok(tokens), + AttrValue::LitStr(tokens) => tokens, AttrValue::Expr(_) | AttrValue::Call(_) => { abort!( self.name, @@ -126,7 +133,7 @@ impl Parse for ClapAttr { let nested; parenthesized!(nested in input); - let method_args: Punctuated<_, _> = nested.parse_terminated(Expr::parse, Token![,])?; + let method_args: Punctuated<_, Token![,]> = nested.parse_terminated(Expr::parse)?; Some(AttrValue::Call(Vec::from_iter(method_args))) } else { None diff --git a/clap_derive/src/derives/args.rs b/clap_derive/src/derives/args.rs index ab2ce319270373e3be4122a9de7f9ec731d0b182..b5d51bfca397d4058d0a88cff0f40b0ea08b315e 100644 --- a/clap_derive/src/derives/args.rs +++ b/clap_derive/src/derives/args.rs @@ -13,6 +13,7 @@ // MIT/Apache 2.0 license. use proc_macro2::{Ident, Span, TokenStream}; +use proc_macro_error::{abort, abort_call_site}; use quote::{format_ident, quote, quote_spanned}; use syn::ext::IdentExt; use syn::{ @@ -20,27 +21,30 @@ use syn::{ Fields, Generics, }; +use crate::dummies; use crate::item::{Item, Kind, Name}; use crate::utils::{inner_type, sub_type, Sp, Ty}; -pub fn derive_args(input: &DeriveInput) -> Result { +pub fn derive_args(input: &DeriveInput) -> TokenStream { let ident = &input.ident; + dummies::args(ident); + match input.data { Data::Struct(DataStruct { fields: Fields::Named(ref fields), .. }) => { let name = Name::Derived(ident.clone()); - let item = Item::from_args_struct(input, name)?; + let item = Item::from_args_struct(input, name); let fields = fields .named .iter() .map(|field| { - let item = Item::from_args_field(field, item.casing(), item.env_casing())?; - Ok((field, item)) + let item = Item::from_args_field(field, item.casing(), item.env_casing()); + (field, item) }) - .collect::, syn::Error>>()?; + .collect::>(); gen_for_struct(&item, ident, &input.generics, &fields) } Data::Struct(DataStruct { @@ -48,15 +52,15 @@ pub fn derive_args(input: &DeriveInput) -> Result { .. }) => { let name = Name::Derived(ident.clone()); - let item = Item::from_args_struct(input, name)?; + let item = Item::from_args_struct(input, name); let fields = Punctuated::::new(); let fields = fields .iter() .map(|field| { - let item = Item::from_args_field(field, item.casing(), item.env_casing())?; - Ok((field, item)) + let item = Item::from_args_field(field, item.casing(), item.env_casing()); + (field, item) }) - .collect::, syn::Error>>()?; + .collect::>(); gen_for_struct(&item, ident, &input.generics, &fields) } _ => abort_call_site!("`#[derive(Args)]` only supports non-tuple structs"), @@ -68,7 +72,7 @@ pub fn gen_for_struct( item_name: &Ident, generics: &Generics, fields: &[(&Field, Item)], -) -> Result { +) -> TokenStream { if !matches!(&*item.kind(), Kind::Command(_)) { abort! { item.kind().span(), "`{}` cannot be used with `command`", @@ -78,13 +82,13 @@ pub fn gen_for_struct( let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); - let constructor = gen_constructor(fields)?; - let updater = gen_updater(fields, true)?; + let constructor = gen_constructor(fields); + let updater = gen_updater(fields, true); let raw_deprecated = raw_deprecated(); let app_var = Ident::new("__clap_app", Span::call_site()); - let augmentation = gen_augment(fields, &app_var, item, false)?; - let augmentation_update = gen_augment(fields, &app_var, item, true)?; + let augmentation = gen_augment(fields, &app_var, item, false); + let augmentation_update = gen_augment(fields, &app_var, item, true); let group_id = if item.skip_group() { quote!(None) @@ -93,7 +97,7 @@ pub fn gen_for_struct( quote!(Some(clap::Id::from(#group_id))) }; - Ok(quote! { + quote! { #[allow(dead_code, unreachable_code, unused_variables, unused_braces)] #[allow( clippy::style, @@ -105,8 +109,8 @@ pub fn gen_for_struct( clippy::nursery, clippy::cargo, clippy::suspicious_else_formatting, - clippy::almost_swapped, )] + #[deny(clippy::correctness)] impl #impl_generics clap::FromArgMatches for #item_name #ty_generics #where_clause { fn from_arg_matches(__clap_arg_matches: &clap::ArgMatches) -> ::std::result::Result { Self::from_arg_matches_mut(&mut __clap_arg_matches.clone()) @@ -140,8 +144,8 @@ pub fn gen_for_struct( clippy::nursery, clippy::cargo, clippy::suspicious_else_formatting, - clippy::almost_swapped, )] + #[deny(clippy::correctness)] impl #impl_generics clap::Args for #item_name #ty_generics #where_clause { fn group_id() -> Option { #group_id @@ -153,7 +157,7 @@ pub fn gen_for_struct( #augmentation_update } } - }) + } } /// Generate a block of code to add arguments/subcommands corresponding to @@ -163,12 +167,11 @@ pub fn gen_augment( app_var: &Ident, parent_item: &Item, override_required: bool, -) -> Result { +) -> TokenStream { let mut subcommand_specified = false; - let mut args = Vec::new(); - for (field, item) in fields { + let args = fields.iter().filter_map(|(field, item)| { let kind = item.kind(); - let genned = match &*kind { + match &*kind { Kind::Command(_) | Kind::Value | Kind::Skip(_, _) @@ -176,10 +179,7 @@ pub fn gen_augment( | Kind::ExternalSubcommand => None, Kind::Subcommand(ty) => { if subcommand_specified { - abort!( - field.span(), - "`#[command(subcommand)]` can only be used once per container" - ); + abort!(field.span(), "`#[command(subcommand)]` can only be used once per container"); } subcommand_specified = true; @@ -354,9 +354,8 @@ pub fn gen_augment( }); }) } - }; - args.push(genned); - } + } + }); let deprecations = if !override_required { parent_item.deprecations() @@ -409,7 +408,7 @@ pub fn gen_augment( ) ) }; - Ok(quote! {{ + quote! {{ #deprecations let #app_var = #app_var #initial_app_methods @@ -417,15 +416,15 @@ pub fn gen_augment( ; #( #args )* #app_var #final_app_methods - }}) + }} } -pub fn gen_constructor(fields: &[(&Field, Item)]) -> Result { +pub fn gen_constructor(fields: &[(&Field, Item)]) -> TokenStream { let fields = fields.iter().map(|(field, item)| { let field_name = field.ident.as_ref().unwrap(); let kind = item.kind(); let arg_matches = format_ident!("__clap_arg_matches"); - let genned = match &*kind { + match &*kind { Kind::Command(_) | Kind::Value | Kind::ExternalSubcommand => { @@ -520,20 +519,18 @@ pub fn gen_constructor(fields: &[(&Field, Item)]) -> Result { - gen_parsers(item, ty, field_name, field, None)? + gen_parsers(item, ty, field_name, field, None) } - }; - Ok(genned) - }).collect::, syn::Error>>()?; + } + }); - Ok(quote! {{ + quote! {{ #( #fields ),* - }}) + }} } -pub fn gen_updater(fields: &[(&Field, Item)], use_self: bool) -> Result { - let mut genned_fields = Vec::new(); - for (field, item) in fields { +pub fn gen_updater(fields: &[(&Field, Item)], use_self: bool) -> TokenStream { + let fields = fields.iter().map(|(field, item)| { let field_name = field.ident.as_ref().unwrap(); let kind = item.kind(); @@ -547,8 +544,10 @@ pub fn gen_updater(fields: &[(&Field, Item)], use_self: bool) -> Result { + match &*kind { + Kind::Command(_) + | Kind::Value + | Kind::ExternalSubcommand => { abort! { kind.span(), "`{}` cannot be used with `arg`", kind.name(), @@ -618,20 +617,17 @@ pub fn gen_updater(fields: &[(&Field, Item)], use_self: bool) -> Result quote!(), - Kind::Arg(ty) | Kind::FromGlobal(ty) => { - gen_parsers(item, ty, field_name, field, Some(&access))? - } - }; - genned_fields.push(genned); - } + Kind::Arg(ty) | Kind::FromGlobal(ty) => gen_parsers(item, ty, field_name, field, Some(&access)), + } + }); - Ok(quote! { - #( #genned_fields )* - }) + quote! { + #( #fields )* + } } fn gen_parsers( @@ -640,7 +636,7 @@ fn gen_parsers( field_name: &Ident, field: &Field, update: Option<&TokenStream>, -) -> Result { +) -> TokenStream { let span = ty.span(); let convert_type = inner_type(&field.ty); let id = item.id(); @@ -713,7 +709,7 @@ fn gen_parsers( } }; - let genned = if let Some(access) = update { + if let Some(access) = update { quote_spanned! { field.span()=> if #arg_matches.contains_id(#id) { #access @@ -722,8 +718,7 @@ fn gen_parsers( } } else { quote_spanned!(field.span()=> #field_name: #field_value ) - }; - Ok(genned) + } } #[cfg(feature = "raw-deprecated")] diff --git a/clap_derive/src/derives/into_app.rs b/clap_derive/src/derives/into_app.rs index 72f081fd8d1c2a453b73094a11772d552f006cc0..a45667ab29630875c6934467ac7a02867713f933 100644 --- a/clap_derive/src/derives/into_app.rs +++ b/clap_derive/src/derives/into_app.rs @@ -18,11 +18,7 @@ use syn::{Generics, Ident}; use crate::item::Item; -pub fn gen_for_struct( - item: &Item, - item_name: &Ident, - generics: &Generics, -) -> Result { +pub fn gen_for_struct(item: &Item, item_name: &Ident, generics: &Generics) -> TokenStream { let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); let name = item.cased_name(); @@ -40,8 +36,8 @@ pub fn gen_for_struct( clippy::nursery, clippy::cargo, clippy::suspicious_else_formatting, - clippy::almost_swapped, )] + #[deny(clippy::correctness)] impl #impl_generics clap::CommandFactory for #item_name #ty_generics #where_clause { fn command<'b>() -> clap::Command { let #app_var = clap::Command::new(#name); @@ -55,20 +51,16 @@ pub fn gen_for_struct( } }; - Ok(tokens) + tokens } -pub fn gen_for_enum( - item: &Item, - item_name: &Ident, - generics: &Generics, -) -> Result { +pub fn gen_for_enum(item: &Item, item_name: &Ident, generics: &Generics) -> TokenStream { let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); let name = item.cased_name(); let app_var = Ident::new("__clap_app", Span::call_site()); - Ok(quote! { + quote! { #[allow(dead_code, unreachable_code, unused_variables, unused_braces)] #[allow( clippy::style, @@ -80,8 +72,8 @@ pub fn gen_for_enum( clippy::nursery, clippy::cargo, clippy::suspicious_else_formatting, - clippy::almost_swapped, )] + #[deny(clippy::correctness)] impl #impl_generics clap::CommandFactory for #item_name #ty_generics #where_clause { fn command<'b>() -> clap::Command { let #app_var = clap::Command::new(#name) @@ -97,5 +89,5 @@ pub fn gen_for_enum( .arg_required_else_help(false) } } - }) + } } diff --git a/clap_derive/src/derives/parser.rs b/clap_derive/src/derives/parser.rs index 39b0b8a774696f66acf584354b513a88e485c187..617857cacaa4632d6ec0f16bb390d24262910853 100644 --- a/clap_derive/src/derives/parser.rs +++ b/clap_derive/src/derives/parser.rs @@ -13,6 +13,7 @@ // MIT/Apache 2.0 license. use proc_macro2::TokenStream; +use proc_macro_error::abort_call_site; use quote::quote; use syn::Ident; use syn::Variant; @@ -22,10 +23,11 @@ use syn::{ }; use crate::derives::{args, into_app, subcommand}; +use crate::dummies; use crate::item::Item; use crate::item::Name; -pub fn derive_parser(input: &DeriveInput) -> Result { +pub fn derive_parser(input: &DeriveInput) -> TokenStream { let ident = &input.ident; let pkg_name = std::env::var("CARGO_PKG_NAME").ok().unwrap_or_default(); @@ -34,46 +36,52 @@ pub fn derive_parser(input: &DeriveInput) -> Result { fields: Fields::Named(ref fields), .. }) => { + dummies::parser_struct(ident); + let name = Name::Assigned(quote!(#pkg_name)); - let item = Item::from_args_struct(input, name)?; + let item = Item::from_args_struct(input, name); let fields = fields .named .iter() .map(|field| { - let item = Item::from_args_field(field, item.casing(), item.env_casing())?; - Ok((field, item)) + let item = Item::from_args_field(field, item.casing(), item.env_casing()); + (field, item) }) - .collect::, syn::Error>>()?; + .collect::>(); gen_for_struct(&item, ident, &input.generics, &fields) } Data::Struct(DataStruct { fields: Fields::Unit, .. }) => { + dummies::parser_struct(ident); + let name = Name::Assigned(quote!(#pkg_name)); - let item = Item::from_args_struct(input, name)?; + let item = Item::from_args_struct(input, name); let fields = Punctuated::::new(); let fields = fields .iter() .map(|field| { - let item = Item::from_args_field(field, item.casing(), item.env_casing())?; - Ok((field, item)) + let item = Item::from_args_field(field, item.casing(), item.env_casing()); + (field, item) }) - .collect::, syn::Error>>()?; + .collect::>(); gen_for_struct(&item, ident, &input.generics, &fields) } Data::Enum(ref e) => { + dummies::parser_enum(ident); + let name = Name::Assigned(quote!(#pkg_name)); - let item = Item::from_subcommand_enum(input, name)?; + let item = Item::from_subcommand_enum(input, name); let variants = e .variants .iter() .map(|variant| { let item = - Item::from_subcommand_variant(variant, item.casing(), item.env_casing())?; - Ok((variant, item)) + Item::from_subcommand_variant(variant, item.casing(), item.env_casing()); + (variant, item) }) - .collect::, syn::Error>>()?; + .collect::>(); gen_for_enum(&item, ident, &input.generics, &variants) } _ => abort_call_site!("`#[derive(Parser)]` only supports non-tuple structs and enums"), @@ -85,18 +93,18 @@ fn gen_for_struct( item_name: &Ident, generics: &Generics, fields: &[(&Field, Item)], -) -> Result { +) -> TokenStream { let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); - let into_app = into_app::gen_for_struct(item, item_name, generics)?; - let args = args::gen_for_struct(item, item_name, generics, fields)?; + let into_app = into_app::gen_for_struct(item, item_name, generics); + let args = args::gen_for_struct(item, item_name, generics, fields); - Ok(quote! { + quote! { impl #impl_generics clap::Parser for #item_name #ty_generics #where_clause {} #into_app #args - }) + } } fn gen_for_enum( @@ -104,16 +112,16 @@ fn gen_for_enum( item_name: &Ident, generics: &Generics, variants: &[(&Variant, Item)], -) -> Result { +) -> TokenStream { let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); - let into_app = into_app::gen_for_enum(item, item_name, generics)?; - let subcommand = subcommand::gen_for_enum(item, item_name, generics, variants)?; + let into_app = into_app::gen_for_enum(item, item_name, generics); + let subcommand = subcommand::gen_for_enum(item, item_name, generics, variants); - Ok(quote! { + quote! { impl #impl_generics clap::Parser for #item_name #ty_generics #where_clause {} #into_app #subcommand - }) + } } diff --git a/clap_derive/src/derives/subcommand.rs b/clap_derive/src/derives/subcommand.rs index 403fe4557a1c318363d5d6014530a5a9ce4e98c2..8a44e0c42196fd82282eaf97b4e319ba66e460ae 100644 --- a/clap_derive/src/derives/subcommand.rs +++ b/clap_derive/src/derives/subcommand.rs @@ -13,29 +13,33 @@ // MIT/Apache 2.0 license. use proc_macro2::{Ident, Span, TokenStream}; +use proc_macro_error::{abort, abort_call_site}; use quote::{format_ident, quote, quote_spanned}; use syn::{spanned::Spanned, Data, DeriveInput, FieldsUnnamed, Generics, Variant}; use crate::derives::args; +use crate::dummies; use crate::item::{Item, Kind, Name}; use crate::utils::{is_simple_ty, subty_if_name}; -pub fn derive_subcommand(input: &DeriveInput) -> Result { +pub fn derive_subcommand(input: &DeriveInput) -> TokenStream { let ident = &input.ident; + dummies::subcommand(ident); + match input.data { Data::Enum(ref e) => { let name = Name::Derived(ident.clone()); - let item = Item::from_subcommand_enum(input, name)?; + let item = Item::from_subcommand_enum(input, name); let variants = e .variants .iter() .map(|variant| { let item = - Item::from_subcommand_variant(variant, item.casing(), item.env_casing())?; - Ok((variant, item)) + Item::from_subcommand_variant(variant, item.casing(), item.env_casing()); + (variant, item) }) - .collect::, syn::Error>>()?; + .collect::>(); gen_for_enum(&item, ident, &input.generics, &variants) } _ => abort_call_site!("`#[derive(Subcommand)]` only supports enums"), @@ -47,7 +51,7 @@ pub fn gen_for_enum( item_name: &Ident, generics: &Generics, variants: &[(&Variant, Item)], -) -> Result { +) -> TokenStream { if !matches!(&*item.kind(), Kind::Command(_)) { abort! { item.kind().span(), "`{}` cannot be used with `command`", @@ -57,14 +61,14 @@ pub fn gen_for_enum( let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); - let from_arg_matches = gen_from_arg_matches(variants)?; - let update_from_arg_matches = gen_update_from_arg_matches(variants)?; + let from_arg_matches = gen_from_arg_matches(variants); + let update_from_arg_matches = gen_update_from_arg_matches(variants); - let augmentation = gen_augment(variants, item, false)?; - let augmentation_update = gen_augment(variants, item, true)?; - let has_subcommand = gen_has_subcommand(variants)?; + let augmentation = gen_augment(variants, item, false); + let augmentation_update = gen_augment(variants, item, true); + let has_subcommand = gen_has_subcommand(variants); - Ok(quote! { + quote! { #[allow(dead_code, unreachable_code, unused_variables, unused_braces)] #[allow( clippy::style, @@ -76,8 +80,8 @@ pub fn gen_for_enum( clippy::nursery, clippy::cargo, clippy::suspicious_else_formatting, - clippy::almost_swapped, )] + #[deny(clippy::correctness)] impl #impl_generics clap::FromArgMatches for #item_name #ty_generics #where_clause { fn from_arg_matches(__clap_arg_matches: &clap::ArgMatches) -> ::std::result::Result { Self::from_arg_matches_mut(&mut __clap_arg_matches.clone()) @@ -102,8 +106,8 @@ pub fn gen_for_enum( clippy::nursery, clippy::cargo, clippy::suspicious_else_formatting, - clippy::almost_swapped, )] + #[deny(clippy::correctness)] impl #impl_generics clap::Subcommand for #item_name #ty_generics #where_clause { fn augment_subcommands <'b>(__clap_app: clap::Command) -> clap::Command { #augmentation @@ -115,222 +119,225 @@ pub fn gen_for_enum( #has_subcommand } } - }) + } } fn gen_augment( variants: &[(&Variant, Item)], parent_item: &Item, override_required: bool, -) -> Result { +) -> TokenStream { use syn::Fields::*; let app_var = Ident::new("__clap_app", Span::call_site()); - let mut subcommands = Vec::new(); - for (variant, item) in variants { - let kind = item.kind(); + let subcommands: Vec<_> = variants + .iter() + .filter_map(|(variant, item)| { + let kind = item.kind(); - let genned = match &*kind { - Kind::Skip(_, _) | Kind::Arg(_) | Kind::FromGlobal(_) | Kind::Value => None, + match &*kind { + Kind::Skip(_, _) | + Kind::Arg(_) | + Kind::FromGlobal(_) | + Kind::Value => None, - Kind::ExternalSubcommand => { - let ty = match variant.fields { - Unnamed(ref fields) if fields.unnamed.len() == 1 => &fields.unnamed[0].ty, + Kind::ExternalSubcommand => { + let ty = match variant.fields { + Unnamed(ref fields) if fields.unnamed.len() == 1 => &fields.unnamed[0].ty, - _ => abort!( - variant, - "The enum variant marked with `external_subcommand` must be \ + _ => abort!( + variant, + "The enum variant marked with `external_subcommand` must be \ a single-typed tuple, and the type must be either `Vec` \ or `Vec`." - ), - }; - let deprecations = if !override_required { - item.deprecations() - } else { - quote!() - }; - let subty = subty_if_name(ty, "Vec").ok_or_else(|| { - format_err!( - ty.span(), - "The type must be `Vec<_>` \ - to be used with `external_subcommand`." - ) - })?; - let subcommand = quote_spanned! { kind.span()=> - #deprecations - let #app_var = #app_var - .external_subcommand_value_parser(clap::value_parser!(#subty)); - }; - Some(subcommand) - } - - Kind::Flatten(_) => match variant.fields { - Unnamed(FieldsUnnamed { ref unnamed, .. }) if unnamed.len() == 1 => { - let ty = &unnamed[0]; + ), + }; let deprecations = if !override_required { item.deprecations() } else { quote!() }; - let next_help_heading = item.next_help_heading(); - let next_display_order = item.next_display_order(); - let subcommand = if override_required { - quote! { - #deprecations - let #app_var = #app_var - #next_help_heading - #next_display_order; - let #app_var = <#ty as clap::Subcommand>::augment_subcommands_for_update(#app_var); - } - } else { - quote! { - #deprecations - let #app_var = #app_var - #next_help_heading - #next_display_order; - let #app_var = <#ty as clap::Subcommand>::augment_subcommands(#app_var); - } + let subty = subty_if_name(ty, "Vec").unwrap_or_else(|| { + abort!( + ty.span(), + "The type must be `Vec<_>` \ + to be used with `external_subcommand`." + ) + }); + let subcommand = quote_spanned! { kind.span()=> + #deprecations + let #app_var = #app_var + .external_subcommand_value_parser(clap::value_parser!(#subty)); }; Some(subcommand) } - _ => abort!( - variant, - "`flatten` is usable only with single-typed tuple variants" - ), - }, - Kind::Subcommand(_) => { - let subcommand_var = Ident::new("__clap_subcommand", Span::call_site()); - let arg_block = match variant.fields { - Named(_) => { - abort!(variant, "non single-typed tuple enums are not supported") - } - Unit => quote!( #subcommand_var ), + Kind::Flatten(_) => match variant.fields { Unnamed(FieldsUnnamed { ref unnamed, .. }) if unnamed.len() == 1 => { let ty = &unnamed[0]; - if override_required { - quote_spanned! { ty.span()=> - { - <#ty as clap::Subcommand>::augment_subcommands_for_update(#subcommand_var) - } + let deprecations = if !override_required { + item.deprecations() + } else { + quote!() + }; + let next_help_heading = item.next_help_heading(); + let next_display_order = item.next_display_order(); + let subcommand = if override_required { + quote! { + #deprecations + let #app_var = #app_var + #next_help_heading + #next_display_order; + let #app_var = <#ty as clap::Subcommand>::augment_subcommands_for_update(#app_var); } } else { - quote_spanned! { ty.span()=> - { - <#ty as clap::Subcommand>::augment_subcommands(#subcommand_var) - } + quote! { + #deprecations + let #app_var = #app_var + #next_help_heading + #next_display_order; + let #app_var = <#ty as clap::Subcommand>::augment_subcommands(#app_var); } - } - } - Unnamed(..) => { - abort!(variant, "non single-typed tuple enums are not supported") + }; + Some(subcommand) } - }; + _ => abort!( + variant, + "`flatten` is usable only with single-typed tuple variants" + ), + }, - let name = item.cased_name(); - let deprecations = if !override_required { - item.deprecations() - } else { - quote!() - }; - let initial_app_methods = item.initial_top_level_methods(); - let final_from_attrs = item.final_top_level_methods(); - let override_methods = if override_required { - quote_spanned! { kind.span()=> - .subcommand_required(false) - .arg_required_else_help(false) - } - } else { - quote!() - }; - let subcommand = quote! { - let #app_var = #app_var.subcommand({ - #deprecations; - let #subcommand_var = clap::Command::new(#name); - let #subcommand_var = #subcommand_var - .subcommand_required(true) - .arg_required_else_help(true); - let #subcommand_var = #subcommand_var #initial_app_methods; - let #subcommand_var = #arg_block; - #subcommand_var #final_from_attrs #override_methods - }); - }; - Some(subcommand) - } + Kind::Subcommand(_) => { + let subcommand_var = Ident::new("__clap_subcommand", Span::call_site()); + let arg_block = match variant.fields { + Named(_) => { + abort!(variant, "non single-typed tuple enums are not supported") + } + Unit => quote!( #subcommand_var ), + Unnamed(FieldsUnnamed { ref unnamed, .. }) if unnamed.len() == 1 => { + let ty = &unnamed[0]; + if override_required { + quote_spanned! { ty.span()=> + { + <#ty as clap::Subcommand>::augment_subcommands_for_update(#subcommand_var) + } + } + } else { + quote_spanned! { ty.span()=> + { + <#ty as clap::Subcommand>::augment_subcommands(#subcommand_var) + } + } + } + } + Unnamed(..) => { + abort!(variant, "non single-typed tuple enums are not supported") + } + }; - Kind::Command(_) => { - let subcommand_var = Ident::new("__clap_subcommand", Span::call_site()); - let sub_augment = match variant.fields { - Named(ref fields) => { - // Defer to `gen_augment` for adding cmd methods - let fields = fields - .named - .iter() - .map(|field| { - let item = - Item::from_args_field(field, item.casing(), item.env_casing())?; - Ok((field, item)) - }) - .collect::, syn::Error>>()?; - args::gen_augment(&fields, &subcommand_var, item, override_required)? - } - Unit => { - let arg_block = quote!( #subcommand_var ); - let initial_app_methods = item.initial_top_level_methods(); - let final_from_attrs = item.final_top_level_methods(); - quote! { + let name = item.cased_name(); + let deprecations = if !override_required { + item.deprecations() + } else { + quote!() + }; + let initial_app_methods = item.initial_top_level_methods(); + let final_from_attrs = item.final_top_level_methods(); + let override_methods = if override_required { + quote_spanned! { kind.span()=> + .subcommand_required(false) + .arg_required_else_help(false) + } + } else { + quote!() + }; + let subcommand = quote! { + let #app_var = #app_var.subcommand({ + #deprecations; + let #subcommand_var = clap::Command::new(#name); + let #subcommand_var = #subcommand_var + .subcommand_required(true) + .arg_required_else_help(true); let #subcommand_var = #subcommand_var #initial_app_methods; let #subcommand_var = #arg_block; - #subcommand_var #final_from_attrs + #subcommand_var #final_from_attrs #override_methods + }); + }; + Some(subcommand) + } + + Kind::Command(_) => { + let subcommand_var = Ident::new("__clap_subcommand", Span::call_site()); + let sub_augment = match variant.fields { + Named(ref fields) => { + // Defer to `gen_augment` for adding cmd methods + let fields = fields + .named + .iter() + .map(|field| { + let item = Item::from_args_field(field, item.casing(), item.env_casing()); + (field, item) + }) + .collect::>(); + args::gen_augment(&fields, &subcommand_var, item, override_required) } - } - Unnamed(FieldsUnnamed { ref unnamed, .. }) if unnamed.len() == 1 => { - let ty = &unnamed[0]; - let arg_block = if override_required { - quote_spanned! { ty.span()=> - { - <#ty as clap::Args>::augment_args_for_update(#subcommand_var) - } + Unit => { + let arg_block = quote!( #subcommand_var ); + let initial_app_methods = item.initial_top_level_methods(); + let final_from_attrs = item.final_top_level_methods(); + quote! { + let #subcommand_var = #subcommand_var #initial_app_methods; + let #subcommand_var = #arg_block; + #subcommand_var #final_from_attrs } - } else { - quote_spanned! { ty.span()=> - { - <#ty as clap::Args>::augment_args(#subcommand_var) + }, + Unnamed(FieldsUnnamed { ref unnamed, .. }) if unnamed.len() == 1 => { + let ty = &unnamed[0]; + let arg_block = if override_required { + quote_spanned! { ty.span()=> + { + <#ty as clap::Args>::augment_args_for_update(#subcommand_var) + } + } + } else { + quote_spanned! { ty.span()=> + { + <#ty as clap::Args>::augment_args(#subcommand_var) + } } + }; + let initial_app_methods = item.initial_top_level_methods(); + let final_from_attrs = item.final_top_level_methods(); + quote! { + let #subcommand_var = #subcommand_var #initial_app_methods; + let #subcommand_var = #arg_block; + #subcommand_var #final_from_attrs } - }; - let initial_app_methods = item.initial_top_level_methods(); - let final_from_attrs = item.final_top_level_methods(); - quote! { - let #subcommand_var = #subcommand_var #initial_app_methods; - let #subcommand_var = #arg_block; - #subcommand_var #final_from_attrs } - } - Unnamed(..) => { - abort!(variant, "non single-typed tuple enums are not supported") - } - }; + Unnamed(..) => { + abort!(variant, "non single-typed tuple enums are not supported") + } + }; - let deprecations = if !override_required { - item.deprecations() - } else { - quote!() - }; - let name = item.cased_name(); - let subcommand = quote! { - let #app_var = #app_var.subcommand({ - #deprecations - let #subcommand_var = clap::Command::new(#name); - #sub_augment - }); - }; - Some(subcommand) + let deprecations = if !override_required { + item.deprecations() + } else { + quote!() + }; + let name = item.cased_name(); + let subcommand = quote! { + let #app_var = #app_var.subcommand({ + #deprecations + let #subcommand_var = clap::Command::new(#name); + #sub_augment + }); + }; + Some(subcommand) + } } - }; - subcommands.push(genned); - } + }) + .collect(); let deprecations = if !override_required { parent_item.deprecations() @@ -339,15 +346,15 @@ fn gen_augment( }; let initial_app_methods = parent_item.initial_top_level_methods(); let final_app_methods = parent_item.final_top_level_methods(); - Ok(quote! { + quote! { #deprecations; let #app_var = #app_var #initial_app_methods; #( #subcommands )*; #app_var #final_app_methods - }) + } } -fn gen_has_subcommand(variants: &[(&Variant, Item)]) -> Result { +fn gen_has_subcommand(variants: &[(&Variant, Item)]) -> TokenStream { use syn::Fields::*; let mut ext_subcmd = false; @@ -384,20 +391,19 @@ fn gen_has_subcommand(variants: &[(&Variant, Item)]) -> Result { let ty = &fields.unnamed[0]; - Ok(quote! { + quote! { if <#ty as clap::Subcommand>::has_subcommand(__clap_name) { return true; } - }) + } } _ => abort!( variant, "`flatten` is usable only with single-typed tuple variants" ), - }) - .collect::, syn::Error>>()?; + }); - let genned = if ext_subcmd { + if ext_subcmd { quote! { true } } else { quote! { @@ -407,79 +413,77 @@ fn gen_has_subcommand(variants: &[(&Variant, Item)]) -> Result Result { +fn gen_from_arg_matches(variants: &[(&Variant, Item)]) -> TokenStream { use syn::Fields::*; + let mut ext_subcmd = None; + let subcommand_name_var = format_ident!("__clap_name"); let sub_arg_matches_var = format_ident!("__clap_arg_matches"); + let (flatten_variants, variants): (Vec<_>, Vec<_>) = variants + .iter() + .filter_map(|(variant, item)| { + let kind = item.kind(); + match &*kind { + Kind::Skip(_, _) | Kind::Arg(_) | Kind::FromGlobal(_) | Kind::Value => None, - let mut ext_subcmd = None; - let mut flatten_variants = Vec::new(); - let mut unflatten_variants = Vec::new(); - for (variant, item) in variants { - let kind = item.kind(); - match &*kind { - Kind::Skip(_, _) | Kind::Arg(_) | Kind::FromGlobal(_) | Kind::Value => {} - - Kind::ExternalSubcommand => { - if ext_subcmd.is_some() { - abort!( - item.kind().span(), - "Only one variant can be marked with `external_subcommand`, \ + Kind::ExternalSubcommand => { + if ext_subcmd.is_some() { + abort!( + item.kind().span(), + "Only one variant can be marked with `external_subcommand`, \ this is the second" - ); - } + ); + } - let ty = match variant.fields { - Unnamed(ref fields) if fields.unnamed.len() == 1 => &fields.unnamed[0].ty, + let ty = match variant.fields { + Unnamed(ref fields) if fields.unnamed.len() == 1 => &fields.unnamed[0].ty, - _ => abort!( - variant, - "The enum variant marked with `external_subcommand` must be \ + _ => abort!( + variant, + "The enum variant marked with `external_subcommand` must be \ a single-typed tuple, and the type must be either `Vec` \ or `Vec`." - ), - }; - - let (span, str_ty) = match subty_if_name(ty, "Vec") { - Some(subty) => { - if is_simple_ty(subty, "String") { - (subty.span(), quote!(::std::string::String)) - } else if is_simple_ty(subty, "OsString") { - (subty.span(), quote!(::std::ffi::OsString)) - } else { - abort!( - ty.span(), - "The type must be either `Vec` or `Vec` \ + ), + }; + + let (span, str_ty) = match subty_if_name(ty, "Vec") { + Some(subty) => { + if is_simple_ty(subty, "String") { + (subty.span(), quote!(::std::string::String)) + } else if is_simple_ty(subty, "OsString") { + (subty.span(), quote!(::std::ffi::OsString)) + } else { + abort!( + ty.span(), + "The type must be either `Vec` or `Vec` \ to be used with `external_subcommand`." - ); + ); + } } - } - None => abort!( - ty.span(), - "The type must be either `Vec` or `Vec` \ + None => abort!( + ty.span(), + "The type must be either `Vec` or `Vec` \ to be used with `external_subcommand`." - ), - }; + ), + }; - ext_subcmd = Some((span, &variant.ident, str_ty)); - } - Kind::Flatten(_) | Kind::Subcommand(_) | Kind::Command(_) => { - if matches!(&*item.kind(), Kind::Flatten(_)) { - flatten_variants.push((variant, item)); - } else { - unflatten_variants.push((variant, item)); + ext_subcmd = Some((span, &variant.ident, str_ty)); + None } + Kind::Flatten(_) | Kind::Subcommand(_) | Kind::Command(_) => Some((variant, item)), } - } - } + }) + .partition(|(_, item)| { + let kind = item.kind(); + matches!(&*kind, Kind::Flatten(_)) + }); - let subcommands = unflatten_variants.iter().map(|(variant, item)| { + let subcommands = variants.iter().map(|(variant, item)| { let sub_name = item.cased_name(); let variant_name = &variant.ident; let constructor_block = match variant.fields { @@ -488,11 +492,11 @@ fn gen_from_arg_matches(variants: &[(&Variant, Item)]) -> Result, syn::Error>>()?; - args::gen_constructor(&fields)? + .collect::>(); + args::gen_constructor(&fields) }, Unit => quote!(), Unnamed(ref fields) if fields.unnamed.len() == 1 => { @@ -502,18 +506,18 @@ fn gen_from_arg_matches(variants: &[(&Variant, Item)]) -> Result abort_call_site!("{}: tuple enums are not supported", variant.ident), }; - Ok(quote! { + quote! { if #subcommand_name_var == #sub_name && !#sub_arg_matches_var.contains_id("") { return ::std::result::Result::Ok(Self :: #variant_name #constructor_block) } - }) - }).collect::, syn::Error>>()?; + } + }); let child_subcommands = flatten_variants.iter().map(|(variant, _attrs)| { let variant_name = &variant.ident; match variant.fields { Unnamed(ref fields) if fields.unnamed.len() == 1 => { let ty = &fields.unnamed[0]; - Ok(quote! { + quote! { if __clap_arg_matches .subcommand_name() .map(|__clap_name| <#ty as clap::Subcommand>::has_subcommand(__clap_name)) @@ -522,14 +526,14 @@ fn gen_from_arg_matches(variants: &[(&Variant, Item)]) -> Result::from_arg_matches_mut(__clap_arg_matches)?; return ::std::result::Result::Ok(Self :: #variant_name (__clap_res)); } - }) + } } _ => abort!( variant, "`flatten` is usable only with single-typed tuple variants" ), } - }).collect::, syn::Error>>()?; + }); let wildcard = match ext_subcmd { Some((span, var_name, str_ty)) => quote_spanned! { span=> @@ -551,7 +555,7 @@ fn gen_from_arg_matches(variants: &[(&Variant, Item)]) -> Result ::std::result::Result { #raw_deprecated @@ -566,10 +570,10 @@ fn gen_from_arg_matches(variants: &[(&Variant, Item)]) -> Result Result { +fn gen_update_from_arg_matches(variants: &[(&Variant, Item)]) -> TokenStream { use syn::Fields::*; let (flatten, variants): (Vec<_>, Vec<_>) = variants @@ -603,11 +607,11 @@ fn gen_update_from_arg_matches(variants: &[(&Variant, Item)]) -> Result, syn::Error>>()?; - let update = args::gen_updater(&fields, false)?; + .collect::>(); + let update = args::gen_updater(&fields, false); (quote!( { #( #field_names, )* }), quote!( { #update } )) } Unit => (quote!(), quote!({})), @@ -626,38 +630,38 @@ fn gen_update_from_arg_matches(variants: &[(&Variant, Item)]) -> Result { let (_, mut __clap_arg_sub_matches) = __clap_arg_matches.remove_subcommand().unwrap(); let __clap_arg_matches = &mut __clap_arg_sub_matches; #updater } - }) - }).collect::, _>>()?; + } + }); let child_subcommands = flatten.iter().map(|(variant, _attrs)| { let variant_name = &variant.ident; match variant.fields { Unnamed(ref fields) if fields.unnamed.len() == 1 => { let ty = &fields.unnamed[0]; - Ok(quote! { + quote! { if <#ty as clap::Subcommand>::has_subcommand(__clap_name) { if let Self :: #variant_name (child) = s { <#ty as clap::FromArgMatches>::update_from_arg_matches_mut(child, __clap_arg_matches)?; return ::std::result::Result::Ok(()); } } - }) + } } _ => abort!( variant, "`flatten` is usable only with single-typed tuple variants" ), } - }).collect::, _>>()?; + }); let raw_deprecated = args::raw_deprecated(); - Ok(quote! { + quote! { fn update_from_arg_matches_mut<'b>( &mut self, __clap_arg_matches: &mut clap::ArgMatches, @@ -675,5 +679,5 @@ fn gen_update_from_arg_matches(variants: &[(&Variant, Item)]) -> Result Result { +pub fn derive_value_enum(input: &DeriveInput) -> TokenStream { let ident = &input.ident; + dummies::value_enum(ident); + match input.data { Data::Enum(ref e) => { let name = Name::Derived(ident.clone()); - let item = Item::from_value_enum(input, name)?; - let mut variants = Vec::new(); - for variant in &e.variants { - let item = - Item::from_value_enum_variant(variant, item.casing(), item.env_casing())?; - variants.push((variant, item)); - } + let item = Item::from_value_enum(input, name); + let variants = e + .variants + .iter() + .map(|variant| { + let item = + Item::from_value_enum_variant(variant, item.casing(), item.env_casing()); + (variant, item) + }) + .collect::>(); gen_for_enum(&item, ident, &variants) } _ => abort_call_site!("`#[derive(ValueEnum)]` only supports enums"), } } -pub fn gen_for_enum( - item: &Item, - item_name: &Ident, - variants: &[(&Variant, Item)], -) -> Result { +pub fn gen_for_enum(item: &Item, item_name: &Ident, variants: &[(&Variant, Item)]) -> TokenStream { if !matches!(&*item.kind(), Kind::Value) { abort! { item.kind().span(), "`{}` cannot be used with `value`", @@ -46,11 +49,11 @@ pub fn gen_for_enum( } } - let lits = lits(variants)?; + let lits = lits(variants); let value_variants = gen_value_variants(&lits); let to_possible_value = gen_to_possible_value(item, &lits); - Ok(quote! { + quote! { #[allow(dead_code, unreachable_code, unused_variables, unused_braces)] #[allow( clippy::style, @@ -62,37 +65,39 @@ pub fn gen_for_enum( clippy::nursery, clippy::cargo, clippy::suspicious_else_formatting, - clippy::almost_swapped, )] + #[deny(clippy::correctness)] impl clap::ValueEnum for #item_name { #value_variants #to_possible_value } - }) + } } -fn lits(variants: &[(&Variant, Item)]) -> Result, syn::Error> { - let mut genned = Vec::new(); - for (variant, item) in variants { - if let Kind::Skip(_, _) = &*item.kind() { - continue; - } - if !matches!(variant.fields, Fields::Unit) { - abort!(variant.span(), "`#[derive(ValueEnum)]` only supports unit variants. Non-unit variants must be skipped"); - } - let fields = item.field_methods(); - let deprecations = item.deprecations(); - let name = item.cased_name(); - genned.push(( - quote_spanned! { variant.span()=> { - #deprecations - clap::builder::PossibleValue::new(#name) - #fields - }}, - variant.ident.clone(), - )); - } - Ok(genned) +fn lits(variants: &[(&Variant, Item)]) -> Vec<(TokenStream, Ident)> { + variants + .iter() + .filter_map(|(variant, item)| { + if let Kind::Skip(_, _) = &*item.kind() { + None + } else { + if !matches!(variant.fields, Fields::Unit) { + abort!(variant.span(), "`#[derive(ValueEnum)]` only supports unit variants. Non-unit variants must be skipped"); + } + let fields = item.field_methods(); + let deprecations = item.deprecations(); + let name = item.cased_name(); + Some(( + quote_spanned! { variant.span()=> { + #deprecations + clap::builder::PossibleValue::new(#name) + #fields + }}, + variant.ident.clone(), + )) + } + }) + .collect::>() } fn gen_value_variants(lits: &[(TokenStream, Ident)]) -> TokenStream { diff --git a/clap_derive/src/dummies.rs b/clap_derive/src/dummies.rs index b10bedc64a4e40e4df9f54fb2642f2f21f98b25c..1f54e1dbcbbf21d6b8e06b5cb980d8b86f366605 100644 --- a/clap_derive/src/dummies.rs +++ b/clap_derive/src/dummies.rs @@ -1,20 +1,23 @@ //! Dummy implementations that we emit along with an error. use proc_macro2::Ident; +use proc_macro_error::append_dummy; use quote::quote; -#[must_use] -pub fn parser(name: &Ident) -> proc_macro2::TokenStream { - let into_app = into_app(name); - quote!( - impl clap::Parser for #name {} - #into_app - ) +pub fn parser_struct(name: &Ident) { + into_app(name); + args(name); + append_dummy(quote!( impl clap::Parser for #name {} )); } -#[must_use] -pub fn into_app(name: &Ident) -> proc_macro2::TokenStream { - quote! { +pub fn parser_enum(name: &Ident) { + into_app(name); + subcommand(name); + append_dummy(quote!( impl clap::Parser for #name {} )); +} + +pub fn into_app(name: &Ident) { + append_dummy(quote! { impl clap::CommandFactory for #name { fn command<'b>() -> clap::Command { unimplemented!() @@ -23,12 +26,11 @@ pub fn into_app(name: &Ident) -> proc_macro2::TokenStream { unimplemented!() } } - } + }); } -#[must_use] -pub fn from_arg_matches(name: &Ident) -> proc_macro2::TokenStream { - quote! { +pub fn from_arg_matches(name: &Ident) { + append_dummy(quote! { impl clap::FromArgMatches for #name { fn from_arg_matches(_m: &clap::ArgMatches) -> ::std::result::Result { unimplemented!() @@ -37,13 +39,12 @@ pub fn from_arg_matches(name: &Ident) -> proc_macro2::TokenStream { unimplemented!() } } - } + }); } -#[must_use] -pub fn subcommand(name: &Ident) -> proc_macro2::TokenStream { - let from_arg_matches = from_arg_matches(name); - quote! { +pub fn subcommand(name: &Ident) { + from_arg_matches(name); + append_dummy(quote! { impl clap::Subcommand for #name { fn augment_subcommands(_cmd: clap::Command) -> clap::Command { unimplemented!() @@ -55,14 +56,12 @@ pub fn subcommand(name: &Ident) -> proc_macro2::TokenStream { unimplemented!() } } - #from_arg_matches - } + }); } -#[must_use] -pub fn args(name: &Ident) -> proc_macro2::TokenStream { - let from_arg_matches = from_arg_matches(name); - quote! { +pub fn args(name: &Ident) { + from_arg_matches(name); + append_dummy(quote! { impl clap::Args for #name { fn augment_args(_cmd: clap::Command) -> clap::Command { unimplemented!() @@ -71,13 +70,11 @@ pub fn args(name: &Ident) -> proc_macro2::TokenStream { unimplemented!() } } - #from_arg_matches - } + }); } -#[must_use] -pub fn value_enum(name: &Ident) -> proc_macro2::TokenStream { - quote! { +pub fn value_enum(name: &Ident) { + append_dummy(quote! { impl clap::ValueEnum for #name { fn value_variants<'a>() -> &'a [Self]{ unimplemented!() @@ -89,5 +86,5 @@ pub fn value_enum(name: &Ident) -> proc_macro2::TokenStream { unimplemented!() } } - } + }) } diff --git a/clap_derive/src/item.rs b/clap_derive/src/item.rs index b7814f7de9ddb56870818f174b390526b296c747..5e8272ac0c1e04939c216d179f6592cd68cd8103 100644 --- a/clap_derive/src/item.rs +++ b/clap_derive/src/item.rs @@ -16,6 +16,7 @@ use std::env; use heck::{ToKebabCase, ToLowerCamelCase, ToShoutySnakeCase, ToSnakeCase, ToUpperCamelCase}; use proc_macro2::{self, Span, TokenStream}; +use proc_macro_error::abort; use quote::{format_ident, quote, quote_spanned, ToTokens}; use syn::DeriveInput; use syn::{self, ext::IdentExt, spanned::Spanned, Attribute, Field, Ident, LitStr, Type, Variant}; @@ -52,7 +53,7 @@ pub struct Item { } impl Item { - pub fn from_args_struct(input: &DeriveInput, name: Name) -> Result { + pub fn from_args_struct(input: &DeriveInput, name: Name) -> Self { let ident = input.ident.clone(); let span = input.ident.span(); let attrs = &input.attrs; @@ -61,15 +62,15 @@ impl Item { let kind = Sp::new(Kind::Command(Sp::new(Ty::Other, span)), span); let mut res = Self::new(name, ident, None, argument_casing, env_casing, kind); - let parsed_attrs = ClapAttr::parse_all(attrs)?; - res.infer_kind(&parsed_attrs)?; - res.push_attrs(&parsed_attrs)?; + let parsed_attrs = ClapAttr::parse_all(attrs); + res.infer_kind(&parsed_attrs); + res.push_attrs(&parsed_attrs); res.push_doc_comment(attrs, "about", Some("long_about")); - Ok(res) + res } - pub fn from_subcommand_enum(input: &DeriveInput, name: Name) -> Result { + pub fn from_subcommand_enum(input: &DeriveInput, name: Name) -> Self { let ident = input.ident.clone(); let span = input.ident.span(); let attrs = &input.attrs; @@ -78,15 +79,15 @@ impl Item { let kind = Sp::new(Kind::Command(Sp::new(Ty::Other, span)), span); let mut res = Self::new(name, ident, None, argument_casing, env_casing, kind); - let parsed_attrs = ClapAttr::parse_all(attrs)?; - res.infer_kind(&parsed_attrs)?; - res.push_attrs(&parsed_attrs)?; + let parsed_attrs = ClapAttr::parse_all(attrs); + res.infer_kind(&parsed_attrs); + res.push_attrs(&parsed_attrs); res.push_doc_comment(attrs, "about", Some("long_about")); - Ok(res) + res } - pub fn from_value_enum(input: &DeriveInput, name: Name) -> Result { + pub fn from_value_enum(input: &DeriveInput, name: Name) -> Self { let ident = input.ident.clone(); let span = input.ident.span(); let attrs = &input.attrs; @@ -95,9 +96,9 @@ impl Item { let kind = Sp::new(Kind::Value, span); let mut res = Self::new(name, ident, None, argument_casing, env_casing, kind); - let parsed_attrs = ClapAttr::parse_all(attrs)?; - res.infer_kind(&parsed_attrs)?; - res.push_attrs(&parsed_attrs)?; + let parsed_attrs = ClapAttr::parse_all(attrs); + res.infer_kind(&parsed_attrs); + res.push_attrs(&parsed_attrs); // Ignoring `push_doc_comment` as there is no top-level clap builder to add documentation // to @@ -109,14 +110,14 @@ impl Item { ); } - Ok(res) + res } pub fn from_subcommand_variant( variant: &Variant, struct_casing: Sp, env_casing: Sp, - ) -> Result { + ) -> Self { let name = variant.ident.clone(); let ident = variant.ident.clone(); let span = variant.span(); @@ -137,9 +138,9 @@ impl Item { env_casing, kind, ); - let parsed_attrs = ClapAttr::parse_all(&variant.attrs)?; - res.infer_kind(&parsed_attrs)?; - res.push_attrs(&parsed_attrs)?; + let parsed_attrs = ClapAttr::parse_all(&variant.attrs); + res.infer_kind(&parsed_attrs); + res.push_attrs(&parsed_attrs); if matches!(&*res.kind, Kind::Command(_) | Kind::Subcommand(_)) { res.push_doc_comment(&variant.attrs, "about", Some("long_about")); } @@ -163,14 +164,14 @@ impl Item { | Kind::Arg(_) => (), } - Ok(res) + res } pub fn from_value_enum_variant( variant: &Variant, argument_casing: Sp, env_casing: Sp, - ) -> Result { + ) -> Self { let ident = variant.ident.clone(); let span = variant.span(); let kind = Sp::new(Kind::Value, span); @@ -182,21 +183,21 @@ impl Item { env_casing, kind, ); - let parsed_attrs = ClapAttr::parse_all(&variant.attrs)?; - res.infer_kind(&parsed_attrs)?; - res.push_attrs(&parsed_attrs)?; + let parsed_attrs = ClapAttr::parse_all(&variant.attrs); + res.infer_kind(&parsed_attrs); + res.push_attrs(&parsed_attrs); if matches!(&*res.kind, Kind::Value) { res.push_doc_comment(&variant.attrs, "help", None); } - Ok(res) + res } pub fn from_args_field( field: &Field, struct_casing: Sp, env_casing: Sp, - ) -> Result { + ) -> Self { let name = field.ident.clone().unwrap(); let ident = field.ident.clone().unwrap(); let span = field.span(); @@ -210,9 +211,9 @@ impl Item { env_casing, kind, ); - let parsed_attrs = ClapAttr::parse_all(&field.attrs)?; - res.infer_kind(&parsed_attrs)?; - res.push_attrs(&parsed_attrs)?; + let parsed_attrs = ClapAttr::parse_all(&field.attrs); + res.infer_kind(&parsed_attrs); + res.push_attrs(&parsed_attrs); if matches!(&*res.kind, Kind::Arg(_)) { res.push_doc_comment(&field.attrs, "help", Some("long_help")); } @@ -243,7 +244,7 @@ impl Item { | Kind::ExternalSubcommand => {} } - Ok(res) + res } fn new( @@ -328,7 +329,7 @@ impl Item { } } - fn infer_kind(&mut self, attrs: &[ClapAttr]) -> Result<(), syn::Error> { + fn infer_kind(&mut self, attrs: &[ClapAttr]) { for attr in attrs { if let Some(AttrValue::Call(_)) = &attr.value { continue; @@ -338,7 +339,7 @@ impl Item { let kind = match &attr.magic { Some(MagicAttrName::FromGlobal) => { if attr.value.is_some() { - let expr = attr.value_or_abort()?; + let expr = attr.value_or_abort(); abort!(expr, "attribute `{}` does not accept a value", attr.name); } let ty = self @@ -351,7 +352,7 @@ impl Item { } Some(MagicAttrName::Subcommand) if attr.value.is_none() => { if attr.value.is_some() { - let expr = attr.value_or_abort()?; + let expr = attr.value_or_abort(); abort!(expr, "attribute `{}` does not accept a value", attr.name); } let ty = self @@ -364,7 +365,7 @@ impl Item { } Some(MagicAttrName::ExternalSubcommand) if attr.value.is_none() => { if attr.value.is_some() { - let expr = attr.value_or_abort()?; + let expr = attr.value_or_abort(); abort!(expr, "attribute `{}` does not accept a value", attr.name); } let kind = Sp::new(Kind::ExternalSubcommand, attr.name.clone().span()); @@ -372,7 +373,7 @@ impl Item { } Some(MagicAttrName::Flatten) if attr.value.is_none() => { if attr.value.is_some() { - let expr = attr.value_or_abort()?; + let expr = attr.value_or_abort(); abort!(expr, "attribute `{}` does not accept a value", attr.name); } let ty = self @@ -395,14 +396,12 @@ impl Item { }; if let Some(kind) = kind { - self.set_kind(kind)?; + self.set_kind(kind); } } - - Ok(()) } - fn push_attrs(&mut self, attrs: &[ClapAttr]) -> Result<(), syn::Error> { + fn push_attrs(&mut self, attrs: &[ClapAttr]) { for attr in attrs { let actual_attr_kind = *attr.kind.get(); let expected_attr_kind = self.kind.attr_kind(); @@ -438,7 +437,7 @@ impl Item { match &attr.magic { Some(MagicAttrName::Short) if attr.value.is_none() => { - assert_attr_kind(attr, &[AttrKind::Arg])?; + assert_attr_kind(attr, &[AttrKind::Arg]); self.push_method( *attr.kind.get(), @@ -448,13 +447,13 @@ impl Item { } Some(MagicAttrName::Long) if attr.value.is_none() => { - assert_attr_kind(attr, &[AttrKind::Arg])?; + assert_attr_kind(attr, &[AttrKind::Arg]); self.push_method(*attr.kind.get(), attr.name.clone(), self.name.clone().translate(*self.casing)); } Some(MagicAttrName::ValueParser) if attr.value.is_none() => { - assert_attr_kind(attr, &[AttrKind::Arg])?; + assert_attr_kind(attr, &[AttrKind::Arg]); self.deprecations.push(Deprecation { span: attr.name.span(), @@ -466,7 +465,7 @@ impl Item { } Some(MagicAttrName::Action) if attr.value.is_none() => { - assert_attr_kind(attr, &[AttrKind::Arg])?; + assert_attr_kind(attr, &[AttrKind::Arg]); self.deprecations.push(Deprecation { span: attr.name.span(), @@ -478,7 +477,7 @@ impl Item { } Some(MagicAttrName::Env) if attr.value.is_none() => { - assert_attr_kind(attr, &[AttrKind::Arg])?; + assert_attr_kind(attr, &[AttrKind::Arg]); self.push_method( *attr.kind.get(), @@ -488,7 +487,7 @@ impl Item { } Some(MagicAttrName::ValueEnum) if attr.value.is_none() => { - assert_attr_kind(attr, &[AttrKind::Arg])?; + assert_attr_kind(attr, &[AttrKind::Arg]); self.is_enum = true } @@ -498,45 +497,45 @@ impl Item { } Some(MagicAttrName::About) if attr.value.is_none() => { - assert_attr_kind(attr, &[AttrKind::Command])?; + assert_attr_kind(attr, &[AttrKind::Command]); if let Some(method) = - Method::from_env(attr.name.clone(), "CARGO_PKG_DESCRIPTION")? + Method::from_env(attr.name.clone(), "CARGO_PKG_DESCRIPTION") { self.methods.push(method); } } Some(MagicAttrName::LongAbout) if attr.value.is_none() => { - assert_attr_kind(attr, &[AttrKind::Command])?; + assert_attr_kind(attr, &[AttrKind::Command]); self.force_long_help = true; } Some(MagicAttrName::LongHelp) if attr.value.is_none() => { - assert_attr_kind(attr, &[AttrKind::Arg])?; + assert_attr_kind(attr, &[AttrKind::Arg]); self.force_long_help = true; } Some(MagicAttrName::Author) if attr.value.is_none() => { - assert_attr_kind(attr, &[AttrKind::Command])?; + assert_attr_kind(attr, &[AttrKind::Command]); - if let Some(method) = Method::from_env(attr.name.clone(), "CARGO_PKG_AUTHORS")? { + if let Some(method) = Method::from_env(attr.name.clone(), "CARGO_PKG_AUTHORS") { self.methods.push(method); } } Some(MagicAttrName::Version) if attr.value.is_none() => { - assert_attr_kind(attr, &[AttrKind::Command])?; + assert_attr_kind(attr, &[AttrKind::Command]); - if let Some(method) = Method::from_env(attr.name.clone(), "CARGO_PKG_VERSION")? { + if let Some(method) = Method::from_env(attr.name.clone(), "CARGO_PKG_VERSION") { self.methods.push(method); } } Some(MagicAttrName::DefaultValueT) => { - assert_attr_kind(attr, &[AttrKind::Arg])?; + assert_attr_kind(attr, &[AttrKind::Arg]); let ty = if let Some(ty) = self.ty.as_ref() { ty @@ -544,7 +543,7 @@ impl Item { abort!( attr.name.clone(), "#[arg(default_value_t)] (without an argument) can be used \ - only on field level\n\n= note: {note}\n\n", + only on field level"; note = "see \ https://github.com/clap-rs/clap/blob/master/examples/derive_ref/README.md#magic-attributes") @@ -584,7 +583,7 @@ impl Item { } Some(MagicAttrName::DefaultValuesT) => { - assert_attr_kind(attr, &[AttrKind::Arg])?; + assert_attr_kind(attr, &[AttrKind::Arg]); let ty = if let Some(ty) = self.ty.as_ref() { ty @@ -592,18 +591,18 @@ impl Item { abort!( attr.name.clone(), "#[arg(default_values_t)] (without an argument) can be used \ - only on field level\n\n= note: {note}\n\n", + only on field level"; note = "see \ https://github.com/clap-rs/clap/blob/master/examples/derive_ref/README.md#magic-attributes") }; - let expr = attr.value_or_abort()?; + let expr = attr.value_or_abort(); let container_type = Ty::from_syn_ty(ty); if *container_type != Ty::Vec { abort!( attr.name.clone(), - "#[arg(default_values_t)] can be used only on Vec types\n\n= note: {note}\n\n", + "#[arg(default_values_t)] can be used only on Vec types"; note = "see \ https://github.com/clap-rs/clap/blob/master/examples/derive_ref/README.md#magic-attributes") @@ -668,7 +667,7 @@ impl Item { } Some(MagicAttrName::DefaultValueOsT) => { - assert_attr_kind(attr, &[AttrKind::Arg])?; + assert_attr_kind(attr, &[AttrKind::Arg]); let ty = if let Some(ty) = self.ty.as_ref() { ty @@ -676,7 +675,7 @@ impl Item { abort!( attr.name.clone(), "#[arg(default_value_os_t)] (without an argument) can be used \ - only on field level\n\n= note: {note}\n\n", + only on field level"; note = "see \ https://github.com/clap-rs/clap/blob/master/examples/derive_ref/README.md#magic-attributes") @@ -716,7 +715,7 @@ impl Item { } Some(MagicAttrName::DefaultValuesOsT) => { - assert_attr_kind(attr, &[AttrKind::Arg])?; + assert_attr_kind(attr, &[AttrKind::Arg]); let ty = if let Some(ty) = self.ty.as_ref() { ty @@ -724,18 +723,18 @@ impl Item { abort!( attr.name.clone(), "#[arg(default_values_os_t)] (without an argument) can be used \ - only on field level\n\n= note: {note}\n\n", + only on field level"; note = "see \ https://github.com/clap-rs/clap/blob/master/examples/derive_ref/README.md#magic-attributes") }; - let expr = attr.value_or_abort()?; + let expr = attr.value_or_abort(); let container_type = Ty::from_syn_ty(ty); if *container_type != Ty::Vec { abort!( attr.name.clone(), - "#[arg(default_values_os_t)] can be used only on Vec types\n\n= note: {note}\n\n", + "#[arg(default_values_os_t)] can be used only on Vec types"; note = "see \ https://github.com/clap-rs/clap/blob/master/examples/derive_ref/README.md#magic-attributes") @@ -800,29 +799,29 @@ impl Item { } Some(MagicAttrName::NextDisplayOrder) => { - assert_attr_kind(attr, &[AttrKind::Command])?; + assert_attr_kind(attr, &[AttrKind::Command]); - let expr = attr.value_or_abort()?; + let expr = attr.value_or_abort(); self.next_display_order = Some(Method::new(attr.name.clone(), quote!(#expr))); } Some(MagicAttrName::NextHelpHeading) => { - assert_attr_kind(attr, &[AttrKind::Command])?; + assert_attr_kind(attr, &[AttrKind::Command]); - let expr = attr.value_or_abort()?; + let expr = attr.value_or_abort(); self.next_help_heading = Some(Method::new(attr.name.clone(), quote!(#expr))); } Some(MagicAttrName::RenameAll) => { - let lit = attr.lit_str_or_abort()?; - self.casing = CasingStyle::from_lit(lit)?; + let lit = attr.lit_str_or_abort(); + self.casing = CasingStyle::from_lit(lit); } Some(MagicAttrName::RenameAllEnv) => { - assert_attr_kind(attr, &[AttrKind::Command, AttrKind::Arg])?; + assert_attr_kind(attr, &[AttrKind::Command, AttrKind::Arg]); - let lit = attr.lit_str_or_abort()?; - self.env_casing = CasingStyle::from_lit(lit)?; + let lit = attr.lit_str_or_abort(); + self.env_casing = CasingStyle::from_lit(lit); } Some(MagicAttrName::Skip) if actual_attr_kind == AttrKind::Group => { @@ -840,20 +839,20 @@ impl Item { | Some(MagicAttrName::Author) | Some(MagicAttrName::Version) => { - let expr = attr.value_or_abort()?; + let expr = attr.value_or_abort(); self.push_method(*attr.kind.get(), attr.name.clone(), expr); } // Magic only for the default, otherwise just forward to the builder Some(MagicAttrName::ValueParser) | Some(MagicAttrName::Action) => { - let expr = attr.value_or_abort()?; + let expr = attr.value_or_abort(); self.push_method(*attr.kind.get(), attr.name.clone(), expr); } // Directives that never receive a value Some(MagicAttrName::ValueEnum) | Some(MagicAttrName::VerbatimDocComment) => { - let expr = attr.value_or_abort()?; + let expr = attr.value_or_abort(); abort!(expr, "attribute `{}` does not accept a value", attr.name); } @@ -884,8 +883,6 @@ impl Item { ); } } - - Ok(()) } fn push_doc_comment(&mut self, attrs: &[Attribute], short_name: &str, long_name: Option<&str>) { @@ -915,7 +912,7 @@ impl Item { } } - fn set_kind(&mut self, kind: Sp) -> Result<(), syn::Error> { + fn set_kind(&mut self, kind: Sp) { match (self.kind.get(), kind.get()) { (Kind::Arg(_), Kind::FromGlobal(_)) | (Kind::Arg(_), Kind::Subcommand(_)) @@ -935,7 +932,6 @@ impl Item { abort!(kind.span(), "`{}` cannot be used with `{}`", new, old); } } - Ok(()) } pub fn find_default_method(&self) -> Option<&Method> { @@ -1215,21 +1211,19 @@ impl Method { Method { name, args } } - fn from_env(ident: Ident, env_var: &str) -> Result, syn::Error> { + fn from_env(ident: Ident, env_var: &str) -> Option { let mut lit = match env::var(env_var) { Ok(val) => { if val.is_empty() { - return Ok(None); + return None; } LitStr::new(&val, ident.span()) } Err(_) => { - abort!( - ident, - "cannot derive `{}` from Cargo.toml\n\n= note: {note}\n\n= help: {help}\n\n", - ident, - note = format_args!("`{}` environment variable is not set", env_var), - help = format_args!("use `{} = \"...\"` to set {} manually", ident, ident) + abort!(ident, + "cannot derive `{}` from Cargo.toml", ident; + note = "`{}` environment variable is not set", env_var; + help = "use `{} = \"...\"` to set {} manually", ident, ident; ); } }; @@ -1239,7 +1233,7 @@ impl Method { lit = LitStr::new(&edited, lit.span()); } - Ok(Some(Method::new(ident, quote!(#lit)))) + Some(Method::new(ident, quote!(#lit))) } pub(crate) fn args(&self) -> &TokenStream { @@ -1305,7 +1299,7 @@ impl ToTokens for Deprecation { } } -fn assert_attr_kind(attr: &ClapAttr, possible_kind: &[AttrKind]) -> Result<(), syn::Error> { +fn assert_attr_kind(attr: &ClapAttr, possible_kind: &[AttrKind]) { if *attr.kind.get() == AttrKind::Clap || *attr.kind.get() == AttrKind::StructOpt { // deprecated } else if !possible_kind.contains(attr.kind.get()) { @@ -1321,7 +1315,6 @@ fn assert_attr_kind(attr: &ClapAttr, possible_kind: &[AttrKind]) -> Result<(), s options.join(", ") ); } - Ok(()) } /// replace all `:` with `, ` when not inside the `<>` @@ -1371,13 +1364,13 @@ pub enum CasingStyle { } impl CasingStyle { - fn from_lit(name: &LitStr) -> Result, syn::Error> { + fn from_lit(name: &LitStr) -> Sp { use self::CasingStyle::*; let normalized = name.value().to_upper_camel_case().to_lowercase(); let cs = |kind| Sp::new(kind, name.span()); - let s = match normalized.as_ref() { + match normalized.as_ref() { "camel" | "camelcase" => cs(Camel), "kebab" | "kebabcase" => cs(Kebab), "pascal" | "pascalcase" => cs(Pascal), @@ -1387,8 +1380,7 @@ impl CasingStyle { "upper" | "uppercase" => cs(Upper), "verbatim" | "verbatimcase" => cs(Verbatim), s => abort!(name, "unsupported casing: `{}`", s), - }; - Ok(s) + } } } diff --git a/clap_derive/src/lib.rs b/clap_derive/src/lib.rs index d3cae9b65d367827441a2c8a2590b34ec42f5151..84f2f0ded9fa12d34a2f0cd2e66ab913225866e9 100644 --- a/clap_derive/src/lib.rs +++ b/clap_derive/src/lib.rs @@ -19,11 +19,8 @@ extern crate proc_macro; use proc_macro::TokenStream; +use proc_macro_error::proc_macro_error; use syn::{parse_macro_input, DeriveInput}; -use syn::{Data, DataStruct, Fields}; - -#[macro_use] -mod macros; mod attr; mod derives; @@ -33,14 +30,10 @@ mod utils; /// Generates the `ValueEnum` impl. #[proc_macro_derive(ValueEnum, attributes(clap, value))] +#[proc_macro_error] pub fn value_enum(input: TokenStream) -> TokenStream { let input: DeriveInput = parse_macro_input!(input); - derives::derive_value_enum(&input) - .unwrap_or_else(|err| { - let dummy = dummies::value_enum(&input.ident); - to_compile_error(err, dummy) - }) - .into() + derives::derive_value_enum(&input).into() } /// Generates the `Parser` implementation. @@ -50,67 +43,24 @@ pub fn value_enum(input: TokenStream) -> TokenStream { /// implementing a conversion code to instantiate an instance of the user /// context struct. #[proc_macro_derive(Parser, attributes(clap, structopt, command, arg, group))] +#[proc_macro_error] pub fn parser(input: TokenStream) -> TokenStream { let input: DeriveInput = parse_macro_input!(input); - derives::derive_parser(&input) - .unwrap_or_else(|err| { - let specific_dummy = match input.data { - Data::Struct(DataStruct { - fields: Fields::Named(ref _fields), - .. - }) => Some(dummies::args(&input.ident)), - Data::Struct(DataStruct { - fields: Fields::Unit, - .. - }) => Some(dummies::args(&input.ident)), - Data::Enum(_) => Some(dummies::subcommand(&input.ident)), - _ => None, - }; - let dummy = specific_dummy - .map(|specific_dummy| { - let parser_dummy = dummies::parser(&input.ident); - quote::quote! { - #parser_dummy - #specific_dummy - } - }) - .unwrap_or_else(|| quote::quote!()); - to_compile_error(err, dummy) - }) - .into() + derives::derive_parser(&input).into() } /// Generates the `Subcommand` impl. #[proc_macro_derive(Subcommand, attributes(clap, command, arg, group))] +#[proc_macro_error] pub fn subcommand(input: TokenStream) -> TokenStream { let input: DeriveInput = parse_macro_input!(input); - derives::derive_subcommand(&input) - .unwrap_or_else(|err| { - let dummy = dummies::subcommand(&input.ident); - to_compile_error(err, dummy) - }) - .into() + derives::derive_subcommand(&input).into() } /// Generates the `Args` impl. #[proc_macro_derive(Args, attributes(clap, command, arg, group))] +#[proc_macro_error] pub fn args(input: TokenStream) -> TokenStream { let input: DeriveInput = parse_macro_input!(input); - derives::derive_args(&input) - .unwrap_or_else(|err| { - let dummy = dummies::args(&input.ident); - to_compile_error(err, dummy) - }) - .into() -} - -fn to_compile_error( - error: syn::Error, - dummy: proc_macro2::TokenStream, -) -> proc_macro2::TokenStream { - let compile_errors = error.to_compile_error(); - quote::quote!( - #dummy - #compile_errors - ) + derives::derive_args(&input).into() } diff --git a/clap_derive/src/macros.rs b/clap_derive/src/macros.rs deleted file mode 100644 index 282048bc1752e796205c17ca24555b98a948af0b..0000000000000000000000000000000000000000 --- a/clap_derive/src/macros.rs +++ /dev/null @@ -1,21 +0,0 @@ -macro_rules! format_err { - ($obj:expr, $($format:tt)+) => {{ - #[allow(unused_imports)] - use $crate::utils::error::*; - let msg = format!($($format)+); - $obj.EXPECTED_Span_OR_ToTokens(msg) - }}; -} - -macro_rules! abort { - ($obj:expr, $($format:tt)+) => {{ - return Err(format_err!($obj, $($format)+)); - }}; -} - -macro_rules! abort_call_site { - ($($format:tt)+) => {{ - let span = proc_macro2::Span::call_site(); - abort!(span, $($format)+) - }}; -} diff --git a/clap_derive/src/utils/doc_comments.rs b/clap_derive/src/utils/doc_comments.rs index 63c6ad1ef32883d32133cf41d2810365cac1916d..5183b6b25e1748ce4975c26a60c6416fe13c3dc9 100644 --- a/clap_derive/src/utils/doc_comments.rs +++ b/clap_derive/src/utils/doc_comments.rs @@ -6,26 +6,24 @@ use std::iter; pub fn extract_doc_comment(attrs: &[syn::Attribute]) -> Vec { + use syn::Lit::*; + use syn::Meta::*; + use syn::MetaNameValue; + // multiline comments (`/** ... */`) may have LFs (`\n`) in them, // we need to split so we could handle the lines correctly // // we also need to remove leading and trailing blank lines let mut lines: Vec<_> = attrs .iter() - .filter(|attr| attr.path().is_ident("doc")) + .filter(|attr| attr.path.is_ident("doc")) .filter_map(|attr| { - // non #[doc = "..."] attributes are not our concern - // we leave them for rustc to handle - match &attr.meta { - syn::Meta::NameValue(syn::MetaNameValue { - value: - syn::Expr::Lit(syn::ExprLit { - lit: syn::Lit::Str(s), - .. - }), - .. - }) => Some(s.value()), - _ => None, + if let Ok(NameValue(MetaNameValue { lit: Str(s), .. })) = attr.parse_meta() { + Some(s.value()) + } else { + // non #[doc = "..."] attributes are not our concern + // we leave them for rustc to handle + None } }) .skip_while(|s| is_blank(s)) diff --git a/clap_derive/src/utils/error.rs b/clap_derive/src/utils/error.rs deleted file mode 100644 index 276e349493caa5b5d02db074a13dcf743c741fdf..0000000000000000000000000000000000000000 --- a/clap_derive/src/utils/error.rs +++ /dev/null @@ -1,22 +0,0 @@ -pub trait SpanError { - #[allow(non_snake_case)] - fn EXPECTED_Span_OR_ToTokens(&self, msg: D) -> syn::Error; -} - -pub trait ToTokensError { - #[allow(non_snake_case)] - fn EXPECTED_Span_OR_ToTokens(&self, msg: D) -> syn::Error; -} - -impl ToTokensError for T { - fn EXPECTED_Span_OR_ToTokens(&self, msg: D) -> syn::Error { - // Curb monomorphization from generating too many identical `new_spanned`. - syn::Error::new_spanned(self.to_token_stream(), msg) - } -} - -impl SpanError for proc_macro2::Span { - fn EXPECTED_Span_OR_ToTokens(&self, msg: D) -> syn::Error { - syn::Error::new(*self, msg) - } -} diff --git a/clap_derive/src/utils/mod.rs b/clap_derive/src/utils/mod.rs index 13e6e710620d4e632c4b14b1e3489c725d1b185b..9f8b6f380abf2b25b5d1e1833f188808e6307444 100644 --- a/clap_derive/src/utils/mod.rs +++ b/clap_derive/src/utils/mod.rs @@ -1,5 +1,3 @@ -pub mod error; - mod doc_comments; mod spanned; mod ty; diff --git a/clap_lex/BUILD.gn b/clap_lex/BUILD.gn index e63c4ea58aeb6cc8f344c0650261fadbe59327b5..760036b03f7659c360e8b644d80f8d187cbd40da 100644 --- a/clap_lex/BUILD.gn +++ b/clap_lex/BUILD.gn @@ -14,14 +14,14 @@ import("//build/ohos.gni") ohos_cargo_crate("lib") { - crate_name = "clap_lex" - crate_type = "rlib" - crate_root = "src/lib.rs" + crate_name = "clap_lex" + crate_type = "rlib" + crate_root = "src/lib.rs" - sources = [ "src/lib.rs" ] - edition = "2021" - cargo_pkg_version = "0.3.3" - cargo_pkg_name = "clap_lex" - cargo_pkg_description = "Minimal, flexible command line parser" - deps = [ "//third_party/rust/crates/os_str_bytes:lib" ] + sources = ["src/lib.rs"] + edition = "2021" + cargo_pkg_version = "0.3.1" + cargo_pkg_name = "clap_lex" + cargo_pkg_description = "Minimal, flexible command line parser" + deps = ["//third_party/rust/crates/os_str_bytes:lib"] } diff --git a/clap_lex/CHANGELOG.md b/clap_lex/CHANGELOG.md index 9e2046799c4f32d1512ea6ddf053fa3886c6534b..6b64af9063453237ce5e5727911f2f5cb7de96b5 100644 --- a/clap_lex/CHANGELOG.md +++ b/clap_lex/CHANGELOG.md @@ -7,10 +7,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] - ReleaseDate -## [0.3.3] - 2023-03-16 - -## [0.3.2] - 2023-02-23 - ## [0.3.1] - 2023-01-13 ### Compatibility @@ -50,9 +46,7 @@ MSRV changed to 1.64.0 - Drop `memchr` dependency -[Unreleased]: https://github.com/clap-rs/clap/compare/clap_lex-v0.3.3...HEAD -[0.3.3]: https://github.com/clap-rs/clap/compare/clap_lex-v0.3.2...clap_lex-v0.3.3 -[0.3.2]: https://github.com/clap-rs/clap/compare/clap_lex-v0.3.1...clap_lex-v0.3.2 +[Unreleased]: https://github.com/clap-rs/clap/compare/clap_lex-v0.3.1...HEAD [0.3.1]: https://github.com/clap-rs/clap/compare/clap_lex-v0.3.0...clap_lex-v0.3.1 [0.3.0]: https://github.com/clap-rs/clap/compare/clap_lex-v0.2.4...clap_lex-v0.3.0 [0.2.4]: https://github.com/clap-rs/clap/compare/clap_lex-v0.2.3...clap_lex-v0.2.4 diff --git a/clap_lex/Cargo.toml b/clap_lex/Cargo.toml index da2d1e7351f61323aad5c33757281e74fc93ea82..e8d9673ee8fb3ed5b12af8d6588058961fde9566 100644 --- a/clap_lex/Cargo.toml +++ b/clap_lex/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clap_lex" -version = "0.3.3" +version = "0.3.1" description = "Minimal, flexible command line parser" repository = "https://github.com/clap-rs/clap/tree/master/clap_lex" categories = ["command-line-interface"] @@ -30,4 +30,4 @@ pre-release-replacements = [ bench = false [dependencies] -os_str_bytes = { version = "6.0.0", default-features = false, features = ["raw_os_str"] } +os_str_bytes = { version = "6.0", default-features = false, features = ["raw_os_str"] } diff --git a/clap_lex/README.md b/clap_lex/README.md index 93434053fb59c63882464adb2fef3eba7dcfe89e..7f4c46d3f395dbe82bff3cf641054b1cb75c70dd 100644 --- a/clap_lex/README.md +++ b/clap_lex/README.md @@ -5,15 +5,15 @@ [![Crates.io](https://img.shields.io/crates/v/clap_lex?style=flat-square)](https://crates.io/crates/clap_lex) [![Crates.io](https://img.shields.io/crates/d/clap_lex?style=flat-square)](https://crates.io/crates/clap_lex) -[![License](https://img.shields.io/badge/license-Apache%202.0-blue?style=flat-square)](https://github.com/clap-rs/clap/blob/clap_lex-v0.3.3/LICENSE-APACHE) -[![License](https://img.shields.io/badge/license-MIT-blue?style=flat-square)](https://github.com/clap-rs/clap/blob/clap_lex-v0.3.3/LICENSE-MIT) +[![License](https://img.shields.io/badge/license-Apache%202.0-blue?style=flat-square)](https://github.com/clap-rs/clap/blob/clap_lex-v0.3.1/LICENSE-APACHE) +[![License](https://img.shields.io/badge/license-MIT-blue?style=flat-square)](https://github.com/clap-rs/clap/blob/clap_lex-v0.3.1/LICENSE-MIT) Dual-licensed under [Apache 2.0](LICENSE-APACHE) or [MIT](LICENSE-MIT). 1. [About](#about) 2. [API Reference](https://docs.rs/clap_lex) 3. [Questions & Discussions](https://github.com/clap-rs/clap/discussions) -4. [CONTRIBUTING](https://github.com/clap-rs/clap/blob/clap_lex-v0.3.3/clap_lex/CONTRIBUTING.md) -5. [Sponsors](https://github.com/clap-rs/clap/blob/clap_lex-v0.3.3/README.md#sponsors) +4. [CONTRIBUTING](https://github.com/clap-rs/clap/blob/clap_lex-v0.3.1/clap_lex/CONTRIBUTING.md) +5. [Sponsors](https://github.com/clap-rs/clap/blob/clap_lex-v0.3.1/README.md#sponsors) ## About diff --git a/clap_lex/src/lib.rs b/clap_lex/src/lib.rs index bc9720fc570ee0cb71a7d8cafab6b259949b2520..bc4d4ba6594b87e1245b31e29e2d1a12af411258 100644 --- a/clap_lex/src/lib.rs +++ b/clap_lex/src/lib.rs @@ -7,10 +7,8 @@ //! # Examples //! //! ```rust -//! use std::path::PathBuf; -//! -//! type BoxedError = Box; -//! +//! # use std::path::PathBuf; +//! # type BoxedError = Box; //! #[derive(Debug)] //! struct Args { //! paths: Vec, diff --git a/clap_mangen/CHANGELOG.md b/clap_mangen/CHANGELOG.md index 69634b1dbc864b1f18a619fdfe2d99100d47839c..fbb4b9980af68d0cc1a36e24d8b61faf7d29ed6f 100644 --- a/clap_mangen/CHANGELOG.md +++ b/clap_mangen/CHANGELOG.md @@ -7,16 +7,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] - ReleaseDate -## [0.2.10] - 2023-03-16 - -## [0.2.9] - 2023-02-22 - -### Fixes - -- Only show value names if a value is taken - -## [0.2.8] - 2023-02-15 - ## [0.2.7] - 2023-01-13 ### Compatibility @@ -82,10 +72,7 @@ MSRV changed to 1.64.0 - Expanded the documentation -[Unreleased]: https://github.com/clap-rs/clap/compare/clap_mangen-v0.2.10...HEAD -[0.2.10]: https://github.com/clap-rs/clap/compare/clap_mangen-v0.2.9...clap_mangen-v0.2.10 -[0.2.9]: https://github.com/clap-rs/clap/compare/clap_mangen-v0.2.8...clap_mangen-v0.2.9 -[0.2.8]: https://github.com/clap-rs/clap/compare/clap_mangen-v0.2.7...clap_mangen-v0.2.8 +[Unreleased]: https://github.com/clap-rs/clap/compare/clap_mangen-v0.2.7...HEAD [0.2.7]: https://github.com/clap-rs/clap/compare/clap_mangen-v0.2.6...clap_mangen-v0.2.7 [0.2.6]: https://github.com/clap-rs/clap/compare/clap_mangen-v0.2.5...clap_mangen-v0.2.6 [0.2.5]: https://github.com/clap-rs/clap/compare/clap_mangen-v0.2.4...clap_mangen-v0.2.5 diff --git a/clap_mangen/Cargo.toml b/clap_mangen/Cargo.toml index 9eb3b428ebf637d11267f090b7168683d2089be9..7696c7c0bceebae2e9fc9c40193a41be8072c83c 100644 --- a/clap_mangen/Cargo.toml +++ b/clap_mangen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clap_mangen" -version = "0.2.10" +version = "0.2.7" description = "A manpage generator for clap" repository = "https://github.com/clap-rs/clap/tree/master/clap_mangen" categories = ["command-line-interface"] @@ -36,7 +36,7 @@ roff = "0.2.1" clap = { path = "../", version = "4.0.0", default-features = false, features = ["std", "env"] } [dev-dependencies] -snapbox = { version = "0.4.10", features = ["diff"] } +snapbox = { version = "0.4", features = ["diff"] } clap = { path = "../", version = "4.0.0", default-features = false, features = ["std", "help"] } [features] diff --git a/clap_mangen/README.md b/clap_mangen/README.md index fde4d79652bc54eb6ab2960ce10c353951b43834..138e4206f5981486d16b1eeee396cf5cc3d8d159 100644 --- a/clap_mangen/README.md +++ b/clap_mangen/README.md @@ -5,16 +5,16 @@ [![Crates.io](https://img.shields.io/crates/v/clap_mangen?style=flat-square)](https://crates.io/crates/clap_mangen) [![Crates.io](https://img.shields.io/crates/d/clap_mangen?style=flat-square)](https://crates.io/crates/clap_mangen) -[![License](https://img.shields.io/badge/license-Apache%202.0-blue?style=flat-square)](https://github.com/clap-rs/clap/blob/clap_mangen-v0.2.10/LICENSE-APACHE) -[![License](https://img.shields.io/badge/license-MIT-blue?style=flat-square)](https://github.com/clap-rs/clap/blob/clap_mangen-v0.2.10/LICENSE-MIT) +[![License](https://img.shields.io/badge/license-Apache%202.0-blue?style=flat-square)](https://github.com/clap-rs/clap/blob/clap_mangen-v0.2.7/LICENSE-APACHE) +[![License](https://img.shields.io/badge/license-MIT-blue?style=flat-square)](https://github.com/clap-rs/clap/blob/clap_mangen-v0.2.7/LICENSE-MIT) Dual-licensed under [Apache 2.0](LICENSE-APACHE) or [MIT](LICENSE-MIT). 1. [About](#about) 2. [API Reference](https://docs.rs/clap_mangen) 3. [Questions & Discussions](https://github.com/clap-rs/clap/discussions) -4. [CONTRIBUTING](https://github.com/clap-rs/clap/blob/clap_mangen-v0.2.10/clap_mangen/CONTRIBUTING.md) -5. [Sponsors](https://github.com/clap-rs/clap/blob/clap_mangen-v0.2.10/README.md#sponsors) +4. [CONTRIBUTING](https://github.com/clap-rs/clap/blob/clap_mangen-v0.2.7/clap_mangen/CONTRIBUTING.md) +5. [Sponsors](https://github.com/clap-rs/clap/blob/clap_mangen-v0.2.7/README.md#sponsors) ## About @@ -25,9 +25,10 @@ Generate [ROFF](https://en.wikipedia.org/wiki/Roff_(software)) from a `clap::Com We're going to assume you want to generate your man page as part of your development rather than your shipped program having a flag to generate it. -Run -```console -$ cargo add --build clap_mangen +In your `Cargo.toml`: +```toml +[build-dependencies] +clap_mangen = "0.1" ``` In your `build.rs`: diff --git a/clap_mangen/src/render.rs b/clap_mangen/src/render.rs index 99fa6ab447a2d9af2cf31ef00463bc045c1f981c..ab9c9ec75c1507cc0d672f0bb233b4b5c6787772 100644 --- a/clap_mangen/src/render.rs +++ b/clap_mangen/src/render.rs @@ -36,19 +36,19 @@ pub(crate) fn synopsis(roff: &mut Roff, cmd: &clap::Command) { match (opt.get_short(), opt.get_long()) { (Some(short), Some(long)) => { line.push(roman(lhs)); - line.push(bold(format!("-{short}"))); + line.push(bold(format!("-{}", short))); line.push(roman("|")); - line.push(bold(format!("--{long}",))); + line.push(bold(format!("--{}", long))); line.push(roman(rhs)); } (Some(short), None) => { line.push(roman(lhs)); - line.push(bold(format!("-{short} "))); + line.push(bold(format!("-{} ", short))); line.push(roman(rhs)); } (None, Some(long)) => { line.push(roman(lhs)); - line.push(bold(format!("--{long}"))); + line.push(bold(format!("--{}", long))); line.push(roman(rhs)); } (None, None) => continue, @@ -99,11 +99,9 @@ pub(crate) fn options(roff: &mut Roff, cmd: &clap::Command) { (None, None) => vec![], }; - if opt.get_action().takes_values() { - if let Some(value) = &opt.get_value_names() { - header.push(roman("=")); - header.push(italic(value.join(" "))); - } + if let Some(value) = &opt.get_value_names() { + header.push(roman("=")); + header.push(italic(value.join(" "))); } if let Some(defs) = option_default_values(opt) { @@ -170,7 +168,7 @@ pub(crate) fn options(roff: &mut Roff, cmd: &clap::Command) { header.push(roman(rhs)); if let Some(defs) = option_default_values(pos) { - header.push(roman(format!(" {defs}"))); + header.push(roman(format!(" {}", defs))); } let mut body = vec![]; @@ -275,11 +273,11 @@ fn markers(required: bool) -> (&'static str, &'static str) { } fn short_option(opt: char) -> Inline { - bold(format!("-{opt}")) + bold(format!("-{}", opt)) } fn long_option(opt: &str) -> Inline { - bold(format!("--{opt}")) + bold(format!("--{}", opt)) } fn option_help(opt: &clap::Arg) -> Option<&clap::builder::StyledStr> { @@ -321,7 +319,7 @@ fn option_default_values(opt: &clap::Arg) -> Option { .collect::>() .join(","); - return Some(format!("[default: {values}]")); + return Some(format!("[default: {}]", values)); } None @@ -345,7 +343,7 @@ fn format_possible_values(possibles: &Vec<&clap::builder::PossibleValue>) -> (Ve for value in possibles { let val_name = value.get_name(); match value.get_help() { - Some(help) => lines.push(format!("{val_name}: {help}")), + Some(help) => lines.push(format!("{}: {}", val_name, help)), None => lines.push(val_name.to_string()), } } diff --git a/clap_mangen/tests/common.rs b/clap_mangen/tests/common.rs index 029098c0956c265a6ff5e5e061aacb0a535e591b..ca9f1f9b4fb395653b8a9de2a0cb2ec3a8afd5f0 100644 --- a/clap_mangen/tests/common.rs +++ b/clap_mangen/tests/common.rs @@ -312,12 +312,3 @@ pub fn possible_values_command(name: &'static str) -> clap::Command { ]), ) } - -pub fn value_name_without_arg(name: &'static str) -> clap::Command { - clap::Command::new(name).arg( - clap::Arg::new("flag") - .long("flag") - .value_name("SPURIOUS") - .action(clap::ArgAction::SetTrue), - ) -} diff --git a/clap_mangen/tests/roff.rs b/clap_mangen/tests/roff.rs index 38d1aef11bae882207c7b31a1c33b3e3be3c7d71..223196c3a4474655fa5964f36db5106d13d606ca 100644 --- a/clap_mangen/tests/roff.rs +++ b/clap_mangen/tests/roff.rs @@ -83,10 +83,3 @@ fn sub_subcommands_help() { common::assert_matches_path("tests/snapshots/sub_subcommand_help.roff", cmd.clone()); } } - -#[test] -fn value_name_without_arg() { - let name = "my-app"; - let cmd = common::value_name_without_arg(name); - common::assert_matches_path("tests/snapshots/value_name_without_arg.bash.roff", cmd); -} diff --git a/clap_mangen/tests/snapshots/value_name_without_arg.bash.roff b/clap_mangen/tests/snapshots/value_name_without_arg.bash.roff deleted file mode 100644 index 2ffbe0210fab3823c10107446a2a28095a0887de..0000000000000000000000000000000000000000 --- a/clap_mangen/tests/snapshots/value_name_without_arg.bash.roff +++ /dev/null @@ -1,15 +0,0 @@ -.ie /n(.g .ds Aq /(aq -.el .ds Aq ' -.TH my-app 1 "my-app " -.SH NAME -my/-app -.SH SYNOPSIS -/fBmy/-app/fR [/fB/-/-flag/fR] [/fB/-h/fR|/fB/-/-help/fR] -.SH DESCRIPTION -.SH OPTIONS -.TP -/fB/-/-flag/fR - -.TP -/fB/-h/fR, /fB/-/-help/fR -Print help diff --git a/deny.toml b/deny.toml deleted file mode 100644 index cb4ba4cf66c7747594813c6bc3d94aa568f5cdaf..0000000000000000000000000000000000000000 --- a/deny.toml +++ /dev/null @@ -1,149 +0,0 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Note that all fields that take a lint level have these possible values: -# * deny - An error will be produced and the check will fail -# * warn - A warning will be produced, but the check will not fail -# * allow - No warning or error will be produced, though in some cases a note -# will be - -# This section is considered when running `cargo deny check advisories` -# More documentation for the advisories section can be found here: -# https://embarkstudios.github.io/cargo-deny/checks/advisories/cfg.html -[advisories] -# The lint level for security vulnerabilities -vulnerability = "deny" -# The lint level for unmaintained crates -unmaintained = "warn" -# The lint level for crates that have been yanked from their source registry -yanked = "warn" -# The lint level for crates with security notices. Note that as of -# 2019-12-17 there are no security notice advisories in -# https://github.com/rustsec/advisory-db -notice = "warn" -# A list of advisory IDs to ignore. Note that ignored advisories will still -# output a note when they are encountered. -# -# e.g. "RUSTSEC-0000-0000", -ignore = [ -] - -# This section is considered when running `cargo deny check licenses` -# More documentation for the licenses section can be found here: -# https://embarkstudios.github.io/cargo-deny/checks/licenses/cfg.html -[licenses] -unlicensed = "deny" -# List of explicitly allowed licenses -# See https://spdx.org/licenses/ for list of possible licenses -# [possible values: any SPDX 3.11 short identifier (+ optional exception)]. -allow = [ - "MIT", - "Apache-2.0", - "Unicode-DFS-2016", - #"Apache-2.0 WITH LLVM-exception", -] -# List of explicitly disallowed licenses -# See https://spdx.org/licenses/ for list of possible licenses -# [possible values: any SPDX 3.11 short identifier (+ optional exception)]. -deny = [ -] -# Lint level for licenses considered copyleft -copyleft = "deny" -# Blanket approval or denial for OSI-approved or FSF Free/Libre licenses -# * both - The license will be approved if it is both OSI-approved *AND* FSF -# * either - The license will be approved if it is either OSI-approved *OR* FSF -# * osi-only - The license will be approved if is OSI-approved *AND NOT* FSF -# * fsf-only - The license will be approved if is FSF *AND NOT* OSI-approved -# * neither - This predicate is ignored and the default lint level is used -allow-osi-fsf-free = "neither" -# Lint level used when no other predicates are matched -# 1. License isn't in the allow or deny lists -# 2. License isn't copyleft -# 3. License isn't OSI/FSF, or allow-osi-fsf-free = "neither" -default = "deny" -# The confidence threshold for detecting a license from license text. -# The higher the value, the more closely the license text must be to the -# canonical license text of a valid SPDX license file. -# [possible values: any between 0.0 and 1.0]. -confidence-threshold = 0.8 -# Allow 1 or more licenses on a per-crate basis, so that particular licenses -# aren't accepted for every possible crate as with the normal allow list -exceptions = [ - # Each entry is the crate and version constraint, and its specific allow - # list - #{ allow = ["Zlib"], name = "adler32", version = "*" }, -] - -[licenses.private] -# If true, ignores workspace crates that aren't published, or are only -# published to private registries. -# To see how to mark a crate as unpublished (to the official registry), -# visit https://doc.rust-lang.org/cargo/reference/manifest.html#the-publish-field. -ignore = true - -# This section is considered when running `cargo deny check bans`. -# More documentation about the 'bans' section can be found here: -# https://embarkstudios.github.io/cargo-deny/checks/bans/cfg.html -[bans] -# Lint level for when multiple versions of the same crate are detected -multiple-versions = "warn" -# Lint level for when a crate version requirement is `*` -wildcards = "deny" -# The graph highlighting used when creating dotgraphs for crates -# with multiple versions -# * lowest-version - The path to the lowest versioned duplicate is highlighted -# * simplest-path - The path to the version with the fewest edges is highlighted -# * all - Both lowest-version and simplest-path are used -highlight = "all" -# The default lint level for `default` features for crates that are members of -# the workspace that is being checked. This can be overridden by allowing/denying -# `default` on a crate-by-crate basis if desired. -workspace-default-features = "allow" -# The default lint level for `default` features for external crates that are not -# members of the workspace. This can be overridden by allowing/denying `default` -# on a crate-by-crate basis if desired. -external-default-features = "allow" -# List of crates that are allowed. Use with care! -allow = [ - #{ name = "ansi_term", version = "=0.11.0" }, -] -# List of crates to deny -deny = [ - # Each entry the name of a crate and a version range. If version is - # not specified, all versions will be matched. - #{ name = "ansi_term", version = "=0.11.0" }, - # - # Wrapper crates can optionally be specified to allow the crate when it - # is a direct dependency of the otherwise banned crate - #{ name = "ansi_term", version = "=0.11.0", wrappers = [] }, -] - -# This section is considered when running `cargo deny check sources`. -# More documentation about the 'sources' section can be found here: -# https://embarkstudios.github.io/cargo-deny/checks/sources/cfg.html -[sources] -# Lint level for what to happen when a crate from a crate registry that is not -# in the allow list is encountered -unknown-registry = "deny" -# Lint level for what to happen when a crate from a git repository that is not -# in the allow list is encountered -unknown-git = "deny" -# List of URLs for allowed crate registries. Defaults to the crates.io index -# if not specified. If it is specified but empty, no registries are allowed. -allow-registry = ["https://github.com/rust-lang/crates.io-index"] -# List of URLs for allowed Git repositories -allow-git = [] - -[sources.allow-org] -# 1 or more github.com organizations to allow git sources for -github = [] diff --git a/examples/cargo-example-derive.rs b/examples/cargo-example-derive.rs index dfdd799fc19e9188b6c36164849fae19d0dabeb5..d9603db896b110bff973274ae3f14706c5021a4f 100644 --- a/examples/cargo-example-derive.rs +++ b/examples/cargo-example-derive.rs @@ -3,18 +3,18 @@ use clap::Parser; #[derive(Parser)] // requires `derive` feature #[command(name = "cargo")] #[command(bin_name = "cargo")] -enum CargoCli { - ExampleDerive(ExampleDeriveArgs), +enum Cargo { + ExampleDerive(ExampleDerive), } #[derive(clap::Args)] #[command(author, version, about, long_about = None)] -struct ExampleDeriveArgs { +struct ExampleDerive { #[arg(long)] manifest_path: Option, } fn main() { - let CargoCli::ExampleDerive(args) = CargoCli::parse(); + let Cargo::ExampleDerive(args) = Cargo::parse(); println!("{:?}", args.manifest_path); } diff --git a/examples/derive_ref/augment_args.rs b/examples/derive_ref/augment_args.rs index 39d837cfaf56708271f494be7bad2f80589aa51a..458beb44c1e9f7105544de532f00e2618ca4a5c8 100644 --- a/examples/derive_ref/augment_args.rs +++ b/examples/derive_ref/augment_args.rs @@ -23,5 +23,5 @@ fn main() { let derived_matches = DerivedArgs::from_arg_matches(&matches) .map_err(|err| err.exit()) .unwrap(); - println!("Value of derived: {derived_matches:#?}"); + println!("Value of derived: {:#?}", derived_matches); } diff --git a/examples/derive_ref/augment_subcommands.rs b/examples/derive_ref/augment_subcommands.rs index 51cbe75d2a286f615e8df17e667322df26a137b9..577527500c225b5be839725b660ecdc7e4c9d6d4 100644 --- a/examples/derive_ref/augment_subcommands.rs +++ b/examples/derive_ref/augment_subcommands.rs @@ -17,5 +17,5 @@ fn main() { let derived_subcommands = Subcommands::from_arg_matches(&matches) .map_err(|err| err.exit()) .unwrap(); - println!("Derived subcommands: {derived_subcommands:#?}"); + println!("Derived subcommands: {:#?}", derived_subcommands); } diff --git a/examples/derive_ref/flatten_hand_args.rs b/examples/derive_ref/flatten_hand_args.rs index 36aac09323aef0a4499041e5f5c46c337e9234b7..2ceeb7c0f578188105356b6179b10960e35730d6 100644 --- a/examples/derive_ref/flatten_hand_args.rs +++ b/examples/derive_ref/flatten_hand_args.rs @@ -87,5 +87,5 @@ struct Cli { fn main() { let args = Cli::parse(); - println!("{args:#?}"); + println!("{:#?}", args); } diff --git a/examples/derive_ref/hand_subcommand.rs b/examples/derive_ref/hand_subcommand.rs index ebaa60d5d2e7c0f53dbed2817287546f5951a834..5ea169cd1e1360abeefa7d7e404101b7f2bde29a 100644 --- a/examples/derive_ref/hand_subcommand.rs +++ b/examples/derive_ref/hand_subcommand.rs @@ -69,11 +69,11 @@ impl Subcommand for CliSub { struct Cli { #[arg(short, long)] top_level: bool, - #[command(subcommand)] + #[clap(subcommand)] subcommand: CliSub, } fn main() { let args = Cli::parse(); - println!("{args:#?}"); + println!("{:#?}", args); } diff --git a/examples/git-derive.md b/examples/git-derive.md index 57edb612e9ecc16ba399170b76e9889f14dfe781..b5c4794d30a4f1901d315639cfd539729c9a18c5 100644 --- a/examples/git-derive.md +++ b/examples/git-derive.md @@ -102,13 +102,13 @@ Options: -h, --help Print help $ git-derive stash -m "Prototype" -Pushing StashPushArgs { message: Some("Prototype") } +Pushing StashPush { message: Some("Prototype") } $ git-derive stash pop Popping None $ git-derive stash push -m "Prototype" -Pushing StashPushArgs { message: Some("Prototype") } +Pushing StashPush { message: Some("Prototype") } $ git-derive stash pop Popping None diff --git a/examples/git-derive.rs b/examples/git-derive.rs index ad82e0cea7804e04c751bfac7c5373f75eaafc23..519982d1b9777d19c231f88375bf70d2e91a330a 100644 --- a/examples/git-derive.rs +++ b/examples/git-derive.rs @@ -53,7 +53,7 @@ enum Commands { #[arg(required = true)] path: Vec, }, - Stash(StashArgs), + Stash(Stash), #[command(external_subcommand)] External(Vec), } @@ -76,23 +76,23 @@ impl std::fmt::Display for ColorWhen { #[derive(Debug, Args)] #[command(args_conflicts_with_subcommands = true)] -struct StashArgs { +struct Stash { #[command(subcommand)] command: Option, #[command(flatten)] - push: StashPushArgs, + push: StashPush, } #[derive(Debug, Subcommand)] enum StashCommands { - Push(StashPushArgs), + Push(StashPush), Pop { stash: Option }, Apply { stash: Option }, } #[derive(Debug, Args)] -struct StashPushArgs { +struct StashPush { #[arg(short, long)] message: Option, } @@ -102,7 +102,7 @@ fn main() { match args.command { Commands::Clone { remote } => { - println!("Cloning {remote}"); + println!("Cloning {}", remote); } Commands::Diff { mut base, @@ -136,22 +136,22 @@ fn main() { ); } Commands::Push { remote } => { - println!("Pushing to {remote}"); + println!("Pushing to {}", remote); } Commands::Add { path } => { - println!("Adding {path:?}"); + println!("Adding {:?}", path); } Commands::Stash(stash) => { let stash_cmd = stash.command.unwrap_or(StashCommands::Push(stash.push)); match stash_cmd { StashCommands::Push(push) => { - println!("Pushing {push:?}"); + println!("Pushing {:?}", push); } StashCommands::Pop { stash } => { - println!("Popping {stash:?}"); + println!("Popping {:?}", stash); } StashCommands::Apply { stash } => { - println!("Applying {stash:?}"); + println!("Applying {:?}", stash); } } } diff --git a/examples/git.rs b/examples/git.rs index bd05e531582a836888ad1a2084e4bb7ec2a3cb5b..8a2fcc72dfd7dd2ae67ffa7dea19438c9352327f 100644 --- a/examples/git.rs +++ b/examples/git.rs @@ -86,7 +86,7 @@ fn main() { let base = base.unwrap_or("stage"); let head = head.unwrap_or("worktree"); let path = path.unwrap_or(""); - println!("Diffing {base}..{head} {path} (color={color})"); + println!("Diffing {}..{} {} (color={})", base, head, path, color); } Some(("push", sub_matches)) => { println!( @@ -100,22 +100,22 @@ fn main() { .into_iter() .flatten() .collect::>(); - println!("Adding {paths:?}"); + println!("Adding {:?}", paths); } Some(("stash", sub_matches)) => { let stash_command = sub_matches.subcommand().unwrap_or(("push", sub_matches)); match stash_command { ("apply", sub_matches) => { let stash = sub_matches.get_one::("STASH"); - println!("Applying {stash:?}"); + println!("Applying {:?}", stash); } ("pop", sub_matches) => { let stash = sub_matches.get_one::("STASH"); - println!("Popping {stash:?}"); + println!("Popping {:?}", stash); } ("push", sub_matches) => { let message = sub_matches.get_one::("message"); - println!("Pushing {message:?}"); + println!("Pushing {:?}", message); } (name, _) => { unreachable!("Unsupported subcommand `{}`", name) @@ -128,9 +128,9 @@ fn main() { .into_iter() .flatten() .collect::>(); - println!("Calling out to {ext:?} with {args:?}"); + println!("Calling out to {:?} with {:?}", ext, args); } - _ => unreachable!(), // If all subcommands are defined above, anything else is unreachable!() + _ => unreachable!(), // If all subcommands are defined above, anything else is unreachabe!() } // Continued program logic goes here... diff --git a/examples/pacman.rs b/examples/pacman.rs index 7ab30db953fcbf1164f48936fef0d1bd1cbf0449..12e7ffaf2751c44118e2e87d97c98ca558769bdc 100644 --- a/examples/pacman.rs +++ b/examples/pacman.rs @@ -78,7 +78,7 @@ fn main() { .map(|s| s.as_str()) .collect(); let values = packages.join(", "); - println!("Searching for {values}..."); + println!("Searching for {}...", values); return; } @@ -90,18 +90,18 @@ fn main() { let values = packages.join(", "); if sync_matches.get_flag("info") { - println!("Retrieving info for {values}..."); + println!("Retrieving info for {}...", values); } else { - println!("Installing {values}..."); + println!("Installing {}...", values); } } Some(("query", query_matches)) => { if let Some(packages) = query_matches.get_many::("info") { let comma_sep = packages.map(|s| s.as_str()).collect::>().join(", "); - println!("Retrieving info for {comma_sep}..."); + println!("Retrieving info for {}...", comma_sep); } else if let Some(queries) = query_matches.get_many::("search") { let comma_sep = queries.map(|s| s.as_str()).collect::>().join(", "); - println!("Searching Locally for {comma_sep}..."); + println!("Searching Locally for {}...", comma_sep); } else { println!("Displaying all locally installed packages..."); } diff --git a/examples/repl.rs b/examples/repl.rs index 2806ac8e9d4352a77c6b657332bca221fdae7856..ef26591158831e247c824191efb5c938d597607d 100644 --- a/examples/repl.rs +++ b/examples/repl.rs @@ -17,7 +17,7 @@ fn main() -> Result<(), String> { } } Err(err) => { - write!(std::io::stdout(), "{err}").map_err(|e| e.to_string())?; + write!(std::io::stdout(), "{}", err).map_err(|e| e.to_string())?; std::io::stdout().flush().map_err(|e| e.to_string())?; } } diff --git a/examples/tutorial_derive/01_quick.rs b/examples/tutorial_derive/01_quick.rs index 0edcd251f971c8ccf94beaba4bf9a0c47907e08c..960e7ea18c93aa770d02891e251923c62d4e4731 100644 --- a/examples/tutorial_derive/01_quick.rs +++ b/examples/tutorial_derive/01_quick.rs @@ -35,7 +35,7 @@ fn main() { // You can check the value provided by positional arguments, or option arguments if let Some(name) = cli.name.as_deref() { - println!("Value for name: {name}"); + println!("Value for name: {}", name); } if let Some(config_path) = cli.config.as_deref() { diff --git a/examples/tutorial_derive/03_04_subcommands.rs b/examples/tutorial_derive/03_04_subcommands.rs index da7c644c70420fbc38b9965cdc2aa6fdbf62b63d..279a5fff54f9fc3e2a4127541c2e6b9ccf61843a 100644 --- a/examples/tutorial_derive/03_04_subcommands.rs +++ b/examples/tutorial_derive/03_04_subcommands.rs @@ -21,7 +21,7 @@ fn main() { // matches just as you would the top level cmd match &cli.command { Commands::Add { name } => { - println!("'myapp add' was used, name is: {name:?}") + println!("'myapp add' was used, name is: {:?}", name) } } } diff --git a/examples/tutorial_derive/03_04_subcommands_alt.rs b/examples/tutorial_derive/03_04_subcommands_alt.rs index 80b0ec6b9586a3b9309f7bdb7fafa83e78d0c7fd..8b70dba0a9fc17224784bcdfda182724933e7e58 100644 --- a/examples/tutorial_derive/03_04_subcommands_alt.rs +++ b/examples/tutorial_derive/03_04_subcommands_alt.rs @@ -11,11 +11,11 @@ struct Cli { #[derive(Subcommand)] enum Commands { /// Adds files to myapp - Add(AddArgs), + Add(Add), } #[derive(Args)] -struct AddArgs { +struct Add { name: Option, } diff --git a/examples/tutorial_derive/04_02_validate.rs b/examples/tutorial_derive/04_02_validate.rs index 3391d5b72d58b9bff42a666d357b8b29723d8a34..513084dffb159b3c1feebde1ad7be3545112b222 100644 --- a/examples/tutorial_derive/04_02_validate.rs +++ b/examples/tutorial_derive/04_02_validate.rs @@ -21,7 +21,7 @@ const PORT_RANGE: RangeInclusive = 1..=65535; fn port_in_range(s: &str) -> Result { let port: usize = s .parse() - .map_err(|_| format!("`{s}` isn't a port number"))?; + .map_err(|_| format!("`{}` isn't a port number", s))?; if PORT_RANGE.contains(&port) { Ok(port as u16) } else { diff --git a/examples/tutorial_derive/04_03_relations.rs b/examples/tutorial_derive/04_03_relations.rs index cbe491deb4bb59a8e8396a8d19c195d13201ba7c..e366095702ee131e400d9f72f009f1c5f131ebc3 100644 --- a/examples/tutorial_derive/04_03_relations.rs +++ b/examples/tutorial_derive/04_03_relations.rs @@ -56,10 +56,10 @@ fn main() { (_, _, true) => patch += 1, _ => unreachable!(), }; - format!("{major}.{minor}.{patch}") + format!("{}.{}.{}", major, minor, patch) }; - println!("Version: {version}"); + println!("Version: {}", version); // Check for usage of -c if let Some(config) = cli.config.as_deref() { @@ -67,6 +67,6 @@ fn main() { .input_file .as_deref() .unwrap_or_else(|| cli.spec_in.as_deref().unwrap()); - println!("Doing work using input {input} and config {config}"); + println!("Doing work using input {} and config {}", input, config); } } diff --git a/examples/tutorial_derive/04_04_custom.rs b/examples/tutorial_derive/04_04_custom.rs index a84b5ed5fe9c9f7b584c0d9435a7ae0be96a939b..cbc460f19cae9cc2d6577e41756ec49effdcadea 100644 --- a/examples/tutorial_derive/04_04_custom.rs +++ b/examples/tutorial_derive/04_04_custom.rs @@ -66,10 +66,10 @@ fn main() { .exit(); } }; - format!("{major}.{minor}.{patch}") + format!("{}.{}.{}", major, minor, patch) }; - println!("Version: {version}"); + println!("Version: {}", version); // Check for usage of -c if let Some(config) = cli.config.as_deref() { @@ -86,6 +86,6 @@ fn main() { ) .exit() }); - println!("Doing work using input {input} and config {config}"); + println!("Doing work using input {} and config {}", input, config); } } diff --git a/examples/typed-derive.rs b/examples/typed-derive.rs index 8d7a84e96724a45163756d5205ca6de73b59406b..bdf8a5809117d1d516746d40d3d9077b68bd1a22 100644 --- a/examples/typed-derive.rs +++ b/examples/typed-derive.rs @@ -54,7 +54,7 @@ where { let pos = s .find('=') - .ok_or_else(|| format!("invalid KEY=value: no `=` found in `{s}`"))?; + .ok_or_else(|| format!("invalid KEY=value: no `=` found in `{}`", s))?; Ok((s[..pos].parse()?, s[pos + 1..].parse()?)) } @@ -98,5 +98,5 @@ mod foreign_crate { fn main() { let args = Args::parse(); - println!("{args:?}"); + println!("{:?}", args); } diff --git a/src/_derive/_tutorial.rs b/src/_derive/_tutorial.rs index f3f55c3392d9eb866076ca0d74291039fb42cb2b..eb95c8754148a1d35fd58d16b11c033f97fd6066 100644 --- a/src/_derive/_tutorial.rs +++ b/src/_derive/_tutorial.rs @@ -75,7 +75,7 @@ #![doc = include_str!("../../examples/tutorial_derive/03_03_positional.md")] //! //! Note that the default [`ArgAction`][crate::ArgAction] is [`Set`][crate::ArgAction::Set]. To -//! accept multiple values, use [`Append`][crate::ArgAction::Append] via `Vec`: +//! accept multiple values, use [`Append`][crate::ArgAction::Append]: //! ```rust #![doc = include_str!("../../examples/tutorial_derive/03_03_positional_mult.rs")] //! ``` @@ -98,7 +98,7 @@ #![doc = include_str!("../../examples/tutorial_derive/03_02_option.md")] //! //! Note that the default [`ArgAction`][crate::ArgAction] is [`Set`][crate::ArgAction::Set]. To -//! accept multiple occurrences, use [`Append`][crate::ArgAction::Append] via `Vec`: +//! accept multiple occurrences, use [`Append`][crate::ArgAction::Append]: //! ```rust #![doc = include_str!("../../examples/tutorial_derive/03_02_option_mult.rs")] //! ``` diff --git a/src/builder/arg.rs b/src/builder/arg.rs index bf898cbfd6427118fd8e54ad352a6e4e0149368b..ca2d6acbc2b739ad10fa7aa3b38a14020b0d3e8d 100644 --- a/src/builder/arg.rs +++ b/src/builder/arg.rs @@ -2111,8 +2111,7 @@ impl Arg { /// /// Args with a lower value will be displayed first in the help message. This is helpful when /// one would like to emphasise frequently used args, or prioritize those towards the top of - /// the list. Args with duplicate display orders will be displayed in the order they are - /// defined. + /// the list. Args with duplicate display orders will be displayed in alphabetical order. /// /// **NOTE:** The default is 999 for all arguments. /// @@ -4123,7 +4122,7 @@ impl Arg { if self.val_names.len() > 1 { self.val_names .iter() - .map(|n| format!("<{n}>")) + .map(|n| format!("<{}>", n)) .collect::>() .join(delim) } else { @@ -4207,9 +4206,9 @@ impl Arg { debug_assert!(self.is_takes_value_set()); for (n, val_name) in val_names.iter().enumerate() { let arg_name = if self.is_positional() && (num_vals.min_values() == 0 || !required) { - format!("[{val_name}]") + format!("[{}]", val_name) } else { - format!("<{val_name}>") + format!("<{}>", val_name) }; if n != 0 { diff --git a/src/builder/arg_settings.rs b/src/builder/arg_settings.rs index b8bc069c5dbd9c9d9220fce650b3ee7faa707824..0f63e439611a168085cb56cc67c2e1a27194d13f 100644 --- a/src/builder/arg_settings.rs +++ b/src/builder/arg_settings.rs @@ -113,7 +113,7 @@ mod test { assert!(m.is_required_set()); let m = m.unset_setting(ArgSettings::Required); - assert!(!m.is_required_set(), "{m:#?}"); + assert!(!m.is_required_set(), "{:#?}", m); } #[test] @@ -138,8 +138,8 @@ mod test { assert!(m.is_last_set()); let m = m.unset_setting(ArgSettings::Required | ArgSettings::Hidden | ArgSettings::Last); - assert!(!m.is_required_set(), "{m:#?}"); - assert!(!m.is_hide_set(), "{m:#?}"); - assert!(!m.is_last_set(), "{m:#?}"); + assert!(!m.is_required_set(), "{:#?}", m); + assert!(!m.is_hide_set(), "{:#?}", m); + assert!(!m.is_last_set(), "{:#?}", m); } } diff --git a/src/builder/command.rs b/src/builder/command.rs index 635aa1bcd57df86db3a8bd53a2ab1386c386ab43..fc2c983e4d994849e5b9927caaf9f254c2018275 100644 --- a/src/builder/command.rs +++ b/src/builder/command.rs @@ -243,7 +243,7 @@ impl Command { let a = self .args .remove_by_name(id) - .unwrap_or_else(|| panic!("Argument `{id}` is undefined")); + .unwrap_or_else(|| panic!("Argument `{}` is undefined", id)); self.args.push(f(a)); self @@ -287,7 +287,7 @@ impl Command { let subcmd = if let Some(idx) = pos { self.subcommands.remove(idx) } else { - panic!("Command `{name}` is undefined") + panic!("Command `{}` is undefined", name) }; self.subcommands.push(f(subcmd)); @@ -822,7 +822,7 @@ impl Command { let mut styled = StyledStr::new(); let usage = Usage::new(self); write_help(&mut styled, self, &usage, false); - ok!(write!(w, "{styled}")); + ok!(write!(w, "{}", styled)); w.flush() } @@ -837,7 +837,7 @@ impl Command { let mut styled = StyledStr::new(); let usage = Usage::new(self); write_help(&mut styled, self, &usage, true); - ok!(write!(w, "{styled}")); + ok!(write!(w, "{}", styled)); w.flush() } @@ -1057,8 +1057,8 @@ impl Command { /// /// Using `0` will ignore terminal widths and use source formatting. /// - /// Defaults to current terminal width when `wrap_help` feature flag is enabled. If current - /// width cannot be determined, the default is 100. + /// Defaults to current terminal width when `wrap_help` feature flag is enabled. If the flag + /// is disabled or it cannot be determined, the default is 100. /// /// **NOTE:** This setting applies globally and *not* on a per-command basis. /// @@ -2599,7 +2599,7 @@ impl Command { /// Set the placement of this subcommand within the help. /// /// Subcommands with a lower value will be displayed first in the help message. Subcommands - /// with duplicate display orders will be displayed in order they are defined. + /// with duplicate display orders will be displayed in alphabetical order. /// /// This is helpful when one would like to emphasize frequently used subcommands, or prioritize /// those towards the top of the list. @@ -3947,22 +3947,22 @@ impl Command { sc_names.push_str(sc.name.as_str()); let mut flag_subcmd = false; if let Some(l) = sc.get_long_flag() { - write!(sc_names, "|--{l}").unwrap(); + write!(sc_names, "|--{}", l).unwrap(); flag_subcmd = true; } if let Some(s) = sc.get_short_flag() { - write!(sc_names, "|-{s}").unwrap(); + write!(sc_names, "|-{}", s).unwrap(); flag_subcmd = true; } if flag_subcmd { - sc_names = format!("{{{sc_names}}}"); + sc_names = format!("{{{}}}", sc_names); } let usage_name = self .bin_name .as_ref() - .map(|bin_name| format!("{bin_name}{mid_string}{sc_names}")) + .map(|bin_name| format!("{}{}{}", bin_name, mid_string, sc_names)) .unwrap_or(sc_names); sc.usage_name = Some(usage_name); @@ -4044,19 +4044,19 @@ impl Command { sc_names.push_str(sc.name.as_str()); let mut flag_subcmd = false; if let Some(l) = sc.get_long_flag() { - write!(sc_names, "|--{l}").unwrap(); + write!(sc_names, "|--{}", l).unwrap(); flag_subcmd = true; } if let Some(s) = sc.get_short_flag() { - write!(sc_names, "|-{s}").unwrap(); + write!(sc_names, "|-{}", s).unwrap(); flag_subcmd = true; } if flag_subcmd { - sc_names = format!("{{{sc_names}}}"); + sc_names = format!("{{{}}}", sc_names); } - let usage_name = format!("{self_bin_name}{mid_string}{sc_names}"); + let usage_name = format!("{}{}{}", self_bin_name, mid_string, sc_names); debug!( "Command::_build_bin_names:iter: Setting usage_name of {} to {:?}", sc.name, usage_name @@ -4334,7 +4334,7 @@ impl Command { .unwrap_or_default() }; let display_name = self.get_display_name().unwrap_or_else(|| self.get_name()); - format!("{display_name} {ver}\n") + format!("{} {}\n", display_name, ver) } pub(crate) fn format_group(&self, g: &Id) -> StyledStr { @@ -4593,14 +4593,12 @@ impl Command { // specified by the user is sent through. If hide_short_help is not included, // then items specified with hidden_short_help will also be hidden. let should_long = |v: &Arg| { - !v.is_hide_set() - && (v.get_long_help().is_some() - || v.is_hide_long_help_set() - || v.is_hide_short_help_set() - || (!v.is_hide_possible_values_set() - && v.get_possible_values() - .iter() - .any(PossibleValue::should_show_help))) + v.get_long_help().is_some() + || v.is_hide_long_help_set() + || v.is_hide_short_help_set() + || v.get_possible_values() + .iter() + .any(PossibleValue::should_show_help) }; // Subcommands aren't checked because we prefer short help for them, deferring to diff --git a/src/builder/debug_asserts.rs b/src/builder/debug_asserts.rs index 86e36778cff6e145a667ca203236a67a1624f778..bfebbb4c43f38d096a2f84a74ca2190bb31e6a87 100644 --- a/src/builder/debug_asserts.rs +++ b/src/builder/debug_asserts.rs @@ -40,20 +40,20 @@ pub(crate) fn assert_app(cmd: &Command) { for sc in cmd.get_subcommands() { if let Some(s) = sc.get_short_flag().as_ref() { - short_flags.push(Flag::Command(format!("-{s}"), sc.get_name())); + short_flags.push(Flag::Command(format!("-{}", s), sc.get_name())); } for short_alias in sc.get_all_short_flag_aliases() { - short_flags.push(Flag::Command(format!("-{short_alias}"), sc.get_name())); + short_flags.push(Flag::Command(format!("-{}", short_alias), sc.get_name())); } if let Some(l) = sc.get_long_flag().as_ref() { assert!(!l.starts_with('-'), "Command {}: long_flag {:?} must not start with a `-`, that will be handled by the parser", sc.get_name(), l); - long_flags.push(Flag::Command(format!("--{l}"), sc.get_name())); + long_flags.push(Flag::Command(format!("--{}", l), sc.get_name())); } for long_alias in sc.get_all_long_flag_aliases() { - long_flags.push(Flag::Command(format!("--{long_alias}"), sc.get_name())); + long_flags.push(Flag::Command(format!("--{}", long_alias), sc.get_name())); } } @@ -68,20 +68,26 @@ pub(crate) fn assert_app(cmd: &Command) { ); if let Some(s) = arg.get_short() { - short_flags.push(Flag::Arg(format!("-{s}"), arg.get_id().as_str())); + short_flags.push(Flag::Arg(format!("-{}", s), arg.get_id().as_str())); } for (short_alias, _) in &arg.short_aliases { - short_flags.push(Flag::Arg(format!("-{short_alias}"), arg.get_id().as_str())); + short_flags.push(Flag::Arg( + format!("-{}", short_alias), + arg.get_id().as_str(), + )); } if let Some(l) = arg.get_long() { assert!(!l.starts_with('-'), "Argument {}: long {:?} must not start with a `-`, that will be handled by the parser", arg.get_id(), l); - long_flags.push(Flag::Arg(format!("--{l}"), arg.get_id().as_str())); + long_flags.push(Flag::Arg(format!("--{}", l), arg.get_id().as_str())); } for (long_alias, _) in &arg.aliases { - long_flags.push(Flag::Arg(format!("--{long_alias}"), arg.get_id().as_str())); + long_flags.push(Flag::Arg( + format!("--{}", long_alias), + arg.get_id().as_str(), + )); } // Name conflicts @@ -423,16 +429,19 @@ fn detect_duplicate_flags(flags: &[Flag], short_or_long: &str) { for (one, two) in find_duplicates(flags) { match (one, two) { (Command(flag, one), Command(_, another)) if one != another => panic!( - "the '{flag}' {short_or_long} flag is specified for both '{one}' and '{another}' subcommands" + "the '{}' {} flag is specified for both '{}' and '{}' subcommands", + flag, short_or_long, one, another ), (Arg(flag, one), Arg(_, another)) if one != another => panic!( - "{short_or_long} option names must be unique, but '{flag}' is in use by both '{one}' and '{another}'" + "{} option names must be unique, but '{}' is in use by both '{}' and '{}'", + short_or_long, flag, one, another ), (Arg(flag, arg), Command(_, sub)) | (Command(flag, sub), Arg(_, arg)) => panic!( - "the '{flag}' {short_or_long} flag for the '{arg}' argument conflicts with the short flag \ - for '{sub}' subcommand" + "the '{}' {} flag for the '{}' argument conflicts with the short flag \ + for '{}' subcommand", + flag, short_or_long, arg, sub ), _ => {} @@ -520,8 +529,10 @@ fn _verify_positionals(cmd: &Command) -> bool { assert!( highest_idx == num_p, - "Found positional argument whose index is {highest_idx} but there \ - are only {num_p} positional arguments defined", + "Found positional argument whose index is {} but there \ + are only {} positional arguments defined", + highest_idx, + num_p ); for arg in cmd.get_arguments() { diff --git a/src/builder/range.rs b/src/builder/range.rs index 6ecf05369a5fcbfceb86d1947e8467a10105668e..3f077bd86e64c50fd1167346a2c5b6b34f131717 100644 --- a/src/builder/range.rs +++ b/src/builder/range.rs @@ -183,7 +183,7 @@ impl std::fmt::Display for ValueRange { impl std::fmt::Debug for ValueRange { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "{self}") + write!(f, "{}", self) } } diff --git a/src/builder/str.rs b/src/builder/str.rs index be69c3f6ee632af3e63b62259da08b937683ab5b..c6689d31065cf819a4871e6b9909e65dc5506631 100644 --- a/src/builder/str.rs +++ b/src/builder/str.rs @@ -246,10 +246,7 @@ pub(crate) mod inner { } pub(crate) fn into_string(self) -> String { - match self { - Self::Static(s) => s.to_owned(), - Self::Owned(s) => s.into(), - } + self.as_str().to_owned() } } } diff --git a/src/builder/value_hint.rs b/src/builder/value_hint.rs index ee286b194c85bc5d154644b5fceb46673ffb00c5..812d5d8668b093ed9e33424ddcc3bc419c7cee1c 100644 --- a/src/builder/value_hint.rs +++ b/src/builder/value_hint.rs @@ -89,7 +89,7 @@ impl FromStr for ValueHint { "hostname" => ValueHint::Hostname, "url" => ValueHint::Url, "emailaddress" => ValueHint::EmailAddress, - _ => return Err(format!("unknown ValueHint: `{s}`")), + _ => return Err(format!("unknown ValueHint: `{}`", s)), }) } } diff --git a/src/derive.rs b/src/derive.rs index 98bb0121b6eb6c2bebc12a9efd5068c19ef064a6..a30f2da50ac66e36a3141fb6fe8049abf9469bf8 100644 --- a/src/derive.rs +++ b/src/derive.rs @@ -385,7 +385,7 @@ pub trait ValueEnum: Sized + Clone { .matches(input, ignore_case) }) .cloned() - .ok_or_else(|| format!("invalid variant: {input}")) + .ok_or_else(|| format!("invalid variant: {}", input)) } /// The canonical argument value. diff --git a/src/error/format.rs b/src/error/format.rs index d3ce6c64c19edcedc28422c64307928c32c778bf..98d34b7ef4e75d96f1208cf863b2b43f58d04f63 100644 --- a/src/error/format.rs +++ b/src/error/format.rs @@ -461,7 +461,7 @@ fn did_you_mean(styled: &mut StyledStr, context: &str, valid: &ContextValue) { fn escape(s: impl AsRef) -> String { let s = s.as_ref(); if s.contains(char::is_whitespace) { - format!("{s:?}") + format!("{:?}", s) } else { s.to_owned() } diff --git a/src/error/mod.rs b/src/error/mod.rs index 2d8bf62e47c752427482339e0945facc6834496d..9c8828574d469ad43f33a46d3862c012daeadf98 100644 --- a/src/error/mod.rs +++ b/src/error/mod.rs @@ -692,7 +692,7 @@ impl Error { Some((flag, None)) => { err = err.insert_context_unchecked( ContextKind::SuggestedArg, - ContextValue::String(format!("--{flag}")), + ContextValue::String(format!("--{}", flag)), ); } None => {} @@ -782,7 +782,7 @@ impl Display for Error { if let Some(backtrace) = self.inner.backtrace.as_ref() { ok!(writeln!(f)); ok!(writeln!(f, "Backtrace:")); - ok!(writeln!(f, "{backtrace}")); + ok!(writeln!(f, "{}", backtrace)); } Ok(()) } diff --git a/src/mkeymap.rs b/src/mkeymap.rs index e9d6ab8442e07e6196ad7bd863384a50a71e932e..a54fae455c0d8b1ee4301d22b984ad14edbdc4df 100644 --- a/src/mkeymap.rs +++ b/src/mkeymap.rs @@ -126,8 +126,6 @@ impl MKeyMap { /// We need a lazy build here since some we may change args after creating /// the map, you can checkout who uses `args_mut`. pub(crate) fn _build(&mut self) { - // There will be at least as many keys as args, so that is a good starting point - self.keys.reserve(self.args.len()); for (i, arg) in self.args.iter().enumerate() { append_keys(&mut self.keys, arg, i); } diff --git a/src/output/help_template.rs b/src/output/help_template.rs index e84cd727c79209f3bff0f918bd6f0f628a752e26..6fe9db1b4a7e8746a202a17d1eb364e5128cca46 100644 --- a/src/output/help_template.rs +++ b/src/output/help_template.rs @@ -368,8 +368,7 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { .get_subcommand_help_heading() .unwrap_or(&default_help_heading), ); - self.header(":"); - self.none("\n"); + self.header(":\n"); self.write_subcommands(self.cmd); } @@ -380,8 +379,7 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { } first = false; // Write positional args if any - self.header("Arguments:"); - self.none("\n"); + self.header("Arguments:\n"); self.write_args(&pos, "Arguments", positional_sort_key); } @@ -390,8 +388,7 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { self.none("\n\n"); } first = false; - self.header("Options:"); - self.none("\n"); + self.header("Options:\n"); self.write_args(&non_pos, "Options", option_sort_key); } if !custom_headings.is_empty() { @@ -413,9 +410,7 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { self.none("\n\n"); } first = false; - self.header(heading); - self.header(":"); - self.none("\n"); + self.header(format!("{}:\n", heading)); self.write_args(&args, heading, option_sort_key); } } @@ -490,7 +485,7 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { debug!("HelpTemplate::short"); if let Some(s) = arg.get_short() { - self.literal(format!("-{s}")); + self.literal(format!("-{}", s)); } else if arg.get_long().is_some() { self.none(" "); } @@ -503,7 +498,7 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { if arg.get_short().is_some() { self.none(", "); } - self.literal(format!("--{long}")); + self.literal(format!("--{}", long)); } } @@ -743,7 +738,7 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { .map(|pvs| pvs.to_string_lossy()) .map(|pvs| { if pvs.contains(char::is_whitespace) { - Cow::from(format!("{pvs:?}")) + Cow::from(format!("{:?}", pvs)) } else { pvs } @@ -751,7 +746,7 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { .collect::>() .join(" "); - spec_vals.push(format!("[default: {pvs}]")); + spec_vals.push(format!("[default: {}]", pvs)); } let als = a @@ -763,7 +758,7 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { .join(", "); if !als.is_empty() { debug!("HelpTemplate::spec_vals: Found aliases...{:?}", a.aliases); - spec_vals.push(format!("[aliases: {als}]")); + spec_vals.push(format!("[aliases: {}]", als)); } let als = a @@ -778,7 +773,7 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { "HelpTemplate::spec_vals: Found short aliases...{:?}", a.short_aliases ); - spec_vals.push(format!("[short aliases: {als}]")); + spec_vals.push(format!("[short aliases: {}]", als)); } let possible_vals = a.get_possible_values(); @@ -797,7 +792,7 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { .collect::>() .join(", "); - spec_vals.push(format!("[possible values: {pvs}]")); + spec_vals.push(format!("[possible values: {}]", pvs)); } let connector = if self.use_long { "\n" } else { " " }; spec_vals.join(connector) @@ -840,11 +835,11 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { styled.literal(subcommand.get_name()); if let Some(short) = subcommand.get_short_flag() { styled.none(", "); - styled.literal(format!("-{short}")); + styled.literal(format!("-{}", short)); } if let Some(long) = subcommand.get_long_flag() { styled.none(", "); - styled.literal(format!("--{long}")); + styled.literal(format!("--{}", long)); } longest = longest.max(styled.display_width()); ord_v.push((subcommand.get_display_order(), styled, subcommand)); @@ -907,7 +902,7 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { let mut short_als = a .get_visible_short_flag_aliases() - .map(|a| format!("-{a}")) + .map(|a| format!("-{}", a)) .collect::>(); let als = a.get_visible_aliases().map(|s| s.to_string()); short_als.extend(als); @@ -921,7 +916,7 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { "HelpTemplate::spec_vals: Found short flag aliases...{:?}", a.get_all_short_flag_aliases().collect::>() ); - spec_vals.push(format!("[aliases: {all_als}]")); + spec_vals.push(format!("[aliases: {}]", all_als)); } spec_vals.join(" ") diff --git a/src/output/textwrap/core.rs b/src/output/textwrap/core.rs index 25c9eb6b0e9362ad44c90a827b3d0036fb2d84ea..b890c6c7bca1c8bffa6f040106a7d4425132d6b8 100644 --- a/src/output/textwrap/core.rs +++ b/src/output/textwrap/core.rs @@ -105,7 +105,7 @@ mod tests { assert_eq!(ch.width().unwrap(), 1, "char: {}", desc); #[cfg(not(feature = "unicode"))] - assert_eq!(ch_width(ch), 1, "char: {desc}"); + assert_eq!(ch_width(ch), 1, "char: {}", desc); } } @@ -123,7 +123,7 @@ mod tests { assert!(ch.width().unwrap() <= 2, "char: {}", desc); #[cfg(not(feature = "unicode"))] - assert_eq!(ch_width(ch), 1, "char: {desc}"); + assert_eq!(ch_width(ch), 1, "char: {}", desc); } } diff --git a/src/parser/arg_matcher.rs b/src/parser/arg_matcher.rs index d584689cdbc204d201365c6a3700351976a4fc4c..c7e94e6782687af19959d7118c7d934f0c14f67f 100644 --- a/src/parser/arg_matcher.rs +++ b/src/parser/arg_matcher.rs @@ -217,9 +217,9 @@ impl ArgMatcher { raw_vals: Default::default(), trailing_idx: None, }); - debug_assert_eq!(pending.id, *id, "{INTERNAL_ERROR_MSG}"); + debug_assert_eq!(pending.id, *id, "{}", INTERNAL_ERROR_MSG); if ident.is_some() { - debug_assert_eq!(pending.ident, ident, "{INTERNAL_ERROR_MSG}"); + debug_assert_eq!(pending.ident, ident, "{}", INTERNAL_ERROR_MSG); } if trailing_values { pending.trailing_idx.get_or_insert(pending.raw_vals.len()); diff --git a/src/parser/error.rs b/src/parser/error.rs index 66b2bc79e85f324ee954ecd3705af26dd41efd61..5652336139f40e97f1ebbdaf932d69070225b12c 100644 --- a/src/parser/error.rs +++ b/src/parser/error.rs @@ -27,7 +27,10 @@ impl MatchesError { } Err(err) => err, }; - panic!("Mismatch between definition and access of `{id}`. {err}",) + panic!( + "Mismatch between definition and access of `{}`. {}", + id, err + ) } } @@ -39,7 +42,8 @@ impl std::fmt::Display for MatchesError { Self::Downcast { actual, expected } => { writeln!( f, - "Could not downcast to {expected:?}, need to downcast to {actual:?}" + "Could not downcast to {:?}, need to downcast to {:?}", + expected, actual ) } Self::UnknownArgument {} => { diff --git a/src/parser/matches/arg_matches.rs b/src/parser/matches/arg_matches.rs index 67d2918d0bd26b6413f615995a6b5b003b712cdc..23f53c02b9f2d20cbf1d7eb1faa7195358bc9a84 100644 --- a/src/parser/matches/arg_matches.rs +++ b/src/parser/matches/arg_matches.rs @@ -139,12 +139,9 @@ impl ArgMatches { /// ``` #[cfg_attr(debug_assertions, track_caller)] pub fn get_count(&self, id: &str) -> u8 { - *self.get_one::(id).unwrap_or_else(|| { - panic!( - "arg `{}`'s `ArgAction` should be `Count` which should provide a default", - id - ) - }) + *self + .get_one::(id) + .expect("ArgAction::Count is defaulted") } /// Gets the value of a specific [`ArgAction::SetTrue`][crate::ArgAction::SetTrue] or [`ArgAction::SetFalse`][crate::ArgAction::SetFalse] flag @@ -176,12 +173,7 @@ impl ArgMatches { pub fn get_flag(&self, id: &str) -> bool { *self .get_one::(id) - .unwrap_or_else(|| { - panic!( - "arg `{}`'s `ArgAction` should be one of `SetTrue`, `SetFalse` which should provide a default", - id - ) - }) + .expect("ArgAction::SetTrue / ArgAction::SetFalse is defaulted") } /// Iterate over values of a specific option or positional argument. @@ -1310,9 +1302,10 @@ impl ArgMatches { if arg == Id::EXTERNAL || self.valid_args.iter().any(|s| *s == arg) { } else { panic!( - "`{arg:?}` is not an id of an argument or a group.\n\ + "`{:?}` is not an id of an argument or a group.\n\ Make sure you're using the name of the argument itself \ - and not the name of short or long flags." + and not the name of short or long flags.", + arg ); } } @@ -1327,7 +1320,7 @@ impl ArgMatches { { if name.is_empty() || self.valid_subcommands.iter().any(|s| *s == name) { } else { - panic!("`{name}` is not a name of a subcommand."); + panic!("`{}` is not a name of a subcommand.", name); } } diff --git a/src/parser/parser.rs b/src/parser/parser.rs index 2579034318147c11328730045bd32d2fd4c05829..dc99e32ece6ea004f3f95ce31344f0eb9f9c28c8 100644 --- a/src/parser/parser.rs +++ b/src/parser/parser.rs @@ -895,7 +895,8 @@ impl<'cmd> Parser<'cmd> { debug_assert_eq!( res, Ok(()), - "tracking of `flag_subcmd_skip` is off for `{short_arg:?}`" + "tracking of `flag_subcmd_skip` is off for `{:?}`", + short_arg ); while let Some(c) = short_arg.next_flag() { let c = match c { @@ -981,7 +982,7 @@ impl<'cmd> Parser<'cmd> { Ok(ParseResult::FlagSubCommand(name)) } else { Ok(ParseResult::NoMatchingArg { - arg: format!("-{c}"), + arg: format!("-{}", c), }) }; } @@ -1569,7 +1570,7 @@ impl<'cmd> Parser<'cmd> { did_you_mean.is_none() && !trailing_values && self.cmd.has_positionals(); ClapError::unknown_argument( self.cmd, - format!("--{arg}"), + format!("--{}", arg), did_you_mean, suggested_trailing_arg, Usage::new(self.cmd) diff --git a/src/parser/validator.rs b/src/parser/validator.rs index 49d28a34f8cfaae69be1470f18a4d5e19fa82b98..991dc513f691c3d39644eee1164f771419d3ea8d 100644 --- a/src/parser/validator.rs +++ b/src/parser/validator.rs @@ -519,10 +519,13 @@ fn gather_direct_conflicts(cmd: &Command, id: &Id) -> Vec { } else if let Some(group) = cmd.find_group(id) { gather_group_direct_conflicts(group) } else { - debug_assert!(false, "id={id:?} is unknown"); + debug_assert!(false, "id={:?} is unknown", id); Vec::new() }; - debug!("Conflicts::gather_direct_conflicts id={id:?}, conflicts={conf:?}",); + debug!( + "Conflicts::gather_direct_conflicts id={:?}, conflicts={:?}", + id, conf + ); conf } diff --git a/src/util/color.rs b/src/util/color.rs index 5a0a8ce6d69c394a71ceb4d958626a279d893e71..4d59b2eb288dfed69815a8d4347d93022a9b6f11 100644 --- a/src/util/color.rs +++ b/src/util/color.rs @@ -82,7 +82,7 @@ impl std::str::FromStr for ColorChoice { return Ok(*variant); } } - Err(format!("invalid variant: {s}")) + Err(format!("invalid variant: {}", s)) } } diff --git a/tests/builder/help.rs b/tests/builder/help.rs index 28aed85556fe9f4abb0452c88321ae448524dd0f..984a86c245ffdeee5206260bd57710338f9800de 100644 --- a/tests/builder/help.rs +++ b/tests/builder/help.rs @@ -676,29 +676,6 @@ Options: utils::assert_output(app, "ctest --help", POS_VALS_HELP, false); } -#[test] -fn hidden_possible_vals() { - static POS_VALS_HELP: &str = "\ -Usage: ctest [pos] - -Arguments: - [pos] - -Options: - -h, --help Print help -"; - let app = Command::new("ctest").arg( - Arg::new("pos") - .hide_possible_values(true) - .value_parser([ - PossibleValue::new("fast"), - PossibleValue::new("slow").help("not as fast"), - ]) - .action(ArgAction::Set), - ); - utils::assert_output(app, "ctest --help", POS_VALS_HELP, false); -} - #[test] #[cfg(feature = "wrap_help")] fn issue_626_panic() { diff --git a/tests/builder/hidden_args.rs b/tests/builder/hidden_args.rs index 537c8fc1b5aa7041b068baf487de5d17bf34df9d..4cdfb24534988e639187903c0febfd4ac3a5792b 100644 --- a/tests/builder/hidden_args.rs +++ b/tests/builder/hidden_args.rs @@ -1,6 +1,6 @@ use super::utils; -use clap::{arg, builder::PossibleValue, Arg, ArgAction, Command}; +use clap::{arg, Arg, ArgAction, Command}; static HIDDEN_ARGS: &str = "\ tests stuff @@ -278,27 +278,3 @@ fn hide_subcmds_only() { utils::assert_output(cmd, "test --help", HIDDEN_SUBCMDS_ONLY, false); } - -#[test] -fn hidden_arg_with_possible_value_with_help() { - // Normally the presence of a possible value with a help text triggers a - // change of the --help help text by appending `(see more with '--help')` - // or `(see a summary with '-h')`. When the argument is completely hidden - // we however do not want it to trigger that change. - static POS_VALS_HELP: &str = "\ -Usage: ctest - -Options: - -h, --help Print help -"; - let app = Command::new("ctest").arg( - Arg::new("pos") - .hide(true) - .value_parser([ - PossibleValue::new("fast"), - PossibleValue::new("slow").help("not as fast"), - ]) - .action(ArgAction::Set), - ); - utils::assert_output(app, "ctest --help", POS_VALS_HELP, false); -} diff --git a/tests/builder/ignore_errors.rs b/tests/builder/ignore_errors.rs index dfb3575364023af6460a66333faaa5f17bfbef6d..c98cfc2e1420c6552d2d985b074f6a8f2b04f604 100644 --- a/tests/builder/ignore_errors.rs +++ b/tests/builder/ignore_errors.rs @@ -21,7 +21,7 @@ fn single_long_arg_without_value() { let r = cmd.try_get_matches_from(vec!["cmd", "--config" /* missing: , "config file" */]); - assert!(r.is_ok(), "unexpected error: {r:?}"); + assert!(r.is_ok(), "unexpected error: {:?}", r); let m = r.unwrap(); assert!(m.contains_id("config")); } diff --git a/tests/builder/positionals.rs b/tests/builder/positionals.rs index f15b2edc316b3fe1fb5bbfdf5a88ddcfa47e2c8c..b931b119abe23fd6a9b31f7f4b1d563983ee8c85 100644 --- a/tests/builder/positionals.rs +++ b/tests/builder/positionals.rs @@ -179,7 +179,7 @@ fn positional_possible_values() { Arg::new("positional").index(1).value_parser(["test123"]), ]) .try_get_matches_from(vec!["", "-f", "test123"]); - assert!(r.is_ok(), "{r:#?}"); + assert!(r.is_ok(), "{:#?}", r); let m = r.unwrap(); assert!(m.contains_id("positional")); assert!(*m.get_one::("flag").expect("defaulted by clap")); diff --git a/tests/builder/tests.rs b/tests/builder/tests.rs index a7148574fe4e250ae4f2c2f272b2464323486148..072a8773cc300306872349f593eb3753cac0af48 100644 --- a/tests/builder/tests.rs +++ b/tests/builder/tests.rs @@ -195,7 +195,7 @@ pub fn check_complex_output(args: &str, out: &str) { } if let Some(p) = matches.get_one::("positional").map(|v| v.as_str()) { - writeln!(w, "positional present with value: {p}").unwrap(); + writeln!(w, "positional present with value: {}", p).unwrap(); } else { writeln!(w, "positional NOT present").unwrap(); } @@ -207,17 +207,17 @@ pub fn check_complex_output(args: &str, out: &str) { writeln!(w, "flag NOT present").unwrap(); } n => { - writeln!(w, "flag present {n} times").unwrap(); + writeln!(w, "flag present {} times", n).unwrap(); } } if matches.contains_id("option") { if let Some(v) = matches.get_one::("option").map(|v| v.as_str()) { - writeln!(w, "scoption present with value: {v}").unwrap(); + writeln!(w, "scoption present with value: {}", v).unwrap(); } if let Some(ov) = matches.get_many::("option") { for o in ov { - writeln!(w, "An scoption: {o}").unwrap(); + writeln!(w, "An scoption: {}", o).unwrap(); } } } else { @@ -228,7 +228,7 @@ pub fn check_complex_output(args: &str, out: &str) { .get_one::("scpositional") .map(|v| v.as_str()) { - writeln!(w, "scpositional present with value: {p}").unwrap(); + writeln!(w, "scpositional present with value: {}", p).unwrap(); } } } else { diff --git a/tests/builder/utils.rs b/tests/builder/utils.rs index e0b434e2956055d81ed5ef78f336b7e88b446690..f76efbec26c0f74825106151a5610ed77d66b923 100644 --- a/tests/builder/utils.rs +++ b/tests/builder/utils.rs @@ -28,7 +28,7 @@ pub fn assert_output(l: Command, args: &str, expected: &str, stderr: bool) { let mut buf = Cursor::new(Vec::with_capacity(50)); let res = l.try_get_matches_from(args.split(' ').collect::>()); let err = res.unwrap_err(); - write!(&mut buf, "{err}").unwrap(); + write!(&mut buf, "{}", err).unwrap(); let actual = buf.into_inner(); let actual = String::from_utf8(actual).unwrap(); assert_eq!( diff --git a/tests/derive/groups.rs b/tests/derive/groups.rs index 1c9bcb50762381b02dc164afe9422b2ec88f14a2..88f674a5e8099e9e1155f47f40c1ad42badd6448 100644 --- a/tests/derive/groups.rs +++ b/tests/derive/groups.rs @@ -73,9 +73,9 @@ fn skip_group_avoids_duplicate_ids() { #[derive(clap::Args, Debug)] #[group(skip)] pub struct Compose { - #[command(flatten)] + #[clap(flatten)] pub left: L, - #[command(flatten)] + #[clap(flatten)] pub right: R, } @@ -108,9 +108,9 @@ fn helpful_panic_on_duplicate_groups() { #[derive(clap::Args, Debug)] pub struct Compose { - #[command(flatten)] + #[clap(flatten)] pub left: L, - #[command(flatten)] + #[clap(flatten)] pub right: R, } diff --git a/tests/derive/utils.rs b/tests/derive/utils.rs index d08ef999283292017613c499954b352a146a71a4..a6a0e36d91759e478deba199862ab762a666de94 100644 --- a/tests/derive/utils.rs +++ b/tests/derive/utils.rs @@ -17,8 +17,8 @@ pub const FULL_TEMPLATE: &str = "\ pub fn get_help() -> String { let output = ::command().render_help().to_string(); - eprintln!("\n%%% HELP %%%:=====\n{output}\n=====\n"); - eprintln!("\n%%% HELP (DEBUG) %%%:=====\n{output:?}\n=====\n"); + eprintln!("\n%%% HELP %%%:=====\n{}\n=====\n", output); + eprintln!("\n%%% HELP (DEBUG) %%%:=====\n{:?}\n=====\n", output); output } @@ -28,8 +28,8 @@ pub fn get_long_help() -> String { .render_long_help() .to_string(); - eprintln!("\n%%% LONG_HELP %%%:=====\n{output}\n=====\n"); - eprintln!("\n%%% LONG_HELP (DEBUG) %%%:=====\n{output:?}\n=====\n"); + eprintln!("\n%%% LONG_HELP %%%:=====\n{}\n=====\n", output); + eprintln!("\n%%% LONG_HELP (DEBUG) %%%:=====\n{:?}\n=====\n", output); output } @@ -42,8 +42,14 @@ pub fn get_subcommand_long_help(subcmd: &str) -> String { .render_long_help() .to_string(); - eprintln!("\n%%% SUBCOMMAND `{subcmd}` HELP %%%:=====\n{output}\n=====\n",); - eprintln!("\n%%% SUBCOMMAND `{subcmd}` HELP (DEBUG) %%%:=====\n{output:?}\n=====\n",); + eprintln!( + "\n%%% SUBCOMMAND `{}` HELP %%%:=====\n{}\n=====\n", + subcmd, output + ); + eprintln!( + "\n%%% SUBCOMMAND `{}` HELP (DEBUG) %%%:=====\n{:?}\n=====\n", + subcmd, output + ); output } diff --git a/tests/derive_ui/clap_empty_attr.stderr b/tests/derive_ui/clap_empty_attr.stderr index 596fbe09db7b6e2328b03486d8ea65f1a6dcfd1a..414ffdc0f49d8528fd68b8bd3dda1150393bca61 100644 --- a/tests/derive_ui/clap_empty_attr.stderr +++ b/tests/derive_ui/clap_empty_attr.stderr @@ -1,8 +1,8 @@ error: expected attribute arguments in parentheses: #[command(...)] - --> tests/derive_ui/clap_empty_attr.rs:4:3 + --> tests/derive_ui/clap_empty_attr.rs:4:1 | 4 | #[command] - | ^^^^^^^ + | ^^^^^^^^^^ error: expected parentheses: #[arg(...)] --> tests/derive_ui/clap_empty_attr.rs:9:11 diff --git a/tests/derive_ui/default_values_t_invalid.stderr b/tests/derive_ui/default_values_t_invalid.stderr index 78a336960fd7b4f2bd606ccdb9dd9814dc202274..c8923f3f621f3d0d1ad2f6031064a236f4ab718d 100644 --- a/tests/derive_ui/default_values_t_invalid.stderr +++ b/tests/derive_ui/default_values_t_invalid.stderr @@ -1,6 +1,6 @@ error: #[arg(default_values_t)] can be used only on Vec types - = note: see https://github.com/clap-rs/clap/blob/master/examples/derive_ref/README.md#magic-attributes + = note: see https://github.com/clap-rs/clap/blob/master/examples/derive_ref/README.md#magic-attributes --> tests/derive_ui/default_values_t_invalid.rs:6:11 |