diff --git a/src/attribute.rs b/src/attribute.rs index bf657a0..939ea01 100644 --- a/src/attribute.rs +++ b/src/attribute.rs @@ -42,7 +42,7 @@ impl AttributeDiscriminant { impl<'src> Attribute<'src> { pub(crate) fn new( name: Name<'src>, - argument: Option>, + mut arguments: Vec>, ) -> CompileResult<'src, Self> { use AttributeDiscriminant::*; @@ -56,8 +56,7 @@ impl<'src> Attribute<'src> { }) })?; - let found = argument.as_ref().iter().count(); - + let found = arguments.len(); let range = discriminant.argument_range(); if !range.contains(&found) { @@ -72,9 +71,9 @@ impl<'src> Attribute<'src> { } Ok(match discriminant { - Confirm => Self::Confirm(argument), - Doc => Self::Doc(argument), - Group => Self::Group(argument.unwrap()), + Confirm => Self::Confirm(arguments.pop()), + Doc => Self::Doc(arguments.pop()), + Group => Self::Group(arguments.pop().unwrap()), Linux => Self::Linux, Macos => Self::Macos, NoCd => Self::NoCd, diff --git a/src/parser.rs b/src/parser.rs index 857284d..14fdabe 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -987,15 +987,29 @@ impl<'run, 'src> Parser<'run, 'src> { loop { let name = self.parse_name()?; - let argument = if self.accepted(ParenL)? { - let argument = self.parse_string_literal()?; - self.expect(ParenR)?; - Some(argument) + let arguments: Vec = if self.next_is(Colon) { + self.presume(Colon)?; + let single_arg = self.parse_string_literal()?; + vec![single_arg] + } else if self.next_is(ParenL) { + self.presume(ParenL)?; + let mut args = Vec::new(); + loop { + args.push(self.parse_string_literal()?); + if self.next_is(ParenR) { + self.presume(ParenR)?; + break; + } + if self.next_is(Comma) { + self.presume(Comma)?; + } + } + args } else { - None + Vec::new() }; - let attribute = Attribute::new(name, argument)?; + let attribute = Attribute::new(name, arguments)?; if let Some(line) = attributes.get(&attribute) { return Err(name.error(CompileErrorKind::DuplicateAttribute { @@ -1158,6 +1172,18 @@ mod tests { tree: (justfile (alias t test)), } + test! { + name: single_argument_attribute_shorthand, + text: "[group: 'some-group']\nalias t := test", + tree: (justfile (alias t test)), + } + + test! { + name: single_argument_attribute_shorthand_multiple_same_line, + text: "[group: 'some-group', group: 'some-other-group']\nalias t := test", + tree: (justfile (alias t test)), + } + test! { name: aliases_multiple, text: "alias t := test\nalias b := build", diff --git a/tests/attributes.rs b/tests/attributes.rs index 9c79bb7..a604777 100644 --- a/tests/attributes.rs +++ b/tests/attributes.rs @@ -72,7 +72,7 @@ fn multiple_attributes_one_line_error_message() { ) .stderr( " - error: Expected ']', ',', or '(', but found identifier + error: Expected ']', ':', ',', or '(', but found identifier ——▶ justfile:1:17 │ 1 │ [macos, windows linux] diff --git a/tests/confirm.rs b/tests/confirm.rs index b1a2657..a93c1fc 100644 --- a/tests/confirm.rs +++ b/tests/confirm.rs @@ -130,7 +130,7 @@ fn confirm_recipe_with_prompt_too_many_args() { echo confirmed ", ) - .stderr("error: Expected ')', but found ','\n ——▶ justfile:1:64\n │\n1 │ [confirm(\"This is dangerous - are you sure you want to run it?\",\"this second argument is not supported\")]\n │ ^\n") + .stderr("error: Attribute `confirm` got 2 arguments but takes at most 1 argument\n ——▶ justfile:1:2\n │\n1 │ [confirm(\"This is dangerous - are you sure you want to run it?\",\"this second argument is not supported\")]\n │ ^^^^^^^\n") .stdout("") .status(1) .run(); diff --git a/tests/groups.rs b/tests/groups.rs index 6c072e8..f704882 100644 --- a/tests/groups.rs +++ b/tests/groups.rs @@ -126,11 +126,10 @@ fn list_groups_with_custom_prefix() { Test::new() .justfile( " - [group('B')] + [group: 'B'] foo: - [group('A')] - [group('B')] + [group: 'A', group: 'B'] bar: ", )