@ -3,8 +3,9 @@ use std::borrow::Cow;
/// Get the vec of escaped / quoted / doublequoted filenames from the input str
/// Get the vec of escaped / quoted / doublequoted filenames from the input str
pub fn shellwords ( input : & str ) -> Vec < Cow < ' _ , str > > {
pub fn shellwords ( input : & str ) -> Vec < Cow < ' _ , str > > {
enum State {
enum State {
Normal ,
OnWhitespace ,
NormalEscaped ,
Unquoted ,
UnquotedEscaped ,
Quoted ,
Quoted ,
QuoteEscaped ,
QuoteEscaped ,
Dquoted ,
Dquoted ,
@ -13,7 +14,7 @@ pub fn shellwords(input: &str) -> Vec<Cow<'_, str>> {
use State ::* ;
use State ::* ;
let mut state = Normal ;
let mut state = Unquoted ;
let mut args : Vec < Cow < str > > = Vec ::new ( ) ;
let mut args : Vec < Cow < str > > = Vec ::new ( ) ;
let mut escaped = String ::with_capacity ( input . len ( ) ) ;
let mut escaped = String ::with_capacity ( input . len ( ) ) ;
@ -22,31 +23,47 @@ pub fn shellwords(input: &str) -> Vec<Cow<'_, str>> {
for ( i , c ) in input . char_indices ( ) {
for ( i , c ) in input . char_indices ( ) {
state = match state {
state = match state {
Normal = > match c {
OnWhitespace = > match c {
'"' = > {
end = i ;
Dquoted
}
'\'' = > {
end = i ;
Quoted
}
'\\' = > {
'\\' = > {
if cfg! ( unix ) {
if cfg! ( unix ) {
escaped . push_str ( & input [ start .. i ] ) ;
escaped . push_str ( & input [ start .. i ] ) ;
start = i + 1 ;
start = i + 1 ;
NormalEscaped
Unquoted Escaped
} else {
} else {
Normal
OnWhitespace
}
}
}
}
'"' = > {
c if c . is_ascii_whitespace ( ) = > {
end = i ;
end = i ;
Dquoted
OnWhitespace
}
}
'\'' = > {
_ = > Unquoted ,
end = i ;
} ,
Quoted
Unquoted = > match c {
'\\' = > {
if cfg! ( unix ) {
escaped . push_str ( & input [ start .. i ] ) ;
start = i + 1 ;
UnquotedEscaped
} else {
Unquoted
}
}
}
c if c . is_ascii_whitespace ( ) = > {
c if c . is_ascii_whitespace ( ) = > {
end = i ;
end = i ;
Normal
OnWhitespace
}
}
_ = > Normal ,
_ = > Unquoted ,
} ,
} ,
NormalEscaped = > Normal ,
UnquotedEscaped = > Unquoted ,
Quoted = > match c {
Quoted = > match c {
'\\' = > {
'\\' = > {
if cfg! ( unix ) {
if cfg! ( unix ) {
@ -59,7 +76,7 @@ pub fn shellwords(input: &str) -> Vec<Cow<'_, str>> {
}
}
'\'' = > {
'\'' = > {
end = i ;
end = i ;
Normal
OnWhitespace
}
}
_ = > Quoted ,
_ = > Quoted ,
} ,
} ,
@ -76,7 +93,7 @@ pub fn shellwords(input: &str) -> Vec<Cow<'_, str>> {
}
}
'"' = > {
'"' = > {
end = i ;
end = i ;
Normal
OnWhitespace
}
}
_ = > Dquoted ,
_ = > Dquoted ,
} ,
} ,
@ -195,4 +212,18 @@ mod test {
] ;
] ;
assert_eq! ( expected , result ) ;
assert_eq! ( expected , result ) ;
}
}
#[ test ]
fn test_lists ( ) {
let input =
r#":set statusline.center ["file-type","file-encoding"] '["list", "in", "qoutes"]'"# ;
let result = shellwords ( input ) ;
let expected = vec! [
Cow ::from ( ":set" ) ,
Cow ::from ( "statusline.center" ) ,
Cow ::from ( r#"["file-type","file-encoding"]"# ) ,
Cow ::from ( r#"["list", "in", "qoutes"]"# ) ,
] ;
assert_eq! ( expected , result ) ;
}
}
}