mirror of
https://github.com/gechandesu/shellish.git
synced 2026-10-04 16:36:47 +03:00
fix remaining tests, bump version
This commit is contained in:
+48
-9
@@ -8,7 +8,7 @@ pub const safe_chars = '%+,-./0123456789:=@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghij
|
||||
// special_chars contains ASCII characters that must be escaped in shell.
|
||||
pub const special_chars = ' \$"\'\\!'
|
||||
|
||||
const special_chars_runes = [` `, `$`, `"`, `'`, `\``, `\\`, `!`]
|
||||
const special_chars_runes = [` `, `$`, `"`, `'`, `\``, `\\`, `!`]!
|
||||
|
||||
// quote returns a quoted version of string `s`.
|
||||
//
|
||||
@@ -163,12 +163,14 @@ fn parse(line string) ![]string {
|
||||
mut single_quoted := false
|
||||
mut double_quoted := false
|
||||
mut back_quoted := false
|
||||
mut dollar_quoted := false
|
||||
mut dollar_depth := 0
|
||||
mut commented := false
|
||||
|
||||
mut got := Mode.no
|
||||
|
||||
for i, c in line {
|
||||
mut r := c
|
||||
dollar_quoted := dollar_depth > 0
|
||||
|
||||
if escaped {
|
||||
if r == `t` {
|
||||
@@ -177,8 +179,14 @@ fn parse(line string) ![]string {
|
||||
if r == `n` {
|
||||
r = `\n`
|
||||
}
|
||||
buf << r
|
||||
escaped = false
|
||||
if commented {
|
||||
if r == `\n` {
|
||||
commented = false
|
||||
}
|
||||
continue
|
||||
}
|
||||
buf << r
|
||||
got = .normal
|
||||
continue
|
||||
}
|
||||
@@ -199,6 +207,36 @@ fn parse(line string) ![]string {
|
||||
continue
|
||||
}
|
||||
|
||||
if commented {
|
||||
if r == `\n` {
|
||||
commented = false
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if r == `#` && !single_quoted && !double_quoted && !back_quoted && !dollar_quoted {
|
||||
// Everything up to the end of the line is a comment. The word being
|
||||
// accumulated, if any, is terminated by it.
|
||||
if got != .no {
|
||||
tokens << buf.bytestr()
|
||||
buf = []u8{}
|
||||
got = .no
|
||||
}
|
||||
commented = true
|
||||
continue
|
||||
}
|
||||
|
||||
if r == `;` && !single_quoted && !double_quoted && !back_quoted && !dollar_quoted {
|
||||
// Command separator is a token on its own.
|
||||
if got != .no {
|
||||
tokens << buf.bytestr()
|
||||
buf = []u8{}
|
||||
}
|
||||
tokens << ';'
|
||||
got = .no
|
||||
continue
|
||||
}
|
||||
|
||||
if r.is_space() {
|
||||
if single_quoted || double_quoted || back_quoted || dollar_quoted {
|
||||
buf << r
|
||||
@@ -217,17 +255,18 @@ fn parse(line string) ![]string {
|
||||
}
|
||||
}
|
||||
`(` {
|
||||
if !single_quoted && !double_quoted && !dollar_quoted {
|
||||
if !dollar_quoted && buf.len - 1 >= 0 && buf[buf.len - 1..][0] == `$` {
|
||||
dollar_quoted = true
|
||||
if !single_quoted && !double_quoted {
|
||||
// Opens a `$(` expression or nests inside an already opened one.
|
||||
if dollar_quoted || (buf.len > 0 && buf.last() == `$`) {
|
||||
dollar_depth++
|
||||
buf << r
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
`)` {
|
||||
if !single_quoted && !double_quoted && !dollar_quoted {
|
||||
dollar_quoted = false
|
||||
if !single_quoted && !double_quoted && dollar_quoted {
|
||||
dollar_depth--
|
||||
}
|
||||
}
|
||||
`"` {
|
||||
@@ -264,7 +303,7 @@ fn parse(line string) ![]string {
|
||||
single_quoted { return error('non-terminated quote in string') }
|
||||
double_quoted { return error('non-terminated double quote in string') }
|
||||
back_quoted { return error('non-terminated backtick in string') }
|
||||
dollar_quoted { return error('non-terminated dollar expression in string') }
|
||||
dollar_depth > 0 { return error('non-terminated dollar expression in string') }
|
||||
else {}
|
||||
}
|
||||
|
||||
|
||||
+4
-5
@@ -30,7 +30,6 @@ fn test_strip_ansi_escape_codes() {
|
||||
}
|
||||
|
||||
// Original test data taken from https://github.com/python/cpython/blob/3.14/Lib/test/test_shlex.py
|
||||
// FIXME: All test-cases must pass.
|
||||
// vfmt off
|
||||
const test_data = {
|
||||
'foo': ['foo']
|
||||
@@ -90,10 +89,10 @@ const test_data = {
|
||||
'":-) ;-)"': [':-) ;-)']
|
||||
'foo `bar baz`': ['foo', '`bar baz`']
|
||||
r'foo "$(bar baz)"': ['foo', r'$(bar baz)']
|
||||
// r'foo $(bar)': ['foo', r'$(bar)'] // failing
|
||||
// r'foo $(bar baz)': ['foo', r'$(bar baz)'] // failing
|
||||
// r'foo#bar\nbaz': ['foo', 'baz'] // failing
|
||||
// 'foo;bar': ['foo', ';', 'bar'] // failing
|
||||
r'foo $(bar)': ['foo', r'$(bar)']
|
||||
r'foo $(bar baz)': ['foo', r'$(bar baz)']
|
||||
r'foo#bar\nbaz': ['foo', 'baz']
|
||||
'foo;bar': ['foo', ';', 'bar']
|
||||
|
||||
'"foo\\\\\\x bar\\" df\'a\\ \'df"': ['foo\\\\x bar" df\'a\\ \'df']
|
||||
'"foo\\ x\\x\\\\"\\\'"foobar"': [r"foo\ x\x\'foobar"]
|
||||
|
||||
Reference in New Issue
Block a user