Skip to content

Let layout determine the editor's remaining height - #950

Open
Michael Greene (mgreenegit) wants to merge 3 commits into
microsoft:mainfrom
mgreenegit:fix/editor-height-small-viewports
Open

Michael Greene (mgreenegit) wants to merge 3 commits into
microsoft:mainfrom
mgreenegit:fix/editor-height-small-viewports

Conversation

@mgreenegit

@mgreenegit Michael Greene (mgreenegit) commented Sep 11, 2026

Copy link
Copy Markdown
Member

Problem

draw_editor currently determines the text area's height by subtracting fixed UI reservations from the viewport: 2 rows with search hidden/disabled, 4 with Search, and 5 with Replace. The adjacent TODO identifies the underlying limitation:

The layout code should be able to just figure out the height on its own.

This duplicates information that is already present in the UI tree. The editor must know how much space its siblings consume, and that accounting must stay synchronized with what is actually drawn.

It also allows a negative intrinsic height in short viewports: a three-row viewport with Replace active requests 3 - 5 = -2. The intrinsic-size setter stores that value, and the layout engine uses it in parent sizing and sibling positioning.

Change

Add one opt-in layout attribute, Context::attr_fill_height, and use it for the editor's text area (or its empty placeholder when no document is open).

The existing vertical-block layout now:

  1. Reserves the measured outer heights of fixed siblings and the padding/borders of filling children.
  2. Clamps the remaining content-height budget to zero.
  3. Divides that budget between children marked to fill, assigning any indivisible remainder to later filling siblings.

The editor is the only production caller added here. With one filling child, its content height is simply:

max(parent content height - fixed sibling heights - filling-child decorations, 0)

Menu, search and status rows are accounted for from the current tree, including siblings drawn after the editor. Floating nodes are outside that stack and do not consume its height.

This removes the editor's hard-coded row subtraction and resolves the adjacent TODO. It also preserves the small-viewport safety goal: insufficient space gives the unbordered editor zero height, not a negative requested size.

Why this is useful

  • One source of layout information: changing the surrounding UI's height no longer requires updating a second reservation table in draw_editor.
  • The usual geometry stays the same: when the existing menu/search/status rows fit, the editor occupies the same remaining rows and the status bar follows it at the bottom.
  • The safety check belongs to allocation: the nonnegative budget is enforced where the available space is distributed, rather than in a caller that reconstructs the layout.

This is a focused vertical-height capability, not a general flexbox system: no weights, shrink priorities, new layout modes or horizontal sizing changes. Unmarked children keep their existing intrinsic-height allocation. Intrinsic measurement and the specialized table/scrollarea layout rules are unchanged.

Scope and review

Three files: the editor call site, the TUI attribute/allocation implementation, and focused TUI tests. No dependencies, settings, commands or platform-specific code are added.

This revision supersedes the PR's initial caller-side clamp and arithmetic-only test with the layout-based fix and geometry tests. It deliberately expands the original one-file scope to address the existing TODO; the original commit remains in the history.

It does not guarantee that all controls remain visible or usable in arbitrarily short terminals, and it does not change existing clipping or overflow policy.

Validation

Four regressions inspect actual node rectangles after the TUI layout pass:

  • Editor-shaped stacks for hidden/disabled search, Search and Replace, plus different header/search/footer heights to verify that the allocator does not depend on the editor's constants.
  • No document, an empty text buffer, and a long text buffer, with shrinking/growing Resize events through heights 1-8, ordinary heights 24/80, and the largest accepted terminal height, 32767.
  • Separate direct-layout checks at zero and COORD_TYPE_SAFE_MAX; those geometry bounds are outside the terminal Resize event contract.
  • Floating-node exclusion, unchanged fixed-only layout, two filling siblings sharing an odd-sized budget, and nested padding/borders with a trailing status row.

Before the allocator change, the initial three layout regressions failed. For example, an eight-row viewport left the empty editor at zero rows instead of the expected six; the nested case also displaced the trailing status row. All four final regressions pass.

Local verification on Windows with Rust 1.97.1:

cargo test --offline --locked --package edit --lib --bin edit
# library: 47 passed, 0 failed, 1 existing ignored
# binary:   2 passed, 0 failed

cargo clippy --offline --locked --package edit --lib --bin edit --tests -- --no-deps --deny warnings
# passed

These exercise the real layout engine and text-area widgets, but are not end-to-end tests of the running editor or evidence of a reproduced crash. Cross-platform validation remains for upstream CI; the local results are not a claim that CI has passed.

Origin

The boundary case arose during a separate console experiment, but this change applies independently to the existing editor. No console implementation, providers or AI code is included, and acceptance does not require agreement on those features.

When the viewport is shorter than the rows reserved for editor chrome or search, draw_editor currently supplies a negative intrinsic height. Clamp the available text height to zero, preserving existing heights when space is sufficient. Keep the calculation private and cover hidden/disabled/search/replace modes at zero, boundary, normal, and maximum supported heights, including shrinking and growing sequences.

Provenance: extract the nonnegative height calculation used in console-exploration-0 at 1d21f16b14998d643ff79e4ce36bb519e3d1fd7b (also retained in combined-exploration-0 at a0f14a4). This is an independently useful console prerequisite, not the embedded console feature. No providers, AI, process launch, dependencies, settings, public API, or keyboard behavior are added.

Validation: the focused regression failed before the clamp (height 1, reserved 2 yielded -1). cargo test --locked --package edit --bin edit passes all 3 tests afterward on Windows with msrustup ms-prod rustc 1.97.1. Candidate structural gate accepted. Review/rollback boundary: this one file; revert this commit independently.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
(cherry picked from commit af11d6bd14bbc30b786173772b6d2d648150c518)
@mgreenegit
Michael Greene (mgreenegit) marked this pull request as ready for review September 11, 2026 21:55
Resolve the adjacent TODO with an opt-in fill-height attribute for vertical blocks. Reserve measured sibling heights and decorations, clamp remaining content height to zero, and distribute it between filling children. Migrate the editor and empty placeholder off fixed UI row reservations.

Replace the initial arithmetic-only regression with actual layout geometry coverage for small/resized viewports, empty and long text buffers, floating nodes, fixed siblings, shared remainder and nested decorations. Preserve existing intrinsic measurement and specialized table/scrollarea layout behavior.

Validated 47 library tests and 2 binary tests, warning-denying Clippy, and the focused structural change gate. No console implementation is included.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@mgreenegit Michael Greene (mgreenegit) changed the title Clamp editor intrinsic height in small viewports Let layout determine the editor's remaining height Sep 16, 2026
Apply the exact whitespace-only change reported by both Linux and Windows Check formatting jobs. The four targeted layout regressions pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

@lhecker Leonard Hecker (lhecker) 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.

I don't believe this is the right direction. My intention was to implement CSS grid & flexbox support in the near term (or at least a subset of those). Like this: https://jsfiddle.net/vkubqc4d/

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.

2 participants