Skip to content

feat(editor): add native context menus and text services - #13

Merged
ahonn merged 6 commits into
masterfrom
feat/editor-context-menu
Oct 5, 2026
Merged

ahonn merged 6 commits into
masterfrom
feat/editor-context-menu

Conversation

@ahonn

@ahonn ahonn commented Oct 3, 2026

Copy link
Copy Markdown
Owner

Add native macOS context menus for editing Markdown and using system text services. Right-click actions now follow the clicked text or object and preserve the existing selection when appropriate.

The branch contains two commits:

  • perf(a11y): reuse text readings and group distant lines caches accessible readings and groups distant rows while preserving selection mappings and geometry.
  • feat(editor): add native context menus and text services adds the editor actions, native integrations, replacement guards, and regression coverage.

Changes

  • Add paragraph and inline formatting, clipboard formats, block insertion, and actions for links, tables, code blocks, and images.
  • Integrate spelling and grammar, smart substitutions, data detection, translation, lookup, speech, sharing, Services, and Writing Tools.
  • Persist text-checking preferences and localize application menu captions.
  • Preserve Markdown syntax and existing formatting when native tools replace readable text. Proofread preserves mixed bold and italic ranges.
  • Reject stale results after document or selection changes. Reject writes to read-only content and unsupported structural selections.
  • Preserve undo behavior for replacements and imported images. Keep the caret in the expected position after substitutions.

Validation

The final Git tree is identical to the tree tested before the commit cleanup. No code changed during that cleanup.

  • cargo test --workspace --locked: 1,977 passed, 0 failed, 4 ignored.
  • The ignored Sparkle release-notes test passed when run separately.
  • cargo fmt --all -- --check: passed.
  • cargo clippy --workspace --all-targets --locked -- -D warnings: passed.
  • Application build and bundle creation: passed.

The latest device review used Apple Silicon and macOS 27.0 (26A428). It recorded 21 passing entries, two protected-write cases with a UI issue, and one unverified IME case. Entries include combined actions and are not independent test-case counts.

Device checks covered TextEdit clipboard interoperability, translation replacement and undo, mixed-format Proofread, stale sessions, read-only protection, checking preferences, and restart persistence. They also covered Unicode selections across 20 paragraphs in a 300-paragraph document, table edits, code background menus, and the image picker. Earlier device checks covered the remaining formatting and object actions.

Known issue and coverage limits

The system Proofread popover still enables Replace for read-only documents and unsupported structural selections. The application rejects the write and preserves the source, but the UI does not explain the rejection. This is a non-blocking usability issue.

IME composition, VoiceOver speech, older supported macOS versions, and Intel hardware still need device verification. Not all Writing Tools modes or third-party Services were exercised. External sharing, calendar creation, and browser navigation were not executed. The image-copy race was not reproduced on the device, and the long-document checks are not performance benchmarks.

ahonn added 2 commits October 4, 2026 20:36
Cache accessible readings, group distant lines, and keep row geometry stable during scrolling.
Preserve document selection mappings and cover cache reuse and grouped text with tests.
Add native menus for text, links, tables, code blocks, and Markdown insertion. Integrate spelling,
substitutions, translation, Writing Tools, and system services with persisted preferences. Guard
asynchronous results against document and selection changes, and reject writes to read-only content.
Preserve Markdown structure and formatting during native replacements, with undo support and
regression coverage.

Spelling scans return ranges only; guesses are fetched for the one word a menu asks about. An
edit moves the diagnostics beside it and removes those it touches. Typing links only text that
spells its own scheme. Smart deletion and smart copy apply to a selection made by a word gesture.

A word picked across concealed spelling is a ReadingSelection in the core's kind layer; the
selection layer depends on neither commands nor projection. Selection kinds map through
map_with_schema, and a replacement states its ReplacementStyle. Vim Normal mode keeps such a
selection, and an opener typed over it wraps it.
@ahonn
ahonn force-pushed the feat/editor-context-menu branch from d1c74c9 to 56a468f Compare October 4, 2026 09:36
ahonn added 4 commits October 5, 2026 01:05
A command that leaves the editor in front no longer closes the spelling or substitutions
panel; the panel is cancelled only when another panel takes the editor's place. Replacing
the document also ends a word-gesture selection, so a later selection at the same range is
not treated as one.
Use selection geometry for native text popovers after the selection is painted. Retire text-service
responders before closing checking panels. Keep tall-table controls inside the viewport. Add
regression tests and document the native presentation lifecycle.
Use the painted baseline and font runs for AppKit lookup. Preserve CJK fallback styles and UTF-16
ranges.
@ahonn
ahonn merged commit 71a0917 into master Oct 5, 2026
1 check passed
@ahonn
ahonn deleted the feat/editor-context-menu branch October 5, 2026 01:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant