Skip to content

Project an escape as its two characters so deleting the backslash converts the run #255

Description

@Azganoth

Summary

Text the file keeps literal and text that is live syntax read identically on screen, and there is no character to delete to convert one into the other. Removing an escape today means deleting the whole run and retyping it.

Projecting the escape itself — the backslash and the character it escapes — gives the author the character back. Deleting it converts the run. Nothing is stored to make this work: the escape is derived from the text and the serializer's safety check, so it is available again on every open, including after a save and reopen.

This is the reversal gesture #238 scopes. It replaces a guess about what the author meant with something the author does.

Expected behavior

A caret arriving at a character the file will escape projects two characters, the backslash and that character. Deleting the backslash converts the run to the syntax it describes. Undo reverses it like any other document change.

The projection shows what the file will hold, not what it held when opened.

This is the inverse of a gesture that already exists: a link projects its source, and an edit making that source invalid commits it as literal text.

Related context

Done when

  • A caret at an escaped character projects the backslash and that character.
  • Deleting the backslash converts the run; Undo reverses it.
  • The caret-time cost is measured and recorded before the design is fixed.
  • Adapter precedence is settled where an escape abuts a live target.
  • docs/specification.md Inline Content describes the rule.

Notes

Implementation direction

Blocked on the escaping precision issue and does not work before it. Against today's serializer a file holding \[a](b) saves as \[a]\(b), so an author deleting the first backslash sees no change at all — the run stays literal because \( still breaks it. The gesture is spelled as one deletion but only completes in pairs, and its first half is silent. Precise escaping reduces it to one backslash and one deletion. Before that fix the projection would also surface escapes that should not exist: garden_sensor_name would project \_ twice.

Two properties are accepted rather than solved, both measured in #245:

  • The escape sits where the syntax needs breaking, not where the author wrote it. Keeping ![alt](x.png) literal cannot be done by escaping the ! — that leaves a literal ! followed by a live link. The escape belongs on the [.
  • Nested runs still pair. [![alt](i.png)](l.md) needs two escapes even minimally, so deleting one yields the image without the link.

Two measured cases place an escape flush against a live projection target and are what adapter precedence has to answer for: \![alt](x.png) yields text:"!" beside a link, and \<https://example.com> yields text:"<" beside one.

The symmetry with typing \ into projected link source is read from docs/specification.md rather than observed; confirm it before building on it.

Out of scope

  • Bare URLs. Typed link source becomes a link #238 records that a bare URL has no literal state, because mdast-util-gfm-autolink-literal decodes escapes after parsing. There is no surviving escape to project, and inline code remains the way to show one as text.
  • Making the distinction visible before the caret arrives. A projection entered by the caret tells an author what an escape is once they suspect one; it does not distinguish two identical-looking runs on sight. src/features/editor/plugins/markerPresentation.ts already decorates ranges without touching document text and is the cheaper answer if visibility is wanted.
  • Storing anything durable about an escape. How a Markdown escape should be represented in the editor #245 rejected both a parse-time mark and a session-scoped record.
  • Preserving authored escape form.

Metadata

Metadata

Assignees

Labels

FeatureNew feature or request

Projects

Status
In Progress

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions