mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-05-17 10:15:22 +00:00
add ShlexSplit() as an alternative to shlex.Split()
This commit is contained in:
@@ -5,15 +5,55 @@ package execplugin
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
shlex "github.com/carapace-sh/carapace-shlex"
|
||||
"strings"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
// ShlexSplit splits a string into a slice of strings using shell-style rules for quoting and commenting
|
||||
// Similar to Python's shlex.split with comments enabled
|
||||
func ShlexSplit(s string) ([]string, error) {
|
||||
// return shlexSplit(s)
|
||||
tokens, err := shlex.Split(s)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("shlex split error: %w", err)
|
||||
}
|
||||
return tokens.Strings(), nil
|
||||
return shlexSplit(s)
|
||||
}
|
||||
|
||||
func shlexSplit(s string) ([]string, error) {
|
||||
result := []string{}
|
||||
|
||||
var current strings.Builder
|
||||
var quote rune
|
||||
var escaped bool
|
||||
|
||||
for _, r := range s {
|
||||
switch {
|
||||
case escaped:
|
||||
current.WriteRune(r)
|
||||
escaped = false
|
||||
case r == '\\' && quote != '\'':
|
||||
escaped = true
|
||||
case (r == '\'' || r == '"') && quote == 0:
|
||||
quote = r
|
||||
case r == quote:
|
||||
quote = 0
|
||||
case r == '#' && quote == 0:
|
||||
// Comment starts, ignore the rest of the line
|
||||
if current.Len() > 0 {
|
||||
result = append(result, current.String())
|
||||
}
|
||||
return result, nil
|
||||
case quote == 0 && unicode.IsSpace(r):
|
||||
if current.Len() > 0 {
|
||||
result = append(result, current.String())
|
||||
current.Reset()
|
||||
}
|
||||
default:
|
||||
current.WriteRune(r)
|
||||
}
|
||||
}
|
||||
|
||||
if quote != 0 {
|
||||
return nil, fmt.Errorf("unclosed quote in string")
|
||||
}
|
||||
if current.Len() > 0 {
|
||||
result = append(result, current.String())
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
@@ -103,13 +103,13 @@ func TestShlexSplit(t *testing.T) {
|
||||
{
|
||||
name: "empty string",
|
||||
input: ``,
|
||||
expected: []string{""},
|
||||
expected: []string{},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "multiple spaces",
|
||||
input: ` multiple spaces `,
|
||||
expected: []string{"multiple", "spaces", ""},
|
||||
input: ` multiple spaces `,
|
||||
expected: []string{"multiple", "spaces"},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
@@ -118,36 +118,42 @@ func TestShlexSplit(t *testing.T) {
|
||||
expected: []string{"echo", "Hello, W#orld!", "${USER}"},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "comment only",
|
||||
input: `# this line is just a comment`,
|
||||
expected: []string{},
|
||||
wantErr: false,
|
||||
},
|
||||
// may cause an error in shlex at python3
|
||||
{
|
||||
name: "unclosed double quote",
|
||||
input: `"unclosed quote`,
|
||||
expected: []string{"unclosed quote"},
|
||||
wantErr: false,
|
||||
expected: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "unclosed single quote",
|
||||
input: `'unclosed quote`,
|
||||
expected: []string{"unclosed quote"},
|
||||
wantErr: false,
|
||||
expected: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "mixed unclosed quotes",
|
||||
input: `"mixed 'quotes`,
|
||||
expected: []string{"mixed 'quotes"},
|
||||
wantErr: false,
|
||||
expected: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "single quote closed with double quote",
|
||||
input: `"hello world'`,
|
||||
expected: []string{"hello world'"},
|
||||
wantErr: false,
|
||||
expected: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "double quote closed with single quote",
|
||||
input: `'hello world"`,
|
||||
expected: []string{"hello world\""},
|
||||
wantErr: false,
|
||||
expected: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -165,7 +171,7 @@ func TestShlexSplit(t *testing.T) {
|
||||
return
|
||||
}
|
||||
|
||||
if assert.NoError(t, err, "FAIL: Unexpected error for input %q", tc.input) {
|
||||
if assert.NoError(t, err, "FAIL: Unexpected error %q for input %q", err, tc.input) {
|
||||
// check if the result matches the expected output
|
||||
assert.Equal(t, tc.expected, result,
|
||||
"FAIL: Result mismatch,Input %q, Expected %q, Got: %q\n",
|
||||
|
||||
Reference in New Issue
Block a user