aboutsummaryrefslogtreecommitdiff
path: root/cmd/krino/review.go
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-09-14 11:05:13 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-09-14 11:05:13 +0200
commitadc3410395771609d2db5ee5ae2b9da71115c5ca (patch)
tree453def41e18f607332be1088920f9d0c563603a3 /cmd/krino/review.go
parent0468ce38470aa3ae8092b92d4f77e72d25dfa108 (diff)
downloadkrino-adc3410395771609d2db5ee5ae2b9da71115c5ca.tar.gz
krino-adc3410395771609d2db5ee5ae2b9da71115c5ca.zip
krino: coloured output, and --no-color
One palette type styles the plan table, warnings, headers, outcome counts, prompt keys, undo's refused steps and krino log's (undone), from the 16-colour ANSI palette plus bold and faint only. Widths are measured on the plain text, so columns line up; with colour off the output is unchanged. --no-color works before or after any subcommand, as NO_COLOR does. The two search-and-replace colourings are gone.
Diffstat (limited to 'cmd/krino/review.go')
-rw-r--r--cmd/krino/review.go36
1 files changed, 10 insertions, 26 deletions
diff --git a/cmd/krino/review.go b/cmd/krino/review.go
index 4f5ad05..a6c1b5a 100644
--- a/cmd/krino/review.go
+++ b/cmd/krino/review.go
@@ -6,7 +6,6 @@ import (
"fmt"
"io"
"os"
- "strings"
"krino/internal/plan"
"krino/internal/tui"
@@ -20,9 +19,10 @@ import (
// strings.Reader. root is the directory being reviewed, threaded through to
// reviewChains so a per-file destination renders the same way the
// directory-level table does (root-relative inside root, ~-abbreviated
-// outside it) instead of always falling back to the abbreviated form.
-func reviewDir(out io.Writer, chains []plan.Chain, root string) (map[string]bool, rune, error) {
- return reviewChains(keyReader{stdin}, out, chains, root)
+// outside it) instead of always falling back to the abbreviated form. p
+// styles the prompts and the per-file steps (spec §8.2).
+func reviewDir(out io.Writer, chains []plan.Chain, root string, p palette) (map[string]bool, rune, error) {
+ return reviewChains(keyReader{stdin}, out, chains, root, p)
}
// keyReader adapts tui.ReadKey - one key at a time, from a real *os.File -
@@ -57,8 +57,8 @@ func (k keyReader) Read(p []byte) (int, error) {
// keeps it. root is the directory being reviewed - passed only to
// reviewPerFile's destination rendering (review finding 1, fix round
// 2026-09-12); nothing here uses it directly.
-func reviewChains(in io.Reader, out io.Writer, chains []plan.Chain, root string) (map[string]bool, rune, error) {
- fmt.Fprint(out, "\n[a] apply all [c] choose per file [s] skip this directory [q] quit\n")
+func reviewChains(in io.Reader, out io.Writer, chains []plan.Chain, root string, p palette) (map[string]bool, rune, error) {
+ fmt.Fprint(out, "\n"+p.keys("[a] apply all [c] choose per file [s] skip this directory [q] quit")+"\n")
for {
key, err := readKey(in)
if err != nil {
@@ -72,7 +72,7 @@ func reviewChains(in io.Reader, out io.Writer, chains []plan.Chain, root string)
case 'q':
return map[string]bool{}, 'q', nil
case 'c':
- approved, quit, err := reviewPerFile(in, out, chains, root)
+ approved, quit, err := reviewPerFile(in, out, chains, root, p)
if err != nil {
return nil, 0, err
}
@@ -99,7 +99,7 @@ func reviewChains(in io.Reader, out io.Writer, chains []plan.Chain, root string)
// 2026-09-12): passing "" here always fails filepath.Rel("", dir) and
// silently fell back to the abbreviated form even for a destination inside
// root, which is not what spec §8.3's own worked example shows.
-func reviewPerFile(in io.Reader, out io.Writer, chains []plan.Chain, root string) (approved map[string]bool, quit bool, err error) {
+func reviewPerFile(in io.Reader, out io.Writer, chains []plan.Chain, root string, p palette) (approved map[string]bool, quit bool, err error) {
approved = map[string]bool{}
yesRest := false
for i, c := range chains {
@@ -110,9 +110,9 @@ func reviewPerFile(in io.Reader, out io.Writer, chains []plan.Chain, root string
fmt.Fprintf(out, "\n[%d/%d] %s\n", i+1, len(chains), c.File.Rel)
for _, s := range c.Steps {
- fmt.Fprintf(out, " %s\n", actionCell(s, root))
+ fmt.Fprintf(out, " %s\n", styleAction(p, s, actionCell(s, root)))
}
- fmt.Fprint(out, " [y] yes [n] no [a] yes to this and all remaining [d] done, apply chosen so far [q] quit, apply nothing\n")
+ fmt.Fprint(out, " "+p.keys("[y] yes [n] no [a] yes to this and all remaining [d] done, apply chosen so far [q] quit, apply nothing")+"\n")
for {
key, kerr := readKey(in)
@@ -162,19 +162,3 @@ func approveAll(chains []plan.Chain) map[string]bool {
}
return approved
}
-
-// colourDeletePermanently wraps spec §8.2's "DELETE permanently" marker in
-// the terminal's own ANSI red (bold, slot 1 - never hex), the one thing the
-// spec singles out for emphasis (Ruling 2026-09-12/7). It is applied to
-// text render.go's printPlan already produced, rather than threading a
-// colour parameter through the renderer itself: that keeps render.go and
-// its golden-file tests exactly as plan 4 built them. colour is always the
-// caller's own tui.Colour(stdout) decision - with it false this is a no-op,
-// which is what keeps every escape byte out of a plan piped to a file or
-// read by another tool.
-func colourDeletePermanently(text string, colour bool) string {
- if !colour {
- return text
- }
- return strings.ReplaceAll(text, "DELETE permanently", "\x1b[1;31mDELETE permanently\x1b[0m")
-}