Skip to content

feat: bear-style text editor parity#35

Merged
luctst merged 9 commits into
mainfrom
feat/bear-editor-parity
Jun 9, 2026
Merged

feat: bear-style text editor parity#35
luctst merged 9 commits into
mainfrom
feat/bear-editor-parity

Conversation

@luctst

@luctst luctst commented Jun 9, 2026

Copy link
Copy Markdown
Owner

Summary

Enrich the Marcdown text editor to feel as close to Bear's editor as possible — the goal being a daily-driver markdown editor good enough to replace Raycast Notes.

Built via a 4-agent workflow: PM functional spec → Thomas design review → oonolive-swift tests-first → guy implementation.

What lands

Styling helpers (each as its own commit):

  • Depth-aware MarcdownListMarkerKind (bullets cycle filled/hollow circle → filled/hollow diamond by depth; ordered carries its depth)
  • ListIndentation — Tab / Shift+Tab indent/outdent on list lines (2-space step)
  • OrderedListRenumber — renumbers contiguous ordered run at the anchor's depth, skipping deeper nested children
  • BlockquoteContinuation — Enter continues > ; Enter on empty > exits (strips one level for nested)
  • HeadingContinuation — Backspace on empty # strips the marker atomically
  • FocusLine + MarkdownStyler.restyle(storage:source:focusLine:) — concealed syntax (**, link ](url), list markers, etc.) reveals on the line the cursor is on, re-conceals on leave
  • ListContinuation refinements — empty-marker exit emits blank-line separator after content; backspace at marker-start triggers atomic join

Editor wiring (NoteEditorView.Coordinator):

  • Routes insertTab:, insertBacktab:, insertNewlineIgnoringFieldEditor:, moveLeft:, moveRight: to the new helpers
  • Arrow keys jump over concealed runs (link URLs, bold delimiters, etc.) in a single keystroke
  • Runs OrderedListRenumber after every list-affecting edit
  • Recomputes FocusLine on selection change and feeds it to restyle
  • CheckboxIconLayoutManager draws depth-aware bullet glyphs and uses body color for both bullets and ordered numbers

Test plan

Automated (all green locally):

  • swift test --package-path Packages/MarcdownStyling — 293/293 passing
  • swift test --package-path Packages/MarcdownEditor — 31/31 passing
  • swift test --package-path Packages/MarcdownCore — 27/27 passing
  • xcodebuild -scheme Marcdown -configuration Debug build — SUCCEEDED

Manual (please verify in the running app):

  • Cursor entering a line with **bold** / [label](url) / list markers reveals the syntax, leaves re-conceal it
  • Tab/Shift+Tab on bullet / ordered / task lines indents/outdents
  • Enter on > hello continues the blockquote; Enter on empty > exits
  • Backspace on empty # strips the marker
  • Backspace at start of - bar (after - foo) joins lines and strips the marker
  • Empty-bullet Enter after content inserts a blank-line separator
  • Left/Right arrow jumps concealed runs in one keystroke
  • Nested bullets render with the depth-aware glyph cycle (●, ○, ◆, ◇)
  • Ordered numbers render in body color, not accent
  • IME composition still works on every new path

Deferred (out of scope for this PR)

  • Multi-line selection Tab/Shift+Tab (caret-only handled today)
  • Cmd+B / Cmd+I formatting shortcuts (separate workstream)
  • Focus-reveal animation / debounce — currently instant
  • Move-line up/down (Cmd+Opt+Up/Down)
  • Drag-to-reorder list items
  • Checkbox toggle bounce / strikethrough wipe animations

Known cost

OrderedListRenumber.renumberRun returns a full-buffer rewrite that the coordinator applies as a single replaceCharacters — each renumber is one fat undo step. Worth optimizing later to (range, replacement) for just the changed sub-run.

@luctst luctst merged commit 86152d1 into main Jun 9, 2026
4 checks passed
@luctst luctst deleted the feat/bear-editor-parity branch June 9, 2026 09:11
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