feat: Go to shows a repo file's icon before its name #85
No files matched your search
@@ -97,26 +97,15 @@ func (m *Model) refreshContext(key, name string, path []string, src provider.Sou
|
|||||||
// containerRender draws a vault or scope, starred or not. In the
|
// containerRender draws a vault or scope, starred or not. In the
|
||||||
// Opened links list it also names the source, since they come from many.
|
// Opened links list it also names the source, since they come from many.
|
||||||
func (m Model) containerRender(withSource bool) func(styles.Styles, provider.Container, int) string {
|
func (m Model) containerRender(withSource bool) func(styles.Styles, provider.Container, int) string {
|
||||||
st, iconSet := m.store, m.icons
|
st := m.store
|
||||||
return func(sty styles.Styles, c provider.Container, width int) string {
|
return func(sty styles.Styles, c provider.Container, width int) string {
|
||||||
n := st.Node(storeKey(c))
|
n := st.Node(storeKey(c))
|
||||||
line := c.Name
|
line := c.Name
|
||||||
if c.Source.Kind == provider.KindRepo {
|
if c.Source.Kind == provider.KindRepo {
|
||||||
// A secret file: a lock for an encrypted one, a leaf for
|
// A secret file: its icon, and its type after it ("sops ·
|
||||||
// Spring config, a whale for compose, a file in the warning
|
|
||||||
// colour for plain text, and its type after it ("sops ·
|
|
||||||
// age", "env · plain text").
|
// age", "env · plain text").
|
||||||
icon, style := iconSet.Encrypted, sty.KindRepo
|
if icon := m.fileIcon(sty, c); icon != "" {
|
||||||
switch {
|
line = icon + " " + line
|
||||||
case strings.HasPrefix(c.Detail, "spring"):
|
|
||||||
icon, style = iconSet.Spring, sty.Spring
|
|
||||||
case strings.HasPrefix(c.Detail, "compose"):
|
|
||||||
icon, style = iconSet.Compose, sty.Compose
|
|
||||||
case !strings.HasPrefix(c.Detail, "sops"):
|
|
||||||
icon, style = iconSet.PlainFile, sty.Warning
|
|
||||||
}
|
|
||||||
if icon != "" {
|
|
||||||
line = style.Render(icon) + " " + line
|
|
||||||
}
|
}
|
||||||
line += sty.Muted.Render(" " + c.Detail)
|
line += sty.Muted.Render(" " + c.Detail)
|
||||||
}
|
}
|
||||||
@@ -155,6 +144,28 @@ func (m Model) objectRender() func(styles.Styles, provider.Object, int) string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fileIcon is a repo file's icon, in its colour: a lock for an encrypted
|
||||||
|
// one, a leaf for Spring config, a whale for compose, a file in the
|
||||||
|
// warning colour for plain text; "" for other vaults, or without icons.
|
||||||
|
func (m Model) fileIcon(sty styles.Styles, c provider.Container) string {
|
||||||
|
if c.Source.Kind != provider.KindRepo {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
icon, style := m.icons.Encrypted, sty.KindRepo
|
||||||
|
switch {
|
||||||
|
case strings.HasPrefix(c.Detail, "spring"):
|
||||||
|
icon, style = m.icons.Spring, sty.Spring
|
||||||
|
case strings.HasPrefix(c.Detail, "compose"):
|
||||||
|
icon, style = m.icons.Compose, sty.Compose
|
||||||
|
case !strings.HasPrefix(c.Detail, "sops"):
|
||||||
|
icon, style = m.icons.PlainFile, sty.Warning
|
||||||
|
}
|
||||||
|
if icon == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return style.Render(icon)
|
||||||
|
}
|
||||||
|
|
||||||
// dimIf draws a hidden item's row (shown with H) in the muted colour,
|
// dimIf draws a hidden item's row (shown with H) in the muted colour,
|
||||||
// whole, so it stands apart from what's listed by the provider's rules.
|
// whole, so it stands apart from what's listed by the provider's rules.
|
||||||
func dimIf(sty styles.Styles, hidden bool, line string) string {
|
func dimIf(sty styles.Styles, hidden bool, line string) string {
|
||||||
|
|||||||
+26
-8
@@ -47,7 +47,7 @@ func (m *Model) storeEntries() (favs, recent []option) {
|
|||||||
account = strings.Trim(detail+" · "+account, " ·")
|
account = strings.Trim(detail+" · "+account, " ·")
|
||||||
sort := strings.ToLower(strings.Join(path, "/")) + " " + account
|
sort := strings.ToLower(strings.Join(path, "/")) + " " + account
|
||||||
out = append(out, entry{depth, sort, option{
|
out = append(out, entry{depth, sort, option{
|
||||||
label: m.pathLabel(r.Kind, path, account), note: n.Note, mark: " ",
|
label: m.pathLabel(r.Kind, path, account, m.refFileIcon(r)), note: n.Note, mark: " ",
|
||||||
id: prefix + key + "|" + acct, star: key, starAccount: acct, starred: n.StarredFor(acct),
|
id: prefix + key + "|" + acct, star: key, starAccount: acct, starred: n.StarredFor(acct),
|
||||||
plain: m.inPlainEnv(r),
|
plain: m.inPlainEnv(r),
|
||||||
run: func(m *Model) tea.Cmd {
|
run: func(m *Model) tea.Cmd {
|
||||||
@@ -128,12 +128,15 @@ const recentMax = 20
|
|||||||
|
|
||||||
// pathLabel draws a jump list entry: the provider's icon and the path in
|
// pathLabel draws a jump list entry: the provider's icon and the path in
|
||||||
// its colour, then the account.
|
// its colour, then the account.
|
||||||
func (m Model) pathLabel(kind provider.Kind, path []string, account string) string {
|
func (m Model) pathLabel(kind provider.Kind, path []string, account, fileIcon string) string {
|
||||||
style := m.st.Kind(kind)
|
style := m.st.Kind(kind)
|
||||||
parts := make([]string, len(path))
|
parts := make([]string, len(path))
|
||||||
for i, p := range path {
|
for i, p := range path {
|
||||||
parts[i] = style.Render(p)
|
parts[i] = style.Render(p)
|
||||||
}
|
}
|
||||||
|
if fileIcon != "" && len(parts) > 1 {
|
||||||
|
parts[1] = fileIcon + " " + parts[1]
|
||||||
|
}
|
||||||
label := style.Render(m.icons.Prefix(kind)) + strings.Join(parts, m.st.Muted.Render(" / "))
|
label := style.Render(m.icons.Prefix(kind)) + strings.Join(parts, m.st.Muted.Render(" / "))
|
||||||
if account != "" {
|
if account != "" {
|
||||||
label += m.st.Muted.Render(" · " + account)
|
label += m.st.Muted.Render(" · " + account)
|
||||||
@@ -144,19 +147,34 @@ func (m Model) pathLabel(kind provider.Kind, path []string, account string) stri
|
|||||||
// inPlainEnv reports whether r is a key in a plain env file, as far as
|
// inPlainEnv reports whether r is a key in a plain env file, as far as
|
||||||
// the files loaded tell.
|
// the files loaded tell.
|
||||||
func (m Model) inPlainEnv(r ref.Ref) bool {
|
func (m Model) inPlainEnv(r ref.Ref) bool {
|
||||||
if r.Kind != provider.KindRepo || r.Name == "" {
|
c, ok := m.repoFile(r)
|
||||||
return false
|
return ok && r.Name != "" && c.Detail == provider.DetailPlainEnv
|
||||||
|
}
|
||||||
|
|
||||||
|
// repoFile is the repo file r is or is in, as far as the files loaded
|
||||||
|
// tell.
|
||||||
|
func (m Model) repoFile(r ref.Ref) (provider.Container, bool) {
|
||||||
|
if r.Kind != provider.KindRepo || r.IsSource() {
|
||||||
|
return provider.Container{}, false
|
||||||
}
|
}
|
||||||
file := r
|
file := r
|
||||||
file.Name, file.Type = "", ""
|
file.Name, file.Type = "", ""
|
||||||
for _, e := range m.cache.containers {
|
for _, e := range m.cache.containers {
|
||||||
for _, c := range e.value {
|
for _, c := range e.value {
|
||||||
if c.Detail == provider.DetailPlainEnv && storeKey(c) == file.String() {
|
if storeKey(c) == file.String() {
|
||||||
return true
|
return c, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return provider.Container{}, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// refFileIcon is the icon of the repo file r is or is in, if it's loaded.
|
||||||
|
func (m Model) refFileIcon(r ref.Ref) string {
|
||||||
|
if c, ok := m.repoFile(r); ok {
|
||||||
|
return m.fileIcon(m.st, c)
|
||||||
|
}
|
||||||
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// objectDetail is the Detail of the secret with the store key key, as far
|
// objectDetail is the Detail of the secret with the store key key, as far
|
||||||
@@ -175,7 +193,7 @@ func (m Model) objectDetail(key string) string {
|
|||||||
// repoLabel draws a repo, or a file in it, as everywhere else: the repo
|
// repoLabel draws a repo, or a file in it, as everywhere else: the repo
|
||||||
// icon and colour, "app / apps/api/.env".
|
// icon and colour, "app / apps/api/.env".
|
||||||
func (m Model) repoLabel(repo string, file ...string) string {
|
func (m Model) repoLabel(repo string, file ...string) string {
|
||||||
return m.pathLabel(provider.KindRepo, append([]string{repo}, file...), "")
|
return m.pathLabel(provider.KindRepo, append([]string{repo}, file...), "", "")
|
||||||
}
|
}
|
||||||
|
|
||||||
// sourceMatches reports whether src is the subscription or workspace r
|
// sourceMatches reports whether src is the subscription or workspace r
|
||||||
|
|||||||
@@ -269,7 +269,7 @@ func (m Model) refLabel(r ref.Ref) string {
|
|||||||
default:
|
default:
|
||||||
path = append(path, r.ContainerName(), r.Name)
|
path = append(path, r.ContainerName(), r.Name)
|
||||||
}
|
}
|
||||||
label := m.pathLabel(r.Kind, path, "")
|
label := m.pathLabel(r.Kind, path, "", m.refFileIcon(r))
|
||||||
var extra []string
|
var extra []string
|
||||||
if t := strings.ToLower(pluralLabels[r.Type]); t != "" && r.Type != provider.TypeSecret {
|
if t := strings.ToLower(pluralLabels[r.Type]); t != "" && r.Type != provider.TypeSecret {
|
||||||
if r.IsContainer() {
|
if r.IsContainer() {
|
||||||
|
|||||||
@@ -58,11 +58,11 @@ func (m *Model) searchEntries() (sources, items []option) {
|
|||||||
var es []entry
|
var es []entry
|
||||||
// key is the store key, so ctrl+f stars the entry; mark shows how
|
// key is the store key, so ctrl+f stars the entry; mark shows how
|
||||||
// much is loaded, reload (ctrl+r) loads it again.
|
// much is loaded, reload (ctrl+r) loads it again.
|
||||||
add := func(depth int, row string, kind provider.Kind, path []string, account, key, mark string, run, reload func(*Model) tea.Cmd) *option {
|
add := func(depth int, row string, kind provider.Kind, path []string, account, fileIcon, key, mark string, run, reload func(*Model) tea.Cmd) *option {
|
||||||
n := m.store.Node(key)
|
n := m.store.Node(key)
|
||||||
sort := strings.ToLower(strings.Join(path, "/")) + " " + account
|
sort := strings.ToLower(strings.Join(path, "/")) + " " + account
|
||||||
es = append(es, entry{depth, sort,
|
es = append(es, entry{depth, sort,
|
||||||
option{label: m.pathLabel(kind, path, account), note: n.Note, star: key,
|
option{label: m.pathLabel(kind, path, account, fileIcon), note: n.Note, star: key,
|
||||||
starAccount: cachefile.ProviderOf(row), starred: n.StarredFor(cachefile.ProviderOf(row)),
|
starAccount: cachefile.ProviderOf(row), starred: n.StarredFor(cachefile.ProviderOf(row)),
|
||||||
mark: mark, run: run, reload: reload, id: sort, group: row, kind: kind}})
|
mark: mark, run: run, reload: reload, id: sort, group: row, kind: kind}})
|
||||||
return &es[len(es)-1].opt
|
return &es[len(es)-1].opt
|
||||||
@@ -81,7 +81,7 @@ func (m *Model) searchEntries() (sources, items []option) {
|
|||||||
}
|
}
|
||||||
src.Provider, src.ProviderLabel = p.ID(), p.Label()
|
src.Provider, src.ProviderLabel = p.ID(), p.Label()
|
||||||
row := sourceRowKey(p.ID(), src.ID)
|
row := sourceRowKey(p.ID(), src.ID)
|
||||||
dim(src.Hidden, add(0, row, src.Kind, []string{src.Name}, accountOf(src), sourceKey(src), m.sourceMark(row), func(m *Model) tea.Cmd {
|
dim(src.Hidden, add(0, row, src.Kind, []string{src.Name}, accountOf(src), "", sourceKey(src), m.sourceMark(row), func(m *Model) tea.Cmd {
|
||||||
m.nav = &nav{sourceRow: row, sourceOnly: true}
|
m.nav = &nav{sourceRow: row, sourceOnly: true}
|
||||||
return nil
|
return nil
|
||||||
}, func(m *Model) tea.Cmd { return m.loadSource(src) }))
|
}, func(m *Model) tea.Cmd { return m.loadSource(src) }))
|
||||||
@@ -94,7 +94,7 @@ func (m *Model) searchEntries() (sources, items []option) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
reload := func(m *Model) tea.Cmd { return m.loadContainer(c) }
|
reload := func(m *Model) tea.Cmd { return m.loadContainer(c) }
|
||||||
dim(c.Hidden, add(1, row, c.Source.Kind, []string{src.Name, c.Name}, accountOf(src), storeKey(c), m.vaultMark(c), func(m *Model) tea.Cmd {
|
dim(c.Hidden, add(1, row, c.Source.Kind, []string{src.Name, c.Name}, accountOf(src), m.fileIcon(m.st, c), storeKey(c), m.vaultMark(c), func(m *Model) tea.Cmd {
|
||||||
m.startNav(r, actGo, row)
|
m.startNav(r, actGo, row)
|
||||||
return nil
|
return nil
|
||||||
}, reload))
|
}, reload))
|
||||||
@@ -109,7 +109,7 @@ func (m *Model) searchEntries() (sources, items []option) {
|
|||||||
typ := strings.TrimSuffix(strings.ToLower(pluralLabels[t]), "s") // "key"
|
typ := strings.TrimSuffix(strings.ToLower(pluralLabels[t]), "s") // "key"
|
||||||
suffix = strings.Trim(typ+" · "+suffix, " ·")
|
suffix = strings.Trim(typ+" · "+suffix, " ·")
|
||||||
}
|
}
|
||||||
e := add(2, row, c.Source.Kind, []string{src.Name, c.Name, o.Name}, suffix, objectKey(o), " ", func(m *Model) tea.Cmd {
|
e := add(2, row, c.Source.Kind, []string{src.Name, c.Name, o.Name}, suffix, m.fileIcon(m.st, c), objectKey(o), " ", func(m *Model) tea.Cmd {
|
||||||
m.startNav(r, actGo, row)
|
m.startNav(r, actGo, row)
|
||||||
return nil
|
return nil
|
||||||
}, reload)
|
}, reload)
|
||||||
|
|||||||
Reference in new issue
Block a user