Skip to content

feat: implement end-to-end code folding#96

Merged
tig merged 15 commits into
developfrom
folding-ui
May 13, 2026
Merged

feat: implement end-to-end code folding#96
tig merged 15 commits into
developfrom
folding-ui

Conversation

@tig
Copy link
Copy Markdown
Member

@tig tig commented May 13, 2026

Summary

Implements the folding feature as specified in \specs/folding/spec.md\ and \specs/folding-ui/spec.md.

What's included

Folding data model (lifted from AvaloniaEdit \d7a6b63, heavily adapted):

  • \FoldingManager\ — owns \TextSegmentCollection, subscribes to document changes, exposes \FoldingChanged\ event
  • \FoldingSection\ — represents a foldable region with \IsFolded\ toggle
  • \NewFolding\ / \XmlFoldingStrategy\ — unchanged from upstream

Rendering pipeline integration:

  • \FoldingTransformer\ — \IVisualLineTransformer\ that replaces folded ranges with \FoldingMarkerElement\ (\⋯)
  • Auto-installed when \Editor.FoldingManager\ is set

Editor integration:

  • \FoldingManager?\ property on \Editor\
  • \DrawVisibleLines\ skips folded lines via \GetVisibleLineNumbers()\ mapping
  • \ContentSize\ adjusts for hidden lines
  • Caret auto-expands folds when navigating into them
  • \Command.Collapse\ with Ctrl+M keybinding
  • Gutter fold indicators (▸/▾/│) with click-to-toggle

ted integration (R9 compliance):

  • \BraceFoldingStrategy\ for C-family/JSON brace folding
  • Auto-updates folds on document changes

Tests

  • 19 new folding-specific tests (FoldingManager, BraceFoldingStrategy, FoldingTransformer)
  • All 345 tests pass (0 errors, 0 warnings)

Upstream tracking

  • Updated \ hird_party/AvaloniaEdit/UPSTREAM.md\ with folding lift documentation

Lift AvaloniaEdit folding data model (FoldingManager, FoldingSection, NewFolding,
XmlFoldingStrategy) into Terminal.Gui.Document.Folding namespace. Add rendering
pipeline integration via FoldingTransformer and FoldingMarkerElement.

Editor integration:
- FoldingManager property with auto-install of FoldingTransformer
- DrawVisibleLines skips folded lines via GetVisibleLineNumbers() mapping
- ContentSize adjusts for hidden lines
- Caret auto-expands folds when navigating into them
- Ctrl+M toggle fold command
- Gutter shows fold indicators (▸/▾/│) with click-to-toggle

ted integration:
- BraceFoldingStrategy for C-family/JSON brace folding
- Auto-updates folds on document changes

Tests: 19 new folding tests (FoldingManager, BraceFoldingStrategy, FoldingTransformer)
All 345 tests pass with 0 errors, 0 warnings.

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c8d31f9663

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/Terminal.Gui.Editor/Editor.Drawing.cs
Comment thread src/Terminal.Gui.Editor/Folding/FoldingManager.cs Outdated
Factor Gutter into two distinct subviews:
- LineNumberGutter: line numbers and line-selection mouse handling
- FoldingGutter: fold indicators (▸/▾/│) with Command.Toggle bound to
  MouseFlags.LeftButtonClicked via MouseBindings/AddCommand pattern

This replaces the monolithic OnMouseEvent with proper command bindings,
enabling independent styling and logic separation.

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a9c0c3172b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/Terminal.Gui.Editor/Editor.Drawing.cs Outdated
Comment thread src/Terminal.Gui.Editor/Editor.cs Outdated
…ter priming, caret-in-fold

- Invalidate _cachedVisibleLineNumbers on Document replacement (P1)
- Compute hidden line count as union of folded ranges to avoid
  double-counting nested folds (P1)
- Prime syntax highlighter from mapped document line number, not
  viewport row index, when folds exist above viewport (P1)
- Move EnsureCaretNotInFold from FoldingChanged to SetCaretOffset so
  collapsing a fold doesn't immediately re-expand it (P2)
- Fix whitespace formatting in TedApp.cs (CI failure)

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9ff774d16e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/Terminal.Gui.Editor/Editor.Drawing.cs
Comment thread src/Terminal.Gui.Editor/Editor.cs
tig and others added 2 commits May 13, 2026 00:05
… is set

The FoldingManager setter was missing the UpdateLineNumberPadding() call,
so SyncLayout() never ran and the FoldingGutter subview was never created.
LineNumberGutter also used Viewport.Width (0 before layout) instead of
Dim.Fill(). Both subviews now use Dim-based layout.

Added 4 new GutterTests that fail without this fix:
- Gutter_Has_LineNumberGutter_SubView_Without_Folding
- Gutter_Has_Both_SubViews_With_Folding
- LineNumberGutter_Width_Is_Fill_Not_Zero
- FoldingGutter_Has_Toggle_MouseBinding

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Swapped Gutter subview order so LineNumberGutter is at X=0 with
Width=Dim.Fill(2) and FoldingGutter is at X=Pos.Right(lineNumbers)
with Width=2.

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

_document = value;
_document.Changed += OnDocumentChanged;
_caretAnchor = CreateCaretAnchor (caretOffset);

P1 Badge Reset folding manager when replacing the document

Updating Editor.Document swaps _document but leaves FoldingManager untouched, so the installed folding pipeline can still reference fold offsets from the previous document. If callers reuse the editor and assign a new TextDocument without also recreating FoldingManager, visible-line mapping and content height calculations run against stale fold state, which can hide or skip valid lines in the new file. The document swap path should clear or rebind folding state atomically.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/Terminal.Gui.Editor/Rendering/FoldingTransformer.cs Outdated
tig and others added 2 commits May 13, 2026 00:17
Address P1 CR feedback: viewport.Y is an index into the visible-line
list, but EnsureCaretVisible, cursor placement, and MousePositionToOffset
were using raw document line indices. Added GetCaretVisibleLineIndex()
that maps the caret's document line to its position in the visible-line
list, and updated all viewport-coordinate consumers:

- EnsureCaretVisible: uses GetCaretVisibleLineIndex()
- UpdateCursorPosition: uses GetCaretVisibleLineIndex()
- MousePositionToOffset: maps through GetVisibleLineNumbers()

MoveCaretVertically continues using GetCaretLineIndex() (document-level
navigation is correct there — folding skip is handled by
EnsureCaretNotInFold).

Also merges develop (UPSTREAM.md conflict: Folding + Indentation rows).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Deduplicate folded sections by start offset before applying transforms.
Only the leftmost fold on a line is applied — once collapsed, the tail
is hidden and subsequent folds are subsumed. Fixes double-marker issue
when GetFoldingsContaining and AllFoldings overlap or nested folds
start on the same line.

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c20249957f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/Terminal.Gui.Editor/Editor.cs
Comment thread src/Terminal.Gui.Editor/Editor.cs
Merge develop which landed the AvaloniaEdit highlighting lift. Conflicts:
- Editor.Drawing.cs: kept folding visible-line mapping, dropped old
  SyntaxHighlighter/PrepareSyntaxHighlighter (replaced by HighlightingColorizer)
- TedApp.cs: kept folding init, dropped old SyntaxHighlighter setup
- UPSTREAM.md: combined Folding + Highlighting entries

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 514d27ac82

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/Terminal.Gui.Editor/Editor.Commands.cs
Comment thread src/Terminal.Gui.Editor/Editor.Commands.cs
tig and others added 2 commits May 13, 2026 00:40
Introduce [Flags] GutterOptions enum with None=0, LineNumbers=1, Folding=2.
Replace Editor.ShowLineNumbers bool with Editor.GutterOptions property.
Gutter.SyncLayout now dynamically adds/removes LineNumberGutter and
FoldingGutter subviews based on the flags (and FoldingManager presence).
Update ted, unit tests, and integration tests accordingly.
Add two new test cases: Folding_Only and Folding_Flag_Without_FoldingManager.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add 'Fold Indicators' checkbox to ted's Options menu so users can
independently toggle the folding gutter column on/off (R9 compliance).

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 233f612c31

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/Terminal.Gui.Editor/Editor.Drawing.cs Outdated
Gutter, LineNumberGutter, and FoldingGutter add MouseBindings for
WheeledUp→ScrollUp and WheeledDown→ScrollDown without AddCommand
handlers. When fired, DefaultCommandNotBoundHandler invokes TryBubbleUp
which reaches the Editor (Padding's Parent) because Editor sets
CommandsToBubbleUp to include ScrollUp/ScrollDown/ScrollLeft/ScrollRight.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
tig and others added 4 commits May 13, 2026 01:05
GetVisibleLineNumbers() previously used GetFoldingAtLine() which returns
only the first fold found. If multiple collapsed folds start on the same
line with different end offsets, lines inside the longer fold could leak
into the visible-line map. Now scans all folded sections starting on the
line and skips past the maximum end line.

Addresses PR review feedback (P2).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Move LineNumberGutter to LineNumberGutter.cs and FoldingGutter to
FoldingGutter.cs, leaving only the Gutter class in Gutter.cs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add AGENTS.md pointing agents to CLAUDE.md for project rules.
- Rename GetLineNumberPaddingWidth to GetGutterWidth and
  UpdateLineNumberPadding to UpdateGutterWidth since the method now
  computes width for both line numbers and folding columns.

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

Align the namespace with the assembly name. This is the same change as PR #98
(copilot/fix-editor-namespace-issue) applied directly to the folding-ui branch.

- Changed RootNamespace in .csproj from Terminal.Gui.Views to Terminal.Gui.Editor
- Updated all namespace declarations (Terminal.Gui.Views -> Terminal.Gui.Editor,
  Terminal.Gui.Views.Rendering -> Terminal.Gui.Editor.Rendering)
- Updated embedded resource prefix in Resources.cs
- Updated using directives across tests, examples, and benchmarks
- Re-added 'using Terminal.Gui.Views' where TG's own view types are needed
- Updated specs/docs references

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d4a03718b8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/Terminal.Gui.Editor/Editor.cs
@tig tig merged commit 398ed8a into develop May 13, 2026
8 checks passed
@tig tig deleted the folding-ui branch May 13, 2026 07:27
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.

1 participant