From a8aa2e193b744a9eec3559c673262888e6b3f271 Mon Sep 17 00:00:00 2001 From: maxlandon Date: Tue, 28 Nov 2023 19:12:58 +0000 Subject: [PATCH] Use mvdan/sh for parsing input (#35) * Use mvdan/sh for parsing and removing comments * Update readline dep --- go.mod | 9 +++++---- go.sum | 11 +++++++++++ line.go | 26 ++++++++++++++++++++++++++ run.go | 6 +++--- 4 files changed, 45 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index b885ec4..68fb096 100644 --- a/go.mod +++ b/go.mod @@ -4,11 +4,11 @@ go 1.21 require ( github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 - github.com/reeflective/readline v1.0.9 + github.com/reeflective/readline v1.0.11 github.com/rsteube/carapace v0.43.3 github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 - golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561 + golang.org/x/exp v0.0.0-20231127185646-65229373498e ) require ( @@ -16,10 +16,11 @@ require ( github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/rivo/uniseg v0.4.4 // indirect - golang.org/x/sys v0.8.0 // indirect - golang.org/x/term v0.8.0 // indirect + golang.org/x/sys v0.15.0 // indirect + golang.org/x/term v0.15.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/yaml.v3 v3.0.1 // indirect + mvdan.cc/sh/v3 v3.7.0 // indirect ) replace github.com/rsteube/carapace v0.43.3 => github.com/reeflective/carapace v0.25.2-0.20230816093630-a30f5184fa0d diff --git a/go.sum b/go.sum index adab06f..8951a4e 100644 --- a/go.sum +++ b/go.sum @@ -18,10 +18,13 @@ github.com/reeflective/carapace v0.25.2-0.20230816093630-a30f5184fa0d h1:RK0OaQs github.com/reeflective/carapace v0.25.2-0.20230816093630-a30f5184fa0d/go.mod h1:jkLt41Ne2TD2xPuMdX/2O05Smhy8vMgG7O2TYvC0yOc= github.com/reeflective/readline v1.0.9 h1:ZA+V4HIWonwn8B4gUaaKwPtBogch19qgdk1I+hqULdk= github.com/reeflective/readline v1.0.9/go.mod h1:mcD0HxNVJVteVwDm9caXKg52nQACVyfh8EyuBmgVlzY= +github.com/reeflective/readline v1.0.11 h1:4+aiebj7a89hTRJOMM98H+md1Kxu+v1XkfdCs0n6odQ= +github.com/reeflective/readline v1.0.11/go.mod h1:mcD0HxNVJVteVwDm9caXKg52nQACVyfh8EyuBmgVlzY= github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.10.1-0.20230524175051-ec119421bb97 h1:3RPlVWzZ/PDqmVuf/FKHARG5EMid/tl7cv54Sw/QRVY= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= @@ -29,12 +32,20 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561 h1:MDc5xs78ZrZr3HMQugiXOAkSZtfTpbJLDr/lwfgO53E= golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= +golang.org/x/exp v0.0.0-20231127185646-65229373498e h1:Gvh4YaCaXNs6dKTlfgismwWZKyjVZXwOPfIyUaqU3No= +golang.org/x/exp v0.0.0-20231127185646-65229373498e/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= +golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +mvdan.cc/sh/v3 v3.7.0 h1:lSTjdP/1xsddtaKfGg7Myu7DnlHItd3/M2tomOcNNBg= +mvdan.cc/sh/v3 v3.7.0/go.mod h1:K2gwkaesF/D7av7Kxl0HbF5kGOd2ArupNTX3X44+8l8= diff --git a/line.go b/line.go index 06408df..d33ce06 100644 --- a/line.go +++ b/line.go @@ -5,6 +5,9 @@ import ( "errors" "strings" "unicode/utf8" + + "github.com/kballard/go-shellquote" + "mvdan.cc/sh/v3/syntax" ) var ( @@ -21,6 +24,29 @@ var ( errUnterminatedEscape = errors.New("unterminated backslash-escape") ) +// parse is in charge of removing all comments from the input line +// before execution, and if successfully parsed, split into words. +func (c *Console) parse(line string) (args []string, err error) { + lineReader := strings.NewReader(line) + parser := syntax.NewParser(syntax.KeepComments(false)) + + // Parse the shell string a syntax, removing all comments. + stmts, err := parser.Parse(lineReader, "") + if err != nil { + return nil, err + } + + var parsedLine bytes.Buffer + + err = syntax.NewPrinter().Print(&parsedLine, stmts) + if err != nil { + return nil, err + } + + // Split the line into shell words. + return shellquote.Split(parsedLine.String()) +} + // acceptMultiline determines if the line just accepted is complete (in which case // we should execute it), or incomplete (in which case we must read in multiline). func (c *Console) acceptMultiline(line []rune) (accept bool) { diff --git a/run.go b/run.go index a50c0ce..29c6821 100644 --- a/run.go +++ b/run.go @@ -59,10 +59,10 @@ func (c *Console) Start() error { // so we must be sure we use the good one. menu = c.activeMenu() - // Split the line into shell words. - args, err := shellquote.Split(line) + // Parse the line with bash-syntax, removing comments. + args, err := c.parse(line) if err != nil { - fmt.Printf("Line error: %s\n", err.Error()) + fmt.Printf("Parsing error: %s\n", err.Error()) continue }