feat: lazysecrets list marks starred and recent entries, and --starred-icon shows the stars

This commit is contained in:
keb committed 2026-10-14 21:24:01 +02:00
1 parent 50156d706e
commit 77e3fcd551
5 files changed
+74 -3

No files matched your search

+22 -1
View File
@@ -19,6 +19,7 @@ import (
"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/store"
"git.kebcloud.no/keb/lazysecrets/internal/ui/icons"
"git.kebcloud.no/keb/lazysecrets/internal/ui/styles"
)
@@ -39,13 +40,14 @@ import (
// follows as it loads. A list that can't be read is a line too, as it
// fails: the vault or source, then ✗ and why in the theme's error colour.
// They're in the output rather than on stderr, which would draw over fzf.
func listCmd(providers []provider.Provider, cachePath string, timeout func(provider.Kind) time.Duration, theme styles.Styles, withIcons bool, args []string, out io.Writer) error {
func listCmd(providers []provider.Provider, st *store.Store, cachePath string, timeout func(provider.Kind) time.Duration, theme styles.Styles, withIcons bool, args []string, out 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: 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)")
starIcon := fs.Bool("starred-icon", false, "put ★ before starred names, in the theme's favouriteColor (text)")
kinds := fs.String("kind", "", "only these kinds, comma-separated: "+strings.Join(listing.Kinds, ", ")+" (vault: also scopes and repo files)")
showErrors := fs.Bool("errors", true, "list the lists that can't be read, with why (text: ✗ lines; json: \"error\")")
if err := fs.Parse(args); err != nil {
@@ -77,6 +79,9 @@ func listCmd(providers []provider.Provider, cachePath string, timeout func(provi
write = func(e listing.Entry) error {
// A tab or line break in a name would break the line up.
name := nameOf(e, theme, iconSet, *color == "always")
if *starIcon {
name = starOf(e, theme, *color == "always") + name
}
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
@@ -110,6 +115,10 @@ func listCmd(providers []provider.Provider, cachePath string, timeout func(provi
}
f = listing.Run(context.Background(), listing.Options{
Providers: providers, Cache: f, MaxAge: *maxAge, Cached: *cached, Kinds: only, Timeout: timeout,
Mark: func(link, account string) (bool, bool) {
n := st.Node(link)
return n.StarredFor(account), !n.LastUsed.IsZero()
},
}, emit)
if cachePath != "" && !*cached {
byID := map[string]provider.Provider{}
@@ -129,6 +138,18 @@ func listCmd(providers []provider.Provider, cachePath string, timeout func(provi
var oneLine = strings.NewReplacer("\t", " ", "\r\n", " ", "\n", " ", "\r", " ")
// starOf is ★ for a starred entry, as the TUI marks them, and spaces
// the same width for the rest, so names line up.
func starOf(e listing.Entry, theme styles.Styles, color bool) string {
switch {
case !e.Starred:
return " "
case color:
return theme.Favourite.Render("★") + " "
}
return "★ "
}
// 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 {