Skip to content

feat: Allow setting rows/cols for dimensions instead of just pixels - #763

Open
DaltonSW wants to merge 5 commits into
charmbracelet:mainfrom
DaltonSW:feat/rows-cols
Open

feat: Allow setting rows/cols for dimensions instead of just pixels#763
DaltonSW wants to merge 5 commits into
charmbracelet:mainfrom
DaltonSW:feat/rows-cols

Conversation

@DaltonSW

Copy link
Copy Markdown
Contributor

Adds Set Rows/Set Columns commands to size the terminal in character
cells instead of pixels. The pixel size is derived by probing the live
xterm.js terminal's own fit/measurement APIs and iterating to an exact
match, so it stays correct across font/theme changes without depending
on any of xterm.js's private internals.

  • I have read CONTRIBUTING.md.
  • I have created a discussion that was approved by a maintainer (for new features). (I got Discord approval, if that counts)

@meowgorithm

Copy link
Copy Markdown
Member

@DaltonSW mind fixing the build errors?

@DaltonSW

Copy link
Copy Markdown
Contributor Author

@meowgorithm Done! I think I misunderstood LFS stuff. 😅

Did you want me to clean up any of the govulncheck or golint stuff?

@meowgorithm

Copy link
Copy Markdown
Member

Apologies for the slow reply @DaltonSW — yes, please. We'll need CI green in order to merge this.

@DaltonSW
DaltonSW force-pushed the feat/rows-cols branch 2 times, most recently from 0380b12 to 1b0ea2c Compare August 4, 2026 12:42
@andrinoff

Copy link
Copy Markdown
Member

Hey @DaltonSW, thank you for this PR. Regarding the token variables, I talked to Christian, lets add an exception for this rule (in this repo)

@andrinoff andrinoff left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thank you, @DaltonSW! Just a few things

Comment thread vhs.go
Comment on lines +239 to +253
var cellWidth, cellHeight float64
for range dimensionProbeAttempts {
cols, rows := measure(probeWidth, probeHeight)

tooSmall := cols <= 0 || rows <= 0 ||
(style.Columns > 0 && cols < style.Columns) ||
(style.Rows > 0 && rows < style.Rows)
if !tooSmall {
cellWidth = float64(probeWidth) / float64(cols)
cellHeight = float64(probeHeight) / float64(rows)
break
}
probeWidth = double(probeWidth)
probeHeight = double(probeHeight)
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

silent failure. if !tooSmall is never satisfied cellWidth and cellHeight stay 0

Comment thread vhs.go
Comment on lines +255 to +262
contentWidth := probeWidth
contentHeight := probeHeight
if style.Columns > 0 {
contentWidth = int(math.Round(cellWidth * float64(style.Columns)))
}
if style.Rows > 0 {
contentHeight = int(math.Round(cellHeight * float64(style.Rows)))
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

it will result in an 0x0 image, reasons in comment 1

Comment thread vhs.go
Comment on lines +267 to +282
for range dimensionCorrectionAttempts {
cols, rows := measure(contentWidth, contentHeight)

converged := true
if style.Columns > 0 && cols != style.Columns {
contentWidth += int(math.Round(float64(style.Columns-cols) * cellWidth))
converged = false
}
if style.Rows > 0 && rows != style.Rows {
contentHeight += int(math.Round(float64(style.Rows-rows) * cellHeight))
converged = false
}
if converged {
break
}
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

this will give up silently after 5 attempts

@andrinoff andrinoff left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We should round up to even numbers, because MP4 and WebM Video dont like odd numbers as the resolution

Adds `Set Rows`/`Set Columns` commands to size the terminal in character
cells instead of pixels. The pixel size is derived by probing the live
xterm.js terminal's own fit/measurement APIs and iterating to an exact
match, so it stays correct across font/theme changes without depending
on any of xterm.js's private internals.
Adds demo tapes for Set Rows and Set Columns (individually and
combined) and documents them in examples/settings/README.md,
matching the existing width/height example pattern.
resolveRowsColumns gave up quietly in two places: if the probe loop never
measured the terminal, cellWidth/cellHeight stayed zero and the viewport
was computed as 0x0; and if the correction loop ran out of attempts, the
tape rendered at whatever grid it happened to land on.

Both now return a descriptive error naming the requested grid and the
closest measurement. Setup returns an error so they reach the caller
through the existing Evaluate error path.
MP4 and WebM encoders reject odd-numbered resolutions, but the
grid-derived width/height from Set Rows/Set Columns could land on an
odd pixel count.
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.

3 participants