Skip to content

Commit 8d3f253

Browse files
committed
Remove @mainactor from CodeBlockHighlighter/Theme for background rendering, cache isDark
1 parent 265c238 commit 8d3f253

File tree

5 files changed

+25
-20
lines changed

5 files changed

+25
-20
lines changed

Sources/AgentColorSyntax/CodeBlockLangDef.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import AppKit
22

33
// MARK: - Language Definition
44

5-
public struct LangDef {
5+
public struct LangDef: @unchecked Sendable {
66
public let keywords: Set<String>
77
public let declKeywords: Set<String>
88
public let types: Set<String>

Sources/AgentColorSyntax/CodeBlockSyntax+Diff.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ extension CodeBlockHighlighter {
1111
let result = NSMutableAttributedString(string: code, attributes: [
1212
.font: font, .foregroundColor: text
1313
])
14-
let isDark = NSApp.effectiveAppearance.bestMatch(from: [.darkAqua, .aqua]) == .darkAqua
14+
let isDark = CodeBlockTheme.isDark
1515

1616
let removedBg = isDark
1717
? NSColor(red: 0.4, green: 0.1, blue: 0.1, alpha: 1.0) // dark red

Sources/AgentColorSyntax/CodeBlockSyntax+PathColor.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,22 @@ extension CodeBlockHighlighter {
66

77
// Path segment colors for multi-color file path highlighting
88
public static var pathHome: NSColor {
9-
NSApp.effectiveAppearance.bestMatch(from: [.darkAqua, .aqua]) == .darkAqua
9+
CodeBlockTheme.isDark
1010
? NSColor(red: 0.5, green: 0.5, blue: 0.55, alpha: 1) // dim gray
1111
: NSColor(red: 0.45, green: 0.45, blue: 0.5, alpha: 1)
1212
}
1313
public static var pathTopDir: NSColor {
14-
NSApp.effectiveAppearance.bestMatch(from: [.darkAqua, .aqua]) == .darkAqua
14+
CodeBlockTheme.isDark
1515
? NSColor(red: 0.6, green: 0.75, blue: 0.55, alpha: 1) // muted green
1616
: NSColor(red: 0.3, green: 0.5, blue: 0.25, alpha: 1)
1717
}
1818
public static var pathMiddle: NSColor {
19-
NSApp.effectiveAppearance.bestMatch(from: [.darkAqua, .aqua]) == .darkAqua
19+
CodeBlockTheme.isDark
2020
? NSColor(red: 0.816, green: 0.659, blue: 1.0, alpha: 1) // lavender
2121
: NSColor(red: 0.4, green: 0.2, blue: 0.7, alpha: 1)
2222
}
2323
public static var pathFilename: NSColor {
24-
NSApp.effectiveAppearance.bestMatch(from: [.darkAqua, .aqua]) == .darkAqua
24+
CodeBlockTheme.isDark
2525
? NSColor(red: 0.35, green: 0.7, blue: 1.0, alpha: 1) // bright blue
2626
: NSColor(red: 0.0, green: 0.3, blue: 0.8, alpha: 1)
2727
}

Sources/AgentColorSyntax/CodeBlockSyntax.swift

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import AppKit
22

33
// MARK: - Highlighter
44

5-
@MainActor public enum CodeBlockHighlighter {
5+
public enum CodeBlockHighlighter: Sendable {
66
private static let wordRx: NSRegularExpression? = try? NSRegularExpression(pattern: #"\b(?:[a-zA-Z][a-zA-Z0-9_]*|_[a-zA-Z0-9][a-zA-Z0-9_]*)\b"#)
77
private static let funcRx: NSRegularExpression? = try? NSRegularExpression(pattern: #"\b([a-zA-Z_][a-zA-Z0-9_]*)\s*(?=\()"#)
88
private static let propRx: NSRegularExpression? = try? NSRegularExpression(pattern: #"\.([a-zA-Z_][a-zA-Z0-9_]*)"#)
@@ -516,42 +516,42 @@ import AppKit
516516

517517
// Terminal output theme colors
518518
private static var termDir: NSColor {
519-
NSApp.effectiveAppearance.bestMatch(from: [.darkAqua, .aqua]) == .darkAqua
519+
CodeBlockTheme.isDark
520520
? NSColor(red: 0.35, green: 0.7, blue: 1.0, alpha: 1) // bright blue
521521
: NSColor(red: 0.0, green: 0.3, blue: 0.8, alpha: 1)
522522
}
523523
private static var termExec: NSColor {
524-
NSApp.effectiveAppearance.bestMatch(from: [.darkAqua, .aqua]) == .darkAqua
524+
CodeBlockTheme.isDark
525525
? NSColor(red: 0.4, green: 0.9, blue: 0.4, alpha: 1) // green
526526
: NSColor(red: 0.0, green: 0.5, blue: 0.0, alpha: 1)
527527
}
528528
private static var termSymlink: NSColor {
529-
NSApp.effectiveAppearance.bestMatch(from: [.darkAqua, .aqua]) == .darkAqua
529+
CodeBlockTheme.isDark
530530
? NSColor(red: 0.9, green: 0.5, blue: 0.9, alpha: 1) // magenta
531531
: NSColor(red: 0.6, green: 0.0, blue: 0.6, alpha: 1)
532532
}
533533
private static var termSize: NSColor {
534-
NSApp.effectiveAppearance.bestMatch(from: [.darkAqua, .aqua]) == .darkAqua
534+
CodeBlockTheme.isDark
535535
? NSColor(red: 0.85, green: 0.85, blue: 0.5, alpha: 1) // yellow
536536
: NSColor(red: 0.5, green: 0.4, blue: 0.0, alpha: 1)
537537
}
538538
private static var termDate: NSColor {
539-
NSApp.effectiveAppearance.bestMatch(from: [.darkAqua, .aqua]) == .darkAqua
539+
CodeBlockTheme.isDark
540540
? NSColor(red: 0.6, green: 0.6, blue: 0.7, alpha: 1) // dim
541541
: NSColor(red: 0.4, green: 0.4, blue: 0.5, alpha: 1)
542542
}
543543
private static var termPerm: NSColor {
544-
NSApp.effectiveAppearance.bestMatch(from: [.darkAqua, .aqua]) == .darkAqua
544+
CodeBlockTheme.isDark
545545
? NSColor(red: 0.6, green: 0.7, blue: 0.6, alpha: 1) // muted green
546546
: NSColor(red: 0.3, green: 0.4, blue: 0.3, alpha: 1)
547547
}
548548
private static var termPath: NSColor {
549-
NSApp.effectiveAppearance.bestMatch(from: [.darkAqua, .aqua]) == .darkAqua
549+
CodeBlockTheme.isDark
550550
? NSColor(red: 0.4, green: 0.85, blue: 0.85, alpha: 1) // cyan
551551
: NSColor(red: 0.0, green: 0.5, blue: 0.5, alpha: 1)
552552
}
553553
private static var termError: NSColor {
554-
NSApp.effectiveAppearance.bestMatch(from: [.darkAqua, .aqua]) == .darkAqua
554+
CodeBlockTheme.isDark
555555
? NSColor(red: 1.0, green: 0.4, blue: 0.4, alpha: 1) // red
556556
: NSColor(red: 0.8, green: 0.0, blue: 0.0, alpha: 1)
557557
}
@@ -565,7 +565,7 @@ import AppKit
565565
private static let termErrorRx: NSRegularExpression? = try? NSRegularExpression(pattern: #"\b(?:error|Error|ERROR|fatal|FATAL|failed|FAILED|No such file|Permission denied|not found|cannot)\b"#)
566566
private static let termWarningRx: NSRegularExpression? = try? NSRegularExpression(pattern: #"\b(?:warning|Warning|WARNING|deprecated|DEPRECATED|caution)\b"#)
567567
private static var termWarning: NSColor {
568-
NSApp.effectiveAppearance.bestMatch(from: [.darkAqua, .aqua]) == .darkAqua
568+
CodeBlockTheme.isDark
569569
? NSColor(red: 1.0, green: 0.8, blue: 0.2, alpha: 1) // yellow
570570
: NSColor(red: 0.7, green: 0.5, blue: 0.0, alpha: 1)
571571
}
@@ -655,7 +655,7 @@ import AppKit
655655

656656
/// Highlight a D1F diff line: background stripe for the diff marker, code syntax for the text.
657657
private static func highlightD1FLine(line: String, font: NSFont) -> NSAttributedString {
658-
let isDark = NSApp.effectiveAppearance.bestMatch(from: [.darkAqua, .aqua]) == .darkAqua
658+
let isDark = CodeBlockTheme.isDark
659659
let trimmed = line.trimmingCharacters(in: .whitespaces)
660660

661661
// Strip emoji prefix to get the code content for syntax highlighting

Sources/AgentColorSyntax/CodeBlockTheme.swift

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,16 @@ import AppKit
22

33
// MARK: - Code Block Theme (Xcode Dark/Light palette from JibberJabber)
44

5-
@MainActor public enum CodeBlockTheme {
6-
private static var isDark: Bool {
7-
NSApp.effectiveAppearance.bestMatch(from: [.darkAqua, .aqua]) == .darkAqua
5+
public enum CodeBlockTheme: Sendable {
6+
private nonisolated(unsafe) static var _isDark: Bool = false
7+
8+
/// Call from main thread on launch and appearance changes to cache dark mode state.
9+
@MainActor public static func updateAppearance() {
10+
_isDark = NSApp.effectiveAppearance.bestMatch(from: [.darkAqua, .aqua]) == .darkAqua
811
}
912

13+
public static var isDark: Bool { _isDark }
14+
1015
private static func c(_ d: UInt32, _ l: UInt32) -> NSColor {
1116
let h = isDark ? d : l
1217
return NSColor(

0 commit comments

Comments
 (0)