fix: unambiguous repo key names, clearer config and key names, and a newer lazysecrets's files no longer stop an older one
This commit is contained in:
16 files changed
+189
-58
No files matched your search
@@ -79,6 +79,9 @@ type Options struct {
|
||||
// and keeps its state, for the status pane.
|
||||
ConfigFiles []string
|
||||
StatePath string
|
||||
// Warning shows when the window opens: what lazysecrets skipped
|
||||
// instead of failing to start.
|
||||
Warning string
|
||||
// Changelog is CHANGELOG.md, for the status pane.
|
||||
Changelog string
|
||||
// CacheFile keeps what was loaded between runs; "" keeps it for this
|
||||
@@ -474,6 +477,9 @@ func New(providers []provider.Provider, opts Options) Model {
|
||||
m.cachePath, m.placeDir, m.sourcesAt = opts.CacheFile, opts.Dir, map[string]time.Time{}
|
||||
m.shareKey, m.shareRules = opts.ShareKey, opts.ShareRules
|
||||
m.configFiles, m.statePath, m.changelog = opts.ConfigFiles, opts.StatePath, changelogFields(opts.Changelog)
|
||||
if opts.Warning != "" {
|
||||
m.flash = warning(opts.Warning)
|
||||
}
|
||||
if m.cachePath != "" {
|
||||
m.loadCacheFile()
|
||||
if len(m.sourceResults) > 0 {
|
||||
|
||||
@@ -122,3 +122,11 @@ func TestUpdateAsked(t *testing.T) {
|
||||
t.Errorf("U on a dev build:\n%s", dev.screen())
|
||||
}
|
||||
}
|
||||
|
||||
func TestStartupWarning(t *testing.T) {
|
||||
t.Parallel()
|
||||
d := newDriverOpts(t, Options{Warning: "theme: skipped unknown activeBorder"})
|
||||
if !strings.Contains(d.screen(), "theme: skipped unknown activeBorder") {
|
||||
t.Errorf("no warning:\n%s", d.screen())
|
||||
}
|
||||
}
|
||||
@@ -95,7 +95,7 @@ func (m *Map) Actions() []Action {
|
||||
a(Lists, "pane3", &m.Pane3, "Secrets pane", "move", "Focus the Secrets pane."),
|
||||
a(Lists, "pane4", &m.Pane4, "detail pane", "move", "Focus the detail pane."),
|
||||
a(Lists, "pane0", &m.Pane0, "status", "move", "Focus the status pane: version and updates, accounts, config files, links and the changelog, on the right."),
|
||||
a(Lists, "enter", &m.Enter, "open", "move", "Go into the selected item: from a subscription to its vaults, from a vault to its secrets. On a provider header, fold or unfold it."),
|
||||
a(Lists, "open", &m.Enter, "open", "move", "Go into the selected item: from a subscription to its vaults, from a vault to its secrets. On a provider header, fold or unfold it."),
|
||||
a(Lists, "back", &m.Back, "back", "move", "Go back: clear an applied filter, leave the versions view, or focus the previous pane."),
|
||||
|
||||
a(Lists, "filter", &m.Filter, "filter", "lists", "Filter the focused list by name, fuzzily: dbpw finds db-password. In Sources the provider and account match too."),
|
||||
@@ -103,7 +103,7 @@ func (m *Map) Actions() []Action {
|
||||
a(Lists, "nextTab", &m.NextTab, "next tab", "lists", "Next tab of the focused pane."),
|
||||
a(Lists, "sourcesView", &m.SourcesView, "grouped/flat sources", "lists", "Switch the Sources pane between grouped by provider and a flat list."),
|
||||
a(Lists, "star", &m.Favourite, "star", "lists", "Star or unstar the selected subscription, vault or secret, for the account showing it. Starred items get a ★ and sort first."),
|
||||
a(Lists, "search", &m.Search, "search", "lists", "Go to anything: search every vault and secret loaded and jump to one. Again in Go to: only the source or group you're in, and back to all. On the left, the scope: All, an account (or Databricks, or Repos), or one source (○ ◐ ● for how much of it is loaded)."),
|
||||
a(Lists, "goTo", &m.Search, "search", "lists", "Go to anything: search every vault and secret loaded and jump to one. Again in Go to: only the source or group you're in, and back to all. On the left, the scope: All, an account (or Databricks, or Repos), or one source (○ ◐ ● for how much of it is loaded)."),
|
||||
a(Lists, "favourites", &m.Favourites, "favourites", "lists", "Go to, on Favourites: everything you've starred, to search and jump to."),
|
||||
a(Lists, "recent", &m.Recent, "recent", "lists", "Go to, on Recent: what you used last, newest first."),
|
||||
a(Lists, "commands", &m.Commands, "commands", "lists", "List the custom commands for the focused pane (customCommands in the config) and run one."),
|
||||
@@ -116,7 +116,7 @@ func (m *Map) Actions() []Action {
|
||||
a(Lists, "openInBrowser", &m.Open, "open in browser", "secrets", "Open the selected subscription, vault or item in the browser (Azure portal or Databricks workspace)."),
|
||||
a(Lists, "edit", &m.Edit, "open file", "secrets", "Open the selected SOPS or .env file, or the file of the selected secret at its line; on the status pane, your config (made if it isn't there yet). SOPS files open with sops edit. Others open in the nvim lazysecrets runs in (quitting lazysecrets), else in $VISUAL or $EDITOR, else in the system's default app."),
|
||||
|
||||
a(Lists, "share", &m.Share, "copy link", "share", "Copy a lazysecrets:// link to the selected subscription, workspace, vault, scope or secret, for sharing. From the versions view the link is pinned to that version."),
|
||||
a(Lists, "copyLink", &m.Share, "copy link", "share", "Copy a lazysecrets:// link to the selected subscription, workspace, vault, scope or secret, for sharing. From the versions view the link is pinned to that version."),
|
||||
a(Lists, "shareMenu", &m.ShareMenu, "share", "share", "Choose what to share: the lazysecrets link, the plain Key Vault URL, the config reference, the web page, or env files as an encrypted link."),
|
||||
a(Lists, "openLink", &m.OpenRef, "open link", "share", "Open a lazysecrets:// link, Key Vault URL or reference. Pasting one into lazysecrets does the same."),
|
||||
|
||||
@@ -184,13 +184,13 @@ var defaults = map[string][]string{
|
||||
"lists.top": {"g", "home"}, "lists.bottom": {"G", "end"},
|
||||
"lists.nextPane": {"tab"}, "lists.prevPane": {"shift+tab", "h", "left"}, "lists.details": {"l", "right"},
|
||||
"lists.pane1": {"1"}, "lists.pane2": {"2"}, "lists.pane3": {"3"}, "lists.pane4": {"4"}, "lists.pane0": {"0"},
|
||||
"lists.enter": {"enter"}, "lists.back": {"esc", "backspace"},
|
||||
"lists.open": {"enter"}, "lists.back": {"esc", "backspace"},
|
||||
"lists.filter": {"/"}, "lists.prevTab": {"["}, "lists.nextTab": {"]"}, "lists.sourcesView": {"`"},
|
||||
"lists.star": {"f"}, "lists.favourites": {"F"}, "lists.recent": {"R"}, "lists.search": {"ctrl+s"}, "lists.note": {"n"},
|
||||
"lists.star": {"f"}, "lists.favourites": {"F"}, "lists.recent": {"R"}, "lists.goTo": {"ctrl+s"}, "lists.note": {"n"},
|
||||
"lists.commands": {"x"},
|
||||
"lists.reveal": {"space"}, "lists.copyValue": {"y"}, "lists.copyReference": {"Y"},
|
||||
"lists.versions": {"v"}, "lists.openInBrowser": {"o"}, "lists.edit": {"e"},
|
||||
"lists.share": {"s"}, "lists.shareMenu": {"S"}, "lists.openLink": {"ctrl+o"},
|
||||
"lists.copyLink": {"s"}, "lists.shareMenu": {"S"}, "lists.openLink": {"ctrl+o"},
|
||||
"lists.dividerLeft": {"ctrl+left", "<"}, "lists.dividerRight": {"ctrl+right", ">"},
|
||||
"lists.taller": {"ctrl+down", "}"}, "lists.shorter": {"ctrl+up", "{"},
|
||||
"lists.zoomIn": {"+"}, "lists.zoomOut": {"_"}, "lists.resetLayout": {"="},
|
||||
|
||||
@@ -45,7 +45,9 @@ var Roles = map[string]string{
|
||||
}
|
||||
|
||||
// FromTheme returns the default styles with the theme's roles applied, and
|
||||
// the default text colour if the theme sets one.
|
||||
// the default text colour if the theme sets one. Roles it doesn't know are
|
||||
// skipped (see Unknown): a theme file made for a newer lazysecrets still
|
||||
// works.
|
||||
func FromTheme(theme map[string][]string) (Styles, color.Color, error) {
|
||||
st := Default()
|
||||
var fg color.Color
|
||||
@@ -56,7 +58,7 @@ func FromTheme(theme map[string][]string) (Styles, color.Color, error) {
|
||||
sort.Strings(roles)
|
||||
for _, role := range roles {
|
||||
if _, ok := Roles[role]; !ok {
|
||||
return st, nil, fmt.Errorf("theme: unknown role %q (known: %s)", role, strings.Join(sortedRoles(), ", "))
|
||||
continue
|
||||
}
|
||||
v, err := parse(theme[role])
|
||||
if err != nil {
|
||||
@@ -107,13 +109,20 @@ func FromTheme(theme map[string][]string) (Styles, color.Color, error) {
|
||||
return st, fg, nil
|
||||
}
|
||||
|
||||
func sortedRoles() []string {
|
||||
var out []string
|
||||
for r := range Roles {
|
||||
out = append(out, r)
|
||||
// Unknown says which of the theme's roles aren't known, for a warning, or
|
||||
// is empty.
|
||||
func Unknown(theme map[string][]string) string {
|
||||
var unknown []string
|
||||
for r := range theme {
|
||||
if _, ok := Roles[r]; !ok {
|
||||
unknown = append(unknown, r)
|
||||
}
|
||||
}
|
||||
slices.Sort(out)
|
||||
return out
|
||||
if len(unknown) == 0 {
|
||||
return ""
|
||||
}
|
||||
slices.Sort(unknown)
|
||||
return "theme: skipped unknown " + strings.Join(unknown, ", ") + " (a typo, or from a newer lazysecrets)"
|
||||
}
|
||||
|
||||
// value is a parsed role: a colour (nil for default) and attributes.
|
||||
|
||||
@@ -44,19 +44,29 @@ func TestFromTheme(t *testing.T) {
|
||||
|
||||
func TestFromThemeRejectsMistakes(t *testing.T) {
|
||||
for name, theme := range map[string]map[string][]string{
|
||||
"role": {"activeBorder": {"red"}},
|
||||
"colour": {"errorColor": {"redish"}},
|
||||
"hex": {"errorColor": {"#fff"}},
|
||||
"palette": {"errorColor": {"300"}},
|
||||
} {
|
||||
if _, _, err := FromTheme(theme); err == nil {
|
||||
t.Errorf("%s: no error", name)
|
||||
} else if name == "role" && !strings.Contains(err.Error(), "activeBorderColor") {
|
||||
t.Errorf("unknown role error should list the known ones: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnknownRolesSkipped(t *testing.T) {
|
||||
theme := map[string][]string{"activeBorder": {"red"}, "errorColor": {"red"}}
|
||||
if _, _, err := FromTheme(theme); err != nil {
|
||||
t.Errorf("unknown role failed the theme: %v", err)
|
||||
}
|
||||
if w := Unknown(theme); !strings.Contains(w, "unknown activeBorder ") || strings.Contains(w, "errorColor") {
|
||||
t.Errorf("warning = %q", w)
|
||||
}
|
||||
if w := Unknown(map[string][]string{"errorColor": {"red"}}); w != "" {
|
||||
t.Errorf("warning for known roles: %q", w)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEmptyThemeIsDefault(t *testing.T) {
|
||||
st, fg, err := FromTheme(nil)
|
||||
if err != nil || fg != nil || st.Selected.GetReverse() || st.Selected.GetBackground() != lipgloss.BrightBlack {
|
||||
|
||||
Reference in new issue
Block a user