feat: lazysecrets list colours names from the theme, with icons

This commit is contained in:
keb committed 2026-10-14 21:24:01 +02:00
1 parent b1455451e6
commit e99462bd21
4 files changed
+83 -10

No files matched your search

+48 -7
View File
@@ -13,38 +13,50 @@ import (
"syscall"
"time"
"charm.land/lipgloss/v2"
"git.kebcloud.no/keb/lazysecrets/internal/cachefile"
"git.kebcloud.no/keb/lazysecrets/internal/listing"
"git.kebcloud.no/keb/lazysecrets/internal/provider"
"git.kebcloud.no/keb/lazysecrets/internal/ui/icons"
"git.kebcloud.no/keb/lazysecrets/internal/ui/styles"
)
// listCmd prints every source, vault and secret lazysecrets can find, one
// per line, for fzf, editor pickers and scripts:
//
// lazysecrets list | fzf --delimiter='\t' --with-nth=3 | cut -f1
// lazysecrets list | fzf --ansi --delimiter='\t' --with-nth=3 | cut -f1
//
// 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.
//
// What's cached prints at once; what's missing or older than --max-age
// follows as it loads. Lists that can't be read are reported on stderr.
func listCmd(providers []provider.Provider, cachePath string, timeout func(provider.Kind) time.Duration, args []string, out, errOut io.Writer) error {
func listCmd(providers []provider.Provider, cachePath string, timeout func(provider.Kind) time.Duration, theme styles.Styles, withIcons bool, args []string, out, errOut io.Writer) error {
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: link, kind and name, 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)")
if err := fs.Parse(args); err != nil {
return err
}
if fs.NArg() > 0 {
return fmt.Errorf("usage: lazysecrets list [--cached] [--max-age 2m] [--format text|json]")
}
if *color != "always" && *color != "never" {
return fmt.Errorf("--color: %q is not always or never", *color)
}
iconSet := icons.None
if *iconsOn {
iconSet = icons.NerdFont
}
var write func(listing.Entry) error
switch *format {
case "text":
write = func(e listing.Entry) error {
name := strings.Join(e.Path, " / ")
if e.Account != "" {
name += " · " + e.Account
}
_, err := fmt.Fprintf(out, "%s\t%s\t%s\n", e.Link, e.Kind, name)
_, err := fmt.Fprintf(out, "%s\t%s\t%s\n", e.Link, e.Kind, nameOf(e, theme, iconSet, *color == "always"))
return err
}
case "json":
@@ -95,3 +107,32 @@ func listCmd(providers []provider.Provider, cachePath string, timeout func(provi
}
return nil
}
// 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.
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 == "" {
return s
}
return st.Render(s)
}
kind := provider.Kind("")
for _, k := range []provider.Kind{provider.KindAzure, provider.KindDatabricks, provider.KindRepo} {
if strings.EqualFold(string(k), e.Provider) {
kind = k
}
}
icon := iconSet.Prefix(kind)
var name string
if n := len(e.Path); n > 0 {
if n > 1 {
name = render(theme.Muted, strings.Join(e.Path[:n-1], " / ")+" / ")
}
name += e.Path[n-1]
}
if e.Account != "" {
name += render(theme.Muted, " · "+e.Account)
}
return render(theme.Kind(kind), strings.TrimSuffix(icon, " ")) + strings.Repeat(" ", min(len(icon), 1)) + name
}