94 lines
2.0 KiB
Go
94 lines
2.0 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"strings"
|
|
"text/tabwriter"
|
|
)
|
|
|
|
// newTabWriter returns a tabwriter for stdout.
|
|
func newTabWriter() *tabwriter.Writer {
|
|
return tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
|
|
}
|
|
|
|
// printTable writes a header + rows to a tabwriter.
|
|
// headers: e.g. []string{"ID", "TITLE", "TYPE"}
|
|
// rows: [][]string
|
|
func printTable(w io.Writer, headers []string, rows [][]string) {
|
|
tw := tabwriter.NewWriter(w, 0, 0, 2, ' ', 0)
|
|
fmt.Fprintln(tw, strings.Join(headers, "\t"))
|
|
for _, row := range rows {
|
|
fmt.Fprintln(tw, strings.Join(row, "\t"))
|
|
}
|
|
tw.Flush()
|
|
}
|
|
|
|
// printJSON marshals v to JSON and writes to stdout.
|
|
func printJSON(v any) {
|
|
enc := json.NewEncoder(os.Stdout)
|
|
enc.SetIndent("", " ")
|
|
if err := enc.Encode(v); err != nil {
|
|
fmt.Fprintln(os.Stderr, "json encode error:", err)
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
// truncate returns s truncated to maxLen chars, with "..." if truncated.
|
|
func truncate(s string, maxLen int) string {
|
|
if len(s) <= maxLen {
|
|
return s
|
|
}
|
|
if maxLen <= 3 {
|
|
return s[:maxLen]
|
|
}
|
|
return s[:maxLen-3] + "..."
|
|
}
|
|
|
|
// depsStatus returns "OK" or "blocked: X,Y" for display.
|
|
func depsStatus(issue Issue) string {
|
|
if len(issue.Depends) == 0 {
|
|
return "OK"
|
|
}
|
|
if issue.DepsResolved {
|
|
return "OK"
|
|
}
|
|
return "blocked: " + strings.Join(issue.Depends, ",")
|
|
}
|
|
|
|
// joinStrings joins a slice with commas, or returns "-" if empty.
|
|
func joinStrings(ss []string) string {
|
|
if len(ss) == 0 {
|
|
return "-"
|
|
}
|
|
return strings.Join(ss, ",")
|
|
}
|
|
|
|
// pctBar returns a compact string like "75%" or "0%".
|
|
func pctBar(p int) string {
|
|
return fmt.Sprintf("%d%%", p)
|
|
}
|
|
|
|
// statusShort normalizes status for display.
|
|
func statusShort(s string) string {
|
|
switch strings.ToLower(s) {
|
|
case "in-progress":
|
|
return "in-progress"
|
|
case "completado", "done", "completed":
|
|
return "completado"
|
|
case "pendiente", "pending":
|
|
return "pendiente"
|
|
case "bloqueado", "blocked":
|
|
return "bloqueado"
|
|
case "deferred":
|
|
return "deferred"
|
|
default:
|
|
if s == "" {
|
|
return "-"
|
|
}
|
|
return s
|
|
}
|
|
}
|