krz/orgstar

A native macOS editor for org-mode files. editor org-mode swift

Sources/OrgEditorAppKit/EditorCommands.swift

85c633a83a4744bef9dde8b52462f9c2a1c037e4
orgstar/Sources/OrgEditorAppKit/EditorCommands.swift history · blame · raw

85 lines · 4145 bytes

 1#if os(macOS)
 2import OrgCore
 3
 4/// Every command a key, menu or the palette can run, by id.
 5public struct EditorCommand: Sendable {
 6    public enum Action: Sendable {
 7        /// An `OrgCore` command, run through `OrgEditor.perform`.
 8        case text(any OrgCommand)
 9        /// Folding and other view changes the editor makes itself.
10        case view
11        /// A text-system action; `extending` is its variant that extends the selection, used
12        /// while a mark is active.
13        case edit(selector: String, extending: String? = nil)
14        /// Mark handling in the editor.
15        case mark
16        /// Handled by the app (save, quick open, palette).
17        case app
18    }
19
20    public let id: String
21    public let title: String
22    public let action: Action
23
24    /// Shown in the palette; text-system movement and editing are left to keys.
25    public var inPalette: Bool {
26        switch action {
27        case .edit, .mark: false
28        default: true
29        }
30    }
31}
32
33public enum EditorCommands {
34    public static let all: [EditorCommand] = Commands.all.map { EditorCommand(id: $0.id, title: $0.title, action: .text($0)) } + [
35        EditorCommand(id: "org.cycle", title: "Cycle Visibility", action: .view),
36        EditorCommand(id: "org.cycle-global", title: "Cycle Global Visibility", action: .view),
37
38        EditorCommand(id: "app.save", title: "Save", action: .app),
39        EditorCommand(id: "app.quick-open", title: "Quick Open…", action: .app),
40        EditorCommand(id: "app.palette", title: "Command Palette…", action: .app),
41        EditorCommand(id: "app.search", title: "Search Notes", action: .app),
42        EditorCommand(id: "app.reload-keymap", title: "Reload Keymap", action: .app),
43
44        movement("forward-char", "Forward Character", "moveForward:"),
45        movement("backward-char", "Backward Character", "moveBackward:"),
46        movement("next-line", "Next Line", "moveDown:"),
47        movement("previous-line", "Previous Line", "moveUp:"),
48        movement("beginning-of-line", "Beginning of Line", "moveToBeginningOfParagraph:"),
49        movement("end-of-line", "End of Line", "moveToEndOfParagraph:"),
50        movement("forward-word", "Forward Word", "moveWordForward:"),
51        movement("backward-word", "Backward Word", "moveWordBackward:"),
52        movement("beginning-of-buffer", "Beginning of Buffer", "moveToBeginningOfDocument:"),
53        movement("end-of-buffer", "End of Buffer", "moveToEndOfDocument:"),
54        movement("scroll-up", "Scroll Up", "pageDown:"),
55        movement("scroll-down", "Scroll Down", "pageUp:"),
56        edit("recenter", "Recenter", "centerSelectionInVisibleArea:"),
57        edit("delete-char", "Delete Character", "deleteForward:"),
58        edit("kill-word", "Kill Word", "deleteWordForward:"),
59        edit("backward-kill-word", "Kill Word Backward", "deleteWordBackward:"),
60        edit("kill-line", "Kill Line", "deleteToEndOfParagraph:"),
61        edit("yank", "Yank", "yank:"),
62        edit("select-all", "Select All", "selectAll:"),
63        edit("kill-region", "Kill Region", "cut:"),
64        edit("copy-region", "Copy Region", "copy:"),
65        edit("undo", "Undo", "undo:"),
66        edit("transpose-chars", "Transpose Characters", "transpose:"),
67        edit("find", "Find", "performTextFinderAction:"),
68        EditorCommand(id: "edit.set-mark", title: "Set Mark", action: .mark),
69        EditorCommand(id: "edit.keyboard-quit", title: "Quit", action: .mark),
70    ]
71
72    private static func movement(_ name: String, _ title: String, _ selector: String) -> EditorCommand {
73        let extending = String(selector.dropLast()) + "AndModifySelection:"
74        return EditorCommand(id: "edit.\(name)", title: title, action: .edit(selector: selector, extending: extending))
75    }
76
77    private static func edit(_ name: String, _ title: String, _ selector: String) -> EditorCommand {
78        EditorCommand(id: "edit.\(name)", title: title, action: .edit(selector: selector))
79    }
80
81    private static let byID = Dictionary(uniqueKeysWithValues: all.map { ($0.id, $0) })
82
83    public static func command(_ id: String) -> EditorCommand? { byID[id] }
84}
85#endif