From 48286e51159cbafa34a2c1bcc81b277f3f8020ba Mon Sep 17 00:00:00 2001 From: M09Ic Date: Sat, 27 Jun 2026 10:04:51 +0800 Subject: [PATCH] Expose console command execution --- run.go | 9 +++++++++ run_execute_test.go | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 run_execute_test.go diff --git a/run.go b/run.go index 8cd2653..ce3e73c 100644 --- a/run.go +++ b/run.go @@ -143,6 +143,15 @@ func (m *Menu) RunCommandLine(ctx context.Context, line string) (err error) { return m.RunCommandArgs(ctx, args) } +// Execute runs a processed argument vector against a menu command tree. +// +// Most callers should prefer Menu.RunCommandArgs, which resets the active menu +// before execution. Execute is useful for integrations that already prepared a +// menu and need direct access to the lower-level execution path. +func (c *Console) Execute(ctx context.Context, menu *Menu, args []string, async bool) error { + return c.execute(ctx, menu, args, async) +} + // execute - The user has entered a command input line, the arguments have been processed: // we synchronize a few elements of the console, then pass these arguments to the command // parser for execution and error handling. diff --git a/run_execute_test.go b/run_execute_test.go new file mode 100644 index 0000000..544b346 --- /dev/null +++ b/run_execute_test.go @@ -0,0 +1,33 @@ +package console + +import ( + "context" + "testing" + + "github.com/spf13/cobra" +) + +func TestConsoleExecuteRunsPreparedMenu(t *testing.T) { + c := New("test") + menu := c.ActiveMenu() + + var ran bool + root := &cobra.Command{Use: "root"} + root.AddCommand(&cobra.Command{ + Use: "run", + Run: func(*cobra.Command, []string) { + ran = true + }, + }) + menu.Command = root + + if err := c.Execute(context.Background(), menu, []string{"run"}, false); err != nil { + t.Fatal(err) + } + if !ran { + t.Fatal("Execute did not run the target command") + } + if c.isExecuting.Load() { + t.Fatal("Execute left the console marked as executing") + } +}