Skip to content

Commit

Permalink
💝 A general purpose WithCommand option. (#2)
Browse files Browse the repository at this point in the history
A general purpose WithCommand option.
  • Loading branch information
cardil authored Sep 20, 2024
1 parent 176dc37 commit 24d49d4
Show file tree
Hide file tree
Showing 9 changed files with 127 additions and 54 deletions.
14 changes: 8 additions & 6 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ on:
pull_request:
types: [opened, synchronize, reopened]

env:
FORCE_COLOR: true

jobs:

build:
Expand All @@ -14,20 +17,19 @@ jobs:
strategy:
matrix:
go-version:
- '1.18'
- '1.22'
- '1.23'
steps:

- name: Set up Go ${{ matrix.go-version }}
uses: actions/setup-go@v2
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go-version }}
id: go

- name: Check out code into the Go module directory
uses: actions/checkout@v2
uses: actions/checkout@v4

- name: Test
run: go run gotest.tools/gotestsum@v1.8.0 --format testname --
run: go run gotest.tools/gotestsum@v1.12.0 --format testname --
-race -count=1 -short ./...
env:
FORCE_COLOR: true
39 changes: 39 additions & 0 deletions .golangci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
run:
timeout: 5m

linters:
disable-all: false
presets:
- bugs
- unused
- complexity
- format
- performance
- style
enable:
- gci
disable:
- paralleltest
- nlreturn
- exhaustivestruct
- wsl
- godox
- scopelint
- maligned
- interfacer
- golint
- ireturn
- varnamelen
- exhaustruct
- depguard

issues:
exclude-rules:
- path: _test\.go
linters:
- wrapcheck

linters-settings:
gomoddirectives:
# List of allowed `replace` directives. Default is empty.
replace-allow-list: []
33 changes: 0 additions & 33 deletions types.go → app.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package commandline

import (
"errors"
"io"
"os"

"github.com/spf13/cobra"
Expand All @@ -24,9 +23,6 @@ type CobraProvider interface {
Command() *cobra.Command
}

// Option is used to configure an App.
type Option func(*App)

// New creates a new App from CobraProvider.
func New(cp CobraProvider) *App {
return &App{
Expand All @@ -42,35 +38,6 @@ func (a *App) ExecuteOrDie(options ...Option) {
}
}

// WithArgs creates an option which sets args.
func WithArgs(args ...string) Option {
return func(app *App) {
app.root.SetArgs(args)
}
}

// WithInput creates an option witch sets os.Stdin.
func WithInput(in io.Reader) Option {
return func(app *App) {
app.root.SetIn(in)
}
}

// WithOutput creates an option witch sets os.Stdout and os.Stderr.
func WithOutput(out io.Writer) Option {
return func(app *App) {
app.root.SetOut(out)
app.root.SetErr(out)
}
}

// WithExit creates an option which sets the exit function.
func WithExit(fn func(code int)) Option {
return func(app *App) {
app.Exit = fn
}
}

// Execute will execute the application with the provided options and return
// error if any.
func (a *App) Execute(options ...Option) error {
Expand Down
12 changes: 7 additions & 5 deletions types_test.go → app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package commandline_test
import (
"bytes"
"errors"
"io/ioutil"
"io"
"testing"

"github.com/spf13/cobra"
Expand All @@ -15,9 +15,11 @@ func TestExecuteOrDie(t *testing.T) {
var buf bytes.Buffer
var retcode int
commandline.New(new(testApp)).ExecuteOrDie(
commandline.WithOutput(&buf),
commandline.WithInput(bytes.NewBufferString("Input")),
commandline.WithArgs("arg1", "arg2"),
commandline.WithCommand(func(cmd *cobra.Command) {
cmd.SetOut(&buf)
cmd.SetIn(bytes.NewBufferString("Input"))
cmd.SetArgs([]string{"arg1", "arg2"})
}),
commandline.WithExit(func(code int) {
retcode = code
}),
Expand Down Expand Up @@ -46,7 +48,7 @@ func (t testApp) Command() *cobra.Command {
SilenceUsage: true,
SilenceErrors: true,
RunE: func(cmd *cobra.Command, args []string) error {
in, err := ioutil.ReadAll(cmd.InOrStdin())
in, err := io.ReadAll(cmd.InOrStdin())
if err != nil {
return err
}
Expand Down
10 changes: 5 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
module github.com/wavesoftware/go-commandline

go 1.18
go 1.22.0

require (
github.com/spf13/cobra v1.5.0
github.com/spf13/cobra v1.8.1
github.com/wavesoftware/go-retcode v1.0.0
gotest.tools/v3 v3.3.0
gotest.tools/v3 v3.5.1
)

require (
github.com/google/go-cmp v0.5.5 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
)
12 changes: 12 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
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/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU=
github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM=
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.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
Expand Down Expand Up @@ -37,5 +46,8 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1N
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools/v3 v3.3.0 h1:MfDY1b1/0xN1CyMlQDac0ziEy9zJQd9CXBRRDHw2jJo=
gotest.tools/v3 v3.3.0/go.mod h1:Mcr9QNxkg0uMvy/YElmo4SpXgJKWgQvYrT7Kw5RzJ1A=
gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
49 changes: 49 additions & 0 deletions options.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package commandline

import (
"io"

"github.com/spf13/cobra"
)

// Option is used to configure an App.
type Option func(*App)

// WithArgs creates an option which sets args.
// Deprecated: use WithCommand instead.
func WithArgs(args ...string) Option {
return WithCommand(func(cmd *cobra.Command) {
cmd.SetArgs(args)
})
}

// WithInput creates an option witch sets os.Stdin.
// Deprecated: use WithCommand instead.
func WithInput(in io.Reader) Option {
return WithCommand(func(cmd *cobra.Command) {
cmd.SetIn(in)
})
}

// WithOutput creates an option witch sets os.Stdout and os.Stderr.
// Deprecated: use WithCommand instead.
func WithOutput(out io.Writer) Option {
return WithCommand(func(cmd *cobra.Command) {
cmd.SetOut(out)
cmd.SetErr(out)
})
}

// WithCommand will allow one to change the cobra.Command.
func WithCommand(fn func(cmd *cobra.Command)) Option {
return func(app *App) {
fn(app.root)
}
}

// WithExit creates an option which sets the exit function.
func WithExit(fn func(code int)) Option {
return func(app *App) {
app.Exit = fn
}
}
8 changes: 5 additions & 3 deletions test/cmd/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import (
"bytes"
"testing"

"github.com/spf13/cobra"
"github.com/wavesoftware/go-commandline"
main "github.com/wavesoftware/go-commandline/test/cmd"
"github.com/wavesoftware/go-commandline/test/internal/cli"
"gotest.tools/v3/assert"

"github.com/wavesoftware/go-commandline"
)

func TestTheMain(t *testing.T) {
Expand All @@ -26,7 +26,9 @@ type state struct {

func (s *state) opts() []commandline.Option {
return []commandline.Option{
commandline.WithOutput(&s.out),
commandline.WithCommand(func(cmd *cobra.Command) {
cmd.SetOut(&s.out)
}),
commandline.WithExit(func(code int) {
s.exitCode = code
}),
Expand Down
4 changes: 2 additions & 2 deletions test/internal/cli/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ import (
)

// Opts is the list of commandline options to pass to the main function.
var Opts []commandline.Option
var Opts []commandline.Option //nolint:gochecknoglobals

type App struct{}

func (a App) Command() *cobra.Command {
return &cobra.Command{
Use: "example",
Run: func(cmd *cobra.Command, args []string) {
Run: func(cmd *cobra.Command, _ []string) {
cmd.Println("Hello, world!")
},
}
Expand Down

0 comments on commit 24d49d4

Please sign in to comment.