feat: display a block cursor in Vim Normal mode

This commit is contained in:
2026-10-22 12:28:27 +02:00
parent 923425826d
commit 5803a00944
3 changed files with 68 additions and 2 deletions
+29 -2
View File
@@ -61,10 +61,14 @@ final class NotesTextView: NSTextView, @MainActor NSLayoutManagerDelegate {
private var tasks: [(range: NSRange, attachment: ListAttachment)] = []
private var checkboxes: [NSButton] = []
private var horizontalSelection: (anchor: Int, head: Int)?
var vimState = NotesVimState()
var vimState = NotesVimState() {
didSet {
if oldValue.mode != vimState.mode { needsDisplay = true }
}
}
var vimModeChanged: (() -> Void)?
var vimEnabled = false {
didSet { resetVim() }
didSet { resetVim(); needsDisplay = true }
}
var markdownContents: NSAttributedString { Self.serialize(attributedString()) }
@@ -77,6 +81,29 @@ final class NotesTextView: NSTextView, @MainActor NSLayoutManagerDelegate {
refreshTasks()
}
private var normalCursorWidth: CGFloat {
let position = selectedRange().location
let cursorFont = position < (textStorage?.length ?? 0)
? textStorage?.attribute(.font, at: position, effectiveRange: nil) as? NSFont : font
return max(2, ceil((cursorFont ?? NotesAppearance.font).maximumAdvancement.width))
}
override func drawInsertionPoint(in rect: NSRect, color: NSColor, turnedOn flag: Bool) {
guard vimEnabled, vimMode == .normal else {
super.drawInsertionPoint(in: rect, color: color, turnedOn: flag)
return
}
var block = rect
block.size.width = normalCursorWidth
super.drawInsertionPoint(in: block, color: color.withAlphaComponent(0.45), turnedOn: flag)
}
override func setNeedsDisplay(_ invalidRect: NSRect) {
var rect = invalidRect
if vimEnabled, vimMode == .normal { rect.size.width += normalCursorWidth }
super.setNeedsDisplay(rect)
}
private static func serialize(_ contents: NSAttributedString, keepingMetadata: Bool = false) -> NSAttributedString {
let result = NSMutableAttributedString(attributedString: contents)
restoreListLayout(in: result)