diff --git a/internal/terminal/terminal_posix.go b/internal/terminal/terminal_posix.go index e8a5abc59..08527b777 100644 --- a/internal/terminal/terminal_posix.go +++ b/internal/terminal/terminal_posix.go @@ -4,7 +4,6 @@ import ( "bytes" "fmt" "io" - "os" ) const ( @@ -18,22 +17,22 @@ const ( // PosixClearCurrentLine removes all characters from the current line and resets the // cursor position to the first column. -func PosixClearCurrentLine(wr io.Writer, _ uintptr) { +func PosixClearCurrentLine(wr io.Writer, _ uintptr) error { // clear current line _, err := wr.Write([]byte(PosixControlMoveCursorHome + PosixControlClearLine)) if err != nil { - fmt.Fprintf(os.Stderr, "write failed: %v\n", err) - return + return fmt.Errorf("write failed: %w", err) } + return nil } // PosixMoveCursorUp moves the cursor to the line n lines above the current one. -func PosixMoveCursorUp(wr io.Writer, _ uintptr, n int) { +func PosixMoveCursorUp(wr io.Writer, _ uintptr, n int) error { data := []byte(PosixControlMoveCursorHome) data = append(data, bytes.Repeat([]byte(PosixControlMoveCursorUp), n)...) _, err := wr.Write(data) if err != nil { - fmt.Fprintf(os.Stderr, "write failed: %v\n", err) - return + return fmt.Errorf("write failed: %w", err) } + return nil } diff --git a/internal/terminal/terminal_unix.go b/internal/terminal/terminal_unix.go index 65e353d9f..732219bb4 100644 --- a/internal/terminal/terminal_unix.go +++ b/internal/terminal/terminal_unix.go @@ -12,12 +12,12 @@ import ( // ClearCurrentLine removes all characters from the current line and resets the // cursor position to the first column. -func ClearCurrentLine(_ uintptr) func(io.Writer, uintptr) { +func ClearCurrentLine(_ uintptr) func(io.Writer, uintptr) error { return PosixClearCurrentLine } // MoveCursorUp moves the cursor to the line n lines above the current one. -func MoveCursorUp(_ uintptr) func(io.Writer, uintptr, int) { +func MoveCursorUp(_ uintptr) func(io.Writer, uintptr, int) error { return PosixMoveCursorUp } diff --git a/internal/terminal/terminal_windows.go b/internal/terminal/terminal_windows.go index d68d0197e..fffabc5ee 100644 --- a/internal/terminal/terminal_windows.go +++ b/internal/terminal/terminal_windows.go @@ -15,7 +15,7 @@ import ( // clearCurrentLine removes all characters from the current line and resets the // cursor position to the first column. -func ClearCurrentLine(fd uintptr) func(io.Writer, uintptr) { +func ClearCurrentLine(fd uintptr) func(io.Writer, uintptr) error { // easy case, the terminal is cmd or psh, without redirection if isWindowsTerminal(fd) { return windowsClearCurrentLine @@ -26,7 +26,7 @@ func ClearCurrentLine(fd uintptr) func(io.Writer, uintptr) { } // moveCursorUp moves the cursor to the line n lines above the current one. -func MoveCursorUp(fd uintptr) func(io.Writer, uintptr, int) { +func MoveCursorUp(fd uintptr) func(io.Writer, uintptr, int) error { // easy case, the terminal is cmd or psh, without redirection if isWindowsTerminal(fd) { return windowsMoveCursorUp @@ -45,7 +45,7 @@ var ( // windowsClearCurrentLine removes all characters from the current line and // resets the cursor position to the first column. -func windowsClearCurrentLine(_ io.Writer, fd uintptr) { +func windowsClearCurrentLine(_ io.Writer, fd uintptr) error { var info windows.ConsoleScreenBufferInfo windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info) @@ -58,10 +58,11 @@ func windowsClearCurrentLine(_ io.Writer, fd uintptr) { count = uint32(info.Size.X) procFillConsoleOutputAttribute.Call(fd, uintptr(info.Attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&w))) procFillConsoleOutputCharacter.Call(fd, uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&w))) + return nil } // windowsMoveCursorUp moves the cursor to the line n lines above the current one. -func windowsMoveCursorUp(_ io.Writer, fd uintptr, n int) { +func windowsMoveCursorUp(_ io.Writer, fd uintptr, n int) error { var info windows.ConsoleScreenBufferInfo windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info) @@ -70,6 +71,7 @@ func windowsMoveCursorUp(_ io.Writer, fd uintptr, n int) { X: 0, Y: info.CursorPosition.Y - int16(n), }) + return nil } // isWindowsTerminal return true if the file descriptor is a windows terminal (cmd, psh). diff --git a/internal/ui/termstatus/status.go b/internal/ui/termstatus/status.go index e654f5cac..3803882e6 100644 --- a/internal/ui/termstatus/status.go +++ b/internal/ui/termstatus/status.go @@ -37,8 +37,8 @@ type Terminal struct { // yield a default value immediately closed chan struct{} - clearCurrentLine func(io.Writer, uintptr) - moveCursorUp func(io.Writer, uintptr, int) + clearCurrentLine func(io.Writer, uintptr) error + moveCursorUp func(io.Writer, uintptr, int) error } type message struct { @@ -214,7 +214,10 @@ func (t *Terminal) run(ctx context.Context) { // ignore all messages, do nothing, we are in the background process group continue } - t.clearCurrentLine(t.wr, t.fd) + if err := t.clearCurrentLine(t.wr, t.fd); err != nil { + _, _ = fmt.Fprintf(t.errWriter, "write failed: %v\n", err) + continue + } var dst io.Writer if msg.err { @@ -256,7 +259,9 @@ func (t *Terminal) writeStatus(status []string) { t.lastStatusLen = statusLen for _, line := range status { - t.clearCurrentLine(t.wr, t.fd) + if err := t.clearCurrentLine(t.wr, t.fd); err != nil { + _, _ = fmt.Fprintf(t.errWriter, "write failed: %v\n", err) + } _, err := t.wr.Write([]byte(line)) if err != nil { @@ -265,7 +270,9 @@ func (t *Terminal) writeStatus(status []string) { } if len(status) > 0 { - t.moveCursorUp(t.wr, t.fd, len(status)-1) + if err := t.moveCursorUp(t.wr, t.fd, len(status)-1); err != nil { + _, _ = fmt.Fprintf(t.errWriter, "write failed: %v\n", err) + } } }