diff --git a/cmd/lazysecrets/list.go b/cmd/lazysecrets/list.go index 2b26f46..5a787b9 100644 --- a/cmd/lazysecrets/list.go +++ b/cmd/lazysecrets/list.go @@ -28,9 +28,10 @@ import ( // // lazysecrets list | fzf --ansi --with-nth='2..-3' --accept-nth=-1 // -// Each line is the kind, the name, the account and the link, -// tab-separated (all but the name one word each, so even fields split on -// spaces keep them first and last): the name coloured from the theme, +// Each line is the kind, the name, why it couldn't be read (empty unless +// it failed), the account and the link, tab-separated: kind, account and +// link are one word each, so even fields split on spaces keep them first +// and last two. The name is coloured from the theme, // with the provider's icon (as in the TUI: --icons, LAZYSECRETS_ICONS, // ui.icons); the link never is. // @@ -42,7 +43,7 @@ func listCmd(providers []provider.Provider, cachePath string, timeout func(provi fs := flag.NewFlagSet("list", flag.ContinueOnError) cached := fs.Bool("cached", false, "only what's cached, and repos: load nothing from Azure or Databricks") maxAge := fs.Duration("max-age", 2*time.Minute, "load cached lists older than this again") - format := fs.String("format", "text", "text: kind, name, account and link, tab-separated; json: an object per line") + format := fs.String("format", "text", "text: kind, name, error, account and link, tab-separated; json: an object per line") color := fs.String("color", "always", "colour the names (text): always or never; fzf needs --ansi") iconsOn := fs.Bool("icons", withIcons, "put the provider's Nerd Font icon before names (text)") kinds := fs.String("kind", "", "only these kinds, comma-separated: "+strings.Join(listing.Kinds, ", ")+" (vault: also scopes and repo files)") @@ -75,7 +76,9 @@ func listCmd(providers []provider.Provider, cachePath string, timeout func(provi case "text": write = func(e listing.Entry) error { // A tab or line break in a name would break the line up. - _, err := fmt.Fprintf(out, "%s\t%s\t%s\t%s\n", e.Kind, oneLine.Replace(nameOf(e, theme, iconSet, *color == "always")), e.Account, e.Link) + name := nameOf(e, theme, iconSet, *color == "always") + why := errorOf(e, theme, *color == "always") + _, err := fmt.Fprintf(out, "%s\t%s\t%s\t%s\t%s\n", e.Kind, oneLine.Replace(name), oneLine.Replace(why), e.Account, e.Link) return err } case "json": @@ -126,9 +129,17 @@ func listCmd(providers []provider.Provider, cachePath string, timeout func(provi var oneLine = strings.NewReplacer("\t", " ", "\r\n", " ", "\n", " ", "\r", " ") +// errorOf is why a list couldn't be read, or "": with colour, a red ✗ +// before it, as the TUI marks lists it can't read. +func errorOf(e listing.Entry, theme styles.Styles, color bool) string { + if e.Error == "" || !color { + return e.Error + } + return theme.Error.Render("✗ " + e.Error) +} + // 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 ✗ and why after it. +// the path with the item's own name standing out, and the account. func nameOf(e listing.Entry, theme styles.Styles, iconSet icons.Set, color bool) string { render := func(st lipgloss.Style, s string) string { if !color || s == "" { @@ -153,8 +164,5 @@ func nameOf(e listing.Entry, theme styles.Styles, iconSet icons.Set, color bool) if e.AccountLabel != "" { name += render(theme.Muted, " · "+e.AccountLabel) } - if e.Error != "" { - name += " " + render(theme.Error, "✗ "+e.Error) - } return render(theme.Kind(kind), strings.TrimSuffix(icon, " ")) + strings.Repeat(" ", min(len(icon), 1)) + name } diff --git a/cmd/lazysecrets/list_test.go b/cmd/lazysecrets/list_test.go index 3791044..6694b82 100644 --- a/cmd/lazysecrets/list_test.go +++ b/cmd/lazysecrets/list_test.go @@ -26,11 +26,16 @@ func TestListNames(t *testing.T) { func TestListErrorNames(t *testing.T) { e := listing.Entry{Provider: "azure", Path: []string{"platform-prod", "kv-restricted"}, Error: "403 Forbidden"} - if got := nameOf(e, styles.Default(), icons.NerdFont, false); got != icons.NerdFont.Azure+" platform-prod / kv-restricted ✗ 403 Forbidden" { + if got := nameOf(e, styles.Default(), icons.NerdFont, false); got != icons.NerdFont.Azure+" platform-prod / kv-restricted" { + t.Errorf("the name has more: %q", got) + } + if got := errorOf(e, styles.Default(), false); got != "403 Forbidden" { t.Errorf("plain: %q", got) } - red := styles.Default().Error.Render("✗ 403 Forbidden") - if got := nameOf(e, styles.Default(), icons.NerdFont, true); !strings.HasSuffix(got, red) { - t.Errorf("why isn't in the error colour: %q", got) + if got := errorOf(e, styles.Default(), true); got != styles.Default().Error.Render("✗ 403 Forbidden") { + t.Errorf("why isn't a red ✗: %q", got) + } + if got := errorOf(listing.Entry{}, styles.Default(), true); got != "" { + t.Errorf("no error: %q", got) } }