Released v1
This commit is contained in:
@@ -0,0 +1,239 @@
|
||||
package output
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"reflect"
|
||||
"text/tabwriter"
|
||||
|
||||
"git.franklin.lab/steve.cliff/pcli/model"
|
||||
)
|
||||
|
||||
func Print(data any, format string, w io.Writer) error {
|
||||
if format == "table" {
|
||||
return printTable(data, w)
|
||||
}
|
||||
return printJSON(data, w)
|
||||
}
|
||||
|
||||
func printJSON(data any, w io.Writer) error {
|
||||
envelope := model.Envelope{
|
||||
Data: data,
|
||||
Error: nil,
|
||||
}
|
||||
encoder := json.NewEncoder(w)
|
||||
encoder.SetIndent("", " ")
|
||||
return encoder.Encode(envelope)
|
||||
}
|
||||
|
||||
func PrintError(err error, format string, w io.Writer) error {
|
||||
if format == "table" {
|
||||
fmt.Fprintf(os.Stderr, "Error: %s\n", err.Error())
|
||||
return nil
|
||||
}
|
||||
|
||||
errMsg := err.Error()
|
||||
envelope := model.Envelope{
|
||||
Data: nil,
|
||||
Error: &errMsg,
|
||||
}
|
||||
encoder := json.NewEncoder(w)
|
||||
encoder.SetIndent("", " ")
|
||||
return encoder.Encode(envelope)
|
||||
}
|
||||
|
||||
func PrintErrorWithCommand(err error, format string, w io.Writer, command string) error {
|
||||
if format == "table" {
|
||||
fmt.Fprintf(os.Stderr, "Error in %s command: %s\n", command, err.Error())
|
||||
return nil
|
||||
}
|
||||
|
||||
errMsg := fmt.Sprintf("Error in %s command: %s", command, err.Error())
|
||||
envelope := model.Envelope{
|
||||
Data: nil,
|
||||
Error: &errMsg,
|
||||
}
|
||||
encoder := json.NewEncoder(w)
|
||||
encoder.SetIndent("", " ")
|
||||
return encoder.Encode(envelope)
|
||||
}
|
||||
|
||||
func printTable(data any, w io.Writer) error {
|
||||
if data == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
tw := tabwriter.NewWriter(w, 0, 0, 2, ' ', 0)
|
||||
defer tw.Flush()
|
||||
|
||||
v := reflect.ValueOf(data)
|
||||
|
||||
if v.Kind() == reflect.Slice {
|
||||
if v.Len() == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
elemType := v.Index(0).Type()
|
||||
switch elemType.Name() {
|
||||
case "Project":
|
||||
return printProjectTable(data.([]model.Project), tw)
|
||||
case "Board":
|
||||
return printBoardTable(data.([]model.Board), tw)
|
||||
case "Card":
|
||||
return printCardTable(data.([]model.Card), tw)
|
||||
case "CardWithList":
|
||||
return printCardWithListTable(data.([]model.CardWithList), tw)
|
||||
case "Comment":
|
||||
return printCommentTable(data.([]model.Comment), tw)
|
||||
case "TaskList":
|
||||
return printTaskListTable(data.([]model.TaskList), tw)
|
||||
case "Task":
|
||||
return printTaskTable(data.([]model.Task), tw)
|
||||
case "Label":
|
||||
return printLabelTable(data.([]model.Label), tw)
|
||||
case "Action":
|
||||
return printActionTable(data.([]model.Action), tw)
|
||||
default:
|
||||
return fmt.Errorf("unsupported slice type for table output: %s", elemType.Name())
|
||||
}
|
||||
}
|
||||
|
||||
switch data := data.(type) {
|
||||
case *model.Project:
|
||||
return printProjectTable([]model.Project{*data}, tw)
|
||||
case *model.Board:
|
||||
return printBoardTable([]model.Board{*data}, tw)
|
||||
case *model.Card:
|
||||
return printCardTable([]model.Card{*data}, tw)
|
||||
case *model.Comment:
|
||||
return printCommentTable([]model.Comment{*data}, tw)
|
||||
case *model.TaskList:
|
||||
return printTaskListTable([]model.TaskList{*data}, tw)
|
||||
case *model.Task:
|
||||
return printTaskTable([]model.Task{*data}, tw)
|
||||
case *model.Label:
|
||||
return printLabelTable([]model.Label{*data}, tw)
|
||||
case model.StatusSummary:
|
||||
return printStatusTable(data, tw)
|
||||
case *model.StatusSummary:
|
||||
return printStatusTable(*data, tw)
|
||||
default:
|
||||
return fmt.Errorf("unsupported type for table output: %T", data)
|
||||
}
|
||||
}
|
||||
|
||||
func printProjectTable(projects []model.Project, tw *tabwriter.Writer) error {
|
||||
fmt.Fprintln(tw, "ID\tNAME\tDESCRIPTION\tHIDDEN")
|
||||
for _, p := range projects {
|
||||
desc := ""
|
||||
if p.Description != nil {
|
||||
desc = *p.Description
|
||||
}
|
||||
fmt.Fprintf(tw, "%s\t%s\t%s\t%v\n", p.ID, p.Name, desc, p.IsHidden)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func printBoardTable(boards []model.Board, tw *tabwriter.Writer) error {
|
||||
fmt.Fprintln(tw, "ID\tNAME\tPROJECT_ID\tDEFAULT_VIEW")
|
||||
for _, b := range boards {
|
||||
fmt.Fprintf(tw, "%s\t%s\t%s\t%s\n", b.ID, b.Name, b.ProjectID, b.DefaultView)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func printCardTable(cards []model.Card, tw *tabwriter.Writer) error {
|
||||
fmt.Fprintln(tw, "ID\tNAME\tLIST_ID\tTYPE\tCLOSED")
|
||||
for _, c := range cards {
|
||||
fmt.Fprintf(tw, "%s\t%s\t%s\t%s\t%v\n", c.ID, c.Name, c.ListID, c.Type, c.IsClosed)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func printCardWithListTable(cards []model.CardWithList, tw *tabwriter.Writer) error {
|
||||
fmt.Fprintln(tw, "ID\tNAME\tLIST\tTYPE\tCLOSED")
|
||||
for _, c := range cards {
|
||||
fmt.Fprintf(tw, "%s\t%s\t%s\t%s\t%v\n", c.ID, c.Name, c.ListName, c.Type, c.IsClosed)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func printCommentTable(comments []model.Comment, tw *tabwriter.Writer) error {
|
||||
fmt.Fprintln(tw, "ID\tCARD_ID\tTEXT\tCREATED_AT")
|
||||
for _, c := range comments {
|
||||
createdAt := ""
|
||||
if c.CreatedAt != nil {
|
||||
createdAt = *c.CreatedAt
|
||||
}
|
||||
fmt.Fprintf(tw, "%s\t%s\t%s\t%s\n", c.ID, c.CardID, c.Text, createdAt)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func printTaskListTable(taskLists []model.TaskList, tw *tabwriter.Writer) error {
|
||||
fmt.Fprintln(tw, "ID\tNAME\tCARD_ID\tPOSITION")
|
||||
for _, tl := range taskLists {
|
||||
fmt.Fprintf(tw, "%s\t%s\t%s\t%.0f\n", tl.ID, tl.Name, tl.CardID, tl.Position)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func printTaskTable(tasks []model.Task, tw *tabwriter.Writer) error {
|
||||
fmt.Fprintln(tw, "ID\tNAME\tTASK_LIST_ID\tCOMPLETED")
|
||||
for _, t := range tasks {
|
||||
fmt.Fprintf(tw, "%s\t%s\t%s\t%v\n", t.ID, t.Name, t.TaskListID, t.IsCompleted)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func printLabelTable(labels []model.Label, tw *tabwriter.Writer) error {
|
||||
fmt.Fprintln(tw, "ID\tNAME\tCOLOR\tBOARD_ID")
|
||||
for _, l := range labels {
|
||||
name := ""
|
||||
if l.Name != nil {
|
||||
name = *l.Name
|
||||
}
|
||||
fmt.Fprintf(tw, "%s\t%s\t%s\t%s\n", l.ID, name, l.Color, l.BoardID)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func printActionTable(actions []model.Action, tw *tabwriter.Writer) error {
|
||||
fmt.Fprintln(tw, "ID\tTYPE\tCARD_ID\tCREATED_AT")
|
||||
for _, a := range actions {
|
||||
createdAt := ""
|
||||
if a.CreatedAt != nil {
|
||||
createdAt = *a.CreatedAt
|
||||
}
|
||||
fmt.Fprintf(tw, "%s\t%s\t%s\t%s\n", a.ID, a.Type, a.CardID, createdAt)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func printStatusTable(summary model.StatusSummary, tw *tabwriter.Writer) error {
|
||||
// Print total board count
|
||||
fmt.Fprintf(tw, "%d boards\n\n", summary.TotalBoards)
|
||||
|
||||
// Print each board with its lists
|
||||
for i, board := range summary.Boards {
|
||||
fmt.Fprintf(tw, "Board: %s\n", board.Name)
|
||||
fmt.Fprintln(tw, "LIST\tCARDS")
|
||||
|
||||
for _, list := range board.Lists {
|
||||
cardsText := fmt.Sprintf("%d", list.OpenCards)
|
||||
if list.ClosedCards > 0 {
|
||||
cardsText += fmt.Sprintf(" (%d closed)", list.ClosedCards)
|
||||
}
|
||||
fmt.Fprintf(tw, "%s\t%s\n", list.Name, cardsText)
|
||||
}
|
||||
|
||||
// Add blank line between boards (except last one)
|
||||
if i < len(summary.Boards)-1 {
|
||||
fmt.Fprintln(tw)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user