Skip to content

tty: add IsStdoutTerminal, StderrTerminalWidth, and IsInteractiveTerminal#1931

Merged
lpcox merged 2 commits intomainfrom
copilot/go-fan-review-golang-org-x-term
Mar 15, 2026
Merged

tty: add IsStdoutTerminal, StderrTerminalWidth, and IsInteractiveTerminal#1931
lpcox merged 2 commits intomainfrom
copilot/go-fan-review-golang-org-x-term

Conversation

Copy link
Contributor

Copilot AI commented Mar 15, 2026

Addresses the improvement opportunities from the go-fan module review of golang.org/x/term (#issue).

Changes

internal/tty/tty.go

  • IsStdoutTerminal() — symmetric wrapper to IsStderrTerminal(), useful for detecting piped stdout in future CLI output formatting
  • StderrTerminalWidth() — returns terminal width via term.GetSize; returns (0, false) when stderr is not a terminal or width cannot be determined
  • IsInteractiveTerminal() — unified signal combining IsStderrTerminal() && !IsRunningInContainer(); provides a single predicate for "output is definitely going to a human terminal"

internal/tty/tty_test.go

  • Tests for IsStdoutTerminal (agreement with term.IsTerminal)
  • TestTermIsTerminal_PipeIsNotTerminal — documents that pipe fds return false from term.IsTerminal, validating the invariant both wrappers rely on
  • Tests for StderrTerminalWidth — verifies width>0 only when stderr is a terminal, and 0/false in CI
  • Tests for IsInteractiveTerminal — verifies it equals IsStderrTerminal() && !IsRunningInContainer(), and is false in CI

Security Summary

No security vulnerabilities introduced. CodeQL: 0 alerts.

Copilot AI and others added 2 commits March 14, 2026 23:56
… with tests

Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
Copilot AI linked an issue Mar 15, 2026 that may be closed by this pull request
4 tasks
Copilot AI requested a review from lpcox March 15, 2026 00:01
@lpcox lpcox marked this pull request as ready for review March 15, 2026 00:08
Copilot AI review requested due to automatic review settings March 15, 2026 00:08
@lpcox lpcox merged commit 0dc86c6 into main Mar 15, 2026
11 checks passed
@lpcox lpcox deleted the copilot/go-fan-review-golang-org-x-term branch March 15, 2026 00:08
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends the internal/tty helpers to provide additional terminal/TTY predicates and terminal width detection, enabling callers to make more reliable decisions about human-facing CLI output formatting.

Changes:

  • Add IsStdoutTerminal() as a stdout counterpart to IsStderrTerminal().
  • Add StderrTerminalWidth() to retrieve stderr terminal width via golang.org/x/term.
  • Add IsInteractiveTerminal() as a single predicate combining “stderr is a terminal” and “not running in a container”, plus corresponding tests.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
internal/tty/tty.go Adds new exported helpers for stdout terminal detection, stderr terminal width, and an “interactive terminal” predicate.
internal/tty/tty_test.go Adds unit tests covering the new helpers and documents term.IsTerminal behavior for pipe FDs.
Comments suppressed due to low confidence (2)

internal/tty/tty_test.go:97

  • This CI-specific test assumes CI/GITHUB_ACTIONS implies a non-terminal stderr. That’s not guaranteed across CI providers or when running tests locally with CI=1, and can make the test fail spuriously. Consider checking term.IsTerminal(int(os.Stderr.Fd())) and skipping if stderr is actually a terminal, or directly asserting !IsStderrTerminal() before the interactive check.
	if os.Getenv("CI") == "" && os.Getenv("GITHUB_ACTIONS") == "" {
		t.Skip("Skipping CI-specific assertion: not running in a CI environment")
	}
	assert.False(t, IsInteractiveTerminal(), "should not be interactive in CI")

internal/tty/tty_test.go:69

  • TestStderrTerminalWidth assumes that if term.IsTerminal(stderr) is true then StderrTerminalWidth() must succeed. The function’s contract is “true if successful”, but term.GetSize can legitimately fail (or return non-positive width) even when IsTerminal is true (e.g., some CI/pseudo-TTYs, Windows/remote environments), which would make this test flaky. Consider asserting weaker invariants: when ok is true, width must be >0 and stderr must be a terminal; when ok is false, width must be 0 (and don’t fail solely because IsTerminal is true).
func TestStderrTerminalWidth(t *testing.T) {
	width, ok := StderrTerminalWidth()
	isTerminal := term.IsTerminal(int(os.Stderr.Fd()))
	if isTerminal {
		assert.True(t, ok, "should succeed when stderr is a terminal")
		assert.Greater(t, width, 0, "terminal width should be positive")
	} else {
		assert.False(t, ok, "should fail when stderr is not a terminal")
		assert.Equal(t, 0, width, "width should be 0 when not a terminal")
	}

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +75 to +80
if os.Getenv("CI") == "" && os.Getenv("GITHUB_ACTIONS") == "" {
t.Skip("Skipping CI-specific assertion: not running in a CI environment")
}
width, ok := StderrTerminalWidth()
assert.False(t, ok, "should not detect terminal width in CI")
assert.Equal(t, 0, width, "width should be 0 in CI")
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.

[go-fan] Go Module Review: golang.org/x/term

3 participants