Skip to content

Commit 46267a6

Browse files
authored
fix: more commands have autocomplete (#4704)
1 parent 0f8a67e commit 46267a6

7 files changed

+63
-24
lines changed

cmd/ftl/cmd_config.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ func (s *configCmd) provider() optional.Option[ftlv1.ConfigProvider] {
5353

5454
type configListCmd struct {
5555
Values bool `help:"List configuration values."`
56-
Module string `optional:"" arg:"" placeholder:"MODULE" help:"List configuration only in this module."`
56+
Module string `optional:"" arg:"" placeholder:"MODULE" help:"List configuration only in this module." predictor:"modules"`
5757
}
5858

5959
func (s *configListCmd) Run(ctx context.Context, adminClient admin.EnvironmentClient) error {
@@ -77,7 +77,7 @@ func (s *configListCmd) Run(ctx context.Context, adminClient admin.EnvironmentCl
7777
}
7878

7979
type configGetCmd struct {
80-
Ref configuration.Ref `arg:"" help:"Configuration reference in the form [<module>.]<name>."`
80+
Ref configuration.Ref `arg:"" help:"Configuration reference in the form [<module>.]<name>." predictor:"configs"`
8181
}
8282

8383
func (s *configGetCmd) Help() string {
@@ -99,7 +99,7 @@ func (s *configGetCmd) Run(ctx context.Context, adminClient admin.EnvironmentCli
9999

100100
type configSetCmd struct {
101101
JSON bool `help:"Assume input value is JSON. Note: For string configs, the JSON value itself must be a string (e.g., '\"hello\"' or '\"{'key': 'value'}\"')."`
102-
Ref configuration.Ref `arg:"" help:"Configuration reference in the form [<module>.]<name>."`
102+
Ref configuration.Ref `arg:"" help:"Configuration reference in the form [<module>.]<name>." predictor:"configs"`
103103
Value *string `arg:"" placeholder:"VALUE" help:"Configuration value (read from stdin if omitted)." optional:""`
104104
}
105105

@@ -143,7 +143,7 @@ func (s *configSetCmd) Run(ctx context.Context, scmd *configCmd, adminClient adm
143143
}
144144

145145
type configUnsetCmd struct {
146-
Ref configuration.Ref `arg:"" help:"Configuration reference in the form [<module>.]<name>."`
146+
Ref configuration.Ref `arg:"" help:"Configuration reference in the form [<module>.]<name>." predictor:"configs"`
147147
}
148148

149149
func (s *configUnsetCmd) Run(ctx context.Context, scmd *configCmd, adminClient admin.EnvironmentClient) error {

cmd/ftl/cmd_download.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111

1212
type downloadCmd struct {
1313
Dest string `short:"d" help:"Destination directory." default:"."`
14-
Deployment key.Deployment `help:"Deployment to download." arg:""`
14+
Deployment key.Deployment `help:"Deployment to download." arg:"" predictor:"deployments"`
1515
}
1616

1717
func (d *downloadCmd) Run(ctx context.Context, client ftlv1connect.AdminServiceClient) error {

cmd/ftl/cmd_secret.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ variables, and so on.
4545

4646
type secretListCmd struct {
4747
Values bool `help:"List secret values."`
48-
Module string `optional:"" arg:"" placeholder:"MODULE" help:"List secrets only in this module."`
48+
Module string `optional:"" arg:"" placeholder:"MODULE" help:"List secrets only in this module." predictor:"modules"`
4949
}
5050

5151
func (s *secretListCmd) Run(ctx context.Context, adminClient admin.EnvironmentClient) error {
@@ -68,7 +68,7 @@ func (s *secretListCmd) Run(ctx context.Context, adminClient admin.EnvironmentCl
6868
}
6969

7070
type secretGetCmd struct {
71-
Ref cf.Ref `arg:"" help:"Secret reference in the form [<module>.]<name>."`
71+
Ref cf.Ref `arg:"" help:"Secret reference in the form [<module>.]<name>." predictor:"secrets"`
7272
}
7373

7474
func (s *secretGetCmd) Help() string {
@@ -90,7 +90,7 @@ func (s *secretGetCmd) Run(ctx context.Context, adminClient admin.EnvironmentCli
9090

9191
type secretSetCmd struct {
9292
JSON bool `help:"Assume input value is JSON. Note: For string secrets, the JSON value itself must be a string (e.g., '\"hello\"' or '\"{'key': 'value'}\"')."`
93-
Ref cf.Ref `arg:"" help:"Secret reference in the form [<module>.]<name>."`
93+
Ref cf.Ref `arg:"" help:"Secret reference in the form [<module>.]<name>." predictor:"secrets"`
9494
Value string `arg:"" placeholder:"VALUE" help:"Secret value (read from stdin if omitted)." optional:""`
9595
}
9696

@@ -139,7 +139,7 @@ func (s *secretSetCmd) Run(ctx context.Context, adminClient admin.EnvironmentCli
139139
}
140140

141141
type secretUnsetCmd struct {
142-
Ref cf.Ref `arg:"" help:"Secret reference in the form [<module>.]<name>."`
142+
Ref cf.Ref `arg:"" help:"Secret reference in the form [<module>.]<name>." predictor:"secrets"`
143143
}
144144

145145
func (s *secretUnsetCmd) Run(ctx context.Context, adminClient admin.EnvironmentClient) (err error) {

cmd/ftl/cmd_sql_migration_new.go

+1-5
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import (
1717
)
1818

1919
type migrationSQLCmd struct {
20-
Datasource string `arg:"" help:"The qualified name of the datasource in the form module.datasource to create the migration for. If the module is not specified FTL will attempt to infer it from the current working directory."`
20+
Datasource string `arg:"" help:"The qualified name of the datasource in the form module.datasource to create the migration for. If the module is not specified FTL will attempt to infer it from the current working directory." predictor:"databases"`
2121
Name string `arg:"" help:"Name of the migration, this will be included in the migration file name."`
2222
}
2323

@@ -50,10 +50,6 @@ func (i migrationSQLCmd) Run(ctx context.Context) error {
5050
if module == nil {
5151
return fmt.Errorf("could not find module %q", parts[0])
5252
}
53-
54-
if err != nil {
55-
return fmt.Errorf("could not discover modules: %w", err)
56-
}
5753
var migrationDir string
5854
var found bool
5955
if sqlDirs, ok := module.SQLDatabases[dsName]; ok {

cmd/ftl/cmd_subscription_reset.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import (
1313
)
1414

1515
type resetSubscriptionCmd struct {
16-
Subscription reflection.Ref `arg:"" required:"" help:"Full path of subscription to reset."`
16+
Subscription reflection.Ref `arg:"" required:"" help:"Full path of subscription to reset." predictor:"subscriptions"`
1717
Latest bool `flag:"latest" help:"Reset subscription to latest offset." default:"true" negatable:"beginning"`
1818
}
1919

cmd/ftl/cmd_update.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import (
1414

1515
type updateCmd struct {
1616
Replicas int32 `short:"n" help:"Number of replicas to deploy." default:"1"`
17-
Deployment key.Deployment `arg:"" help:"Deployment to update."`
17+
Deployment key.Deployment `arg:"" help:"Deployment to update." predictor:"deployments"`
1818
}
1919

2020
func (u *updateCmd) Run(ctx context.Context, client ftlv1connect.SchemaServiceClient) error {

internal/terminal/predictors.go

+51-8
Original file line numberDiff line numberDiff line change
@@ -4,36 +4,79 @@ import (
44
"github.com/posener/complete"
55

66
"github.com/block/ftl/common/schema"
7+
"github.com/block/ftl/common/slices"
78
"github.com/block/ftl/internal/log"
89
"github.com/block/ftl/internal/schema/schemaeventsource"
910
)
1011

1112
func Predictors(view *schemaeventsource.View) map[string]complete.Predictor {
1213
return map[string]complete.Predictor{
13-
"verbs": &verbPredictor{view: *view},
14-
"deployments": &deploymentsPredictor{view: *view},
15-
"log-level": &logLevelPredictor{},
14+
"verbs": &declPredictor[*schema.Verb]{view: *view},
15+
"configs": &declPredictor[*schema.Config]{view: *view},
16+
"secrets": &declPredictor[*schema.Secret]{view: *view},
17+
"databases": &declPredictor[*schema.Database]{view: *view},
18+
"subscriptions": &subscriptionsPredictor{view: *view},
19+
"modules": &modulePredictor{view: *view},
20+
"deployments": &deploymentsPredictor{view: *view},
21+
"log-level": &logLevelPredictor{},
1622
}
1723
}
1824

19-
type verbPredictor struct {
25+
type declPredictor[d schema.Decl] struct {
2026
view schemaeventsource.View
2127
}
2228

23-
func (v *verbPredictor) Predict(args complete.Args) []string {
24-
sch := v.view.GetCanonical()
29+
func (p *declPredictor[d]) Predict(args complete.Args) []string {
30+
sch := p.view.GetCanonical()
2531
ret := []string{}
2632
for _, module := range sch.Modules {
2733
for _, dec := range module.Decls {
28-
if verb, ok := dec.(*schema.Verb); ok {
29-
ref := schema.Ref{Module: module.Name, Name: verb.Name}
34+
if _, ok := dec.(d); ok {
35+
ref := schema.Ref{Module: module.Name, Name: dec.GetName()}
3036
ret = append(ret, ref.String())
3137
}
3238
}
3339
}
3440
return ret
3541
}
3642

43+
type subscriptionsPredictor struct {
44+
view schemaeventsource.View
45+
}
46+
47+
func (p *subscriptionsPredictor) Predict(args complete.Args) []string {
48+
sch := p.view.GetCanonical()
49+
ret := []string{}
50+
for _, module := range sch.Modules {
51+
for _, dec := range module.Decls {
52+
verb, ok := dec.(*schema.Verb)
53+
if !ok {
54+
continue
55+
}
56+
_, ok = slices.FindVariant[*schema.MetadataSubscriber](verb.Metadata)
57+
if !ok {
58+
continue
59+
}
60+
ref := schema.Ref{Module: module.Name, Name: dec.GetName()}
61+
ret = append(ret, ref.String())
62+
}
63+
}
64+
return ret
65+
}
66+
67+
type modulePredictor struct {
68+
view schemaeventsource.View
69+
}
70+
71+
func (v *modulePredictor) Predict(args complete.Args) []string {
72+
sch := v.view.GetCanonical()
73+
ret := []string{}
74+
for _, module := range sch.Modules {
75+
ret = append(ret, module.Name)
76+
}
77+
return ret
78+
}
79+
3780
type deploymentsPredictor struct {
3881
view schemaeventsource.View
3982
}

0 commit comments

Comments
 (0)