Skip to content

progress: trim to the terminal width when writing to stderr - #449

Open
stepancheg wants to merge 1 commit into
jedib0t:mainfrom
stepancheg:cursor/progress-stderr-terminal-width-1243
Open

stepancheg wants to merge 1 commit into
jedib0t:mainfrom
stepancheg:cursor/progress-stderr-terminal-width-1243

Conversation

@stepancheg

@stepancheg stepancheg commented Nov 7, 2026 •

Copy link
Copy Markdown

This commit was generated by AI.

The size watcher ran only for os.Stdout and always measured stdout, so a bar written to stderr kept a width of 0 and was never trimmed. In a narrow terminal the line wrapped, and because the redraw moves the cursor up one row per tracker, every refresh left the old line behind and the output scrolled. For example, the img tool in rules_img writes its bars to os.Stderr, and they overflow terminals narrower than about 110 columns.

Measure the file descriptor of the output writer when it is a terminal (os.Stdout, os.Stderr or another file). Buffers and wrappers that do not expose Fd() behave as before, and SetTerminalWidth still overrides the measured width.

Bars written to stderr are now cut at the terminal width, as stdout bars already were, so long messages may be truncated where they used to wrap. Calling Fd() puts an *os.File into blocking mode; the old code already did this to os.Stdout, and now it also happens to other file writers.

The pseudo-terminal tests use ioctls from golang.org/x/sys, already a dependency, rather than adding a pty library just for tests. Opening a pty that way differs on each OS, so the tests are Linux-only, which is what CI runs. Windows is untested beyond compiling.

This commit was generated by AI.

The size watcher ran only for `os.Stdout` and always measured stdout, so
a bar written to stderr kept a width of 0 and was never trimmed. In a
narrow terminal the line wrapped, and because the redraw moves the
cursor up one row per tracker, every refresh left the old line behind
and the output scrolled. For example, the img tool in
[rules_img](https://github.com/bazel-contrib/rules_img) writes its bars
to `os.Stderr`, and they overflow terminals narrower than about 110
columns.

Measure the file descriptor of the output writer when it is a terminal
(`os.Stdout`, `os.Stderr` or another file). Buffers and wrappers that do
not expose `Fd()` behave as before, and `SetTerminalWidth` still
overrides the measured width.

Bars written to stderr are now cut at the terminal width, as stdout bars
already were, so long messages may be truncated where they used to wrap.
Calling `Fd()` puts an `*os.File` into blocking mode; the old code
already did this to `os.Stdout`, and now it also happens to other file
writers.

The pseudo-terminal tests use ioctls from `golang.org/x/sys`, already a
dependency, rather than adding a pty library just for tests. Opening a
pty that way differs on each OS, so the tests are Linux-only, which is
what CI runs. Windows is untested beyond compiling.
@sonarqubecloud

sonarqubecloud Bot commented Nov 7, 2026

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant