diff --git a/cmd/lazysecrets/list.go b/cmd/lazysecrets/list.go index 9550fbc..78bad5e 100644 --- a/cmd/lazysecrets/list.go +++ b/cmd/lazysecrets/list.go @@ -72,7 +72,8 @@ func listCmd(providers []provider.Provider, cachePath string, timeout func(provi switch *format { case "text": write = func(e listing.Entry) error { - _, err := fmt.Fprintf(out, "%s\t%s\n", nameOf(e, theme, iconSet, *color == "always"), e.Link) + // A tab or line break in a name would break the line up. + _, err := fmt.Fprintf(out, "%s\t%s\n", oneLine.Replace(nameOf(e, theme, iconSet, *color == "always")), e.Link) return err } case "json": @@ -121,6 +122,8 @@ func listCmd(providers []provider.Provider, cachePath string, timeout func(provi return nil // or the reader has what it wanted } +var oneLine = strings.NewReplacer("\t", " ", "\r\n", " ", "\n", " ", "\r", " ") + // nameOf is an entry's name for the text format: the provider's icon, // the path with the item's own name standing out, and the account. A // list that couldn't be read has ✗ for the icon, and why after it. diff --git a/internal/listing/listing.go b/internal/listing/listing.go index 7012ce1..9a06717 100644 --- a/internal/listing/listing.go +++ b/internal/listing/listing.go @@ -312,10 +312,22 @@ func (r result) failed() Entry { default: e = Entry{Kind: "source", Provider: kindOf(r.p.Kind()), Path: []string{r.p.Label()}} } - e.Error = r.err.Error() + e.Error = firstLine(r.err.Error()) return e } +// firstLine is an error's first line, the summary (Azure's go on with +// the caller's IDs and more): an entry is one line. Tabs, which would +// split it into columns, are spaces. +func firstLine(s string) string { + for line := range strings.Lines(s) { + if line = strings.TrimSpace(line); line != "" { + return strings.ReplaceAll(line, "\t", " ") + } + } + return "unreadable" +} + func kindOf(k provider.Kind) string { return strings.ToLower(string(k)) } // accountOf is the account part of a source's provider label ("alice" in diff --git a/internal/listing/listing_test.go b/internal/listing/listing_test.go index be61c74..9908d24 100644 --- a/internal/listing/listing_test.go +++ b/internal/listing/listing_test.go @@ -211,3 +211,15 @@ func TestListKinds(t *testing.T) { t.Error("a list that failed wasn't listed") } } + +func TestErrorsAreOneLine(t *testing.T) { + for in, want := range map[string]string{ + "403 Forbidden: Caller is not authorized\nCaller: appid=x;oid=y\nVault: kv;location=z": "403 Forbidden: Caller is not authorized", + "\n timeout\tafter 30s\n": "timeout after 30s", + "": "unreadable", + } { + if got := firstLine(in); got != want { + t.Errorf("firstLine(%q) = %q, want %q", in, got, want) + } + } +}