解决issue3:优化 table 输出格式及 batch-close

同时新增batch-close: 新增 Duration 字段记录批量操作耗时
This commit is contained in:
yetja 2026-05-26 15:14:57 +08:00
parent 1276744ee2
commit 60b6ea6f6c
2 changed files with 44 additions and 9 deletions

View File

@ -66,22 +66,44 @@ func printTable(w io.Writer, envelope *Envelope) error {
return nil
}
// Try to render as table if data is a slice of maps
switch data := envelope.Data.(type) {
case []interface{}:
return printSliceTable(w, data)
case map[string]interface{}:
// For maps with nested structures, prefer JSON
if slice := findSliceInMap(data); slice != nil {
return printSliceTable(w, slice)
}
if hasComplexValues(data) {
return printJSON(w, envelope)
}
return printMapTable(w, data)
default:
// Fallback to JSON
return printJSON(w, envelope)
}
}
func findSliceInMap(m map[string]interface{}) []interface{} {
for _, key := range []string{
"issues", "pull_requests", "milestones", "webhooks", "issue_tags",
"commits", "files", "members", "collaborators", "users", "branches",
"releases", "entries", "tags", "watchers",
} {
if v, ok := m[key]; ok {
if slice, ok := v.([]interface{}); ok && len(slice) > 0 {
return slice
}
}
}
for _, v := range m {
if slice, ok := v.([]interface{}); ok && len(slice) > 0 {
if _, isMap := slice[0].(map[string]interface{}); isMap {
return slice
}
}
}
return nil
}
func hasComplexValues(m map[string]interface{}) bool {
for _, v := range m {
switch v.(type) {
@ -98,7 +120,6 @@ func printSliceTable(w io.Writer, items []interface{}) error {
return nil
}
// Collect headers from first item
first, ok := items[0].(map[string]interface{})
if !ok {
data, _ := json.MarshalIndent(items, "", " ")
@ -109,7 +130,6 @@ func printSliceTable(w io.Writer, items []interface{}) error {
headers := collectKeys(first)
tw := tabwriter.NewWriter(w, 0, 4, 2, ' ', 0)
// Print headers
fmt.Fprintln(tw, strings.Join(headers, "\t"))
dashes := make([]string, len(headers))
for i, h := range headers {
@ -117,7 +137,6 @@ func printSliceTable(w io.Writer, items []interface{}) error {
}
fmt.Fprintln(tw, strings.Join(dashes, "\t"))
// Print rows
for _, item := range items {
m, ok := item.(map[string]interface{})
if !ok {
@ -144,7 +163,6 @@ func printMapTable(w io.Writer, m map[string]interface{}) error {
func collectKeys(m map[string]interface{}) []string {
keys := make([]string, 0, len(m))
// Prefer common keys first
priority := []string{"id", "name", "login", "title", "status", "state", "created_at", "updated_at"}
seen := map[string]bool{}
for _, k := range priority {
@ -170,10 +188,21 @@ func formatValue(v interface{}) string {
case reflect.Map, reflect.Slice:
data, _ := json.Marshal(v)
s := string(data)
if len(s) > 60 {
return s[:57] + "..."
if len(s) > 50 {
return s[:47] + "..."
}
return s
case reflect.Bool:
if v.(bool) {
return "yes"
}
return "no"
case reflect.Float64:
f := v.(float64)
if f == float64(int64(f)) {
return fmt.Sprintf("%d", int64(f))
}
return fmt.Sprintf("%v", v)
default:
return fmt.Sprintf("%v", v)
}

View File

@ -6,6 +6,7 @@ import (
"os"
"strconv"
"strings"
"time"
"github.com/gitlink-org/gitlink-cli/shortcuts/common"
)
@ -25,6 +26,7 @@ type batchSummary struct {
Total int `json:"total" yaml:"total"`
Succeeded int `json:"succeeded" yaml:"succeeded"`
Failed int `json:"failed" yaml:"failed"`
Duration string `json:"duration" yaml:"duration"`
Results []batchResult `json:"results" yaml:"results"`
}
@ -46,6 +48,8 @@ func runBatchClose(ctx *common.RuntimeContext) error {
return err
}
start := time.Now()
numbers, err := collectIssueNumbers(ctx.Arg("numbers"), ctx.Arg("from"))
if err != nil {
return err
@ -82,6 +86,8 @@ func runBatchClose(ctx *common.RuntimeContext) error {
summary.Results = append(summary.Results, result)
}
summary.Duration = time.Since(start).String()
if err := ctx.OutputData(summary); err != nil {
return err
}