Skip to content

Commit

Permalink
Migrate to kong, make parsers extensible, add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
TomWright committed Oct 24, 2024
1 parent e081e49 commit 9dbe990
Show file tree
Hide file tree
Showing 23 changed files with 590 additions and 436 deletions.
10 changes: 5 additions & 5 deletions cmd/dasel/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import (
"os"

"github.com/tomwright/dasel/v3/internal/cli"
_ "github.com/tomwright/dasel/v3/parsing/d"
_ "github.com/tomwright/dasel/v3/parsing/json"
_ "github.com/tomwright/dasel/v3/parsing/toml"
_ "github.com/tomwright/dasel/v3/parsing/yaml"
)

func main() {
cmd := cli.RootCmd()
if err := cmd.Execute(); err != nil {
cmd.PrintErrln("Error:", err.Error())
os.Exit(1)
}
cli.MustRun(os.Stdin, os.Stdout, os.Stderr)
}
2 changes: 1 addition & 1 deletion execution/execute_binary.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func binaryExprExecutor(opts *Options, e ast.BinaryExpr) (expressionExecutor, er
return left.NotEqual(right)
case lexer.Equals:
err := left.Set(right)
return left, err
return right, err
case lexer.And:
leftBool, err := left.BoolValue()
if err != nil {
Expand Down
5 changes: 5 additions & 0 deletions execution/func_to_string.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ var FuncToString = NewFunc(
func(data *model.Value, args model.Values) (*model.Value, error) {
switch args[0].Type() {
case model.TypeString:
stringValue, err := args[0].StringValue()
if err != nil {
return nil, err
}
model.NewStringValue(stringValue)
return args[0], nil
case model.TypeInt:
i, err := args[0].IntValue()
Expand Down
16 changes: 2 additions & 14 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,8 @@ module github.com/tomwright/dasel/v3
go 1.23

require (
github.com/alecthomas/chroma/v2 v2.14.0
github.com/clbanning/mxj/v2 v2.7.0
github.com/alecthomas/kong v1.2.1
github.com/google/go-cmp v0.5.9
github.com/pelletier/go-toml/v2 v2.2.2
github.com/spf13/cobra v1.8.1
golang.org/x/net v0.29.0
golang.org/x/text v0.18.0
gopkg.in/yaml.v3 v3.0.1
)

require (
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
github.com/dlclark/regexp2 v1.11.0 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
)
26 changes: 4 additions & 22 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,34 +1,20 @@
github.com/alecthomas/assert/v2 v2.7.0 h1:QtqSACNS3tF7oasA8CU6A6sXZSBDqnm7RfpLl9bZqbE=
github.com/alecthomas/assert/v2 v2.7.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
github.com/alecthomas/chroma/v2 v2.14.0 h1:R3+wzpnUArGcQz7fCETQBzO5n9IMNi13iIs46aU4V9E=
github.com/alecthomas/chroma/v2 v2.14.0/go.mod h1:QolEbTfmUHIMVpBqxeDnNBj2uoeI4EbYP4i6n68SG4I=
github.com/alecthomas/assert/v2 v2.10.0 h1:jjRCHsj6hBJhkmhznrCzoNpbA3zqy0fYiUcYZP/GkPY=
github.com/alecthomas/assert/v2 v2.10.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
github.com/alecthomas/kong v1.2.1 h1:E8jH4Tsgv6wCRX2nGrdPyHDUCSG83WH2qE4XLACD33Q=
github.com/alecthomas/kong v1.2.1/go.mod h1:rKTSFhbdp3Ryefn8x5MOEprnRFQ7nlmMC01GKhehhBM=
github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME=
github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
Expand All @@ -38,10 +24,6 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Expand Down
56 changes: 56 additions & 0 deletions internal/cli/command.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package cli

import (
"io"
"reflect"

"github.com/alecthomas/kong"
"github.com/tomwright/dasel/v3/internal"
)

type Globals struct {
Stdin io.Reader `kong:"-"`
Stdout io.Writer `kong:"-"`
Stderr io.Writer `kong:"-"`
}

type CLI struct {
Globals

Query QueryCmd `cmd:"" help:"Execute a query"`
}

func MustRun(stdin io.Reader, stdout, stderr io.Writer) {
ctx, err := Run(stdin, stdout, stderr)
ctx.FatalIfErrorf(err)
}

func Run(stdin io.Reader, stdout, stderr io.Writer) (*kong.Context, error) {
cli := &CLI{
Globals: Globals{
Stdin: stdin,
Stdout: stdout,
Stderr: stderr,
},
}

ctx := kong.Parse(
cli,
kong.Name("dasel"),
kong.Description("Query and modify data structures from the command line."),
kong.UsageOnError(),
kong.ConfigureHelp(kong.HelpOptions{Compact: true}),
kong.Vars{
"version": internal.Version,
},
kong.Bind(&cli.Globals),
kong.TypeMapper(reflect.TypeFor[*[]variable](), &variableMapper{}),
kong.OptionFunc(func(k *kong.Kong) error {
k.Stdout = cli.Stdout
k.Stderr = cli.Stderr
return nil
}),
)
err := ctx.Run()
return ctx, err
}
111 changes: 111 additions & 0 deletions internal/cli/command_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package cli_test

import (
"bytes"
"errors"
"os"
"reflect"
"testing"

"github.com/tomwright/dasel/v3/internal/cli"
)

func runDasel(args []string, in []byte) ([]byte, []byte, error) {
stdOut := bytes.NewBuffer([]byte{})
stdErr := bytes.NewBuffer([]byte{})
stdIn := bytes.NewReader(in)

originalArgs := os.Args
defer func() {
os.Args = originalArgs
}()

os.Args = append([]string{"dasel", "query"}, args...)

_, err := cli.Run(stdIn, stdOut, stdErr)

return stdOut.Bytes(), stdErr.Bytes(), err
}

type testCase struct {
args []string
in []byte
stdout []byte
stderr []byte
err error
}

func runTest(tc testCase) func(t *testing.T) {
return func(t *testing.T) {
if tc.stdout == nil {
tc.stdout = []byte{}
}
if tc.stderr == nil {
tc.stderr = []byte{}
}

gotStdOut, gotStdErr, gotErr := runDasel(tc.args, tc.in)
if !errors.Is(gotErr, tc.err) && !errors.Is(tc.err, gotErr) {
t.Errorf("expected error %v, got %v", tc.err, gotErr)
return
}

if !reflect.DeepEqual(tc.stderr, gotStdErr) {
t.Errorf("expected stderr %s, got %s", string(tc.stderr), string(gotStdErr))
}

if !reflect.DeepEqual(tc.stdout, gotStdOut) {
t.Errorf("expected stdout %s, got %s", string(tc.stdout), string(gotStdOut))
}
}
}

func TestRun(t *testing.T) {
t.Run("complex set", func(t *testing.T) {
t.Run("set nested with spread", runTest(testCase{
args: []string{"-i", "json", "-o", "json", "--root", `user = {user..., name: {"first": $this.user.name, "last": "Doe"}}`},
in: []byte(`{"user": {"name": "John"}}`),
stdout: []byte(`{
"user": {
"name": {
"first": "John",
"last": "Doe"
}
}
}
`),
stderr: nil,
err: nil,
}))
t.Run("set nested", runTest(testCase{
args: []string{"-i", "json", "-o", "json", "--root", `user.name = {"first": user.name, "last": "Doe"}`},
in: []byte(`{"user": {"name": "John"}}`),
stdout: []byte(`{
"user": {
"name": {
"first": "John",
"last": "Doe"
}
}
}
`),
stderr: nil,
err: nil,
}))
t.Run("set nested with localised group", runTest(testCase{
args: []string{"-i", "json", "-o", "json", "--root", `user.(name = {"first": name, "last": "Doe"})`},
in: []byte(`{"user": {"name": "John"}}`),
stdout: []byte(`{
"user": {
"name": {
"first": "John",
"last": "Doe"
}
}
}
`),
stderr: nil,
err: nil,
}))
})
}
Loading

0 comments on commit 9dbe990

Please sign in to comment.