You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
On macOS, ⌘⌫ (Cmd+Backspace) in the CodeMirror 6 note editor must match Zed’s default Editor binding exactly: editor::DeleteToBeginningOfLine (hard / logical line start — not soft-wrap boundary, not full DeleteLine).
Why This Matters
Line-kill chords are high-frequency when editing notes. After the CM6 cutover, ⌘⌫ feels wrong vs Zed. This is an explicit product keymap decision with Zed as the single source of truth — not “macOS TextEdit vaguely” and not CM’s stock soft-wrap-aware default.
User (macOS): wants ⌘⌫ to behave like Zed (where it “works correctly”); earlier wording (“한 줄이 통째로 사라지길”) described the feel of clearing a line from EOL, not Zed’s separate full-line-delete chord.
Do not conflate: JetBrains keymap in Zed maps cmd-backspace → editor::DeleteLine (assets/keymaps/macos/jetbrains.json). That is not the default. Memo follows default-macos, not JetBrains.
Action implementation
DeleteToBeginningOfLine — doc: “Deletes from the cursor to the beginning of the current line.” Field stop_at_indent defaults to false; default keymap binds the action with no args.
select_to_beginning_of_line with stop_at_soft_wraps: false (hardcoded) and stop_at_indent: action.stop_at_indent (default false)
backspace (deletes the resulting selection; if still empty, deletes one unit left — typically the preceding newline)
Line target uses indented_line_beginning / line_beginning: with stop_at_soft_boundaries: false, the target is always the logical / hard line start, never a soft-wrap visual boundary.
Previous “Needs verification / recommended default / alternative bind ⌘⌫ to deleteLine” language is superseded. Product choice is fixed:
⌘⌫ → Zed editor::DeleteToBeginningOfLine
Exact semantic rules:
Hard line only. Ignore soft-wrap visual boundaries. From mid-wrap, delete through to the logical line start (column 0 of that hard line), not the start of the current visual wrap row.
No indent stop. Default binding does not stop at first non-whitespace (stop_at_indent: false). Indentation before the cursor is deleted too.
Cursor mid-line / at EOL. Delete all text from hard BOL → cursor; leave an empty hard line; cursor at BOL. From EOL this clears the whole line’s text (empty line remains) — the “line went away” feel without removing the linebreak.
Cursor already at hard BOL (empty selection). Do not no-op: delete one unit backward (normally the preceding \n), joining with the previous line. At document start, nothing left to delete.
Non-empty selection (Zed-specific). Do not only delete the selected span. Zed reverses the selection, extends the head to hard BOL, then deletes → effectively hard BOL → selection’s right edge. Example from Zed’s test: "one «two three» four" + action → " four".
Multiple cursors. Apply per selection/cursor (Zed tests exercise multi-cursor delete-to-BOL).
Newlines. Only crossed when already at hard BOL (join) or when a multi-line selection’s right edge is past newlines after the BOL expansion. Mid-line ⌘⌫ does not delete into the previous line.
Undo. One transactional undo step for the kill (Zed wraps in transact).
Related chords (do not overload onto ⌘⌫)
Chord
Memo target
Notes
⇧⌘K
CM deleteLine ≈ Zed editor::DeleteLine
Removes entire hard line including linebreak; line literally disappears. Cursor lands on following (or previous) line.
⌥⌫
CM deleteGroupBackward ≈ Zed DeleteToPreviousWordStart
Word/group delete; ignore_newlines: false in Zed default.
⌘⌦
Optional parity: delete to hard EOL
Zed DeleteToEndOfLine also uses stop_at_soft_wraps: false. Nice-to-have, not required to close this issue.
Observable contract (QA)
Mid-line + ⌘⌫ → text BOL..cursor gone; empty remainder of line kept.
EOL + ⌘⌫ → line text cleared; empty hard line remains.
Empty line / caret at BOL + ⌘⌫ → join with previous line (line “removed”).
Soft-wrap on + caret mid visual wrap → still deletes to hard BOL (may clear text across multiple visual rows of one hard line).
Selection "one two three four" with "two three" selected + ⌘⌫ → " four" (BOL→selection end), not"one four".
⇧⌘K still full line delete; ⌥⌫ still word/group; ⌘N/⌘B/⌘\ unaffected.
Hangul IME: while view.composing, do not corrupt composition.
Current Behavior (memo / CM today)
What CodeMirror ships
From @codemirror/commandsstandardKeymap / defaultKeymap:
Chord (macOS)
Command
Effect vs Zed
⌘⌫
deleteLineBoundaryBackward
Soft-wrap–aware boundary via view.moveToLineBoundary. Mismatch with Zed hard-line rule.
—
deleteToLineStart (exported, not bound to ⌘⌫)
Uses lineBlockAt(head).from (hard line for normal text). Closer for empty cursors; see gaps below.
⌥⌫
deleteGroupBackward
OK keep.
⇧⌘K
deleteLine
Matches Zed’s separate full-line delete chord.
CM deleteBy (used by both delete helpers): non-empty selection → delete selection only. That diverges from Zed rule (5) above.
What memo does today
components/codemirror-editor.tsx installs filtered defaultKeymap (Tab overridden). macOS { mac: "Mod-Backspace", run: deleteLineBoundaryBackward } is kept — so memo currently follows CM soft-wrap boundary, not Zed.
CodeMirror mapping (implementation guidance)
Approach
Empty cursor / hard line
Soft wrap
Non-empty selection
Verdict
Stock deleteLineBoundaryBackward
Soft-wrap boundary
Soft
Delete selection only
Reject — not Zed
Stock deleteToLineStart
Hard line start + BOL→join
Hard (via line block)
Delete selection only
Close for caret-only; fails Zed selection expansion
Custom command (required for exact parity)
doc.lineAt(head).from → head; if at from, delete from-1
Hard
Expand each range to line.from .. range.to then delete (mirror Zed reverse+select-to-BOL)
Required for SoT
Recommendation: implement a small custom command (e.g. zedDeleteToBeginningOfLine) + Prec.high macOS binding for Mod-Backspace with preventDefault: true. Keep CM deleteLine on ⇧⌘K. Optionally leave or remove the stock mac-only deleteLineBoundaryBackward binding so it cannot win on precedence.
Summary
On macOS, ⌘⌫ (Cmd+Backspace) in the CodeMirror 6 note editor must match Zed’s default Editor binding exactly:
editor::DeleteToBeginningOfLine(hard / logical line start — not soft-wrap boundary, not fullDeleteLine).Why This Matters
Line-kill chords are high-frequency when editing notes. After the CM6 cutover, ⌘⌫ feels wrong vs Zed. This is an explicit product keymap decision with Zed as the single source of truth — not “macOS TextEdit vaguely” and not CM’s stock soft-wrap-aware default.
Conversation Context
chasehuh/memo; editor: CM6 from CodeMirror 6 inline Markdown image widgets #8.memo-app.tsxonly handle ⌘N / ⌘B / ⌘\ — they do not intercept Backspace.Source of truth: Zed (locked)
Verified against
zed-industries/zed@7cf50a771f54427f76b4584030c7b3b66f4e39f5(mainat research time).Default macOS keymap (Editor context)
cmd-backspaceeditor::DeleteToBeginningOfLineassets/keymaps/default-macos.jsonL74cmd-deleteeditor::DeleteToEndOfLinealt-backspaceeditor::DeleteToPreviousWordStart(ignore_newlines: false)cmd-shift-keditor::DeleteLine(full hard-line remove — different chord)Action implementation
DeleteToBeginningOfLine— doc: “Deletes from the cursor to the beginning of the current line.” Fieldstop_at_indentdefaults tofalse; default keymap binds the action with no args.Implementation
delete_to_beginning_of_line:reversed = trueselect_to_beginning_of_linewithstop_at_soft_wraps: false(hardcoded) andstop_at_indent: action.stop_at_indent(default false)backspace(deletes the resulting selection; if still empty, deletes one unit left — typically the preceding newline)Line target uses
indented_line_beginning/line_beginning: withstop_at_soft_boundaries: false, the target is always the logical / hard line start, never a soft-wrap visual boundary.Covering tests:
test_beginning_end_of_line,test_delete_to_line_boundary(selection cases), soft-wrap ignore behavior for the same movement flags intest_beginning_end_of_line_ignore_soft_wrap.Desired Behavior (Zed-locked — supersedes earlier waffle)
Previous “Needs verification / recommended default / alternative bind ⌘⌫ to deleteLine” language is superseded. Product choice is fixed:
⌘⌫ → Zed
editor::DeleteToBeginningOfLineExact semantic rules:
stop_at_indent: false). Indentation before the cursor is deleted too.\n), joining with the previous line. At document start, nothing left to delete."one «two three» four"+ action →" four".transact).Related chords (do not overload onto ⌘⌫)
deleteLine≈ Zededitor::DeleteLinedeleteGroupBackward≈ ZedDeleteToPreviousWordStartignore_newlines: falsein Zed default.DeleteToEndOfLinealso usesstop_at_soft_wraps: false. Nice-to-have, not required to close this issue.Observable contract (QA)
"one two three four"with"two three"selected + ⌘⌫ →" four"(BOL→selection end), not"one four".view.composing, do not corrupt composition.Current Behavior (memo / CM today)
What CodeMirror ships
From
@codemirror/commandsstandardKeymap/defaultKeymap:deleteLineBoundaryBackwardview.moveToLineBoundary. Mismatch with Zed hard-line rule.deleteToLineStart(exported, not bound to ⌘⌫)lineBlockAt(head).from(hard line for normal text). Closer for empty cursors; see gaps below.deleteGroupBackwarddeleteLineCM
deleteBy(used by both delete helpers): non-empty selection → delete selection only. That diverges from Zed rule (5) above.What memo does today
components/codemirror-editor.tsxinstalls filtereddefaultKeymap(Tab overridden). macOS{ mac: "Mod-Backspace", run: deleteLineBoundaryBackward }is kept — so memo currently follows CM soft-wrap boundary, not Zed.CodeMirror mapping (implementation guidance)
deleteLineBoundaryBackwarddeleteToLineStartdoc.lineAt(head).from→ head; if at from, deletefrom-1line.from .. range.tothen delete (mirror Zed reverse+select-to-BOL)Recommendation: implement a small custom command (e.g.
zedDeleteToBeginningOfLine) +Prec.highmacOS binding forMod-BackspacewithpreventDefault: true. Keep CMdeleteLineon ⇧⌘K. Optionally leave or remove the stock mac-onlydeleteLineBoundaryBackwardbinding so it cannot win on precedence.Suggested module (optional):
Implementation Notes
Likely files
components/codemirror-editor.tsx—Prec.high(keymap.of([…]))for macOS line-kill.lib/editor/line-kill.ts(new) — custom Zed-parity command.Flow
Tests
Edge Cases And Risks
deleteLine(that is ⇧⌘K / JetBrains-keymap territory).Non-Goals
editor::DeleteLine.Acceptance Criteria
DeleteToBeginningOfLinerules (1)–(8) above, including hard-line + selection expands to BOL.input.rsimplementation (or this issue’s SoT section).deleteLine.QA Plan
main;pnpm dev.one two three fourwithtwo threeselected → expectfour.Suggested PR Scope
S — “fix macOS ⌘⌫ to match Zed DeleteToBeginningOfLine”. Link #9 for wrap QA.