mirror of
https://github.com/nushell/nushell.git
synced 2025-08-09 04:45:04 +02:00
Allow different names for ...rest (#3954)
* Allow different names for ...rest * Resolves #3945 * This change requires an explicit name for the rest argument in `WholeStreamCommand`, which is why there are so many changed files. * Remove redundant clone * Add tests
This commit is contained in:
@ -88,7 +88,7 @@ mod tests {
|
||||
Signature::build("bundle add")
|
||||
.switch("skip-install", "Adds the gem to the Gemfile but does not install it.", None)
|
||||
.named("group", SyntaxShape::String, "Specify the group(s) for the added gem. Multiple groups should be separated by commas.", Some('g'))
|
||||
.rest(SyntaxShape::Any, "options")
|
||||
.rest("rest", SyntaxShape::Any, "options")
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1601,7 +1601,7 @@ fn parse_internal_command(
|
||||
|
||||
positional.push(arg);
|
||||
current_positional += 1;
|
||||
} else if let Some((rest_type, _)) = &signature.rest_positional {
|
||||
} else if let Some((_, rest_type, _)) = &signature.rest_positional {
|
||||
let (arg, err) = parse_arg(*rest_type, scope, &lite_cmd.parts[idx]);
|
||||
if error.is_none() {
|
||||
error = err;
|
||||
|
@ -185,20 +185,20 @@ pub fn parse_type_token(type_: &Token) -> (SyntaxShape, Option<ParseError>) {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn parse_rest_name(name_token: &Token) -> Option<ParseError> {
|
||||
pub(crate) fn parse_rest_name(name_token: &Token) -> (Spanned<String>, Option<ParseError>) {
|
||||
return if let TokenContents::Baseline(name) = &name_token.contents {
|
||||
if !name.starts_with("...") {
|
||||
Some(parse_rest_name_err(name_token))
|
||||
} else if !name.starts_with("...rest") {
|
||||
Some(ParseError::mismatch(
|
||||
"rest argument name to be 'rest'",
|
||||
token_to_spanned_string(name_token),
|
||||
))
|
||||
} else {
|
||||
None
|
||||
match name.strip_prefix("...") {
|
||||
Some(var_name) => (var_name.to_string().spanned(name_token.span), None),
|
||||
None => (
|
||||
"InternalError".to_string().spanned(name_token.span),
|
||||
Some(parse_rest_name_err(name_token)),
|
||||
),
|
||||
}
|
||||
} else {
|
||||
Some(parse_rest_name_err(name_token))
|
||||
(
|
||||
"InternalError".to_string().spanned(name_token.span),
|
||||
Some(parse_rest_name_err(name_token)),
|
||||
)
|
||||
};
|
||||
|
||||
fn parse_rest_name_err(token: &Token) -> ParseError {
|
||||
|
@ -231,7 +231,7 @@ fn parse_rest(
|
||||
tokens: &[Token],
|
||||
tokens_as_str: &Spanned<String>,
|
||||
) -> (
|
||||
Option<(SyntaxShape, Description)>,
|
||||
Option<(String, SyntaxShape, Description)>,
|
||||
usize,
|
||||
Option<ParseError>,
|
||||
) {
|
||||
@ -251,7 +251,7 @@ fn parse_rest(
|
||||
let mut type_ = SyntaxShape::Any;
|
||||
let mut comment = "".to_string();
|
||||
|
||||
let error = parse_rest_name(&tokens[i]);
|
||||
let (name, error) = parse_rest_name(&tokens[i]);
|
||||
err = err.or(error);
|
||||
i += 1;
|
||||
|
||||
@ -268,7 +268,7 @@ fn parse_rest(
|
||||
comment = parsed_comment.unwrap_or_else(|| "".to_string());
|
||||
}
|
||||
|
||||
(Some((type_, comment)), i, err)
|
||||
(Some((name.item, type_, comment)), i, err)
|
||||
}
|
||||
|
||||
fn parse_optional_type(tokens: &[Token]) -> (Option<SyntaxShape>, usize, Option<ParseError>) {
|
||||
@ -352,7 +352,7 @@ fn to_signature(
|
||||
name: &str,
|
||||
params: Vec<Parameter>,
|
||||
flags: Vec<Flag>,
|
||||
rest: Option<(SyntaxShape, Description)>,
|
||||
rest: Option<(String, SyntaxShape, Description)>,
|
||||
) -> Signature {
|
||||
let mut sign = Signature::new(name);
|
||||
|
||||
|
@ -332,7 +332,23 @@ fn simple_def_with_rest_arg() {
|
||||
assert!(err.is_none());
|
||||
assert_eq!(
|
||||
sign.rest_positional,
|
||||
Some((SyntaxShape::Any, "".to_string()))
|
||||
Some(("rest".to_string(), SyntaxShape::Any, "".to_string()))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn simple_def_with_rest_arg_other_name() {
|
||||
let name = "my_func";
|
||||
let sign = "[ ...paths:path # A pathological test]";
|
||||
let (sign, err) = parse_signature(name, &sign.to_string().spanned_unknown());
|
||||
assert!(err.is_none());
|
||||
assert_eq!(
|
||||
sign.rest_positional,
|
||||
Some((
|
||||
"paths".to_string(),
|
||||
SyntaxShape::FilePath,
|
||||
"A pathological test".to_string()
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
@ -344,7 +360,11 @@ fn simple_def_with_rest_arg_with_type_and_comment() {
|
||||
assert!(err.is_none());
|
||||
assert_eq!(
|
||||
sign.rest_positional,
|
||||
Some((SyntaxShape::FilePath, "My super cool rest arg".to_string()))
|
||||
Some((
|
||||
"rest".to_string(),
|
||||
SyntaxShape::FilePath,
|
||||
"My super cool rest arg".to_string()
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
@ -380,6 +400,10 @@ fn simple_def_with_param_flag_and_rest() {
|
||||
);
|
||||
assert_eq!(
|
||||
sign.rest_positional,
|
||||
Some((SyntaxShape::Table, "Another rest".to_string()))
|
||||
Some((
|
||||
"rest".to_string(),
|
||||
SyntaxShape::Table,
|
||||
"Another rest".to_string()
|
||||
))
|
||||
);
|
||||
}
|
||||
|
Reference in New Issue
Block a user