Leading-whitespace summary fix with always-head invariant#5
Merged
Conversation
The previous iteration dispatched the indicator `before-string` between parent and head depending on whether the region had leading whitespace. The head overlay was `evaporate t` and relied on Emacs dropping it when zero-length. That broke the uniform "indicator lives on parent" invariant and triggered display quirks where parent's `before-string` could be shadowed by head's `invisible` property when both overlays started at the same position. This change makes the head overlay the single, uniform home of the indicator. Head is always created (even zero-length) and does not evaporate, so the indicator has a stable host regardless of leading whitespace. Parent is also made non-evaporating so that an edit cannot drop the parent before the modification-hook runs cleanup on head and body. Tests covering the parent-before-string and head-evaporates cases are rewritten to match the new invariant.
Replace the character-by-character `looking-at-p' + `forward-char' loop in `occult--leading-whitespace' with a single `skip-chars-forward' call bounded by END. This is the idiomatic form, runs in C, and handles a slightly broader ASCII whitespace set (form feed and vertical tab in addition to the previous space/tab/LF/CR). Update `occult--visible-end' docstring to state explicitly that BEG is the start of the fold's visible content (first non-whitespace position), not the fold's outer start, and that `occult-summary-max-length' is measured from there. This documents the semantic introduced by the leading-whitespace fix: the summary budget is now spent on real content and leading blank lines do not consume any of it.
Four new tests lock in behavior that was previously only indirectly covered: - `occult-summary-max-length' is measured from the first non-whitespace position, not from the fold start. The test uses cap=3 on a region with two leading newlines and asserts body-split lands at head-split+cap, not beg+cap. - `occult-edit-region' cleans up the head overlay inside the indirect edit buffer alongside parent and body, so the fold content is fully visible for editing. - The base buffer's head overlay survives an edit session opening and still carries the indicator `before-string'. - `revert-buffer' persistence round-trips leading-whitespace folds: after save + delete + restore, the head overlay is re-created with the correct extent and indicator.
SPEC.md: - Core Mechanism now describes three overlays (parent, head, body) rather than two, and notes that parent and head are non-evaporating. - Summary Line Format states that `occult-summary-max-length' is measured from `head-split' (first non-whitespace position), not from the region start. - Overlay Properties gains a Head overlay table, removes `before-string' from the Parent table, and flips Parent `evaporate' to nil. changelog.org: - New 1.2.0 entry covering the leading-whitespace fix, the uniform indicator placement, and the max-length semantic clarification. Credits @ImFstAsFckBoi for the initial investigation and prototype in PR #2.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Folding a region that begins with blank lines used to collapse the summary to just the indicator + ellipsis, because
occult--visible-endmeasured the first line from the region start. This PR introduces a three-overlay structure (parent / head / body) where a new head overlay hides any leading whitespace and always hosts the indicator, even when zero-length. The visible summary now starts at the first non-whitespace character, andoccult-summary-max-lengthis measured from there so leading blank lines no longer consume any of the budget. Parent and head are non-evaporating so a text edit cannot drop them before the modification-hook cleans up.Martin's two commits from #2 are cherry-picked verbatim to establish the head overlay and the
occult--leading-whitespacehelper. Follow-up commits apply the always-head invariant he proposed in his own review thread (indicator lives uniformly on head regardless of input shape), refactor the helper to useskip-chars-forward, clarify theoccult--visible-enddocstring around the new semantics, and update SPEC.md and changelog.org to describe the three-overlay structure and the max-length measurement point.Closes #2