krz/orgstar

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

Commit 6330c50eb5

6330c50eb5da699838579e60fafaa27ee27ade5f

parent: 6f59c47b8d

Verified · cmc

cmc <hello@cleberg.net> · 2026-10-08 05:43 UTC

Mac preset keys for links, clocking, export and act at point

⌃⌘X acts at point; ⌘K, ⌃⌘O, ⌃⌘L for links; ⌃⌘I, ⌃⇧⌘I, ⌃⌘J for the clock; ⇧⌘E export; ⌃⌘N narrowing; sort, property, footnote, effort and edit-block keys; ⌃⇧⌘ arrows for TODO keywords; ⌥⇧⌘ up and down for same-level headings; ⌃⌘, priority; ⌃⌘V tangle.

Layout: unified · split

Sources/OrgCore/Keymap/Presets.swift +84
@@ -1225,5 +1225,89 @@ public enum KeymapPreset: String, Sendable, CaseIterable {
1225 command = "org.timestamp.day-earlier" 1225 command = "org.timestamp.day-earlier"
1226 when = "timestamp" 1226 when = "timestamp"
1227 1227
1228 # Act at point, links, clocking, export and the rest of C-c.
1229 [[bind]]
1230 keys = "C-s-x"
1231 command = "org.ctrl-c-ctrl-c"
1232 [[bind]]
1233 keys = "C-s-x"
1234 command = "org.dblock.update"
1235 when = "dblock"
1236 [[bind]]
1237 keys = "C-s-x"
1238 command = "org.table.recalc-all"
1239 when = "tblfm"
1240 [[bind]]
1241 keys = "C-s-x"
1242 command = "org.babel.execute"
1243 when = "src"
1244 [[bind]]
1245 keys = "s-k"
1246 command = "org.link.insert"
1247 [[bind]]
1248 keys = "C-s-o"
1249 command = "org.link.open"
1250 [[bind]]
1251 keys = "C-s-l"
1252 command = "org.link.store"
1253 [[bind]]
1254 keys = "C-s-i"
1255 command = "app.clock.in"
1256 [[bind]]
1257 keys = "C-S-s-i"
1258 command = "app.clock.out"
1259 [[bind]]
1260 keys = "C-s-j"
1261 command = "app.clock.goto"
1262 [[bind]]
1263 keys = "s-S-e"
1264 command = "app.export-dialog"
1265 [[bind]]
1266 keys = "C-s-n"
1267 command = "org.narrow.toggle"
1268 [[bind]]
1269 keys = "C-S-s-s"
1270 command = "org.sort"
1271 [[bind]]
1272 keys = "C-S-s-p"
1273 command = "org.property.read-and-set"
1274 [[bind]]
1275 keys = "C-S-s-f"
1276 command = "org.footnote.action"
1277 [[bind]]
1278 keys = "C-s-'"
1279 command = "org.edit-special"
1280 [[bind]]
1281 keys = "C-S-s-<right>"
1282 command = "org.todo.next"
1283 when = "heading"
1284 [[bind]]
1285 keys = "C-S-s-<left>"
1286 command = "org.todo.previous"
1287 when = "heading"
1288 [[bind]]
1289 keys = "C-S-s-<right>"
1290 command = "org.property.next-value"
1291 when = "property"
1292 [[bind]]
1293 keys = "C-S-s-<left>"
1294 command = "org.property.previous-value"
1295 when = "property"
1296 [[bind]]
1297 keys = "M-S-s-<down>"
1298 command = "org.heading.forward-same-level"
1299 [[bind]]
1300 keys = "M-S-s-<up>"
1301 command = "org.heading.backward-same-level"
1302 [[bind]]
1303 keys = "C-S-s-e"
1304 command = "org.effort.set"
1305 [[bind]]
1306 keys = "C-s-,"
1307 command = "org.priority.set"
1308 [[bind]]
1309 keys = "C-s-v"
1310 command = "org.babel.tangle"
1311
1228 """ 1312 """
1229} 1313}
Tests/OrgCoreTests/KeymapTests.swift +16
@@ -153,6 +153,22 @@ struct KeymapTests {
153 #expect(KeymapPreset.mac.keymap.keys(for: "org.deadline") == [KeyChord("e", [.control, .command])]) 153 #expect(KeymapPreset.mac.keymap.keys(for: "org.deadline") == [KeyChord("e", [.control, .command])])
154 } 154 }
155 155
156 /// The Mac preset reaches links, clocking, export and act-at-point without the palette.
157 @Test func macPresetCoversOrgAreas() {
158 let mac = KeymapPreset.mac.keymap
159 let expected: [(String, String)] = [
160 ("org.ctrl-c-ctrl-c", "C-s-x"), ("org.link.insert", "s-k"), ("org.link.open", "C-s-o"), ("org.link.store", "C-s-l"),
161 ("app.clock.in", "C-s-i"), ("app.clock.out", "C-s-I"), ("app.clock.goto", "C-s-j"), ("app.export-dialog", "s-E"),
162 ("org.narrow.toggle", "C-s-n"), ("org.sort", "C-s-S"), ("org.property.read-and-set", "C-s-P"),
163 ("org.footnote.action", "C-s-F"), ("org.edit-special", "C-s-'"), ("org.todo.next", "C-S-s-<right>"),
164 ("org.heading.forward-same-level", "M-S-s-<down>"), ("org.effort.set", "C-s-E"), ("org.priority.set", "C-s-,"),
165 ("org.babel.tangle", "C-s-v"),
166 ]
167 for (command, keys) in expected {
168 #expect(mac.keys(for: command).map(KeySequence.format) == keys, "\(command)")
169 }
170 }
171
156 /// A binding whose keys start a longer live binding never runs: the dispatcher waits for more. 172 /// A binding whose keys start a longer live binding never runs: the dispatcher waits for more.
157 @Test func presetsBindNoPrefixes() { 173 @Test func presetsBindNoPrefixes() {
158 for preset in KeymapPreset.allCases { 174 for preset in KeymapPreset.allCases {