mirror of
https://github.com/JanDeDobbeleer/oh-my-posh.git
synced 2026-08-24 02:34:19 -05:00
fix(runtime): honor COLUMNS fallback without a TTY
This commit is contained in:
committed by
Jan De Dobbeleer
parent
413f96fb12
commit
102edf0153
@@ -28,3 +28,10 @@
|
||||
- On Windows there is no SIGPIPE; child lifecycle management must rely on fd closure / stdin EOF.
|
||||
- On native Linux, process spawns cost 11-16ms - daemon architectures that pay off on Windows can
|
||||
be a wash there (see the bash serve revert in [bash](bash.md)).
|
||||
|
||||
## Statusline width detection
|
||||
|
||||
- On Unix, `terminal-dimensions` runs `stty size` against the renderer's stdin. Claude Code sends
|
||||
statusline JSON over that stdin, so it is not a TTY. A valid `COLUMNS` fallback must replace the
|
||||
resulting `stty` error; returning a non-zero width with the stale error makes
|
||||
`prompt.Engine.canWriteRightBlock` reject ordinary right-aligned blocks (verified 2026-08-03).
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -62,18 +63,12 @@ func (term *Terminal) TerminalWidth() (int, error) {
|
||||
}
|
||||
|
||||
width, err := terminal.Width()
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
if width == 0 {
|
||||
width, err = resolveTerminalWidth(width, err, term.Getenv("COLUMNS"))
|
||||
}
|
||||
|
||||
// fetch width from the environment variable
|
||||
// in case the terminal width is not available
|
||||
if width == 0 {
|
||||
i, err := strconv.Atoi(term.Getenv("COLUMNS"))
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
width = uint(i)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
|
||||
term.CmdFlags.TerminalWidth = int(width)
|
||||
@@ -82,6 +77,22 @@ func (term *Terminal) TerminalWidth() (int, error) {
|
||||
return term.CmdFlags.TerminalWidth, err
|
||||
}
|
||||
|
||||
func resolveTerminalWidth(width uint, terminalErr error, columns string) (uint, error) {
|
||||
if width != 0 {
|
||||
return width, terminalErr
|
||||
}
|
||||
|
||||
columnWidth, err := strconv.Atoi(columns)
|
||||
if err != nil {
|
||||
return 0, errors.Join(terminalErr, err)
|
||||
}
|
||||
if columnWidth <= 0 {
|
||||
return 0, errors.Join(terminalErr, errors.New("terminal width must be greater than zero"))
|
||||
}
|
||||
|
||||
return uint(columnWidth), nil
|
||||
}
|
||||
|
||||
func (term *Terminal) Platform() string {
|
||||
const key = "environment_platform"
|
||||
if val, found := cache.Get[string](cache.Device, key); found {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -64,3 +65,60 @@ func TestMemoryPercentageCalculation(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveTerminalWidth(t *testing.T) {
|
||||
terminalErr := errors.New("not a tty")
|
||||
cases := []struct {
|
||||
TerminalError error
|
||||
Name string
|
||||
Columns string
|
||||
TerminalWidth uint
|
||||
ExpectedWidth uint
|
||||
ExpectedToError bool
|
||||
}{
|
||||
{
|
||||
Name: "terminal width is available",
|
||||
Columns: "120",
|
||||
TerminalWidth: 80,
|
||||
ExpectedWidth: 80,
|
||||
},
|
||||
{
|
||||
Name: "COLUMNS replaces terminal error",
|
||||
Columns: "120",
|
||||
TerminalError: terminalErr,
|
||||
ExpectedWidth: 120,
|
||||
},
|
||||
{
|
||||
Name: "terminal and COLUMNS both fail",
|
||||
Columns: "invalid",
|
||||
TerminalError: terminalErr,
|
||||
ExpectedToError: true,
|
||||
},
|
||||
{
|
||||
Name: "zero COLUMNS is invalid",
|
||||
Columns: "0",
|
||||
TerminalError: terminalErr,
|
||||
ExpectedToError: true,
|
||||
},
|
||||
{
|
||||
Name: "negative COLUMNS is invalid",
|
||||
Columns: "-1",
|
||||
TerminalError: terminalErr,
|
||||
ExpectedToError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.Name, func(t *testing.T) {
|
||||
width, err := resolveTerminalWidth(tc.TerminalWidth, tc.TerminalError, tc.Columns)
|
||||
|
||||
assert.Equal(t, tc.ExpectedWidth, width)
|
||||
if tc.ExpectedToError {
|
||||
assert.Error(t, err)
|
||||
assert.ErrorIs(t, err, terminalErr)
|
||||
return
|
||||
}
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user