Move the command tree into internal/cli #9

Merged
clawbot merged 2 commits from issue-8-cli-package into next 2026-09-29 01:51:35 +02:00
3 changed files with 31 additions and 18 deletions
Showing only changes of commit 54596ef54b - Show all commits
+11 -12
View File
@@ -4,8 +4,8 @@ package cli
import (
"fmt"
"io"
"os"
"github.com/spf13/cobra"
)
// appname is the name the program reports in its logs and its version.
@@ -13,23 +13,22 @@ const appname = "simplexcalc"
// Main runs the command named on the command line and returns the exit
// status for main to pass to os.Exit.
//
// It leaves cobra's output streams at their defaults. cobra writes the
// usage and an unknown help topic to stderr, but SetOut moves them onto
// the stream it is given.
func Main(version string) int {
return execute(version, os.Args[1:], os.Stdout, os.Stderr)
return execute(rootCmd(version))
}
// execute is Main with the arguments and the output passed in, so that
// a test can supply them.
func execute(version string, args []string, stdout, stderr io.Writer) int {
root := rootCmd(version)
root.SetArgs(args)
root.SetOut(stdout)
root.SetErr(stderr)
// execute runs root and returns the exit status. It takes the command
// so that a test can set its arguments and output streams first.
func execute(root *cobra.Command) int {
err := root.Execute()
if err != nil {
// cobra has already printed the error; this only sets the exit
// status, which is what a supervisor and a shell script read.
_, _ = fmt.Fprintln(stderr, "exiting: "+err.Error())
_, _ = fmt.Fprintln(root.ErrOrStderr(), "exiting: "+err.Error())
return 1
}
+12 -2
View File
@@ -14,7 +14,12 @@ func TestVersionPrintsVersion(t *testing.T) {
var stdout, stderr bytes.Buffer
status := cli.Execute("1.2.3", []string{"version"}, &stdout, &stderr)
root := cli.RootCmd("1.2.3")
root.SetArgs([]string{"version"})
root.SetOut(&stdout)
root.SetErr(&stderr)
status := cli.Execute(root)
if status != 0 {
t.Fatalf("status = %d, want 0; stderr: %q", status, stderr.String())
}
@@ -30,7 +35,12 @@ func TestUnknownCommandFails(t *testing.T) {
var stdout, stderr bytes.Buffer
status := cli.Execute("1.2.3", []string{"frobnicate"}, &stdout, &stderr)
root := cli.RootCmd("1.2.3")
root.SetArgs([]string{"frobnicate"})
root.SetOut(&stdout)
root.SetErr(&stderr)
status := cli.Execute(root)
if status == 0 {
t.Fatal("status = 0, want non-zero")
}
+8 -4
View File
@@ -1,7 +1,11 @@
package cli
// Execute is execute, exported for the external test package, which
// needs to supply the arguments and read the output.
// RootCmd and Execute are rootCmd and execute, exported for the external
// test package, which builds the command tree itself so that it can
// supply the arguments and read the output.
//
//nolint:gochecknoglobals // a test seam, not mutable state.
var Execute = execute
//nolint:gochecknoglobals // test seams, not mutable state.
var (
RootCmd = rootCmd
Execute = execute
)