Skip to content

input: Expose consumer-controlled editor fold state #2826

Description

@dannote

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions