krz/orgstar

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

Commit 674de54223

674de542235029741e65b44cbb458b8846dec924

parent: 9abba9cfc5

Verified · cmc

cmc <hello@cleberg.net> · 2026-10-08 03:34 UTC

Apply every editing setting on iOS

OrgPreferences.options now carries org-M-RET-may-split-line,
org-hide-emphasis-markers, org-pretty-entities, braced sub/superscripts,
the startup options and spell checking, with the Mac's defaults. The iOS
editor turns spell checking on only when the setting is on.

Layout: unified · split

Sources/OrgApp/OrgPreferences.swift +9 −2
@@ -14,13 +14,20 @@ public enum OrgPreferences {
14 return settings 14 return settings
15 } 15 }
16 16
17 /// What commands run from the agenda and capture follow: logging and tags. 17 /// The editing options, as the Mac's Settings apply them.
18 public static func options(_ defaults: UserDefaults = .standard) -> EditingOptions { 18 public static func options(_ defaults: UserDefaults = .standard) -> EditingOptions {
19 var options = EditingOptions( 19 var options = EditingOptions(
20 tagsColumn: integer("tagsColumn", defaults), insertHeadingRespectContent: bool("headingAfterSubtree", defaults), 20 tagsColumn: integer("tagsColumn", defaults), insertHeadingRespectContent: bool("headingAfterSubtree", defaults),
21 metaReturnMaySplitLine: bool("splitLine", defaults),
21 listAllowAlphabetical: bool("alphabeticalLists", defaults), fillColumn: integer("fillColumn", defaults), 22 listAllowAlphabetical: bool("alphabeticalLists", defaults), fillColumn: integer("fillColumn", defaults),
23 hideEmphasisMarkers: bool("hiddenMarkers", defaults), prettyEntities: bool("prettyEntities", defaults), subSuperscriptsNeedBraces: true,
22 logDone: LogHow(rawValue: string("logDone", defaults)), logIntoDrawer: string("logIntoDrawer", defaults).nonEmpty, 24 logDone: LogHow(rawValue: string("logDone", defaults)), logIntoDrawer: string("logIntoDrawer", defaults).nonEmpty,
23 logReschedule: LogHow(rawValue: string("logReschedule", defaults)), logRedeadline: LogHow(rawValue: string("logRedeadline", defaults)) 25 hideDrawerStartup: bool("hideDrawerStartup", defaults), hideBlockStartup: bool("hideBlockStartup", defaults),
26 logReschedule: LogHow(rawValue: string("logReschedule", defaults)), logRedeadline: LogHow(rawValue: string("logRedeadline", defaults)),
27 useSpeedCommands: bool("useSpeedCommands", defaults), startupWithInlineImages: bool("startupWithInlineImages", defaults),
28 startupIndented: bool("startupIndented", defaults), hideLeadingStars: bool("hideLeadingStars", defaults),
29 startupAlignAllTables: bool("startupAlignAllTables", defaults), startupTruncated: bool("startupTruncated", defaults),
30 spellCheck: bool("spellCheck", defaults)
24 ) 31 )
25 options.electricPair = bool("electricPair", defaults) 32 options.electricPair = bool("electricPair", defaults)
26 return options 33 return options
Sources/OrgstarMobile/MobileEditor.swift +4 −2
@@ -54,7 +54,9 @@ final class KeyedTextView: UITextView {
54final class MobileEditor: NSObject, DocumentBuffer { 54final class MobileEditor: NSObject, DocumentBuffer {
55 private(set) var document: DocumentState 55 private(set) var document: DocumentState
56 let textView: UITextView 56 let textView: UITextView
57 var options: EditingOptions = .org 57 var options: EditingOptions = .org {
58 didSet { textView.spellCheckingType = options.spellCheck ? .yes : .no }
59 }
58 var keymap = KeymapPreset.emacs.keymap 60 var keymap = KeymapPreset.emacs.keymap
59 var onChange: (() -> Void)? 61 var onChange: (() -> Void)?
60 var onMessage: ((String) -> Void)? 62 var onMessage: ((String) -> Void)?
@@ -96,7 +98,7 @@ final class MobileEditor: NSObject, DocumentBuffer {
96 textView.smartQuotesType = .no 98 textView.smartQuotesType = .no
97 textView.smartDashesType = .no 99 textView.smartDashesType = .no
98 textView.smartInsertDeleteType = .no 100 textView.smartInsertDeleteType = .no
99 textView.spellCheckingType = .yes 101 textView.spellCheckingType = options.spellCheck ? .yes : .no
100 textView.keyboardDismissMode = .interactive 102 textView.keyboardDismissMode = .interactive
101 textView.alwaysBounceVertical = true 103 textView.alwaysBounceVertical = true
102 textView.textContainerInset = UIEdgeInsets(top: 12, left: 8, bottom: 24, right: 8) 104 textView.textContainerInset = UIEdgeInsets(top: 12, left: 8, bottom: 24, right: 8)
Tests/OrgAppTests/OrgPreferencesTests.swift +7
@@ -11,6 +11,9 @@ struct OrgPreferencesTests {
11 #expect(OrgPreferences.options(defaults).logDone == nil && OrgPreferences.options(defaults).tagsColumn == -77) 11 #expect(OrgPreferences.options(defaults).logDone == nil && OrgPreferences.options(defaults).tagsColumn == -77)
12 #expect(OrgPreferences.agendaSpan(defaults) == 10 && OrgPreferences.agendaStartOffset(defaults) == -3) 12 #expect(OrgPreferences.agendaSpan(defaults) == 10 && OrgPreferences.agendaStartOffset(defaults) == -3)
13 #expect(OrgPreferences.reminders(defaults) && OrgPreferences.reminderLead(defaults) == 12) 13 #expect(OrgPreferences.reminders(defaults) && OrgPreferences.reminderLead(defaults) == 12)
14 let fallbacks = OrgPreferences.options(defaults)
15 #expect(!fallbacks.metaReturnMaySplitLine && fallbacks.hideEmphasisMarkers && fallbacks.prettyEntities && fallbacks.subSuperscriptsNeedBraces)
16 #expect(fallbacks.startupIndented && !fallbacks.spellCheck && fallbacks.hideDrawerStartup && !fallbacks.hideBlockStartup)
14 17
15 let problems = UserConfig.apply(""" 18 let problems = UserConfig.apply("""
16 org-todo-keywords = "TODO NEXT | DONE" 19 org-todo-keywords = "TODO NEXT | DONE"
@@ -19,6 +22,9 @@ struct OrgPreferencesTests {
19 org-agenda-span = 7 22 org-agenda-span = 7
20 org-agenda-start-day = "-1d" 23 org-agenda-start-day = "-1d"
21 appt-message-warning-time = 30 24 appt-message-warning-time = 30
25 org-M-RET-may-split-line = true
26 org-hide-emphasis-markers = false
27 org-pretty-entities = false
22 [orgstar] 28 [orgstar]
23 reminders = false 29 reminders = false
24 """, to: defaults) 30 """, to: defaults)
@@ -26,6 +32,7 @@ struct OrgPreferencesTests {
26 #expect(OrgPreferences.orgSettings(defaults).todoSequences.first?.active.map(\.name) == ["TODO", "NEXT"]) 32 #expect(OrgPreferences.orgSettings(defaults).todoSequences.first?.active.map(\.name) == ["TODO", "NEXT"])
27 let options = OrgPreferences.options(defaults) 33 let options = OrgPreferences.options(defaults)
28 #expect(options.logDone == .time && options.logIntoDrawer == "LOGBOOK") 34 #expect(options.logDone == .time && options.logIntoDrawer == "LOGBOOK")
35 #expect(options.metaReturnMaySplitLine && !options.hideEmphasisMarkers && !options.prettyEntities)
29 #expect(OrgPreferences.agendaSpan(defaults) == 7 && OrgPreferences.agendaStartOffset(defaults) == -1) 36 #expect(OrgPreferences.agendaSpan(defaults) == 7 && OrgPreferences.agendaStartOffset(defaults) == -1)
30 #expect(!OrgPreferences.reminders(defaults) && OrgPreferences.reminderLead(defaults) == 30) 37 #expect(!OrgPreferences.reminders(defaults) && OrgPreferences.reminderLead(defaults) == 30)
31 } 38 }