58 lines
1.1 KiB
Go
58 lines
1.1 KiB
Go
package service
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"unicode"
|
|
)
|
|
|
|
// shlexSplit splits s into shell-like words, honoring single and double
|
|
// quotes. Small hand-rolled equivalent of Python's shlex.split (used by
|
|
// macos_service_wrapper.py / service_manager.py to parse the free-form
|
|
// service Args string), avoiding an extra third-party dependency.
|
|
func shlexSplit(s string) ([]string, error) {
|
|
var words []string
|
|
var current strings.Builder
|
|
inWord := false
|
|
|
|
runes := []rune(s)
|
|
i := 0
|
|
for i < len(runes) {
|
|
r := runes[i]
|
|
switch {
|
|
case r == '\'' || r == '"':
|
|
quote := r
|
|
i++
|
|
closed := false
|
|
for i < len(runes) {
|
|
if runes[i] == quote {
|
|
closed = true
|
|
i++
|
|
break
|
|
}
|
|
current.WriteRune(runes[i])
|
|
i++
|
|
}
|
|
if !closed {
|
|
return nil, fmt.Errorf("no closing quotation")
|
|
}
|
|
inWord = true
|
|
case unicode.IsSpace(r):
|
|
if inWord {
|
|
words = append(words, current.String())
|
|
current.Reset()
|
|
inWord = false
|
|
}
|
|
i++
|
|
default:
|
|
current.WriteRune(r)
|
|
inWord = true
|
|
i++
|
|
}
|
|
}
|
|
if inWord {
|
|
words = append(words, current.String())
|
|
}
|
|
return words, nil
|
|
}
|