fix: align Vim indicator and restore Normal Escape dismissal
This commit is contained in:
@@ -196,7 +196,7 @@ Notes autosave locally as RTFD packages, including embedded images, under `~/Lib
|
||||
|
||||
### Vim editing
|
||||
|
||||
Click **Vim Off** at the left of the Notes header to enable modal editing. The button shows **NORMAL**, **INSERT**, **VISUAL**, or **VISUAL LINE**; click it again to disable Vim. This preference persists across reopening and app restarts. Opening or switching notes starts in Normal mode when enabled; ordinary editing is unchanged when disabled.
|
||||
Click **Vim Off** at the top-right of the Notes header to enable modal editing. The button shows **NORMAL**, **INSERT**, **VISUAL**, or **VISUAL LINE**; click it again to disable Vim. This preference persists across reopening and app restarts. Opening or switching notes starts in Normal mode when enabled; ordinary editing is unchanged when disabled.
|
||||
|
||||
| Operation | Keys |
|
||||
| --- | --- |
|
||||
@@ -212,11 +212,11 @@ Click **Vim Off** at the left of the Notes header to enable modal editing. The b
|
||||
| Delete characters; delete / change through line end | `x`; `D` / `C` |
|
||||
| Paste after / before | `p` / `P` |
|
||||
| Native Undo / Redo | `u` / Control-R; Command-Z / Command-Shift-Z remain available |
|
||||
| Return to Normal / cancel a pending command | Escape or Control-[ |
|
||||
| Return to Normal (from Insert/Visual) | Escape or Control-[ |
|
||||
|
||||
Counts work before motions and operators, including `3j`, `2dd`, and `2d3w`. Vertical movement uses logical lines rather than wrapped display rows and retains the desired column across shorter lines. Character motions and selections respect composed Unicode characters and skip hidden Markdown syntax. Whole-token operators carry recognized inline formatting delimiters with their visible text; linewise operations include heading and list prefixes. Yank/delete/change use a local unnamed register, preserving attributed text and embedded images for `p`/`P` without replacing the system clipboard. Editing and Undo still use the native text view and RTFD autosaves.
|
||||
|
||||
Escape closes an open picker first; otherwise, with Vim enabled, it returns to Normal without dismissing Notes. Command-W still dismisses the window. Command shortcuts, formatting controls, and native Insert-mode input remain available. Pending commands cancel on focus changes and Command shortcuts. This is a supported Vim subset, not an embedded Vim: search, text objects, named registers, macros, and dot-repeat are not implemented.
|
||||
Escape closes an open picker first. With Vim enabled, Escape returns Insert or Visual mode to Normal; in Normal mode it dismisses Notes, just as when Vim is disabled. Command-W still dismisses the window. Command shortcuts, formatting controls, and native Insert-mode input remain available. Pending commands cancel on focus changes and Command shortcuts. This is a supported Vim subset, not an embedded Vim: search, text objects, named registers, macros, and dot-repeat are not implemented.
|
||||
|
||||
|
||||
## Translation
|
||||
|
||||
@@ -71,7 +71,7 @@ final class NotesController: NSViewController, NSTextViewDelegate {
|
||||
vimButton.font = .monospacedSystemFont(ofSize: 10, weight: .medium)
|
||||
vimButton.contentTintColor = SunsetPalette.secondaryText
|
||||
vimButton.setAccessibilityLabel("Toggle Vim editing")
|
||||
vimButton.toolTip = "Toggle Vim editing. Escape: Normal mode; i: Insert; v: Visual; Command-W: close."
|
||||
vimButton.toolTip = "Toggle Vim editing. Escape: Normal mode, then close; i: Insert; v: Visual."
|
||||
editor.vimModeChanged = { [weak self] in self?.updateVimIndicator() }
|
||||
editor.vimEnabled = defaults.bool(forKey: "notesVimEnabled")
|
||||
for control in [noteTitle, vimButton] {
|
||||
@@ -81,10 +81,10 @@ final class NotesController: NSViewController, NSTextViewDelegate {
|
||||
}
|
||||
NSLayoutConstraint.activate([
|
||||
noteTitle.centerXAnchor.constraint(equalTo: header.centerXAnchor),
|
||||
vimButton.leadingAnchor.constraint(equalTo: header.leadingAnchor, constant: 12),
|
||||
vimButton.trailingAnchor.constraint(equalTo: header.trailingAnchor, constant: -12),
|
||||
vimButton.widthAnchor.constraint(equalToConstant: 90),
|
||||
noteTitle.leadingAnchor.constraint(greaterThanOrEqualTo: vimButton.trailingAnchor, constant: 8),
|
||||
noteTitle.trailingAnchor.constraint(lessThanOrEqualTo: header.trailingAnchor, constant: -44),
|
||||
noteTitle.leadingAnchor.constraint(greaterThanOrEqualTo: header.leadingAnchor, constant: 44),
|
||||
noteTitle.trailingAnchor.constraint(lessThanOrEqualTo: vimButton.leadingAnchor, constant: -8),
|
||||
])
|
||||
actions.closed = { [weak self] in self?.focusEditor() }
|
||||
actions.selectNote = { [weak self] in self?.switchNote($0) }
|
||||
|
||||
@@ -124,7 +124,7 @@ extension NotesTextView {
|
||||
|
||||
@discardableResult
|
||||
func handleVimEscape() -> Bool {
|
||||
guard vimEnabled, !hasMarkedText() else { return false }
|
||||
guard vimEnabled, vimState.mode != .normal, !hasMarkedText() else { return false }
|
||||
let buffer = VimBuffer(attributedString())
|
||||
var head = vimState.head ?? buffer.index(selectedRange().location)
|
||||
if vimState.mode == .insert && head > buffer.lineStart(head) { head -= 1 }
|
||||
|
||||
@@ -208,7 +208,8 @@ func vimPreferenceEscapePickersAndNativeShortcutsCoexist() throws {
|
||||
try vimKeys("w", editor: editor)
|
||||
#expect(editor.markdownString == beforeMotion)
|
||||
try vimKeys("d", editor: editor)
|
||||
launcher.dismiss(restoringFocus: false)
|
||||
window.sendEvent(escape)
|
||||
#expect(!window.isVisible)
|
||||
launcher.present(command: .notes)
|
||||
let reopenedContent = try #require(window.contentView)
|
||||
let reopened = try #require(descendants(reopenedContent).compactMap { $0 as? NotesTextView }.first)
|
||||
|
||||
Reference in New Issue
Block a user