| @@ -234,7 +234,7 @@ public struct EmacsImport: Sendable { |
| 234 | 234 | return modes.isEmpty ? [nil] : modes |
| 235 | 235 | } |
| 236 | 236 | |
| 237 | | /// `(kbd "C-c x")`, `"C-c x"` (keymap-set), or a vector of one key. |
| 237 | /// `(kbd "C-c x")` or `"C-c x"` (keymap-set); key vectors such as `[f5]` are skipped. |
| 238 | 238 | func keyString(_ sexp: Sexp) -> String? { |
| 239 | 239 | if let s = sexp.string { return s } |
| 240 | 240 | if sexp.head == "kbd", let s = sexp.elements?.dropFirst().first?.string { return s } |
| @@ -618,7 +618,7 @@ public struct EmacsImport: Sendable { |
| 618 | 618 | |
| 619 | 619 | /// Emacs commands and the Orgstar commands that do the same. |
| 620 | 620 | static let commands: [String: String] = [ |
| 621 | | "org-todo": "org.todo.cycle", "org-shiftright": "org.todo.cycle", "org-priority-up": "org.priority.up", "org-priority-down": "org.priority.down", |
| 621 | "org-todo": "org.todo.cycle", "org-shiftright": "org.todo.next", "org-shiftleft": "org.todo.previous", "org-priority-up": "org.priority.up", "org-priority-down": "org.priority.down", |
| 622 | 622 | "org-metaleft": "org.heading.promote", "org-metaright": "org.heading.demote", "org-do-promote": "org.heading.promote", "org-do-demote": "org.heading.demote", |
| 623 | 623 | "org-promote-subtree": "org.subtree.promote", "org-demote-subtree": "org.subtree.demote", |
| 624 | 624 | "org-shiftmetaleft": "org.subtree.promote", "org-shiftmetaright": "org.subtree.demote", |
| @@ -629,8 +629,8 @@ public struct EmacsImport: Sendable { |
| 629 | 629 | "org-next-visible-heading": "org.heading.next", "org-previous-visible-heading": "org.heading.previous", |
| 630 | 630 | "org-forward-heading-same-level": "org.heading.forward-same-level", "org-backward-heading-same-level": "org.heading.backward-same-level", |
| 631 | 631 | "outline-up-heading": "org.heading.up", "org-up-element": "org.heading.up", |
| 632 | | "org-set-tags-command": "org.tags.set", "org-set-property": "org.property.set", |
| 633 | | "org-toggle-checkbox": "org.checkbox.toggle", "org-ctrl-c-ctrl-c": "org.dwim", "+org/dwim-at-point": "org.dwim", |
| 632 | "org-set-tags-command": "org.tags.set", "org-set-property": "org.property.read-and-set", |
| 633 | "org-toggle-checkbox": "org.checkbox.toggle", "org-ctrl-c-ctrl-c": "org.ctrl-c-ctrl-c", "+org/dwim-at-point": "org.dwim", |
| 634 | 634 | "org-schedule": "org.schedule", "org-deadline": "org.deadline", "org-time-stamp": "org.timestamp.active", "org-timestamp": "org.timestamp.active", |
| 635 | 635 | "org-time-stamp-inactive": "org.timestamp.inactive", "org-timestamp-inactive": "org.timestamp.inactive", |
| 636 | 636 | "org-fill-paragraph": "org.fill-paragraph", "org-cycle": "org.cycle", "org-shifttab": "org.cycle-global", "org-global-cycle": "org.cycle-global", |
| @@ -652,7 +652,8 @@ public struct EmacsImport: Sendable { |
| 652 | 652 | extension EmacsImport { |
| 653 | 653 | /// Applies `items`: settings to `defaults` (and so config.toml), folders to the workspace, |
| 654 | 654 | /// capture templates and key bindings appended to capture.toml and keymap.toml in |
| 655 | | /// `directory`, leaving out templates whose key is there already. Returns a summary. |
| 655 | /// `directory`, leaving out templates whose key is there already and bindings that are |
| 656 | /// there already. Returns a summary. |
| 656 | 657 | @MainActor |
| 657 | 658 | public static func apply( |
| 658 | 659 | _ items: [Item], defaults: UserDefaults = .standard, workspace: WorkspaceModel?, directory: URL = UserConfig.directory |
| @@ -695,9 +696,13 @@ extension EmacsImport { |
| 695 | 696 | } |
| 696 | 697 | let keymapFile = directory.appendingPathComponent("keymap.toml") |
| 697 | 698 | var keymap = (try? String(contentsOf: keymapFile, encoding: .utf8)) ?? "" |
| 699 | func binding(_ keys: String?, _ command: String?, _ mode: String?) -> String { [keys ?? "", command ?? "", mode ?? ""].joined(separator: "\u{0}") } |
| 700 | var existingBindings = Set((try? TOML.parse(keymap))?.filter { $0.name == "bind" && $0.values["when"] == nil } |
| 701 | .map { binding($0.values["keys"]?.string, $0.values["command"]?.string, $0.values["mode"]?.string) } ?? []) |
| 698 | 702 | var addedKeys = "" |
| 699 | 703 | for item in items { |
| 700 | | guard case .binding(let keys, let command, let mode) = item.change else { continue } |
| 704 | guard case .binding(let keys, let command, let mode) = item.change, |
| 705 | existingBindings.insert(binding(keys, command, mode)).inserted else { continue } |
| 701 | 706 | addedKeys += "\n[[bind]]\nkeys = \(UserConfig.format(.string(keys)))\ncommand = \(UserConfig.format(.string(command)))\n" |
| 702 | 707 | if let mode { addedKeys += "mode = \(UserConfig.format(.string(mode)))\n" } |
| 703 | 708 | bindings += 1 |