termstatus: don't buffer stdout

There's not much use in doing so as nearly every write call was paired
with a flush call. Thus, just use an unbuffered writer.
This commit is contained in:
Michael Eischer
2025-09-14 21:47:09 +02:00
parent ef9930cce4
commit 03600ca509

View File

@@ -1,7 +1,6 @@
package termstatus package termstatus
import ( import (
"bufio"
"context" "context"
"fmt" "fmt"
"io" "io"
@@ -19,7 +18,7 @@ import (
// updated. When the output is redirected to a file, the status lines are not // updated. When the output is redirected to a file, the status lines are not
// printed. // printed.
type Terminal struct { type Terminal struct {
wr *bufio.Writer wr io.Writer
fd uintptr fd uintptr
errWriter io.Writer errWriter io.Writer
msg chan message msg chan message
@@ -57,7 +56,7 @@ type fder interface {
// are printed even if the terminal supports it. // are printed even if the terminal supports it.
func New(wr io.Writer, errWriter io.Writer, disableStatus bool) *Terminal { func New(wr io.Writer, errWriter io.Writer, disableStatus bool) *Terminal {
t := &Terminal{ t := &Terminal{
wr: bufio.NewWriter(wr), wr: wr,
errWriter: errWriter, errWriter: errWriter,
msg: make(chan message), msg: make(chan message),
status: make(chan status), status: make(chan status),
@@ -118,13 +117,6 @@ func (t *Terminal) run(ctx context.Context) {
var dst io.Writer var dst io.Writer
if msg.err { if msg.err {
dst = t.errWriter dst = t.errWriter
// assume t.wr and t.errWriter are different, so we need to
// flush clearing the current line
err := t.wr.Flush()
if err != nil {
fmt.Fprintf(os.Stderr, "flush failed: %v\n", err)
}
} else { } else {
dst = t.wr dst = t.wr
} }
@@ -135,11 +127,6 @@ func (t *Terminal) run(ctx context.Context) {
} }
t.writeStatus(status) t.writeStatus(status)
if err := t.wr.Flush(); err != nil {
fmt.Fprintf(os.Stderr, "flush failed: %v\n", err)
}
case stat := <-t.status: case stat := <-t.status:
status = append(status[:0], stat.lines...) status = append(status[:0], stat.lines...)
@@ -169,26 +156,15 @@ func (t *Terminal) writeStatus(status []string) {
for _, line := range status { for _, line := range status {
t.clearCurrentLine(t.wr, t.fd) t.clearCurrentLine(t.wr, t.fd)
_, err := t.wr.WriteString(line) _, err := t.wr.Write([]byte(line))
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "write failed: %v\n", err) fmt.Fprintf(os.Stderr, "write failed: %v\n", err)
} }
// flush is needed so that the current line is updated
err = t.wr.Flush()
if err != nil {
fmt.Fprintf(os.Stderr, "flush failed: %v\n", err)
}
} }
if len(status) > 0 { if len(status) > 0 {
t.moveCursorUp(t.wr, t.fd, len(status)-1) t.moveCursorUp(t.wr, t.fd, len(status)-1)
} }
err := t.wr.Flush()
if err != nil {
fmt.Fprintf(os.Stderr, "flush failed: %v\n", err)
}
} }
// runWithoutStatus listens on the channels and just prints out the messages, // runWithoutStatus listens on the channels and just prints out the messages,
@@ -199,28 +175,18 @@ func (t *Terminal) runWithoutStatus(ctx context.Context) {
case <-ctx.Done(): case <-ctx.Done():
return return
case msg := <-t.msg: case msg := <-t.msg:
var flush func() error
var dst io.Writer var dst io.Writer
if msg.err { if msg.err {
dst = t.errWriter dst = t.errWriter
} else { } else {
dst = t.wr dst = t.wr
flush = t.wr.Flush
} }
if _, err := io.WriteString(dst, msg.line); err != nil { if _, err := io.WriteString(dst, msg.line); err != nil {
_, _ = fmt.Fprintf(os.Stderr, "write failed: %v\n", err) _, _ = fmt.Fprintf(os.Stderr, "write failed: %v\n", err)
} }
if flush == nil {
continue
}
if err := flush(); err != nil {
_, _ = fmt.Fprintf(os.Stderr, "flush failed: %v\n", err)
}
case stat := <-t.status: case stat := <-t.status:
for _, line := range stat.lines { for _, line := range stat.lines {
// Ensure that each message ends with exactly one newline. // Ensure that each message ends with exactly one newline.
@@ -228,9 +194,6 @@ func (t *Terminal) runWithoutStatus(ctx context.Context) {
_, _ = fmt.Fprintf(os.Stderr, "write failed: %v\n", err) _, _ = fmt.Fprintf(os.Stderr, "write failed: %v\n", err)
} }
} }
if err := t.wr.Flush(); err != nil {
_, _ = fmt.Fprintf(os.Stderr, "flush failed: %v\n", err)
}
} }
} }
} }