Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/third_party/rust/clap_builder/src/output/   (Firefox Browser Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 19 kB image not shown  

Quelle  usage.rs

  Sprache: Rust
 

#![cfg_attr(not(feature = "usage"), allow(unused_imports))]
#![cfg_attr(not(feature = "usage"), allow(unused_variables))]
#![cfg_attr(not(feature = "usage"), allow(clippy::manual_map))]
#![cfg_attr(not(feature = "usage"), allow(dead_code))]

// Internal
use crate::builder::ArgAction;
use crate::builder::StyledStr;
use crate::builder::Styles;
use crate::builder::{ArgPredicate, Command};
use crate::parser::ArgMatcher;
use crate::util::ChildGraph;
use crate::util::FlatSet;
use crate::util::Id;

static DEFAULT_SUB_VALUE_NAME: &str = "COMMAND";
const USAGE_SEP: &str = "\n       ";

pub(cratestruct Usage<'cmd> {
    cmd: &'cmd Command,
    styles: &'cmd Styles,
    required: Option<&'cmd ChildGraph<Id>>,
}

impl<'cmd> Usage<'cmd> {
    pub(cratefn new(cmd: &'cmd Command) -> Self {
        Usage {
            cmd,
            styles: cmd.get_styles(),
            required: None,
        }
    }

    pub(cratefn required(mut self, required: &'cmd ChildGraph<Id>) -> Self {
        self.required = Some(required);
        self
    }

    // Creates a usage string for display. This happens just after all arguments were parsed, but before
    // any subcommands have been parsed (so as to give subcommands their own usage recursively)
    pub(cratefn create_usage_with_title(&self, used: &[Id]) -> Option<StyledStr> {
        debug!("Usage::create_usage_with_title");
        use std::fmt::Write as _;
        let mut styled = StyledStr::new();
        let _ = write!(
            styled,
            "{}Usage:{} ",
            self.styles.get_usage().render(),
            self.styles.get_usage().render_reset()
        );
        if self.write_usage_no_title(&mut styled, used) {
            styled.trim_end();
        } else {
            return None;
        }
        debug!("Usage::create_usage_with_title: usage={styled}");
        Some(styled)
    }

    // Creates a usage string (*without title*) if one was not provided by the user manually.
    pub(cratefn create_usage_no_title(&self, used: &[Id]) -> Option<StyledStr> {
        debug!("Usage::create_usage_no_title");

        let mut styled = StyledStr::new();
        if self.write_usage_no_title(&mut styled, used) {
            styled.trim_end();
            debug!("Usage::create_usage_no_title: usage={styled}");
            Some(styled)
        } else {
            None
        }
    }

    // Creates a usage string (*without title*) if one was not provided by the user manually.
    fn write_usage_no_title(&self, styled: &>mut StyledStr, used: &[Id]) -> bool {
        debug!("Usage::create_usage_no_title");
        if let Some(u) = self.cmd.get_override_usage() {
            styled.push_styled(u);
            true
        } else {
            #[cfg(feature = "usage")]
            {
                if used.is_empty() {
                    self.write_help_usage(styled);
                } else {
                    self.write_smart_usage(styled, used);
                }
                true
            }

            #[cfg(not(feature = "usage"))]
            {
                false
            }
        }
    }
}

#[cfg(feature = "usage")]
impl<'cmd> Usage<'cmd> {
    // Creates a usage string for display in help messages (i.e. not for errors)
    fn write_help_usage(&self, styled: &mut StyledStr) {
        debug!("Usage::write_help_usage");
        use std::fmt::Write;

        if self.cmd.has_visible_subcommands() && self.cmd.is_flatten_help_set() {
            if !self.cmd.is_subcommand_required_set()
                || self.cmd.is_args_conflicts_with_subcommands_set()
            {
                self.write_arg_usage(styled, &[], true);
                styled.trim_end();
                let _ = write!(styled, "{}", USAGE_SEP);
            }
            let mut cmd = self.cmd.clone();
            cmd.build();
            for (i, sub) in cmd
                .get_subcommands()
                .filter(|c| !c.is_hide_set())
                .enumerate()
            {
                if i != 0 {
                    styled.trim_end();
                    let _ = write!(styled, "{}", USAGE_SEP);
                }
                Usage::new(sub).write_usage_no_title(styled, &[]);
            }
        } else {
            self.write_arg_usage(styled, &[], true);
            self.write_subcommand_usage(styled);
        }
    }

    // Creates a context aware usage string, or "smart usage" from currently used
    // args, and requirements
    fn write_smart_usage(&self, styled: &mut StyledStr, used: &[Id]) {
        debug!("Usage::create_smart_usage");
        use std::fmt::Write;
        let placeholder = &self.styles.get_placeholder();

        self.write_arg_usage(styled, used, true);

        if self.cmd.is_subcommand_required_set() {
            let value_name = self
                .cmd
                .get_subcommand_value_name()
                .unwrap_or(DEFAULT_SUB_VALUE_NAME);
            let _ = write!(
                styled,
                "{}<{value_name}>{}",
                placeholder.render(),
                placeholder.render_reset()
            );
        }
    }

    fn write_arg_usage(&self, styled: &mut StyledStr, used: &[Id], incl_reqs: bool) {
        debug!("Usage::write_arg_usage; incl_reqs={incl_reqs:?}");
        use std::fmt::Write as _;
        let literal = &self.styles.get_literal();
        let placeholder = &self.styles.get_placeholder();

        let bin_name = self.cmd.get_usage_name_fallback();
        if !bin_name.is_empty() {
            // the trim won't properly remove a leading space due to the formatting
            let _ = write!(
                styled,
                "{}{bin_name}{} ",
                literal.render(),
                literal.render_reset()
            );
        }

        if used.is_empty() && self.needs_options_tag() {
            let _ = write!(
                styled,
                "{}[OPTIONS]{} ",
                placeholder.render(),
                placeholder.render_reset()
            );
        }

        self.write_args(styled, used, !incl_reqs);
    }

    fn write_subcommand_usage(&self, styled: &mut StyledStr) {
        debug!("Usage::write_subcommand_usage");
        use std::fmt::Write as _;

        // incl_reqs is only false when this function is called recursively
        if self.cmd.has_visible_subcommands() || self.cmd.is_allow_external_subcommands_set() {
            let literal = &self.styles.get_literal();
            let placeholder = &self.styles.get_placeholder();
            let value_name = self
                .cmd
                .get_subcommand_value_name()
                .unwrap_or(DEFAULT_SUB_VALUE_NAME);
            if self.cmd.is_subcommand_negates_reqs_set()
                || self.cmd.is_args_conflicts_with_subcommands_set()
            {
                styled.trim_end();
                let _ = write!(styled, "{}", USAGE_SEP);
                if self.cmd.is_args_conflicts_with_subcommands_set() {
                    let bin_name = self.cmd.get_usage_name_fallback();
                    // Short-circuit full usage creation since no args will be relevant
                    let _ = write!(
                        styled,
                        "{}{bin_name}{} ",
                        literal.render(),
                        literal.render_reset()
                    );
                } else {
                    self.write_arg_usage(styled, &[], false);
                }
                let _ = write!(
                    styled,
                    "{}<{value_name}>{}",
                    placeholder.render(),
                    placeholder.render_reset()
                );
            } else if self.cmd.is_subcommand_required_set() {
                let _ = write!(
                    styled,
                    "{}<{value_name}>{}",
                    placeholder.render(),
                    placeholder.render_reset()
                );
            } else {
                let _ = write!(
                    styled,
                    "{}[{value_name}]{}",
                    placeholder.render(),
                    placeholder.render_reset()
                );
            }
        }
    }

    // Determines if we need the `[OPTIONS]` tag in the usage string
    fn needs_options_tag(&self) -> bool {
        debug!("Usage::needs_options_tag");
        'outer: for f in self.cmd.get_non_positionals() {
            debug!("Usage::needs_options_tag:iter: f={}", f.get_id());

            // Don't print `[OPTIONS]` just for help or version
            if f.get_long() == Some("help") || f.get_long() == Some("version") {
                debug!("Usage::needs_options_tag:iter Option is built-in");
                continue;
            }
            match f.get_action() {
                ArgAction::Set
                | ArgAction::Append
                | ArgAction::SetTrue
                | ArgAction::SetFalse
                | ArgAction::Count => {}
                ArgAction::Help
                | ArgAction::HelpShort
                | ArgAction::HelpLong
                | ArgAction::Version => {
                    debug!("Usage::needs_options_tag:iter Option is built-in");
                    continue;
                }
            }

            if f.is_hide_set() {
                debug!("Usage::needs_options_tag:iter Option is hidden");
                continue;
            }
            if f.is_required_set() {
                debug!("Usage::needs_options_tag:iter Option is required");
                continue;
            }
            for grp_s in self.cmd.groups_for_arg(f.get_id()) {
                debug!("Usage::needs_options_tag:iter:iter: grp_s={grp_s:?}");
                if self.cmd.get_groups().any(|g| g.id == grp_s && g.required) {
                    debug!("Usage::needs_options_tag:iter:iter: Group is required");
                    continue 'outer;
                }
            }

            debug!("Usage::needs_options_tag:iter: [OPTIONS] required");
            return true;
        }

        debug!("Usage::needs_options_tag: [OPTIONS] not required");
        false
    }

    // Returns the required args in usage string form by fully unrolling all groups
    pub(cratefn write_args(&self, styled: &>mut StyledStr, incls: &[Id], force_optional: bool) {
        debug!("Usage::write_args: incls={incls:?}",);
        use std::fmt::Write as _;
        let literal = &self.styles.get_literal();

        let required_owned;
        let required = if let Some(required) = self.required {
            required
        } else {
            required_owned = self.cmd.required_graph();
            &required_owned
        };

        let mut unrolled_reqs = Vec::new();
        for a in required.iter() {
            let is_relevant = |(val, req_arg): &(ArgPredicate, Id)| -> Option<Id> {
                let required = match val {
                    ArgPredicate::Equals(_) => false,
                    ArgPredicate::IsPresent => true,
                };
                required.then(|| req_arg.clone())
            };

            for aa in self.cmd.unroll_arg_requires(is_relevant, a) {
                // if we don't check for duplicates here this causes duplicate error messages
                // see https://github.com/clap-rs/clap/issues/2770
                unrolled_reqs.push(aa);
            }
            // always include the required arg itself. it will not be enumerated
            // by unroll_requirements_for_arg.
            unrolled_reqs.push(a.clone());
        }
        debug!("Usage::get_args: unrolled_reqs={unrolled_reqs:?}");

        let mut required_groups_members = FlatSet::new();
        let mut required_groups = FlatSet::new();
        for req in unrolled_reqs.iter().chain(incls.iter()) {
            if self.cmd.find_group(req).is_some() {
                let group_members = self.cmd.unroll_args_in_group(req);
                let elem = self.cmd.format_group(req);
                required_groups.insert(elem);
                required_groups_members.extend(group_members);
            } else {
                debug_assert!(self.cmd.find(req).is_some());
            }
        }

        let mut required_opts = FlatSet::new();
        let mut required_positionals = Vec::new();
        for req in unrolled_reqs.iter().chain(incls.iter()) {
            if let Some(arg) = self.cmd.find(req) {
                if required_groups_members.contains(arg.get_id()) {
                    continue;
                }

                let stylized = arg.stylized(self.styles, Some(!force_optional));
                if let Some(index) = arg.get_index() {
                    let new_len = index + 1;
                    if required_positionals.len() < new_len {
                        required_positionals.resize(new_len, None);
                    }
                    required_positionals[index] = Some(stylized);
                } else {
                    required_opts.insert(stylized);
                }
            } else {
                debug_assert!(self.cmd.find_group(req).is_some());
            }
        }

        for pos in self.cmd.get_positionals() {
            if pos.is_hide_set() {
                continue;
            }
            if required_groups_members.contains(pos.get_id()) {
                continue;
            }

            let index = pos.get_index().unwrap();
            let new_len = index + 1;
            if required_positionals.len() < new_len {
                required_positionals.resize(new_len, None);
            }
            if required_positionals[index].is_some() {
                if pos.is_last_set() {
                    let styled = required_positionals[index].take().unwrap();
                    let mut new = StyledStr::new();
                    let _ = write!(new, "{}--{} ", literal.render(), literal.render_reset());
                    new.push_styled(&styled);
                    required_positionals[index] = Some(new);
                }
            } else {
                let mut styled;
                if pos.is_last_set() {
                    styled = StyledStr::new();
                    let _ = write!(styled, "{}[--{} ", literal.render(), literal.render_reset());
                    styled.push_styled(&pos.stylized(self.styles, Some(true)));
                    let _ = write!(styled, "{}]{}", literal.render(), literal.render_reset());
                } else {
                    styled = pos.stylized(self.styles, Some(false));
                }
                required_positionals[index] = Some(styled);
            }
            if pos.is_last_set() && force_optional {
                required_positionals[index] = None;
            }
        }

        if !force_optional {
            for arg in required_opts {
                styled.push_styled(&arg);
                styled.push_str(" ");
            }
            for arg in required_groups {
                styled.push_styled(&arg);
                styled.push_str(" ");
            }
        }
        for arg in required_positionals.into_iter().flatten() {
            styled.push_styled(&arg);
            styled.push_str(" ");
        }
    }

    pub(cratefn get_required_usage_from(
        &self,
        incls: &[Id],
        matcher: Option<&ArgMatcher>,
        incl_last: bool,
    ) -> Vec<StyledStr> {
        debug!(
            "Usage::get_required_usage_from: incls={:?}, matcher={:?}, incl_last={:?}",
            incls,
            matcher.is_some(),
            incl_last
        );

        let required_owned;
        let required = if let Some(required) = self.required {
            required
        } else {
            required_owned = self.cmd.required_graph();
            &required_owned
        };

        let mut unrolled_reqs = Vec::new();
        for a in required.iter() {
            let is_relevant = |(val, req_arg): &(ArgPredicate, Id)| -> Option<Id> {
                let required = match val {
                    ArgPredicate::Equals(_) => {
                        if let Some(matcher) = matcher {
                            matcher.check_explicit(a, val)
                        } else {
                            false
                        }
                    }
                    ArgPredicate::IsPresent => true,
                };
                required.then(|| req_arg.clone())
            };

            for aa in self.cmd.unroll_arg_requires(is_relevant, a) {
                // if we don't check for duplicates here this causes duplicate error messages
                // see https://github.com/clap-rs/clap/issues/2770
                unrolled_reqs.push(aa);
            }
            // always include the required arg itself. it will not be enumerated
            // by unroll_requirements_for_arg.
            unrolled_reqs.push(a.clone());
        }
        debug!("Usage::get_required_usage_from: unrolled_reqs={unrolled_reqs:?}");

        let mut required_groups_members = FlatSet::new();
        let mut required_groups = FlatSet::new();
        for req in unrolled_reqs.iter().chain(incls.iter()) {
            if self.cmd.find_group(req).is_some() {
                let group_members = self.cmd.unroll_args_in_group(req);
                let is_present = matcher
                    .map(|m| {
                        group_members
                            .iter()
                            .any(|arg| m.check_explicit(arg, &ArgPredicate::IsPresent))
                    })
                    .unwrap_or(false);
                debug!("Usage::get_required_usage_from:iter:{req:?} group is_present={is_present}");
                if is_present {
                    continue;
                }

                let elem = self.cmd.format_group(req);
                required_groups.insert(elem);
                required_groups_members.extend(group_members);
            } else {
                debug_assert!(self.cmd.find(req).is_some(), "`{req}` must exist");
            }
        }

        let mut required_opts = FlatSet::new();
        let mut required_positionals = Vec::new();
        for req in unrolled_reqs.iter().chain(incls.iter()) {
            if let Some(arg) = self.cmd.find(req) {
                if required_groups_members.contains(arg.get_id()) {
                    continue;
                }

                let is_present = matcher
                    .map(|m| m.check_explicit(req, &ArgPredicate::IsPresent))
                    .unwrap_or(false);
                debug!("Usage::get_required_usage_from:iter:{req:?} arg is_present={is_present}");
                if is_present {
                    continue;
                }

                let stylized = arg.stylized(self.styles, Some(true));
                if let Some(index) = arg.get_index() {
                    if !arg.is_last_set() || incl_last {
                        let new_len = index + 1;
                        if required_positionals.len() < new_len {
                            required_positionals.resize(new_len, None);
                        }
                        required_positionals[index] = Some(stylized);
                    }
                } else {
                    required_opts.insert(stylized);
                }
            } else {
                debug_assert!(self.cmd.find_group(req).is_some());
            }
        }

        let mut ret_val = Vec::new();
        ret_val.extend(required_opts);
        ret_val.extend(required_groups);
        for pos in required_positionals.into_iter().flatten() {
            ret_val.push(pos);
        }

        debug!("Usage::get_required_usage_from: ret_val={ret_val:?}");
        ret_val
    }
}

Messung V0.5 in Prozent
C=71 H=96 G=84

¤ Dauer der Verarbeitung: 0.13 Sekunden  (vorverarbeitet am  2026-06-23) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.