Collapsible regions
CodeEditor.Folding takes an IFoldingProvider — asked, per line, where a collapsible region
STARTS, exactly like the other providers, so a host answers out of a syntax tree or an indentation
scan of the visible window rather than by parsing the file. The editor owns which regions are
CLOSED, because that is the user's state and it has to survive a re-parse.
Collapse,Expand,ToggleFold,ExpandAll,IsCollapsed,CollapsedRegions.FoldingMargindraws the chevrons and toggles on a click; hand iteditor.FoldingState.- A collapsed region leaves a boxed placeholder after its header's text — the provider's
FoldRegion.Placeholder, or an ellipsis. - Up and down arrows count ROWS, so a collapsed region is one step and not the fifty lines it
hides. Collapsing over the caret puts the caret on the header. A fold whose header an edit
deletes opens; the rest move with the lines they hide.
Screen rows and document lines are no longer the same number. Extent.Height is now the
visible ROW count, and EditorViewport.VisibleLineCount counts rows. A margin that draws every
line from FirstVisibleLine to FirstVisibleLine + VisibleLineCount still compiles and still
works when nothing is folded; past a collapsed region it stops early instead of drawing hidden
lines on top of the header. Iterate MarginContext.VisibleLines instead and neither happens —
it yields exactly the document lines on screen, and allocates nothing.
CodeLens
CodeEditor.CodeLens takes an ICodeLensProvider: a list of anchor lines, and the items to draw
on the row above each. Items are CodeLensItem(Text, Tooltip, Invoke) — drawn on the annotated
line's own indentation, underlined on hover, and invoked on RELEASE only where the press began.
The anchors are a LIST rather than a per-line question, unlike every other provider, and
deliberately: the editor needs the number of lens rows in the whole document to know how tall the
document is, and asking a million lines that question is the one thing this control will not do.
Rectangular selection and multiple carets
- Alt+drag a rectangle, or Shift+Alt+arrow to open one from the caret (Shift+Alt+Cmd+arrow
on macOS, where Alt+arrow is already word movement). - Ctrl/Cmd+Alt+click adds a caret anywhere. Escape goes back to one.
- Typing, Backspace and Delete happen at every caret, applied last-to-first so each caret keeps the
character it was on — including several carets on the SAME line, where the ordinary position
transform cannot help. A typing run at N carets is one undo step. - Copying takes every selection, top to bottom, one per line, so a column pastes as a column.
SetBoxSelection,AddCaret,CollapseToPrimaryCaret,AdditionalSelections,BoxSelection,
HasMultipleCarets.
Context popovers
PopoverRequested fires on a right-click, on the context-menu key and from RequestPopover. It
hands the host the position, the line, the WORD under it, the selection, and the TextMate scopes
— which is what makes a popover context-dependent without the editor learning any languages. Set
Content and the editor anchors it to that character cell and dismisses it on Escape, a click
away, a scroll, or an edit; set Handled and the editor does nothing further.
GetCellRect(TextPosition) is public, so a host that would rather place its own overlay can.
A right-click INSIDE the selection leaves it alone; anywhere else it moves the caret first.
Opening a document no longer reads it
A document used to be measured line by line as it was set: every line walked a grapheme cluster at
a time to find the widest one, so the horizontal scrollbar could be exact. That is the one cost
proportional to the file, and it is gone. Lines are measured when they first come on screen.
What changes for a host: CodeEditor.Extent.Width now covers every line that has been on
screen, not every line in the document, and it grows as wider lines are scrolled into view — the
way every editor that virtualizes behaves. Extent.Height is unchanged and still exact, because a
line count is known without reading a line. Nothing else moves: the widest visible line is measured
before layout reads the extent, so a scrollbar is never wrong about what is on screen.
A million-line document now opens in under a millisecond, and the demo's scale scenario does
exactly that — see GeneratedBuffer in the demo for a host-supplied ITextBuffer that composes a
line when the control asks for it and stores nothing.
Documentation
A full manual ships with the site: docs.html, a contents tree beside the text, every public type
with the problem it solves and the code that uses it, diagrams of the character grid, of screen
rows against document lines, and of the highlighting pipeline, plus screenshots taken from the
demo. The landing page gains a half-minute tour recorded from the browser demo and a screenshot on
every feature card.