Files
HarborForge.Cli/internal/output/output.go
zhi 7d3cff7d95 feat: implement core CLI packages and Phase 3 commands
- config: resolve binary dir, load/save .hf-config.json
- mode: detect padded-cell vs manual mode via pass_mgr
- client: HTTP client wrapper with auth header support
- passmgr: pass_mgr integration (get-secret, set, generate)
- output: human-readable + JSON output formatting with tables
- help: help and help-brief renderer for groups/commands
- commands: version, health, config (--url, --acc-mgr-token, show)
- auth: token resolution helper (padded-cell auto / manual explicit)
- main: command dispatcher with --json global flag support
- README: updated with current package layout and status
2026-03-21 13:50:29 +00:00

94 lines
2.1 KiB
Go

// Package output handles human-readable and JSON output formatting.
package output
import (
"encoding/json"
"fmt"
"os"
"strings"
)
// JSONMode is true when --json flag is provided.
var JSONMode bool
// PrintJSON prints data as indented JSON to stdout.
func PrintJSON(v interface{}) {
data, err := json.MarshalIndent(v, "", " ")
if err != nil {
fmt.Fprintf(os.Stderr, "error: cannot marshal JSON: %v\n", err)
os.Exit(1)
}
fmt.Println(string(data))
}
// PrintKeyValue prints a set of key-value pairs in human-readable format.
func PrintKeyValue(pairs ...string) {
if len(pairs)%2 != 0 {
pairs = append(pairs, "")
}
maxKeyLen := 0
for i := 0; i < len(pairs); i += 2 {
if len(pairs[i]) > maxKeyLen {
maxKeyLen = len(pairs[i])
}
}
for i := 0; i < len(pairs); i += 2 {
fmt.Printf("%-*s %s\n", maxKeyLen, pairs[i]+":", pairs[i+1])
}
}
// PrintTable prints a simple table with headers and rows.
func PrintTable(headers []string, rows [][]string) {
if len(rows) == 0 {
fmt.Println("(no results)")
return
}
widths := make([]int, len(headers))
for i, h := range headers {
widths[i] = len(h)
}
for _, row := range rows {
for i, cell := range row {
if i < len(widths) && len(cell) > widths[i] {
widths[i] = len(cell)
}
}
}
// header
parts := make([]string, len(headers))
for i, h := range headers {
parts[i] = fmt.Sprintf("%-*s", widths[i], h)
}
fmt.Println(strings.Join(parts, " "))
// separator
seps := make([]string, len(headers))
for i := range headers {
seps[i] = strings.Repeat("-", widths[i])
}
fmt.Println(strings.Join(seps, " "))
// rows
for _, row := range rows {
parts := make([]string, len(headers))
for i := range headers {
cell := ""
if i < len(row) {
cell = row[i]
}
parts[i] = fmt.Sprintf("%-*s", widths[i], cell)
}
fmt.Println(strings.Join(parts, " "))
}
}
// Error prints an error message to stderr and exits.
func Error(msg string) {
fmt.Fprintln(os.Stderr, msg)
os.Exit(1)
}
// Errorf prints a formatted error message to stderr and exits.
func Errorf(format string, args ...interface{}) {
fmt.Fprintf(os.Stderr, format+"\n", args...)
os.Exit(1)
}