@@ -3,8 +3,9 @@ use std::borrow::Cow;
3/// Get the vec of escaped / quoted / doublequoted filenames from the input str
3/// Get the vec of escaped / quoted / doublequoted filenames from the input str
4pub fn shellwords(input: &str) -> Vec<Cow<'_, str>> {
4pub fn shellwords(input: &str) -> Vec<Cow<'_, str>> {
5 enum State {
5 enum State {
6− Normal,
6+ OnWhitespace,
7− NormalEscaped,
7+ Unquoted,
9 QuoteEscaped,
10 QuoteEscaped,
@@ -13,7 +14,7 @@ pub fn shellwords(input: &str) -> Vec<Cow<'_, str>> {
14 use State::*;
15 use State::*;
16− let mut state = Normal;
17+ let mut state = Unquoted;
17 let mut args: Vec<Cow<str>> = Vec::new();
18 let mut args: Vec<Cow<str>> = Vec::new();
18 let mut escaped = String::with_capacity(input.len());
19 let mut escaped = String::with_capacity(input.len());
@@ -22,31 +23,47 @@ pub fn shellwords(input: &str) -> Vec<Cow<'_, str>> {
23 for (i, c) in input.char_indices() {
24 for (i, c) in input.char_indices() {
24 state = match state {
25 state = match state {
25− Normal => match c {
26+ OnWhitespace => match c {
27 if cfg!(unix) {
36 if cfg!(unix) {
28 escaped.push_str(&input[start..i]);
37 escaped.push_str(&input[start..i]);
29 start = i + 1;
38 start = i + 1;
30− NormalEscaped
39+ UnquotedEscaped
32− Normal
41+ OnWhitespace
35− '"' => {
44+ c if c.is_ascii_whitespace() => {
37− Dquoted
46+ OnWhitespace
50+ Unquoted => match c {
39− '\'' => {
51+ '\\' => {
40− end = i;
52+ if cfg!(unix) {
41− Quoted
53+ escaped.push_str(&input[start..i]);
43 c if c.is_ascii_whitespace() => {
60 c if c.is_ascii_whitespace() => {
45− Normal
62+ OnWhitespace
47− _ => Normal,
64+ _ => Unquoted,
49− NormalEscaped => Normal,
66+ UnquotedEscaped => Unquoted,
50 Quoted => match c {
67 Quoted => match c {
52 if cfg!(unix) {
69 if cfg!(unix) {
@@ -59,7 +76,7 @@ pub fn shellwords(input: &str) -> Vec<Cow<'_, str>> {
62− Normal
79+ OnWhitespace
64 _ => Quoted,
81 _ => Quoted,
@@ -76,7 +93,7 @@ pub fn shellwords(input: &str) -> Vec<Cow<'_, str>> {
79− Normal
96+ OnWhitespace
81 _ => Dquoted,
98 _ => Dquoted,
@@ -195,4 +212,18 @@ mod test {
196 assert_eq!(expected, result);
213 assert_eq!(expected, result);
219+ r#":set statusline.center ["file-type","file-encoding"] '["list", "in", "qoutes"]'"#;
220+ let result = shellwords(input);
221+ let expected = vec![
223+ Cow::from("statusline.center"),
224+ Cow::from(r#"["file-type","file-encoding"]"#),
225+ Cow::from(r#"["list", "in", "qoutes"]"#),
227+ assert_eq!(expected, result);