krz/orgstar

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

Commit 322a87d475

322a87d47526d505d903e05d14e65a5464e1468f

parent: 191ddb506f

Verified · cmc

cmc <hello@cleberg.net> · 2026-10-09 07:54 UTC

iOS log mode and dependency settings, Emacs word-syntax table, lazier blocked checks

- iOS: Log Mode in the span menu; widgets stay out of log mode.
- iOS Settings: Blocked entries, and the two TODO dependency settings.
- Agenda sources work out blocked flags only when an enforce setting
  is on and dimming isn't off.
- Regexp word boundaries use Emacs 31's word-syntax table for Org
  buffers; the search view treats ' as punctuation, as
  org-search-syntax-table does.

Layout: unified · split

Sources/OrgApp/AgendaModel.swift +4 −3
@@ -114,6 +114,7 @@ public final class AgendaModel {
114114 /// while their modification date and size are unchanged.
115115 private func sources(open: [String: String]) async -> [AgendaSource] {
116116 let defaults = workspace.settings.org
117 let blocking = options.dimBlockedTasks != .off && (options.enforceTodoDependencies || options.enforceTodoCheckboxDependencies)
117118 var reads: [(path: String, cached: AgendaSource?, mtime: Date, size: Int, text: String?)] = []
118119 for path in files {
119120 if let text = open[path] {
@@ -124,7 +125,7 @@ public final class AgendaModel {
124125 let mtime = attributes?[.modificationDate] as? Date ?? .distantPast
125126 let size = (attributes?[.size] as? NSNumber)?.intValue ?? -1
126127 // A file reading setup files is read again: they may have changed.
127 let cached = cache[path].flatMap { $0.mtime == mtime && $0.size == size && !$0.source.readsSetupFiles ? $0.source : nil }
128 let cached = cache[path].flatMap { $0.mtime == mtime && $0.size == size && !$0.source.readsSetupFiles && $0.source.checksBlocking == blocking ? $0.source : nil }
128129 reads.append((path, cached, mtime, size, nil))
129130 }
130131 let loaded = await Task.detached {
@@ -133,10 +134,10 @@ public final class AgendaModel {
133134 if let cached = read.cached {
134135 sources.append((read.path, read.mtime, read.size, cached, true))
135136 } else if let text = read.text {
136 sources.append((read.path, read.mtime, read.size, AgendaSource(path: read.path, text: text, defaults: defaults.resolvingSetupFiles(in: text, path: read.path, read: OrgSettings.readFile)), false))
137 sources.append((read.path, read.mtime, read.size, AgendaSource(path: read.path, text: text, defaults: defaults.resolvingSetupFiles(in: text, path: read.path, read: OrgSettings.readFile), checksBlocking: blocking), false))
137138 } else if let data = FileManager.default.contents(atPath: read.path) {
138139 let text = SourceText(bytes: [UInt8](data)).text
139 sources.append((read.path, read.mtime, read.size, AgendaSource(path: read.path, text: text, defaults: defaults.resolvingSetupFiles(in: text, path: read.path, read: OrgSettings.readFile)), true))
140 sources.append((read.path, read.mtime, read.size, AgendaSource(path: read.path, text: text, defaults: defaults.resolvingSetupFiles(in: text, path: read.path, read: OrgSettings.readFile), checksBlocking: blocking), true))
140141 }
141142 }
142143 return sources
Sources/OrgCore/Agenda/AgendaSearch.swift +28 −6
@@ -219,7 +219,7 @@ extension Agenda {
219219
220220 /// Case-insensitive, as Org binds `case-fold-search`, with `^` and `$` at each line.
221221 static func compile(_ emacs: String) -> NSRegularExpression? {
222 try? NSRegularExpression(pattern: EmacsRegex.translate(emacs), options: [.caseInsensitive, .anchorsMatchLines])
222 try? NSRegularExpression(pattern: EmacsRegex.translate(emacs, search: true), options: [.caseInsensitive, .anchorsMatchLines])
223223 }
224224 }
225225
@@ -480,10 +480,32 @@ public struct TagsMatcher: Sendable {
480480/// Emacs regular expressions run through ICU, case-insensitively as the matcher binds
481481/// `case-fold-search`.
482482enum EmacsRegex {
483 /// Word syntax in an Org buffer: letters, digits, marks, `$` and `%`, but not `_`, `-` or `'`.
484 static let word = "[\\p{L}\\p{N}\\p{M}$%\\u00b7]"
485
486 static func translate(_ pattern: String) -> String {
483 /// Characters without word syntax in an Org buffer under Emacs 31, as ranges: everything
484 /// else, `$`, `%` and `'` included, is a word character. Emacs also puts a word boundary
485 /// where the script changes, which this doesn't.
486 static let nonWord = ""
487 + "\\x{0}-\\x{23}\\x{26}\\x{28}-\\x{2f}\\x{3a}-\\x{40}\\x{5b}-\\x{60}\\x{7b}-\\x{7f}\\x{a0}-\\x{a4}"
488 + "\\x{a6}-\\x{b1}\\x{b4}\\x{b6}\\x{b8}\\x{ba}-\\x{bf}\\x{d7}\\x{f7}\\x{2c7}\\x{2c9}\\x{2d0}"
489 + "\\x{2d8}-\\x{2db}\\x{2dd}\\x{384}-\\x{385}\\x{5be}\\x{5c0}\\x{5c3}\\x{5c6}\\x{e2f}\\x{e3f}\\x{e46}"
490 + "\\x{e4f}\\x{e5a}-\\x{e5b}\\x{eaf}\\x{ec6}\\x{f00}-\\x{f0b}\\x{f0d}-\\x{f18}\\x{f1a}-\\x{f1f}\\x{f34}"
491 + "\\x{f36}\\x{f38}-\\x{f3f}\\x{f7f}\\x{f85}\\x{fbe}-\\x{fcf}\\x{1361}-\\x{1368}\\x{1800}-\\x{180a}"
492 + "\\x{2000}-\\x{2026}\\x{202f}-\\x{205f}\\x{207d}-\\x{207e}\\x{208d}-\\x{208e}\\x{20ac}\\x{2103}"
493 + "\\x{2109}\\x{2116}\\x{2121}-\\x{2122}\\x{2153}-\\x{2154}\\x{215b}-\\x{215e}\\x{2190}-\\x{244f}"
494 + "\\x{2460}-\\x{246e}\\x{2474}-\\x{24b5}\\x{2500}-\\x{254b}\\x{2592}\\x{25a0}-\\x{25a1}"
495 + "\\x{25a3}-\\x{25a9}\\x{25b2}-\\x{25b3}\\x{25b6}-\\x{25b7}\\x{25bc}-\\x{25bd}\\x{25c0}-\\x{25c1}"
496 + "\\x{25c6}-\\x{25c8}\\x{25cb}\\x{25ce}-\\x{25d1}\\x{25ef}\\x{2605}-\\x{2606}\\x{260e}-\\x{260f}"
497 + "\\x{261c}\\x{261e}\\x{2640}\\x{2642}\\x{2660}-\\x{2661}\\x{2663}-\\x{2665}\\x{2667}-\\x{266a}"
498 + "\\x{266c}-\\x{266d}\\x{266f}\\x{2768}-\\x{276d}\\x{2770}-\\x{2775}\\x{27e6}-\\x{27eb}"
499 + "\\x{2983}-\\x{2998}\\x{29fc}-\\x{29fd}\\x{2a00}-\\x{2bff}\\x{2e00}-\\x{2e7f}\\x{3000}-\\x{3003}"
500 + "\\x{3008}-\\x{301c}\\x{30fb}\\x{3200}-\\x{321c}\\x{3220}-\\x{3229}\\x{3260}-\\x{327b}"
501 + "\\x{327e}-\\x{327f}\\x{3380}-\\x{3384}\\x{3388}-\\x{33ca}\\x{33cf}-\\x{33d0}\\x{33d3}\\x{33d6}"
502 + "\\x{33d8}\\x{33db}-\\x{33dd}\\x{aadb}-\\x{aadf}\\x{fd3e}-\\x{fd3f}\\x{fe35}-\\x{fe44}"
503 + "\\x{fe59}-\\x{fe5e}\\x{ff01}-\\x{ff0f}\\x{ff1b}-\\x{ff20}\\x{ff3b}-\\x{ff40}\\x{ff5b}-\\x{ff65}"
504 + "\\x{ffe0}-\\x{ffe3}\\x{ffe5}\\x{11660}-\\x{1166c}\\x{1fb00}-\\x{1fbff}"
505 /// `search` uses `org-search-view`'s syntax table, where `'` is punctuation.
506 static func translate(_ pattern: String, search: Bool = false) -> String {
507 let nonWord = search ? Self.nonWord + "'" : Self.nonWord
508 let word = "[^" + nonWord + "]"
487509 var out = ""
488510 var chars = Array(pattern)
489511 var i = 0
@@ -532,7 +554,7 @@ enum EmacsRegex {
532554 case "`": out += "^"
533555 case "'": out += "$"
534556 case "w": out += word
535 case "W": out += "[^" + word.dropFirst()
557 case "W": out += "[" + nonWord + "]"
536558 default: out += "\\" + String(n)
537559 }
538560 i += 2
Sources/OrgCore/Agenda/AgendaSource.swift +7 −2
@@ -102,10 +102,15 @@ public struct AgendaSource: Sendable {
102102 let notDoneKeywords: [String]
103103 /// The file's text, for the search view.
104104 let text: String
105 /// Whether the headings' blocked flags were worked out.
106 public let checksBlocking: Bool
105107 let priorities: Priorities
106108
107 public init(path: String, text: String, defaults: OrgSettings = .default) {
109 /// `checksBlocking` false leaves every heading unblocked, for when neither enforce
110 /// setting is on.
111 public init(path: String, text: String, defaults: OrgSettings = .default, checksBlocking: Bool = true) {
108112 self.path = path
113 self.checksBlocking = checksBlocking
109114 readsSetupFiles = text.range(of: "#+setupfile:", options: .caseInsensitive) != nil
110115 let tree = OrgParser.parse(text, defaults: defaults)
111116 let model = DocumentModel(tree: tree)
@@ -236,7 +241,7 @@ public struct AgendaSource: Sendable {
236241 }
237242 var blockedByCheckboxes = false
238243 var blockedByHierarchy = false
239 if info.todo != nil, !info.isDone, buffer.localProperty("NOBLOCKING", heading: info.headingRange.lowerBound).map({ $0 == "nil" }) ?? true {
244 if checksBlocking, info.todo != nil, !info.isDone, buffer.localProperty("NOBLOCKING", heading: info.headingRange.lowerBound).map({ $0 == "nil" }) ?? true {
240245 buffer.point = info.headingRange.lowerBound
241246 blockedByCheckboxes = buffer.hasOpenCheckbox()
242247 blockedByHierarchy = buffer.hierarchyBlocker() != nil
Sources/OrgstarMobile/AgendaScreen.swift +6 −1
@@ -38,6 +38,8 @@ struct AgendaScreen: View {
3838 @AppStorage("agendaOverdueExpanded") private var overdueExpanded = true
3939 @State private var done = 0
4040 @State private var moved = 0
41 /// `org-agenda-log-mode`: closed entries and clocked time on each day.
42 @State private var logMode = false
4143
4244 /// A match typed for the tag and property view, or a search string.
4345 private enum Asking: Identifiable {
@@ -62,6 +64,7 @@ struct AgendaScreen: View {
6264 var startOffset: Int
6365 var subfolders: Bool
6466 var settings: Int
67 var logMode: Bool
6568 }
6669
6770 private var isDark: Bool { colorScheme == .dark }
@@ -202,7 +205,8 @@ struct AgendaScreen: View {
202205 }
203206 .task(id: Key(files: workspace.files.count, changed: workspace.changedFile?.version, edits: session.editVersion, tick: tick,
204207 mode: agenda.mode, start: agenda.start, span: agenda.span, startOffset: agenda.startOffset,
205 subfolders: agenda.includeSubfolders, settings: model.settingsVersion)) {
208 subfolders: agenda.includeSubfolders, settings: model.settingsVersion, logMode: logMode)) {
209 agenda.options.logMode = logMode
206210 await agenda.refresh(open: session.openTexts)
207211 }
208212 }
@@ -381,6 +385,7 @@ struct AgendaScreen: View {
381385 ForEach(SpanRange.allCases) { Text($0.title).tag(Optional($0)) }
382386 Text("\(agenda.span) Days").tag(SpanRange?.none)
383387 }
388 Toggle("Log Mode", systemImage: "clock.arrow.circlepath", isOn: $logMode)
384389 } label: {
385390 Text(range?.title ?? "\(agenda.span) Days")
386391 .font(.footnote.weight(.semibold).monospacedDigit())
Sources/OrgstarMobile/MobileModel.swift +1
@@ -220,6 +220,7 @@ final class MobileModel {
220220 if let agenda {
221221 days.includeSubfolders = agenda.includeSubfolders
222222 days.options = agenda.options
223 days.options.logMode = false
223224 days.calendarEvents = agenda.calendarEvents
224225 days.calendarNames = agenda.calendarNames
225226 }
Sources/OrgstarMobile/SettingsScreen.swift +20
@@ -37,6 +37,26 @@ struct SettingsScreen: View {
3737 Toggle("Show days without entries", isOn: Binding {
3838 OrgPreferences.agendaShowAllDates()
3939 } set: { model.set("agendaShowAllDates", to: .bool($0)) })
40 Picker("Blocked entries", selection: Binding {
41 UserDefaults.standard.string(forKey: "agendaDimBlockedTasks") ?? "t"
42 } set: { model.set("agendaDimBlockedTasks", to: .string($0)) }) {
43 Text("Dimmed").tag("t")
44 Text("Hidden").tag("invisible")
45 Text("Shown as usual").tag("nil")
46 }
47 }
48 Section {
49 let _ = model.settingsVersion
50 Toggle("Not done before TODO children", isOn: Binding {
51 UserDefaults.standard.bool(forKey: "enforceTodoDependencies")
52 } set: { model.set("enforceTodoDependencies", to: .bool($0)) })
53 Toggle("Not done with unchecked boxes", isOn: Binding {
54 UserDefaults.standard.bool(forKey: "enforceTodoCheckboxDependencies")
55 } set: { model.set("enforceTodoCheckboxDependencies", to: .bool($0)) })
56 } header: {
57 Text("TODO Dependencies")
58 } footer: {
59 Text("org-enforce-todo-dependencies and org-enforce-todo-checkbox-dependencies.")
4060 }
4161 calendarSection
4262 Section("In use") {
Tests/OrgCoreTests/AgendaSearchTests.swift +3 −2
@@ -29,6 +29,7 @@ struct AgendaSearchTests {
2929 The phrase two words
3030 spans here; foo_bar and foo-bar.
3131 Costs $5 or 50% (don't) for the café.
32 Marked ©2026, «quoted», a·b, x→y and 😀smile.
3233 * The last
3334 word ends this entry with last
3435 * word starts the next heading
@@ -55,9 +56,9 @@ struct AgendaSearchTests {
5556 "+alpha", "+alpha -beta", "+alpha +gamma", "-alpha", "+beta -nested", "{alph?a}", "+{^Gam}", "-{b[eo]}",
5657 "+{\\<rent\\>}", "+\"two words\"", "+\"two words\"", "+\"the line\"", "{boiler\\b}", "+alpha +\"in the body\"",
5758 "+{foo\\s-bar}", "+boiler -plate", "+{a b}", "+{alpha} -{x y}",
58 // Emacs word syntax in Org buffers: `_`, `-` and `'` are not word characters; `$` and `%` are.
59 // Emacs word syntax in the search view: `_`, `-` and `'` are not word characters; `$` and `%` are.
5960 "+{\\<bar\\>}", "+{foo\\b}", "+{o\\B_}", "+{\\<5\\>}", "+{\\b50\\b}", "+{don\\>}", "+{\\w+_\\w+}", "+{\\W5}",
60 "+{caf\\w\\>}", "+{\\<\\$5}",
61 "+{caf\\w\\>}", "+{\\<\\$5}", "+{\\<2026}", "+{\\<quoted\\>}", "+{a\\b·}", "+{\\<b,}", "+{x\\>}",
6162 // Headlines only.
6263 "*rent", "*alpha", "*+alpha -beta", "*+section", "*-alpha", "*pay rent", "*with alpha and",
6364 // TODO only and whole words.
Tests/OrgCoreTests/TodoDependencyTests.swift +7
@@ -192,6 +192,13 @@ struct TodoDependencyTests {
192192 #expect(blocked(true, true, .invisible) == ["TODO B", "~TODO C", "TODO D"])
193193 }
194194
195 @Test func sourcesCanSkipTheBlockingCheck() {
196 let source = AgendaSource(path: "/tmp/a.org", text: "* TODO A\n** TODO B\n", checksBlocking: false)
197 var options = AgendaOptions()
198 options.enforceTodoDependencies = true
199 #expect(Agenda.todoList([source], options: options).allSatisfy { !$0.isBlocked })
200 }
201
195202 @Test func dwimIsBlocked() {
196203 let text = "* TODO A\n** TODO B\n"
197204 var options = EditingOptions.org
docs/manual/guide/05-todos-and-tags.org +2 −2
@@ -336,7 +336,7 @@ The =COOKIE_DATA= property changes what the parent's cookie counts:
336336| =org-todo-keywords= | Settings ▸ Editing, =config.toml= | See "The default keywords" above |
337337| =org-log-done= | =config.toml= | =nil= |
338338| =org-log-into-drawer= | =config.toml= | =""= (no drawer) |
339| =org-enforce-todo-dependencies= | Settings ▸ Editing, =config.toml= | =false= |
340| =org-enforce-todo-checkbox-dependencies= | Settings ▸ Editing, =config.toml= | =false= |
339| =org-enforce-todo-dependencies= | Settings ▸ Editing (iOS: Settings ▸ TODO Dependencies), =config.toml= | =false= |
340| =org-enforce-todo-checkbox-dependencies= | Settings ▸ Editing (iOS: Settings ▸ TODO Dependencies), =config.toml= | =false= |
341341| =org-tags-column= | Settings ▸ Editing, =config.toml= | =-77= |
342342| =org-use-speed-commands= | =config.toml= | =false= |
docs/manual/guide/07-agenda.org +4 −3
@@ -122,7 +122,7 @@ Days are sorted as =org-agenda-sorting-strategy= sorts them by default for the a
122122
123123** Log mode
124124
125Press =l= to turn log mode (=org-agenda-log-mode=) on or off. Each day then also shows:
125Press =l= to turn log mode (=org-agenda-log-mode=) on or off; on iOS, use Log Mode in the span menu. Each day then also shows:
126126
127127- =Closed= entries whose =CLOSED:= timestamp is on that day;
128128- =Clocked= entries for each =CLOCK:= line that starts on that day, with the clock's start and end times in the left column and the time clocked, such as =1:30=, after the title.
@@ -153,7 +153,7 @@ Ages and distances are written compactly: days up to 13 (=3d=), then whole weeks
153153
154154The keyword's color comes from =[theme.todo]=, else from its class: =todo-next= for keywords of work under way such as =NEXT= and =STRT=, =todo-waiting= for =WAIT=, =HOLD= and similar, =todo-cancelled= for done keywords such as =KILL= and =CANCELLED=, and otherwise =todo= or =done=. Priorities =A=, =B= and =C= use =priority-a=, =priority-b= and =priority-c=; others use =priority=. A category's dot takes its color from =[theme.category]=, else a hue worked out from the category's name, the same on every device. See [[file:13-configuration.org][Configuration]] for the keyword lists and the theme keys.
155155
156With =org-enforce-todo-dependencies= or =org-enforce-todo-checkbox-dependencies= on, an entry that can't be marked done yet is dimmed in every view (=org-agenda-dim-blocked-tasks= =t=). Settings ▸ Agenda ▸ Blocked entries can hide such entries instead (=invisible=), though one held back only by its own checkboxes stays dimmed, or show them as usual (=nil=). Marking a blocked entry done from the agenda is refused with the same message as in the editor; see [[file:05-todos-and-tags.org][TODOs and tags]].
156With =org-enforce-todo-dependencies= or =org-enforce-todo-checkbox-dependencies= on, an entry that can't be marked done yet is dimmed in every view (=org-agenda-dim-blocked-tasks= =t=). Settings ▸ Agenda ▸ Blocked entries (on iOS, Settings ▸ Agenda) can hide such entries instead (=invisible=), though one held back only by its own checkboxes stays dimmed, or show them as usual (=nil=). Marking a blocked entry done from the agenda is refused with the same message as in the editor; see [[file:05-todos-and-tags.org][TODOs and tags]].
157157
158158* Calendar events
159159
@@ -571,7 +571,8 @@ The Agenda tab shows the same views from the same files, using the settings in t
571571- Swipe right on a scheduled entry, a deadline, a habit or a TODO entry, when it isn't done, for Tomorrow, Next Week and Pick Date. Tomorrow is the day after today and Next Week is next Monday. On a deadline row these move the deadline; on other rows they set the scheduled date. A timed row keeps its times.
572572- Touch and hold an entry for TODO State…, Reschedule (Tomorrow, Next Week, Pick Date…), Schedule…, Deadline…, Tags…, Priority…, Clock In, Refile… and Archive….
573573- Marking an entry done and rescheduling one give haptic feedback.
574- There are no keyboard commands, log mode or bulk marks.
574- Log Mode, in the span menu, turns log mode on and off. The widgets never show log mode's entries.
575- There are no keyboard commands or bulk marks.
575576- Reminders are set while the app is open. iOS allows at most 64 pending notifications and the app can't add more while it isn't running, so the agenda's footer says how far ahead they go and asks you to open Orgstar to set later ones.
576577
577578The Today and Up Next widgets show the agenda on the Home Screen and the Lock Screen; see [[file:14-ios.org][iPhone and iPad]].
docs/manual/guide/14-ios.org +4 −2
@@ -155,7 +155,7 @@ Tap a result to open it in the reader. A heading result opens at that heading.
155155The Agenda tab shows the agenda over all your folders, with the span and start day from the settings (10 days from 3 days ago by default). Each day lists its entries in rows: the time or a status such as =Due today= or =3d late= on the left, the category and the keyword above the title. Days without entries are hidden, except today. Today's overdue entries are in a group of their own, and a line marks the current time between timed entries. Pull down to refresh.
156156
157157- Views (top left) :: the built-in views and those in =views.toml=, Tags and Properties… (a match such as =+work-home= or ~TODO="WAIT"~), and Search… (a phrase, or snippets such as =+invoice -paid=).
158- The bar at the bottom :: Earlier, Filter, Today, Go to Date, the span (Day, Week, Month or the configured span) and Later.
158- The bar at the bottom :: Earlier, Filter, Today, Go to Date, the span (Day, Week, Month or the configured span, and Log Mode, which adds closed entries and clocked time) and Later.
159159- Filter :: keep or leave out tags and categories of the entries shown, or type a filter as Org's =/= takes it: =+keep= and =-drop= tags or categories, =<0:30= for effort, =/regexp/=. The filter in use shows above the bar.
160160- + on a day's header :: captures an entry scheduled on that day (see [[file:08-capture.org][Capture]]).
161161- Tap :: an entry to read it, at its heading.
@@ -311,9 +311,11 @@ Changes to the files apply as they sync, and again each time you return to the a
311311
312312Stop Using This Folder returns every setting to its default.
313313
314The Agenda and Calendar sections are the only places the app changes a setting itself:
314The Agenda, TODO Dependencies and Calendar sections are the only places the app changes a setting itself:
315315
316316- Show days without entries :: turns =org-agenda-show-all-dates= on or off.
317- Blocked entries :: Dimmed, Hidden or Shown as usual (=org-agenda-dim-blocked-tasks=).
318- TODO Dependencies :: Not done before TODO children (=org-enforce-todo-dependencies=) and Not done with unchecked boxes (=org-enforce-todo-checkbox-dependencies=).
317319- Show Calendar Events :: turns on =calendar-events=, and asks for access to your calendars. iOS asks for full access, as Calendar has no read-only level; Orgstar only reads. While access is missing the section shows Allow Access to Calendars…; if you declined, allow it in the Settings app under Privacy & Security ▸ Calendars.
318320- The calendars :: tap one to show or hide its events (=calendar-event-calendars=). With every calendar checked the setting is empty, so calendars added later show too.
319321
docs/manual/guide/15-alongside-emacs.org +1
@@ -247,5 +247,6 @@ Other:
247247- Most =#+STARTUP= options for footnotes, entities, LaTeX previews, numbering and odd levels are accepted and ignored; see [[file:13-configuration.org][Configuration]].
248248- =display-line-numbers-type= has no relative or visual mode.
249249- The agenda's text search (see [[file:07-agenda.org][The agenda]]) covers the agenda files only: =org-agenda-text-search-extra-files= and =org-agenda-search-view-max-outline-level= aren't supported. It runs from the view menu rather than the dispatcher's =s= and =S=, and the search view's =[=, =]=, ={= and =}= keys, which add words and regexps to the search, aren't supported.
250- In regexps, =\<=, =\>= and =\b= use Org's word syntax but don't find a word boundary where the script changes between two word characters, as Emacs does (for example between an emoji and a letter).
250251- =org-track-ordered-property-with-tag= isn't supported; Toggle ORDERED Property sets only the property.
251252- When TODO dependencies refuse a change on a =COMMENT= heading, the heading keeps =COMMENT=. Org removes it before the check and doesn't put it back.