refactor(maglevc): build the CLI on the golang-cli library
Replace maglevc's hand-rolled command-tree CLI with git.ipng.ch/ipng/golang-cli v1.3.0, mirroring the evpnc refactor. The tree (commands.go) and the gRPC-status error unwrap (color.go) stay app-specific; the generic parts — parse tree, completion, '?'-help, the readline shell, one-shot dispatch, color helpers, and the watch keypress handler — now come from the library. - main.go: a single cli.App[grpcapi.MaglevClient] with a Connect callback; drops the flag/color-default/dispatch boilerplate. - commands.go: `type node = cli.Node[grpcapi.MaglevClient]`; label() -> cli.Label(); dyn* gain the captured-args parameter the library's Dynamic signature carries; runQuit returns cli.ErrQuit. - watch.go: keypress.WaitForKey replaces the inline cbreak helper. - color.go: only formatError remains, reading cli.ColorEnabled(). - delete tree.go, complete.go, shell.go. - tests use the library API; add TestTreeValid (cli.Validate). Behavior is unchanged except labels/errors now use the library's bright ANSI palette (was dark); escape lengths are identical so tabwriter alignment is unaffected. maglevc additionally gains the OpenBSD readline fix and BSD-correct watch keypress it previously lacked. Builds on linux and openbsd. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+9
-33
@@ -2,42 +2,18 @@
|
||||
|
||||
package main
|
||||
|
||||
import "strings"
|
||||
import (
|
||||
"strings"
|
||||
|
||||
const (
|
||||
ansiBlue = "\x1b[34m"
|
||||
ansiRed = "\x1b[31m"
|
||||
ansiReset = "\x1b[0m"
|
||||
cli "git.ipng.ch/ipng/golang-cli"
|
||||
)
|
||||
|
||||
// colorEnabled is set by the -color flag in main.
|
||||
var colorEnabled bool
|
||||
|
||||
// label wraps s in dark-blue ANSI when color output is enabled.
|
||||
//
|
||||
// Tabwriter caveat: tabwriter.Writer counts *bytes* per cell, not
|
||||
// rendered columns. ANSI escape codes (`\x1b[34m…\x1b[0m`, 11 bytes)
|
||||
// inflate a cell's apparent width without affecting what the terminal
|
||||
// draws. Two things follow:
|
||||
//
|
||||
// 1. Key-value layouts where column 1 is *always* labelled and
|
||||
// column 2 is *always* plain (e.g. `show vpp info`) stay aligned,
|
||||
// because every row adds the same 11 bytes to column 1.
|
||||
// 2. Multi-column tables where only the *header* row is labelled
|
||||
// drift: the header cells each carry 11 extra bytes that the data
|
||||
// rows don't, so data cells get over-padded. In those tables,
|
||||
// leave the header plain (see runShowVPPLBCounters) and only use
|
||||
// label() for labels that appear uniformly column-wise.
|
||||
func label(s string) string {
|
||||
if !colorEnabled {
|
||||
return s
|
||||
}
|
||||
return ansiBlue + s + ansiReset
|
||||
}
|
||||
|
||||
// formatError returns a user-friendly error string. gRPC status errors are
|
||||
// unwrapped to show only the server's message (no "rpc error: code = ..."
|
||||
// boilerplate). The result is wrapped in red ANSI when color is enabled.
|
||||
// boilerplate). The result is wrapped in red when color is enabled. The label()
|
||||
// helper and the ANSI palette now live in the golang-cli library (cli.Label,
|
||||
// cli.Red, ...); only this gRPC-specific unwrap stays here, wired in as
|
||||
// App.FormatError.
|
||||
func formatError(err error) string {
|
||||
msg := err.Error()
|
||||
// google.golang.org/grpc/status errors format as:
|
||||
@@ -45,8 +21,8 @@ func formatError(err error) string {
|
||||
if i := strings.Index(msg, " desc = "); i >= 0 {
|
||||
msg = msg[i+len(" desc = "):]
|
||||
}
|
||||
if colorEnabled {
|
||||
return ansiRed + msg + ansiReset
|
||||
if cli.ColorEnabled() {
|
||||
return cli.Red + msg + cli.Reset
|
||||
}
|
||||
return msg
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user