fix: complete task tokens on trailing whitespace

This commit is contained in:
Valdemar Lorenzen
2026-10-19 12:32:23 +02:00
parent 7c26a88c6c
commit f275695d2f
4 changed files with 75 additions and 4 deletions
@@ -589,3 +589,70 @@ func atomicTasksCopySelectAndPersistMarkdownAlongsideUnicodeAndImages() throws {
#expect(reopenedEditor.string == rendered)
#expect(reopenedEditor.markdownContents.string == source.string)
}
@Test @MainActor
func taskTokensRequireTrailingWhitespaceAndAcceptEmptyBracketsWhileTyping() throws {
_ = NSApplication.shared
let suite = "TaskSyntax.\(UUID().uuidString)"
let defaults = try #require(UserDefaults(suiteName: suite))
let directory = FileManager.default.temporaryDirectory.appendingPathComponent(suite)
defer {
defaults.removePersistentDomain(forName: suite)
try? FileManager.default.removeItem(at: directory)
}
let controller = NotesController(defaults: defaults, directory: directory)
let window = NSWindow(contentRect: NSRect(x: 0, y: 0, width: 750, height: 390),
styleMask: .borderless, backing: .buffered, defer: false)
window.contentViewController = controller
defer { _ = controller.close(); window.orderOut(nil) }
func descendants(_ view: NSView) -> [NSView] { [view] + view.subviews.flatMap(descendants) }
let editor = try #require(descendants(controller.view).compactMap { $0 as? NotesTextView }.first)
window.makeFirstResponder(editor)
for marker in ["- [ ]", "- []", "- [x]", "- [X]", "\t+ []", "12) []"] {
editor.setMarkdownContents(NSAttributedString(string: ""))
editor.setSelectedRange(NSRange(location: 0, length: 0))
var typed = ""
for character in marker {
typed.append(character)
editor.insertText(String(character), replacementRange: editor.selectedRange())
#expect(editor.string == typed)
}
editor.insertText(" ", replacementRange: editor.selectedRange())
let indentation = String(marker.prefix { $0 == " " || $0 == "\t" })
#expect(editor.string == indentation + "\u{fffc} ")
let checkbox = try #require(editor.subviews.compactMap { $0 as? NSButton }.first)
#expect(checkbox.state == (marker.hasSuffix("[x]") || marker.hasSuffix("[X]") ? .on : .off))
editor.insertText("🦊", replacementRange: editor.selectedRange())
#expect(editor.string == indentation + "\u{fffc} 🦊")
#expect(editor.markdownString == marker + " 🦊")
}
editor.setMarkdownContents(NSAttributedString(string: "- []\n"))
#expect(editor.string == "- []\n")
editor.setMarkdownContents(NSAttributedString(string: "- []\ttask"))
#expect(editor.string == "\u{fffc}\ttask")
editor.breakUndoCoalescing()
editor.undoManager?.removeAllActions()
let box = try #require(editor.subviews.compactMap { $0 as? NSButton }.first)
box.performClick(nil)
#expect(editor.markdownString == "- [x]\ttask")
#expect(box.state == .on)
editor.undoManager?.undo()
#expect(editor.markdownString == "- []\ttask")
#expect(box.state == .off)
editor.undoManager?.redo()
#expect(editor.markdownString == "- [x]\ttask")
box.performClick(nil)
#expect(editor.markdownString == "- [ ]\ttask")
let enter = try #require(NSEvent.keyEvent(with: .keyDown, location: .zero, modifierFlags: [],
timestamp: 1, windowNumber: window.windowNumber, context: nil, characters: "\r",
charactersIgnoringModifiers: "\r", isARepeat: false, keyCode: 36))
editor.insertText("- [] task", replacementRange: NSRange(location: 0, length: editor.string.utf16.count))
editor.keyDown(with: enter)
#expect(editor.markdownString == "- [] task\n- [ ] ")
#expect(editor.string == "\u{fffc} task\n\u{fffc} ")
editor.keyDown(with: enter)
#expect(editor.markdownString == "- [] task\n")
editor.insertText("- [] ", replacementRange: NSRange(location: 0, length: editor.string.utf16.count))
editor.keyDown(with: enter)
#expect(editor.markdownString.isEmpty)
}