77
88import SwiftUI
99
10- /// A collection of `NSColor` used for syntax higlighting
11- public struct EditorTheme {
10+ /// A collection of attributes used for syntax highlighting and other colors for the editor.
11+ ///
12+ /// Attributes of a theme that do not apply to text (background, line highlight) are a single `NSColor` for simplicity.
13+ /// All other attributes use the ``EditorTheme/Attribute`` type to store
14+ public struct EditorTheme : Equatable {
15+ /// Represents attributes that can be applied to style text.
16+ public struct Attribute : Equatable , Hashable , Sendable {
17+ let color : NSColor
18+ let bold : Bool
19+ let italic : Bool
1220
13- public var text : NSColor
21+ public init ( color: NSColor , bold: Bool = false , italic: Bool = false ) {
22+ self . color = color
23+ self . bold = bold
24+ self . italic = italic
25+ }
26+
27+ var fontDescriptorTraits : NSFontDescriptor . SymbolicTraits {
28+ switch ( bold, italic) {
29+ case ( true , true ) : return [ . bold, . italic]
30+ case ( true , false ) : return [ . bold]
31+ case ( false , true ) : return [ . italic]
32+ case ( false , false ) : return [ ]
33+ }
34+ }
35+ }
36+
37+ public var text : Attribute
1438 public var insertionPoint : NSColor
15- public var invisibles : NSColor
39+ public var invisibles : Attribute
1640 public var background : NSColor
1741 public var lineHighlight : NSColor
1842 public var selection : NSColor
19- public var keywords : NSColor
20- public var commands : NSColor
21- public var types : NSColor
22- public var attributes : NSColor
23- public var variables : NSColor
24- public var values : NSColor
25- public var numbers : NSColor
26- public var strings : NSColor
27- public var characters : NSColor
28- public var comments : NSColor
43+ public var keywords : Attribute
44+ public var commands : Attribute
45+ public var types : Attribute
46+ public var attributes : Attribute
47+ public var variables : Attribute
48+ public var values : Attribute
49+ public var numbers : Attribute
50+ public var strings : Attribute
51+ public var characters : Attribute
52+ public var comments : Attribute
2953
3054 public init (
31- text: NSColor ,
55+ text: Attribute ,
3256 insertionPoint: NSColor ,
33- invisibles: NSColor ,
57+ invisibles: Attribute ,
3458 background: NSColor ,
3559 lineHighlight: NSColor ,
3660 selection: NSColor ,
37- keywords: NSColor ,
38- commands: NSColor ,
39- types: NSColor ,
40- attributes: NSColor ,
41- variables: NSColor ,
42- values: NSColor ,
43- numbers: NSColor ,
44- strings: NSColor ,
45- characters: NSColor ,
46- comments: NSColor
61+ keywords: Attribute ,
62+ commands: Attribute ,
63+ types: Attribute ,
64+ attributes: Attribute ,
65+ variables: Attribute ,
66+ values: Attribute ,
67+ numbers: Attribute ,
68+ strings: Attribute ,
69+ characters: Attribute ,
70+ comments: Attribute
4771 ) {
4872 self . text = text
4973 self . insertionPoint = insertionPoint
@@ -63,10 +87,10 @@ public struct EditorTheme {
6387 self . comments = comments
6488 }
6589
66- /// Get the color from ``theme`` for the specified capture name .
67- /// - Parameter capture: The capture name
68- /// - Returns: A `NSColor`
69- func colorFor ( _ capture: CaptureName ? ) -> NSColor {
90+ /// Maps a capture type to the attributes for that capture determined by the theme .
91+ /// - Parameter capture: The capture to map to.
92+ /// - Returns: Theme attributes for the capture.
93+ private func mapCapture ( _ capture: CaptureName ? ) -> Attribute {
7094 switch capture {
7195 case . include, . constructor, . keyword, . boolean, . variableBuiltin,
7296 . keywordReturn, . keywordFunction, . repeat , . conditional, . tag:
@@ -82,25 +106,26 @@ public struct EditorTheme {
82106 default : return text
83107 }
84108 }
85- }
86109
87- extension EditorTheme : Equatable {
88- public static func == ( lhs: EditorTheme , rhs: EditorTheme ) -> Bool {
89- return lhs. text == rhs. text &&
90- lhs. insertionPoint == rhs. insertionPoint &&
91- lhs. invisibles == rhs. invisibles &&
92- lhs. background == rhs. background &&
93- lhs. lineHighlight == rhs. lineHighlight &&
94- lhs. selection == rhs. selection &&
95- lhs. keywords == rhs. keywords &&
96- lhs. commands == rhs. commands &&
97- lhs. types == rhs. types &&
98- lhs. attributes == rhs. attributes &&
99- lhs. variables == rhs. variables &&
100- lhs. values == rhs. values &&
101- lhs. numbers == rhs. numbers &&
102- lhs. strings == rhs. strings &&
103- lhs. characters == rhs. characters &&
104- lhs. comments == rhs. comments
110+ /// Get the color from ``theme`` for the specified capture name.
111+ /// - Parameter capture: The capture name
112+ /// - Returns: A `NSColor`
113+ func colorFor( _ capture: CaptureName ? ) -> NSColor {
114+ return mapCapture ( capture) . color
115+ }
116+
117+ /// Returns the correct font with attributes (bold and italics) for a given capture name.
118+ /// - Parameters:
119+ /// - capture: The capture name.
120+ /// - font: The font to add attributes to.
121+ /// - Returns: A new font that has the correct attributes for the capture.
122+ func fontFor( for capture: CaptureName ? , from font: NSFont ) -> NSFont {
123+ let attributes = mapCapture ( capture)
124+ guard attributes. bold || attributes. italic else {
125+ return font
126+ }
127+
128+ let descriptor = font. fontDescriptor. withSymbolicTraits ( attributes. fontDescriptorTraits)
129+ return NSFont ( descriptor: descriptor, size: font. pointSize) ?? font
105130 }
106131}
0 commit comments