@@ -3,8 +3,9 @@ use std::borrow::Cow;
3
3
/// Get the vec of escaped / quoted / doublequoted filenames from the input str
4
4
pub fn shellwords ( input : & str ) -> Vec < Cow < ' _ , str > > {
5
5
enum State {
6
- Normal ,
7
- NormalEscaped ,
6
+ OnWhitespace ,
7
+ Unquoted ,
8
+ UnquotedEscaped ,
8
9
Quoted ,
9
10
QuoteEscaped ,
10
11
Dquoted ,
@@ -13,7 +14,7 @@ pub fn shellwords(input: &str) -> Vec<Cow<'_, str>> {
13
14
14
15
use State :: * ;
15
16
16
- let mut state = Normal ;
17
+ let mut state = Unquoted ;
17
18
let mut args: Vec < Cow < str > > = Vec :: new ( ) ;
18
19
let mut escaped = String :: with_capacity ( input. len ( ) ) ;
19
20
@@ -22,31 +23,47 @@ pub fn shellwords(input: &str) -> Vec<Cow<'_, str>> {
22
23
23
24
for ( i, c) in input. char_indices ( ) {
24
25
state = match state {
25
- Normal => match c {
26
+ OnWhitespace => match c {
27
+ '"' => {
28
+ end = i;
29
+ Dquoted
30
+ }
31
+ '\'' => {
32
+ end = i;
33
+ Quoted
34
+ }
26
35
'\\' => {
27
36
if cfg ! ( unix) {
28
37
escaped. push_str ( & input[ start..i] ) ;
29
38
start = i + 1 ;
30
- NormalEscaped
39
+ UnquotedEscaped
31
40
} else {
32
- Normal
41
+ OnWhitespace
33
42
}
34
43
}
35
- '"' => {
44
+ c if c . is_ascii_whitespace ( ) => {
36
45
end = i;
37
- Dquoted
46
+ OnWhitespace
38
47
}
39
- '\'' => {
40
- end = i;
41
- Quoted
48
+ _ => Unquoted ,
49
+ } ,
50
+ Unquoted => match c {
51
+ '\\' => {
52
+ if cfg ! ( unix) {
53
+ escaped. push_str ( & input[ start..i] ) ;
54
+ start = i + 1 ;
55
+ UnquotedEscaped
56
+ } else {
57
+ Unquoted
58
+ }
42
59
}
43
60
c if c. is_ascii_whitespace ( ) => {
44
61
end = i;
45
- Normal
62
+ OnWhitespace
46
63
}
47
- _ => Normal ,
64
+ _ => Unquoted ,
48
65
} ,
49
- NormalEscaped => Normal ,
66
+ UnquotedEscaped => Unquoted ,
50
67
Quoted => match c {
51
68
'\\' => {
52
69
if cfg ! ( unix) {
@@ -59,7 +76,7 @@ pub fn shellwords(input: &str) -> Vec<Cow<'_, str>> {
59
76
}
60
77
'\'' => {
61
78
end = i;
62
- Normal
79
+ OnWhitespace
63
80
}
64
81
_ => Quoted ,
65
82
} ,
@@ -76,7 +93,7 @@ pub fn shellwords(input: &str) -> Vec<Cow<'_, str>> {
76
93
}
77
94
'"' => {
78
95
end = i;
79
- Normal
96
+ OnWhitespace
80
97
}
81
98
_ => Dquoted ,
82
99
} ,
@@ -195,4 +212,18 @@ mod test {
195
212
] ;
196
213
assert_eq ! ( expected, result) ;
197
214
}
215
+
216
+ #[ test]
217
+ fn test_lists ( ) {
218
+ let input =
219
+ r#":set statusline.center ["file-type","file-encoding"] '["list", "in", "qoutes"]'"# ;
220
+ let result = shellwords ( input) ;
221
+ let expected = vec ! [
222
+ Cow :: from( ":set" ) ,
223
+ Cow :: from( "statusline.center" ) ,
224
+ Cow :: from( r#"["file-type","file-encoding"]"# ) ,
225
+ Cow :: from( r#"["list", "in", "qoutes"]"# ) ,
226
+ ] ;
227
+ assert_eq ! ( expected, result) ;
228
+ }
198
229
}
0 commit comments