Skip to content

Commit 18f37d2

Browse files
committed
feat(cli): shell completion support
1 parent f75fac3 commit 18f37d2

10 files changed

+127
-25
lines changed

.golangci.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ linters-settings:
2020
- github.com/mattn/go-sqlite3
2121
- github.com/mitchellh/cli
2222
- github.com/olekukonko/tablewriter
23+
- github.com/posener/complete
2324
- github.com/rubenv/sql-migrate
2425
exhaustive:
2526
default-signifies-exhaustive: true

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ require (
1212
github.com/mattn/go-sqlite3 v1.14.15
1313
github.com/mitchellh/cli v1.1.5
1414
github.com/olekukonko/tablewriter v0.0.5
15+
github.com/posener/complete v1.2.3
1516
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c
1617
gopkg.in/yaml.v2 v2.4.0
1718
)
@@ -38,7 +39,6 @@ require (
3839
github.com/mattn/go-runewidth v0.0.9 // indirect
3940
github.com/mitchellh/copystructure v1.2.0 // indirect
4041
github.com/mitchellh/reflectwalk v1.0.2 // indirect
41-
github.com/posener/complete v1.2.3 // indirect
4242
github.com/rogpeppe/go-internal v1.9.0 // indirect
4343
github.com/shopspring/decimal v1.3.1 // indirect
4444
github.com/spf13/cast v1.5.0 // indirect

sql-migrate/command_down.go

+16
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"flag"
55
"strings"
66

7+
"github.com/posener/complete"
8+
79
migrate "github.com/rubenv/sql-migrate"
810
)
911

@@ -31,6 +33,20 @@ func (*DownCommand) Synopsis() string {
3133
return "Undo a database migration"
3234
}
3335

36+
func (*DownCommand) AutocompleteArgs() complete.Predictor {
37+
return nil
38+
}
39+
40+
func (*DownCommand) AutocompleteFlags() complete.Flags {
41+
f := complete.Flags{
42+
"-limit": complete.PredictAnything,
43+
"-version": complete.PredictAnything,
44+
"-dryrun": complete.PredictNothing,
45+
}
46+
ConfigFlagsCompletions(f)
47+
return f
48+
}
49+
3450
func (c *DownCommand) Run(args []string) int {
3551
var limit int
3652
var version int64

sql-migrate/command_new.go

+12
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import (
99
"strings"
1010
"text/template"
1111
"time"
12+
13+
"github.com/posener/complete"
1214
)
1315

1416
var templateContent = `
@@ -39,6 +41,16 @@ func (*NewCommand) Synopsis() string {
3941
return "Create a new migration"
4042
}
4143

44+
func (*NewCommand) AutocompleteArgs() complete.Predictor {
45+
return nil
46+
}
47+
48+
func (*NewCommand) AutocompleteFlags() complete.Flags {
49+
f := complete.Flags{}
50+
ConfigFlagsCompletions(f)
51+
return f
52+
}
53+
4254
func (c *NewCommand) Run(args []string) int {
4355
cmdFlags := flag.NewFlagSet("new", flag.ContinueOnError)
4456
cmdFlags.Usage = func() { ui.Output(c.Help()) }

sql-migrate/command_redo.go

+14
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import (
55
"fmt"
66
"strings"
77

8+
"github.com/posener/complete"
9+
810
migrate "github.com/rubenv/sql-migrate"
911
)
1012

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

35+
func (*RedoCommand) AutocompleteArgs() complete.Predictor {
36+
return nil
37+
}
38+
39+
func (*RedoCommand) AutocompleteFlags() complete.Flags {
40+
f := complete.Flags{
41+
"-dryrun": complete.PredictNothing,
42+
}
43+
ConfigFlagsCompletions(f)
44+
return f
45+
}
46+
3347
func (c *RedoCommand) Run(args []string) int {
3448
var dryrun bool
3549

sql-migrate/command_skip.go

+14
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import (
55
"fmt"
66
"strings"
77

8+
"github.com/posener/complete"
9+
810
migrate "github.com/rubenv/sql-migrate"
911
)
1012

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

35+
func (*SkipCommand) AutocompleteArgs() complete.Predictor {
36+
return nil
37+
}
38+
39+
func (*SkipCommand) AutocompleteFlags() complete.Flags {
40+
f := complete.Flags{
41+
"-limit": complete.PredictAnything,
42+
}
43+
ConfigFlagsCompletions(f)
44+
return f
45+
}
46+
3347
func (c *SkipCommand) Run(args []string) int {
3448
var limit int
3549

sql-migrate/command_status.go

+11
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"time"
99

1010
"github.com/olekukonko/tablewriter"
11+
"github.com/posener/complete"
1112

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

37+
func (*StatusCommand) AutocompleteArgs() complete.Predictor {
38+
return nil
39+
}
40+
41+
func (*StatusCommand) AutocompleteFlags() complete.Flags {
42+
f := complete.Flags{}
43+
ConfigFlagsCompletions(f)
44+
return f
45+
}
46+
3647
func (c *StatusCommand) Run(args []string) int {
3748
cmdFlags := flag.NewFlagSet("status", flag.ContinueOnError)
3849
cmdFlags.Usage = func() { ui.Output(c.Help()) }

sql-migrate/command_up.go

+16
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"flag"
55
"strings"
66

7+
"github.com/posener/complete"
8+
79
migrate "github.com/rubenv/sql-migrate"
810
)
911

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

36+
func (*UpCommand) AutocompleteArgs() complete.Predictor {
37+
return nil
38+
}
39+
40+
func (*UpCommand) AutocompleteFlags() complete.Flags {
41+
f := complete.Flags{
42+
"-dryrun": complete.PredictNothing,
43+
"-limit": complete.PredictAnything,
44+
"-version": complete.PredictAnything,
45+
}
46+
ConfigFlagsCompletions(f)
47+
return f
48+
}
49+
3450
func (c *UpCommand) Run(args []string) int {
3551
var limit int
3652
var version int64

sql-migrate/config.go

+21
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"runtime/debug"
1010

1111
"github.com/go-gorp/gorp/v3"
12+
"github.com/posener/complete"
1213
"gopkg.in/yaml.v2"
1314

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

38+
func ConfigFlagsCompletions(f complete.Flags) {
39+
f["-config"] = complete.PredictOr(complete.PredictFiles("*.yaml"), complete.PredictFiles("*.yml"))
40+
f["-env"] = complete.PredictFunc(func(args complete.Args) []string {
41+
cf := flag.NewFlagSet("", flag.ContinueOnError)
42+
ConfigFlags(cf)
43+
if err := cf.Parse(args.All); err != nil {
44+
return nil
45+
}
46+
config, err := ReadConfig()
47+
if err != nil {
48+
return nil
49+
}
50+
envs := make([]string, 0, len(config))
51+
for k := range config {
52+
envs = append(envs, k)
53+
}
54+
return envs
55+
})
56+
}
57+
3758
type Environment struct {
3859
Dialect string `yaml:"dialect"`
3960
DataSource string `yaml:"datasource"`

sql-migrate/main.go

+21-24
Original file line numberDiff line numberDiff line change
@@ -16,33 +16,30 @@ var ui cli.Ui
1616
func realMain() int {
1717
ui = &cli.BasicUi{Writer: os.Stdout}
1818

19-
cli := &cli.CLI{
20-
Args: os.Args[1:],
21-
Commands: map[string]cli.CommandFactory{
22-
"up": func() (cli.Command, error) {
23-
return &UpCommand{}, nil
24-
},
25-
"down": func() (cli.Command, error) {
26-
return &DownCommand{}, nil
27-
},
28-
"redo": func() (cli.Command, error) {
29-
return &RedoCommand{}, nil
30-
},
31-
"status": func() (cli.Command, error) {
32-
return &StatusCommand{}, nil
33-
},
34-
"new": func() (cli.Command, error) {
35-
return &NewCommand{}, nil
36-
},
37-
"skip": func() (cli.Command, error) {
38-
return &SkipCommand{}, nil
39-
},
19+
c := cli.NewCLI("sql-migrate", GetVersion())
20+
c.Args = os.Args[1:]
21+
c.Commands = map[string]cli.CommandFactory{
22+
"up": func() (cli.Command, error) {
23+
return &UpCommand{}, nil
24+
},
25+
"down": func() (cli.Command, error) {
26+
return &DownCommand{}, nil
27+
},
28+
"redo": func() (cli.Command, error) {
29+
return &RedoCommand{}, nil
30+
},
31+
"status": func() (cli.Command, error) {
32+
return &StatusCommand{}, nil
33+
},
34+
"new": func() (cli.Command, error) {
35+
return &NewCommand{}, nil
36+
},
37+
"skip": func() (cli.Command, error) {
38+
return &SkipCommand{}, nil
4039
},
41-
HelpFunc: cli.BasicHelpFunc("sql-migrate"),
42-
Version: GetVersion(),
4340
}
4441

45-
exitCode, err := cli.Run()
42+
exitCode, err := c.Run()
4643
if err != nil {
4744
_, _ = fmt.Fprintf(os.Stderr, "Error executing CLI: %s\n", err.Error())
4845
return 1

0 commit comments

Comments
 (0)