~rjarry/public-inbox

This thread contains a patchset. You're looking at the original emails, but you may wish to use the patch review UI. Review patch
1

[PATCH go-opt] shlex: cosmetic changes

Details
Message ID
<20240402223512.1957773-1-robin@jarry.cc>
DKIM signature
pass
Download raw message
Patch: +87 -85
Rename constants to upper case with less confusing terminology.

Signed-off-by: Robin Jarry <robin@jarry.cc>
---
 args.go  |  11 ++--
 shlex.go | 161 ++++++++++++++++++++++++++++---------------------------
 2 files changed, 87 insertions(+), 85 deletions(-)

diff --git a/args.go b/args.go
index 6d093e31a760..d661052fcfb6 100644
--- a/args.go
+++ b/args.go
@@ -69,7 +69,7 @@ func (a *Args) ShiftSafe(n int) ([]string, error) {
	switch {
	case n == 0:
		shifted = []string{}
	case n >= 0 && n < len(a.infos):
	case n > 0 && n < len(a.infos):
		for i := 0; i < n; i++ {
			shifted = append(shifted, a.infos[i].unquoted)
		}
@@ -109,7 +109,7 @@ func (a *Args) CutSafe(n int) ([]string, error) {
	switch {
	case n == 0:
		cut = []string{}
	case n >= 0 && n < len(a.infos):
	case n > 0 && n < len(a.infos):
		for i := len(a.infos) - n; i < len(a.infos); i++ {
			cut = append(cut, a.infos[i].unquoted)
		}
@@ -192,17 +192,14 @@ func (a *Args) Arg(n int) string {
// Get all arguments after interpreting shell quotes.
func (a *Args) Args() []string {
	args := make([]string, 0, len(a.infos))
	for n := 0; n < len(a.infos); n++ {
		args = append(args, a.infos[n].unquoted)
	for i := range a.infos {
		args = append(args, a.infos[i].unquoted)
	}
	return args
}

// Get the raw command line, with uninterpreted shell quotes.
func (a *Args) String() string {
	if len(a.infos) == 0 {
		return ""
	}
	return string(a.raw)
}

diff --git a/shlex.go b/shlex.go
index 348984d0857d..59c766c1c3a8 100644
--- a/shlex.go
+++ b/shlex.go
@@ -14,7 +14,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

// The following changes are licensed under the MIT license:
// The following changes are published under the MIT license:
//
//  * Internal variables renamed
//  * Recording of the original argument start position in the string
@@ -34,23 +34,23 @@ import (
type runeClass int

const (
	otherRuneClass runeClass = iota
	spaceRuneClass
	escapingQuoteRuneClass
	nonEscapingQuoteRuneClass
	escapeRuneClass
	commentRuneClass
	other runeClass = iota
	space
	doubleQuote
	singleQuote
	backslash
	comment
)

var runeClasses = map[rune]runeClass{
	' ':  spaceRuneClass,
	'\t': spaceRuneClass,
	'\r': spaceRuneClass,
	'\n': spaceRuneClass,
	'"':  escapingQuoteRuneClass,
	'\'': nonEscapingQuoteRuneClass,
	'\\': escapeRuneClass,
	'#':  commentRuneClass,
	' ':  space,
	'\t': space,
	'\r': space,
	'\n': space,
	'"':  doubleQuote,
	'\'': singleQuote,
	'\\': backslash,
	'#':  comment,
}

// the internal state used by the lexer state machine
@@ -59,19 +59,19 @@ type lexerState int
// Lexer state machine states
const (
	// no runes have been seen
	startState lexerState = iota
	start lexerState = iota
	// processing regular runes in a word
	inWordState
	inWord
	// we have just consumed an escape rune; the next rune is literal
	escapingState
	escaping
	// we have just consumed an escape rune within a quoted string
	escapingQuotedState
	escapingQuoted
	// we are within a quoted string that supports escaping ("...")
	quotingEscapingState
	inDoubleQuote
	// we are within a string that does not support escaping ('...')
	quotingState
	inSingleQuote
	// we are within a comment (everything following an unquoted or unescaped #
	commentState
	inComment
)

// Each argument info contains the start offset of the raw argument in the
@@ -84,76 +84,81 @@ type argInfo struct {

// Parse a raw command line and return a list of argument info structs
func parseArgs(raw []rune) ([]argInfo, error) {
	state := startState
	args := make([]argInfo, 0)
	var state lexerState
	var unquoted []rune
	var start int
	var argstart int
	var infos []argInfo

	for i, nextRune := range raw {
		class := runeClasses[nextRune]
	state = start

	for i, char := range raw {
		class := runeClasses[char]

		switch state {
		case startState: // no runes read yet
		case start:
			// no runes read yet
			switch class {
			case spaceRuneClass:
			case space:
				break
			case commentRuneClass:
				state = commentState
			case escapingQuoteRuneClass:
				state = quotingEscapingState
			case nonEscapingQuoteRuneClass:
				state = quotingState
			case escapeRuneClass:
				state = escapingState
			case comment:
				state = inComment
			case doubleQuote:
				state = inDoubleQuote
			case singleQuote:
				state = inSingleQuote
			case backslash:
				state = escaping
			default:
				// start a new word
				unquoted = []rune{nextRune}
				state = inWordState
				unquoted = []rune{char}
				state = inWord
			}
			start = i
		case inWordState: // in a regular word
			argstart = i
		case inWord:
			switch class {
			case spaceRuneClass:
				args = append(args, argInfo{
					start:    start,
			case space:
				infos = append(infos, argInfo{
					start:    argstart,
					unquoted: string(unquoted),
				})
				unquoted = nil
				state = startState
			case escapingQuoteRuneClass:
				state = quotingEscapingState
			case nonEscapingQuoteRuneClass:
				state = quotingState
			case escapeRuneClass:
				state = escapingState
				state = start
			case doubleQuote:
				state = inDoubleQuote
			case singleQuote:
				state = inSingleQuote
			case backslash:
				state = escaping
			default:
				unquoted = append(unquoted, nextRune)
				unquoted = append(unquoted, char)
			}
		case escapingState: // the rune after an escape character
			state = inWordState
			unquoted = append(unquoted, nextRune)
		case escapingQuotedState: // the next rune after an escape character, in double quotes
			state = quotingEscapingState
			unquoted = append(unquoted, nextRune)
		case quotingEscapingState: // in escaping double quotes
		case escaping:
			// the rune after an escape character
			state = inWord
			unquoted = append(unquoted, char)
		case escapingQuoted:
			// the next rune after an escape character, in double quotes
			state = inDoubleQuote
			unquoted = append(unquoted, char)
		case inDoubleQuote:
			switch class {
			case escapingQuoteRuneClass:
				state = inWordState
			case escapeRuneClass:
				state = escapingQuotedState
			case doubleQuote:
				state = inWord
			case backslash:
				state = escapingQuoted
			default:
				unquoted = append(unquoted, nextRune)
				unquoted = append(unquoted, char)
			}
		case quotingState: // in non-escaping single quotes
		case inSingleQuote:
			switch class {
			case nonEscapingQuoteRuneClass:
				state = inWordState
			case singleQuote:
				state = inWord
			default:
				unquoted = append(unquoted, nextRune)
				unquoted = append(unquoted, char)
			}
		case commentState: // in a comment
			if nextRune == '\n' {
				state = startState
		case inComment: // in a comment
			if char == '\n' {
				state = start
			}
		default:
			return nil, fmt.Errorf("Unexpected state: %v", state)
@@ -162,22 +167,22 @@ func parseArgs(raw []rune) ([]argInfo, error) {

	var err error
	switch state {
	case escapingState:
	case escaping:
		err = fmt.Errorf("EOF found after escape character")
	case escapingQuotedState:
	case escapingQuoted:
		err = fmt.Errorf("EOF found after escape character")
	case quotingEscapingState:
	case inDoubleQuote:
		err = fmt.Errorf("EOF found when expecting closing double quote")
	case quotingState:
	case inSingleQuote:
		err = fmt.Errorf("EOF found when expecting closing single quote")
	}

	if unquoted != nil {
		args = append(args, argInfo{
			start:    start,
		infos = append(infos, argInfo{
			start:    argstart,
			unquoted: string(unquoted),
		})
	}

	return args, err
	return infos, err
}
-- 
2.44.0
Details
Message ID
<D09ZV7DU42QU.3BM64QFV9OGZT@ringo>
In-Reply-To
<20240402223512.1957773-1-robin@jarry.cc> (view parent)
DKIM signature
pass
Download raw message
Robin Jarry, Apr 03, 2024 at 00:35:
> Rename constants to upper case with less confusing terminology.
>
> Signed-off-by: Robin Jarry <robin@jarry.cc>

Applied. Thanks!
Reply to thread Export thread (mbox)