Motivation
Applications embedding gpui-component's editor can own fold policy independently of tree-sitter. Examples include:
- LSP-provided folding ranges;
- collapsed generated or boilerplate sections;
- unchanged-region elision in diffs;
- compacted log groups;
- disclosure sections in structured text;
- deterministic fixtures that need a known folded state.
The display-map implementation already models this generically: FoldRange is public, and DisplayMap has candidate, active-fold, query, and clear operations. FoldMap also preserves buffer coordinates, projects only display rows, and adjusts/removes folds after edits.
The public state boundary does not currently expose equivalent consumer control. In the pinned architecture, fold candidates are populated internally from tree-sitter and active folds are toggled by the gutter. On current main, apply_highlighter_fold_candidates allows a highlighter to replace candidates, but it is highlighter-oriented and there is still no public state method for setting the active folded ranges. Consumers therefore cannot declare a complete fold state without reaching into private InputState/DisplayMap fields or pretending to be a syntax highlighter.
Suggested API shape
Would you be open to a public, editor-state-owned API along these lines?
impl EditorState {
pub fn set_fold_candidates(
&mut self,
candidates: Vec<FoldRange>,
cx: &mut Context<Self>,
);
pub fn set_folded_ranges(
&mut self,
folded: Vec<FoldRange>,
cx: &mut Context<Self>,
);
}
A combined atomic method would also work:
pub fn set_folds(
&mut self,
candidates: Vec<FoldRange>,
folded: Vec<FoldRange>,
cx: &mut Context<Self>,
);
Useful contract properties would be:
- the supplied state is authoritative and replaceable, so declarative renderers can reconcile it;
- active folds must be valid candidates (or the method normalizes them predictably);
- buffer/Rope content and buffer coordinates remain unchanged;
- edits retain the existing overlap-removal and line-shifting behavior;
- pointer gutter toggles and programmatic state use the same underlying fold map;
- no tree-sitter, language registry, or highlighter identity is required to provide ranges.
This proposal is intentionally about whole-line editor folds, matching the existing FoldRange and FoldMap behavior. Arbitrary intra-line hidden text, placeholders, and redaction are different projection features and should not be implied by this API.
Current limitation
FoldMap hides only interior whole lines (start_line + 1 .. end_line - 1) and keeps both boundary lines visible. That is suitable for folding, but not for arbitrary hidden text ranges. Exposing the existing fold model at EditorState would still provide a useful generic boundary without broadening its semantics.
Motivation
Applications embedding
gpui-component's editor can own fold policy independently of tree-sitter. Examples include:The display-map implementation already models this generically:
FoldRangeis public, andDisplayMaphas candidate, active-fold, query, and clear operations.FoldMapalso preserves buffer coordinates, projects only display rows, and adjusts/removes folds after edits.The public state boundary does not currently expose equivalent consumer control. In the pinned architecture, fold candidates are populated internally from tree-sitter and active folds are toggled by the gutter. On current
main,apply_highlighter_fold_candidatesallows a highlighter to replace candidates, but it is highlighter-oriented and there is still no public state method for setting the active folded ranges. Consumers therefore cannot declare a complete fold state without reaching into privateInputState/DisplayMapfields or pretending to be a syntax highlighter.Suggested API shape
Would you be open to a public, editor-state-owned API along these lines?
A combined atomic method would also work:
Useful contract properties would be:
This proposal is intentionally about whole-line editor folds, matching the existing
FoldRangeandFoldMapbehavior. Arbitrary intra-line hidden text, placeholders, and redaction are different projection features and should not be implied by this API.Current limitation
FoldMaphides only interior whole lines (start_line + 1 .. end_line - 1) and keeps both boundary lines visible. That is suitable for folding, but not for arbitrary hidden text ranges. Exposing the existing fold model atEditorStatewould still provide a useful generic boundary without broadening its semantics.