diff --git a/internal/cli/run.go b/internal/cli/run.go index 62b6208..8c1a74c 100644 --- a/internal/cli/run.go +++ b/internal/cli/run.go @@ -105,18 +105,36 @@ func newDepsLive(st *store.Store, out io.Writer) Deps { } } -// runDoctor handles `doctor [--account ]` (human-readable diagnostics). +// runDoctor handles `doctor [account]` or `doctor [--account ]`. func runDoctor(args []string, role store.Role, out, errOut io.Writer) int { + // Accept a positional account (human form) or --account (agent form). + var positional string + rest := args + if len(args) > 0 && !strings.HasPrefix(args[0], "-") { + positional, rest = args[0], args[1:] + } fs := flag.NewFlagSet("doctor", flag.ContinueOnError) fs.SetOutput(errOut) usageFlags(fs, "doctor", errOut) - account := fs.String("account", "", "check only this account") - if err := fs.Parse(args); err != nil { + accountFlag := fs.String("account", "", "check only this account") + if err := fs.Parse(rest); err != nil { if errors.Is(err, flag.ErrHelp) { return 0 } return 2 } + if fs.NArg() > 0 { + fmt.Fprintf(errOut, "unexpected argument %q\n", fs.Arg(0)) + return 2 + } + account := *accountFlag + if positional != "" { + if account != "" && account != positional { + fmt.Fprintln(errOut, "give the account once, as a positional or --account, not both") + return 2 + } + account = positional + } st, err := openStore(role) if err != nil { fmt.Fprintf(errOut, "emcli: %v\n", err) @@ -124,7 +142,7 @@ func runDoctor(args []string, role store.Role, out, errOut io.Writer) int { } defer st.Close() d := newDepsLive(st, out) - if err := DoctorCmd(d, *account); err != nil { + if err := DoctorCmd(d, account); err != nil { return 1 } return 0 diff --git a/internal/cli/run_test.go b/internal/cli/run_test.go index cf38675..7479aba 100644 --- a/internal/cli/run_test.go +++ b/internal/cli/run_test.go @@ -58,6 +58,20 @@ func TestListUsageErrorIsJSON(t *testing.T) { } } +func TestDoctorPositionalAccount(t *testing.T) { + adminEnv(t) + // No such account: doctor should reach account lookup and fail there (exit 1), + // proving the positional was accepted (not rejected as an unexpected arg). + code, _, errOut := run(t, "doctor", "ghost") + if code == 2 { + t.Fatalf("positional account must be accepted, got usage error: %q", errOut) + } + // Giving both positional and --account with different values is a usage error. + if code, _, _ := run(t, "doctor", "ghost", "--account", "other"); code != 2 { + t.Fatal("conflicting positional + --account must be a usage error") + } +} + func b64Key() string { // 32 zero bytes, base64. return "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="