Skip to content

Size the editor viewport to the live terminal height - #95

Merged
goofmint merged 1 commit into
mainfrom
feature/92-editor-viewport-height
Aug 28, 2026
Merged

Size the editor viewport to the live terminal height#95
goofmint merged 1 commit into
mainfrom
feature/92-editor-viewport-height

Conversation

@goofmint

@goofmintgoofmint commented Aug 28, 2026

Copy link
Copy Markdown
Owner

fix#92

The editor showed 20 rows no matter how tall the terminal was.

Root cause

EditorView takes an optional viewportHeight prop and falls back to DEFAULT_VIEWPORT_HEIGHT = 20. shell.tsx's EditorArea never passed that prop, so the fallback was the only value it ever used. editorView.tsx's own TSDoc said as much under "Scope note on viewportHeight" — live measurement was deferred to a later task. This is that task.

The fix

computeEditorViewportHeight(terminalHeight, chrome) — a pure function in viewport.ts, beside computeVisibleLineRange — subtracts the chrome from the terminal height and clamps to a minimum of 1 row. EditorArea feeds it the live terminal height and the heights of exactly the chrome this render actually draws, each derived from the same condition that decides whether that region renders at all: the tab bar (tabs.length > 0), the find widget (the same find && isFindOpen && props.findService the JSX uses), Shell's sibling Panel, and the status bar. Nothing is hardcoded that could drift from what is drawn.

EditorView's prop keeps its shape and its prop-wins behaviour; DEFAULT_VIEWPORT_HEIGHT is now only the no-live-terminal fallback, and the TSDoc says that instead of describing the deferral.

useAppContext() rather than useTerminalDimensions()

useTerminalDimensions() cannot be used here. It calls useRenderer(), which throws "Renderer not found." when no renderer is mounted (@opentui/react@0.1.107, index.js:50-55, 72-83). EditorArea is constructed in tests outside a live CliRenderer, so that throw would break them rather than degrade.

useAppContext() returns { renderer } which may be undefined, so useLiveTerminalHeight() subscribes to CliRenderEvents.RESIZE when a renderer exists and returns undefined when one does not — leaving viewportHeight unset and EditorView on its existing constant. It mirrors useLiveTheme's themeService === undefined fallback, including re-syncing to the current height before subscribing so a resize landing between render and effect is not missed.

TAB_BAR_HEIGHT = 3 was measured against the vendored headless renderer rather than assumed: @opentui/core's TabSelectRenderable defaults both showUnderline and showDescription to true.

Validation

bun test 1748 pass / 1 skip / 0 fail; bunx tsc --noEmit clean; bun run lint clean. No existing snapshot needed regenerating — editorView.snapshot.test.tsx always passes an explicit viewportHeight, so prop-wins behaviour is confirmed rather than assumed.

The regression test reproduces the bug exactly when the fix is reverted. Removing viewportHeight={viewportHeight} from EditorArea fails it, with the captured frame in a 50-row terminal showing line0..line19 and then 30 blank rows:

│19 line18
│20 line19
│
│ ← 30 blank rows

Removing the Math.max(1, ...) clamp fails the clamp unit tests with Expected: 1, Received: 0. Both mutations were re-run independently of the implementing agent.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WELSsojQQL1cTAR5iUUsTK


Generated by Claude Code

Summary by CodeRabbit

  • 新機能

    • 端末の実際の高さに応じて、エディターの表示領域が自動調整されるようになりました。
    • タブバー、検索ウィジェット、パネル、ステータスバーの表示領域を考慮して、より多くの行を表示できます。
    • 端末のリサイズ時も表示範囲が追従します。
    • 端末サイズが取得できない場合は、従来の既定値に戻ります。
  • バグ修正

    • 高さのある端末でエディターの表示行数が固定される問題を修正しました。

EditorView always rendered exactly 20 rows because EditorArea never
passed a viewportHeight prop at all, so EditorView silently fell back
to its own hardcoded DEFAULT_VIEWPORT_HEIGHT regardless of the real
terminal size.
EditorArea now reads the live terminal height (useLiveTerminalHeight,
wrapping @opentui/react's resize event without crashing when no
renderer is mounted) and subtracts exactly the chrome it renders this
pass - tab bar, find widget, Shell's sibling Panel, and the status bar
- via a new pure computeEditorViewportHeight (viewport.ts), then
threads the result into EditorView's existing viewportHeight prop.
Each chrome height is derived from the same condition that decides
whether that region renders at all, so it can't drift from what's
actually drawn. When no live terminal is available, viewportHeight is
left undefined and EditorView keeps falling back to its own constant,
unchanged.
Added a regression test that renders a 60-line document into a
terminal taller than the old 20-row cap and asserts lines past index
20 are visible, plus unit tests for computeEditorViewportHeight
covering chrome combinations and the minimum-1-row clamp.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WELSsojQQL1cTAR5iUUsTK
@coderabbitai

coderabbitaiBot commented Aug 28, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ca7147a5-703a-449b-bd2a-c15fc39129f7

📥 Commits

Reviewing files that changed from the base of the PR and between e14293f and d4210ca.

📒 Files selected for processing (5)
  • packages/core/src/ui/editorView.tsx
  • packages/core/src/ui/shell.snapshot.test.tsx
  • packages/core/src/ui/shell.tsx
  • packages/core/src/ui/viewport.test.ts
  • packages/core/src/ui/viewport.ts

Included review availability: 1 review is currently available. Your included PR review attempts over the past 7 days set your current allowance at 2 reviews per hour.


Walkthrough

EditorAreaが端末高と周辺UIの高さからエディターのビューポートを計算します。端末リサイズ時は計算結果を更新します。端末がない場合は従来の既定値を使用します。テストは50行端末で40行目まで表示されることを検証します。

Changes

実測ビューポート測定

Layer / File(s)Summary
ビューポート計算契約
packages/core/src/ui/viewport.ts, packages/core/src/ui/viewport.test.ts
EditorAreaChromecomputeEditorViewportHeightを追加しました。クローム高さを端末高から差し引き、結果を最低1行に制限します。
ShellからEditorViewへの接続
packages/core/src/ui/shell.tsx
端末の初期高を取得し、リサイズイベントを購読します。Panelを含むクローム構成からビューポートを計算し、EditorViewへ渡します。
配線の検証とAPI説明
packages/core/src/ui/editorView.tsx, packages/core/src/ui/shell.snapshot.test.tsx
viewportHeightの算出元とフォールバックを文書化しました。50行端末で60行文書の20行目と40行目が表示される統合テストを追加しました。

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk:⚪ Minimal · up to d4210

The editor viewport now follows the live terminal height while preserving the existing fallback and explicit prop behavior; no actionable merge-blocking risk remains after normal checks and review.

Sequence Diagram(s)

sequenceDiagram
participant CliRenderer
participant EditorArea
participant ViewportCalculator
participant EditorView
CliRenderer->>EditorArea: 端末高とリサイズイベントを提供
EditorArea->>ViewportCalculator: 端末高とクローム高さを渡す
ViewportCalculator-->>EditorArea: viewportHeightを返す
EditorArea->>EditorView: viewportHeightを渡す
Loading

Suggested reviewers:claude

Poem

うさぎは端末の高さを測る

クロームの行を静かに引く
リサイズにも耳をすませ
エディターの窓を広げる
長い文書も跳ねて見える
ぴょん、と正しい表示へ

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ Passedタイトルは、固定の20行表示を廃止し、ライブ端末高に基づいてエディターのビューポートを設定する主変更を正確に表しています。
Linked Issues check✅ PassedIssue #92の「最初の20行だけ表示される」問題に対応しています。端末高とEditorAreaのクロームを使ってビューポート高を計算し、20行を超える表示を回帰テストで検証しています。
Out of Scope Changes check✅ Passed変更はIssue #92への対応に関連しています。ビューポート計算、リサイズ追従、フォールバック、公開Propsの接続、ドキュメント、および関連テストのみを含みます。明らかな範囲外の変更はありません。
Docstring Coverage✅ PassedDocstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 5 functions across 5 files.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/92-editor-viewport-height
🚀 Post-Merge Actions
  • Notionに記載

Comment @coderabbitai help to get the list of available commands.

@goofmint
goofmint merged commit 181c070 into mainAug 28, 2026
6 checks passed
@coderabbitai

Copy link
Copy Markdown

🚀 Post-Merge Actions

  • Notionに記載 — Output delivered via connected integrations.

Sign up for freeto 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.

Bug: Only the first 20 lines are displayed.

2 participants

@goofmint@claude