feat: ui.recentIcon marks items used lately with ◷, and lazysecrets list --recent
This commit is contained in:
9 files changed
+87
-22
No files matched your search
+17
-10
@@ -41,7 +41,7 @@ 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, st *store.Store, 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, withRecent 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")
|
||||
@@ -49,6 +49,7 @@ func listCmd(providers []provider.Provider, st *store.Store, cachePath string, t
|
||||
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)")
|
||||
stars := fs.Bool("stars", true, "put ★ before starred names, in the theme's favouriteColor (text)")
|
||||
recent := fs.Bool("recent", withRecent, "put ◷ before names used lately, in mutedColor (text; default ui.recentIcon)")
|
||||
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 {
|
||||
@@ -79,7 +80,7 @@ func listCmd(providers []provider.Provider, st *store.Store, cachePath string, t
|
||||
case "text":
|
||||
write = func(e listing.Entry) error {
|
||||
colored := *color == "always"
|
||||
mark := markOf(e, theme, iconSet, *stars, colored)
|
||||
mark := markOf(e, theme, iconSet, *stars, *recent, colored)
|
||||
name := nameOf(e, theme, colored)
|
||||
why := errorOf(e, theme, colored)
|
||||
// A tab or line break in a name would break the line up.
|
||||
@@ -165,17 +166,23 @@ func nameOf(e listing.Entry, theme styles.Styles, color bool) string {
|
||||
}
|
||||
|
||||
// markOf is what goes before the name, in a field of its own so a search
|
||||
// leaves it out: ★ for a starred entry (as the TUI marks them; a space
|
||||
// as wide for the rest, so names line up), and the provider's icon.
|
||||
func markOf(e listing.Entry, theme styles.Styles, iconSet icons.Set, stars, color bool) string {
|
||||
// leaves it out: ★ for a starred entry and ◷ for one used lately (as the
|
||||
// TUI marks them; a space as wide for the rest, so names line up), and
|
||||
// the provider's icon.
|
||||
func markOf(e listing.Entry, theme styles.Styles, iconSet icons.Set, stars, recent, color bool) string {
|
||||
render := renderer(color)
|
||||
var parts []string
|
||||
if stars {
|
||||
star := " "
|
||||
if e.Starred {
|
||||
star = render(theme.Favourite, "★")
|
||||
mark := func(on bool, st lipgloss.Style, s string) {
|
||||
if !on {
|
||||
s = " "
|
||||
}
|
||||
parts = append(parts, star)
|
||||
parts = append(parts, render(st, s))
|
||||
}
|
||||
if stars {
|
||||
mark(e.Starred, theme.Favourite, "★")
|
||||
}
|
||||
if recent {
|
||||
mark(e.Recent, theme.Muted, "◷")
|
||||
}
|
||||
kind := provider.Kind("")
|
||||
for _, k := range []provider.Kind{provider.KindAzure, provider.KindDatabricks, provider.KindRepo} {
|
||||
|
||||
@@ -35,12 +35,28 @@ func TestListMarks(t *testing.T) {
|
||||
{listing.Entry{Provider: "azure", Starred: true}, false, false, icons.None, ""},
|
||||
{listing.Entry{Provider: "azure", Starred: true}, true, true, icons.None, styles.Default().Favourite.Render("★")},
|
||||
} {
|
||||
if got := markOf(c.e, styles.Default(), c.set, c.stars, c.color); got != c.want {
|
||||
if got := markOf(c.e, styles.Default(), c.set, c.stars, false, c.color); got != c.want {
|
||||
t.Errorf("markOf(starred %v, stars %v, colour %v) = %q, want %q", c.e.Starred, c.stars, c.color, got, c.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestListRecentMark(t *testing.T) {
|
||||
az := icons.NerdFont.Azure
|
||||
for _, c := range []struct {
|
||||
e listing.Entry
|
||||
want string
|
||||
}{
|
||||
{listing.Entry{Provider: "azure", Starred: true, Recent: true}, "★ ◷ " + az},
|
||||
{listing.Entry{Provider: "azure", Recent: true}, " ◷ " + az},
|
||||
{listing.Entry{Provider: "azure", Starred: true}, "★ " + az}, // as wide as ◷
|
||||
} {
|
||||
if got := markOf(c.e, styles.Default(), icons.NerdFont, true, true, false); got != c.want {
|
||||
t.Errorf("markOf(starred %v, recent %v) = %q, want %q", c.e.Starred, c.e.Recent, got, c.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestListErrors(t *testing.T) {
|
||||
e := listing.Entry{Provider: "azure", Path: []string{"platform-prod", "kv-restricted"}, Error: "403 Forbidden"}
|
||||
if got := nameOf(e, styles.Default(), false); got != "platform-prod / kv-restricted" {
|
||||
|
||||
@@ -298,6 +298,8 @@ Flags:
|
||||
}
|
||||
}
|
||||
|
||||
recentIcon := cfg.UI.RecentIcon != nil && *cfg.UI.RecentIcon
|
||||
|
||||
// Stars, notes and the layout. Demo mode keeps them in memory, so
|
||||
// sample vaults never end up in the real file.
|
||||
stateDir, err := config.StateDir()
|
||||
@@ -387,7 +389,7 @@ Flags:
|
||||
if d, err := config.CacheDir(); err == nil && !*demo && config.On(cfg.Storage.Cache) {
|
||||
cachePath = filepath.Join(d, "cache.json")
|
||||
}
|
||||
return listCmd(providers, st, cachePath, timeoutFor, theme, *icons, listArgs, os.Stdout)
|
||||
return listCmd(providers, st, cachePath, timeoutFor, theme, *icons, recentIcon, listArgs, os.Stdout)
|
||||
}
|
||||
if shareArgs != nil {
|
||||
// The files from a repo, the key from whichever provider it's
|
||||
@@ -478,6 +480,7 @@ Flags:
|
||||
ShareRules: shareRules(cfg),
|
||||
Open: open,
|
||||
OpenAction: openAction,
|
||||
RecentIcon: recentIcon,
|
||||
Styles: &theme,
|
||||
DefaultFg: defaultFg,
|
||||
})
|
||||
|
||||
Reference in new issue
Block a user