From dbb0eb2bbdf6d695cf0d9ac15a1b513af8ba431d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl-Einar=20Bergstr=C3=B8m?= Date: Wed, 14 Oct 2026 21:23:53 +0200 Subject: [PATCH] fix: a wrapped value in the details keeps its colour on every line (#69) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A long value in the details pane (a ref, a note, a vault's detail, an error) was coloured, then wrapped: the colour's reset only came on the last line, and each line is drawn on its own, so the lines after the first lost the colour. Each wrapped line now starts with the styles still on at the end of the one before. Reviewed-on: https://git.kebcloud.no/keb/lazysecrets/pulls/69 Co-authored-by: Karl-Einar Bergstrøm --- internal/ui/panes/detail.go | 20 +++++++++++++++++++- internal/ui/panes/detail_test.go | 17 +++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 internal/ui/panes/detail_test.go diff --git a/internal/ui/panes/detail.go b/internal/ui/panes/detail.go index 5c1e782..8d363c9 100644 --- a/internal/ui/panes/detail.go +++ b/internal/ui/panes/detail.go @@ -180,6 +180,24 @@ func (d Detail) View(st styles.Styles, focused bool, spin string) string { const spinnerPlaceholder = "\x00spin\x00" +// carryStyle starts each wrapped line with the styles still on at the end +// of the line before: a styled value wrapped in the middle (a long ref) +// would go on unstyled, as each line is drawn on its own. +func carryStyle(lines []string) []string { + var on string + for i, line := range lines { + lines[i] = on + line + for _, code := range sgr.FindAllString(line, -1) { + if code == "\x1b[m" || code == "\x1b[0m" { + on = "" + } else { + on += code + } + } + } + return lines +} + // lines renders the body, wrapped to the pane width. func (d Detail) lines(st styles.Styles) []string { inner := max(1, d.w-3) @@ -187,7 +205,7 @@ func (d Detail) lines(st styles.Styles) []string { field := func(label, value string) { prefix := " " + st.Label.Render(fmt.Sprintf("%-10s", label)) + " " indent := strings.Repeat(" ", 12) - wrapped := strings.Split(ansi.Hardwrap(value, max(1, inner-11), true), "\n") + wrapped := carryStyle(strings.Split(ansi.Hardwrap(value, max(1, inner-11), true), "\n")) out = append(out, prefix+wrapped[0]) for _, w := range wrapped[1:] { out = append(out, indent+w) diff --git a/internal/ui/panes/detail_test.go b/internal/ui/panes/detail_test.go new file mode 100644 index 0000000..1d47f72 --- /dev/null +++ b/internal/ui/panes/detail_test.go @@ -0,0 +1,17 @@ +package panes + +import ( + "strings" + "testing" +) + +func TestWrappedValueKeepsItsStyle(t *testing.T) { + red := "\x1b[31m" + got := carryStyle([]string{red + "@Microsoft.KeyVault(SecretUri=https://kv", "-app-prod.vault.azure.net/secrets/x)\x1b[m", "after"}) + if !strings.HasPrefix(got[1], red) { + t.Errorf("the wrapped line lost the style: %q", got[1]) + } + if strings.HasPrefix(got[2], red) { + t.Errorf("the style went on past its reset: %q", got[2]) + } +}