Skip to content

fix: open the pair where the caret reaches two inline objects meeting - #415

Merged
Azganoth merged 1 commit into
mainfrom
bug/projection-boundary-give-way
Sep 6, 2026
Merged

fix: open the pair where the caret reaches two inline objects meeting#415
Azganoth merged 1 commit into
mainfrom
bug/projection-boundary-give-way

Conversation

@Azganoth

@Azganoth Azganoth commented Sep 6, 2026

Copy link
Copy Markdown
Owner

Summary

A caret only ever arrives where two adjacent inline objects meet with one of them already projected, because reaching either object projects it first. An active session keeps a caret that is inside its range, and the session's own edge counts as inside, so target discovery never ran at the one position the pair exists on. The pair #312 opens was reachable by clicking and by nothing else, and under keyboard motion the author still read one neighbour as the file holds it and the other as it renders, decided by the direction of travel.

  • A clean session whose empty caret sits on its own edge is restored onto a plugin-free probe of the document it is holding out of view, and the ordinary precedence is put to that. Where the answer takes in everything the session covers and more, the session gives way where it stands and what discovery found opens in its place.
  • Asking discovery, rather than asking whether a neighbour happens to be there, keeps the rule adapter-agnostic and leaves the caret alone wherever the answer is the object already open.
  • Requiring the answer to contain the session is what stops the caret being handed sideways. Two identical adjacent references are one text node and pair with nothing, so discovery there answers with the neighbour itself; giving way to it would swap which of the two reads as source and silently undo an edit to the first.
  • Restricted to a clean session and an empty caret, so reaching an edge neither commits an edit nor disturbs a selection.
  • Both pieces this needs came from Project both objects when the caret sits between two #312: a session could already declare that it no longer owns the caret, and finalizing in place already restores without recording a suppressed selection, which is what stops the object simply reopening in the pair's place.

The issue's first reading of this defect said the caret skipped the meeting place and passed a character over with it. It does not, and the issue has been corrected: that reading came from comparing positions across the projected and canonical documents instead of reading the caret drawn in place. There is one cause, and no document position is skipped.

Related Issue

Closes #413

Verification

Focused tests drive the editor mount the plugin tests use.

  • A caret reaching the meeting place from inside the first object, and from inside the second, opens the pair, and both arrive at the same caret.
  • A projection whose object has no projectable neighbour keeps the caret on its own edge, unmoved.
  • A projection whose neighbour pairs with nothing keeps the caret rather than handing it over, covering two identical adjacent references, where the neighbour is what discovery answers with.
  • A projection holding an edit keeps the edit and stays open when the caret reaches its edge.
  • Everything Project both objects when the caret sits between two #312 settled about the pair once it is open still holds, including giving way to the object the caret moves into, the seam rule for an edit, a deletion and a paste, and the escaped-side conversions.

Manually verified by sweeping the caret one position at a time across Z *ab***cd** Z, Z [ab](x)[cd](y) Z, A ©® b and Z *ab* cd Z in both directions, with the caret drawn in place: each press moves one position, the pair opens on the meeting place in both directions for each pair, and the run with a plain-text neighbour is unchanged.

The whole frontend suite and the corpus round trips run clean, and the coverage floor holds.

Not verified: the desktop E2E suite, which CI runs as its own job; backend checks, since nothing under src-tauri/ changed.

Notes

The changelog entry for the pair is amended rather than given a Fixed line of its own, because both changes are unreleased and a reader of the release notes should meet one coherent statement rather than a feature followed by a defect in it that never shipped.

A caret only ever arrives where two objects meet with one of them already
projected, because reaching either object projects it first, and an active
session keeps a caret on its own edge: `isRangeInside` is inclusive, so
discovery never ran at the one position the pair exists on. The pair was
reachable by click and by nothing else.

A clean session whose caret sits on its edge now restores onto a plugin-free
probe and puts the ordinary precedence to the document it was holding out of
view. Where that answers with a range taking in everything the session covers
and more, the session gives way where it stands and the pair opens in its place.

Asking discovery, rather than asking whether a neighbour is there, keeps the
rule adapter-agnostic. Requiring the answer to contain the session is what
keeps it from handing the caret sideways: two identical adjacent references are
one text node and pair with nothing, so discovery there answers with the
neighbour itself, and giving way to it would swap which of the two reads as
source and undo an edit to the first.

Restricted to a clean session and an empty caret, so reaching an edge neither
commits an edit nor disturbs a selection, and a projection whose object has no
projectable neighbour keeps the caret exactly where it had it.
@Azganoth Azganoth added the Bug Something isn't working label Sep 6, 2026
@Azganoth Azganoth self-assigned this Sep 6, 2026
@Azganoth
Azganoth merged commit 0046046 into main Sep 6, 2026
3 checks passed
@Azganoth
Azganoth deleted the bug/projection-boundary-give-way branch September 6, 2026 03:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

A projection keeps the caret where its object meets another, so the pair never opens by keyboard

1 participant