Skip to content

Commit b944b8c

Browse files
authored
feat!: more consistent and clear command usage (#236)
1 parent 4888567 commit b944b8c

File tree

107 files changed

+1935
-1338
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

107 files changed

+1935
-1338
lines changed
Lines changed: 73 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"errors"
55
"fmt"
66

7-
"github.com/jahvon/tuikit/types"
87
"github.com/spf13/cobra"
98

109
"github.com/jahvon/flow/cmd/internal/flags"
@@ -16,31 +15,67 @@ import (
1615
"github.com/jahvon/flow/types/executable"
1716
)
1817

19-
func RegisterLibraryCmd(ctx *context.Context, rootCmd *cobra.Command) {
20-
libraryCmd := &cobra.Command{
21-
Use: "library",
22-
Short: "View and manage your library of workspaces and executables.",
23-
Aliases: []string{"lib"},
24-
Args: cobra.NoArgs,
18+
func RegisterBrowseCmd(ctx *context.Context, rootCmd *cobra.Command) {
19+
browseCmd := &cobra.Command{
20+
Use: "browse [EXECUTABLE-REFERENCE]",
21+
Short: "Discover and explore available executables.",
22+
Aliases: []string{"ls", "library"},
23+
Long: "Browse executables across workspaces.\n\n" +
24+
" flow browse # Interactive multi-pane executable browser\n" +
25+
" flow browse --list # Simple list view of executables\n" +
26+
" flow browse VERB [ID] # Detailed view of specific executable\n\n" +
27+
fmt.Sprintf(
28+
"See %s for more information on executable verbs and "+
29+
"%s for more information on executable references.",
30+
io.TypesDocsURL("flowfile", "executableverb"),
31+
io.TypesDocsURL("flowfile", "executableref"),
32+
),
33+
Args: cobra.MaximumNArgs(2),
34+
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
35+
execList, err := ctx.ExecutableCache.GetExecutableList(ctx.Logger)
36+
if err != nil {
37+
return nil, cobra.ShellCompDirectiveError
38+
}
39+
execIDs := make([]string, 0, len(execList))
40+
for _, e := range execList {
41+
execIDs = append(execIDs, e.ID())
42+
}
43+
return execIDs, cobra.ShellCompDirectiveNoFileComp
44+
},
2545
PreRun: func(cmd *cobra.Command, args []string) { StartTUI(ctx, cmd) },
2646
PostRun: func(cmd *cobra.Command, args []string) { WaitForTUI(ctx, cmd) },
27-
Run: func(cmd *cobra.Command, args []string) { libraryFunc(ctx, cmd, args) },
28-
}
29-
RegisterFlag(ctx, libraryCmd, *flags.FilterWorkspaceFlag)
30-
RegisterFlag(ctx, libraryCmd, *flags.FilterNamespaceFlag)
31-
RegisterFlag(ctx, libraryCmd, *flags.FilterVerbFlag)
32-
RegisterFlag(ctx, libraryCmd, *flags.FilterTagFlag)
33-
RegisterFlag(ctx, libraryCmd, *flags.FilterExecSubstringFlag)
34-
RegisterFlag(ctx, libraryCmd, *flags.AllNamespacesFlag)
35-
registerGlanceLibraryCmd(ctx, libraryCmd)
36-
registerViewLibraryCmd(ctx, libraryCmd)
37-
rootCmd.AddCommand(libraryCmd)
47+
Run: func(cmd *cobra.Command, args []string) { browseFunc(ctx, cmd, args) },
48+
}
49+
RegisterFlag(ctx, browseCmd, *flags.ListFlag)
50+
RegisterFlag(ctx, browseCmd, *flags.OutputFormatFlag)
51+
RegisterFlag(ctx, browseCmd, *flags.FilterWorkspaceFlag)
52+
RegisterFlag(ctx, browseCmd, *flags.FilterNamespaceFlag)
53+
RegisterFlag(ctx, browseCmd, *flags.FilterVerbFlag)
54+
RegisterFlag(ctx, browseCmd, *flags.FilterTagFlag)
55+
RegisterFlag(ctx, browseCmd, *flags.FilterExecSubstringFlag)
56+
RegisterFlag(ctx, browseCmd, *flags.AllNamespacesFlag)
57+
rootCmd.AddCommand(browseCmd)
3858
}
3959

40-
func libraryFunc(ctx *context.Context, cmd *cobra.Command, _ []string) {
60+
func browseFunc(ctx *context.Context, cmd *cobra.Command, args []string) {
61+
if len(args) >= 1 {
62+
viewExecutable(ctx, cmd, args)
63+
return
64+
}
65+
66+
listMode := flags.ValueFor[bool](ctx, cmd, *flags.ListFlag, false)
67+
if listMode || !TUIEnabled(ctx, cmd) {
68+
listExecutables(ctx, cmd, args)
69+
return
70+
}
71+
72+
executableLibrary(ctx, cmd, args)
73+
}
74+
75+
func executableLibrary(ctx *context.Context, cmd *cobra.Command, _ []string) {
4176
logger := ctx.Logger
4277
if !TUIEnabled(ctx, cmd) {
43-
logger.FatalErr(errors.New("library command requires an interactive terminal"))
78+
logger.FatalErr(errors.New("interactive discovery requires an interactive terminal"))
4479
}
4580

4681
wsFilter := flags.ValueFor[string](ctx, cmd, *flags.FilterWorkspaceFlag, false)
@@ -92,26 +127,7 @@ func libraryFunc(ctx *context.Context, cmd *cobra.Command, _ []string) {
92127
SetView(ctx, cmd, libraryModel)
93128
}
94129

95-
func registerGlanceLibraryCmd(ctx *context.Context, libraryCmd *cobra.Command) {
96-
glanceCmd := &cobra.Command{
97-
Use: "glance",
98-
Short: "View a list of just executables.",
99-
Args: cobra.NoArgs,
100-
PreRun: func(cmd *cobra.Command, args []string) { StartTUI(ctx, cmd) },
101-
PostRun: func(cmd *cobra.Command, args []string) { WaitForTUI(ctx, cmd) },
102-
Run: func(cmd *cobra.Command, args []string) { glanceLibraryCmd(ctx, cmd, args) },
103-
}
104-
RegisterFlag(ctx, glanceCmd, *flags.OutputFormatFlag)
105-
RegisterFlag(ctx, glanceCmd, *flags.FilterWorkspaceFlag)
106-
RegisterFlag(ctx, glanceCmd, *flags.FilterNamespaceFlag)
107-
RegisterFlag(ctx, glanceCmd, *flags.FilterVerbFlag)
108-
RegisterFlag(ctx, glanceCmd, *flags.FilterTagFlag)
109-
RegisterFlag(ctx, glanceCmd, *flags.FilterExecSubstringFlag)
110-
RegisterFlag(ctx, glanceCmd, *flags.AllNamespacesFlag)
111-
libraryCmd.AddCommand(glanceCmd)
112-
}
113-
114-
func glanceLibraryCmd(ctx *context.Context, cmd *cobra.Command, _ []string) {
130+
func listExecutables(ctx *context.Context, cmd *cobra.Command, _ []string) {
115131
logger := ctx.Logger
116132
wsFilter := flags.ValueFor[string](ctx, cmd, *flags.FilterWorkspaceFlag, false)
117133
if wsFilter == "." {
@@ -149,57 +165,35 @@ func glanceLibraryCmd(ctx *context.Context, cmd *cobra.Command, _ []string) {
149165

150166
if TUIEnabled(ctx, cmd) {
151167
runFunc := func(ref string) error { return runByRef(ctx, cmd, ref) }
152-
view := execIO.NewExecutableListView(
153-
ctx,
154-
filteredExec,
155-
types.Format(outputFormat),
156-
runFunc,
157-
)
168+
view := execIO.NewExecutableListView(ctx, filteredExec, runFunc)
158169
SetView(ctx, cmd, view)
159170
} else {
160171
execIO.PrintExecutableList(logger, outputFormat, filteredExec)
161172
}
162173
}
163174

164-
func registerViewLibraryCmd(ctx *context.Context, libraryCmd *cobra.Command) {
165-
viewCmd := &cobra.Command{
166-
Use: "view VERB ID",
167-
Aliases: []string{"show", "find"},
168-
Short: "View an executable's documentation. The executable is found by reference.",
169-
Long: "View an executable by the executable's verb and ID.\nThe target executable's ID should be in the " +
170-
"form of 'ws/ns:name' and the verb should match the target executable's verb or one of its aliases.\n\n" +
171-
fmt.Sprintf(
172-
"See %s for more information on executable verbs.\n"+
173-
"See %s for more information on executable IDs.",
174-
io.TypesDocsURL("flowfile", "ExecutableVerb"),
175-
io.TypesDocsURL("flowfile", "ExecutableRef"),
176-
),
177-
Args: cobra.ExactArgs(2),
178-
PreRun: func(cmd *cobra.Command, args []string) { StartTUI(ctx, cmd) },
179-
PostRun: func(cmd *cobra.Command, args []string) { WaitForTUI(ctx, cmd) },
180-
Run: func(cmd *cobra.Command, args []string) { viewLibraryFunc(ctx, cmd, args) },
181-
}
182-
RegisterFlag(ctx, viewCmd, *flags.OutputFormatFlag)
183-
libraryCmd.AddCommand(viewCmd)
184-
}
185-
186-
func viewLibraryFunc(ctx *context.Context, cmd *cobra.Command, args []string) {
175+
func viewExecutable(ctx *context.Context, cmd *cobra.Command, args []string) {
187176
logger := ctx.Logger
177+
188178
verbStr := args[0]
189179
verb := executable.Verb(verbStr)
190180
if err := verb.Validate(); err != nil {
191181
logger.FatalErr(err)
192182
}
193-
id := args[1]
194-
ws, ns, name := executable.MustParseExecutableID(id)
195-
if ws == "" {
196-
ws = ctx.CurrentWorkspace.AssignedName()
197-
}
198-
if ns == "" && ctx.Config.CurrentNamespace != "" {
199-
ns = ctx.Config.CurrentNamespace
183+
184+
var execID string
185+
if len(args) > 1 {
186+
id := args[1]
187+
ws, ns, name := executable.MustParseExecutableID(id)
188+
if ws == executable.WildcardWorkspace {
189+
ws = ctx.CurrentWorkspace.AssignedName()
190+
}
191+
if ns == executable.WildcardNamespace && ctx.Config.CurrentNamespace != "" {
192+
ns = ctx.Config.CurrentNamespace
193+
}
194+
execID = executable.NewExecutableID(ws, ns, name)
200195
}
201-
id = executable.NewExecutableID(ws, ns, name)
202-
ref := executable.NewRef(id, verb)
196+
ref := executable.NewRef(execID, verb)
203197

204198
exec, err := ctx.ExecutableCache.GetExecutableByRef(logger, ref)
205199
if err != nil && errors.Is(cache.NewExecutableNotFoundError(ref.String()), err) {
@@ -218,7 +212,7 @@ func viewLibraryFunc(ctx *context.Context, cmd *cobra.Command, args []string) {
218212
outputFormat := flags.ValueFor[string](ctx, cmd, *flags.OutputFormatFlag, false)
219213
if TUIEnabled(ctx, cmd) {
220214
runFunc := func(ref string) error { return runByRef(ctx, cmd, ref) }
221-
view := execIO.NewExecutableView(ctx, exec, types.Format(outputFormat), runFunc)
215+
view := execIO.NewExecutableView(ctx, exec, runFunc)
222216
SetView(ctx, cmd, view)
223217
} else {
224218
execIO.PrintExecutable(logger, outputFormat, exec)

0 commit comments

Comments
 (0)