Skip to content

Commit

Permalink
feat(cli): shell completion support
Browse files Browse the repository at this point in the history
  • Loading branch information
scop committed Feb 2, 2024
1 parent bc5e259 commit df41f44
Show file tree
Hide file tree
Showing 10 changed files with 127 additions and 25 deletions.
1 change: 1 addition & 0 deletions .golangci.yaml
Expand Up @@ -20,6 +20,7 @@ linters-settings:
- github.com/mattn/go-sqlite3
- github.com/mitchellh/cli
- github.com/olekukonko/tablewriter
- github.com/posener/complete
- github.com/rubenv/sql-migrate
exhaustive:
default-signifies-exhaustive: true
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Expand Up @@ -12,6 +12,7 @@ require (
github.com/mattn/go-sqlite3 v1.14.19
github.com/mitchellh/cli v1.1.5
github.com/olekukonko/tablewriter v0.0.5
github.com/posener/complete v1.2.3
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c
gopkg.in/yaml.v2 v2.4.0
)
Expand All @@ -38,7 +39,6 @@ require (
github.com/mattn/go-runewidth v0.0.9 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/posener/complete v1.2.3 // indirect
github.com/rogpeppe/go-internal v1.9.0 // indirect
github.com/shopspring/decimal v1.3.1 // indirect
github.com/spf13/cast v1.5.0 // indirect
Expand Down
16 changes: 16 additions & 0 deletions sql-migrate/command_down.go
Expand Up @@ -4,6 +4,8 @@ import (
"flag"
"strings"

"github.com/posener/complete"

migrate "github.com/rubenv/sql-migrate"
)

Expand Down Expand Up @@ -31,6 +33,20 @@ func (*DownCommand) Synopsis() string {
return "Undo a database migration"
}

func (*DownCommand) AutocompleteArgs() complete.Predictor {
return nil
}

func (*DownCommand) AutocompleteFlags() complete.Flags {
f := complete.Flags{
"-limit": complete.PredictAnything,
"-version": complete.PredictAnything,
"-dryrun": complete.PredictNothing,
}
ConfigFlagsCompletions(f)
return f
}

func (c *DownCommand) Run(args []string) int {
var limit int
var version int64
Expand Down
12 changes: 12 additions & 0 deletions sql-migrate/command_new.go
Expand Up @@ -9,6 +9,8 @@ import (
"strings"
"text/template"
"time"

"github.com/posener/complete"
)

var templateContent = `
Expand Down Expand Up @@ -39,6 +41,16 @@ func (*NewCommand) Synopsis() string {
return "Create a new migration"
}

func (*NewCommand) AutocompleteArgs() complete.Predictor {
return nil
}

func (*NewCommand) AutocompleteFlags() complete.Flags {
f := complete.Flags{}
ConfigFlagsCompletions(f)
return f
}

func (c *NewCommand) Run(args []string) int {
cmdFlags := flag.NewFlagSet("new", flag.ContinueOnError)
cmdFlags.Usage = func() { ui.Output(c.Help()) }
Expand Down
14 changes: 14 additions & 0 deletions sql-migrate/command_redo.go
Expand Up @@ -5,6 +5,8 @@ import (
"fmt"
"strings"

"github.com/posener/complete"

migrate "github.com/rubenv/sql-migrate"
)

Expand All @@ -30,6 +32,18 @@ func (*RedoCommand) Synopsis() string {
return "Reapply the last migration"
}

func (*RedoCommand) AutocompleteArgs() complete.Predictor {
return nil
}

func (*RedoCommand) AutocompleteFlags() complete.Flags {
f := complete.Flags{
"-dryrun": complete.PredictNothing,
}
ConfigFlagsCompletions(f)
return f
}

func (c *RedoCommand) Run(args []string) int {
var dryrun bool

Expand Down
14 changes: 14 additions & 0 deletions sql-migrate/command_skip.go
Expand Up @@ -5,6 +5,8 @@ import (
"fmt"
"strings"

"github.com/posener/complete"

migrate "github.com/rubenv/sql-migrate"
)

Expand All @@ -30,6 +32,18 @@ func (*SkipCommand) Synopsis() string {
return "Sets the database level to the most recent version available, without running the migrations"
}

func (*SkipCommand) AutocompleteArgs() complete.Predictor {
return nil
}

func (*SkipCommand) AutocompleteFlags() complete.Flags {
f := complete.Flags{
"-limit": complete.PredictAnything,
}
ConfigFlagsCompletions(f)
return f
}

func (c *SkipCommand) Run(args []string) int {
var limit int

Expand Down
11 changes: 11 additions & 0 deletions sql-migrate/command_status.go
Expand Up @@ -8,6 +8,7 @@ import (
"time"

"github.com/olekukonko/tablewriter"
"github.com/posener/complete"

migrate "github.com/rubenv/sql-migrate"
)
Expand All @@ -33,6 +34,16 @@ func (*StatusCommand) Synopsis() string {
return "Show migration status"
}

func (*StatusCommand) AutocompleteArgs() complete.Predictor {
return nil
}

func (*StatusCommand) AutocompleteFlags() complete.Flags {
f := complete.Flags{}
ConfigFlagsCompletions(f)
return f
}

func (c *StatusCommand) Run(args []string) int {
cmdFlags := flag.NewFlagSet("status", flag.ContinueOnError)
cmdFlags.Usage = func() { ui.Output(c.Help()) }
Expand Down
16 changes: 16 additions & 0 deletions sql-migrate/command_up.go
Expand Up @@ -4,6 +4,8 @@ import (
"flag"
"strings"

"github.com/posener/complete"

migrate "github.com/rubenv/sql-migrate"
)

Expand Down Expand Up @@ -31,6 +33,20 @@ func (*UpCommand) Synopsis() string {
return "Migrates the database to the most recent version available"
}

func (*UpCommand) AutocompleteArgs() complete.Predictor {
return nil
}

func (*UpCommand) AutocompleteFlags() complete.Flags {
f := complete.Flags{
"-dryrun": complete.PredictNothing,
"-limit": complete.PredictAnything,
"-version": complete.PredictAnything,
}
ConfigFlagsCompletions(f)
return f
}

func (c *UpCommand) Run(args []string) int {
var limit int
var version int64
Expand Down
21 changes: 21 additions & 0 deletions sql-migrate/config.go
Expand Up @@ -9,6 +9,7 @@ import (
"runtime/debug"

"github.com/go-gorp/gorp/v3"
"github.com/posener/complete"
"gopkg.in/yaml.v2"

migrate "github.com/rubenv/sql-migrate"
Expand All @@ -34,6 +35,26 @@ func ConfigFlags(f *flag.FlagSet) {
f.StringVar(&ConfigEnvironment, "env", "development", "Environment to use.")
}

func ConfigFlagsCompletions(f complete.Flags) {
f["-config"] = complete.PredictOr(complete.PredictFiles("*.yaml"), complete.PredictFiles("*.yml"))
f["-env"] = complete.PredictFunc(func(args complete.Args) []string {
cf := flag.NewFlagSet("", flag.ContinueOnError)
ConfigFlags(cf)
if err := cf.Parse(args.All); err != nil {
return nil
}
config, err := ReadConfig()
if err != nil {
return nil
}
envs := make([]string, 0, len(config))
for k := range config {
envs = append(envs, k)
}
return envs
})
}

type Environment struct {
Dialect string `yaml:"dialect"`
DataSource string `yaml:"datasource"`
Expand Down
45 changes: 21 additions & 24 deletions sql-migrate/main.go
Expand Up @@ -16,33 +16,30 @@ var ui cli.Ui
func realMain() int {
ui = &cli.BasicUi{Writer: os.Stdout}

cli := &cli.CLI{
Args: os.Args[1:],
Commands: map[string]cli.CommandFactory{
"up": func() (cli.Command, error) {
return &UpCommand{}, nil
},
"down": func() (cli.Command, error) {
return &DownCommand{}, nil
},
"redo": func() (cli.Command, error) {
return &RedoCommand{}, nil
},
"status": func() (cli.Command, error) {
return &StatusCommand{}, nil
},
"new": func() (cli.Command, error) {
return &NewCommand{}, nil
},
"skip": func() (cli.Command, error) {
return &SkipCommand{}, nil
},
c := cli.NewCLI("sql-migrate", GetVersion())
c.Args = os.Args[1:]
c.Commands = map[string]cli.CommandFactory{
"up": func() (cli.Command, error) {
return &UpCommand{}, nil
},
"down": func() (cli.Command, error) {
return &DownCommand{}, nil
},
"redo": func() (cli.Command, error) {
return &RedoCommand{}, nil
},
"status": func() (cli.Command, error) {
return &StatusCommand{}, nil
},
"new": func() (cli.Command, error) {
return &NewCommand{}, nil
},
"skip": func() (cli.Command, error) {
return &SkipCommand{}, nil
},
HelpFunc: cli.BasicHelpFunc("sql-migrate"),
Version: GetVersion(),
}

exitCode, err := cli.Run()
exitCode, err := c.Run()
if err != nil {
_, _ = fmt.Fprintf(os.Stderr, "Error executing CLI: %s\n", err.Error())
return 1
Expand Down

0 comments on commit df41f44

Please sign in to comment.