@@ -5,8 +5,9 @@ use crate::{
55 ChoiceValue , DefaultValue ,
66} ;
77use anyhow:: Result ;
8+ use indexmap:: IndexSet ;
89
9- const UTIL_FNS : [ ( & str , & str ) ; 6 ] = [
10+ const UTIL_FNS : [ ( & str , & str ) ; 7 ] = [
1011 (
1112 "_argc_take_args" ,
1213 r#"
@@ -23,7 +24,7 @@ _argc_take_args() {
2324 else
2425 while [[ $_argc_take_index -lt $_argc_len ]]; do
2526 _argc_take_value="${argc__args[_argc_take_index]}"
26- if [[ -n "$signs" ]] && [[ "$_argc_take_value" =~ ^["$signs"] ]] ; then
27+ if _argc_maybe_flag_option "$signs" "$_argc_take_value"; then
2728 if [[ "${#_argc_take_value}" -gt 1 ]]; then
2829 break
2930 fi
@@ -180,6 +181,35 @@ _argc_check_bool() {
180181 _argc_die "error: environment variable '$env_name' has invalid value for param '$param_name'"
181182 fi
182183}
184+ "# ,
185+ ) ,
186+ (
187+ "_argc_maybe_flag_option" ,
188+ r#"
189+ _argc_maybe_flag_option() {
190+ local signs="$1" arg="$2"
191+ if [[ -z "$signs" ]]; then
192+ return 1
193+ fi
194+ local cond=false
195+ if [[ "$signs" == *"+"* ]]; then
196+ if [[ "$arg" =~ ^\+[^+].* ]]; then
197+ cond=true
198+ fi
199+ elif [[ "$arg" == -* ]]; then
200+ if (( ${#arg} < 3 )) || [[ ! "$arg" =~ ^---.* ]]; then
201+ cond=true
202+ fi
203+ fi
204+ if [[ "$cond" == "false" ]]; then
205+ return 1
206+ fi
207+ local value="${arg%%=*}"
208+ if [[ "$value" =~ [[:space:]] ]]; then
209+ return 1
210+ fi
211+ return 0
212+ }
183213"# ,
184214 ) ,
185215] ;
@@ -232,7 +262,7 @@ fn build_root(cmd: &Command, wrap_width: Option<usize>) -> String {
232262 let after_hook = if after_hook { "\n _argc_after" } else { "" } ;
233263 let mut util_fns = String :: new ( ) ;
234264 for ( fn_name, util_fn) in UTIL_FNS {
235- if command. contains ( fn_name) {
265+ if command. contains ( fn_name) || util_fns . contains ( fn_name ) {
236266 util_fns. push_str ( util_fn) ;
237267 }
238268 }
@@ -369,21 +399,6 @@ fn build_parse(cmd: &Command, suffix: &str) -> String {
369399 } else {
370400 String :: new ( )
371401 } ;
372- let parse_unknown_flag_options = if !cmd. flag_option_params . is_empty ( ) {
373- let unknown_flags = flag_option_signs
374- . chars ( )
375- . map ( |v| format ! ( "{v}?*" ) )
376- . collect :: < Vec < String > > ( )
377- . join ( " | " ) ;
378- format ! (
379- r#"
380- {unknown_flags})
381- _argc_die "error: unexpected argument \`$_argc_key\` found"
382- ;;"#
383- )
384- } else {
385- String :: new ( )
386- } ;
387402 let parse_subcommands = if !cmd. subcommands . is_empty ( ) {
388403 let mut parses: Vec < String > = cmd
389404 . subcommands
@@ -437,13 +452,24 @@ fn build_parse(cmd: &Command, suffix: &str) -> String {
437452 String :: new ( )
438453 } ;
439454
455+ let handle_unknown_flag_options = if !cmd. flag_option_params . is_empty ( ) {
456+ let signs = flag_option_signs. iter ( ) . collect :: < String > ( ) ;
457+ format ! (
458+ r#"
459+ if _argc_maybe_flag_option "{signs}" "$_argc_item"; then
460+ _argc_die "error: unexpected argument \`$_argc_key\` found"
461+ fi"# ,
462+ )
463+ } else {
464+ String :: new ( )
465+ } ;
440466 let parse_fallback = if !cmd. subcommands . is_empty ( ) && cmd. positional_params . is_empty ( ) {
441467 let name = cmd. full_name ( ) ;
442468 if let Some ( subcmd) = cmd. find_default_subcommand ( ) {
443469 let paths = subcmd. paths . join ( "_" ) ;
444470 format ! (
445471 r#"
446- *)
472+ *){handle_unknown_flag_options}
447473 if [[ "${{#argc__positionals[@]}}" -eq 0 ]]; then
448474 _argc_action=_argc_parse_{paths}
449475 break
@@ -453,7 +479,7 @@ fn build_parse(cmd: &Command, suffix: &str) -> String {
453479 } else {
454480 format ! (
455481 r#"
456- *)
482+ *){handle_unknown_flag_options}
457483 _argc_die "error: \`{name}\` requires a subcommand but one was not provided"$'\n'" [subcommands: $_argc_subcmds]"
458484 ;;"#
459485 )
@@ -473,7 +499,7 @@ fn build_parse(cmd: &Command, suffix: &str) -> String {
473499 } ;
474500 format ! (
475501 r#"
476- *)
502+ *){handle_unknown_flag_options}
477503 argc__positionals+=("$_argc_item")
478504 _argc_index=$((_argc_index + 1)){terminated}
479505 ;;"#
@@ -499,7 +525,6 @@ fn build_parse(cmd: &Command, suffix: &str) -> String {
499525 parse_dash,
500526 parse_flag_options,
501527 parse_subcommands,
502- parse_unknown_flag_options,
503528 parse_fallback,
504529 ]
505530 . join ( "" ) ;
@@ -524,7 +549,7 @@ _argc_parse{suffix}() {{
524549 )
525550}
526551
527- fn build_parse_flag_option ( param : & FlagOptionParam , signs : & str ) -> String {
552+ fn build_parse_flag_option ( param : & FlagOptionParam , signs : & IndexSet < char > ) -> String {
528553 let names = param. list_names ( ) . join ( " | " ) ;
529554 let long_name = param. long_name ( ) ;
530555 let var_name = param. var_name ( ) ;
@@ -555,7 +580,11 @@ fn build_parse_flag_option(param: &FlagOptionParam, signs: &str) -> String {
555580 ;;"#
556581 )
557582 } else {
558- let signs = if param. terminated ( ) { "" } else { signs } ;
583+ let signs: String = if param. terminated ( ) {
584+ "" . into ( )
585+ } else {
586+ signs. iter ( ) . collect :: < String > ( )
587+ } ;
559588 let delimiter = match param. delimiter ( ) {
560589 Some ( v) => v. to_string ( ) ,
561590 None => String :: new ( ) ,
0 commit comments