1
0
Fork 0
mirror of https://github.com/diamondburned/arikawa.git synced 2025-03-23 10:29:30 +00:00

Shellwords: Simpler error and implementation

This commit is contained in:
diamondburned 2020-12-19 18:02:31 -08:00
parent 3e2814748f
commit e0f051b4c6
2 changed files with 25 additions and 42 deletions

View file

@ -1,48 +1,35 @@
package shellwords package shellwords
import ( import (
"fmt"
"strings" "strings"
) )
// WordOffset is the offset from the position cursor to print on the error.
const WordOffset = 7
var escaper = strings.NewReplacer( var escaper = strings.NewReplacer(
"`", "\\`", "__", "\\_\\_",
"@", "\\@",
"\\", "\\\\", "\\", "\\\\",
) )
type ErrParse struct { // ErrMissingClose is returned when the parsed line is missing a closing quote.
type ErrMissingClose struct {
Position int Position int
Words string // joined Words string // joined
} }
func (e ErrParse) Error() string { func (e ErrMissingClose) Error() string {
// Magic number 5. // Underline 7 characters around.
var a = max(0, e.Position-WordOffset) var start = e.Position
var b = min(len(e.Words), e.Position+WordOffset)
var word = e.Words[a:b]
var uidx = e.Position - a
errstr := strings.Builder{} errstr := strings.Builder{}
errstr.WriteString("Unexpected quote or escape") errstr.WriteString("missing quote close")
// Do a bound check. if e.Words[start:] != "" {
if uidx+1 > len(word) { errstr.WriteString(": ")
// Invalid. errstr.WriteString(escaper.Replace(e.Words[:start]))
errstr.WriteString(".") errstr.WriteString("__")
return errstr.String() errstr.WriteString(escaper.Replace(e.Words[start:]))
errstr.WriteString("__")
} }
// Write the pre-underline part.
fmt.Fprintf(
&errstr, ": %s__%s__",
escaper.Replace(word[:uidx]),
escaper.Replace(string(word[uidx:])),
)
return errstr.String() return errstr.String()
} }
@ -117,7 +104,7 @@ func Parse(line string) ([]string, error) {
} }
if escaped || singleQuoted || doubleQuoted { if escaped || singleQuoted || doubleQuoted {
return args, &ErrParse{ return args, ErrMissingClose{
Position: cursor + buf.Len(), Position: cursor + buf.Len(),
Words: strings.Join(args, " "), Words: strings.Join(args, " "),
} }
@ -133,17 +120,3 @@ func isSpace(r rune) bool {
} }
return false return false
} }
func min(i, j int) int {
if i < j {
return i
}
return j
}
func max(i, j int) int {
if i < j {
return j
}
return i
}

View file

@ -14,7 +14,17 @@ type wordsTest struct {
func TestParse(t *testing.T) { func TestParse(t *testing.T) {
var tests = []wordsTest{ var tests = []wordsTest{
{ {
`this is a "test"`, "",
nil,
false,
},
{
"'",
nil,
true,
},
{
`this is a "te""st"`,
[]string{"this", "is", "a", "test"}, []string{"this", "is", "a", "test"},
false, false,
}, },