@@ -13,6 +13,8 @@ pub(crate) enum Attribute<'src> {
1313 Arg {
1414 help : Option < StringLiteral < ' src > > ,
1515 long : Option < StringLiteral < ' src > > ,
16+ #[ serde( skip) ]
17+ long_key : Option < Token < ' src > > ,
1618 name : StringLiteral < ' src > ,
1719 pattern : Option < Pattern < ' src > > ,
1820 short : Option < StringLiteral < ' src > > ,
@@ -91,7 +93,7 @@ impl<'src> Attribute<'src> {
9193 pub ( crate ) fn new (
9294 name : Name < ' src > ,
9395 arguments : Vec < StringLiteral < ' src > > ,
94- mut keyword_arguments : BTreeMap < & ' src str , ( Name < ' src > , StringLiteral < ' src > ) > ,
96+ mut keyword_arguments : BTreeMap < & ' src str , ( Name < ' src > , Option < StringLiteral < ' src > > ) > ,
9597 ) -> CompileResult < ' src , Self > {
9698 let discriminant = name
9799 . lexeme ( )
@@ -117,25 +119,29 @@ impl<'src> Attribute<'src> {
117119
118120 let attribute = match discriminant {
119121 AttributeDiscriminant :: Arg => {
120- let name = arguments. into_iter ( ) . next ( ) . unwrap ( ) ;
122+ let arg = arguments. into_iter ( ) . next ( ) . unwrap ( ) ;
121123
122- let long = keyword_arguments
124+ let ( long, long_key ) = keyword_arguments
123125 . remove ( "long" )
124- . map ( |( _name, literal) | {
125- Self :: check_option_name ( & name, & literal) ?;
126- Ok ( literal)
126+ . map ( |( name, literal) | {
127+ if let Some ( literal) = literal {
128+ Self :: check_option_name ( & arg, & literal) ?;
129+ Ok ( ( Some ( literal) , None ) )
130+ } else {
131+ Ok ( ( Some ( arg. clone ( ) ) , Some ( * name) ) )
132+ }
127133 } )
128- . transpose ( ) ?;
134+ . transpose ( ) ?
135+ . unwrap_or ( ( None , None ) ) ;
129136
130- let short = keyword_arguments
131- . remove ( "short" )
132- . map ( |( _name, literal) | {
133- Self :: check_option_name ( & name, & literal) ?;
137+ let short = Self :: remove_required ( & mut keyword_arguments, "short" ) ?
138+ . map ( |( _key, literal) | {
139+ Self :: check_option_name ( & arg, & literal) ?;
134140
135141 if literal. cooked . chars ( ) . count ( ) != 1 {
136142 return Err ( literal. token . error (
137143 CompileErrorKind :: ShortOptionWithMultipleCharacters {
138- parameter : name . cooked . clone ( ) ,
144+ parameter : arg . cooked . clone ( ) ,
139145 } ,
140146 ) ) ;
141147 }
@@ -144,29 +150,27 @@ impl<'src> Attribute<'src> {
144150 } )
145151 . transpose ( ) ?;
146152
147- let pattern = keyword_arguments
148- . remove ( "pattern" )
149- . map ( |( _name, literal) | Pattern :: new ( & literal) )
153+ let pattern = Self :: remove_required ( & mut keyword_arguments, "pattern" ) ?
154+ . map ( |( _key, literal) | Pattern :: new ( & literal) )
150155 . transpose ( ) ?;
151156
152- let value = keyword_arguments
153- . remove ( "value" )
154- . map ( |( name, literal) | {
157+ let value = Self :: remove_required ( & mut keyword_arguments, "value" ) ?
158+ . map ( |( key, literal) | {
155159 if long. is_none ( ) && short. is_none ( ) {
156- return Err ( name . error ( CompileErrorKind :: ArgAttributeValueRequiresOption ) ) ;
160+ return Err ( key . error ( CompileErrorKind :: ArgAttributeValueRequiresOption ) ) ;
157161 }
158162 Ok ( literal)
159163 } )
160164 . transpose ( ) ?;
161165
162- let help = keyword_arguments
163- . remove ( "help" )
164- . map ( |( _name, literal) | literal) ;
166+ let help =
167+ Self :: remove_required ( & mut keyword_arguments, "help" ) ?. map ( |( _key, literal) | literal) ;
165168
166169 Self :: Arg {
167170 help,
168171 long,
169- name,
172+ long_key,
173+ name : arg,
170174 pattern,
171175 short,
172176 value,
@@ -214,6 +218,20 @@ impl<'src> Attribute<'src> {
214218 Ok ( attribute)
215219 }
216220
221+ fn remove_required (
222+ keyword_arguments : & mut BTreeMap < & ' src str , ( Name < ' src > , Option < StringLiteral < ' src > > ) > ,
223+ key : & ' src str ,
224+ ) -> CompileResult < ' src , Option < ( Name < ' src > , StringLiteral < ' src > ) > > {
225+ let Some ( ( key, literal) ) = keyword_arguments. remove ( key) else {
226+ return Ok ( None ) ;
227+ } ;
228+
229+ let literal =
230+ literal. ok_or_else ( || key. error ( CompileErrorKind :: AttributeKeyMissingValue { key } ) ) ?;
231+
232+ Ok ( Some ( ( key, literal) ) )
233+ }
234+
217235 pub ( crate ) fn discriminant ( & self ) -> AttributeDiscriminant {
218236 self . into ( )
219237 }
@@ -238,6 +256,7 @@ impl Display for Attribute<'_> {
238256 Self :: Arg {
239257 help,
240258 long,
259+ long_key : _,
241260 name,
242261 pattern,
243262 short,
0 commit comments