krz/orgstar

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

Sources/OrgEditorAppKit/EditorCommands.swift

3a3dedba062790e1580c66d38606eda4b02cb501
orgstar/Sources/OrgEditorAppKit/EditorCommands.swift history · blame · raw

158 lines · 10649 bytes

  1#if os(macOS)
  2import AppKit
  3import OrgCore
  4
  5/// Every command a key, menu or the palette can run, by id.
  6public struct EditorCommand: Sendable {
  7    public enum Action: Sendable {
  8        /// An `OrgCore` command, run through `OrgEditor.perform`.
  9        case text(any OrgCommand)
 10        /// Folding and other view changes the editor makes itself.
 11        case view
 12        /// A text-system action; `extending` is its variant that extends the selection, used
 13        /// while a mark is active.
 14        case edit(selector: String, extending: String? = nil)
 15        /// Mark handling in the editor.
 16        case mark
 17        /// The find bar.
 18        case find(NSTextFinder.Action)
 19        /// Handled by the app (save, quick open, palette).
 20        case app
 21    }
 22
 23    public let id: String
 24    public let title: String
 25    public let action: Action
 26
 27    /// Shown in the palette; text-system movement and editing are left to keys.
 28    public var inPalette: Bool {
 29        switch action {
 30        case .edit, .mark: false
 31        default: true
 32        }
 33    }
 34}
 35
 36public enum EditorCommands {
 37    public static let all: [EditorCommand] = Commands.everything.map { EditorCommand(id: $0.id, title: $0.title, action: .text($0)) } + [
 38        EditorCommand(id: "org.cycle", title: "Cycle Visibility", action: .view),
 39        EditorCommand(id: "org.cycle-global", title: "Cycle Global Visibility", action: .view),
 40        EditorCommand(id: "org.fold.toggle", title: "Toggle Fold", action: .view),
 41        EditorCommand(id: "org.fold.open", title: "Open Fold", action: .view),
 42        EditorCommand(id: "org.fold.close", title: "Close Fold", action: .view),
 43        EditorCommand(id: "org.narrow.subtree", title: "Narrow to Subtree", action: .view),
 44        EditorCommand(id: "org.narrow.block", title: "Narrow to Block", action: .view),
 45        EditorCommand(id: "org.widen", title: "Widen", action: .view),
 46        EditorCommand(id: "org.narrow.toggle", title: "Narrow to Subtree or Widen", action: .view),
 47        EditorCommand(id: "org.toggle-inline-images", title: "Show or Hide Inline Images", action: .view),
 48        EditorCommand(id: "editor.complete", title: "Complete at Point", action: .view),
 49        EditorCommand(id: "editor.toggle-spell-check", title: "Check Spelling While Typing", action: .view),
 50        EditorCommand(id: "editor.toggle-truncate-lines", title: "Truncate or Wrap Long Lines", action: .view),
 51        EditorCommand(id: "org.table.toggle-column-width", title: "Shrink or Expand Table Column", action: .view),
 52        EditorCommand(id: "org.table.shrink", title: "Shrink Table Columns with Widths", action: .view),
 53        EditorCommand(id: "org.table.expand", title: "Expand Table Columns", action: .view),
 54        EditorCommand(id: "org.link.insert", title: "Insert Link…", action: .app),
 55        EditorCommand(id: "org.link.store", title: "Store Link", action: .app),
 56        EditorCommand(id: "org.id.store-link", title: "Store ID Link", action: .app),
 57        EditorCommand(id: "org.subtree.paste", title: "Paste Subtree", action: .app),
 58        EditorCommand(id: "app.block.save", title: "Save Block", action: .app),
 59        EditorCommand(id: "app.block.cancel", title: "Leave Block", action: .app),
 60
 61        EditorCommand(id: "app.save", title: "Save", action: .app),
 62        EditorCommand(id: "app.quit", title: "Quit Orgstar", action: .app),
 63        EditorCommand(id: "app.save-all", title: "Save All Buffers", action: .app),
 64        EditorCommand(id: "app.buffer.switch", title: "Switch to Buffer…", action: .app),
 65        EditorCommand(id: "app.buffer.kill", title: "Close Buffer", action: .app),
 66        EditorCommand(id: "app.buffer.kill-others", title: "Close Other Buffers", action: .app),
 67        EditorCommand(id: "app.buffer.kill-all", title: "Close All Buffers", action: .app),
 68        EditorCommand(id: "app.buffer.next", title: "Next Buffer", action: .app),
 69        EditorCommand(id: "app.buffer.previous", title: "Previous Buffer", action: .app),
 70        EditorCommand(id: "app.buffer.last", title: "Last Buffer", action: .app),
 71        EditorCommand(id: "app.babel.cancel", title: "Cancel Running Task", action: .app),
 72        EditorCommand(id: "app.toggle-tab-bar", title: "Show or Hide Tab Bar", action: .app),
 73        EditorCommand(id: "app.toggle-outline", title: "Show or Hide Outline", action: .app),
 74        EditorCommand(id: "app.toggle-backlinks", title: "Show or Hide Backlinks", action: .app),
 75        EditorCommand(id: "app.toggle-inspector", title: "Show or Hide Columns and Clock", action: .app),
 76        EditorCommand(id: "app.toggle-markup", title: "Show or Hide Markup", action: .app),
 77        EditorCommand(id: "app.edit-config", title: "Edit Config File", action: .app),
 78        EditorCommand(id: "app.import-emacs", title: "Import from Emacs…", action: .app),
 79        EditorCommand(id: "app.toggle-line-numbers", title: "Show or Hide Line Numbers", action: .app),
 80        EditorCommand(id: "app.quick-open", title: "Quick Open…", action: .app),
 81        EditorCommand(id: "app.palette", title: "Command Palette…", action: .app),
 82        EditorCommand(id: "app.search", title: "Search Notes", action: .app),
 83        EditorCommand(id: "app.reload-keymap", title: "Reload Keymap", action: .app),
 84        EditorCommand(id: "app.refile", title: "Refile…", action: .app),
 85        EditorCommand(id: "app.archive", title: "Archive Subtree", action: .app),
 86        EditorCommand(id: "app.agenda", title: "Agenda", action: .app),
 87        EditorCommand(id: "app.capture", title: "Capture…", action: .app),
 88        EditorCommand(id: "app.board", title: "Board", action: .app),
 89        EditorCommand(id: "app.clock.in", title: "Clock In", action: .app),
 90        EditorCommand(id: "app.clock.in-recent", title: "Clock In to Recent Entry…", action: .app),
 91        EditorCommand(id: "app.clock.in-last", title: "Clock In to Last Entry", action: .app),
 92        EditorCommand(id: "app.clock.out", title: "Clock Out", action: .app),
 93        EditorCommand(id: "app.clock.cancel", title: "Cancel Clock", action: .app),
 94        EditorCommand(id: "app.clock.goto", title: "Go to Clocked Entry", action: .app),
 95        EditorCommand(id: "app.clock.goto-recent", title: "Go to Recent Clocked Entry…", action: .app),
 96        EditorCommand(id: "app.clock.default", title: "Mark as Default Clock Task", action: .app),
 97        EditorCommand(id: "app.clock.resolve", title: "Resolve Open Clocks…", action: .app),
 98        EditorCommand(id: "app.clock.report", title: "Clock Report", action: .app),
 99        EditorCommand(id: "app.table-import", title: "Import Table from File…", action: .app),
100        EditorCommand(id: "app.table-export", title: "Export Table to File…", action: .app),
101        EditorCommand(id: "app.export-dialog", title: "Export…", action: .app),
102        EditorCommand(id: "app.sync-conflicts", title: "Resolve Sync Conflicts…", action: .app),
103        EditorCommand(id: "app.revert", title: "Revert to File on Disk", action: .app),
104        EditorCommand(id: "app.recovery", title: "Recovery Versions…", action: .app),
105        EditorCommand(id: "app.export.html", title: "Export to HTML", action: .app),
106        EditorCommand(id: "app.export.html-open", title: "Export to HTML and Open", action: .app),
107        EditorCommand(id: "app.export.markdown", title: "Export to Markdown", action: .app),
108        EditorCommand(id: "app.export.pdf", title: "Export to PDF with Emacs", action: .app),
109        EditorCommand(id: "app.export.odt", title: "Export to ODT with Emacs", action: .app),
110        EditorCommand(id: "app.export.latex", title: "Export to LaTeX with Emacs", action: .app),
111        EditorCommand(id: "app.export.text", title: "Export to Plain Text with Emacs", action: .app),
112
113        movement("forward-char", "Forward Character", "moveForward:"),
114        movement("backward-char", "Backward Character", "moveBackward:"),
115        movement("next-line", "Next Line", "moveDown:"),
116        movement("previous-line", "Previous Line", "moveUp:"),
117        movement("beginning-of-line", "Beginning of Line", "moveToBeginningOfParagraph:"),
118        movement("end-of-line", "End of Line", "moveToEndOfParagraph:"),
119        movement("forward-word", "Forward Word", "moveWordForward:"),
120        movement("backward-word", "Backward Word", "moveWordBackward:"),
121        movement("beginning-of-buffer", "Beginning of Buffer", "moveToBeginningOfDocument:"),
122        movement("end-of-buffer", "End of Buffer", "moveToEndOfDocument:"),
123        movement("scroll-up", "Scroll Up", "pageDown:"),
124        movement("scroll-down", "Scroll Down", "pageUp:"),
125        edit("recenter", "Recenter", "centerSelectionInVisibleArea:"),
126        edit("delete-char", "Delete Character", "deleteForward:"),
127        edit("kill-word", "Kill Word", "deleteWordForward:"),
128        edit("backward-kill-word", "Kill Word Backward", "deleteWordBackward:"),
129        edit("kill-line", "Kill Line", "deleteToEndOfParagraph:"),
130        edit("yank", "Yank", "yank:"),
131        edit("select-all", "Select All", "selectAll:"),
132        edit("kill-region", "Kill Region", "cut:"),
133        edit("copy-region", "Copy Region", "copy:"),
134        edit("undo", "Undo", "undo:"),
135        edit("transpose-chars", "Transpose Characters", "transpose:"),
136        EditorCommand(id: "edit.find", title: "Find", action: .find(.showFindInterface)),
137        EditorCommand(id: "edit.replace", title: "Find and Replace", action: .find(.showReplaceInterface)),
138        EditorCommand(id: "edit.find-next", title: "Find Next", action: .find(.nextMatch)),
139        EditorCommand(id: "edit.find-previous", title: "Find Previous", action: .find(.previousMatch)),
140        EditorCommand(id: "edit.use-selection-for-find", title: "Use Selection for Find", action: .find(.setSearchString)),
141        EditorCommand(id: "edit.set-mark", title: "Set Mark", action: .mark),
142        EditorCommand(id: "edit.keyboard-quit", title: "Quit", action: .mark),
143    ]
144
145    private static func movement(_ name: String, _ title: String, _ selector: String) -> EditorCommand {
146        let extending = String(selector.dropLast()) + "AndModifySelection:"
147        return EditorCommand(id: "edit.\(name)", title: title, action: .edit(selector: selector, extending: extending))
148    }
149
150    private static func edit(_ name: String, _ title: String, _ selector: String) -> EditorCommand {
151        EditorCommand(id: "edit.\(name)", title: title, action: .edit(selector: selector))
152    }
153
154    private static let byID = Dictionary(uniqueKeysWithValues: all.map { ($0.id, $0) })
155
156    public static func command(_ id: String) -> EditorCommand? { byID[id] }
157}
158#endif