@@ -2,6 +2,7 @@ use crate::parser::{ParseArg, Parser};
22use proc_macro2:: { token_stream, Delimiter , Ident , Literal , Span , TokenStream , TokenTree } ;
33use proc_macro_error:: abort;
44use quote:: quote;
5+ use std:: ffi:: OsString ;
56use std:: iter:: Peekable ;
67
78// Scan string literal to tokenstream, used by most of the macros
@@ -13,18 +14,18 @@ use std::iter::Peekable;
1314pub fn scan_str_lit ( lit : & Literal ) -> TokenStream {
1415 let s = lit. to_string ( ) ;
1516 if !s. starts_with ( '\"' ) {
16- return quote ! ( #lit) ;
17+ return quote ! ( :: cmd_lib :: CmdString :: default ( ) . append ( & #lit. to_owned ( ) ) ) ;
1718 }
1819 let mut iter = s[ 1 ..s. len ( ) - 1 ] // To trim outside ""
1920 . chars ( )
2021 . peekable ( ) ;
21- let mut output = quote ! ( "" ) ;
22- let mut last_part = String :: new ( ) ;
23- fn seal_last_part ( last_part : & mut String , output : & mut TokenStream ) {
22+ let mut output = quote ! ( :: cmd_lib :: CmdString :: default ( ) ) ;
23+ let mut last_part = OsString :: new ( ) ;
24+ fn seal_last_part ( last_part : & mut OsString , output : & mut TokenStream ) {
2425 if !last_part. is_empty ( ) {
25- let lit_str = format ! ( "\" {}\" " , last_part) ;
26+ let lit_str = format ! ( "\" {}\" " , last_part. to_str ( ) . unwrap ( ) ) ;
2627 let l = syn:: parse_str :: < Literal > ( & lit_str) . unwrap ( ) ;
27- output. extend ( quote ! ( + #l ) ) ;
28+ output. extend ( quote ! ( . append ( & #l ) ) ) ;
2829 last_part. clear ( ) ;
2930 }
3031 }
@@ -33,7 +34,7 @@ pub fn scan_str_lit(lit: &Literal) -> TokenStream {
3334 if ch == '$' {
3435 if iter. peek ( ) == Some ( & '$' ) {
3536 iter. next ( ) ;
36- last_part. push ( '$' ) ;
37+ last_part. push ( "$" ) ;
3738 continue ;
3839 }
3940
@@ -63,12 +64,12 @@ pub fn scan_str_lit(lit: &Literal) -> TokenStream {
6364 }
6465 if !var. is_empty ( ) {
6566 let var = syn:: parse_str :: < Ident > ( & var) . unwrap ( ) ;
66- output. extend ( quote ! ( + & #var. to_string ( ) ) ) ;
67+ output. extend ( quote ! ( . append ( & #var. to_owned ( ) ) ) ) ;
6768 } else {
68- output. extend ( quote ! ( + "$" ) ) ;
69+ output. extend ( quote ! ( . append ( & "$" ) ) ) ;
6970 }
7071 } else {
71- last_part. push ( ch) ;
72+ last_part. push ( ch. to_string ( ) ) ;
7273 }
7374 }
7475 seal_last_part ( & mut last_part, & mut output) ;
@@ -123,7 +124,7 @@ impl Lexer {
123124 }
124125 TokenTree :: Ident ( ident) => {
125126 let s = ident. to_string ( ) ;
126- self . extend_last_arg ( quote ! ( #s) ) ;
127+ self . extend_last_arg ( quote ! ( & #s) ) ;
127128 }
128129 TokenTree :: Punct ( punct) => {
129130 let ch = punct. as_char ( ) ;
@@ -142,7 +143,7 @@ impl Lexer {
142143 self . scan_dollar ( ) ;
143144 } else {
144145 let s = ch. to_string ( ) ;
145- self . extend_last_arg ( quote ! ( #s) ) ;
146+ self . extend_last_arg ( quote ! ( & #s) ) ;
146147 }
147148 }
148149 }
@@ -200,9 +201,9 @@ impl Lexer {
200201
201202 fn extend_last_arg ( & mut self , stream : TokenStream ) {
202203 if self . last_arg_str . is_empty ( ) {
203- self . last_arg_str = quote ! ( String :: new ( ) ) ;
204+ self . last_arg_str = quote ! ( :: cmd_lib :: CmdString :: default ( ) ) ;
204205 }
205- self . last_arg_str . extend ( quote ! ( + #stream) ) ;
206+ self . last_arg_str . extend ( quote ! ( . append ( #stream) ) ) ;
206207 }
207208
208209 fn check_set_redirect ( redirect : & mut bool , name : & str , span : Span ) {
@@ -236,7 +237,8 @@ impl Lexer {
236237 let s = lit. to_string ( ) ;
237238 if s. starts_with ( '\"' ) || s. starts_with ( 'r' ) {
238239 // string literal
239- self . extend_last_arg ( scan_str_lit ( & lit) ) ;
240+ let ss = scan_str_lit ( & lit) ;
241+ self . extend_last_arg ( quote ! ( & #ss) ) ;
240242 } else {
241243 let mut is_redirect = false ;
242244 if s == "1" || s == "2" {
@@ -249,7 +251,7 @@ impl Lexer {
249251 }
250252 }
251253 if !is_redirect {
252- self . extend_last_arg ( quote ! ( #s) ) ;
254+ self . extend_last_arg ( quote ! ( & #s) ) ;
253255 }
254256 }
255257 }
@@ -363,7 +365,7 @@ impl Lexer {
363365 let peek_no_gap = self . iter . peek_no_gap ( ) . map ( |tt| tt. to_owned ( ) ) ;
364366 // let peek_no_gap = None;
365367 if let Some ( TokenTree :: Ident ( var) ) = peek_no_gap {
366- self . extend_last_arg ( quote ! ( & #var. to_string ( ) ) ) ;
368+ self . extend_last_arg ( quote ! ( & #var. to_owned ( ) ) ) ;
367369 } else if let Some ( TokenTree :: Group ( g) ) = peek_no_gap {
368370 if g. delimiter ( ) != Delimiter :: Brace && g. delimiter ( ) != Delimiter :: Bracket {
369371 abort ! (
@@ -380,7 +382,7 @@ impl Lexer {
380382 abort ! ( span, "more than one variable in grouping" ) ;
381383 }
382384 if g. delimiter ( ) == Delimiter :: Brace {
383- self . extend_last_arg ( quote ! ( & #var. to_string ( ) ) ) ;
385+ self . extend_last_arg ( quote ! ( & #var. to_owned ( ) ) ) ;
384386 } else {
385387 if !self . last_arg_str . is_empty ( ) {
386388 abort ! ( span, "vector variable can only be used alone" ) ;
0 commit comments