chore: Update from template

This commit is contained in:
Ed Page 2024-05-04 21:59:40 +02:00
commit 800d7cb8ad
142 changed files with 853 additions and 852 deletions

View file

@ -1,5 +1,4 @@
msrv = "1.74" # MSRV
warn-on-all-wildcard-imports = true
allow-print-in-tests = true
allow-expect-in-tests = true
allow-unwrap-in-tests = true
allow-dbg-in-tests = true

View file

@ -3,6 +3,7 @@
'before 5am on the first day of the month',
],
semanticCommits: 'enabled',
commitMessageLowerCase: 'never',
configMigration: true,
dependencyDashboard: true,
customManagers: [
@ -19,29 +20,28 @@
'^\\.github/workflows/rust-next.yml$',
],
matchStrings: [
'MSRV.*?(?<currentValue>\\d+\\.\\d+(\\.\\d+)?)',
'(?<currentValue>\\d+\\.\\d+(\\.\\d+)?).*?MSRV',
'STABLE.*?(?<currentValue>\\d+\\.\\d+(\\.\\d+)?)',
'(?<currentValue>\\d+\\.\\d+(\\.\\d+)?).*?STABLE',
],
depNameTemplate: 'rust',
depNameTemplate: 'STABLE',
packageNameTemplate: 'rust-lang/rust',
datasourceTemplate: 'github-releases',
},
],
packageRules: [
{
commitMessageTopic: 'MSRV',
commitMessageTopic: 'Rust Stable',
matchManagers: [
'custom.regex',
],
matchPackageNames: [
'rust',
'STABLE',
],
minimumReleaseAge: '252 days', // 6 releases * 6 weeks per release * 7 days per week
internalChecksFilter: 'strict',
extractVersion: '^(?<version>\\d+\\.\\d+)', // Drop the patch version
schedule: [
'* * * * *',
],
automerge: true,
},
// Goals:
// - Keep version reqs low, ignoring compatible normal/build dependencies
@ -74,6 +74,7 @@
matchCurrentVersion: '>=1.0.0',
matchUpdateTypes: [
'minor',
'patch',
],
enabled: false,
},
@ -101,6 +102,7 @@
matchCurrentVersion: '>=1.0.0',
matchUpdateTypes: [
'minor',
'patch',
],
automerge: true,
groupName: 'compatible (dev)',

46
.github/settings.yml vendored
View file

@ -101,34 +101,18 @@ repository:
# description: "Meta: Request for post-merge review."
# color: '#E10C02'
branches:
- name: master
protection:
required_pull_request_reviews: null
required_conversation_resolution: true
required_status_checks:
# Required. Require branches to be up to date before merging.
strict: false
contexts: ["CI", "Lint Commits", "Spell Check with Typos"]
enforce_admins: false
restrictions: null
- name: v2-master
protection:
required_pull_request_reviews: null
required_conversation_resolution: true
required_status_checks:
# Required. Require branches to be up to date before merging.
strict: false
contexts: ["CI", "Lint Commits", "Spell Check with Typos"]
enforce_admins: false
restrictions: null
- name: v3-master
protection:
required_pull_request_reviews: null
required_conversation_resolution: true
required_status_checks:
# Required. Require branches to be up to date before merging.
strict: false
contexts: ["CI", "Lint Commits", "Spell Check with Typos"]
enforce_admins: false
restrictions: null
# This serves more as documentation.
# Branch protection API was replaced by rulesets but settings isn't updated.
# See https://github.com/repository-settings/app/issues/825
#
# branches:
# - name: master
# protection:
# required_pull_request_reviews: null
# required_conversation_resolution: true
# required_status_checks:
# # Required. Require branches to be up to date before merging.
# strict: false
# contexts: ["CI", "Spell Check with Typos"]
# enforce_admins: false
# restrictions: null

View file

@ -17,6 +17,10 @@ env:
CARGO_TERM_COLOR: always
CLICOLOR: 1
concurrency:
group: "${{ github.workflow }}-${{ github.ref }}"
cancel-in-progress: true
jobs:
security_audit:
permissions:

View file

@ -14,16 +14,22 @@ env:
CARGO_TERM_COLOR: always
CLICOLOR: 1
concurrency:
group: "${{ github.workflow }}-${{ github.ref }}"
cancel-in-progress: true
jobs:
ci:
permissions:
contents: none
name: CI
needs: [test, check, docs, rustfmt, clippy, cffconvert]
needs: [test, check, lockfile, docs, rustfmt, clippy, cffconvert]
runs-on: ubuntu-latest
if: "always()"
steps:
- name: Done
run: exit 0
- name: Failed
run: exit 1
if: "contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') || contains(needs.*.result, 'skipped')"
test:
name: Test
strategy:
@ -39,7 +45,7 @@ jobs:
rust: "stable"
features: "full"
- build: mac
os: macos-latest
os: macos-14
rust: "stable"
features: "full"
- build: minimal
@ -64,6 +70,7 @@ jobs:
with:
toolchain: ${{ matrix.rust }}
- uses: Swatinem/rust-cache@v2
- uses: taiki-e/install-action@cargo-hack
- name: Build
run: make build-${{matrix.features}}
- name: Test
@ -144,7 +151,7 @@ jobs:
toolchain: stable
- uses: Swatinem/rust-cache@v2
- name: "Is lockfile updated?"
run: cargo fetch --locked
run: cargo update --workspace --locked
docs:
name: Docs
runs-on: ubuntu-latest
@ -154,7 +161,7 @@ jobs:
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
toolchain: "1.74" # MSRV
toolchain: "1.76" # STABLE
- uses: Swatinem/rust-cache@v2
- name: Check documentation
env:
@ -169,9 +176,7 @@ jobs:
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
# Not MSRV because its harder to jump between versions and people are
# more likely to have stable
toolchain: stable
toolchain: "1.76" # STABLE
components: rustfmt
- uses: Swatinem/rust-cache@v2
- name: Check formatting
@ -185,7 +190,7 @@ jobs:
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
toolchain: "1.74" # MSRV
toolchain: "1.76" # STABLE
components: clippy
- uses: Swatinem/rust-cache@v2
- name: Lint (ultra-minimal)

View file

@ -11,6 +11,10 @@ env:
CARGO_TERM_COLOR: always
CLICOLOR: 1
concurrency:
group: "${{ github.workflow }}-${{ github.ref }}"
cancel-in-progress: true
jobs:
committed:
name: Lint Commits

View file

@ -12,6 +12,10 @@ env:
CARGO_TERM_COLOR: always
CLICOLOR: 1
concurrency:
group: "${{ github.workflow }}-${{ github.ref }}"
cancel-in-progress: true
jobs:
pre-commit:
permissions:

View file

@ -12,6 +12,10 @@ env:
CARGO_TERM_COLOR: always
CLICOLOR: 1
concurrency:
group: "${{ github.workflow }}-${{ github.ref }}"
cancel-in-progress: true
jobs:
test:
name: Test
@ -32,7 +36,7 @@ jobs:
rust: "beta"
features: "full"
- build: mac
os: macos-latest
os: macos-14
rust: "beta"
features: "full"
- build: nightly
@ -91,6 +95,7 @@ jobs:
with:
toolchain: stable
- uses: Swatinem/rust-cache@v2
- uses: taiki-e/install-action@cargo-hack
- name: Update dependencues
run: cargo update
- name: Build

View file

@ -10,6 +10,10 @@ env:
CARGO_TERM_COLOR: always
CLICOLOR: 1
concurrency:
group: "${{ github.workflow }}-${{ github.ref }}"
cancel-in-progress: true
jobs:
spelling:
name: Spell Check with Typos

17
Cargo.lock generated
View file

@ -160,6 +160,17 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "automod"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edf3ee19dbc0a46d740f6f0926bde8c50f02bdbc7b536842da28f6ac56513a8b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
]
[[package]]
name = "backtrace"
version = "0.3.67"
@ -401,6 +412,7 @@ dependencies = [
name = "clap"
version = "4.5.4"
dependencies = [
"automod",
"clap_builder 4.5.2",
"clap_derive",
"humantime",
@ -454,6 +466,7 @@ dependencies = [
name = "clap_complete"
version = "4.5.2"
dependencies = [
"automod",
"clap 4.5.4",
"clap_lex 0.7.0",
"completest",
@ -505,11 +518,15 @@ checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
[[package]]
name = "clap_lex"
version = "0.7.0"
dependencies = [
"automod",
]
[[package]]
name = "clap_mangen"
version = "0.2.20"
dependencies = [
"automod",
"clap 4.5.4",
"roff",
"snapbox",

View file

@ -25,6 +25,79 @@ include = [
"examples/**/*"
]
[workspace.lints.rust]
rust_2018_idioms = "warn"
unreachable_pub = "warn"
unsafe_op_in_unsafe_fn = "warn"
unused_lifetimes = "warn"
unused_macro_rules = "warn"
unused_qualifications = "warn"
[workspace.lints.clippy]
bool_assert_comparison = "allow"
branches_sharing_code = "allow"
checked_conversions = "warn"
collapsible_else_if = "allow"
create_dir = "warn"
dbg_macro = "warn"
debug_assert_with_mut_call = "warn"
doc_markdown = "warn"
empty_enum = "warn"
enum_glob_use = "warn"
expl_impl_clone_on_copy = "warn"
explicit_deref_methods = "warn"
explicit_into_iter_loop = "warn"
fallible_impl_from = "warn"
filter_map_next = "warn"
flat_map_option = "warn"
float_cmp_const = "warn"
fn_params_excessive_bools = "warn"
from_iter_instead_of_collect = "warn"
if_same_then_else = "allow"
implicit_clone = "warn"
imprecise_flops = "warn"
inconsistent_struct_constructor = "warn"
inefficient_to_string = "warn"
infinite_loop = "warn"
invalid_upcast_comparisons = "warn"
large_digit_groups = "warn"
large_stack_arrays = "warn"
large_types_passed_by_value = "warn"
let_and_return = "allow" # sometimes good to name what you are returning
linkedlist = "warn"
lossy_float_literal = "warn"
macro_use_imports = "warn"
match_wildcard_for_single_variants = "warn"
mem_forget = "warn"
mutex_integer = "warn"
needless_continue = "warn"
needless_for_each = "warn"
negative_feature_names = "warn"
path_buf_push_overwrite = "warn"
ptr_as_ptr = "warn"
rc_mutex = "warn"
redundant_feature_names = "warn"
ref_option_ref = "warn"
rest_pat_in_fully_bound_structs = "warn"
same_functions_in_if_condition = "warn"
self_named_module_files = "warn"
semicolon_if_nothing_returned = "warn"
# single_match_else = "warn"
# str_to_string = "warn"
# string_add = "warn"
string_add_assign = "warn"
string_lit_as_bytes = "warn"
# string_to_string = "warn"
todo = "warn"
trait_duplication_in_bounds = "warn"
verbose_file_reads = "warn"
# wildcard_imports = "warn"
zero_sized_map_values = "warn"
# Fix later:
multiple_bound_locations = "allow"
assigning_clones = "allow"
blocks_in_conditions = "allow"
[package]
name = "clap"
version = "4.5.4"
@ -113,6 +186,7 @@ trycmd = { version = "0.15.1", default-features = false, features = ["color-auto
humantime = "2.1.0"
snapbox = "0.5.9"
shlex = "1.3.0"
automod = "1.0.14"
[[example]]
name = "demo"
@ -381,3 +455,6 @@ opt-level = 1
[profile.bench]
lto = true
codegen-units = 1
[lints]
workspace = true

View file

@ -35,3 +35,6 @@ name = "rustup"
[[bench]]
harness = false
name = "ripgrep"
[lints]
workspace = true

View file

@ -1,3 +1,5 @@
#![allow(elided_lifetimes_in_paths)] // needed for divan
use clap::{arg, ArgMatches, Command};
macro_rules! create_app {

View file

@ -1,3 +1,5 @@
#![allow(elided_lifetimes_in_paths)] // needed for divan
use clap::ArgMatches;
use clap::Command;

View file

@ -1,7 +1,9 @@
// Used to simulate a fairly large number of options/flags and parsing with thousands of positional
// args
//
// CLI used is adapted from ripgrep 48a8a3a691220f9e5b2b08f4051abe8655ea7e8a
//! Used to simulate a fairly large number of options/flags and parsing with thousands of positional
//! args
//!
//! CLI used is adapted from ripgrep 48a8a3a691220f9e5b2b08f4051abe8655ea7e8a
#![allow(elided_lifetimes_in_paths)] // needed for divan
use std::collections::HashMap;
@ -9,7 +11,7 @@ use clap::{value_parser, Arg, ArgAction, ArgMatches, Command};
use lazy_static::lazy_static;
mod build {
use super::*;
use super::{app_long, app_short, Command};
#[divan::bench]
fn short_help() -> Command {
@ -23,7 +25,7 @@ mod build {
}
mod render_help {
use super::*;
use super::{app_long, app_short, build_help};
#[divan::bench]
fn short_help(bencher: divan::Bencher) {
@ -39,7 +41,7 @@ mod render_help {
}
mod startup {
use super::*;
use super::{app_short, ArgMatches};
#[divan::bench]
fn simple() -> ArgMatches {

View file

@ -1,6 +1,8 @@
// Used to simulate a fairly large number of subcommands
//
// CLI used is from rustup 408ed84f0e50511ed44a405dd91365e5da588790
//! Used to simulate a fairly large number of subcommands
//!
//! CLI used is from rustup 408ed84f0e50511ed44a405dd91365e5da588790
#![allow(elided_lifetimes_in_paths)] // needed for divan
use clap::{Arg, ArgAction, ArgGroup, ArgMatches, Command};
@ -10,7 +12,7 @@ fn build() -> Command {
}
mod startup {
use super::*;
use super::{build_cli, ArgMatches};
#[divan::bench]
fn empty() -> ArgMatches {

View file

@ -1,3 +1,5 @@
#![allow(elided_lifetimes_in_paths)] // needed for divan
use clap::{arg, ArgMatches, Command};
macro_rules! create_app {
@ -18,7 +20,7 @@ fn build() -> Command {
}
mod startup {
use super::*;
use super::{arg, ArgMatches, Command};
#[divan::bench]
fn flag() -> ArgMatches {

View file

@ -1 +1,4 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![forbid(unsafe_code)]
#![warn(clippy::print_stderr)]
#![warn(clippy::print_stdout)]

View file

@ -71,3 +71,6 @@ unicode-width = { version = "0.1.9", optional = true }
static_assertions = "1.1.0"
unic-emoji-char = "0.9.0"
color-print = "0.3.6"
[lints]
workspace = true

View file

@ -510,10 +510,10 @@ impl Arg {
self
}
/// This is a "VarArg" and everything that follows should be captured by it, as if the user had
/// This is a "var arg" and everything that follows should be captured by it, as if the user had
/// used a `--`.
///
/// **NOTE:** To start the trailing "VarArg" on unknown flags (and not just a positional
/// **NOTE:** To start the trailing "var arg" on unknown flags (and not just a positional
/// value), set [`allow_hyphen_values`][Arg::allow_hyphen_values]. Either way, users still
/// have the option to explicitly escape ambiguous arguments with `--`.
///
@ -875,7 +875,7 @@ impl Arg {
impl Arg {
/// Specify how to react to an argument when parsing it.
///
/// [ArgAction] controls things like
/// [`ArgAction`] controls things like
/// - Overwriting previous values with new ones
/// - Appending new values to all previous ones
/// - Counting how many times a flag occurs
@ -997,7 +997,7 @@ impl Arg {
/// - It reaches the [`Arg::value_terminator`] if set
///
/// Alternatively,
/// - Use a delimiter between values with [Arg::value_delimiter]
/// - Use a delimiter between values with [`Arg::value_delimiter`]
/// - Require a flag occurrence per value with [`ArgAction::Append`]
/// - Require positional arguments to appear after `--` with [`Arg::last`]
///
@ -1018,7 +1018,7 @@ impl Arg {
/// assert_eq!(m.get_one::<String>("mode").unwrap(), "fast");
/// ```
///
/// Flag/option hybrid (see also [default_missing_value][Arg::default_missing_value])
/// Flag/option hybrid (see also [`default_missing_value`][Arg::default_missing_value])
/// ```rust
/// # use clap_builder as clap;
/// # use clap::{Command, Arg, error::ErrorKind, ArgAction};
@ -3641,8 +3641,8 @@ impl Arg {
/// only need to be set for one of the two arguments, they do not need to be set for each.
///
/// **NOTE:** Defining a conflict is two-way, but does *not* need to defined for both arguments
/// (i.e. if A conflicts with B, defining A.conflicts_with(B) is sufficient. You do not
/// need to also do B.conflicts_with(A))
/// (i.e. if A conflicts with B, defining `A.conflicts_with(B)` is sufficient. You do not
/// need to also do `B.conflicts_with(A)`)
///
/// **NOTE:** [`Arg::conflicts_with_all(names)`] allows specifying an argument which conflicts with more than one argument.
///
@ -3701,8 +3701,8 @@ impl Arg {
/// only need to be set for one of the two arguments, they do not need to be set for each.
///
/// **NOTE:** Defining a conflict is two-way, but does *not* need to defined for both arguments
/// (i.e. if A conflicts with B, defining A.conflicts_with(B) is sufficient. You do not need
/// need to also do B.conflicts_with(A))
/// (i.e. if A conflicts with B, defining `A.conflicts_with(B)` is sufficient. You do not need
/// need to also do `B.conflicts_with(A)`)
///
/// **NOTE:** [`Arg::exclusive(true)`] allows specifying an argument which conflicts with every other argument.
///
@ -3992,7 +3992,7 @@ impl Arg {
self.val_delim
}
/// Get the value terminator for this argument. The value_terminator is a value
/// Get the value terminator for this argument. The `value_terminator` is a value
/// that terminates parsing of multi-valued arguments.
#[inline]
pub fn get_value_terminator(&self) -> Option<&Str> {
@ -4094,8 +4094,8 @@ impl Arg {
}
/// Behavior when parsing the argument
pub fn get_action(&self) -> &super::ArgAction {
const DEFAULT: super::ArgAction = super::ArgAction::Set;
pub fn get_action(&self) -> &ArgAction {
const DEFAULT: ArgAction = ArgAction::Set;
self.action.as_ref().unwrap_or(&DEFAULT)
}
@ -4202,7 +4202,7 @@ impl Arg {
pub(crate) fn _build(&mut self) {
if self.action.is_none() {
if self.num_vals == Some(ValueRange::EMPTY) {
let action = super::ArgAction::SetTrue;
let action = ArgAction::SetTrue;
self.action = Some(action);
} else {
let action =
@ -4211,9 +4211,9 @@ impl Arg {
//
// Bounded values are probably a group and the user should explicitly opt-in to
// Append
super::ArgAction::Append
ArgAction::Append
} else {
super::ArgAction::Set
ArgAction::Set
};
self.action = Some(action);
}
@ -4432,14 +4432,14 @@ impl Ord for Arg {
impl Eq for Arg {}
impl Display for Arg {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
let plain = Styles::plain();
self.stylized(&plain, None).fmt(f)
}
}
impl fmt::Debug for Arg {
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
let mut ds = f.debug_struct("Arg");
#[allow(unused_mut)]
@ -4519,7 +4519,7 @@ mod test {
.action(ArgAction::SetTrue);
f._build();
assert_eq!(f.to_string(), "--flag")
assert_eq!(f.to_string(), "--flag");
}
#[test]
@ -4542,7 +4542,7 @@ mod test {
f.short_aliases = vec![('b', true)];
f._build();
assert_eq!(f.to_string(), "-a")
assert_eq!(f.to_string(), "-a");
}
#[test]

View file

@ -236,7 +236,7 @@ impl ArgGroup {
/// // maybe we don't know which of the two flags was used...
/// assert!(m.contains_id("req_flags"));
/// ```
/// In this next example, we show the default behavior (i.e. `multiple(false)) which will throw
/// In this next example, we show the default behavior (i.e. `multiple(false)`) which will throw
/// an error if more than one of the args in the group was used.
///
/// ```rust
@ -585,7 +585,7 @@ mod test {
#[test]
fn arg_group_send_sync() {
fn foo<T: Send + Sync>(_: T) {}
foo(ArgGroup::new("test"))
foo(ArgGroup::new("test"));
}
#[test]

View file

@ -447,7 +447,7 @@ impl Command {
/// ```
#[must_use]
pub fn groups(mut self, groups: impl IntoIterator<Item = impl Into<ArgGroup>>) -> Self {
for g in groups.into_iter() {
for g in groups {
self = self.group(g.into());
}
self
@ -545,7 +545,7 @@ impl Command {
/// that exhaustively test your CLI to ensure the asserts are evaluated, this will run those
/// asserts in a way convenient for running as a test.
///
/// **Note::** This will not help with asserts in [`ArgMatches`], those will need exhaustive
/// **Note:** This will not help with asserts in [`ArgMatches`], those will need exhaustive
/// testing of your CLI.
///
/// # Examples
@ -584,7 +584,7 @@ impl Command {
/// let mut cmd = Command::new("myprog");
/// let err = cmd.error(ErrorKind::InvalidValue, "Some failure case");
/// ```
pub fn error(&mut self, kind: ErrorKind, message: impl std::fmt::Display) -> Error {
pub fn error(&mut self, kind: ErrorKind, message: impl fmt::Display) -> Error {
Error::raw(kind, message).format(self)
}
@ -2567,7 +2567,7 @@ impl Command {
#[must_use]
pub fn long_flag_aliases(mut self, names: impl IntoIterator<Item = impl Into<Str>>) -> Self {
for s in names {
self = self.long_flag_alias(s)
self = self.long_flag_alias(s);
}
self
}
@ -3750,7 +3750,7 @@ impl Command {
// Subcommand_1.1.1 (contains Arg)
//
fn get_subcommands_containing(&self, arg: &Arg) -> Vec<&Self> {
let mut vec = std::vec::Vec::new();
let mut vec = Vec::new();
for idx in 0..self.subcommands.len() {
if self.subcommands[idx]
.args
@ -4592,7 +4592,7 @@ impl Command {
#[inline]
pub(crate) fn set(&mut self, s: AppSettings) {
self.settings.set(s)
self.settings.set(s);
}
#[inline]
@ -4656,7 +4656,7 @@ impl Command {
/// Iterate through all the names of all subcommands (not recursively), including aliases.
/// Used for suggestions.
pub(crate) fn all_subcommand_names(&self) -> impl Iterator<Item = &str> + Captures {
pub(crate) fn all_subcommand_names(&self) -> impl Iterator<Item = &str> + Captures<'_> {
self.get_subcommands().flat_map(|sc| {
let name = sc.get_name();
let aliases = sc.get_all_aliases();
@ -4699,7 +4699,7 @@ impl Command {
if !args.contains(n) {
if self.find(n).is_some() {
debug!("Command::unroll_args_in_group:iter: this is an arg");
args.push(n.clone())
args.push(n.clone());
} else {
debug!("Command::unroll_args_in_group:iter: this is a group");
g_vec.push(n);
@ -4730,7 +4730,7 @@ impl Command {
for r in arg.requires.iter().filter_map(&func) {
if let Some(req) = self.find(&r) {
if !req.requires.is_empty() {
r_vec.push(req.get_id())
r_vec.push(req.get_id());
}
}
args.push(r);
@ -4880,11 +4880,12 @@ impl From<&'_ Command> for Command {
}
impl fmt::Display for Command {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.name)
}
}
#[allow(dead_code)] // atm dependent on features enabled
pub(crate) trait AppTag: crate::builder::ext::Extension {}
#[derive(Default, Copy, Clone, Debug)]

View file

@ -398,26 +398,24 @@ enum Flag<'a> {
}
impl PartialEq for Flag<'_> {
fn eq(&self, other: &Flag) -> bool {
fn eq(&self, other: &Flag<'_>) -> bool {
self.cmp(other) == Ordering::Equal
}
}
impl PartialOrd for Flag<'_> {
fn partial_cmp(&self, other: &Flag) -> Option<Ordering> {
fn partial_cmp(&self, other: &Flag<'_>) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Flag<'_> {
fn cmp(&self, other: &Self) -> Ordering {
use Flag::*;
match (self, other) {
(Command(s1, _), Command(s2, _))
| (Arg(s1, _), Arg(s2, _))
| (Command(s1, _), Arg(s2, _))
| (Arg(s1, _), Command(s2, _)) => {
(Flag::Command(s1, _), Flag::Command(s2, _))
| (Flag::Arg(s1, _), Flag::Arg(s2, _))
| (Flag::Command(s1, _), Flag::Arg(s2, _))
| (Flag::Arg(s1, _), Flag::Command(s2, _)) => {
if s1 == s2 {
Ordering::Equal
} else {
@ -428,20 +426,18 @@ impl Ord for Flag<'_> {
}
}
fn detect_duplicate_flags(flags: &[Flag], short_or_long: &str) {
use Flag::*;
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!(
(Flag::Command(flag, one), Flag::Command(_, another)) if one != another => panic!(
"the '{flag}' {short_or_long} flag is specified for both '{one}' and '{another}' subcommands"
),
(Arg(flag, one), Arg(_, another)) if one != another => panic!(
(Flag::Arg(flag, one), Flag::Arg(_, another)) if one != another => panic!(
"{short_or_long} option names must be unique, but '{flag}' is in use by both '{one}' and '{another}'"
),
(Arg(flag, arg), Command(_, sub)) | (Command(flag, sub), Arg(_, arg)) => panic!(
(Flag::Arg(flag, arg), Flag::Command(_, sub)) | (Flag::Command(flag, sub), Flag::Arg(_, arg)) => panic!(
"the '{flag}' {short_or_long} flag for the '{arg}' argument conflicts with the short flag \
for '{sub}' subcommand"
),
@ -467,22 +463,6 @@ fn find_duplicates<T: PartialEq>(slice: &[T]) -> impl Iterator<Item = (&T, &T)>
fn assert_app_flags(cmd: &Command) {
macro_rules! checker {
($a:ident requires $($b:ident)|+) => {
if cmd.$a() {
let mut s = String::new();
$(
if !cmd.$b() {
use std::fmt::Write;
write!(&mut s, " AppSettings::{} is required when AppSettings::{} is set.\n", std::stringify!($b), std::stringify!($a)).unwrap();
}
)+
if !s.is_empty() {
panic!("{s}")
}
}
};
($a:ident conflicts $($b:ident)|+) => {
if cmd.$a() {
let mut s = String::new();
@ -735,7 +715,7 @@ fn assert_arg(arg: &Arg) {
arg.is_multiple_values_set(),
"Argument '{}' uses hint CommandWithArguments and must accept multiple values",
arg.get_id()
)
);
}
}

View file

@ -49,11 +49,6 @@ impl Extensions {
/// Supports conversion to `Any`. Traits to be extended by `impl_downcast!` must extend `Extension`.
pub(crate) trait Extension: std::fmt::Debug + Send + Sync + 'static {
/// Convert `Box<dyn Trait>` (where `Trait: Extension`) to `Box<dyn Any>`.
///
/// `Box<dyn Any>` can /// then be further `downcast` into
/// `Box<ConcreteType>` where `ConcreteType` implements `Trait`.
fn into_any(self: Box<Self>) -> Box<dyn std::any::Any>;
/// Clone `&Box<dyn Trait>` (where `Trait: Extension`) to `Box<dyn Extension>`.
///
/// `Box<dyn Any>` can /// then be further `downcast` into
@ -75,9 +70,6 @@ impl<T> Extension for T
where
T: Clone + std::fmt::Debug + Send + Sync + 'static,
{
fn into_any(self: Box<Self>) -> Box<dyn std::any::Any> {
self
}
fn clone_extension(&self) -> Box<dyn Extension> {
Box::new(self.clone())
}

View file

@ -85,15 +85,15 @@ impl From<&'_ std::ffi::OsString> for OsStr {
}
#[cfg(feature = "string")]
impl From<std::string::String> for OsStr {
fn from(name: std::string::String) -> Self {
impl From<String> for OsStr {
fn from(name: String) -> Self {
Self::from_string(name.into())
}
}
#[cfg(feature = "string")]
impl From<&'_ std::string::String> for OsStr {
fn from(name: &'_ std::string::String) -> Self {
impl From<&'_ String> for OsStr {
fn from(name: &'_ String) -> Self {
Self::from_ref(name.as_str().as_ref())
}
}
@ -210,13 +210,13 @@ impl PartialEq<OsStr> for &'_ std::ffi::OsStr {
}
}
impl PartialEq<std::string::String> for OsStr {
impl PartialEq<String> for OsStr {
#[inline]
fn eq(&self, other: &std::string::String) -> bool {
fn eq(&self, other: &String) -> bool {
PartialEq::eq(self.as_os_str(), other.as_str())
}
}
impl PartialEq<OsStr> for std::string::String {
impl PartialEq<OsStr> for String {
#[inline]
fn eq(&self, other: &OsStr) -> bool {
PartialEq::eq(self.as_str(), other.as_os_str())

View file

@ -168,7 +168,7 @@ impl PossibleValue {
self.hide
}
/// Report if PossibleValue is not hidden and has a help message
/// Report if `PossibleValue` is not hidden and has a help message
pub(crate) fn should_show_help(&self) -> bool {
!self.hide && self.help.is_some()
}

View file

@ -174,7 +174,7 @@ impl From<std::ops::RangeToInclusive<usize>> for ValueRange {
}
impl std::fmt::Display for ValueRange {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
ok!(self.start_inclusive.fmt(f));
if !self.is_fixed() {
ok!("..=".fmt(f));
@ -185,7 +185,7 @@ impl std::fmt::Display for ValueRange {
}
impl std::fmt::Debug for ValueRange {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{self}")
}
}

View file

@ -9,7 +9,7 @@ pub struct Str {
impl Str {
#[cfg(feature = "string")]
pub(crate) fn from_string(name: std::string::String) -> Self {
pub(crate) fn from_string(name: String) -> Self {
Self {
name: Inner::from_string(name),
}
@ -45,15 +45,15 @@ impl From<&'_ Str> for Str {
}
#[cfg(feature = "string")]
impl From<std::string::String> for Str {
fn from(name: std::string::String) -> Self {
impl From<String> for Str {
fn from(name: String) -> Self {
Self::from_string(name)
}
}
#[cfg(feature = "string")]
impl From<&'_ std::string::String> for Str {
fn from(name: &'_ std::string::String) -> Self {
impl From<&'_ String> for Str {
fn from(name: &'_ String) -> Self {
Self::from_ref(name.as_str())
}
}
@ -204,13 +204,13 @@ impl PartialEq<Str> for &'_ std::ffi::OsStr {
}
}
impl PartialEq<std::string::String> for Str {
impl PartialEq<String> for Str {
#[inline]
fn eq(&self, other: &std::string::String) -> bool {
fn eq(&self, other: &String) -> bool {
PartialEq::eq(self.as_str(), other.as_str())
}
}
impl PartialEq<Str> for std::string::String {
impl PartialEq<Str> for String {
#[inline]
fn eq(&self, other: &Str) -> bool {
PartialEq::eq(self.as_str(), other.as_str())
@ -226,7 +226,7 @@ pub(crate) mod inner {
}
impl Inner {
pub(crate) fn from_string(name: std::string::String) -> Self {
pub(crate) fn from_string(name: String) -> Self {
Self::Owned(name.into_boxed_str())
}

View file

@ -49,13 +49,13 @@ impl StyledStr {
if let Some(pos) = self.0.find('\n') {
let (leading, help) = self.0.split_at(pos + 1);
if leading.trim().is_empty() {
self.0 = help.to_owned()
self.0 = help.to_owned();
}
}
}
pub(crate) fn trim_end(&mut self) {
self.0 = self.0.trim_end().to_owned()
self.0 = self.0.trim_end().to_owned();
}
#[cfg(feature = "help")]
@ -156,14 +156,14 @@ impl Default for &'_ StyledStr {
}
}
impl From<std::string::String> for StyledStr {
fn from(name: std::string::String) -> Self {
impl From<String> for StyledStr {
fn from(name: String) -> Self {
StyledStr(name)
}
}
impl From<&'_ std::string::String> for StyledStr {
fn from(name: &'_ std::string::String) -> Self {
impl From<&'_ String> for StyledStr {
fn from(name: &'_ String) -> Self {
let mut styled = StyledStr::new();
styled.push_str(name);
styled
@ -200,7 +200,7 @@ impl std::fmt::Write for StyledStr {
/// Color-unaware printing. Never uses coloring.
impl std::fmt::Display for StyledStr {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
for part in self.iter_text() {
part.fmt(f)?;
}

View file

@ -21,26 +21,26 @@ pub use anstyle::*;
#[derive(Clone, Debug)]
#[allow(missing_copy_implementations)] // Large enough type that I want an explicit `clone()` for now
pub struct Styles {
header: anstyle::Style,
error: anstyle::Style,
usage: anstyle::Style,
literal: anstyle::Style,
placeholder: anstyle::Style,
valid: anstyle::Style,
invalid: anstyle::Style,
header: Style,
error: Style,
usage: Style,
literal: Style,
placeholder: Style,
valid: Style,
invalid: Style,
}
impl Styles {
/// No terminal styling
pub const fn plain() -> Self {
Self {
header: anstyle::Style::new(),
error: anstyle::Style::new(),
usage: anstyle::Style::new(),
literal: anstyle::Style::new(),
placeholder: anstyle::Style::new(),
valid: anstyle::Style::new(),
invalid: anstyle::Style::new(),
header: Style::new(),
error: Style::new(),
usage: Style::new(),
literal: Style::new(),
placeholder: Style::new(),
valid: Style::new(),
invalid: Style::new(),
}
}
@ -49,17 +49,15 @@ impl Styles {
#[cfg(feature = "color")]
{
Self {
header: anstyle::Style::new().bold().underline(),
error: anstyle::Style::new()
.fg_color(Some(anstyle::Color::Ansi(anstyle::AnsiColor::Red)))
header: Style::new().bold().underline(),
error: Style::new()
.fg_color(Some(Color::Ansi(AnsiColor::Red)))
.bold(),
usage: anstyle::Style::new().bold().underline(),
literal: anstyle::Style::new().bold(),
placeholder: anstyle::Style::new(),
valid: anstyle::Style::new()
.fg_color(Some(anstyle::Color::Ansi(anstyle::AnsiColor::Green))),
invalid: anstyle::Style::new()
.fg_color(Some(anstyle::Color::Ansi(anstyle::AnsiColor::Yellow))),
usage: Style::new().bold().underline(),
literal: Style::new().bold(),
placeholder: Style::new(),
valid: Style::new().fg_color(Some(Color::Ansi(AnsiColor::Green))),
invalid: Style::new().fg_color(Some(Color::Ansi(AnsiColor::Yellow))),
}
}
#[cfg(not(feature = "color"))]
@ -70,49 +68,49 @@ impl Styles {
/// General Heading style, e.g. [`help_heading`][crate::Arg::help_heading]
#[inline]
pub const fn header(mut self, style: anstyle::Style) -> Self {
pub const fn header(mut self, style: Style) -> Self {
self.header = style;
self
}
/// Error heading
#[inline]
pub const fn error(mut self, style: anstyle::Style) -> Self {
pub const fn error(mut self, style: Style) -> Self {
self.error = style;
self
}
/// Usage heading
#[inline]
pub const fn usage(mut self, style: anstyle::Style) -> Self {
pub const fn usage(mut self, style: Style) -> Self {
self.usage = style;
self
}
/// Literal command-line syntax, e.g. `--help`
#[inline]
pub const fn literal(mut self, style: anstyle::Style) -> Self {
pub const fn literal(mut self, style: Style) -> Self {
self.literal = style;
self
}
/// Descriptions within command-line syntax, e.g. [`value_name`][crate::Arg::value_name]
#[inline]
pub const fn placeholder(mut self, style: anstyle::Style) -> Self {
pub const fn placeholder(mut self, style: Style) -> Self {
self.placeholder = style;
self
}
/// Highlight suggested usage
#[inline]
pub const fn valid(mut self, style: anstyle::Style) -> Self {
pub const fn valid(mut self, style: Style) -> Self {
self.valid = style;
self
}
/// Highlight invalid usage
#[inline]
pub const fn invalid(mut self, style: anstyle::Style) -> Self {
pub const fn invalid(mut self, style: Style) -> Self {
self.invalid = style;
self
}
@ -122,43 +120,43 @@ impl Styles {
impl Styles {
/// General Heading style, e.g. [`help_heading`][crate::Arg::help_heading]
#[inline(always)]
pub const fn get_header(&self) -> &anstyle::Style {
pub const fn get_header(&self) -> &Style {
&self.header
}
/// Error heading
#[inline(always)]
pub const fn get_error(&self) -> &anstyle::Style {
pub const fn get_error(&self) -> &Style {
&self.error
}
/// Usage heading
#[inline(always)]
pub const fn get_usage(&self) -> &anstyle::Style {
pub const fn get_usage(&self) -> &Style {
&self.usage
}
/// Literal command-line syntax, e.g. `--help`
#[inline(always)]
pub const fn get_literal(&self) -> &anstyle::Style {
pub const fn get_literal(&self) -> &Style {
&self.literal
}
/// Descriptions within command-line syntax, e.g. [`value_name`][crate::Arg::value_name]
#[inline(always)]
pub const fn get_placeholder(&self) -> &anstyle::Style {
pub const fn get_placeholder(&self) -> &Style {
&self.placeholder
}
/// Highlight suggested usage
#[inline(always)]
pub const fn get_valid(&self) -> &anstyle::Style {
pub const fn get_valid(&self) -> &Style {
&self.valid
}
/// Highlight invalid usage
#[inline(always)]
pub const fn get_invalid(&self) -> &anstyle::Style {
pub const fn get_invalid(&self) -> &Style {
&self.invalid
}
}

View file

@ -31,7 +31,7 @@ fn global_setting() {
#[test]
fn app_send_sync() {
fn foo<T: Send + Sync>(_: T) {}
foo(Command::new("test"))
foo(Command::new("test"));
}
#[test]
@ -52,5 +52,5 @@ fn issue_2090() {
#[test]
fn arg_send_sync() {
fn foo<T: Send + Sync>(_: T) {}
foo(Arg::new("test"))
foo(Arg::new("test"));
}

View file

@ -2,7 +2,7 @@ use std::str::FromStr;
/// Provide shell with hint on how to complete an argument.
///
/// See [Arg::value_hint][crate::Arg::value_hint] to set this on an argument.
/// See [`Arg::value_hint`][crate::Arg::value_hint] to set this on an argument.
///
/// See the `clap_complete` crate for completion script generation.
///

View file

@ -564,7 +564,7 @@ where
}
impl std::fmt::Debug for ValueParser {
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
match &self.0 {
ValueParserInner::Bool => f.debug_struct("ValueParser::bool").finish(),
ValueParserInner::String => f.debug_struct("ValueParser::string").finish(),
@ -606,23 +606,6 @@ trait AnyValueParser: Send + Sync + 'static {
self.parse_ref(cmd, arg, value)
}
fn parse(
&self,
cmd: &crate::Command,
arg: Option<&crate::Arg>,
value: std::ffi::OsString,
) -> Result<AnyValue, crate::Error>;
fn parse_(
&self,
cmd: &crate::Command,
arg: Option<&crate::Arg>,
value: std::ffi::OsString,
_source: ValueSource,
) -> Result<AnyValue, crate::Error> {
self.parse(cmd, arg, value)
}
/// Describes the content of `AnyValue`
fn type_id(&self) -> AnyValueId;
@ -659,27 +642,6 @@ where
Ok(AnyValue::new(value))
}
fn parse(
&self,
cmd: &crate::Command,
arg: Option<&crate::Arg>,
value: std::ffi::OsString,
) -> Result<AnyValue, crate::Error> {
let value = ok!(TypedValueParser::parse(self, cmd, arg, value));
Ok(AnyValue::new(value))
}
fn parse_(
&self,
cmd: &crate::Command,
arg: Option<&crate::Arg>,
value: std::ffi::OsString,
source: ValueSource,
) -> Result<AnyValue, crate::Error> {
let value = ok!(TypedValueParser::parse_(self, cmd, arg, value, source));
Ok(AnyValue::new(value))
}
fn type_id(&self) -> AnyValueId {
AnyValueId::of::<T>()
}
@ -1346,12 +1308,12 @@ where
/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("50")).unwrap(), 50);
/// ```
#[derive(Copy, Clone, Debug)]
pub struct RangedI64ValueParser<T: std::convert::TryFrom<i64> + Clone + Send + Sync = i64> {
pub struct RangedI64ValueParser<T: TryFrom<i64> + Clone + Send + Sync = i64> {
bounds: (std::ops::Bound<i64>, std::ops::Bound<i64>),
target: std::marker::PhantomData<T>,
}
impl<T: std::convert::TryFrom<i64> + Clone + Send + Sync> RangedI64ValueParser<T> {
impl<T: TryFrom<i64> + Clone + Send + Sync> RangedI64ValueParser<T> {
/// Select full range of `i64`
pub fn new() -> Self {
Self::from(..)
@ -1431,10 +1393,9 @@ impl<T: std::convert::TryFrom<i64> + Clone + Send + Sync> RangedI64ValueParser<T
}
}
impl<T: std::convert::TryFrom<i64> + Clone + Send + Sync + 'static> TypedValueParser
for RangedI64ValueParser<T>
impl<T: TryFrom<i64> + Clone + Send + Sync + 'static> TypedValueParser for RangedI64ValueParser<T>
where
<T as std::convert::TryFrom<i64>>::Error: Send + Sync + 'static + std::error::Error + ToString,
<T as TryFrom<i64>>::Error: Send + Sync + 'static + std::error::Error + ToString,
{
type Value = T;
@ -1490,7 +1451,7 @@ where
}
}
impl<T: std::convert::TryFrom<i64> + Clone + Send + Sync, B: RangeBounds<i64>> From<B>
impl<T: TryFrom<i64> + Clone + Send + Sync, B: RangeBounds<i64>> From<B>
for RangedI64ValueParser<T>
{
fn from(range: B) -> Self {
@ -1501,7 +1462,7 @@ impl<T: std::convert::TryFrom<i64> + Clone + Send + Sync, B: RangeBounds<i64>> F
}
}
impl<T: std::convert::TryFrom<i64> + Clone + Send + Sync> Default for RangedI64ValueParser<T> {
impl<T: TryFrom<i64> + Clone + Send + Sync> Default for RangedI64ValueParser<T> {
fn default() -> Self {
Self::new()
}
@ -1546,12 +1507,12 @@ impl<T: std::convert::TryFrom<i64> + Clone + Send + Sync> Default for RangedI64V
/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("50")).unwrap(), 50);
/// ```
#[derive(Copy, Clone, Debug)]
pub struct RangedU64ValueParser<T: std::convert::TryFrom<u64> = u64> {
pub struct RangedU64ValueParser<T: TryFrom<u64> = u64> {
bounds: (std::ops::Bound<u64>, std::ops::Bound<u64>),
target: std::marker::PhantomData<T>,
}
impl<T: std::convert::TryFrom<u64>> RangedU64ValueParser<T> {
impl<T: TryFrom<u64>> RangedU64ValueParser<T> {
/// Select full range of `u64`
pub fn new() -> Self {
Self::from(..)
@ -1631,10 +1592,9 @@ impl<T: std::convert::TryFrom<u64>> RangedU64ValueParser<T> {
}
}
impl<T: std::convert::TryFrom<u64> + Clone + Send + Sync + 'static> TypedValueParser
for RangedU64ValueParser<T>
impl<T: TryFrom<u64> + Clone + Send + Sync + 'static> TypedValueParser for RangedU64ValueParser<T>
where
<T as std::convert::TryFrom<u64>>::Error: Send + Sync + 'static + std::error::Error + ToString,
<T as TryFrom<u64>>::Error: Send + Sync + 'static + std::error::Error + ToString,
{
type Value = T;
@ -1690,7 +1650,7 @@ where
}
}
impl<T: std::convert::TryFrom<u64>, B: RangeBounds<u64>> From<B> for RangedU64ValueParser<T> {
impl<T: TryFrom<u64>, B: RangeBounds<u64>> From<B> for RangedU64ValueParser<T> {
fn from(range: B) -> Self {
Self {
bounds: (range.start_bound().cloned(), range.end_bound().cloned()),
@ -1699,7 +1659,7 @@ impl<T: std::convert::TryFrom<u64>, B: RangeBounds<u64>> From<B> for RangedU64Va
}
}
impl<T: std::convert::TryFrom<u64>> Default for RangedU64ValueParser<T> {
impl<T: TryFrom<u64>> Default for RangedU64ValueParser<T> {
fn default() -> Self {
Self::new()
}
@ -2158,7 +2118,7 @@ where
}
}
/// When encountered, report [ErrorKind::UnknownArgument][crate::error::ErrorKind::UnknownArgument]
/// When encountered, report [`ErrorKind::UnknownArgument`][crate::error::ErrorKind::UnknownArgument]
///
/// Useful to help users migrate, either from old versions or similar tools.
///
@ -2274,7 +2234,7 @@ impl TypedValueParser for UnknownArgumentValueParser {
}
}
/// Register a type with [value_parser!][crate::value_parser!]
/// Register a type with [`value_parser!`][crate::value_parser!]
///
/// # Example
///
@ -2650,10 +2610,6 @@ macro_rules! value_parser {
mod private {
use super::*;
// Prefer these so `clap_derive` defaults to optimized implementations
pub trait _ValueParserViaSelfSealed {}
impl<P: Into<ValueParser>> _ValueParserViaSelfSealed for &&&&&&&_AutoValueParser<P> {}
pub trait _ValueParserViaFactorySealed {}
impl<P: ValueParserFactory> _ValueParserViaFactorySealed for &&&&&&_AutoValueParser<P> {}

View file

@ -311,10 +311,10 @@ impl<T: Parser> Parser for Box<T> {
}
impl<T: CommandFactory> CommandFactory for Box<T> {
fn command<'help>() -> Command {
fn command() -> Command {
<T as CommandFactory>::command()
}
fn command_for_update<'help>() -> Command {
fn command_for_update() -> Command {
<T as CommandFactory>::command_for_update()
}
}
@ -355,7 +355,7 @@ impl<T: Subcommand> Subcommand for Box<T> {
}
}
fn format_error<I: CommandFactory>(err: crate::Error) -> crate::Error {
fn format_error<I: CommandFactory>(err: Error) -> Error {
let mut cmd = I::command();
err.format(&mut cmd)
}

View file

@ -545,7 +545,7 @@ fn did_you_mean(styled: &mut StyledStr, styles: &Styles, context: &str, valid: &
struct Escape<'s>(&'s str);
impl<'s> std::fmt::Display for Escape<'s> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.0.contains(char::is_whitespace) {
std::fmt::Debug::fmt(self.0, f)
} else {

View file

@ -12,7 +12,7 @@ use std::{
convert::From,
error,
fmt::{self, Debug, Display, Formatter},
io::{self},
io,
result::Result as StdResult,
};
@ -85,7 +85,7 @@ impl<F: ErrorFormatter> Error<F> {
/// Prefer [`Command::error`] for generating errors.
///
/// [`Command::error`]: crate::Command::error
pub fn raw(kind: ErrorKind, message: impl std::fmt::Display) -> Self {
pub fn raw(kind: ErrorKind, message: impl Display) -> Self {
Self::new(kind).set_message(message.to_string())
}
@ -455,7 +455,7 @@ impl<F: ErrorFormatter> Error<F> {
(ContextKind::InvalidValue, ContextValue::String(bad_val)),
(
ContextKind::ValidValue,
ContextValue::Strings(good_vals.iter().map(|s| (*s).to_owned()).collect()),
ContextValue::Strings(good_vals.iter().map(|s| (*s).clone()).collect()),
),
]);
if let Some(suggestion) = suggestion {
@ -832,8 +832,8 @@ impl<F: ErrorFormatter> From<fmt::Error> for Error<F> {
}
}
impl<F: ErrorFormatter> std::fmt::Debug for Error<F> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
impl<F: ErrorFormatter> Debug for Error<F> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
self.inner.fmt(f)
}
}
@ -846,7 +846,7 @@ impl<F: ErrorFormatter> error::Error for Error<F> {
}
impl<F: ErrorFormatter> Display for Error<F> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
// Assuming `self.message` already has a trailing newline, from `try_help` or similar
ok!(write!(f, "{}", self.formatted()));
if let Some(backtrace) = self.inner.backtrace.as_ref() {
@ -884,7 +884,7 @@ impl Message {
}
}
fn formatted(&self, styles: &Styles) -> Cow<StyledStr> {
fn formatted(&self, styles: &Styles) -> Cow<'_, StyledStr> {
match self {
Message::Raw(s) => {
let styled = format::format_error_message(s, styles, None, None);
@ -921,7 +921,7 @@ impl Backtrace {
#[cfg(feature = "debug")]
impl Display for Backtrace {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
// `backtrace::Backtrace` uses `Debug` instead of `Display`
write!(f, "{:?}", self.0)
}
@ -940,7 +940,7 @@ impl Backtrace {
#[cfg(not(feature = "debug"))]
impl Display for Backtrace {
fn fmt(&self, _: &mut Formatter) -> fmt::Result {
fn fmt(&self, _: &mut Formatter<'_>) -> fmt::Result {
Ok(())
}
}

View file

@ -3,30 +3,13 @@
// (see LICENSE or <http://opensource.org/licenses/MIT>) All files in the project carrying such
// notice may not be copied, modified, or distributed except according to those terms.
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![doc = include_str!("../README.md")]
#![doc(html_logo_url = "https://raw.githubusercontent.com/clap-rs/clap/master/assets/clap.png")]
#![warn(
missing_docs,
missing_debug_implementations,
missing_copy_implementations,
trivial_casts,
unused_allocation,
trivial_numeric_casts,
clippy::single_char_pattern
)]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![forbid(unsafe_code)]
// Wanting consistency in our calls
#![allow(clippy::write_with_newline)]
// Gets in the way of logging
#![allow(clippy::let_and_return)]
// HACK https://github.com/rust-lang/rust-clippy/issues/7290
#![allow(clippy::single_component_path_imports)]
#![allow(clippy::branches_sharing_code)]
// Doesn't allow for debug statements, etc to be unique
#![allow(clippy::if_same_then_else)]
// Breaks up parallelism that clarifies intent
#![allow(clippy::collapsible_else_if)]
#![warn(missing_docs)]
#![warn(clippy::print_stderr)]
#![warn(clippy::print_stdout)]
#[cfg(not(feature = "std"))]
compile_error!("`std` feature is currently required to build `clap`");
@ -44,7 +27,7 @@ pub use crate::util::Id;
/// See [`Command::error`] to create an error.
///
/// [`Command::error`]: crate::Command::error
pub type Error = crate::error::Error<crate::error::DefaultFormatter>;
pub type Error = error::Error<error::DefaultFormatter>;
pub use crate::derive::{Args, CommandFactory, FromArgMatches, Parser, Subcommand, ValueEnum};

View file

@ -81,7 +81,7 @@ impl PartialEq<char> for KeyType {
impl MKeyMap {
/// If any arg has corresponding key in this map, we can search the key with
/// u64(for positional argument), char(for short flag), &str and OsString
/// `u64` (for positional argument), `char` (for short flag), `&str` and `OsString`
/// (for long flag)
pub(crate) fn contains<K>(&self, key: K) -> bool
where
@ -96,8 +96,8 @@ impl MKeyMap {
}
/// Find the arg have corresponding key in this map, we can search the key
/// with u64(for positional argument), char(for short flag), &str and
/// OsString (for long flag)
/// with `u64` (for positional argument), `char` (for short flag), `&str` and
/// `OsString` (for long flag)
pub(crate) fn get<K: ?Sized>(&self, key: &K) -> Option<&Arg>
where
KeyType: PartialEq<K>,

View file

@ -77,7 +77,7 @@ impl Colorizer {
/// Color-unaware printing. Never uses coloring.
impl std::fmt::Display for Colorizer {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.content.fmt(f)
}
}

View file

@ -74,7 +74,7 @@ const DEFAULT_NO_ARGS_TEMPLATE: &str = "\
{usage-heading} {usage}{after-help}\
";
/// `clap` HelpTemplate Writer.
/// Help template writer
///
/// Wraps a writer stream providing different methods to generate help for `clap` objects.
pub(crate) struct HelpTemplate<'cmd, 'writer> {
@ -1031,7 +1031,7 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> {
.unwrap_or_default();
self.subcmd(sc_str, next_line_help, longest);
self.help(None, about, spec_vals, next_line_help, longest)
self.help(None, about, spec_vals, next_line_help, longest);
}
fn sc_spec_vals(&self, a: &Command) -> String {

View file

@ -2,7 +2,7 @@
//!
//! Benefits of forking:
//! - Pull in only what we need rather than relying on the compiler to remove what we don't need
//! - `LineWrapper` is able to incrementally wrap which will help with `StyledStr
//! - `LineWrapper` is able to incrementally wrap which will help with `StyledStr`
pub(crate) mod core;
#[cfg(feature = "wrap_help")]

View file

@ -114,7 +114,7 @@ impl ArgMatcher {
self.matches.args.iter()
}
pub(crate) fn entry(&mut self, arg: Id) -> crate::util::Entry<Id, MatchedArg> {
pub(crate) fn entry(&mut self, arg: Id) -> crate::util::Entry<'_, Id, MatchedArg> {
self.matches.args.entry(arg)
}
@ -149,7 +149,7 @@ impl ArgMatcher {
ma.new_val_group();
}
pub(crate) fn start_occurrence_of_external(&mut self, cmd: &crate::Command) {
pub(crate) fn start_occurrence_of_external(&mut self, cmd: &Command) {
let id = Id::from_static_ref(Id::EXTERNAL);
debug!("ArgMatcher::start_occurrence_of_external: id={id:?}");
let ma = self.entry(id).or_insert(MatchedArg::new_external(cmd));

View file

@ -36,7 +36,7 @@ impl MatchesError {
impl std::error::Error for MatchesError {}
impl std::fmt::Display for MatchesError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Downcast { actual, expected } => {
writeln!(

View file

@ -221,7 +221,7 @@ impl ArgMatches {
pub fn get_many<T: Any + Clone + Send + Sync + 'static>(
&self,
id: &str,
) -> Option<ValuesRef<T>> {
) -> Option<ValuesRef<'_, T>> {
MatchesError::unwrap(id, self.try_get_many(id))
}
@ -259,7 +259,7 @@ impl ArgMatches {
pub fn get_occurrences<T: Any + Clone + Send + Sync + 'static>(
&self,
id: &str,
) -> Option<OccurrencesRef<T>> {
) -> Option<OccurrencesRef<'_, T>> {
MatchesError::unwrap(id, self.try_get_occurrences(id))
}
@ -1077,7 +1077,7 @@ impl ArgMatches {
pub fn try_get_many<T: Any + Clone + Send + Sync + 'static>(
&self,
id: &str,
) -> Result<Option<ValuesRef<T>>, MatchesError> {
) -> Result<Option<ValuesRef<'_, T>>, MatchesError> {
let arg = match ok!(self.try_get_arg_t::<T>(id)) {
Some(arg) => arg,
None => return Ok(None),
@ -1096,7 +1096,7 @@ impl ArgMatches {
pub fn try_get_occurrences<T: Any + Clone + Send + Sync + 'static>(
&self,
id: &str,
) -> Result<Option<OccurrencesRef<T>>, MatchesError> {
) -> Result<Option<OccurrencesRef<'_, T>>, MatchesError> {
let arg = match ok!(self.try_get_arg_t::<T>(id)) {
Some(arg) => arg,
None => return Ok(None),
@ -1348,7 +1348,7 @@ pub(crate) struct SubCommand {
/// ```
#[derive(Clone, Debug)]
pub struct IdsRef<'a> {
iter: std::slice::Iter<'a, Id>,
iter: Iter<'a, Id>,
}
impl<'a> Iterator for IdsRef<'a> {
@ -1585,7 +1585,7 @@ impl Default for RawValues<'_> {
#[derive(Clone, Debug)]
#[deprecated(since = "4.1.0", note = "Use Occurrences instead")]
pub struct GroupedValues<'a> {
pub(crate) struct GroupedValues<'a> {
#[allow(clippy::type_complexity)]
iter: Map<Iter<'a, Vec<AnyValue>>, fn(&Vec<AnyValue>) -> Vec<&str>>,
len: usize,
@ -1926,13 +1926,13 @@ mod tests {
#[test]
fn test_default_raw_values() {
let mut values: RawValues = Default::default();
let mut values: RawValues<'_> = Default::default();
assert_eq!(values.next(), None);
}
#[test]
fn test_default_indices() {
let mut indices: Indices = Indices::default();
let mut indices: Indices<'_> = Indices::default();
assert_eq!(indices.next(), None);
}
@ -1972,7 +1972,7 @@ mod tests {
)
.try_get_matches_from(["test", "one"])
.unwrap()
.get_many::<std::ffi::OsString>("POTATO")
.get_many::<OsString>("POTATO")
.expect("present")
.count();
assert_eq!(l, 1);

View file

@ -72,10 +72,10 @@ impl MatchedArg {
}
pub(crate) fn push_index(&mut self, index: usize) {
self.indices.push(index)
self.indices.push(index);
}
pub(crate) fn vals(&self) -> Iter<Vec<AnyValue>> {
pub(crate) fn vals(&self) -> Iter<'_, Vec<AnyValue>> {
self.vals.iter()
}
@ -83,7 +83,7 @@ impl MatchedArg {
self.vals
}
pub(crate) fn vals_flatten(&self) -> Flatten<Iter<Vec<AnyValue>>> {
pub(crate) fn vals_flatten(&self) -> Flatten<Iter<'_, Vec<AnyValue>>> {
self.vals.iter().flatten()
}
@ -91,11 +91,11 @@ impl MatchedArg {
self.vals.into_iter().flatten()
}
pub(crate) fn raw_vals(&self) -> Iter<Vec<OsString>> {
pub(crate) fn raw_vals(&self) -> Iter<'_, Vec<OsString>> {
self.raw_vals.iter()
}
pub(crate) fn raw_vals_flatten(&self) -> Flatten<Iter<Vec<OsString>>> {
pub(crate) fn raw_vals_flatten(&self) -> Flatten<Iter<'_, Vec<OsString>>> {
self.raw_vals.iter().flatten()
}
@ -162,7 +162,7 @@ impl MatchedArg {
if let Some(existing) = self.source {
self.source = Some(existing.max(source));
} else {
self.source = Some(source)
self.source = Some(source);
}
}

View file

@ -745,7 +745,7 @@ impl<'cmd> Parser<'cmd> {
// maybe here lifetime should be 'a
debug!("Parser::parse_long_arg");
#[allow(clippy::blocks_in_if_conditions)]
#[allow(clippy::blocks_in_conditions)]
if matches!(parse_state, ParseState::Opt(opt) | ParseState::Pos(opt) if
self.cmd[opt].is_allow_hyphen_values_set())
{
@ -863,7 +863,7 @@ impl<'cmd> Parser<'cmd> {
) -> ClapResult<ParseResult> {
debug!("Parser::parse_short_arg: short_arg={short_arg:?}");
#[allow(clippy::blocks_in_if_conditions)]
#[allow(clippy::blocks_in_conditions)]
if matches!(parse_state, ParseState::Opt(opt) | ParseState::Pos(opt)
if self.cmd[opt].is_allow_hyphen_values_set() || (self.cmd[opt].is_allow_negative_numbers_set() && short_arg.is_negative_number()))
{
@ -1165,7 +1165,7 @@ impl<'cmd> Parser<'cmd> {
split_raw_vals.extend(raw_val.split(val_delim).map(|x| x.to_owned()));
}
}
raw_vals = split_raw_vals
raw_vals = split_raw_vals;
}
}

View file

@ -112,7 +112,7 @@ impl<'cmd> Validator<'cmd> {
let args_count = matcher
.args()
.filter(|(arg_id, matched)| {
matched.check_explicit(&crate::builder::ArgPredicate::IsPresent)
matched.check_explicit(&ArgPredicate::IsPresent)
// Avoid including our own groups by checking none of them. If a group is present, the
// args for the group will be.
&& self.cmd.find(arg_id).is_some()
@ -125,15 +125,14 @@ impl<'cmd> Validator<'cmd> {
matcher
.args()
.filter(|(_, matched)| matched.check_explicit(&crate::builder::ArgPredicate::IsPresent))
.filter_map(|(id, _)| {
.filter(|(_, matched)| matched.check_explicit(&ArgPredicate::IsPresent))
.find_map(|(id, _)| {
debug!("Validator::validate_exclusive:iter:{id:?}");
self.cmd
.find(id)
// Find `arg`s which are exclusive but also appear with other args.
.filter(|&arg| arg.is_exclusive_set() && args_count > 1)
})
.next()
.map(|arg| {
// Throw an error for the first conflict found.
Err(Error::argument_conflict(

View file

@ -39,7 +39,7 @@ impl<K: PartialEq + Eq, V> FlatMap<K, V> {
}
}
pub fn contains_key<Q: ?Sized>(&self, key: &Q) -> bool
pub(crate) fn contains_key<Q: ?Sized>(&self, key: &Q) -> bool
where
K: Borrow<Q>,
Q: Eq,
@ -52,7 +52,7 @@ impl<K: PartialEq + Eq, V> FlatMap<K, V> {
false
}
pub fn remove<Q: ?Sized>(&mut self, key: &Q) -> Option<V>
pub(crate) fn remove<Q: ?Sized>(&mut self, key: &Q) -> Option<V>
where
K: Borrow<Q>,
Q: std::hash::Hash + Eq,
@ -60,7 +60,7 @@ impl<K: PartialEq + Eq, V> FlatMap<K, V> {
self.remove_entry(key).map(|(_, v)| v)
}
pub fn remove_entry<Q: ?Sized>(&mut self, key: &Q) -> Option<(K, V)>
pub(crate) fn remove_entry<Q: ?Sized>(&mut self, key: &Q) -> Option<(K, V)>
where
K: Borrow<Q>,
Q: std::hash::Hash + Eq,
@ -79,7 +79,7 @@ impl<K: PartialEq + Eq, V> FlatMap<K, V> {
self.keys.is_empty()
}
pub fn entry(&mut self, key: K) -> Entry<K, V> {
pub(crate) fn entry(&mut self, key: K) -> Entry<'_, K, V> {
for (index, existing) in self.keys.iter().enumerate() {
if *existing == key {
return Entry::Occupied(OccupiedEntry { v: self, index });
@ -88,7 +88,7 @@ impl<K: PartialEq + Eq, V> FlatMap<K, V> {
Entry::Vacant(VacantEntry { v: self, key })
}
pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
pub(crate) fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
where
K: Borrow<Q>,
Q: Eq,
@ -101,7 +101,7 @@ impl<K: PartialEq + Eq, V> FlatMap<K, V> {
None
}
pub fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V>
pub(crate) fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V>
where
K: Borrow<Q>,
Q: Eq,
@ -114,18 +114,18 @@ impl<K: PartialEq + Eq, V> FlatMap<K, V> {
None
}
pub fn keys(&self) -> std::slice::Iter<'_, K> {
pub(crate) fn keys(&self) -> std::slice::Iter<'_, K> {
self.keys.iter()
}
pub fn iter(&self) -> Iter<K, V> {
pub(crate) fn iter(&self) -> Iter<'_, K, V> {
Iter {
keys: self.keys.iter(),
values: self.values.iter(),
}
}
pub fn iter_mut(&mut self) -> IterMut<K, V> {
pub(crate) fn iter_mut(&mut self) -> IterMut<'_, K, V> {
IterMut {
keys: self.keys.iter_mut(),
values: self.values.iter_mut(),
@ -142,13 +142,13 @@ impl<K: PartialEq + Eq, V> Default for FlatMap<K, V> {
}
}
pub enum Entry<'a, K: 'a, V: 'a> {
pub(crate) enum Entry<'a, K, V> {
Vacant(VacantEntry<'a, K, V>),
Occupied(OccupiedEntry<'a, K, V>),
}
impl<'a, K: 'a, V: 'a> Entry<'a, K, V> {
pub fn or_insert(self, default: V) -> &'a mut V {
pub(crate) fn or_insert(self, default: V) -> &'a mut V {
match self {
Entry::Occupied(entry) => &mut entry.v.values[entry.index],
Entry::Vacant(entry) => {
@ -159,7 +159,7 @@ impl<'a, K: 'a, V: 'a> Entry<'a, K, V> {
}
}
pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
pub(crate) fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
match self {
Entry::Occupied(entry) => &mut entry.v.values[entry.index],
Entry::Vacant(entry) => {
@ -171,17 +171,17 @@ impl<'a, K: 'a, V: 'a> Entry<'a, K, V> {
}
}
pub struct VacantEntry<'a, K: 'a, V: 'a> {
pub(crate) struct VacantEntry<'a, K, V> {
v: &'a mut FlatMap<K, V>,
key: K,
}
pub struct OccupiedEntry<'a, K: 'a, V: 'a> {
pub(crate) struct OccupiedEntry<'a, K, V> {
v: &'a mut FlatMap<K, V>,
index: usize,
}
pub struct Iter<'a, K: 'a, V: 'a> {
pub(crate) struct Iter<'a, K, V> {
keys: std::slice::Iter<'a, K>,
values: std::slice::Iter<'a, V>,
}
@ -217,7 +217,7 @@ impl<'a, K, V> DoubleEndedIterator for Iter<'a, K, V> {
impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> {}
pub struct IterMut<'a, K: 'a, V: 'a> {
pub(crate) struct IterMut<'a, K, V> {
keys: std::slice::IterMut<'a, K>,
values: std::slice::IterMut<'a, V>,
}

View file

@ -25,7 +25,7 @@ impl<T: PartialEq + Eq> FlatSet<T> {
true
}
pub fn contains<Q: ?Sized>(&self, value: &Q) -> bool
pub(crate) fn contains<Q: ?Sized>(&self, value: &Q) -> bool
where
T: Borrow<Q>,
Q: Eq,
@ -38,7 +38,7 @@ impl<T: PartialEq + Eq> FlatSet<T> {
false
}
pub fn retain<F>(&mut self, f: F)
pub(crate) fn retain<F>(&mut self, f: F)
where
F: FnMut(&T) -> bool,
{
@ -53,7 +53,7 @@ impl<T: PartialEq + Eq> FlatSet<T> {
self.inner.iter()
}
pub fn sort_by_key<K, F>(&mut self, f: F)
pub(crate) fn sort_by_key<K, F>(&mut self, f: F)
where
F: FnMut(&T) -> K,
K: Ord,

View file

@ -46,15 +46,15 @@ impl From<&'_ Str> for Id {
}
#[cfg(feature = "string")]
impl From<std::string::String> for Id {
fn from(name: std::string::String) -> Self {
impl From<String> for Id {
fn from(name: String) -> Self {
Self(name.into())
}
}
#[cfg(feature = "string")]
impl From<&'_ std::string::String> for Id {
fn from(name: &'_ std::string::String) -> Self {
impl From<&'_ String> for Id {
fn from(name: &'_ String) -> Self {
Self(name.into())
}
}
@ -150,13 +150,13 @@ impl PartialEq<Id> for Str {
}
}
impl PartialEq<std::string::String> for Id {
impl PartialEq<String> for Id {
#[inline]
fn eq(&self, other: &std::string::String) -> bool {
fn eq(&self, other: &String) -> bool {
PartialEq::eq(self.as_str(), other.as_str())
}
}
impl PartialEq<Id> for std::string::String {
impl PartialEq<Id> for String {
#[inline]
fn eq(&self, other: &Id) -> bool {
PartialEq::eq(other, self)

View file

@ -48,6 +48,7 @@ trycmd = { version = "0.15.1", default-features = false, features = ["color-auto
completest = "0.4.0"
completest-pty = "0.5.0"
clap = { path = "../", version = "4.0.0", default-features = false, features = ["std", "derive", "help"] }
automod = "1.0.14"
[[example]]
name = "dynamic"
@ -58,3 +59,6 @@ default = []
unstable-doc = ["unstable-dynamic"] # for docs.rs
unstable-dynamic = ["dep:clap_lex", "dep:shlex", "dep:unicode-xid", "clap/derive", "dep:is_executable", "dep:pathdiff"]
debug = ["clap/debug"]
[lints]
workspace = true

View file

@ -1,4 +1,4 @@
//! Example to test arguments with different ValueHint values.
//! Example to test arguments with different `ValueHint` values.
//!
//! Usage with zsh:
//! ```console

View file

@ -20,7 +20,7 @@ pub trait Completer {
fn write_complete(
&self,
cmd: &mut clap::Command,
args: Vec<std::ffi::OsString>,
args: Vec<OsString>,
current_dir: Option<&std::path::Path>,
buf: &mut dyn std::io::Write,
) -> Result<(), std::io::Error>;
@ -29,10 +29,10 @@ pub trait Completer {
/// Complete the given command
pub fn complete(
cmd: &mut clap::Command,
args: Vec<std::ffi::OsString>,
args: Vec<OsString>,
arg_index: usize,
current_dir: Option<&std::path::Path>,
) -> Result<Vec<(std::ffi::OsString, Option<StyledStr>)>, std::io::Error> {
) -> Result<Vec<(OsString, Option<StyledStr>)>, std::io::Error> {
cmd.build();
let raw_args = clap_lex::RawArgs::new(args);
@ -91,7 +91,7 @@ fn complete_arg(
current_dir: Option<&std::path::Path>,
pos_index: usize,
is_escaped: bool,
) -> Result<Vec<(std::ffi::OsString, Option<StyledStr>)>, std::io::Error> {
) -> Result<Vec<(OsString, Option<StyledStr>)>, std::io::Error> {
debug!(
"complete_arg: arg={:?}, cmd={:?}, current_dir={:?}, pos_index={}, is_escaped={}",
arg,
@ -114,7 +114,7 @@ fn complete_arg(
// HACK: Need better `OsStr` manipulation
(format!("--{}={}", flag, os.to_string_lossy()).into(), help)
}),
)
);
}
} else {
completions.extend(longs_and_visible_aliases(cmd).into_iter().filter_map(

View file

@ -8,9 +8,9 @@ use clap::ValueEnum;
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[non_exhaustive]
pub enum Shell {
/// Bourne Again SHell (bash)
/// Bourne Again `SHell` (bash)
Bash,
/// Friendly Interactive SHell (fish)
/// Friendly Interactive `SHell` (fish)
Fish,
}
@ -42,7 +42,7 @@ impl ValueEnum for Shell {
&[Shell::Bash, Shell::Fish]
}
fn to_possible_value<'a>(&self) -> Option<PossibleValue> {
fn to_possible_value(&self) -> Option<PossibleValue> {
Some(match self {
Shell::Bash => PossibleValue::new("bash"),
Shell::Fish => PossibleValue::new("fish"),

View file

@ -252,10 +252,10 @@ where
S: Into<String>,
{
cmd.set_bin_name(bin_name);
_generate::<G>(gen, cmd, buf)
_generate::<G>(gen, cmd, buf);
}
fn _generate<G: Generator>(gen: G, cmd: &mut Command, buf: &mut dyn Write) {
cmd.build();
gen.generate(cmd, buf)
gen.generate(cmd, buf);
}

View file

@ -56,6 +56,11 @@
//! }
//! ```
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![warn(missing_docs)]
#![warn(clippy::print_stderr)]
#![warn(clippy::print_stdout)]
const INTERNAL_ERROR_MSG: &str = "Fatal internal error. Please consider filing a bug \
report at https://github.com/clap-rs/clap/issues";

View file

@ -1,6 +1,6 @@
use std::{fmt::Write as _, io::Write};
use clap::*;
use clap::{Arg, Command, ValueHint};
use crate::generator::{utils, Generator};
@ -204,7 +204,7 @@ fn option_details_for_path(cmd: &Command, path: &str) -> String {
]);
}
v.extend(["return 0", ";;"].iter().map(|s| s.to_string()));
v.extend(["return 0", ";;"].iter().map(|s| (*s).to_string()));
v.join("\n ")
}));
}
@ -237,7 +237,7 @@ fn option_details_for_path(cmd: &Command, path: &str) -> String {
]);
}
v.extend(["return 0", ";;"].iter().map(|s| s.to_string()));
v.extend(["return 0", ";;"].iter().map(|s| (*s).to_string()));
v.join("\n ")
}));
}
@ -249,7 +249,7 @@ fn option_details_for_path(cmd: &Command, path: &str) -> String {
fn vals_for(o: &Arg) -> String {
debug!("vals_for: o={}", o.get_id());
if let Some(vals) = crate::generator::utils::possible_values(o) {
if let Some(vals) = utils::possible_values(o) {
format!(
"$(compgen -W \"{}\" -- \"${{cur}}\")",
vals.iter()

View file

@ -1,7 +1,7 @@
use std::io::Write;
use clap::builder::StyledStr;
use clap::*;
use clap::Command;
use crate::generator::{utils, Generator};
use crate::INTERNAL_ERROR_MSG;

View file

@ -1,6 +1,6 @@
use std::io::Write;
use clap::*;
use clap::{builder, Arg, Command, ValueHint};
use crate::generator::{utils, Generator};
@ -36,7 +36,7 @@ fn escape_string(string: &str, escape_comma: bool) -> String {
}
}
fn escape_help(help: &clap::builder::StyledStr) -> String {
fn escape_help(help: &builder::StyledStr) -> String {
escape_string(&help.to_string().replace('\n', " "), false)
}
@ -141,7 +141,7 @@ fn gen_fish_inner(
template.push_str(format!(" -a \"{}\"", &subcommand.get_name()).as_str());
if let Some(data) = subcommand.get_about() {
template.push_str(format!(" -d '{}'", escape_help(data)).as_str())
template.push_str(format!(" -d '{}'", escape_help(data)).as_str());
}
buffer.push_str(template.as_str());
@ -161,7 +161,7 @@ fn value_completion(option: &Arg) -> String {
return "".to_string();
}
if let Some(data) = crate::generator::utils::possible_values(option) {
if let Some(data) = utils::possible_values(option) {
// We return the possible values with their own empty description e.g. {a\t,b\t}
// this makes sure that a and b don't get the description of the option or argument
format!(

View file

@ -1,7 +1,7 @@
use std::io::Write;
use clap::builder::StyledStr;
use clap::*;
use clap::{Arg, Command};
use crate::generator::{utils, Generator};
use crate::INTERNAL_ERROR_MSG;

View file

@ -12,15 +12,15 @@ use crate::Generator;
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[non_exhaustive]
pub enum Shell {
/// Bourne Again SHell (bash)
/// Bourne Again `SHell` (bash)
Bash,
/// Elvish shell
Elvish,
/// Friendly Interactive SHell (fish)
/// Friendly Interactive `SHell` (fish)
Fish,
/// PowerShell
/// `PowerShell`
PowerShell,
/// Z SHell (zsh)
/// Z `SHell` (zsh)
Zsh,
}
@ -58,7 +58,7 @@ impl ValueEnum for Shell {
]
}
fn to_possible_value<'a>(&self) -> Option<PossibleValue> {
fn to_possible_value(&self) -> Option<PossibleValue> {
Some(match self {
Shell::Bash => PossibleValue::new("bash"),
Shell::Elvish => PossibleValue::new("elvish"),
@ -113,7 +113,7 @@ impl Shell {
/// from that.
///
/// If SHELL is not set, then on windows, it will default to powershell, and on
/// other OSes it will return `None`.
/// other operating systems it will return `None`.
///
/// If SHELL is set, but contains a value that doesn't correspond to one of the supported shell
/// types, then return `None`.

View file

@ -1,6 +1,6 @@
use std::io::Write;
use clap::*;
use clap::{Arg, ArgAction, Command, ValueHint};
use crate::generator::{utils, Generator};
use crate::INTERNAL_ERROR_MSG;
@ -356,7 +356,7 @@ fn get_args_of(parent: &Command, p_global: Option<&Command>) -> String {
// Uses either `possible_vals` or `value_hint` to give hints about possible argument values
fn value_completion(arg: &Arg) -> Option<String> {
if let Some(values) = crate::generator::utils::possible_values(arg) {
if let Some(values) = utils::possible_values(arg) {
if values
.iter()
.any(|value| !value.is_hide_set() && value.get_help().is_some())
@ -678,7 +678,7 @@ mod tests {
assert_eq!(
escape_value(raw_string),
"\\\\\\ \\[foo\\]\\(\\)\\ \\`bar\\ https\\://\\$PATH"
)
);
}
#[test]
@ -687,6 +687,6 @@ mod tests {
assert_eq!(
escape_help(raw_string),
"\\\\ \\[foo\\]() \\`bar https\\://\\$PATH"
)
);
}
}

View file

@ -190,8 +190,8 @@ fn complete() {
File::create(Path::new(testdir_path).join("a_file")).unwrap();
File::create(Path::new(testdir_path).join("b_file")).unwrap();
std::fs::create_dir(Path::new(testdir_path).join("c_dir")).unwrap();
std::fs::create_dir(Path::new(testdir_path).join("d_dir")).unwrap();
std::fs::create_dir_all(Path::new(testdir_path).join("c_dir")).unwrap();
std::fs::create_dir_all(Path::new(testdir_path).join("d_dir")).unwrap();
let input = format!(
"exhaustive hint --file {}/\t\t",

View file

@ -1,6 +1,6 @@
use clap::builder::PossibleValue;
pub fn basic_command(name: &'static str) -> clap::Command {
pub(crate) fn basic_command(name: &'static str) -> clap::Command {
clap::Command::new(name)
.arg(
clap::Arg::new("config")
@ -25,7 +25,7 @@ pub fn basic_command(name: &'static str) -> clap::Command {
)
}
pub fn feature_sample_command(name: &'static str) -> clap::Command {
pub(crate) fn feature_sample_command(name: &'static str) -> clap::Command {
clap::Command::new(name)
.version("3.0")
.propagate_version(true)
@ -55,7 +55,7 @@ pub fn feature_sample_command(name: &'static str) -> clap::Command {
)
}
pub fn special_commands_command(name: &'static str) -> clap::Command {
pub(crate) fn special_commands_command(name: &'static str) -> clap::Command {
feature_sample_command(name)
.subcommand(
clap::Command::new("some_cmd")
@ -74,7 +74,7 @@ pub fn special_commands_command(name: &'static str) -> clap::Command {
.subcommand(clap::Command::new("some-hidden-cmd").hide(true))
}
pub fn quoting_command(name: &'static str) -> clap::Command {
pub(crate) fn quoting_command(name: &'static str) -> clap::Command {
clap::Command::new(name)
.version("3.0")
.arg(
@ -124,7 +124,7 @@ pub fn quoting_command(name: &'static str) -> clap::Command {
])
}
pub fn aliases_command(name: &'static str) -> clap::Command {
pub(crate) fn aliases_command(name: &'static str) -> clap::Command {
clap::Command::new(name)
.version("3.0")
.about("testing bash completions")
@ -149,7 +149,7 @@ pub fn aliases_command(name: &'static str) -> clap::Command {
.arg(clap::Arg::new("positional"))
}
pub fn sub_subcommands_command(name: &'static str) -> clap::Command {
pub(crate) fn sub_subcommands_command(name: &'static str) -> clap::Command {
feature_sample_command(name).subcommand(
clap::Command::new("some_cmd")
.about("top level subcommand")
@ -170,7 +170,7 @@ pub fn sub_subcommands_command(name: &'static str) -> clap::Command {
)
}
pub fn value_hint_command(name: &'static str) -> clap::Command {
pub(crate) fn value_hint_command(name: &'static str) -> clap::Command {
clap::Command::new(name)
.arg(
clap::Arg::new("choice")
@ -254,7 +254,7 @@ pub fn value_hint_command(name: &'static str) -> clap::Command {
)
}
pub fn value_terminator_command(name: &'static str) -> clap::Command {
pub(crate) fn value_terminator_command(name: &'static str) -> clap::Command {
clap::Command::new(name).arg(
clap::Arg::new("arguments")
.help("multi-valued argument with a value terminator")
@ -263,7 +263,7 @@ pub fn value_terminator_command(name: &'static str) -> clap::Command {
)
}
pub fn two_multi_valued_arguments_command(name: &'static str) -> clap::Command {
pub(crate) fn two_multi_valued_arguments_command(name: &'static str) -> clap::Command {
clap::Command::new(name)
.arg(
clap::Arg::new("first")
@ -277,13 +277,13 @@ pub fn two_multi_valued_arguments_command(name: &'static str) -> clap::Command {
)
}
pub fn subcommand_last(name: &'static str) -> clap::Command {
pub(crate) fn subcommand_last(name: &'static str) -> clap::Command {
clap::Command::new(name)
.arg(clap::Arg::new("free").last(true))
.subcommands([clap::Command::new("foo"), clap::Command::new("bar")])
}
pub fn assert_matches(
pub(crate) fn assert_matches(
expected: impl Into<snapbox::Data>,
gen: impl clap_complete::Generator,
mut cmd: clap::Command,
@ -298,7 +298,7 @@ pub fn assert_matches(
.matches(expected, buf);
}
pub fn register_example<R: completest::RuntimeBuilder>(context: &str, name: &str) {
pub(crate) fn register_example<R: completest::RuntimeBuilder>(context: &str, name: &str) {
use completest::Runtime as _;
let scratch = snapbox::path::PathFixture::mutable_temp().unwrap();
@ -354,7 +354,7 @@ pub fn register_example<R: completest::RuntimeBuilder>(context: &str, name: &str
scratch.close().unwrap();
}
pub fn load_runtime<R: completest::RuntimeBuilder>(
pub(crate) fn load_runtime<R: completest::RuntimeBuilder>(
context: &str,
name: &str,
) -> Box<dyn completest::Runtime>
@ -421,7 +421,7 @@ impl completest::Runtime for ScratchRuntime {
}
}
pub fn has_command(command: &str) -> bool {
pub(crate) fn has_command(command: &str) -> bool {
let output = match std::process::Command::new(command)
.arg("--version")
.output()

View file

@ -139,7 +139,7 @@ fn complete(cmd: &mut Command, args: impl AsRef<str>, current_dir: Option<&Path>
if let Some((prior, after)) = input.split_once("[TAB]") {
args.extend(prior.split_whitespace().map(From::from));
if prior.ends_with(char::is_whitespace) {
args.push(std::ffi::OsString::default())
args.push(std::ffi::OsString::default());
}
arg_index = args.len() - 1;
// HACK: this cannot handle in-word '[TAB]'
@ -147,7 +147,7 @@ fn complete(cmd: &mut Command, args: impl AsRef<str>, current_dir: Option<&Path>
} else {
args.extend(input.split_whitespace().map(From::from));
if input.ends_with(char::is_whitespace) {
args.push(std::ffi::OsString::default())
args.push(std::ffi::OsString::default());
}
arg_index = args.len() - 1;
}

View file

@ -1,8 +1 @@
mod bash;
mod common;
mod dynamic;
mod elvish;
mod fish;
mod general;
mod powershell;
mod zsh;
automod::dir!("tests/testsuite");

View file

@ -37,3 +37,6 @@ clap_complete = { path = "../clap_complete", version = "4.0.0" }
[dev-dependencies]
snapbox = { version = "0.5.9", features = ["diff"] }
clap = { path = "../", version = "4.0.0", default-features = false, features = ["std", "help"] }
[lints]
workspace = true

View file

@ -3,8 +3,8 @@
use std::fmt::Write;
// Internal
use clap::*;
use clap_complete::*;
use clap::{builder, Arg, ArgAction, Command, ValueHint};
use clap_complete::{generator, Generator};
/// Generate fig completion file
pub struct Fig;

View file

@ -6,9 +6,11 @@
//! Generates [Fig](https://github.com/withfig/autocomplete) completions for [`clap`](https://github.com/clap-rs/clap) based CLIs
#![doc(html_logo_url = "https://raw.githubusercontent.com/clap-rs/clap/master/assets/clap.png")]
#![warn(missing_docs, trivial_casts, unused_allocation, trivial_numeric_casts)]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![forbid(unsafe_code)]
#![allow(clippy::needless_doctest_main)]
#![warn(missing_docs)]
#![warn(clippy::print_stderr)]
#![warn(clippy::print_stdout)]
mod fig;
pub use fig::Fig;

View file

@ -1,4 +1,6 @@
pub fn basic_command(name: &'static str) -> clap::Command {
#![allow(dead_code)]
pub(crate) fn basic_command(name: &'static str) -> clap::Command {
clap::Command::new(name)
.arg(
clap::Arg::new("config")
@ -23,7 +25,7 @@ pub fn basic_command(name: &'static str) -> clap::Command {
)
}
pub fn feature_sample_command(name: &'static str) -> clap::Command {
pub(crate) fn feature_sample_command(name: &'static str) -> clap::Command {
clap::Command::new(name)
.version("3.0")
.propagate_version(true)
@ -53,7 +55,7 @@ pub fn feature_sample_command(name: &'static str) -> clap::Command {
)
}
pub fn special_commands_command(name: &'static str) -> clap::Command {
pub(crate) fn special_commands_command(name: &'static str) -> clap::Command {
feature_sample_command(name)
.subcommand(
clap::Command::new("some_cmd")
@ -72,7 +74,7 @@ pub fn special_commands_command(name: &'static str) -> clap::Command {
.subcommand(clap::Command::new("some-hidden-cmd").hide(true))
}
pub fn quoting_command(name: &'static str) -> clap::Command {
pub(crate) fn quoting_command(name: &'static str) -> clap::Command {
clap::Command::new(name)
.version("3.0")
.arg(
@ -122,7 +124,7 @@ pub fn quoting_command(name: &'static str) -> clap::Command {
])
}
pub fn aliases_command(name: &'static str) -> clap::Command {
pub(crate) fn aliases_command(name: &'static str) -> clap::Command {
clap::Command::new(name)
.version("3.0")
.about("testing bash completions")
@ -147,7 +149,7 @@ pub fn aliases_command(name: &'static str) -> clap::Command {
.arg(clap::Arg::new("positional"))
}
pub fn sub_subcommands_command(name: &'static str) -> clap::Command {
pub(crate) fn sub_subcommands_command(name: &'static str) -> clap::Command {
feature_sample_command(name).subcommand(
clap::Command::new("some_cmd")
.about("top level subcommand")
@ -165,7 +167,7 @@ pub fn sub_subcommands_command(name: &'static str) -> clap::Command {
)
}
pub fn value_hint_command(name: &'static str) -> clap::Command {
pub(crate) fn value_hint_command(name: &'static str) -> clap::Command {
clap::Command::new(name)
.arg(
clap::Arg::new("choice")
@ -249,7 +251,7 @@ pub fn value_hint_command(name: &'static str) -> clap::Command {
)
}
pub fn assert_matches(
pub(crate) fn assert_matches(
expected: impl Into<snapbox::Data>,
gen: impl clap_complete::Generator,
mut cmd: clap::Command,

View file

@ -39,3 +39,6 @@ snapbox = { version = "0.5.9", features = ["diff", "examples", "path"] }
clap = { path = "../", version = "4.0.0", default-features = false, features = ["std", "help"] }
completest = "0.4.0"
completest-nu = "0.4.0"
[lints]
workspace = true

View file

@ -16,8 +16,11 @@
//! ```
#![doc(html_logo_url = "https://raw.githubusercontent.com/clap-rs/clap/master/assets/clap.png")]
#![warn(missing_docs, trivial_casts, unused_allocation, trivial_numeric_casts)]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![forbid(unsafe_code)]
#![warn(missing_docs)]
#![warn(clippy::print_stderr)]
#![warn(clippy::print_stdout)]
use clap::builder::StyledStr;
use clap::{builder::PossibleValue, Arg, ArgAction, Command};
@ -46,14 +49,14 @@ impl Generator for Nushell {
completions.push_str("export use completions *\n");
buf.write_all(completions.as_bytes())
.expect("Failed to write to generated file")
.expect("Failed to write to generated file");
}
}
fn append_value_completion_and_help(
arg: &Arg,
name: &str,
possible_values: &Vec<PossibleValue>,
possible_values: &[PossibleValue],
s: &mut String,
) {
let takes_values = arg
@ -65,7 +68,7 @@ fn append_value_completion_and_help(
s.push_str(": string");
if !possible_values.is_empty() {
s.push_str(format!(r#"@"nu-complete {} {}""#, name, arg.get_id()).as_str())
s.push_str(format!(r#"@"nu-complete {} {}""#, name, arg.get_id()).as_str());
}
}

View file

@ -2,7 +2,7 @@
use clap::{builder::PossibleValue, Arg, ArgAction, Command, ValueHint};
pub fn basic_command(name: &'static str) -> Command {
pub(crate) fn basic_command(name: &'static str) -> Command {
Command::new(name)
.arg(
Arg::new("config")
@ -23,7 +23,7 @@ pub fn basic_command(name: &'static str) -> Command {
)
}
pub fn feature_sample_command(name: &'static str) -> Command {
pub(crate) fn feature_sample_command(name: &'static str) -> Command {
Command::new(name)
.version("3.0")
.propagate_version(true)
@ -53,7 +53,7 @@ pub fn feature_sample_command(name: &'static str) -> Command {
)
}
pub fn special_commands_command(name: &'static str) -> Command {
pub(crate) fn special_commands_command(name: &'static str) -> Command {
feature_sample_command(name)
.subcommand(
Command::new("some_cmd")
@ -72,7 +72,7 @@ pub fn special_commands_command(name: &'static str) -> Command {
.subcommand(Command::new("some-hidden-cmd").hide(true))
}
pub fn quoting_command(name: &'static str) -> Command {
pub(crate) fn quoting_command(name: &'static str) -> Command {
Command::new(name)
.version("3.0")
.arg(
@ -121,7 +121,7 @@ pub fn quoting_command(name: &'static str) -> Command {
])
}
pub fn aliases_command(name: &'static str) -> Command {
pub(crate) fn aliases_command(name: &'static str) -> Command {
Command::new(name)
.version("3.0")
.about("testing nushell completions")
@ -146,7 +146,7 @@ pub fn aliases_command(name: &'static str) -> Command {
.arg(Arg::new("positional"))
}
pub fn sub_subcommands_command(name: &'static str) -> Command {
pub(crate) fn sub_subcommands_command(name: &'static str) -> Command {
feature_sample_command(name).subcommand(
Command::new("some_cmd")
.about("top level subcommand")
@ -167,7 +167,7 @@ pub fn sub_subcommands_command(name: &'static str) -> Command {
)
}
pub fn value_hint_command(name: &'static str) -> Command {
pub(crate) fn value_hint_command(name: &'static str) -> Command {
Command::new(name)
.arg(
Arg::new("choice")
@ -243,10 +243,10 @@ pub fn value_hint_command(name: &'static str) -> Command {
)
}
pub fn assert_matches(
pub(crate) fn assert_matches(
expected: impl Into<snapbox::Data>,
gen: impl clap_complete::Generator,
mut cmd: clap::Command,
mut cmd: Command,
name: &'static str,
) {
let mut buf = vec![];
@ -258,7 +258,7 @@ pub fn assert_matches(
.matches(expected, buf);
}
pub fn register_example<R: completest::RuntimeBuilder>(context: &str, name: &str) {
pub(crate) fn register_example<R: completest::RuntimeBuilder>(context: &str, name: &str) {
use completest::Runtime as _;
let scratch = snapbox::path::PathFixture::mutable_temp().unwrap();
@ -306,7 +306,7 @@ pub fn register_example<R: completest::RuntimeBuilder>(context: &str, name: &str
scratch.close().unwrap();
}
pub fn load_runtime<R: completest::RuntimeBuilder>(
pub(crate) fn load_runtime<R: completest::RuntimeBuilder>(
context: &str,
name: &str,
) -> Box<dyn completest::Runtime>
@ -365,7 +365,7 @@ impl completest::Runtime for ScratchRuntime {
}
}
pub fn has_command(command: &str) -> bool {
pub(crate) fn has_command(command: &str) -> bool {
let output = match std::process::Command::new(command)
.arg("--version")
.output()

View file

@ -40,3 +40,6 @@ debug = []
unstable-v5 = ["deprecated"]
deprecated = []
raw-deprecated = ["deprecated"]
[lints]
workspace = true

View file

@ -14,15 +14,15 @@ use syn::{
use crate::utils::Sp;
#[derive(Clone)]
pub struct ClapAttr {
pub kind: Sp<AttrKind>,
pub name: Ident,
pub magic: Option<MagicAttrName>,
pub value: Option<AttrValue>,
pub(crate) struct ClapAttr {
pub(crate) kind: Sp<AttrKind>,
pub(crate) name: Ident,
pub(crate) magic: Option<MagicAttrName>,
pub(crate) value: Option<AttrValue>,
}
impl ClapAttr {
pub fn parse_all(all_attrs: &[Attribute]) -> Result<Vec<Self>, syn::Error> {
pub(crate) fn parse_all(all_attrs: &[Attribute]) -> Result<Vec<Self>, syn::Error> {
let mut parsed = Vec::new();
for attr in all_attrs {
let kind = if attr.path().is_ident("clap") {
@ -50,13 +50,13 @@ impl ClapAttr {
Ok(parsed)
}
pub fn value_or_abort(&self) -> Result<&AttrValue, syn::Error> {
pub(crate) fn value_or_abort(&self) -> Result<&AttrValue, syn::Error> {
self.value
.as_ref()
.ok_or_else(|| format_err!(self.name, "attribute `{}` requires a value", self.name))
}
pub fn lit_str_or_abort(&self) -> Result<&LitStr, syn::Error> {
pub(crate) fn lit_str_or_abort(&self) -> Result<&LitStr, syn::Error> {
let value = self.value_or_abort()?;
match value {
AttrValue::LitStr(tokens) => Ok(tokens),
@ -72,7 +72,7 @@ impl ClapAttr {
}
impl Parse for ClapAttr {
fn parse(input: ParseStream) -> syn::Result<Self> {
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
let name: Ident = input.parse()?;
let name_str = name.to_string();
@ -142,7 +142,7 @@ impl Parse for ClapAttr {
}
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum MagicAttrName {
pub(crate) enum MagicAttrName {
Short,
Long,
ValueParser,
@ -172,7 +172,7 @@ pub enum MagicAttrName {
#[derive(Clone)]
#[allow(clippy::large_enum_variant)]
pub enum AttrValue {
pub(crate) enum AttrValue {
LitStr(LitStr),
Expr(Expr),
Call(Vec<Expr>),
@ -185,14 +185,14 @@ impl ToTokens for AttrValue {
Self::Expr(t) => t.to_tokens(tokens),
Self::Call(t) => {
let t = quote!(#(#t),*);
t.to_tokens(tokens)
t.to_tokens(tokens);
}
}
}
}
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum AttrKind {
pub(crate) enum AttrKind {
Clap,
StructOpt,
Command,
@ -202,7 +202,7 @@ pub enum AttrKind {
}
impl AttrKind {
pub fn as_str(&self) -> &'static str {
pub(crate) fn as_str(&self) -> &'static str {
match self {
Self::Clap => "clap",
Self::StructOpt => "structopt",

View file

@ -22,7 +22,7 @@ use syn::{
use crate::item::{Item, Kind, Name};
use crate::utils::{inner_type, sub_type, Sp, Ty};
pub fn derive_args(input: &DeriveInput) -> Result<TokenStream, syn::Error> {
pub(crate) fn derive_args(input: &DeriveInput) -> Result<TokenStream, syn::Error> {
let ident = &input.ident;
match input.data {
@ -55,7 +55,7 @@ pub fn derive_args(input: &DeriveInput) -> Result<TokenStream, syn::Error> {
}
}
pub fn gen_for_struct(
pub(crate) fn gen_for_struct(
item: &Item,
item_name: &Ident,
generics: &Generics,
@ -166,7 +166,7 @@ pub fn gen_for_struct(
/// Generate a block of code to add arguments/subcommands corresponding to
/// the `fields` to an cmd.
pub fn gen_augment(
pub(crate) fn gen_augment(
fields: &[(&Field, Item)],
app_var: &Ident,
parent_item: &Item,
@ -431,7 +431,7 @@ pub fn gen_augment(
}})
}
pub fn gen_constructor(fields: &[(&Field, Item)]) -> Result<TokenStream, syn::Error> {
pub(crate) fn gen_constructor(fields: &[(&Field, Item)]) -> Result<TokenStream, syn::Error> {
let fields = fields.iter().map(|(field, item)| {
let field_name = field.ident.as_ref().unwrap();
let kind = item.kind();
@ -542,7 +542,10 @@ pub fn gen_constructor(fields: &[(&Field, Item)]) -> Result<TokenStream, syn::Er
}})
}
pub fn gen_updater(fields: &[(&Field, Item)], use_self: bool) -> Result<TokenStream, syn::Error> {
pub(crate) fn gen_updater(
fields: &[(&Field, Item)],
use_self: bool,
) -> Result<TokenStream, syn::Error> {
let mut genned_fields = Vec::new();
for (field, item) in fields {
let field_name = field.ident.as_ref().unwrap();
@ -750,19 +753,19 @@ fn gen_parsers(
}
#[cfg(feature = "raw-deprecated")]
pub fn raw_deprecated() -> TokenStream {
pub(crate) fn raw_deprecated() -> TokenStream {
quote! {}
}
#[cfg(not(feature = "raw-deprecated"))]
pub fn raw_deprecated() -> TokenStream {
pub(crate) fn raw_deprecated() -> TokenStream {
quote! {
#![allow(deprecated)] // Assuming any deprecation in here will be related to a deprecation in `Args`
}
}
pub fn collect_args_fields<'a>(
pub(crate) fn collect_args_fields<'a>(
item: &'a Item,
fields: &'a FieldsNamed,
) -> Result<Vec<(&'a Field, Item)>, syn::Error> {

View file

@ -18,7 +18,7 @@ use syn::{Generics, Ident};
use crate::item::Item;
pub fn gen_for_struct(
pub(crate) fn gen_for_struct(
item: &Item,
item_name: &Ident,
generics: &Generics,
@ -66,7 +66,7 @@ pub fn gen_for_struct(
Ok(tokens)
}
pub fn gen_for_enum(
pub(crate) fn gen_for_enum(
item: &Item,
item_name: &Ident,
generics: &Generics,

View file

@ -17,7 +17,7 @@ mod parser;
mod subcommand;
mod value_enum;
pub use self::parser::derive_parser;
pub use args::derive_args;
pub use subcommand::derive_subcommand;
pub use value_enum::derive_value_enum;
pub(crate) use self::parser::derive_parser;
pub(crate) use args::derive_args;
pub(crate) use subcommand::derive_subcommand;
pub(crate) use value_enum::derive_value_enum;

View file

@ -26,7 +26,7 @@ use crate::derives::{args, into_app, subcommand};
use crate::item::Item;
use crate::item::Name;
pub fn derive_parser(input: &DeriveInput) -> Result<TokenStream, syn::Error> {
pub(crate) fn derive_parser(input: &DeriveInput) -> Result<TokenStream, syn::Error> {
let ident = &input.ident;
let pkg_name = std::env::var("CARGO_PKG_NAME").ok().unwrap_or_default();

View file

@ -21,7 +21,7 @@ use crate::derives::args::collect_args_fields;
use crate::item::{Item, Kind, Name};
use crate::utils::{is_simple_ty, subty_if_name};
pub fn derive_subcommand(input: &DeriveInput) -> Result<TokenStream, syn::Error> {
pub(crate) fn derive_subcommand(input: &DeriveInput) -> Result<TokenStream, syn::Error> {
let ident = &input.ident;
match input.data {
@ -43,7 +43,7 @@ pub fn derive_subcommand(input: &DeriveInput) -> Result<TokenStream, syn::Error>
}
}
pub fn gen_for_enum(
pub(crate) fn gen_for_enum(
item: &Item,
item_name: &Ident,
generics: &Generics,
@ -140,7 +140,7 @@ fn gen_augment(
parent_item: &Item,
override_required: bool,
) -> Result<TokenStream, syn::Error> {
use syn::Fields::*;
use syn::Fields::{Named, Unit, Unnamed};
let app_var = Ident::new("__clap_app", Span::call_site());
@ -357,7 +357,7 @@ fn gen_augment(
}
fn gen_has_subcommand(variants: &[(&Variant, Item)]) -> Result<TokenStream, syn::Error> {
use syn::Fields::*;
use syn::Fields::Unnamed;
let mut ext_subcmd = false;
@ -421,7 +421,7 @@ fn gen_has_subcommand(variants: &[(&Variant, Item)]) -> Result<TokenStream, syn:
}
fn gen_from_arg_matches(variants: &[(&Variant, Item)]) -> Result<TokenStream, syn::Error> {
use syn::Fields::*;
use syn::Fields::{Named, Unit, Unnamed};
let subcommand_name_var = format_ident!("__clap_name");
let sub_arg_matches_var = format_ident!("__clap_arg_matches");
@ -572,7 +572,7 @@ fn gen_from_arg_matches(variants: &[(&Variant, Item)]) -> Result<TokenStream, sy
}
fn gen_update_from_arg_matches(variants: &[(&Variant, Item)]) -> Result<TokenStream, syn::Error> {
use syn::Fields::*;
use syn::Fields::{Named, Unit, Unnamed};
let (flatten, variants): (Vec<_>, Vec<_>) = variants
.iter()

View file

@ -15,7 +15,7 @@ use syn::{spanned::Spanned, Data, DeriveInput, Fields, Ident, Variant};
use crate::item::{Item, Kind, Name};
pub fn derive_value_enum(input: &DeriveInput) -> Result<TokenStream, syn::Error> {
pub(crate) fn derive_value_enum(input: &DeriveInput) -> Result<TokenStream, syn::Error> {
let ident = &input.ident;
match input.data {
@ -34,7 +34,7 @@ pub fn derive_value_enum(input: &DeriveInput) -> Result<TokenStream, syn::Error>
}
}
pub fn gen_for_enum(
pub(crate) fn gen_for_enum(
item: &Item,
item_name: &Ident,
variants: &[(&Variant, Item)],

View file

@ -4,7 +4,7 @@ use proc_macro2::Ident;
use quote::quote;
#[must_use]
pub fn parser(name: &Ident) -> proc_macro2::TokenStream {
pub(crate) fn parser(name: &Ident) -> proc_macro2::TokenStream {
let into_app = into_app(name);
quote!(
#[automatically_derived]
@ -14,7 +14,7 @@ pub fn parser(name: &Ident) -> proc_macro2::TokenStream {
}
#[must_use]
pub fn into_app(name: &Ident) -> proc_macro2::TokenStream {
pub(crate) fn into_app(name: &Ident) -> proc_macro2::TokenStream {
quote! {
#[automatically_derived]
impl clap::CommandFactory for #name {
@ -29,7 +29,7 @@ pub fn into_app(name: &Ident) -> proc_macro2::TokenStream {
}
#[must_use]
pub fn from_arg_matches(name: &Ident) -> proc_macro2::TokenStream {
pub(crate) fn from_arg_matches(name: &Ident) -> proc_macro2::TokenStream {
quote! {
#[automatically_derived]
impl clap::FromArgMatches for #name {
@ -44,7 +44,7 @@ pub fn from_arg_matches(name: &Ident) -> proc_macro2::TokenStream {
}
#[must_use]
pub fn subcommand(name: &Ident) -> proc_macro2::TokenStream {
pub(crate) fn subcommand(name: &Ident) -> proc_macro2::TokenStream {
let from_arg_matches = from_arg_matches(name);
quote! {
#[automatically_derived]
@ -64,7 +64,7 @@ pub fn subcommand(name: &Ident) -> proc_macro2::TokenStream {
}
#[must_use]
pub fn args(name: &Ident) -> proc_macro2::TokenStream {
pub(crate) fn args(name: &Ident) -> proc_macro2::TokenStream {
let from_arg_matches = from_arg_matches(name);
quote! {
#[automatically_derived]
@ -81,7 +81,7 @@ pub fn args(name: &Ident) -> proc_macro2::TokenStream {
}
#[must_use]
pub fn value_enum(name: &Ident) -> proc_macro2::TokenStream {
pub(crate) fn value_enum(name: &Ident) -> proc_macro2::TokenStream {
quote! {
#[automatically_derived]
impl clap::ValueEnum for #name {

View file

@ -20,17 +20,17 @@ use quote::{format_ident, quote, quote_spanned, ToTokens};
use syn::DeriveInput;
use syn::{self, ext::IdentExt, spanned::Spanned, Attribute, Field, Ident, LitStr, Type, Variant};
use crate::attr::*;
use crate::attr::{AttrKind, AttrValue, ClapAttr, MagicAttrName};
use crate::utils::{extract_doc_comment, format_doc_comment, inner_type, is_simple_ty, Sp, Ty};
/// Default casing style for generated arguments.
pub const DEFAULT_CASING: CasingStyle = CasingStyle::Kebab;
pub(crate) const DEFAULT_CASING: CasingStyle = CasingStyle::Kebab;
/// Default casing style for environment variables
pub const DEFAULT_ENV_CASING: CasingStyle = CasingStyle::ScreamingSnake;
pub(crate) const DEFAULT_ENV_CASING: CasingStyle = CasingStyle::ScreamingSnake;
#[derive(Clone)]
pub struct Item {
pub(crate) struct Item {
name: Name,
casing: Sp<CasingStyle>,
env_casing: Sp<CasingStyle>,
@ -53,7 +53,7 @@ pub struct Item {
}
impl Item {
pub fn from_args_struct(input: &DeriveInput, name: Name) -> Result<Self, syn::Error> {
pub(crate) fn from_args_struct(input: &DeriveInput, name: Name) -> Result<Self, syn::Error> {
let ident = input.ident.clone();
let span = input.ident.span();
let attrs = &input.attrs;
@ -70,7 +70,10 @@ impl Item {
Ok(res)
}
pub fn from_subcommand_enum(input: &DeriveInput, name: Name) -> Result<Self, syn::Error> {
pub(crate) fn from_subcommand_enum(
input: &DeriveInput,
name: Name,
) -> Result<Self, syn::Error> {
let ident = input.ident.clone();
let span = input.ident.span();
let attrs = &input.attrs;
@ -87,7 +90,7 @@ impl Item {
Ok(res)
}
pub fn from_value_enum(input: &DeriveInput, name: Name) -> Result<Self, syn::Error> {
pub(crate) fn from_value_enum(input: &DeriveInput, name: Name) -> Result<Self, syn::Error> {
let ident = input.ident.clone();
let span = input.ident.span();
let attrs = &input.attrs;
@ -113,7 +116,7 @@ impl Item {
Ok(res)
}
pub fn from_subcommand_variant(
pub(crate) fn from_subcommand_variant(
variant: &Variant,
struct_casing: Sp<CasingStyle>,
env_casing: Sp<CasingStyle>,
@ -167,7 +170,7 @@ impl Item {
Ok(res)
}
pub fn from_value_enum_variant(
pub(crate) fn from_value_enum_variant(
variant: &Variant,
argument_casing: Sp<CasingStyle>,
env_casing: Sp<CasingStyle>,
@ -193,7 +196,7 @@ impl Item {
Ok(res)
}
pub fn from_args_field(
pub(crate) fn from_args_field(
field: &Field,
struct_casing: Sp<CasingStyle>,
env_casing: Sp<CasingStyle>,
@ -501,11 +504,11 @@ impl Item {
Some(MagicAttrName::ValueEnum) if attr.value.is_none() => {
assert_attr_kind(attr, &[AttrKind::Arg])?;
self.is_enum = true
self.is_enum = true;
}
Some(MagicAttrName::VerbatimDocComment) if attr.value.is_none() => {
self.verbatim_doc_comment = true
self.verbatim_doc_comment = true;
}
Some(MagicAttrName::About) if attr.value.is_none() => {
@ -941,14 +944,14 @@ impl Item {
Ok(())
}
pub fn find_default_method(&self) -> Option<&Method> {
pub(crate) fn find_default_method(&self) -> Option<&Method> {
self.methods
.iter()
.find(|m| m.name == "default_value" || m.name == "default_value_os")
}
/// generate methods from attributes on top of struct or enum
pub fn initial_top_level_methods(&self) -> TokenStream {
pub(crate) fn initial_top_level_methods(&self) -> TokenStream {
let next_display_order = self.next_display_order.as_ref().into_iter();
let next_help_heading = self.next_help_heading.as_ref().into_iter();
quote!(
@ -957,7 +960,7 @@ impl Item {
)
}
pub fn final_top_level_methods(&self) -> TokenStream {
pub(crate) fn final_top_level_methods(&self) -> TokenStream {
let methods = &self.methods;
let doc_comment = &self.doc_comment;
@ -965,49 +968,49 @@ impl Item {
}
/// generate methods on top of a field
pub fn field_methods(&self) -> proc_macro2::TokenStream {
pub(crate) fn field_methods(&self) -> TokenStream {
let methods = &self.methods;
let doc_comment = &self.doc_comment;
quote!( #(#doc_comment)* #(#methods)* )
}
pub fn group_id(&self) -> &Name {
pub(crate) fn group_id(&self) -> &Name {
&self.group_id
}
pub fn group_methods(&self) -> TokenStream {
pub(crate) fn group_methods(&self) -> TokenStream {
let group_methods = &self.group_methods;
quote!( #(#group_methods)* )
}
pub fn deprecations(&self) -> proc_macro2::TokenStream {
pub(crate) fn deprecations(&self) -> TokenStream {
let deprecations = &self.deprecations;
quote!( #(#deprecations)* )
}
pub fn next_display_order(&self) -> TokenStream {
pub(crate) fn next_display_order(&self) -> TokenStream {
let next_display_order = self.next_display_order.as_ref().into_iter();
quote!( #(#next_display_order)* )
}
pub fn next_help_heading(&self) -> TokenStream {
pub(crate) fn next_help_heading(&self) -> TokenStream {
let next_help_heading = self.next_help_heading.as_ref().into_iter();
quote!( #(#next_help_heading)* )
}
pub fn id(&self) -> &Name {
pub(crate) fn id(&self) -> &Name {
&self.name
}
pub fn cased_name(&self) -> TokenStream {
pub(crate) fn cased_name(&self) -> TokenStream {
self.name.clone().translate(*self.casing)
}
pub fn value_name(&self) -> TokenStream {
pub(crate) fn value_name(&self) -> TokenStream {
self.name.clone().translate(CasingStyle::ScreamingSnake)
}
pub fn value_parser(&self, field_type: &Type) -> Method {
pub(crate) fn value_parser(&self, field_type: &Type) -> Method {
self.value_parser
.clone()
.map(|p| {
@ -1030,7 +1033,7 @@ impl Item {
})
}
pub fn action(&self, field_type: &Type) -> Method {
pub(crate) fn action(&self, field_type: &Type) -> Method {
self.action
.clone()
.map(|p| p.resolve(field_type))
@ -1049,29 +1052,29 @@ impl Item {
})
}
pub fn kind(&self) -> Sp<Kind> {
pub(crate) fn kind(&self) -> Sp<Kind> {
self.kind.clone()
}
pub fn is_positional(&self) -> bool {
pub(crate) fn is_positional(&self) -> bool {
self.is_positional
}
pub fn casing(&self) -> Sp<CasingStyle> {
pub(crate) fn casing(&self) -> Sp<CasingStyle> {
self.casing
}
pub fn env_casing(&self) -> Sp<CasingStyle> {
pub(crate) fn env_casing(&self) -> Sp<CasingStyle> {
self.env_casing
}
pub fn has_explicit_methods(&self) -> bool {
pub(crate) fn has_explicit_methods(&self) -> bool {
self.methods
.iter()
.any(|m| m.name != "help" && m.name != "long_help")
}
pub fn skip_group(&self) -> bool {
pub(crate) fn skip_group(&self) -> bool {
self.skip_group
}
}
@ -1109,20 +1112,20 @@ fn default_value_parser(inner_type: &Type, span: Span) -> Method {
}
#[derive(Clone)]
pub enum Action {
pub(crate) enum Action {
Explicit(Method),
Implicit(Ident),
}
impl Action {
pub fn resolve(self, _field_type: &Type) -> Method {
pub(crate) fn resolve(self, _field_type: &Type) -> Method {
match self {
Self::Explicit(method) => method,
Self::Implicit(ident) => default_action(_field_type, ident.span()),
}
}
pub fn span(&self) -> Span {
pub(crate) fn span(&self) -> Span {
match self {
Self::Explicit(method) => method.name.span(),
Self::Implicit(ident) => ident.span(),
@ -1162,7 +1165,7 @@ fn default_action(field_type: &Type, span: Span) -> Method {
#[allow(clippy::large_enum_variant)]
#[derive(Clone)]
pub enum Kind {
pub(crate) enum Kind {
Arg(Sp<Ty>),
Command(Sp<Ty>),
Value,
@ -1174,7 +1177,7 @@ pub enum Kind {
}
impl Kind {
pub fn name(&self) -> &'static str {
pub(crate) fn name(&self) -> &'static str {
match self {
Self::Arg(_) => "arg",
Self::Command(_) => "command",
@ -1187,7 +1190,7 @@ impl Kind {
}
}
pub fn attr_kind(&self) -> AttrKind {
pub(crate) fn attr_kind(&self) -> AttrKind {
match self {
Self::Arg(_) => AttrKind::Arg,
Self::Command(_) => AttrKind::Command,
@ -1200,7 +1203,7 @@ impl Kind {
}
}
pub fn ty(&self) -> Option<&Sp<Ty>> {
pub(crate) fn ty(&self) -> Option<&Sp<Ty>> {
match self {
Self::Arg(ty)
| Self::Command(ty)
@ -1213,13 +1216,13 @@ impl Kind {
}
#[derive(Clone)]
pub struct Method {
pub(crate) struct Method {
name: Ident,
args: TokenStream,
}
impl Method {
pub fn new(name: Ident, args: TokenStream) -> Self {
pub(crate) fn new(name: Ident, args: TokenStream) -> Self {
Method { name, args }
}
@ -1256,7 +1259,7 @@ impl Method {
}
impl ToTokens for Method {
fn to_tokens(&self, ts: &mut proc_macro2::TokenStream) {
fn to_tokens(&self, ts: &mut TokenStream) {
let Method { ref name, ref args } = self;
let tokens = quote!( .#name(#args) );
@ -1266,11 +1269,11 @@ impl ToTokens for Method {
}
#[derive(Clone)]
pub struct Deprecation {
pub span: Span,
pub id: &'static str,
pub version: &'static str,
pub description: String,
pub(crate) struct Deprecation {
pub(crate) span: Span,
pub(crate) id: &'static str,
pub(crate) version: &'static str,
pub(crate) description: String,
}
impl Deprecation {
@ -1289,7 +1292,7 @@ impl Deprecation {
}
impl ToTokens for Deprecation {
fn to_tokens(&self, ts: &mut proc_macro2::TokenStream) {
fn to_tokens(&self, ts: &mut TokenStream) {
let tokens = if cfg!(feature = "deprecated") {
let Deprecation {
span,
@ -1335,7 +1338,7 @@ fn assert_attr_kind(attr: &ClapAttr, possible_kind: &[AttrKind]) -> Result<(), s
/// replace all `:` with `, ` when not inside the `<>`
///
/// `"author1:author2:author3" => "author1, author2, author3"`
/// `"author1 <http://website1.com>:author2" => "author1 <http://website1.com>, author2"
/// `"author1 <http://website1.com>:author2" => "author1 <http://website1.com>, author2"`
fn process_author_str(author: &str) -> String {
let mut res = String::with_capacity(author.len());
let mut inside_angle_braces = 0usize;
@ -1359,7 +1362,7 @@ fn process_author_str(author: &str) -> String {
/// Defines the casing for the attributes long representation.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum CasingStyle {
pub(crate) enum CasingStyle {
/// Indicate word boundaries with uppercase letter, excluding the first word.
Camel,
/// Keep all letters lowercase and indicate word boundaries with hyphens.
@ -1380,7 +1383,9 @@ pub enum CasingStyle {
impl CasingStyle {
fn from_lit(name: &LitStr) -> Result<Sp<Self>, syn::Error> {
use self::CasingStyle::*;
use self::CasingStyle::{
Camel, Kebab, Lower, Pascal, ScreamingSnake, Snake, Upper, Verbatim,
};
let normalized = name.value().to_upper_camel_case().to_lowercase();
let cs = |kind| Sp::new(kind, name.span());
@ -1401,14 +1406,14 @@ impl CasingStyle {
}
#[derive(Clone)]
pub enum Name {
pub(crate) enum Name {
Derived(Ident),
Assigned(TokenStream),
}
impl Name {
pub fn translate(self, style: CasingStyle) -> TokenStream {
use CasingStyle::*;
pub(crate) fn translate(self, style: CasingStyle) -> TokenStream {
use CasingStyle::{Camel, Kebab, Lower, Pascal, ScreamingSnake, Snake, Upper, Verbatim};
match self {
Name::Assigned(tokens) => tokens,
@ -1429,8 +1434,8 @@ impl Name {
}
}
pub fn translate_char(self, style: CasingStyle) -> TokenStream {
use CasingStyle::*;
pub(crate) fn translate_char(self, style: CasingStyle) -> TokenStream {
use CasingStyle::{Camel, Kebab, Lower, Pascal, ScreamingSnake, Snake, Upper, Verbatim};
match self {
Name::Assigned(tokens) => quote!( (#tokens).chars().next().unwrap() ),
@ -1460,7 +1465,7 @@ impl ToTokens for Name {
Name::Assigned(t) => t.to_tokens(tokens),
Name::Derived(ident) => {
let s = ident.unraw().to_string();
quote_spanned!(ident.span()=> #s).to_tokens(tokens)
quote_spanned!(ident.span()=> #s).to_tokens(tokens);
}
}
}

View file

@ -12,11 +12,13 @@
// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the
// MIT/Apache 2.0 license.
#![doc(html_logo_url = "https://raw.githubusercontent.com/clap-rs/clap/master/assets/clap.png")]
#![doc = include_str!("../README.md")]
#![doc(html_logo_url = "https://raw.githubusercontent.com/clap-rs/clap/master/assets/clap.png")]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![forbid(unsafe_code)]
extern crate proc_macro;
#![warn(missing_docs)]
#![warn(clippy::print_stderr)]
#![warn(clippy::print_stdout)]
use proc_macro::TokenStream;
use syn::{parse_macro_input, DeriveInput};

View file

@ -5,7 +5,7 @@
use std::iter;
pub fn extract_doc_comment(attrs: &[syn::Attribute]) -> Vec<String> {
pub(crate) fn extract_doc_comment(attrs: &[syn::Attribute]) -> Vec<String> {
// multiline comments (`/** ... */`) may have LFs (`\n`) in them,
// we need to split so we could handle the lines correctly
//
@ -49,7 +49,7 @@ pub fn extract_doc_comment(attrs: &[syn::Attribute]) -> Vec<String> {
lines
}
pub fn format_doc_comment(
pub(crate) fn format_doc_comment(
lines: &[String],
preprocess: bool,
force_long: bool,

View file

@ -1,9 +1,9 @@
pub trait SpanError {
pub(crate) trait SpanError {
#[allow(non_snake_case)]
fn EXPECTED_Span_OR_ToTokens<D: std::fmt::Display>(&self, msg: D) -> syn::Error;
}
pub trait ToTokensError {
pub(crate) trait ToTokensError {
#[allow(non_snake_case)]
fn EXPECTED_Span_OR_ToTokens<D: std::fmt::Display>(&self, msg: D) -> syn::Error;
}

View file

@ -1,13 +1,13 @@
pub mod error;
pub(crate) mod error;
mod doc_comments;
mod spanned;
mod ty;
pub use doc_comments::extract_doc_comment;
pub use doc_comments::format_doc_comment;
pub(crate) use doc_comments::extract_doc_comment;
pub(crate) use doc_comments::format_doc_comment;
pub use self::{
pub(crate) use self::{
spanned::Sp,
ty::{inner_type, is_simple_ty, sub_type, subty_if_name, Ty},
};

View file

@ -6,21 +6,21 @@ use std::ops::{Deref, DerefMut};
/// An entity with a span attached.
#[derive(Debug, Copy, Clone)]
pub struct Sp<T> {
pub(crate) struct Sp<T> {
val: T,
span: Span,
}
impl<T> Sp<T> {
pub fn new(val: T, span: Span) -> Self {
pub(crate) fn new(val: T, span: Span) -> Self {
Sp { val, span }
}
pub fn get(&self) -> &T {
pub(crate) fn get(&self) -> &T {
&self.val
}
pub fn span(&self) -> Span {
pub(crate) fn span(&self) -> Span {
self.span
}
}

View file

@ -8,7 +8,7 @@ use syn::{
};
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Ty {
pub(crate) enum Ty {
Unit,
Vec,
VecVec,
@ -20,8 +20,8 @@ pub enum Ty {
}
impl Ty {
pub fn from_syn_ty(ty: &syn::Type) -> Sp<Self> {
use self::Ty::*;
pub(crate) fn from_syn_ty(ty: &Type) -> Sp<Self> {
use self::Ty::{Option, OptionOption, OptionVec, OptionVecVec, Other, Unit, Vec, VecVec};
let t = |kind| Sp::new(kind, ty.span());
if is_unit_ty(ty) {
@ -41,7 +41,7 @@ impl Ty {
}
}
pub fn as_str(&self) -> &'static str {
pub(crate) fn as_str(&self) -> &'static str {
match self {
Self::Unit => "()",
Self::Vec => "Vec<T>",
@ -55,7 +55,7 @@ impl Ty {
}
}
pub fn inner_type(field_ty: &syn::Type) -> &syn::Type {
pub(crate) fn inner_type(field_ty: &Type) -> &Type {
let ty = Ty::from_syn_ty(field_ty);
match *ty {
Ty::Vec | Ty::Option => sub_type(field_ty).unwrap_or(field_ty),
@ -70,12 +70,12 @@ pub fn inner_type(field_ty: &syn::Type) -> &syn::Type {
}
}
pub fn sub_type(ty: &syn::Type) -> Option<&syn::Type> {
pub(crate) fn sub_type(ty: &Type) -> Option<&Type> {
subty_if(ty, |_| true)
}
fn only_last_segment(mut ty: &syn::Type) -> Option<&PathSegment> {
while let syn::Type::Group(syn::TypeGroup { elem, .. }) = ty {
fn only_last_segment(mut ty: &Type) -> Option<&PathSegment> {
while let Type::Group(syn::TypeGroup { elem, .. }) = ty {
ty = elem;
}
match ty {
@ -92,7 +92,7 @@ fn only_last_segment(mut ty: &syn::Type) -> Option<&PathSegment> {
}
}
fn subty_if<F>(ty: &syn::Type, f: F) -> Option<&syn::Type>
fn subty_if<F>(ty: &Type, f: F) -> Option<&Type>
where
F: FnOnce(&PathSegment) -> bool,
{
@ -113,11 +113,11 @@ where
})
}
pub fn subty_if_name<'a>(ty: &'a syn::Type, name: &str) -> Option<&'a syn::Type> {
pub(crate) fn subty_if_name<'a>(ty: &'a Type, name: &str) -> Option<&'a Type> {
subty_if(ty, |seg| seg.ident == name)
}
pub fn is_simple_ty(ty: &syn::Type, name: &str) -> bool {
pub(crate) fn is_simple_ty(ty: &Type, name: &str) -> bool {
only_last_segment(ty)
.map(|segment| {
if let PathArguments::None = segment.arguments {
@ -129,12 +129,12 @@ pub fn is_simple_ty(ty: &syn::Type, name: &str) -> bool {
.unwrap_or(false)
}
fn is_generic_ty(ty: &syn::Type, name: &str) -> bool {
fn is_generic_ty(ty: &Type, name: &str) -> bool {
subty_if_name(ty, name).is_some()
}
fn is_unit_ty(ty: &syn::Type) -> bool {
if let syn::Type::Tuple(tuple) = ty {
fn is_unit_ty(ty: &Type) -> bool {
if let Type::Tuple(tuple) = ty {
tuple.elems.is_empty()
} else {
false

View file

@ -26,5 +26,11 @@ pre-release-replacements = [
{file="README.md", search="github.com/clap-rs/clap/blob/[^/]+/", replace="github.com/clap-rs/clap/blob/{{tag_name}}/", exactly=4, prerelease = true},
]
[dev-dependencies]
automod = "1.0.14"
[lib]
bench = false
[lints]
workspace = true

View file

@ -1,9 +1,10 @@
use std::ffi::OsStr;
/// String-like methods for [`OsStr`]
pub trait OsStrExt: private::Sealed {
/// Converts to a string slice.
///
/// The Utf8Error is guaranteed to have a valid UTF8 boundary
/// The `Utf8Error` is guaranteed to have a valid UTF8 boundary
/// in its `valid_up_to()`
fn try_str(&self) -> Result<&str, std::str::Utf8Error>;
/// Returns `true` if the given pattern matches a sub-slice of
@ -253,18 +254,15 @@ impl<'s, 'n> Iterator for Split<'s, 'n> {
fn next(&mut self) -> Option<Self::Item> {
let haystack = self.haystack?;
match haystack.split_once(self.needle) {
Some((first, second)) => {
if !haystack.is_empty() {
debug_assert_ne!(haystack, second);
}
self.haystack = Some(second);
Some(first)
}
None => {
self.haystack = None;
Some(haystack)
if let Some((first, second)) = haystack.split_once(self.needle) {
if !haystack.is_empty() {
debug_assert_ne!(haystack, second);
}
self.haystack = Some(second);
Some(first)
} else {
self.haystack = None;
Some(haystack)
}
}
}
@ -275,10 +273,12 @@ impl<'s, 'n> Iterator for Split<'s, 'n> {
///
/// `index` must be at a valid UTF-8 boundary
pub(crate) unsafe fn split_at(os: &OsStr, index: usize) -> (&OsStr, &OsStr) {
let bytes = os.as_encoded_bytes();
let (first, second) = bytes.split_at(index);
(
OsStr::from_encoded_bytes_unchecked(first),
OsStr::from_encoded_bytes_unchecked(second),
)
unsafe {
let bytes = os.as_encoded_bytes();
let (first, second) = bytes.split_at(index);
(
OsStr::from_encoded_bytes_unchecked(first),
OsStr::from_encoded_bytes_unchecked(second),
)
}
}

View file

@ -110,6 +110,11 @@
//! println!("{args:?}");
//! ```
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![warn(missing_docs)]
#![warn(clippy::print_stderr)]
#![warn(clippy::print_stdout)]
mod ext;
use std::ffi::OsStr;
@ -158,7 +163,7 @@ impl RawArgs {
/// let mut paths = raw.remaining(&mut cursor).map(PathBuf::from).collect::<Vec<_>>();
/// println!("{paths:?}");
/// ```
pub fn new(iter: impl IntoIterator<Item = impl Into<std::ffi::OsString>>) -> Self {
pub fn new(iter: impl IntoIterator<Item = impl Into<OsString>>) -> Self {
let iter = iter.into_iter();
Self::from(iter)
}

View file

@ -0,0 +1 @@
automod::dir!("tests/testsuite");

View file

@ -6,7 +6,7 @@ use std::ffi::OsStr;
fn to_long_stdio() {
let raw = clap_lex::RawArgs::new(["bin", "-"]);
let mut cursor = raw.cursor();
assert_eq!(raw.next_os(&mut cursor), Some(std::ffi::OsStr::new("bin")));
assert_eq!(raw.next_os(&mut cursor), Some(OsStr::new("bin")));
let next = raw.next(&mut cursor).unwrap();
assert!(!next.is_long());
@ -18,7 +18,7 @@ fn to_long_stdio() {
fn to_long_no_escape() {
let raw = clap_lex::RawArgs::new(["bin", "--"]);
let mut cursor = raw.cursor();
assert_eq!(raw.next_os(&mut cursor), Some(std::ffi::OsStr::new("bin")));
assert_eq!(raw.next_os(&mut cursor), Some(OsStr::new("bin")));
let next = raw.next(&mut cursor).unwrap();
assert!(!next.is_long());
@ -30,7 +30,7 @@ fn to_long_no_escape() {
fn to_long_no_value() {
let raw = clap_lex::RawArgs::new(["bin", "--long"]);
let mut cursor = raw.cursor();
assert_eq!(raw.next_os(&mut cursor), Some(std::ffi::OsStr::new("bin")));
assert_eq!(raw.next_os(&mut cursor), Some(OsStr::new("bin")));
let next = raw.next(&mut cursor).unwrap();
assert!(next.is_long());
@ -44,7 +44,7 @@ fn to_long_no_value() {
fn to_long_with_empty_value() {
let raw = clap_lex::RawArgs::new(["bin", "--long="]);
let mut cursor = raw.cursor();
assert_eq!(raw.next_os(&mut cursor), Some(std::ffi::OsStr::new("bin")));
assert_eq!(raw.next_os(&mut cursor), Some(OsStr::new("bin")));
let next = raw.next(&mut cursor).unwrap();
assert!(next.is_long());
@ -58,7 +58,7 @@ fn to_long_with_empty_value() {
fn to_long_with_value() {
let raw = clap_lex::RawArgs::new(["bin", "--long=hello"]);
let mut cursor = raw.cursor();
assert_eq!(raw.next_os(&mut cursor), Some(std::ffi::OsStr::new("bin")));
assert_eq!(raw.next_os(&mut cursor), Some(OsStr::new("bin")));
let next = raw.next(&mut cursor).unwrap();
assert!(next.is_long());
@ -72,7 +72,7 @@ fn to_long_with_value() {
fn to_short_stdio() {
let raw = clap_lex::RawArgs::new(["bin", "-"]);
let mut cursor = raw.cursor();
assert_eq!(raw.next_os(&mut cursor), Some(std::ffi::OsStr::new("bin")));
assert_eq!(raw.next_os(&mut cursor), Some(OsStr::new("bin")));
let next = raw.next(&mut cursor).unwrap();
assert!(!next.is_short());
@ -84,7 +84,7 @@ fn to_short_stdio() {
fn to_short_escape() {
let raw = clap_lex::RawArgs::new(["bin", "--"]);
let mut cursor = raw.cursor();
assert_eq!(raw.next_os(&mut cursor), Some(std::ffi::OsStr::new("bin")));
assert_eq!(raw.next_os(&mut cursor), Some(OsStr::new("bin")));
let next = raw.next(&mut cursor).unwrap();
assert!(!next.is_short());
@ -96,7 +96,7 @@ fn to_short_escape() {
fn to_short_long() {
let raw = clap_lex::RawArgs::new(["bin", "--long"]);
let mut cursor = raw.cursor();
assert_eq!(raw.next_os(&mut cursor), Some(std::ffi::OsStr::new("bin")));
assert_eq!(raw.next_os(&mut cursor), Some(OsStr::new("bin")));
let next = raw.next(&mut cursor).unwrap();
assert!(!next.is_short());
@ -108,7 +108,7 @@ fn to_short_long() {
fn to_short() {
let raw = clap_lex::RawArgs::new(["bin", "-short"]);
let mut cursor = raw.cursor();
assert_eq!(raw.next_os(&mut cursor), Some(std::ffi::OsStr::new("bin")));
assert_eq!(raw.next_os(&mut cursor), Some(OsStr::new("bin")));
let next = raw.next(&mut cursor).unwrap();
assert!(next.is_short());
@ -123,7 +123,7 @@ fn is_negative_number() {
for number in ["-10.0", "-1", "-100", "-3.5", "-1e10", "-1.3e10"] {
let raw = clap_lex::RawArgs::new(["bin", number]);
let mut cursor = raw.cursor();
assert_eq!(raw.next_os(&mut cursor), Some(std::ffi::OsStr::new("bin")));
assert_eq!(raw.next_os(&mut cursor), Some(OsStr::new("bin")));
let next = raw.next(&mut cursor).unwrap();
assert!(next.is_negative_number());
@ -134,7 +134,7 @@ fn is_negative_number() {
fn is_positive_number() {
let raw = clap_lex::RawArgs::new(["bin", "10.0"]);
let mut cursor = raw.cursor();
assert_eq!(raw.next_os(&mut cursor), Some(std::ffi::OsStr::new("bin")));
assert_eq!(raw.next_os(&mut cursor), Some(OsStr::new("bin")));
let next = raw.next(&mut cursor).unwrap();
assert!(!next.is_negative_number());
@ -145,7 +145,7 @@ fn is_not_number() {
for number in ["--10.0", "-..", "-2..", "-e", "-1e", "-1e10.2", "-.2"] {
let raw = clap_lex::RawArgs::new(["bin", number]);
let mut cursor = raw.cursor();
assert_eq!(raw.next_os(&mut cursor), Some(std::ffi::OsStr::new("bin")));
assert_eq!(raw.next_os(&mut cursor), Some(OsStr::new("bin")));
let next = raw.next(&mut cursor).unwrap();
assert!(
@ -159,7 +159,7 @@ fn is_not_number() {
fn is_stdio() {
let raw = clap_lex::RawArgs::new(["bin", "-"]);
let mut cursor = raw.cursor();
assert_eq!(raw.next_os(&mut cursor), Some(std::ffi::OsStr::new("bin")));
assert_eq!(raw.next_os(&mut cursor), Some(OsStr::new("bin")));
let next = raw.next(&mut cursor).unwrap();
assert!(next.is_stdio());
@ -169,7 +169,7 @@ fn is_stdio() {
fn is_not_stdio() {
let raw = clap_lex::RawArgs::new(["bin", "--"]);
let mut cursor = raw.cursor();
assert_eq!(raw.next_os(&mut cursor), Some(std::ffi::OsStr::new("bin")));
assert_eq!(raw.next_os(&mut cursor), Some(OsStr::new("bin")));
let next = raw.next(&mut cursor).unwrap();
assert!(!next.is_stdio());
@ -179,7 +179,7 @@ fn is_not_stdio() {
fn is_escape() {
let raw = clap_lex::RawArgs::new(["bin", "--"]);
let mut cursor = raw.cursor();
assert_eq!(raw.next_os(&mut cursor), Some(std::ffi::OsStr::new("bin")));
assert_eq!(raw.next_os(&mut cursor), Some(OsStr::new("bin")));
let next = raw.next(&mut cursor).unwrap();
assert!(next.is_escape());
@ -189,7 +189,7 @@ fn is_escape() {
fn is_not_escape() {
let raw = clap_lex::RawArgs::new(["bin", "-"]);
let mut cursor = raw.cursor();
assert_eq!(raw.next_os(&mut cursor), Some(std::ffi::OsStr::new("bin")));
assert_eq!(raw.next_os(&mut cursor), Some(OsStr::new("bin")));
let next = raw.next(&mut cursor).unwrap();
assert!(!next.is_escape());

View file

@ -38,7 +38,11 @@ clap = { path = "../", version = "4.0.0", default-features = false, features = [
[dev-dependencies]
snapbox = { version = "0.5.9", features = ["diff"] }
clap = { path = "../", version = "4.0.0", default-features = false, features = ["std", "help"] }
automod = "1.0.14"
[features]
default = []
debug = ["clap/debug"]
[lints]
workspace = true

View file

@ -4,7 +4,7 @@ use std::io;
// Run this example as `cargo run --example man | man -l -`.
fn main() -> Result<(), std::io::Error> {
fn main() -> Result<(), io::Error> {
let cmd = Command::new("myapp")
.version("1.0")
.author("Kevin K. <kbknapp@gmail.com>:Ola Nordmann <old@nordmann.no>")

View file

@ -1,8 +1,10 @@
#![doc(html_logo_url = "https://raw.githubusercontent.com/clap-rs/clap/master/assets/clap.png")]
#![doc = include_str!("../README.md")]
#![warn(missing_docs, trivial_casts, unused_allocation, trivial_numeric_casts)]
#![doc(html_logo_url = "https://raw.githubusercontent.com/clap-rs/clap/master/assets/clap.png")]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![forbid(unsafe_code)]
#![deny(missing_docs)]
#![warn(missing_docs)]
#![warn(clippy::print_stderr)]
#![warn(clippy::print_stdout)]
mod render;

View file

@ -57,7 +57,7 @@ pub(crate) fn synopsis(roff: &mut Roff, cmd: &clap::Command) {
};
if matches!(opt.get_action(), ArgAction::Count) {
line.push(roman("..."))
line.push(roman("..."));
}
line.push(roman(" "));
}
@ -165,7 +165,7 @@ pub(crate) fn options(roff: &mut Roff, cmd: &clap::Command) {
roff.control("RE", []);
}
possible_options(roff, pos, arg_help_written)
possible_options(roff, pos, arg_help_written);
}
}
@ -241,7 +241,7 @@ fn subcommand_markers(cmd: &clap::Command) -> (&'static str, &'static str) {
markers(cmd.is_subcommand_required_set())
}
fn option_markers(opt: &clap::Arg) -> (&'static str, &'static str) {
fn option_markers(opt: &Arg) -> (&'static str, &'static str) {
markers(opt.is_required_set())
}
@ -261,7 +261,7 @@ fn long_option(opt: &str) -> Inline {
bold(format!("--{opt}"))
}
fn option_help(opt: &clap::Arg) -> Option<&clap::builder::StyledStr> {
fn option_help(opt: &Arg) -> Option<&clap::builder::StyledStr> {
if !opt.is_hide_long_help_set() {
let long_help = opt.get_long_help();
if long_help.is_some() {
@ -275,7 +275,7 @@ fn option_help(opt: &clap::Arg) -> Option<&clap::builder::StyledStr> {
None
}
fn option_environment(opt: &clap::Arg) -> Option<Vec<Inline>> {
fn option_environment(opt: &Arg) -> Option<Vec<Inline>> {
if opt.is_hide_env_set() {
return None;
} else if let Some(env) = opt.get_env() {
@ -289,7 +289,7 @@ fn option_environment(opt: &clap::Arg) -> Option<Vec<Inline>> {
None
}
fn option_default_values(opt: &clap::Arg) -> Option<String> {
fn option_default_values(opt: &Arg) -> Option<String> {
if opt.is_hide_default_value_set() || !opt.get_num_args().expect("built").takes_values() {
return None;
} else if !opt.get_default_values().is_empty() {
@ -306,7 +306,7 @@ fn option_default_values(opt: &clap::Arg) -> Option<String> {
None
}
fn get_possible_values(arg: &clap::Arg) -> Option<(Vec<String>, bool)> {
fn get_possible_values(arg: &Arg) -> Option<(Vec<String>, bool)> {
if arg.is_hide_possible_values_set() {
return None;
}

Some files were not shown because too many files have changed in this diff Show more