Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion cmd/dispatch/notes.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"encoding/csv"
"encoding/json"
"fmt"
"io"
Expand Down Expand Up @@ -40,7 +41,7 @@ func runNotes(w io.Writer, args []string) error {
if len(rest) > 0 {
rest = rest[1:]
}
if len(rest) == 0 || rest[0] == "list" || rest[0] == "--json" {
if len(rest) == 0 || rest[0] == "list" || rest[0] == "--json" || rest[0] == "--csv" {
return runNotesList(w, rest)
}

Expand All @@ -58,17 +59,23 @@ func runNotes(w io.Writer, args []string) error {

func runNotesList(w io.Writer, args []string) error {
jsonOut := false
csvOut := false
if len(args) > 0 && args[0] == "list" {
args = args[1:]
}
for _, arg := range args {
switch arg {
case "--json":
jsonOut = true
case "--csv":
csvOut = true
default:
return fmt.Errorf("notes list does not take arguments, got %q", arg)
}
}
if jsonOut && csvOut {
return fmt.Errorf("--json and --csv cannot be combined")
}

cfg, err := configLoadFn()
if err != nil {
Expand All @@ -84,6 +91,9 @@ func runNotesList(w io.Writer, args []string) error {
enc.SetIndent("", " ")
return enc.Encode(report)
}
if csvOut {
return writeNotesCSV(w, report)
}
writeNotesText(w, report)
return nil
}
Expand Down Expand Up @@ -215,10 +225,25 @@ func writeNotesText(w io.Writer, report notesReport) {
idWidth = len(entry.ID)
}
}

for _, entry := range report.Notes {
fmt.Fprintf(w, " %-*s %s\n", idWidth, entry.ID, entry.Note)
if entry.Summary != "" {
fmt.Fprintf(w, " %-*s %s\n", idWidth, "", entry.Summary)
}
}
}

func writeNotesCSV(w io.Writer, report notesReport) error {
cw := csv.NewWriter(w)
if err := cw.Write([]string{"id", "summary", "note"}); err != nil {
return err
}
for _, entry := range report.Notes {
if err := cw.Write([]string{entry.ID, csvSafe(entry.Summary), csvSafe(entry.Note)}); err != nil {
return err
}
}
cw.Flush()
return cw.Error()
}
24 changes: 24 additions & 0 deletions cmd/dispatch/notes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,29 @@ func TestRunNotesListJSON(t *testing.T) {
}
}

func TestRunNotesListCSV(t *testing.T) {
withConfigSeams(t, notedConfig())
withNotesList(t, func(data.FilterOptions) ([]data.Session, error) { return notedSessions(), nil })

var buf bytes.Buffer
if err := runNotes(&buf, []string{"notes", "--csv"}); err != nil {
t.Fatalf("runNotes csv shortcut: %v", err)
}
out := buf.String()
for _, want := range []string{
"id,summary,note",
"a,Auth fix,follow up",
"b,Build command,ready to ship",
} {
if !strings.Contains(out, want) {
t.Errorf("CSV output missing %q:\n%s", want, out)
}
}
if strings.Contains(out, "orphan note") {
t.Fatalf("orphan note should not appear:\n%s", out)
}
}

func TestRunNotesGetSetClear(t *testing.T) {
cfg := withConfigSeams(t, config.Default())

Expand Down Expand Up @@ -143,6 +166,7 @@ func TestRunNotesErrors(t *testing.T) {
{"notes", "set", "ses-1", "--stdin", "extra"},
{"notes", "clear"},
{"notes", "list", "extra"},
{"notes", "list", "--json", "--csv"},
} {
if err := runNotes(&bytes.Buffer{}, args); err == nil {
t.Fatalf("expected error for args %v", args)
Expand Down