fn parse_internal_command(
    lite_cmd: &LiteCommand,
    registry: &dyn SignatureRegistry,
    signature: &Signature,
    mut idx: usize,
) -> (InternalCommand, Option<ParseError>) {
    // This is a known internal command, so we need to work with the arguments and parse them according to the expected types

    let (name, name_span) = (
        lite_cmd.parts[0..(idx + 1)]
            .iter()
            .map(|x| x.item.clone())
            .collect::<Vec<String>>()
            .join(" "),
        Span::new(
            lite_cmd.parts[0].span.start(),
            lite_cmd.parts[idx].span.end(),
        ),
    );

    let mut internal_command = InternalCommand::new(name, name_span, lite_cmd.span());
    internal_command.args.set_initial_flags(&signature);

    let mut current_positional = 0;
    let mut named = NamedArguments::new();
    let mut positional = vec![];
    let mut error = None;
    idx += 1; // Start where the arguments begin

    while idx < lite_cmd.parts.len() {
        if lite_cmd.parts[idx].item.starts_with('-') && lite_cmd.parts[idx].item.len() > 1 {
            let (named_types, err) =
                get_flags_from_flag(&signature, &lite_cmd.parts[0], &lite_cmd.parts[idx]);

            if err.is_none() {
                for (full_name, named_type) in &named_types {
                    match named_type {
                        NamedType::Mandatory(_, shape) | NamedType::Optional(_, shape) => {
                            if idx == lite_cmd.parts.len() {
                                // Oops, we're missing the argument to our named argument
                                if error.is_none() {
                                    error = Some(ParseError::argument_error(
                                        lite_cmd.parts[0].clone(),
                                        ArgumentError::MissingValueForName(format!("{:?}", shape)),
                                    ));
                                }
                            } else {
                                idx += 1;
                                if lite_cmd.parts.len() > idx {
                                    let (arg, err) =
                                        parse_arg(*shape, registry, &lite_cmd.parts[idx]);
                                    named.insert_mandatory(
                                        full_name.clone(),
                                        lite_cmd.parts[idx - 1].span,
                                        arg,
                                    );

                                    if error.is_none() {
                                        error = err;
                                    }
                                } else if error.is_none() {
                                    error = Some(ParseError::argument_error(
                                        lite_cmd.parts[0].clone(),
                                        ArgumentError::MissingValueForName(full_name.to_owned()),
                                    ));
                                }
                            }
                        }
                        NamedType::Switch(_) => {
                            named.insert_switch(
                                full_name.clone(),
                                Some(Flag::new(FlagKind::Longhand, lite_cmd.parts[idx].span)),
                            );
                        }
                    }
                }
            } else {
                positional.push(garbage(lite_cmd.parts[idx].span));

                if error.is_none() {
                    error = err;
                }
            }
        } else if signature.positional.len() > current_positional {
            let arg = {
                let (new_idx, expr, err) = parse_positional_argument(
                    idx,
                    &lite_cmd,
                    &signature.positional[current_positional].0,
                    signature.positional.len() - current_positional - 1,
                    registry,
                );
                idx = new_idx;
                if error.is_none() {
                    error = err;
                }
                expr
            };

            positional.push(arg);
            current_positional += 1;
        } else if let Some((rest_type, _)) = &signature.rest_positional {
            let (arg, err) = parse_arg(*rest_type, registry, &lite_cmd.parts[idx]);
            if error.is_none() {
                error = err;
            }

            positional.push(arg);
            current_positional += 1;
        } else {
            positional.push(garbage(lite_cmd.parts[idx].span));

            if error.is_none() {
                error = Some(ParseError::argument_error(
                    lite_cmd.parts[0].clone(),
                    ArgumentError::UnexpectedArgument(lite_cmd.parts[idx].clone()),
                ));
            }
        }

        idx += 1;
    }

    // Count the required positional arguments and ensure these have been met
    let mut required_arg_count = 0;
    for positional_arg in &signature.positional {
        if let PositionalType::Mandatory(_, _) = positional_arg.0 {
            required_arg_count += 1;
        }
    }
    if positional.len() < required_arg_count && error.is_none() {
        // to make "command -h" work even if required arguments are missing
        if !named.named.contains_key("help") {
            let (_, name) = &signature.positional[positional.len()];
            error = Some(ParseError::argument_error(
                lite_cmd.parts[0].clone(),
                ArgumentError::MissingMandatoryPositional(name.to_owned()),
            ));
        }
    }

    if !named.is_empty() {
        internal_command.args.named = Some(named);
    }

    if !positional.is_empty() {
        internal_command.args.positional = Some(positional);
    }

    (internal_command, error)
}
/// Does a full parse of an internal command using the lite-ly parse command as a starting point
/// This main focus at this level is to understand what flags were passed in, what positional arguments were passed in, what rest arguments were passed in
/// and to ensure that the basic requirements in terms of number of each were met.
Does a full parse of an internal command using the lite-ly parse command as a starting point
This main focus at this level is to understand what flags were passed in, what positional arguments were passed in, what rest arguments were passed in
and to ensure that the basic requirements in terms of number of each were met.
Does a full parse of an internal command using the lite - ly parse command as a starting point This main focus at this level is to understand what flags were passed in what positional arguments were passed in what rest arguments were passed in and to ensure that the basic requirements in terms of number of each were met .
fn parse_internal_command(
    lite_cmd: &LiteCommand,
    registry: &dyn SignatureRegistry,
    signature: &Signature,
    mut idx: usize,
) -> (InternalCommand, Option<ParseError>) {
    // This is a known internal command, so we need to work with the arguments and parse them according to the expected types
    let (name, name_span) = (
        lite_cmd.parts[0..(idx + 1)]
            .iter()
            .map(|x| x.item.clone())
            .collect::<Vec<String>>()
            .join(" "),
        Span::new(
            lite_cmd.parts[0].span.start(),
            lite_cmd.parts[idx].span.end(),
        ),
    );
    let mut internal_command = InternalCommand::new(name, name_span, lite_cmd.span());
    internal_command.args.set_initial_flags(&signature);
    let mut current_positional = 0;
    let mut named = NamedArguments::new();
    let mut positional = vec![];
    let mut error = None;
    idx += 1; // Start where the arguments begin
    while idx < lite_cmd.parts.len() {
        if lite_cmd.parts[idx].item.starts_with('-') && lite_cmd.parts[idx].item.len() > 1 {
            let (named_types, err) =
                get_flags_from_flag(&signature, &lite_cmd.parts[0], &lite_cmd.parts[idx]);
            if err.is_none() {
                for (full_name, named_type) in &named_types {
                    match named_type {
                        NamedType::Mandatory(_, shape) | NamedType::Optional(_, shape) => {
                            if idx == lite_cmd.parts.len() {
                                // Oops, we're missing the argument to our named argument
                                if error.is_none() {
                                    error = Some(ParseError::argument_error(
                                        lite_cmd.parts[0].clone(),
                                        ArgumentError::MissingValueForName(format!("{:?}", shape)),
                                    ));
                                }
                            } else {
                                idx += 1;
                                if lite_cmd.parts.len() > idx {
                                    let (arg, err) =
                                        parse_arg(*shape, registry, &lite_cmd.parts[idx]);
                                    named.insert_mandatory(
                                        full_name.clone(),
                                        lite_cmd.parts[idx - 1].span,
                                        arg,
                                    );
                                    if error.is_none() {
                                        error = err;
                                    }
                                } else if error.is_none() {
                                    error = Some(ParseError::argument_error(
                                        lite_cmd.parts[0].clone(),
                                        ArgumentError::MissingValueForName(full_name.to_owned()),
                                    ));
                                }
                            }
                        }
                        NamedType::Switch(_) => {
                            named.insert_switch(
                                full_name.clone(),
                                Some(Flag::new(FlagKind::Longhand, lite_cmd.parts[idx].span)),
                            );
                        }
                    }
                }
            } else {
                positional.push(garbage(lite_cmd.parts[idx].span));
                if error.is_none() {
                    error = err;
                }
            }
        } else if signature.positional.len() > current_positional {
            let arg = {
                let (new_idx, expr, err) = parse_positional_argument(
                    idx,
                    &lite_cmd,
                    &signature.positional[current_positional].0,
                    signature.positional.len() - current_positional - 1,
                    registry,
                );
                idx = new_idx;
                if error.is_none() {
                    error = err;
                }
                expr
            };
            positional.push(arg);
            current_positional += 1;
        } else if let Some((rest_type, _)) = &signature.rest_positional {
            let (arg, err) = parse_arg(*rest_type, registry, &lite_cmd.parts[idx]);
            if error.is_none() {
                error = err;
            }
            positional.push(arg);
            current_positional += 1;
        } else {
            positional.push(garbage(lite_cmd.parts[idx].span));
            if error.is_none() {
                error = Some(ParseError::argument_error(
                    lite_cmd.parts[0].clone(),
                    ArgumentError::UnexpectedArgument(lite_cmd.parts[idx].clone()),
                ));
            }
        }
        idx += 1;
    }
    // Count the required positional arguments and ensure these have been met
    let mut required_arg_count = 0;
    for positional_arg in &signature.positional {
        if let PositionalType::Mandatory(_, _) = positional_arg.0 {
            required_arg_count += 1;
        }
    }
    if positional.len() < required_arg_count && error.is_none() {
        // to make "command -h" work even if required arguments are missing
        if !named.named.contains_key("help") {
            let (_, name) = &signature.positional[positional.len()];
            error = Some(ParseError::argument_error(
                lite_cmd.parts[0].clone(),
                ArgumentError::MissingMandatoryPositional(name.to_owned()),
            ));
        }
    }
    if !named.is_empty() {
        internal_command.args.named = Some(named);
    }
    if !positional.is_empty() {
        internal_command.args.positional = Some(positional);
    }
    (internal_command, error)
}
fn parse_internal_command ( lite_cmd : & LiteCommand , registry : & dyn SignatureRegistry , signature : & Signature , mut idx : usize , ) -> ( InternalCommand , Option < ParseError > ) { // This is a known internal command, so we need to work with the arguments and parse them according to the expected types let ( name , name_span ) = ( lite_cmd . parts [ 0 .. ( idx + 1 ) ] . iter ( ) . map ( | x | x . item . clone ( ) ) . collect :: < Vec < String > > ( ) . join ( " " ) , Span :: new ( lite_cmd . parts [ 0 ] . span . start ( ) , lite_cmd . parts [ idx ] . span . end ( ) , ) , ) ; let mut internal_command = InternalCommand :: new ( name , name_span , lite_cmd . span ( ) ) ; internal_command . args . set_initial_flags ( & signature ) ; let mut current_positional = 0 ; let mut named = NamedArguments :: new ( ) ; let mut positional = vec ! [ ] ; let mut error = None ; idx += 1 ; // Start where the arguments begin while idx < lite_cmd . parts . len ( ) { if lite_cmd . parts [ idx ] . item . starts_with ( '-' ) && lite_cmd . parts [ idx ] . item . len ( ) > 1 { let ( named_types , err ) = get_flags_from_flag ( & signature , & lite_cmd . parts [ 0 ] , & lite_cmd . parts [ idx ] ) ; if err . is_none ( ) { for ( full_name , named_type ) in & named_types { match named_type { NamedType :: Mandatory ( _ , shape ) | NamedType :: Optional ( _ , shape ) => { if idx == lite_cmd . parts . len ( ) { // Oops, we're missing the argument to our named argument if error . is_none ( ) { error = Some ( ParseError :: argument_error ( lite_cmd . parts [ 0 ] . clone ( ) , ArgumentError :: MissingValueForName ( format ! ( " " shape ) ) , ) ) ; } } else { idx += 1 ; if lite_cmd . parts . len ( ) > idx { let ( arg , err ) = parse_arg ( * shape , registry , & lite_cmd . parts [ idx ] ) ; named . insert_mandatory ( full_name . clone ( ) , lite_cmd . parts [ idx - 1 ] . span , arg , ) ; if error . is_none ( ) { error = err ; } } else if error . is_none ( ) { error = Some ( ParseError :: argument_error ( lite_cmd . parts [ 0 ] . clone ( ) , ArgumentError :: MissingValueForName ( full_name . to_owned ( ) ) , ) ) ; } } } NamedType :: Switch ( _ ) => { named . insert_switch ( full_name . clone ( ) , Some ( Flag :: new ( FlagKind :: Longhand , lite_cmd . parts [ idx ] . span ) ) , ) ; } } } } else { positional . push ( garbage ( lite_cmd . parts [ idx ] . span ) ) ; if error . is_none ( ) { error = err ; } } } else if signature . positional . len ( ) > current_positional { let arg = { let ( new_idx , expr , err ) = parse_positional_argument ( idx , & lite_cmd , & signature . positional [ current_positional ] . 0 , signature . positional . len ( ) - current_positional - 1 , registry , ) ; idx = new_idx ; if error . is_none ( ) { error = err ; } expr } ; positional . push ( arg ) ; current_positional += 1 ; } else if let Some ( ( rest_type , _ ) ) = & signature . rest_positional { let ( arg , err ) = parse_arg ( * rest_type , registry , & lite_cmd . parts [ idx ] ) ; if error . is_none ( ) { error = err ; } positional . push ( arg ) ; current_positional += 1 ; } else { positional . push ( garbage ( lite_cmd . parts [ idx ] . span ) ) ; if error . is_none ( ) { error = Some ( ParseError :: argument_error ( lite_cmd . parts [ 0 ] . clone ( ) , ArgumentError :: UnexpectedArgument ( lite_cmd . parts [ idx ] . clone ( ) ) , ) ) ; } } idx += 1 ; } // Count the required positional arguments and ensure these have been met let mut required_arg_count = 0 ; for positional_arg in & signature . positional { if let PositionalType :: Mandatory ( _ , _ ) = positional_arg . 0 { required_arg_count += 1 ; } } if positional . len ( ) < required_arg_count && error . is_none ( ) { // to make "command -h" work even if required arguments are missing if ! named . named . contains_key ( " " ) { let ( _ , name ) = & signature . positional [ positional . len ( ) ] ; error = Some ( ParseError :: argument_error ( lite_cmd . parts [ 0 ] . clone ( ) , ArgumentError :: MissingMandatoryPositional ( name . to_owned ( ) ) , ) ) ; } } if ! named . is_empty ( ) { internal_command . args . named = Some ( named ) ; } if ! positional . is_empty ( ) { internal_command . args . positional = Some ( positional ) ; } ( internal_command , error ) }
Does a full parse of an internal command using the lite-ly parse command as a starting point
This main focus at this level is to understand what flags were passed in, what positional arguments were passed in, what rest arguments were passed in
and to ensure that the basic requirements in terms of number of each were met.
Does a full parse of an internal command using the lite - ly parse command as a starting point This main focus at this level is to understand what flags were passed in what positional arguments were passed in what rest arguments were passed in and to ensure that the basic requirements in terms of number of each were met .
lite_cmd
&LiteCommand
registry
&dyn SignatureRegistry
signature
&Signature
idx
usize
lite_cmd
&LiteCommand
registry
&dyn SignatureRegistry
signature
&Signature
idx
usize