119625d8cSopenharmony_ci// Std 219625d8cSopenharmony_ciuse std::{ 319625d8cSopenharmony_ci cell::Cell, 419625d8cSopenharmony_ci ffi::{OsStr, OsString}, 519625d8cSopenharmony_ci}; 619625d8cSopenharmony_ci 719625d8cSopenharmony_ci// Third Party 819625d8cSopenharmony_ciuse clap_lex::RawOsStr; 919625d8cSopenharmony_ciuse clap_lex::RawOsString; 1019625d8cSopenharmony_ci 1119625d8cSopenharmony_ci// Internal 1219625d8cSopenharmony_ciuse crate::builder::{Arg, Command}; 1319625d8cSopenharmony_ciuse crate::error::Error as ClapError; 1419625d8cSopenharmony_ciuse crate::error::Result as ClapResult; 1519625d8cSopenharmony_ciuse crate::mkeymap::KeyType; 1619625d8cSopenharmony_ciuse crate::output::Usage; 1719625d8cSopenharmony_ciuse crate::parser::features::suggestions; 1819625d8cSopenharmony_ciuse crate::parser::AnyValue; 1919625d8cSopenharmony_ciuse crate::parser::{ArgMatcher, SubCommand}; 2019625d8cSopenharmony_ciuse crate::parser::{Validator, ValueSource}; 2119625d8cSopenharmony_ciuse crate::util::Id; 2219625d8cSopenharmony_ciuse crate::ArgAction; 2319625d8cSopenharmony_ciuse crate::INTERNAL_ERROR_MSG; 2419625d8cSopenharmony_ci 2519625d8cSopenharmony_cipub(crate) struct Parser<'cmd> { 2619625d8cSopenharmony_ci cmd: &'cmd mut Command, 2719625d8cSopenharmony_ci cur_idx: Cell<usize>, 2819625d8cSopenharmony_ci /// Index of the previous flag subcommand in a group of flags. 2919625d8cSopenharmony_ci flag_subcmd_at: Option<usize>, 3019625d8cSopenharmony_ci /// Counter indicating the number of items to skip 3119625d8cSopenharmony_ci /// when revisiting the group of flags which includes the flag subcommand. 3219625d8cSopenharmony_ci flag_subcmd_skip: usize, 3319625d8cSopenharmony_ci} 3419625d8cSopenharmony_ci 3519625d8cSopenharmony_ci// Initializing Methods 3619625d8cSopenharmony_ciimpl<'cmd> Parser<'cmd> { 3719625d8cSopenharmony_ci pub(crate) fn new(cmd: &'cmd mut Command) -> Self { 3819625d8cSopenharmony_ci Parser { 3919625d8cSopenharmony_ci cmd, 4019625d8cSopenharmony_ci cur_idx: Cell::new(0), 4119625d8cSopenharmony_ci flag_subcmd_at: None, 4219625d8cSopenharmony_ci flag_subcmd_skip: 0, 4319625d8cSopenharmony_ci } 4419625d8cSopenharmony_ci } 4519625d8cSopenharmony_ci} 4619625d8cSopenharmony_ci 4719625d8cSopenharmony_ci// Parsing Methods 4819625d8cSopenharmony_ciimpl<'cmd> Parser<'cmd> { 4919625d8cSopenharmony_ci // The actual parsing function 5019625d8cSopenharmony_ci #[allow(clippy::cognitive_complexity)] 5119625d8cSopenharmony_ci pub(crate) fn get_matches_with( 5219625d8cSopenharmony_ci &mut self, 5319625d8cSopenharmony_ci matcher: &mut ArgMatcher, 5419625d8cSopenharmony_ci raw_args: &mut clap_lex::RawArgs, 5519625d8cSopenharmony_ci mut args_cursor: clap_lex::ArgCursor, 5619625d8cSopenharmony_ci ) -> ClapResult<()> { 5719625d8cSopenharmony_ci debug!("Parser::get_matches_with"); 5819625d8cSopenharmony_ci // Verify all positional assertions pass 5919625d8cSopenharmony_ci 6019625d8cSopenharmony_ci let mut subcmd_name: Option<String> = None; 6119625d8cSopenharmony_ci let mut keep_state = false; 6219625d8cSopenharmony_ci let mut parse_state = ParseState::ValuesDone; 6319625d8cSopenharmony_ci let mut pos_counter = 1; 6419625d8cSopenharmony_ci 6519625d8cSopenharmony_ci // Already met any valid arg(then we shouldn't expect subcommands after it). 6619625d8cSopenharmony_ci let mut valid_arg_found = false; 6719625d8cSopenharmony_ci // If the user already passed '--'. Meaning only positional args follow. 6819625d8cSopenharmony_ci let mut trailing_values = false; 6919625d8cSopenharmony_ci 7019625d8cSopenharmony_ci // Count of positional args 7119625d8cSopenharmony_ci let positional_count = self 7219625d8cSopenharmony_ci .cmd 7319625d8cSopenharmony_ci .get_keymap() 7419625d8cSopenharmony_ci .keys() 7519625d8cSopenharmony_ci .filter(|x| x.is_position()) 7619625d8cSopenharmony_ci .count(); 7719625d8cSopenharmony_ci // If any arg sets .last(true) 7819625d8cSopenharmony_ci let contains_last = self.cmd.get_arguments().any(|x| x.is_last_set()); 7919625d8cSopenharmony_ci 8019625d8cSopenharmony_ci while let Some(arg_os) = raw_args.next(&mut args_cursor) { 8119625d8cSopenharmony_ci // Recover the replaced items if any. 8219625d8cSopenharmony_ci if let Some(replaced_items) = arg_os 8319625d8cSopenharmony_ci .to_value() 8419625d8cSopenharmony_ci .ok() 8519625d8cSopenharmony_ci .and_then(|a| self.cmd.get_replacement(a)) 8619625d8cSopenharmony_ci { 8719625d8cSopenharmony_ci debug!( 8819625d8cSopenharmony_ci "Parser::get_matches_with: found replacer: {:?}, target: {:?}", 8919625d8cSopenharmony_ci arg_os, replaced_items 9019625d8cSopenharmony_ci ); 9119625d8cSopenharmony_ci raw_args.insert(&args_cursor, replaced_items); 9219625d8cSopenharmony_ci continue; 9319625d8cSopenharmony_ci } 9419625d8cSopenharmony_ci 9519625d8cSopenharmony_ci debug!( 9619625d8cSopenharmony_ci "Parser::get_matches_with: Begin parsing '{:?}' ({:?})", 9719625d8cSopenharmony_ci arg_os.to_value_os(), 9819625d8cSopenharmony_ci arg_os.to_value_os().as_raw_bytes() 9919625d8cSopenharmony_ci ); 10019625d8cSopenharmony_ci 10119625d8cSopenharmony_ci // Has the user already passed '--'? Meaning only positional args follow 10219625d8cSopenharmony_ci if !trailing_values { 10319625d8cSopenharmony_ci if self.cmd.is_subcommand_precedence_over_arg_set() 10419625d8cSopenharmony_ci || !matches!(parse_state, ParseState::Opt(_) | ParseState::Pos(_)) 10519625d8cSopenharmony_ci { 10619625d8cSopenharmony_ci // Does the arg match a subcommand name, or any of its aliases (if defined) 10719625d8cSopenharmony_ci let sc_name = self.possible_subcommand(arg_os.to_value(), valid_arg_found); 10819625d8cSopenharmony_ci debug!("Parser::get_matches_with: sc={:?}", sc_name); 10919625d8cSopenharmony_ci if let Some(sc_name) = sc_name { 11019625d8cSopenharmony_ci if sc_name == "help" && !self.cmd.is_disable_help_subcommand_set() { 11119625d8cSopenharmony_ci ok!(self.parse_help_subcommand(raw_args.remaining(&mut args_cursor))); 11219625d8cSopenharmony_ci unreachable!("`parse_help_subcommand` always errors"); 11319625d8cSopenharmony_ci } else { 11419625d8cSopenharmony_ci subcmd_name = Some(sc_name.to_owned()); 11519625d8cSopenharmony_ci } 11619625d8cSopenharmony_ci break; 11719625d8cSopenharmony_ci } 11819625d8cSopenharmony_ci } 11919625d8cSopenharmony_ci 12019625d8cSopenharmony_ci if arg_os.is_escape() { 12119625d8cSopenharmony_ci if matches!(&parse_state, ParseState::Opt(opt) | ParseState::Pos(opt) if 12219625d8cSopenharmony_ci self.cmd[opt].is_allow_hyphen_values_set()) 12319625d8cSopenharmony_ci { 12419625d8cSopenharmony_ci // ParseResult::MaybeHyphenValue, do nothing 12519625d8cSopenharmony_ci } else { 12619625d8cSopenharmony_ci debug!("Parser::get_matches_with: setting TrailingVals=true"); 12719625d8cSopenharmony_ci trailing_values = true; 12819625d8cSopenharmony_ci matcher.start_trailing(); 12919625d8cSopenharmony_ci continue; 13019625d8cSopenharmony_ci } 13119625d8cSopenharmony_ci } else if let Some((long_arg, long_value)) = arg_os.to_long() { 13219625d8cSopenharmony_ci let parse_result = ok!(self.parse_long_arg( 13319625d8cSopenharmony_ci matcher, 13419625d8cSopenharmony_ci long_arg, 13519625d8cSopenharmony_ci long_value, 13619625d8cSopenharmony_ci &parse_state, 13719625d8cSopenharmony_ci pos_counter, 13819625d8cSopenharmony_ci &mut valid_arg_found, 13919625d8cSopenharmony_ci )); 14019625d8cSopenharmony_ci debug!( 14119625d8cSopenharmony_ci "Parser::get_matches_with: After parse_long_arg {:?}", 14219625d8cSopenharmony_ci parse_result 14319625d8cSopenharmony_ci ); 14419625d8cSopenharmony_ci match parse_result { 14519625d8cSopenharmony_ci ParseResult::NoArg => { 14619625d8cSopenharmony_ci unreachable!("`to_long` always has the flag specified") 14719625d8cSopenharmony_ci } 14819625d8cSopenharmony_ci ParseResult::ValuesDone => { 14919625d8cSopenharmony_ci parse_state = ParseState::ValuesDone; 15019625d8cSopenharmony_ci continue; 15119625d8cSopenharmony_ci } 15219625d8cSopenharmony_ci ParseResult::Opt(id) => { 15319625d8cSopenharmony_ci parse_state = ParseState::Opt(id); 15419625d8cSopenharmony_ci continue; 15519625d8cSopenharmony_ci } 15619625d8cSopenharmony_ci ParseResult::FlagSubCommand(name) => { 15719625d8cSopenharmony_ci debug!( 15819625d8cSopenharmony_ci "Parser::get_matches_with: FlagSubCommand found in long arg {:?}", 15919625d8cSopenharmony_ci &name 16019625d8cSopenharmony_ci ); 16119625d8cSopenharmony_ci subcmd_name = Some(name); 16219625d8cSopenharmony_ci break; 16319625d8cSopenharmony_ci } 16419625d8cSopenharmony_ci ParseResult::EqualsNotProvided { arg } => { 16519625d8cSopenharmony_ci let _ = self.resolve_pending(matcher); 16619625d8cSopenharmony_ci return Err(ClapError::no_equals( 16719625d8cSopenharmony_ci self.cmd, 16819625d8cSopenharmony_ci arg, 16919625d8cSopenharmony_ci Usage::new(self.cmd).create_usage_with_title(&[]), 17019625d8cSopenharmony_ci )); 17119625d8cSopenharmony_ci } 17219625d8cSopenharmony_ci ParseResult::NoMatchingArg { arg } => { 17319625d8cSopenharmony_ci let _ = self.resolve_pending(matcher); 17419625d8cSopenharmony_ci let remaining_args: Vec<_> = 17519625d8cSopenharmony_ci raw_args.remaining(&mut args_cursor).collect(); 17619625d8cSopenharmony_ci return Err(self.did_you_mean_error( 17719625d8cSopenharmony_ci &arg, 17819625d8cSopenharmony_ci matcher, 17919625d8cSopenharmony_ci &remaining_args, 18019625d8cSopenharmony_ci trailing_values, 18119625d8cSopenharmony_ci )); 18219625d8cSopenharmony_ci } 18319625d8cSopenharmony_ci ParseResult::UnneededAttachedValue { rest, used, arg } => { 18419625d8cSopenharmony_ci let _ = self.resolve_pending(matcher); 18519625d8cSopenharmony_ci return Err(ClapError::too_many_values( 18619625d8cSopenharmony_ci self.cmd, 18719625d8cSopenharmony_ci rest, 18819625d8cSopenharmony_ci arg, 18919625d8cSopenharmony_ci Usage::new(self.cmd).create_usage_with_title(&used), 19019625d8cSopenharmony_ci )); 19119625d8cSopenharmony_ci } 19219625d8cSopenharmony_ci ParseResult::MaybeHyphenValue => { 19319625d8cSopenharmony_ci // Maybe a hyphen value, do nothing. 19419625d8cSopenharmony_ci } 19519625d8cSopenharmony_ci ParseResult::AttachedValueNotConsumed => { 19619625d8cSopenharmony_ci unreachable!() 19719625d8cSopenharmony_ci } 19819625d8cSopenharmony_ci } 19919625d8cSopenharmony_ci } else if let Some(short_arg) = arg_os.to_short() { 20019625d8cSopenharmony_ci // Arg looks like a short flag, and not a possible number 20119625d8cSopenharmony_ci 20219625d8cSopenharmony_ci // Try to parse short args like normal, if allow_hyphen_values or 20319625d8cSopenharmony_ci // AllowNegativeNumbers is set, parse_short_arg will *not* throw 20419625d8cSopenharmony_ci // an error, and instead return Ok(None) 20519625d8cSopenharmony_ci let parse_result = ok!(self.parse_short_arg( 20619625d8cSopenharmony_ci matcher, 20719625d8cSopenharmony_ci short_arg, 20819625d8cSopenharmony_ci &parse_state, 20919625d8cSopenharmony_ci pos_counter, 21019625d8cSopenharmony_ci &mut valid_arg_found, 21119625d8cSopenharmony_ci )); 21219625d8cSopenharmony_ci // If it's None, we then check if one of those two AppSettings was set 21319625d8cSopenharmony_ci debug!( 21419625d8cSopenharmony_ci "Parser::get_matches_with: After parse_short_arg {:?}", 21519625d8cSopenharmony_ci parse_result 21619625d8cSopenharmony_ci ); 21719625d8cSopenharmony_ci match parse_result { 21819625d8cSopenharmony_ci ParseResult::NoArg => { 21919625d8cSopenharmony_ci // Is a single dash `-`, try positional. 22019625d8cSopenharmony_ci } 22119625d8cSopenharmony_ci ParseResult::ValuesDone => { 22219625d8cSopenharmony_ci parse_state = ParseState::ValuesDone; 22319625d8cSopenharmony_ci continue; 22419625d8cSopenharmony_ci } 22519625d8cSopenharmony_ci ParseResult::Opt(id) => { 22619625d8cSopenharmony_ci parse_state = ParseState::Opt(id); 22719625d8cSopenharmony_ci continue; 22819625d8cSopenharmony_ci } 22919625d8cSopenharmony_ci ParseResult::FlagSubCommand(name) => { 23019625d8cSopenharmony_ci // If there are more short flags to be processed, we should keep the state, and later 23119625d8cSopenharmony_ci // revisit the current group of short flags skipping the subcommand. 23219625d8cSopenharmony_ci keep_state = self 23319625d8cSopenharmony_ci .flag_subcmd_at 23419625d8cSopenharmony_ci .map(|at| { 23519625d8cSopenharmony_ci raw_args 23619625d8cSopenharmony_ci .seek(&mut args_cursor, clap_lex::SeekFrom::Current(-1)); 23719625d8cSopenharmony_ci // Since we are now saving the current state, the number of flags to skip during state recovery should 23819625d8cSopenharmony_ci // be the current index (`cur_idx`) minus ONE UNIT TO THE LEFT of the starting position. 23919625d8cSopenharmony_ci self.flag_subcmd_skip = self.cur_idx.get() - at + 1; 24019625d8cSopenharmony_ci }) 24119625d8cSopenharmony_ci .is_some(); 24219625d8cSopenharmony_ci 24319625d8cSopenharmony_ci debug!( 24419625d8cSopenharmony_ci "Parser::get_matches_with:FlagSubCommandShort: subcmd_name={}, keep_state={}, flag_subcmd_skip={}", 24519625d8cSopenharmony_ci name, 24619625d8cSopenharmony_ci keep_state, 24719625d8cSopenharmony_ci self.flag_subcmd_skip 24819625d8cSopenharmony_ci ); 24919625d8cSopenharmony_ci 25019625d8cSopenharmony_ci subcmd_name = Some(name); 25119625d8cSopenharmony_ci break; 25219625d8cSopenharmony_ci } 25319625d8cSopenharmony_ci ParseResult::EqualsNotProvided { arg } => { 25419625d8cSopenharmony_ci let _ = self.resolve_pending(matcher); 25519625d8cSopenharmony_ci return Err(ClapError::no_equals( 25619625d8cSopenharmony_ci self.cmd, 25719625d8cSopenharmony_ci arg, 25819625d8cSopenharmony_ci Usage::new(self.cmd).create_usage_with_title(&[]), 25919625d8cSopenharmony_ci )); 26019625d8cSopenharmony_ci } 26119625d8cSopenharmony_ci ParseResult::NoMatchingArg { arg } => { 26219625d8cSopenharmony_ci let _ = self.resolve_pending(matcher); 26319625d8cSopenharmony_ci // We already know it looks like a flag 26419625d8cSopenharmony_ci let suggested_trailing_arg = 26519625d8cSopenharmony_ci !trailing_values && self.cmd.has_positionals(); 26619625d8cSopenharmony_ci return Err(ClapError::unknown_argument( 26719625d8cSopenharmony_ci self.cmd, 26819625d8cSopenharmony_ci arg, 26919625d8cSopenharmony_ci None, 27019625d8cSopenharmony_ci suggested_trailing_arg, 27119625d8cSopenharmony_ci Usage::new(self.cmd).create_usage_with_title(&[]), 27219625d8cSopenharmony_ci )); 27319625d8cSopenharmony_ci } 27419625d8cSopenharmony_ci ParseResult::MaybeHyphenValue => { 27519625d8cSopenharmony_ci // Maybe a hyphen value, do nothing. 27619625d8cSopenharmony_ci } 27719625d8cSopenharmony_ci ParseResult::UnneededAttachedValue { .. } 27819625d8cSopenharmony_ci | ParseResult::AttachedValueNotConsumed => unreachable!(), 27919625d8cSopenharmony_ci } 28019625d8cSopenharmony_ci } 28119625d8cSopenharmony_ci 28219625d8cSopenharmony_ci if let ParseState::Opt(id) = &parse_state { 28319625d8cSopenharmony_ci // Assume this is a value of a previous arg. 28419625d8cSopenharmony_ci 28519625d8cSopenharmony_ci // get the option so we can check the settings 28619625d8cSopenharmony_ci let arg = &self.cmd[id]; 28719625d8cSopenharmony_ci let parse_result = if let Some(parse_result) = 28819625d8cSopenharmony_ci self.check_terminator(arg, arg_os.to_value_os()) 28919625d8cSopenharmony_ci { 29019625d8cSopenharmony_ci parse_result 29119625d8cSopenharmony_ci } else { 29219625d8cSopenharmony_ci let trailing_values = false; 29319625d8cSopenharmony_ci let arg_values = matcher.pending_values_mut(id, None, trailing_values); 29419625d8cSopenharmony_ci arg_values.push(arg_os.to_value_os().to_os_str().into_owned()); 29519625d8cSopenharmony_ci if matcher.needs_more_vals(arg) { 29619625d8cSopenharmony_ci ParseResult::Opt(arg.get_id().clone()) 29719625d8cSopenharmony_ci } else { 29819625d8cSopenharmony_ci ParseResult::ValuesDone 29919625d8cSopenharmony_ci } 30019625d8cSopenharmony_ci }; 30119625d8cSopenharmony_ci parse_state = match parse_result { 30219625d8cSopenharmony_ci ParseResult::Opt(id) => ParseState::Opt(id), 30319625d8cSopenharmony_ci ParseResult::ValuesDone => ParseState::ValuesDone, 30419625d8cSopenharmony_ci _ => unreachable!(), 30519625d8cSopenharmony_ci }; 30619625d8cSopenharmony_ci // get the next value from the iterator 30719625d8cSopenharmony_ci continue; 30819625d8cSopenharmony_ci } 30919625d8cSopenharmony_ci } 31019625d8cSopenharmony_ci 31119625d8cSopenharmony_ci // Correct pos_counter. 31219625d8cSopenharmony_ci pos_counter = { 31319625d8cSopenharmony_ci let is_second_to_last = pos_counter + 1 == positional_count; 31419625d8cSopenharmony_ci 31519625d8cSopenharmony_ci // The last positional argument, or second to last positional 31619625d8cSopenharmony_ci // argument may be set to .multiple_values(true) or `.multiple_occurrences(true)` 31719625d8cSopenharmony_ci let low_index_mults = is_second_to_last 31819625d8cSopenharmony_ci && self.cmd.get_positionals().any(|a| { 31919625d8cSopenharmony_ci a.is_multiple() && (positional_count != a.get_index().unwrap_or(0)) 32019625d8cSopenharmony_ci }) 32119625d8cSopenharmony_ci && self 32219625d8cSopenharmony_ci .cmd 32319625d8cSopenharmony_ci .get_positionals() 32419625d8cSopenharmony_ci .last() 32519625d8cSopenharmony_ci .map_or(false, |p_name| !p_name.is_last_set()); 32619625d8cSopenharmony_ci 32719625d8cSopenharmony_ci let missing_pos = self.cmd.is_allow_missing_positional_set() 32819625d8cSopenharmony_ci && is_second_to_last 32919625d8cSopenharmony_ci && !trailing_values; 33019625d8cSopenharmony_ci 33119625d8cSopenharmony_ci debug!( 33219625d8cSopenharmony_ci "Parser::get_matches_with: Positional counter...{}", 33319625d8cSopenharmony_ci pos_counter 33419625d8cSopenharmony_ci ); 33519625d8cSopenharmony_ci debug!( 33619625d8cSopenharmony_ci "Parser::get_matches_with: Low index multiples...{:?}", 33719625d8cSopenharmony_ci low_index_mults 33819625d8cSopenharmony_ci ); 33919625d8cSopenharmony_ci 34019625d8cSopenharmony_ci if low_index_mults || missing_pos { 34119625d8cSopenharmony_ci let skip_current = if let Some(n) = raw_args.peek(&args_cursor) { 34219625d8cSopenharmony_ci if let Some(arg) = self 34319625d8cSopenharmony_ci .cmd 34419625d8cSopenharmony_ci .get_positionals() 34519625d8cSopenharmony_ci .find(|a| a.get_index() == Some(pos_counter)) 34619625d8cSopenharmony_ci { 34719625d8cSopenharmony_ci // If next value looks like a new_arg or it's a 34819625d8cSopenharmony_ci // subcommand, skip positional argument under current 34919625d8cSopenharmony_ci // pos_counter(which means current value cannot be a 35019625d8cSopenharmony_ci // positional argument with a value next to it), assume 35119625d8cSopenharmony_ci // current value matches the next arg. 35219625d8cSopenharmony_ci self.is_new_arg(&n, arg) 35319625d8cSopenharmony_ci || self 35419625d8cSopenharmony_ci .possible_subcommand(n.to_value(), valid_arg_found) 35519625d8cSopenharmony_ci .is_some() 35619625d8cSopenharmony_ci } else { 35719625d8cSopenharmony_ci true 35819625d8cSopenharmony_ci } 35919625d8cSopenharmony_ci } else { 36019625d8cSopenharmony_ci true 36119625d8cSopenharmony_ci }; 36219625d8cSopenharmony_ci 36319625d8cSopenharmony_ci if skip_current { 36419625d8cSopenharmony_ci debug!("Parser::get_matches_with: Bumping the positional counter..."); 36519625d8cSopenharmony_ci pos_counter + 1 36619625d8cSopenharmony_ci } else { 36719625d8cSopenharmony_ci pos_counter 36819625d8cSopenharmony_ci } 36919625d8cSopenharmony_ci } else if trailing_values 37019625d8cSopenharmony_ci && (self.cmd.is_allow_missing_positional_set() || contains_last) 37119625d8cSopenharmony_ci { 37219625d8cSopenharmony_ci // Came to -- and one positional has .last(true) set, so we go immediately 37319625d8cSopenharmony_ci // to the last (highest index) positional 37419625d8cSopenharmony_ci debug!("Parser::get_matches_with: .last(true) and --, setting last pos"); 37519625d8cSopenharmony_ci positional_count 37619625d8cSopenharmony_ci } else { 37719625d8cSopenharmony_ci pos_counter 37819625d8cSopenharmony_ci } 37919625d8cSopenharmony_ci }; 38019625d8cSopenharmony_ci 38119625d8cSopenharmony_ci if let Some(arg) = self.cmd.get_keymap().get(&pos_counter) { 38219625d8cSopenharmony_ci if arg.is_last_set() && !trailing_values { 38319625d8cSopenharmony_ci let _ = self.resolve_pending(matcher); 38419625d8cSopenharmony_ci // Its already considered a positional, we don't need to suggest turning it 38519625d8cSopenharmony_ci // into one 38619625d8cSopenharmony_ci let suggested_trailing_arg = false; 38719625d8cSopenharmony_ci return Err(ClapError::unknown_argument( 38819625d8cSopenharmony_ci self.cmd, 38919625d8cSopenharmony_ci arg_os.display().to_string(), 39019625d8cSopenharmony_ci None, 39119625d8cSopenharmony_ci suggested_trailing_arg, 39219625d8cSopenharmony_ci Usage::new(self.cmd).create_usage_with_title(&[]), 39319625d8cSopenharmony_ci )); 39419625d8cSopenharmony_ci } 39519625d8cSopenharmony_ci 39619625d8cSopenharmony_ci if arg.is_trailing_var_arg_set() { 39719625d8cSopenharmony_ci trailing_values = true; 39819625d8cSopenharmony_ci } 39919625d8cSopenharmony_ci 40019625d8cSopenharmony_ci if matcher.pending_arg_id() != Some(arg.get_id()) || !arg.is_multiple_values_set() { 40119625d8cSopenharmony_ci ok!(self.resolve_pending(matcher)); 40219625d8cSopenharmony_ci } 40319625d8cSopenharmony_ci if let Some(_parse_result) = self.check_terminator(arg, arg_os.to_value_os()) { 40419625d8cSopenharmony_ci debug!( 40519625d8cSopenharmony_ci "Parser::get_matches_with: ignoring terminator result {:?}", 40619625d8cSopenharmony_ci _parse_result 40719625d8cSopenharmony_ci ); 40819625d8cSopenharmony_ci } else { 40919625d8cSopenharmony_ci let arg_values = matcher.pending_values_mut( 41019625d8cSopenharmony_ci arg.get_id(), 41119625d8cSopenharmony_ci Some(Identifier::Index), 41219625d8cSopenharmony_ci trailing_values, 41319625d8cSopenharmony_ci ); 41419625d8cSopenharmony_ci arg_values.push(arg_os.to_value_os().to_os_str().into_owned()); 41519625d8cSopenharmony_ci } 41619625d8cSopenharmony_ci 41719625d8cSopenharmony_ci // Only increment the positional counter if it doesn't allow multiples 41819625d8cSopenharmony_ci if !arg.is_multiple() { 41919625d8cSopenharmony_ci pos_counter += 1; 42019625d8cSopenharmony_ci parse_state = ParseState::ValuesDone; 42119625d8cSopenharmony_ci } else { 42219625d8cSopenharmony_ci parse_state = ParseState::Pos(arg.get_id().clone()); 42319625d8cSopenharmony_ci } 42419625d8cSopenharmony_ci valid_arg_found = true; 42519625d8cSopenharmony_ci } else if let Some(external_parser) = 42619625d8cSopenharmony_ci self.cmd.get_external_subcommand_value_parser().cloned() 42719625d8cSopenharmony_ci { 42819625d8cSopenharmony_ci // Get external subcommand name 42919625d8cSopenharmony_ci let sc_name = match arg_os.to_value() { 43019625d8cSopenharmony_ci Ok(s) => s.to_owned(), 43119625d8cSopenharmony_ci Err(_) => { 43219625d8cSopenharmony_ci let _ = self.resolve_pending(matcher); 43319625d8cSopenharmony_ci return Err(ClapError::invalid_utf8( 43419625d8cSopenharmony_ci self.cmd, 43519625d8cSopenharmony_ci Usage::new(self.cmd).create_usage_with_title(&[]), 43619625d8cSopenharmony_ci )); 43719625d8cSopenharmony_ci } 43819625d8cSopenharmony_ci }; 43919625d8cSopenharmony_ci 44019625d8cSopenharmony_ci // Collect the external subcommand args 44119625d8cSopenharmony_ci let mut sc_m = ArgMatcher::new(self.cmd); 44219625d8cSopenharmony_ci sc_m.start_occurrence_of_external(self.cmd); 44319625d8cSopenharmony_ci 44419625d8cSopenharmony_ci for raw_val in raw_args.remaining(&mut args_cursor) { 44519625d8cSopenharmony_ci let val = ok!(external_parser.parse_ref(self.cmd, None, raw_val)); 44619625d8cSopenharmony_ci let external_id = Id::from_static_ref(Id::EXTERNAL); 44719625d8cSopenharmony_ci sc_m.add_val_to(&external_id, val, raw_val.to_os_string()); 44819625d8cSopenharmony_ci } 44919625d8cSopenharmony_ci 45019625d8cSopenharmony_ci matcher.subcommand(SubCommand { 45119625d8cSopenharmony_ci name: sc_name, 45219625d8cSopenharmony_ci matches: sc_m.into_inner(), 45319625d8cSopenharmony_ci }); 45419625d8cSopenharmony_ci 45519625d8cSopenharmony_ci ok!(self.resolve_pending(matcher)); 45619625d8cSopenharmony_ci #[cfg(feature = "env")] 45719625d8cSopenharmony_ci ok!(self.add_env(matcher)); 45819625d8cSopenharmony_ci ok!(self.add_defaults(matcher)); 45919625d8cSopenharmony_ci return Validator::new(self.cmd).validate(parse_state, matcher); 46019625d8cSopenharmony_ci } else { 46119625d8cSopenharmony_ci // Start error processing 46219625d8cSopenharmony_ci let _ = self.resolve_pending(matcher); 46319625d8cSopenharmony_ci return Err(self.match_arg_error(&arg_os, valid_arg_found, trailing_values)); 46419625d8cSopenharmony_ci } 46519625d8cSopenharmony_ci } 46619625d8cSopenharmony_ci 46719625d8cSopenharmony_ci if let Some(ref pos_sc_name) = subcmd_name { 46819625d8cSopenharmony_ci let sc_name = self 46919625d8cSopenharmony_ci .cmd 47019625d8cSopenharmony_ci .find_subcommand(pos_sc_name) 47119625d8cSopenharmony_ci .expect(INTERNAL_ERROR_MSG) 47219625d8cSopenharmony_ci .get_name() 47319625d8cSopenharmony_ci .to_owned(); 47419625d8cSopenharmony_ci ok!(self.parse_subcommand(&sc_name, matcher, raw_args, args_cursor, keep_state)); 47519625d8cSopenharmony_ci } 47619625d8cSopenharmony_ci 47719625d8cSopenharmony_ci ok!(self.resolve_pending(matcher)); 47819625d8cSopenharmony_ci #[cfg(feature = "env")] 47919625d8cSopenharmony_ci ok!(self.add_env(matcher)); 48019625d8cSopenharmony_ci ok!(self.add_defaults(matcher)); 48119625d8cSopenharmony_ci Validator::new(self.cmd).validate(parse_state, matcher) 48219625d8cSopenharmony_ci } 48319625d8cSopenharmony_ci 48419625d8cSopenharmony_ci fn match_arg_error( 48519625d8cSopenharmony_ci &self, 48619625d8cSopenharmony_ci arg_os: &clap_lex::ParsedArg<'_>, 48719625d8cSopenharmony_ci valid_arg_found: bool, 48819625d8cSopenharmony_ci trailing_values: bool, 48919625d8cSopenharmony_ci ) -> ClapError { 49019625d8cSopenharmony_ci // If argument follows a `--` 49119625d8cSopenharmony_ci if trailing_values { 49219625d8cSopenharmony_ci // If the arg matches a subcommand name, or any of its aliases (if defined) 49319625d8cSopenharmony_ci if self 49419625d8cSopenharmony_ci .possible_subcommand(arg_os.to_value(), valid_arg_found) 49519625d8cSopenharmony_ci .is_some() 49619625d8cSopenharmony_ci { 49719625d8cSopenharmony_ci return ClapError::unnecessary_double_dash( 49819625d8cSopenharmony_ci self.cmd, 49919625d8cSopenharmony_ci arg_os.display().to_string(), 50019625d8cSopenharmony_ci Usage::new(self.cmd).create_usage_with_title(&[]), 50119625d8cSopenharmony_ci ); 50219625d8cSopenharmony_ci } 50319625d8cSopenharmony_ci } 50419625d8cSopenharmony_ci 50519625d8cSopenharmony_ci if !(self.cmd.is_args_conflicts_with_subcommands_set() && valid_arg_found) { 50619625d8cSopenharmony_ci let candidates = suggestions::did_you_mean( 50719625d8cSopenharmony_ci &arg_os.display().to_string(), 50819625d8cSopenharmony_ci self.cmd.all_subcommand_names(), 50919625d8cSopenharmony_ci ); 51019625d8cSopenharmony_ci // If the argument looks like a subcommand. 51119625d8cSopenharmony_ci if !candidates.is_empty() { 51219625d8cSopenharmony_ci return ClapError::invalid_subcommand( 51319625d8cSopenharmony_ci self.cmd, 51419625d8cSopenharmony_ci arg_os.display().to_string(), 51519625d8cSopenharmony_ci candidates, 51619625d8cSopenharmony_ci self.cmd 51719625d8cSopenharmony_ci .get_bin_name() 51819625d8cSopenharmony_ci .unwrap_or_else(|| self.cmd.get_name()) 51919625d8cSopenharmony_ci .to_owned(), 52019625d8cSopenharmony_ci Usage::new(self.cmd).create_usage_with_title(&[]), 52119625d8cSopenharmony_ci ); 52219625d8cSopenharmony_ci } 52319625d8cSopenharmony_ci 52419625d8cSopenharmony_ci // If the argument must be a subcommand. 52519625d8cSopenharmony_ci if self.cmd.has_subcommands() 52619625d8cSopenharmony_ci && (!self.cmd.has_positionals() || self.cmd.is_infer_subcommands_set()) 52719625d8cSopenharmony_ci { 52819625d8cSopenharmony_ci return ClapError::unrecognized_subcommand( 52919625d8cSopenharmony_ci self.cmd, 53019625d8cSopenharmony_ci arg_os.display().to_string(), 53119625d8cSopenharmony_ci Usage::new(self.cmd).create_usage_with_title(&[]), 53219625d8cSopenharmony_ci ); 53319625d8cSopenharmony_ci } 53419625d8cSopenharmony_ci } 53519625d8cSopenharmony_ci 53619625d8cSopenharmony_ci let suggested_trailing_arg = !trailing_values 53719625d8cSopenharmony_ci && self.cmd.has_positionals() 53819625d8cSopenharmony_ci && (arg_os.is_long() || arg_os.is_short()); 53919625d8cSopenharmony_ci ClapError::unknown_argument( 54019625d8cSopenharmony_ci self.cmd, 54119625d8cSopenharmony_ci arg_os.display().to_string(), 54219625d8cSopenharmony_ci None, 54319625d8cSopenharmony_ci suggested_trailing_arg, 54419625d8cSopenharmony_ci Usage::new(self.cmd).create_usage_with_title(&[]), 54519625d8cSopenharmony_ci ) 54619625d8cSopenharmony_ci } 54719625d8cSopenharmony_ci 54819625d8cSopenharmony_ci // Checks if the arg matches a subcommand name, or any of its aliases (if defined) 54919625d8cSopenharmony_ci fn possible_subcommand( 55019625d8cSopenharmony_ci &self, 55119625d8cSopenharmony_ci arg: Result<&str, &RawOsStr>, 55219625d8cSopenharmony_ci valid_arg_found: bool, 55319625d8cSopenharmony_ci ) -> Option<&str> { 55419625d8cSopenharmony_ci debug!("Parser::possible_subcommand: arg={:?}", arg); 55519625d8cSopenharmony_ci let arg = some!(arg.ok()); 55619625d8cSopenharmony_ci 55719625d8cSopenharmony_ci if !(self.cmd.is_args_conflicts_with_subcommands_set() && valid_arg_found) { 55819625d8cSopenharmony_ci if self.cmd.is_infer_subcommands_set() { 55919625d8cSopenharmony_ci // For subcommand `test`, we accepts it's prefix: `t`, `te`, 56019625d8cSopenharmony_ci // `tes` and `test`. 56119625d8cSopenharmony_ci let v = self 56219625d8cSopenharmony_ci .cmd 56319625d8cSopenharmony_ci .all_subcommand_names() 56419625d8cSopenharmony_ci .filter(|s| s.starts_with(arg)) 56519625d8cSopenharmony_ci .collect::<Vec<_>>(); 56619625d8cSopenharmony_ci 56719625d8cSopenharmony_ci if v.len() == 1 { 56819625d8cSopenharmony_ci return Some(v[0]); 56919625d8cSopenharmony_ci } 57019625d8cSopenharmony_ci 57119625d8cSopenharmony_ci // If there is any ambiguity, fallback to non-infer subcommand 57219625d8cSopenharmony_ci // search. 57319625d8cSopenharmony_ci } 57419625d8cSopenharmony_ci if let Some(sc) = self.cmd.find_subcommand(arg) { 57519625d8cSopenharmony_ci return Some(sc.get_name()); 57619625d8cSopenharmony_ci } 57719625d8cSopenharmony_ci } 57819625d8cSopenharmony_ci None 57919625d8cSopenharmony_ci } 58019625d8cSopenharmony_ci 58119625d8cSopenharmony_ci // Checks if the arg matches a long flag subcommand name, or any of its aliases (if defined) 58219625d8cSopenharmony_ci fn possible_long_flag_subcommand(&self, arg: &str) -> Option<&str> { 58319625d8cSopenharmony_ci debug!("Parser::possible_long_flag_subcommand: arg={:?}", arg); 58419625d8cSopenharmony_ci if self.cmd.is_infer_subcommands_set() { 58519625d8cSopenharmony_ci let options = self 58619625d8cSopenharmony_ci .cmd 58719625d8cSopenharmony_ci .get_subcommands() 58819625d8cSopenharmony_ci .fold(Vec::new(), |mut options, sc| { 58919625d8cSopenharmony_ci if let Some(long) = sc.get_long_flag() { 59019625d8cSopenharmony_ci if long.starts_with(arg) { 59119625d8cSopenharmony_ci options.push(long); 59219625d8cSopenharmony_ci } 59319625d8cSopenharmony_ci options.extend(sc.get_all_aliases().filter(|alias| alias.starts_with(arg))) 59419625d8cSopenharmony_ci } 59519625d8cSopenharmony_ci options 59619625d8cSopenharmony_ci }); 59719625d8cSopenharmony_ci if options.len() == 1 { 59819625d8cSopenharmony_ci return Some(options[0]); 59919625d8cSopenharmony_ci } 60019625d8cSopenharmony_ci 60119625d8cSopenharmony_ci for sc in options { 60219625d8cSopenharmony_ci if sc == arg { 60319625d8cSopenharmony_ci return Some(sc); 60419625d8cSopenharmony_ci } 60519625d8cSopenharmony_ci } 60619625d8cSopenharmony_ci } else if let Some(sc_name) = self.cmd.find_long_subcmd(arg) { 60719625d8cSopenharmony_ci return Some(sc_name); 60819625d8cSopenharmony_ci } 60919625d8cSopenharmony_ci None 61019625d8cSopenharmony_ci } 61119625d8cSopenharmony_ci 61219625d8cSopenharmony_ci fn parse_help_subcommand( 61319625d8cSopenharmony_ci &self, 61419625d8cSopenharmony_ci cmds: impl Iterator<Item = &'cmd OsStr>, 61519625d8cSopenharmony_ci ) -> ClapResult<std::convert::Infallible> { 61619625d8cSopenharmony_ci debug!("Parser::parse_help_subcommand"); 61719625d8cSopenharmony_ci 61819625d8cSopenharmony_ci let mut cmd = self.cmd.clone(); 61919625d8cSopenharmony_ci let sc = { 62019625d8cSopenharmony_ci let mut sc = &mut cmd; 62119625d8cSopenharmony_ci 62219625d8cSopenharmony_ci for cmd in cmds { 62319625d8cSopenharmony_ci sc = if let Some(sc_name) = 62419625d8cSopenharmony_ci sc.find_subcommand(cmd).map(|sc| sc.get_name().to_owned()) 62519625d8cSopenharmony_ci { 62619625d8cSopenharmony_ci sc._build_subcommand(&sc_name).unwrap() 62719625d8cSopenharmony_ci } else { 62819625d8cSopenharmony_ci return Err(ClapError::unrecognized_subcommand( 62919625d8cSopenharmony_ci sc, 63019625d8cSopenharmony_ci cmd.to_string_lossy().into_owned(), 63119625d8cSopenharmony_ci Usage::new(sc).create_usage_with_title(&[]), 63219625d8cSopenharmony_ci )); 63319625d8cSopenharmony_ci }; 63419625d8cSopenharmony_ci } 63519625d8cSopenharmony_ci 63619625d8cSopenharmony_ci sc 63719625d8cSopenharmony_ci }; 63819625d8cSopenharmony_ci let parser = Parser::new(sc); 63919625d8cSopenharmony_ci 64019625d8cSopenharmony_ci Err(parser.help_err(true)) 64119625d8cSopenharmony_ci } 64219625d8cSopenharmony_ci 64319625d8cSopenharmony_ci fn is_new_arg(&self, next: &clap_lex::ParsedArg<'_>, current_positional: &Arg) -> bool { 64419625d8cSopenharmony_ci #![allow(clippy::needless_bool)] // Prefer consistent if/else-if ladder 64519625d8cSopenharmony_ci 64619625d8cSopenharmony_ci debug!( 64719625d8cSopenharmony_ci "Parser::is_new_arg: {:?}:{}", 64819625d8cSopenharmony_ci next.to_value_os(), 64919625d8cSopenharmony_ci current_positional.get_id() 65019625d8cSopenharmony_ci ); 65119625d8cSopenharmony_ci 65219625d8cSopenharmony_ci if self.cmd[current_positional.get_id()].is_allow_hyphen_values_set() 65319625d8cSopenharmony_ci || (self.cmd[current_positional.get_id()].is_allow_negative_numbers_set() 65419625d8cSopenharmony_ci && next.is_number()) 65519625d8cSopenharmony_ci { 65619625d8cSopenharmony_ci // If allow hyphen, this isn't a new arg. 65719625d8cSopenharmony_ci debug!("Parser::is_new_arg: Allow hyphen"); 65819625d8cSopenharmony_ci false 65919625d8cSopenharmony_ci } else if next.is_long() { 66019625d8cSopenharmony_ci // If this is a long flag, this is a new arg. 66119625d8cSopenharmony_ci debug!("Parser::is_new_arg: --<something> found"); 66219625d8cSopenharmony_ci true 66319625d8cSopenharmony_ci } else if next.is_short() { 66419625d8cSopenharmony_ci // If this is a short flag, this is a new arg. But a singe '-' by 66519625d8cSopenharmony_ci // itself is a value and typically means "stdin" on unix systems. 66619625d8cSopenharmony_ci debug!("Parser::is_new_arg: -<something> found"); 66719625d8cSopenharmony_ci true 66819625d8cSopenharmony_ci } else { 66919625d8cSopenharmony_ci // Nothing special, this is a value. 67019625d8cSopenharmony_ci debug!("Parser::is_new_arg: value"); 67119625d8cSopenharmony_ci false 67219625d8cSopenharmony_ci } 67319625d8cSopenharmony_ci } 67419625d8cSopenharmony_ci 67519625d8cSopenharmony_ci fn parse_subcommand( 67619625d8cSopenharmony_ci &mut self, 67719625d8cSopenharmony_ci sc_name: &str, 67819625d8cSopenharmony_ci matcher: &mut ArgMatcher, 67919625d8cSopenharmony_ci raw_args: &mut clap_lex::RawArgs, 68019625d8cSopenharmony_ci args_cursor: clap_lex::ArgCursor, 68119625d8cSopenharmony_ci keep_state: bool, 68219625d8cSopenharmony_ci ) -> ClapResult<()> { 68319625d8cSopenharmony_ci debug!("Parser::parse_subcommand"); 68419625d8cSopenharmony_ci 68519625d8cSopenharmony_ci let partial_parsing_enabled = self.cmd.is_ignore_errors_set(); 68619625d8cSopenharmony_ci 68719625d8cSopenharmony_ci if let Some(sc) = self.cmd._build_subcommand(sc_name) { 68819625d8cSopenharmony_ci let mut sc_matcher = ArgMatcher::new(sc); 68919625d8cSopenharmony_ci 69019625d8cSopenharmony_ci debug!( 69119625d8cSopenharmony_ci "Parser::parse_subcommand: About to parse sc={}", 69219625d8cSopenharmony_ci sc.get_name() 69319625d8cSopenharmony_ci ); 69419625d8cSopenharmony_ci 69519625d8cSopenharmony_ci { 69619625d8cSopenharmony_ci let mut p = Parser::new(sc); 69719625d8cSopenharmony_ci // HACK: maintain indexes between parsers 69819625d8cSopenharmony_ci // FlagSubCommand short arg needs to revisit the current short args, but skip the subcommand itself 69919625d8cSopenharmony_ci if keep_state { 70019625d8cSopenharmony_ci p.cur_idx.set(self.cur_idx.get()); 70119625d8cSopenharmony_ci p.flag_subcmd_at = self.flag_subcmd_at; 70219625d8cSopenharmony_ci p.flag_subcmd_skip = self.flag_subcmd_skip; 70319625d8cSopenharmony_ci } 70419625d8cSopenharmony_ci if let Err(error) = p.get_matches_with(&mut sc_matcher, raw_args, args_cursor) { 70519625d8cSopenharmony_ci if partial_parsing_enabled { 70619625d8cSopenharmony_ci debug!( 70719625d8cSopenharmony_ci "Parser::parse_subcommand: ignored error in subcommand {}: {:?}", 70819625d8cSopenharmony_ci sc_name, error 70919625d8cSopenharmony_ci ); 71019625d8cSopenharmony_ci } else { 71119625d8cSopenharmony_ci return Err(error); 71219625d8cSopenharmony_ci } 71319625d8cSopenharmony_ci } 71419625d8cSopenharmony_ci } 71519625d8cSopenharmony_ci matcher.subcommand(SubCommand { 71619625d8cSopenharmony_ci name: sc.get_name().to_owned(), 71719625d8cSopenharmony_ci matches: sc_matcher.into_inner(), 71819625d8cSopenharmony_ci }); 71919625d8cSopenharmony_ci } 72019625d8cSopenharmony_ci Ok(()) 72119625d8cSopenharmony_ci } 72219625d8cSopenharmony_ci 72319625d8cSopenharmony_ci fn parse_long_arg( 72419625d8cSopenharmony_ci &mut self, 72519625d8cSopenharmony_ci matcher: &mut ArgMatcher, 72619625d8cSopenharmony_ci long_arg: Result<&str, &RawOsStr>, 72719625d8cSopenharmony_ci long_value: Option<&RawOsStr>, 72819625d8cSopenharmony_ci parse_state: &ParseState, 72919625d8cSopenharmony_ci pos_counter: usize, 73019625d8cSopenharmony_ci valid_arg_found: &mut bool, 73119625d8cSopenharmony_ci ) -> ClapResult<ParseResult> { 73219625d8cSopenharmony_ci // maybe here lifetime should be 'a 73319625d8cSopenharmony_ci debug!("Parser::parse_long_arg"); 73419625d8cSopenharmony_ci 73519625d8cSopenharmony_ci #[allow(clippy::blocks_in_if_conditions)] 73619625d8cSopenharmony_ci if matches!(parse_state, ParseState::Opt(opt) | ParseState::Pos(opt) if 73719625d8cSopenharmony_ci self.cmd[opt].is_allow_hyphen_values_set()) 73819625d8cSopenharmony_ci { 73919625d8cSopenharmony_ci debug!("Parser::parse_long_arg: prior arg accepts hyphenated values",); 74019625d8cSopenharmony_ci return Ok(ParseResult::MaybeHyphenValue); 74119625d8cSopenharmony_ci } 74219625d8cSopenharmony_ci 74319625d8cSopenharmony_ci debug!("Parser::parse_long_arg: Does it contain '='..."); 74419625d8cSopenharmony_ci let long_arg = match long_arg { 74519625d8cSopenharmony_ci Ok(long_arg) => long_arg, 74619625d8cSopenharmony_ci Err(long_arg) => { 74719625d8cSopenharmony_ci return Ok(ParseResult::NoMatchingArg { 74819625d8cSopenharmony_ci arg: long_arg.to_str_lossy().into_owned(), 74919625d8cSopenharmony_ci }); 75019625d8cSopenharmony_ci } 75119625d8cSopenharmony_ci }; 75219625d8cSopenharmony_ci if long_arg.is_empty() { 75319625d8cSopenharmony_ci debug_assert!( 75419625d8cSopenharmony_ci long_value.is_some(), 75519625d8cSopenharmony_ci "`--` should be filtered out before this point" 75619625d8cSopenharmony_ci ); 75719625d8cSopenharmony_ci } 75819625d8cSopenharmony_ci 75919625d8cSopenharmony_ci let arg = if let Some(arg) = self.cmd.get_keymap().get(long_arg) { 76019625d8cSopenharmony_ci debug!("Parser::parse_long_arg: Found valid arg or flag '{}'", arg); 76119625d8cSopenharmony_ci Some((long_arg, arg)) 76219625d8cSopenharmony_ci } else if self.cmd.is_infer_long_args_set() { 76319625d8cSopenharmony_ci self.cmd.get_arguments().find_map(|a| { 76419625d8cSopenharmony_ci if let Some(long) = a.get_long() { 76519625d8cSopenharmony_ci if long.starts_with(long_arg) { 76619625d8cSopenharmony_ci return Some((long, a)); 76719625d8cSopenharmony_ci } 76819625d8cSopenharmony_ci } 76919625d8cSopenharmony_ci a.aliases 77019625d8cSopenharmony_ci .iter() 77119625d8cSopenharmony_ci .find_map(|(alias, _)| alias.starts_with(long_arg).then(|| (alias.as_str(), a))) 77219625d8cSopenharmony_ci }) 77319625d8cSopenharmony_ci } else { 77419625d8cSopenharmony_ci None 77519625d8cSopenharmony_ci }; 77619625d8cSopenharmony_ci 77719625d8cSopenharmony_ci if let Some((_long_arg, arg)) = arg { 77819625d8cSopenharmony_ci let ident = Identifier::Long; 77919625d8cSopenharmony_ci *valid_arg_found = true; 78019625d8cSopenharmony_ci if arg.is_takes_value_set() { 78119625d8cSopenharmony_ci debug!( 78219625d8cSopenharmony_ci "Parser::parse_long_arg({:?}): Found an arg with value '{:?}'", 78319625d8cSopenharmony_ci long_arg, &long_value 78419625d8cSopenharmony_ci ); 78519625d8cSopenharmony_ci let has_eq = long_value.is_some(); 78619625d8cSopenharmony_ci self.parse_opt_value(ident, long_value, arg, matcher, has_eq) 78719625d8cSopenharmony_ci } else if let Some(rest) = long_value { 78819625d8cSopenharmony_ci let required = self.cmd.required_graph(); 78919625d8cSopenharmony_ci debug!( 79019625d8cSopenharmony_ci "Parser::parse_long_arg({:?}): Got invalid literal `{:?}`", 79119625d8cSopenharmony_ci long_arg, rest 79219625d8cSopenharmony_ci ); 79319625d8cSopenharmony_ci let mut used: Vec<Id> = matcher 79419625d8cSopenharmony_ci .arg_ids() 79519625d8cSopenharmony_ci .filter(|arg_id| { 79619625d8cSopenharmony_ci matcher.check_explicit(arg_id, &crate::builder::ArgPredicate::IsPresent) 79719625d8cSopenharmony_ci }) 79819625d8cSopenharmony_ci .filter(|&n| { 79919625d8cSopenharmony_ci self.cmd.find(n).map_or(true, |a| { 80019625d8cSopenharmony_ci !(a.is_hide_set() || required.contains(a.get_id())) 80119625d8cSopenharmony_ci }) 80219625d8cSopenharmony_ci }) 80319625d8cSopenharmony_ci .cloned() 80419625d8cSopenharmony_ci .collect(); 80519625d8cSopenharmony_ci used.push(arg.get_id().clone()); 80619625d8cSopenharmony_ci 80719625d8cSopenharmony_ci Ok(ParseResult::UnneededAttachedValue { 80819625d8cSopenharmony_ci rest: rest.to_str_lossy().into_owned(), 80919625d8cSopenharmony_ci used, 81019625d8cSopenharmony_ci arg: arg.to_string(), 81119625d8cSopenharmony_ci }) 81219625d8cSopenharmony_ci } else { 81319625d8cSopenharmony_ci debug!("Parser::parse_long_arg({:?}): Presence validated", long_arg); 81419625d8cSopenharmony_ci let trailing_idx = None; 81519625d8cSopenharmony_ci self.react( 81619625d8cSopenharmony_ci Some(ident), 81719625d8cSopenharmony_ci ValueSource::CommandLine, 81819625d8cSopenharmony_ci arg, 81919625d8cSopenharmony_ci vec![], 82019625d8cSopenharmony_ci trailing_idx, 82119625d8cSopenharmony_ci matcher, 82219625d8cSopenharmony_ci ) 82319625d8cSopenharmony_ci } 82419625d8cSopenharmony_ci } else if let Some(sc_name) = self.possible_long_flag_subcommand(long_arg) { 82519625d8cSopenharmony_ci Ok(ParseResult::FlagSubCommand(sc_name.to_string())) 82619625d8cSopenharmony_ci } else if self 82719625d8cSopenharmony_ci .cmd 82819625d8cSopenharmony_ci .get_keymap() 82919625d8cSopenharmony_ci .get(&pos_counter) 83019625d8cSopenharmony_ci .map_or(false, |arg| { 83119625d8cSopenharmony_ci arg.is_allow_hyphen_values_set() && !arg.is_last_set() 83219625d8cSopenharmony_ci }) 83319625d8cSopenharmony_ci { 83419625d8cSopenharmony_ci debug!( 83519625d8cSopenharmony_ci "Parser::parse_long_args: positional at {} allows hyphens", 83619625d8cSopenharmony_ci pos_counter 83719625d8cSopenharmony_ci ); 83819625d8cSopenharmony_ci Ok(ParseResult::MaybeHyphenValue) 83919625d8cSopenharmony_ci } else { 84019625d8cSopenharmony_ci Ok(ParseResult::NoMatchingArg { 84119625d8cSopenharmony_ci arg: long_arg.to_owned(), 84219625d8cSopenharmony_ci }) 84319625d8cSopenharmony_ci } 84419625d8cSopenharmony_ci } 84519625d8cSopenharmony_ci 84619625d8cSopenharmony_ci fn parse_short_arg( 84719625d8cSopenharmony_ci &mut self, 84819625d8cSopenharmony_ci matcher: &mut ArgMatcher, 84919625d8cSopenharmony_ci mut short_arg: clap_lex::ShortFlags<'_>, 85019625d8cSopenharmony_ci parse_state: &ParseState, 85119625d8cSopenharmony_ci // change this to possible pos_arg when removing the usage of &mut Parser. 85219625d8cSopenharmony_ci pos_counter: usize, 85319625d8cSopenharmony_ci valid_arg_found: &mut bool, 85419625d8cSopenharmony_ci ) -> ClapResult<ParseResult> { 85519625d8cSopenharmony_ci debug!("Parser::parse_short_arg: short_arg={:?}", short_arg); 85619625d8cSopenharmony_ci 85719625d8cSopenharmony_ci #[allow(clippy::blocks_in_if_conditions)] 85819625d8cSopenharmony_ci if matches!(parse_state, ParseState::Opt(opt) | ParseState::Pos(opt) 85919625d8cSopenharmony_ci if self.cmd[opt].is_allow_hyphen_values_set() || (self.cmd[opt].is_allow_negative_numbers_set() && short_arg.is_number())) 86019625d8cSopenharmony_ci { 86119625d8cSopenharmony_ci debug!("Parser::parse_short_args: prior arg accepts hyphenated values",); 86219625d8cSopenharmony_ci return Ok(ParseResult::MaybeHyphenValue); 86319625d8cSopenharmony_ci } else if self 86419625d8cSopenharmony_ci .cmd 86519625d8cSopenharmony_ci .get_keymap() 86619625d8cSopenharmony_ci .get(&pos_counter) 86719625d8cSopenharmony_ci .map_or(false, |arg| arg.is_allow_negative_numbers_set()) 86819625d8cSopenharmony_ci && short_arg.is_number() 86919625d8cSopenharmony_ci { 87019625d8cSopenharmony_ci debug!("Parser::parse_short_arg: negative number"); 87119625d8cSopenharmony_ci return Ok(ParseResult::MaybeHyphenValue); 87219625d8cSopenharmony_ci } else if self 87319625d8cSopenharmony_ci .cmd 87419625d8cSopenharmony_ci .get_keymap() 87519625d8cSopenharmony_ci .get(&pos_counter) 87619625d8cSopenharmony_ci .map_or(false, |arg| { 87719625d8cSopenharmony_ci arg.is_allow_hyphen_values_set() && !arg.is_last_set() 87819625d8cSopenharmony_ci }) 87919625d8cSopenharmony_ci && short_arg 88019625d8cSopenharmony_ci .clone() 88119625d8cSopenharmony_ci .any(|c| !c.map(|c| self.cmd.contains_short(c)).unwrap_or_default()) 88219625d8cSopenharmony_ci { 88319625d8cSopenharmony_ci debug!( 88419625d8cSopenharmony_ci "Parser::parse_short_args: positional at {} allows hyphens", 88519625d8cSopenharmony_ci pos_counter 88619625d8cSopenharmony_ci ); 88719625d8cSopenharmony_ci return Ok(ParseResult::MaybeHyphenValue); 88819625d8cSopenharmony_ci } 88919625d8cSopenharmony_ci 89019625d8cSopenharmony_ci let mut ret = ParseResult::NoArg; 89119625d8cSopenharmony_ci 89219625d8cSopenharmony_ci let skip = self.flag_subcmd_skip; 89319625d8cSopenharmony_ci self.flag_subcmd_skip = 0; 89419625d8cSopenharmony_ci let res = short_arg.advance_by(skip); 89519625d8cSopenharmony_ci debug_assert_eq!( 89619625d8cSopenharmony_ci res, 89719625d8cSopenharmony_ci Ok(()), 89819625d8cSopenharmony_ci "tracking of `flag_subcmd_skip` is off for `{short_arg:?}`" 89919625d8cSopenharmony_ci ); 90019625d8cSopenharmony_ci while let Some(c) = short_arg.next_flag() { 90119625d8cSopenharmony_ci let c = match c { 90219625d8cSopenharmony_ci Ok(c) => c, 90319625d8cSopenharmony_ci Err(rest) => { 90419625d8cSopenharmony_ci return Ok(ParseResult::NoMatchingArg { 90519625d8cSopenharmony_ci arg: format!("-{}", rest.to_str_lossy()), 90619625d8cSopenharmony_ci }); 90719625d8cSopenharmony_ci } 90819625d8cSopenharmony_ci }; 90919625d8cSopenharmony_ci debug!("Parser::parse_short_arg:iter:{}", c); 91019625d8cSopenharmony_ci 91119625d8cSopenharmony_ci // Check for matching short options, and return the name if there is no trailing 91219625d8cSopenharmony_ci // concatenated value: -oval 91319625d8cSopenharmony_ci // Option: -o 91419625d8cSopenharmony_ci // Value: val 91519625d8cSopenharmony_ci if let Some(arg) = self.cmd.get_keymap().get(&c) { 91619625d8cSopenharmony_ci let ident = Identifier::Short; 91719625d8cSopenharmony_ci debug!( 91819625d8cSopenharmony_ci "Parser::parse_short_arg:iter:{}: Found valid opt or flag", 91919625d8cSopenharmony_ci c 92019625d8cSopenharmony_ci ); 92119625d8cSopenharmony_ci *valid_arg_found = true; 92219625d8cSopenharmony_ci if !arg.is_takes_value_set() { 92319625d8cSopenharmony_ci let arg_values = Vec::new(); 92419625d8cSopenharmony_ci let trailing_idx = None; 92519625d8cSopenharmony_ci ret = ok!(self.react( 92619625d8cSopenharmony_ci Some(ident), 92719625d8cSopenharmony_ci ValueSource::CommandLine, 92819625d8cSopenharmony_ci arg, 92919625d8cSopenharmony_ci arg_values, 93019625d8cSopenharmony_ci trailing_idx, 93119625d8cSopenharmony_ci matcher, 93219625d8cSopenharmony_ci )); 93319625d8cSopenharmony_ci continue; 93419625d8cSopenharmony_ci } 93519625d8cSopenharmony_ci 93619625d8cSopenharmony_ci // Check for trailing concatenated value 93719625d8cSopenharmony_ci // 93819625d8cSopenharmony_ci // Cloning the iterator, so we rollback if it isn't there. 93919625d8cSopenharmony_ci let val = short_arg.clone().next_value_os().unwrap_or_default(); 94019625d8cSopenharmony_ci debug!( 94119625d8cSopenharmony_ci "Parser::parse_short_arg:iter:{}: val={:?} (bytes), val={:?} (ascii), short_arg={:?}", 94219625d8cSopenharmony_ci c, val, val.as_raw_bytes(), short_arg 94319625d8cSopenharmony_ci ); 94419625d8cSopenharmony_ci let val = Some(val).filter(|v| !v.is_empty()); 94519625d8cSopenharmony_ci 94619625d8cSopenharmony_ci // Default to "we're expecting a value later". 94719625d8cSopenharmony_ci // 94819625d8cSopenharmony_ci // If attached value is not consumed, we may have more short 94919625d8cSopenharmony_ci // flags to parse, continue. 95019625d8cSopenharmony_ci // 95119625d8cSopenharmony_ci // e.g. `-xvf`, when require_equals && x.min_vals == 0, we don't 95219625d8cSopenharmony_ci // consume the `vf`, even if it's provided as value. 95319625d8cSopenharmony_ci let (val, has_eq) = if let Some(val) = val.and_then(|v| v.strip_prefix('=')) { 95419625d8cSopenharmony_ci (Some(val), true) 95519625d8cSopenharmony_ci } else { 95619625d8cSopenharmony_ci (val, false) 95719625d8cSopenharmony_ci }; 95819625d8cSopenharmony_ci match ok!(self.parse_opt_value(ident, val, arg, matcher, has_eq)) { 95919625d8cSopenharmony_ci ParseResult::AttachedValueNotConsumed => continue, 96019625d8cSopenharmony_ci x => return Ok(x), 96119625d8cSopenharmony_ci } 96219625d8cSopenharmony_ci } 96319625d8cSopenharmony_ci 96419625d8cSopenharmony_ci return if let Some(sc_name) = self.cmd.find_short_subcmd(c) { 96519625d8cSopenharmony_ci debug!("Parser::parse_short_arg:iter:{}: subcommand={}", c, sc_name); 96619625d8cSopenharmony_ci // Make sure indices get updated before reading `self.cur_idx` 96719625d8cSopenharmony_ci ok!(self.resolve_pending(matcher)); 96819625d8cSopenharmony_ci self.cur_idx.set(self.cur_idx.get() + 1); 96919625d8cSopenharmony_ci debug!("Parser::parse_short_arg: cur_idx:={}", self.cur_idx.get()); 97019625d8cSopenharmony_ci 97119625d8cSopenharmony_ci let name = sc_name.to_string(); 97219625d8cSopenharmony_ci // Get the index of the previously saved flag subcommand in the group of flags (if exists). 97319625d8cSopenharmony_ci // If it is a new flag subcommand, then the formentioned index should be the current one 97419625d8cSopenharmony_ci // (ie. `cur_idx`), and should be registered. 97519625d8cSopenharmony_ci let cur_idx = self.cur_idx.get(); 97619625d8cSopenharmony_ci self.flag_subcmd_at.get_or_insert(cur_idx); 97719625d8cSopenharmony_ci let done_short_args = short_arg.is_empty(); 97819625d8cSopenharmony_ci if done_short_args { 97919625d8cSopenharmony_ci self.flag_subcmd_at = None; 98019625d8cSopenharmony_ci } 98119625d8cSopenharmony_ci Ok(ParseResult::FlagSubCommand(name)) 98219625d8cSopenharmony_ci } else { 98319625d8cSopenharmony_ci Ok(ParseResult::NoMatchingArg { 98419625d8cSopenharmony_ci arg: format!("-{c}"), 98519625d8cSopenharmony_ci }) 98619625d8cSopenharmony_ci }; 98719625d8cSopenharmony_ci } 98819625d8cSopenharmony_ci Ok(ret) 98919625d8cSopenharmony_ci } 99019625d8cSopenharmony_ci 99119625d8cSopenharmony_ci fn parse_opt_value( 99219625d8cSopenharmony_ci &self, 99319625d8cSopenharmony_ci ident: Identifier, 99419625d8cSopenharmony_ci attached_value: Option<&RawOsStr>, 99519625d8cSopenharmony_ci arg: &Arg, 99619625d8cSopenharmony_ci matcher: &mut ArgMatcher, 99719625d8cSopenharmony_ci has_eq: bool, 99819625d8cSopenharmony_ci ) -> ClapResult<ParseResult> { 99919625d8cSopenharmony_ci debug!( 100019625d8cSopenharmony_ci "Parser::parse_opt_value; arg={}, val={:?}, has_eq={:?}", 100119625d8cSopenharmony_ci arg.get_id(), 100219625d8cSopenharmony_ci attached_value, 100319625d8cSopenharmony_ci has_eq 100419625d8cSopenharmony_ci ); 100519625d8cSopenharmony_ci debug!("Parser::parse_opt_value; arg.settings={:?}", arg.settings); 100619625d8cSopenharmony_ci 100719625d8cSopenharmony_ci debug!("Parser::parse_opt_value; Checking for val..."); 100819625d8cSopenharmony_ci // require_equals is set, but no '=' is provided, try throwing error. 100919625d8cSopenharmony_ci if arg.is_require_equals_set() && !has_eq { 101019625d8cSopenharmony_ci if arg.get_min_vals() == 0 { 101119625d8cSopenharmony_ci debug!("Requires equals, but min_vals == 0"); 101219625d8cSopenharmony_ci let arg_values = Vec::new(); 101319625d8cSopenharmony_ci let trailing_idx = None; 101419625d8cSopenharmony_ci let react_result = ok!(self.react( 101519625d8cSopenharmony_ci Some(ident), 101619625d8cSopenharmony_ci ValueSource::CommandLine, 101719625d8cSopenharmony_ci arg, 101819625d8cSopenharmony_ci arg_values, 101919625d8cSopenharmony_ci trailing_idx, 102019625d8cSopenharmony_ci matcher, 102119625d8cSopenharmony_ci )); 102219625d8cSopenharmony_ci debug_assert_eq!(react_result, ParseResult::ValuesDone); 102319625d8cSopenharmony_ci if attached_value.is_some() { 102419625d8cSopenharmony_ci Ok(ParseResult::AttachedValueNotConsumed) 102519625d8cSopenharmony_ci } else { 102619625d8cSopenharmony_ci Ok(ParseResult::ValuesDone) 102719625d8cSopenharmony_ci } 102819625d8cSopenharmony_ci } else { 102919625d8cSopenharmony_ci debug!("Requires equals but not provided. Error."); 103019625d8cSopenharmony_ci Ok(ParseResult::EqualsNotProvided { 103119625d8cSopenharmony_ci arg: arg.to_string(), 103219625d8cSopenharmony_ci }) 103319625d8cSopenharmony_ci } 103419625d8cSopenharmony_ci } else if let Some(v) = attached_value { 103519625d8cSopenharmony_ci let arg_values = vec![v.to_os_str().into_owned()]; 103619625d8cSopenharmony_ci let trailing_idx = None; 103719625d8cSopenharmony_ci let react_result = ok!(self.react( 103819625d8cSopenharmony_ci Some(ident), 103919625d8cSopenharmony_ci ValueSource::CommandLine, 104019625d8cSopenharmony_ci arg, 104119625d8cSopenharmony_ci arg_values, 104219625d8cSopenharmony_ci trailing_idx, 104319625d8cSopenharmony_ci matcher, 104419625d8cSopenharmony_ci )); 104519625d8cSopenharmony_ci debug_assert_eq!(react_result, ParseResult::ValuesDone); 104619625d8cSopenharmony_ci // Attached are always done 104719625d8cSopenharmony_ci Ok(ParseResult::ValuesDone) 104819625d8cSopenharmony_ci } else { 104919625d8cSopenharmony_ci debug!("Parser::parse_opt_value: More arg vals required..."); 105019625d8cSopenharmony_ci ok!(self.resolve_pending(matcher)); 105119625d8cSopenharmony_ci let trailing_values = false; 105219625d8cSopenharmony_ci matcher.pending_values_mut(arg.get_id(), Some(ident), trailing_values); 105319625d8cSopenharmony_ci Ok(ParseResult::Opt(arg.get_id().clone())) 105419625d8cSopenharmony_ci } 105519625d8cSopenharmony_ci } 105619625d8cSopenharmony_ci 105719625d8cSopenharmony_ci fn check_terminator(&self, arg: &Arg, val: &RawOsStr) -> Option<ParseResult> { 105819625d8cSopenharmony_ci if Some(val) 105919625d8cSopenharmony_ci == arg 106019625d8cSopenharmony_ci .terminator 106119625d8cSopenharmony_ci .as_ref() 106219625d8cSopenharmony_ci .map(|s| RawOsStr::from_str(s.as_str())) 106319625d8cSopenharmony_ci { 106419625d8cSopenharmony_ci debug!("Parser::check_terminator: terminator={:?}", arg.terminator); 106519625d8cSopenharmony_ci Some(ParseResult::ValuesDone) 106619625d8cSopenharmony_ci } else { 106719625d8cSopenharmony_ci None 106819625d8cSopenharmony_ci } 106919625d8cSopenharmony_ci } 107019625d8cSopenharmony_ci 107119625d8cSopenharmony_ci fn push_arg_values( 107219625d8cSopenharmony_ci &self, 107319625d8cSopenharmony_ci arg: &Arg, 107419625d8cSopenharmony_ci raw_vals: Vec<OsString>, 107519625d8cSopenharmony_ci matcher: &mut ArgMatcher, 107619625d8cSopenharmony_ci ) -> ClapResult<()> { 107719625d8cSopenharmony_ci debug!("Parser::push_arg_values: {:?}", raw_vals); 107819625d8cSopenharmony_ci 107919625d8cSopenharmony_ci for raw_val in raw_vals { 108019625d8cSopenharmony_ci // update the current index because each value is a distinct index to clap 108119625d8cSopenharmony_ci self.cur_idx.set(self.cur_idx.get() + 1); 108219625d8cSopenharmony_ci debug!( 108319625d8cSopenharmony_ci "Parser::add_single_val_to_arg: cur_idx:={}", 108419625d8cSopenharmony_ci self.cur_idx.get() 108519625d8cSopenharmony_ci ); 108619625d8cSopenharmony_ci let value_parser = arg.get_value_parser(); 108719625d8cSopenharmony_ci let val = ok!(value_parser.parse_ref(self.cmd, Some(arg), &raw_val)); 108819625d8cSopenharmony_ci 108919625d8cSopenharmony_ci matcher.add_val_to(arg.get_id(), val, raw_val); 109019625d8cSopenharmony_ci matcher.add_index_to(arg.get_id(), self.cur_idx.get()); 109119625d8cSopenharmony_ci } 109219625d8cSopenharmony_ci 109319625d8cSopenharmony_ci Ok(()) 109419625d8cSopenharmony_ci } 109519625d8cSopenharmony_ci 109619625d8cSopenharmony_ci fn resolve_pending(&self, matcher: &mut ArgMatcher) -> ClapResult<()> { 109719625d8cSopenharmony_ci let pending = match matcher.take_pending() { 109819625d8cSopenharmony_ci Some(pending) => pending, 109919625d8cSopenharmony_ci None => { 110019625d8cSopenharmony_ci return Ok(()); 110119625d8cSopenharmony_ci } 110219625d8cSopenharmony_ci }; 110319625d8cSopenharmony_ci 110419625d8cSopenharmony_ci debug!("Parser::resolve_pending: id={:?}", pending.id); 110519625d8cSopenharmony_ci let arg = self.cmd.find(&pending.id).expect(INTERNAL_ERROR_MSG); 110619625d8cSopenharmony_ci let _ = ok!(self.react( 110719625d8cSopenharmony_ci pending.ident, 110819625d8cSopenharmony_ci ValueSource::CommandLine, 110919625d8cSopenharmony_ci arg, 111019625d8cSopenharmony_ci pending.raw_vals, 111119625d8cSopenharmony_ci pending.trailing_idx, 111219625d8cSopenharmony_ci matcher, 111319625d8cSopenharmony_ci )); 111419625d8cSopenharmony_ci 111519625d8cSopenharmony_ci Ok(()) 111619625d8cSopenharmony_ci } 111719625d8cSopenharmony_ci 111819625d8cSopenharmony_ci fn react( 111919625d8cSopenharmony_ci &self, 112019625d8cSopenharmony_ci ident: Option<Identifier>, 112119625d8cSopenharmony_ci source: ValueSource, 112219625d8cSopenharmony_ci arg: &Arg, 112319625d8cSopenharmony_ci mut raw_vals: Vec<OsString>, 112419625d8cSopenharmony_ci mut trailing_idx: Option<usize>, 112519625d8cSopenharmony_ci matcher: &mut ArgMatcher, 112619625d8cSopenharmony_ci ) -> ClapResult<ParseResult> { 112719625d8cSopenharmony_ci ok!(self.resolve_pending(matcher)); 112819625d8cSopenharmony_ci 112919625d8cSopenharmony_ci debug!( 113019625d8cSopenharmony_ci "Parser::react action={:?}, identifier={:?}, source={:?}", 113119625d8cSopenharmony_ci arg.get_action(), 113219625d8cSopenharmony_ci ident, 113319625d8cSopenharmony_ci source 113419625d8cSopenharmony_ci ); 113519625d8cSopenharmony_ci 113619625d8cSopenharmony_ci // Process before `default_missing_values` to avoid it counting as values from the command 113719625d8cSopenharmony_ci // line 113819625d8cSopenharmony_ci if source == ValueSource::CommandLine { 113919625d8cSopenharmony_ci ok!(self.verify_num_args(arg, &raw_vals)); 114019625d8cSopenharmony_ci } 114119625d8cSopenharmony_ci 114219625d8cSopenharmony_ci if raw_vals.is_empty() { 114319625d8cSopenharmony_ci // We assume this case is valid: require equals, but min_vals == 0. 114419625d8cSopenharmony_ci if !arg.default_missing_vals.is_empty() { 114519625d8cSopenharmony_ci debug!("Parser::react: has default_missing_vals"); 114619625d8cSopenharmony_ci trailing_idx = None; 114719625d8cSopenharmony_ci raw_vals.extend( 114819625d8cSopenharmony_ci arg.default_missing_vals 114919625d8cSopenharmony_ci .iter() 115019625d8cSopenharmony_ci .map(|s| s.as_os_str().to_owned()), 115119625d8cSopenharmony_ci ); 115219625d8cSopenharmony_ci } 115319625d8cSopenharmony_ci } 115419625d8cSopenharmony_ci 115519625d8cSopenharmony_ci if let Some(val_delim) = arg.get_value_delimiter() { 115619625d8cSopenharmony_ci if self.cmd.is_dont_delimit_trailing_values_set() && trailing_idx == Some(0) { 115719625d8cSopenharmony_ci // Nothing to do 115819625d8cSopenharmony_ci } else { 115919625d8cSopenharmony_ci let mut split_raw_vals = Vec::with_capacity(raw_vals.len()); 116019625d8cSopenharmony_ci for (i, raw_val) in raw_vals.into_iter().enumerate() { 116119625d8cSopenharmony_ci let raw_val = RawOsString::new(raw_val); 116219625d8cSopenharmony_ci if !raw_val.contains(val_delim) 116319625d8cSopenharmony_ci || (self.cmd.is_dont_delimit_trailing_values_set() 116419625d8cSopenharmony_ci && trailing_idx == Some(i)) 116519625d8cSopenharmony_ci { 116619625d8cSopenharmony_ci split_raw_vals.push(raw_val.into_os_string()); 116719625d8cSopenharmony_ci } else { 116819625d8cSopenharmony_ci split_raw_vals 116919625d8cSopenharmony_ci .extend(raw_val.split(val_delim).map(|x| x.to_os_str().into_owned())); 117019625d8cSopenharmony_ci } 117119625d8cSopenharmony_ci } 117219625d8cSopenharmony_ci raw_vals = split_raw_vals 117319625d8cSopenharmony_ci } 117419625d8cSopenharmony_ci } 117519625d8cSopenharmony_ci 117619625d8cSopenharmony_ci match arg.get_action() { 117719625d8cSopenharmony_ci ArgAction::Set => { 117819625d8cSopenharmony_ci if source == ValueSource::CommandLine 117919625d8cSopenharmony_ci && matches!(ident, Some(Identifier::Short) | Some(Identifier::Long)) 118019625d8cSopenharmony_ci { 118119625d8cSopenharmony_ci // Record flag's index 118219625d8cSopenharmony_ci self.cur_idx.set(self.cur_idx.get() + 1); 118319625d8cSopenharmony_ci debug!("Parser::react: cur_idx:={}", self.cur_idx.get()); 118419625d8cSopenharmony_ci } 118519625d8cSopenharmony_ci if matcher.remove(arg.get_id()) 118619625d8cSopenharmony_ci && !(self.cmd.is_args_override_self() || arg.overrides.contains(arg.get_id())) 118719625d8cSopenharmony_ci { 118819625d8cSopenharmony_ci return Err(ClapError::argument_conflict( 118919625d8cSopenharmony_ci self.cmd, 119019625d8cSopenharmony_ci arg.to_string(), 119119625d8cSopenharmony_ci vec![arg.to_string()], 119219625d8cSopenharmony_ci Usage::new(self.cmd).create_usage_with_title(&[]), 119319625d8cSopenharmony_ci )); 119419625d8cSopenharmony_ci } 119519625d8cSopenharmony_ci self.start_custom_arg(matcher, arg, source); 119619625d8cSopenharmony_ci ok!(self.push_arg_values(arg, raw_vals, matcher)); 119719625d8cSopenharmony_ci if cfg!(debug_assertions) && matcher.needs_more_vals(arg) { 119819625d8cSopenharmony_ci debug!( 119919625d8cSopenharmony_ci "Parser::react not enough values passed in, leaving it to the validator to complain", 120019625d8cSopenharmony_ci ); 120119625d8cSopenharmony_ci } 120219625d8cSopenharmony_ci Ok(ParseResult::ValuesDone) 120319625d8cSopenharmony_ci } 120419625d8cSopenharmony_ci ArgAction::Append => { 120519625d8cSopenharmony_ci if source == ValueSource::CommandLine 120619625d8cSopenharmony_ci && matches!(ident, Some(Identifier::Short) | Some(Identifier::Long)) 120719625d8cSopenharmony_ci { 120819625d8cSopenharmony_ci // Record flag's index 120919625d8cSopenharmony_ci self.cur_idx.set(self.cur_idx.get() + 1); 121019625d8cSopenharmony_ci debug!("Parser::react: cur_idx:={}", self.cur_idx.get()); 121119625d8cSopenharmony_ci } 121219625d8cSopenharmony_ci self.start_custom_arg(matcher, arg, source); 121319625d8cSopenharmony_ci ok!(self.push_arg_values(arg, raw_vals, matcher)); 121419625d8cSopenharmony_ci if cfg!(debug_assertions) && matcher.needs_more_vals(arg) { 121519625d8cSopenharmony_ci debug!( 121619625d8cSopenharmony_ci "Parser::react not enough values passed in, leaving it to the validator to complain", 121719625d8cSopenharmony_ci ); 121819625d8cSopenharmony_ci } 121919625d8cSopenharmony_ci Ok(ParseResult::ValuesDone) 122019625d8cSopenharmony_ci } 122119625d8cSopenharmony_ci ArgAction::SetTrue => { 122219625d8cSopenharmony_ci let raw_vals = if raw_vals.is_empty() { 122319625d8cSopenharmony_ci vec![OsString::from("true")] 122419625d8cSopenharmony_ci } else { 122519625d8cSopenharmony_ci raw_vals 122619625d8cSopenharmony_ci }; 122719625d8cSopenharmony_ci 122819625d8cSopenharmony_ci if matcher.remove(arg.get_id()) 122919625d8cSopenharmony_ci && !(self.cmd.is_args_override_self() || arg.overrides.contains(arg.get_id())) 123019625d8cSopenharmony_ci { 123119625d8cSopenharmony_ci return Err(ClapError::argument_conflict( 123219625d8cSopenharmony_ci self.cmd, 123319625d8cSopenharmony_ci arg.to_string(), 123419625d8cSopenharmony_ci vec![arg.to_string()], 123519625d8cSopenharmony_ci Usage::new(self.cmd).create_usage_with_title(&[]), 123619625d8cSopenharmony_ci )); 123719625d8cSopenharmony_ci } 123819625d8cSopenharmony_ci self.start_custom_arg(matcher, arg, source); 123919625d8cSopenharmony_ci ok!(self.push_arg_values(arg, raw_vals, matcher)); 124019625d8cSopenharmony_ci Ok(ParseResult::ValuesDone) 124119625d8cSopenharmony_ci } 124219625d8cSopenharmony_ci ArgAction::SetFalse => { 124319625d8cSopenharmony_ci let raw_vals = if raw_vals.is_empty() { 124419625d8cSopenharmony_ci vec![OsString::from("false")] 124519625d8cSopenharmony_ci } else { 124619625d8cSopenharmony_ci raw_vals 124719625d8cSopenharmony_ci }; 124819625d8cSopenharmony_ci 124919625d8cSopenharmony_ci if matcher.remove(arg.get_id()) 125019625d8cSopenharmony_ci && !(self.cmd.is_args_override_self() || arg.overrides.contains(arg.get_id())) 125119625d8cSopenharmony_ci { 125219625d8cSopenharmony_ci return Err(ClapError::argument_conflict( 125319625d8cSopenharmony_ci self.cmd, 125419625d8cSopenharmony_ci arg.to_string(), 125519625d8cSopenharmony_ci vec![arg.to_string()], 125619625d8cSopenharmony_ci Usage::new(self.cmd).create_usage_with_title(&[]), 125719625d8cSopenharmony_ci )); 125819625d8cSopenharmony_ci } 125919625d8cSopenharmony_ci self.start_custom_arg(matcher, arg, source); 126019625d8cSopenharmony_ci ok!(self.push_arg_values(arg, raw_vals, matcher)); 126119625d8cSopenharmony_ci Ok(ParseResult::ValuesDone) 126219625d8cSopenharmony_ci } 126319625d8cSopenharmony_ci ArgAction::Count => { 126419625d8cSopenharmony_ci let raw_vals = if raw_vals.is_empty() { 126519625d8cSopenharmony_ci let existing_value = *matcher 126619625d8cSopenharmony_ci .get_one::<crate::builder::CountType>(arg.get_id().as_str()) 126719625d8cSopenharmony_ci .unwrap_or(&0); 126819625d8cSopenharmony_ci let next_value = existing_value.saturating_add(1); 126919625d8cSopenharmony_ci vec![OsString::from(next_value.to_string())] 127019625d8cSopenharmony_ci } else { 127119625d8cSopenharmony_ci raw_vals 127219625d8cSopenharmony_ci }; 127319625d8cSopenharmony_ci 127419625d8cSopenharmony_ci matcher.remove(arg.get_id()); 127519625d8cSopenharmony_ci self.start_custom_arg(matcher, arg, source); 127619625d8cSopenharmony_ci ok!(self.push_arg_values(arg, raw_vals, matcher)); 127719625d8cSopenharmony_ci Ok(ParseResult::ValuesDone) 127819625d8cSopenharmony_ci } 127919625d8cSopenharmony_ci ArgAction::Help => { 128019625d8cSopenharmony_ci let use_long = match ident { 128119625d8cSopenharmony_ci Some(Identifier::Long) => true, 128219625d8cSopenharmony_ci Some(Identifier::Short) => false, 128319625d8cSopenharmony_ci Some(Identifier::Index) => true, 128419625d8cSopenharmony_ci None => true, 128519625d8cSopenharmony_ci }; 128619625d8cSopenharmony_ci debug!("Help: use_long={}", use_long); 128719625d8cSopenharmony_ci Err(self.help_err(use_long)) 128819625d8cSopenharmony_ci } 128919625d8cSopenharmony_ci ArgAction::Version => { 129019625d8cSopenharmony_ci let use_long = match ident { 129119625d8cSopenharmony_ci Some(Identifier::Long) => true, 129219625d8cSopenharmony_ci Some(Identifier::Short) => false, 129319625d8cSopenharmony_ci Some(Identifier::Index) => true, 129419625d8cSopenharmony_ci None => true, 129519625d8cSopenharmony_ci }; 129619625d8cSopenharmony_ci debug!("Version: use_long={}", use_long); 129719625d8cSopenharmony_ci Err(self.version_err(use_long)) 129819625d8cSopenharmony_ci } 129919625d8cSopenharmony_ci } 130019625d8cSopenharmony_ci } 130119625d8cSopenharmony_ci 130219625d8cSopenharmony_ci fn verify_num_args(&self, arg: &Arg, raw_vals: &[OsString]) -> ClapResult<()> { 130319625d8cSopenharmony_ci if self.cmd.is_ignore_errors_set() { 130419625d8cSopenharmony_ci return Ok(()); 130519625d8cSopenharmony_ci } 130619625d8cSopenharmony_ci 130719625d8cSopenharmony_ci let actual = raw_vals.len(); 130819625d8cSopenharmony_ci let expected = arg.get_num_args().expect(INTERNAL_ERROR_MSG); 130919625d8cSopenharmony_ci 131019625d8cSopenharmony_ci if 0 < expected.min_values() && actual == 0 { 131119625d8cSopenharmony_ci // Issue 665 (https://github.com/clap-rs/clap/issues/665) 131219625d8cSopenharmony_ci // Issue 1105 (https://github.com/clap-rs/clap/issues/1105) 131319625d8cSopenharmony_ci return Err(ClapError::empty_value( 131419625d8cSopenharmony_ci self.cmd, 131519625d8cSopenharmony_ci &super::get_possible_values_cli(arg) 131619625d8cSopenharmony_ci .iter() 131719625d8cSopenharmony_ci .filter(|pv| !pv.is_hide_set()) 131819625d8cSopenharmony_ci .map(|n| n.get_name().to_owned()) 131919625d8cSopenharmony_ci .collect::<Vec<_>>(), 132019625d8cSopenharmony_ci arg.to_string(), 132119625d8cSopenharmony_ci )); 132219625d8cSopenharmony_ci } else if let Some(expected) = expected.num_values() { 132319625d8cSopenharmony_ci if expected != actual { 132419625d8cSopenharmony_ci debug!("Validator::validate_arg_num_vals: Sending error WrongNumberOfValues"); 132519625d8cSopenharmony_ci return Err(ClapError::wrong_number_of_values( 132619625d8cSopenharmony_ci self.cmd, 132719625d8cSopenharmony_ci arg.to_string(), 132819625d8cSopenharmony_ci expected, 132919625d8cSopenharmony_ci actual, 133019625d8cSopenharmony_ci Usage::new(self.cmd).create_usage_with_title(&[]), 133119625d8cSopenharmony_ci )); 133219625d8cSopenharmony_ci } 133319625d8cSopenharmony_ci } else if actual < expected.min_values() { 133419625d8cSopenharmony_ci return Err(ClapError::too_few_values( 133519625d8cSopenharmony_ci self.cmd, 133619625d8cSopenharmony_ci arg.to_string(), 133719625d8cSopenharmony_ci expected.min_values(), 133819625d8cSopenharmony_ci actual, 133919625d8cSopenharmony_ci Usage::new(self.cmd).create_usage_with_title(&[]), 134019625d8cSopenharmony_ci )); 134119625d8cSopenharmony_ci } else if expected.max_values() < actual { 134219625d8cSopenharmony_ci debug!("Validator::validate_arg_num_vals: Sending error TooManyValues"); 134319625d8cSopenharmony_ci return Err(ClapError::too_many_values( 134419625d8cSopenharmony_ci self.cmd, 134519625d8cSopenharmony_ci raw_vals 134619625d8cSopenharmony_ci .last() 134719625d8cSopenharmony_ci .expect(INTERNAL_ERROR_MSG) 134819625d8cSopenharmony_ci .to_string_lossy() 134919625d8cSopenharmony_ci .into_owned(), 135019625d8cSopenharmony_ci arg.to_string(), 135119625d8cSopenharmony_ci Usage::new(self.cmd).create_usage_with_title(&[]), 135219625d8cSopenharmony_ci )); 135319625d8cSopenharmony_ci } 135419625d8cSopenharmony_ci 135519625d8cSopenharmony_ci Ok(()) 135619625d8cSopenharmony_ci } 135719625d8cSopenharmony_ci 135819625d8cSopenharmony_ci fn remove_overrides(&self, arg: &Arg, matcher: &mut ArgMatcher) { 135919625d8cSopenharmony_ci debug!("Parser::remove_overrides: id={:?}", arg.id); 136019625d8cSopenharmony_ci for override_id in &arg.overrides { 136119625d8cSopenharmony_ci debug!("Parser::remove_overrides:iter:{:?}: removing", override_id); 136219625d8cSopenharmony_ci matcher.remove(override_id); 136319625d8cSopenharmony_ci } 136419625d8cSopenharmony_ci 136519625d8cSopenharmony_ci // Override anything that can override us 136619625d8cSopenharmony_ci let mut transitive = Vec::new(); 136719625d8cSopenharmony_ci for arg_id in matcher.arg_ids() { 136819625d8cSopenharmony_ci if let Some(overrider) = self.cmd.find(arg_id) { 136919625d8cSopenharmony_ci if overrider.overrides.contains(arg.get_id()) { 137019625d8cSopenharmony_ci transitive.push(overrider.get_id()); 137119625d8cSopenharmony_ci } 137219625d8cSopenharmony_ci } 137319625d8cSopenharmony_ci } 137419625d8cSopenharmony_ci for overrider_id in transitive { 137519625d8cSopenharmony_ci debug!("Parser::remove_overrides:iter:{:?}: removing", overrider_id); 137619625d8cSopenharmony_ci matcher.remove(overrider_id); 137719625d8cSopenharmony_ci } 137819625d8cSopenharmony_ci } 137919625d8cSopenharmony_ci 138019625d8cSopenharmony_ci #[cfg(feature = "env")] 138119625d8cSopenharmony_ci fn add_env(&mut self, matcher: &mut ArgMatcher) -> ClapResult<()> { 138219625d8cSopenharmony_ci debug!("Parser::add_env"); 138319625d8cSopenharmony_ci 138419625d8cSopenharmony_ci for arg in self.cmd.get_arguments() { 138519625d8cSopenharmony_ci // Use env only if the arg was absent among command line args, 138619625d8cSopenharmony_ci // early return if this is not the case. 138719625d8cSopenharmony_ci if matcher.contains(&arg.id) { 138819625d8cSopenharmony_ci debug!("Parser::add_env: Skipping existing arg `{}`", arg); 138919625d8cSopenharmony_ci continue; 139019625d8cSopenharmony_ci } 139119625d8cSopenharmony_ci 139219625d8cSopenharmony_ci debug!("Parser::add_env: Checking arg `{}`", arg); 139319625d8cSopenharmony_ci if let Some((_, Some(ref val))) = arg.env { 139419625d8cSopenharmony_ci debug!("Parser::add_env: Found an opt with value={:?}", val); 139519625d8cSopenharmony_ci let arg_values = vec![val.to_owned()]; 139619625d8cSopenharmony_ci let trailing_idx = None; 139719625d8cSopenharmony_ci let _ = ok!(self.react( 139819625d8cSopenharmony_ci None, 139919625d8cSopenharmony_ci ValueSource::EnvVariable, 140019625d8cSopenharmony_ci arg, 140119625d8cSopenharmony_ci arg_values, 140219625d8cSopenharmony_ci trailing_idx, 140319625d8cSopenharmony_ci matcher, 140419625d8cSopenharmony_ci )); 140519625d8cSopenharmony_ci } 140619625d8cSopenharmony_ci } 140719625d8cSopenharmony_ci 140819625d8cSopenharmony_ci Ok(()) 140919625d8cSopenharmony_ci } 141019625d8cSopenharmony_ci 141119625d8cSopenharmony_ci fn add_defaults(&self, matcher: &mut ArgMatcher) -> ClapResult<()> { 141219625d8cSopenharmony_ci debug!("Parser::add_defaults"); 141319625d8cSopenharmony_ci 141419625d8cSopenharmony_ci for arg in self.cmd.get_arguments() { 141519625d8cSopenharmony_ci debug!("Parser::add_defaults:iter:{}:", arg.get_id()); 141619625d8cSopenharmony_ci ok!(self.add_default_value(arg, matcher)); 141719625d8cSopenharmony_ci } 141819625d8cSopenharmony_ci 141919625d8cSopenharmony_ci Ok(()) 142019625d8cSopenharmony_ci } 142119625d8cSopenharmony_ci 142219625d8cSopenharmony_ci fn add_default_value(&self, arg: &Arg, matcher: &mut ArgMatcher) -> ClapResult<()> { 142319625d8cSopenharmony_ci if !arg.default_vals_ifs.is_empty() { 142419625d8cSopenharmony_ci debug!("Parser::add_default_value: has conditional defaults"); 142519625d8cSopenharmony_ci if !matcher.contains(arg.get_id()) { 142619625d8cSopenharmony_ci for (id, val, default) in arg.default_vals_ifs.iter() { 142719625d8cSopenharmony_ci let add = if let Some(a) = matcher.get(id) { 142819625d8cSopenharmony_ci match val { 142919625d8cSopenharmony_ci crate::builder::ArgPredicate::Equals(v) => { 143019625d8cSopenharmony_ci a.raw_vals_flatten().any(|value| v == value) 143119625d8cSopenharmony_ci } 143219625d8cSopenharmony_ci crate::builder::ArgPredicate::IsPresent => true, 143319625d8cSopenharmony_ci } 143419625d8cSopenharmony_ci } else { 143519625d8cSopenharmony_ci false 143619625d8cSopenharmony_ci }; 143719625d8cSopenharmony_ci 143819625d8cSopenharmony_ci if add { 143919625d8cSopenharmony_ci if let Some(default) = default { 144019625d8cSopenharmony_ci let arg_values = vec![default.to_os_string()]; 144119625d8cSopenharmony_ci let trailing_idx = None; 144219625d8cSopenharmony_ci let _ = ok!(self.react( 144319625d8cSopenharmony_ci None, 144419625d8cSopenharmony_ci ValueSource::DefaultValue, 144519625d8cSopenharmony_ci arg, 144619625d8cSopenharmony_ci arg_values, 144719625d8cSopenharmony_ci trailing_idx, 144819625d8cSopenharmony_ci matcher, 144919625d8cSopenharmony_ci )); 145019625d8cSopenharmony_ci } 145119625d8cSopenharmony_ci return Ok(()); 145219625d8cSopenharmony_ci } 145319625d8cSopenharmony_ci } 145419625d8cSopenharmony_ci } 145519625d8cSopenharmony_ci } else { 145619625d8cSopenharmony_ci debug!("Parser::add_default_value: doesn't have conditional defaults"); 145719625d8cSopenharmony_ci } 145819625d8cSopenharmony_ci 145919625d8cSopenharmony_ci if !arg.default_vals.is_empty() { 146019625d8cSopenharmony_ci debug!( 146119625d8cSopenharmony_ci "Parser::add_default_value:iter:{}: has default vals", 146219625d8cSopenharmony_ci arg.get_id() 146319625d8cSopenharmony_ci ); 146419625d8cSopenharmony_ci if matcher.contains(arg.get_id()) { 146519625d8cSopenharmony_ci debug!("Parser::add_default_value:iter:{}: was used", arg.get_id()); 146619625d8cSopenharmony_ci // do nothing 146719625d8cSopenharmony_ci } else { 146819625d8cSopenharmony_ci debug!( 146919625d8cSopenharmony_ci "Parser::add_default_value:iter:{}: wasn't used", 147019625d8cSopenharmony_ci arg.get_id() 147119625d8cSopenharmony_ci ); 147219625d8cSopenharmony_ci let arg_values: Vec<_> = arg 147319625d8cSopenharmony_ci .default_vals 147419625d8cSopenharmony_ci .iter() 147519625d8cSopenharmony_ci .map(crate::builder::OsStr::to_os_string) 147619625d8cSopenharmony_ci .collect(); 147719625d8cSopenharmony_ci let trailing_idx = None; 147819625d8cSopenharmony_ci let _ = ok!(self.react( 147919625d8cSopenharmony_ci None, 148019625d8cSopenharmony_ci ValueSource::DefaultValue, 148119625d8cSopenharmony_ci arg, 148219625d8cSopenharmony_ci arg_values, 148319625d8cSopenharmony_ci trailing_idx, 148419625d8cSopenharmony_ci matcher, 148519625d8cSopenharmony_ci )); 148619625d8cSopenharmony_ci } 148719625d8cSopenharmony_ci } else { 148819625d8cSopenharmony_ci debug!( 148919625d8cSopenharmony_ci "Parser::add_default_value:iter:{}: doesn't have default vals", 149019625d8cSopenharmony_ci arg.get_id() 149119625d8cSopenharmony_ci ); 149219625d8cSopenharmony_ci 149319625d8cSopenharmony_ci // do nothing 149419625d8cSopenharmony_ci } 149519625d8cSopenharmony_ci 149619625d8cSopenharmony_ci Ok(()) 149719625d8cSopenharmony_ci } 149819625d8cSopenharmony_ci 149919625d8cSopenharmony_ci fn start_custom_arg(&self, matcher: &mut ArgMatcher, arg: &Arg, source: ValueSource) { 150019625d8cSopenharmony_ci if source == ValueSource::CommandLine { 150119625d8cSopenharmony_ci // With each new occurrence, remove overrides from prior occurrences 150219625d8cSopenharmony_ci self.remove_overrides(arg, matcher); 150319625d8cSopenharmony_ci } 150419625d8cSopenharmony_ci matcher.start_custom_arg(arg, source); 150519625d8cSopenharmony_ci if source.is_explicit() { 150619625d8cSopenharmony_ci for group in self.cmd.groups_for_arg(arg.get_id()) { 150719625d8cSopenharmony_ci matcher.start_custom_group(group.clone(), source); 150819625d8cSopenharmony_ci matcher.add_val_to( 150919625d8cSopenharmony_ci &group, 151019625d8cSopenharmony_ci AnyValue::new(arg.get_id().clone()), 151119625d8cSopenharmony_ci OsString::from(arg.get_id().as_str()), 151219625d8cSopenharmony_ci ); 151319625d8cSopenharmony_ci } 151419625d8cSopenharmony_ci } 151519625d8cSopenharmony_ci } 151619625d8cSopenharmony_ci} 151719625d8cSopenharmony_ci 151819625d8cSopenharmony_ci// Error, Help, and Version Methods 151919625d8cSopenharmony_ciimpl<'cmd> Parser<'cmd> { 152019625d8cSopenharmony_ci /// Is only used for the long flag(which is the only one needs fuzzy searching) 152119625d8cSopenharmony_ci fn did_you_mean_error( 152219625d8cSopenharmony_ci &mut self, 152319625d8cSopenharmony_ci arg: &str, 152419625d8cSopenharmony_ci matcher: &mut ArgMatcher, 152519625d8cSopenharmony_ci remaining_args: &[&OsStr], 152619625d8cSopenharmony_ci trailing_values: bool, 152719625d8cSopenharmony_ci ) -> ClapError { 152819625d8cSopenharmony_ci debug!("Parser::did_you_mean_error: arg={}", arg); 152919625d8cSopenharmony_ci // Didn't match a flag or option 153019625d8cSopenharmony_ci let longs = self 153119625d8cSopenharmony_ci .cmd 153219625d8cSopenharmony_ci .get_keymap() 153319625d8cSopenharmony_ci .keys() 153419625d8cSopenharmony_ci .filter_map(|x| match x { 153519625d8cSopenharmony_ci KeyType::Long(l) => Some(l.to_string_lossy().into_owned()), 153619625d8cSopenharmony_ci _ => None, 153719625d8cSopenharmony_ci }) 153819625d8cSopenharmony_ci .collect::<Vec<_>>(); 153919625d8cSopenharmony_ci debug!("Parser::did_you_mean_error: longs={:?}", longs); 154019625d8cSopenharmony_ci 154119625d8cSopenharmony_ci let did_you_mean = suggestions::did_you_mean_flag( 154219625d8cSopenharmony_ci arg, 154319625d8cSopenharmony_ci remaining_args, 154419625d8cSopenharmony_ci longs.iter().map(|x| &x[..]), 154519625d8cSopenharmony_ci self.cmd.get_subcommands_mut(), 154619625d8cSopenharmony_ci ); 154719625d8cSopenharmony_ci 154819625d8cSopenharmony_ci // Add the arg to the matches to build a proper usage string 154919625d8cSopenharmony_ci if let Some((name, _)) = did_you_mean.as_ref() { 155019625d8cSopenharmony_ci if let Some(arg) = self.cmd.get_keymap().get(&name.as_ref()) { 155119625d8cSopenharmony_ci self.start_custom_arg(matcher, arg, ValueSource::CommandLine); 155219625d8cSopenharmony_ci } 155319625d8cSopenharmony_ci } 155419625d8cSopenharmony_ci 155519625d8cSopenharmony_ci let required = self.cmd.required_graph(); 155619625d8cSopenharmony_ci let used: Vec<Id> = matcher 155719625d8cSopenharmony_ci .arg_ids() 155819625d8cSopenharmony_ci .filter(|arg_id| { 155919625d8cSopenharmony_ci matcher.check_explicit(arg_id, &crate::builder::ArgPredicate::IsPresent) 156019625d8cSopenharmony_ci }) 156119625d8cSopenharmony_ci .filter(|n| self.cmd.find(n).map_or(true, |a| !a.is_hide_set())) 156219625d8cSopenharmony_ci .cloned() 156319625d8cSopenharmony_ci .collect(); 156419625d8cSopenharmony_ci 156519625d8cSopenharmony_ci // `did_you_mean` is a lot more likely and should cause us to skip the `--` suggestion 156619625d8cSopenharmony_ci // 156719625d8cSopenharmony_ci // In theory, this is only called for `--long`s, so we don't need to check 156819625d8cSopenharmony_ci let suggested_trailing_arg = 156919625d8cSopenharmony_ci did_you_mean.is_none() && !trailing_values && self.cmd.has_positionals(); 157019625d8cSopenharmony_ci ClapError::unknown_argument( 157119625d8cSopenharmony_ci self.cmd, 157219625d8cSopenharmony_ci format!("--{arg}"), 157319625d8cSopenharmony_ci did_you_mean, 157419625d8cSopenharmony_ci suggested_trailing_arg, 157519625d8cSopenharmony_ci Usage::new(self.cmd) 157619625d8cSopenharmony_ci .required(&required) 157719625d8cSopenharmony_ci .create_usage_with_title(&used), 157819625d8cSopenharmony_ci ) 157919625d8cSopenharmony_ci } 158019625d8cSopenharmony_ci 158119625d8cSopenharmony_ci fn help_err(&self, use_long: bool) -> ClapError { 158219625d8cSopenharmony_ci let styled = self.cmd.write_help_err(use_long); 158319625d8cSopenharmony_ci ClapError::display_help(self.cmd, styled) 158419625d8cSopenharmony_ci } 158519625d8cSopenharmony_ci 158619625d8cSopenharmony_ci fn version_err(&self, use_long: bool) -> ClapError { 158719625d8cSopenharmony_ci let styled = self.cmd.write_version_err(use_long); 158819625d8cSopenharmony_ci ClapError::display_version(self.cmd, styled) 158919625d8cSopenharmony_ci } 159019625d8cSopenharmony_ci} 159119625d8cSopenharmony_ci 159219625d8cSopenharmony_ci#[derive(Debug, PartialEq, Eq)] 159319625d8cSopenharmony_cipub(crate) enum ParseState { 159419625d8cSopenharmony_ci ValuesDone, 159519625d8cSopenharmony_ci Opt(Id), 159619625d8cSopenharmony_ci Pos(Id), 159719625d8cSopenharmony_ci} 159819625d8cSopenharmony_ci 159919625d8cSopenharmony_ci/// Recoverable Parsing results. 160019625d8cSopenharmony_ci#[derive(Debug, PartialEq, Clone)] 160119625d8cSopenharmony_ci#[must_use] 160219625d8cSopenharmony_cienum ParseResult { 160319625d8cSopenharmony_ci FlagSubCommand(String), 160419625d8cSopenharmony_ci Opt(Id), 160519625d8cSopenharmony_ci ValuesDone, 160619625d8cSopenharmony_ci /// Value attached to the short flag is not consumed(e.g. 'u' for `-cu` is 160719625d8cSopenharmony_ci /// not consumed). 160819625d8cSopenharmony_ci AttachedValueNotConsumed, 160919625d8cSopenharmony_ci /// This long flag doesn't need a value but is provided one. 161019625d8cSopenharmony_ci UnneededAttachedValue { 161119625d8cSopenharmony_ci rest: String, 161219625d8cSopenharmony_ci used: Vec<Id>, 161319625d8cSopenharmony_ci arg: String, 161419625d8cSopenharmony_ci }, 161519625d8cSopenharmony_ci /// This flag might be an hyphen Value. 161619625d8cSopenharmony_ci MaybeHyphenValue, 161719625d8cSopenharmony_ci /// Equals required but not provided. 161819625d8cSopenharmony_ci EqualsNotProvided { 161919625d8cSopenharmony_ci arg: String, 162019625d8cSopenharmony_ci }, 162119625d8cSopenharmony_ci /// Failed to match a Arg. 162219625d8cSopenharmony_ci NoMatchingArg { 162319625d8cSopenharmony_ci arg: String, 162419625d8cSopenharmony_ci }, 162519625d8cSopenharmony_ci /// No argument found e.g. parser is given `-` when parsing a flag. 162619625d8cSopenharmony_ci NoArg, 162719625d8cSopenharmony_ci} 162819625d8cSopenharmony_ci 162919625d8cSopenharmony_ci#[derive(Clone, Debug, PartialEq, Eq)] 163019625d8cSopenharmony_cipub(crate) struct PendingArg { 163119625d8cSopenharmony_ci pub(crate) id: Id, 163219625d8cSopenharmony_ci pub(crate) ident: Option<Identifier>, 163319625d8cSopenharmony_ci pub(crate) raw_vals: Vec<OsString>, 163419625d8cSopenharmony_ci pub(crate) trailing_idx: Option<usize>, 163519625d8cSopenharmony_ci} 163619625d8cSopenharmony_ci 163719625d8cSopenharmony_ci#[derive(Copy, Clone, Debug, PartialEq, Eq)] 163819625d8cSopenharmony_cipub(crate) enum Identifier { 163919625d8cSopenharmony_ci Short, 164019625d8cSopenharmony_ci Long, 164119625d8cSopenharmony_ci Index, 164219625d8cSopenharmony_ci} 1643