@@ -10,18 +10,18 @@ use yansi::{Color, Paint};
1010pub enum Installable {
1111 Flake {
1212 reference : String ,
13- attribute : Vec < String > ,
13+ attribute : String ,
1414 } ,
1515 File {
1616 path : PathBuf ,
17- attribute : Vec < String > ,
17+ attribute : String ,
1818 } ,
1919 Store {
2020 path : PathBuf ,
2121 } ,
2222 Expression {
2323 expression : String ,
24- attribute : Vec < String > ,
24+ attribute : String ,
2525 } ,
2626}
2727
@@ -51,14 +51,14 @@ impl FromArgMatches for Installable {
5151 if let Some ( f) = file {
5252 return Ok ( Self :: File {
5353 path : PathBuf :: from ( f) ,
54- attribute : parse_attribute ( installable. cloned ( ) . unwrap_or_default ( ) ) ,
54+ attribute : installable. cloned ( ) . unwrap_or_default ( ) ,
5555 } ) ;
5656 }
5757
5858 if let Some ( e) = expr {
5959 return Ok ( Self :: Expression {
6060 expression : e. to_string ( ) ,
61- attribute : parse_attribute ( installable. cloned ( ) . unwrap_or_default ( ) ) ,
61+ attribute : installable. cloned ( ) . unwrap_or_default ( ) ,
6262 } ) ;
6363 }
6464
@@ -67,12 +67,10 @@ impl FromArgMatches for Installable {
6767 let reference = elems. next ( ) . unwrap ( ) . to_owned ( ) ;
6868 return Ok ( Self :: Flake {
6969 reference,
70- attribute : parse_attribute (
71- elems
72- . next ( )
73- . map ( std:: string:: ToString :: to_string)
74- . unwrap_or_default ( ) ,
75- ) ,
70+ attribute : elems
71+ . next ( )
72+ . map ( std:: string:: ToString :: to_string)
73+ . unwrap_or_default ( ) ,
7674 } ) ;
7775 }
7876
@@ -82,12 +80,10 @@ impl FromArgMatches for Installable {
8280 let mut elems = f. splitn ( 2 , '#' ) ;
8381 Installable :: Flake {
8482 reference : elems. next ( ) . unwrap ( ) . to_owned ( ) ,
85- attribute : parse_attribute (
86- elems
87- . next ( )
88- . map ( std:: string:: ToString :: to_string)
89- . unwrap_or_default ( ) ,
90- ) ,
83+ attribute : elems
84+ . next ( )
85+ . map ( std:: string:: ToString :: to_string)
86+ . unwrap_or_default ( ) ,
9187 }
9288 } )
9389 }
@@ -124,7 +120,7 @@ impl FromArgMatches for Installable {
124120 if let Ok ( f) = env:: var ( "NH_FILE" ) {
125121 return Ok ( Self :: File {
126122 path : PathBuf :: from ( f) ,
127- attribute : parse_attribute ( env:: var ( "NH_ATTRP" ) . unwrap_or_default ( ) ) ,
123+ attribute : env:: var ( "NH_ATTRP" ) . unwrap_or_default ( ) ,
128124 } ) ;
129125 }
130126
@@ -206,82 +202,35 @@ Nix accepts various kinds of installables:
206202 }
207203}
208204
209- // TODO: should handle quoted attributes, like foo."bar.baz" -> ["foo",
210- // "bar.baz"] maybe use chumsky?
211- pub fn parse_attribute < S > ( s : S ) -> Vec < String >
212- where
213- S : AsRef < str > ,
214- {
215- let s = s. as_ref ( ) ;
216- let mut res = Vec :: new ( ) ;
217-
218- if s. is_empty ( ) {
219- return res;
220- }
221-
222- let mut in_quote = false ;
223-
224- let mut elem = String :: new ( ) ;
225- for char in s. chars ( ) {
226- match char {
227- '.' => {
228- if in_quote {
229- elem. push ( char) ;
230- } else {
231- res. push ( elem. clone ( ) ) ;
232- elem = String :: new ( ) ;
233- }
234- } ,
235- '"' => {
236- in_quote = !in_quote;
237- } ,
238- _ => elem. push ( char) ,
239- }
240- }
241-
242- res. push ( elem) ;
243-
244- assert ! ( !in_quote, "Failed to parse attribute: {s}" ) ;
245-
246- res
247- }
248-
249- #[ test]
250- fn test_parse_attribute ( ) {
251- assert_eq ! ( parse_attribute( r"foo.bar" ) , vec![ "foo" , "bar" ] ) ;
252- assert_eq ! ( parse_attribute( r#"foo."bar.baz""# ) , vec![ "foo" , "bar.baz" ] ) ;
253- let v: Vec < String > = vec ! [ ] ;
254- assert_eq ! ( parse_attribute( "" ) , v) ;
255- }
256-
257205impl Installable {
258206 #[ must_use]
259207 pub fn to_args ( & self ) -> Vec < String > {
260- let mut res = Vec :: new ( ) ;
261208 match self {
262209 Self :: Flake {
263210 reference,
264211 attribute,
265212 } => {
266- res . push ( format ! ( "{reference}#{}" , join_attribute ( attribute ) ) ) ;
213+ vec ! [ format!( "{reference}#{attribute}" ) ]
267214 } ,
268215 Self :: File { path, attribute } => {
269- res. push ( String :: from ( "--file" ) ) ;
270- res. push ( path. to_str ( ) . unwrap ( ) . to_string ( ) ) ;
271- res. push ( join_attribute ( attribute) ) ;
216+ vec ! [
217+ String :: from( "--file" ) ,
218+ path. to_str( ) . unwrap( ) . to_string( ) ,
219+ attribute. to_string( ) ,
220+ ]
272221 } ,
273222 Self :: Expression {
274223 expression,
275224 attribute,
276225 } => {
277- res. push ( String :: from ( "--expr" ) ) ;
278- res. push ( expression. to_string ( ) ) ;
279- res. push ( join_attribute ( attribute) ) ;
226+ vec ! [
227+ String :: from( "--expr" ) ,
228+ expression. to_string( ) ,
229+ attribute. to_string( ) ,
230+ ]
280231 } ,
281- Self :: Store { path } => res . push ( path. to_str ( ) . unwrap ( ) . to_string ( ) ) ,
232+ Self :: Store { path } => vec ! [ path. to_str( ) . unwrap( ) . to_string( ) ] ,
282233 }
283-
284- res
285234 }
286235}
287236
@@ -306,38 +255,6 @@ fn test_installable_to_args() {
306255 ) ;
307256}
308257
309- fn join_attribute < I > ( attribute : I ) -> String
310- where
311- I : IntoIterator ,
312- I :: Item : AsRef < str > ,
313- {
314- let mut res = String :: new ( ) ;
315- let mut first = true ;
316- for elem in attribute {
317- if first {
318- first = false ;
319- } else {
320- res. push ( '.' ) ;
321- }
322-
323- let s = elem. as_ref ( ) ;
324-
325- if s. contains ( '.' ) {
326- res. push_str ( & format ! ( r#""{s}""# ) ) ;
327- } else {
328- res. push_str ( s) ;
329- }
330- }
331-
332- res
333- }
334-
335- #[ test]
336- fn test_join_attribute ( ) {
337- assert_eq ! ( join_attribute( vec![ "foo" , "bar" ] ) , "foo.bar" ) ;
338- assert_eq ! ( join_attribute( vec![ "foo" , "bar.baz" ] ) , r#"foo."bar.baz""# ) ;
339- }
340-
341258impl Installable {
342259 #[ must_use]
343260 pub const fn str_kind ( & self ) -> & str {
0 commit comments