Skip to main content

Module foldable_view_mode

Module foldable_view_mode 

Source
Expand description

foldable-view-mode — the one place <Tab> folds the block at point.

§Why a shared minor and not a chord per view

A grouped, read-only view folds by blocks, and cycling the block at the cursor is a property of that class of view rather than of any one of them. By the “shared behaviour is a minor mode, never a copied keymap” standing rule the chord belongs here once.

It did not start that way, and the shape of the drift is the argument. As of 2026-09-01 magit-nav-mode bound both chords, and its own module doc already stated the generalisation — “navigating sections and folding are meaningful wherever there are sections” — while scoping it to magit. org-agenda-mode then grew an independent copy. Meanwhile project search, the LSP references view, *problems* and *compilation* had neither chord: four foldable grouped views with no way to collapse a block, and nobody noticed, because a gap in a copied set does not announce itself. That is the same failure refreshable-view-mode closed for gr, one chord later.

§The split

Exactly refreshable_view_mode’s:

  • <S-Tab> is owned outright. Cycling every fold in the buffer is generic — magit’s action:magit-cycle-sections body was literally Effect::AppAction(AppEffect::CycleFoldsGlobal), the same expression this mode’s own action evaluates to. There is nothing per-view to declare, so there is no declaration.
  • <Tab> is a target, not a body. A view that wants the plain cycle-the-fold-at-cursor names FOLD_TOGGLE_DEFAULT_ACTION; a view with a genuine specialisation names its own action. Magit’s is real: on a status file line the first press expands the diff so <Tab> and = agree, and everywhere else it is the plain toggle.

Resolution is host-side (Editor::resolve_fold_toggle_action) because it needs the buffer’s active-mode set, which lives on the editor rather than in the ServiceRegistry — the same reason the refresh resolution lives there.

§Activation

Automatic: a mode returning Some from Mode::fold_toggle_action pulls this minor in through the implies cascade. One line per view, and no second thing to remember — forgetting it would kill the chord exactly as silently as the copied keymaps did.

ActivationPolicy::Manual so it never auto-attaches to ordinary buffers. <Tab> in a document buffer is the terminal alias for <C-i>, jump-list-forward, and must stay that way. Taking it costs that motion in the views that opt in, which is the deliberate trade: in a grouped read-only view you navigate with <CR> and ]], and folding a block is the thing you reach for.

Structs§

FoldableViewMode
foldable-view-mode minor. Two keymap entries, no per-buffer resources (Guard = ()), and no <Tab> handler — that body belongs to each view.

Constants§

FOLD_TOGGLE_DEFAULT_ACTION
The body a view names when it wants the ordinary behaviour: cycle the fold containing the cursor. Named explicitly rather than defaulted so that “this view folds” is a statement the view makes, not one it falls into.
VIEW_FOLD_CYCLE_ACTION
<S-Tab>. Owned outright — see the module doc.
VIEW_FOLD_TOGGLE_ACTION
The canonical command name <Tab> resolves to. The host intercepts this id, resolves the active modes’ declared fold-toggle action, and dispatches that.

Functions§

register_foldable_view_actions
Register the three action names.
register_foldable_view_mode
Register FoldableViewMode in registry. Called by register_foundation_modes; it must be registered for the implies cascade to pull it in (an unregistered shared minor is logged at debug! and the chord simply does not bind).