fix(bonfire): reroute only the owning console's lines to a live view

- the registered view keeps the console that started it; Println, Printf
  and status lines go above it only from that console, other consoles
  write to their own writers (bonfire.PrintAbove still reaches any view)
- runLive claims the single live slot by check and set under liveMu and
  reports when it could not, so the widget prints plain lines
- unregister, finish and wait run deferred, so a panic in work leaves no
  registration behind and still propagates (WR-02)
This commit is contained in:
Jakub Zych
2026-10-22 02:10:48 +02:00
parent b077dc3598
commit 86e4e270d3
6 changed files with 200 additions and 56 deletions

View File

@@ -128,10 +128,11 @@ func (c *console) setGlobals(g Globals) {
// live reports whether widgets animate: stdout is a terminal and none of
// -q, --no-ansi and -n is set (D-03). A live view that is already running
// makes nested widgets print plain lines.
// makes nested widgets print plain lines: runLive then reports that it did
// not start.
func (c *console) live() bool {
g := c.globals
return c.tty && !g.Quiet && g.Color != ColorNever && !g.NoInteraction && !liveActive()
return c.tty && !g.Quiet && g.Color != ColorNever && !g.NoInteraction
}
// canPrompt reports whether prompts may wait for input from a person:
@@ -170,13 +171,14 @@ func (c *console) styled(w io.Writer) io.Writer {
return &colorprofile.Writer{Forward: w, Profile: c.profile()}
}
// emit writes s, a styled line or block, to w. While a live view runs on
// stdout, lines for stdout print above it instead of tearing it.
// emit writes s, a styled line or block, to w. While a live view this
// console started runs on stdout, lines for stdout print above it instead
// of tearing it.
func (c *console) emit(w io.Writer, s string) {
if w == nil {
return
}
if w == c.out && printAboveLines(s) {
if w == c.out && printAbove(c, s) {
return
}
_, _ = io.WriteString(c.styled(w), s)
@@ -194,7 +196,7 @@ func (c *console) Println(a ...any) {
return
}
s := fmt.Sprintln(a...)
if printAboveLines(s) {
if printAbove(c, s) {
return
}
_, _ = io.WriteString(c.out, s)
@@ -205,7 +207,7 @@ func (c *console) Printf(format string, a ...any) {
return
}
s := fmt.Sprintf(format, a...)
if strings.HasSuffix(s, "\n") && printAboveLines(s) {
if strings.HasSuffix(s, "\n") && printAbove(c, s) {
return
}
_, _ = io.WriteString(c.out, s)