@@ -2,6 +2,8 @@ import ActiveApplicationMonitor
22import AppKit
33import AXNotificationStream
44import Environment
5+ import Highlightr
6+ import Splash
57import SwiftUI
68import XPCShared
79
@@ -90,7 +92,13 @@ public final class SuggestionWidgetController {
9092 }
9193
9294 enum Suggestion {
93- case code( [ String ] , startLineIndex: Int , currentSuggestionIndex: Int , suggestionCount: Int )
95+ case code(
96+ String ,
97+ language: String ,
98+ startLineIndex: Int ,
99+ currentSuggestionIndex: Int ,
100+ suggestionCount: Int
101+ )
94102 }
95103
96104 public nonisolated init ( ) {
@@ -132,19 +140,21 @@ public final class SuggestionWidgetController {
132140
133141 public func suggestCode(
134142 _ code: String ,
143+ language: String ,
135144 startLineIndex: Int ,
136145 fileURL: URL ,
137146 currentSuggestionIndex: Int ,
138147 suggestionCount: Int
139148 ) {
140149 withAnimation ( . easeInOut( duration: 0.2 ) ) {
141- suggestionPanelViewModel. suggestion = code . split ( separator : " \n " ) . map ( String . init )
150+ suggestionPanelViewModel. suggestion = highlighted ( code : code , language : language )
142151 suggestionPanelViewModel. startLineIndex = startLineIndex
143152 suggestionPanelViewModel. isPanelDisplayed = true
144153 suggestionPanelViewModel. currentSuggestionIndex = currentSuggestionIndex
145154 suggestionPanelViewModel. suggestionCount = suggestionCount
146155 suggestionForFiles [ fileURL] = . code(
147- suggestionPanelViewModel. suggestion,
156+ code,
157+ language: language,
148158 startLineIndex: startLineIndex,
149159 currentSuggestionIndex: currentSuggestionIndex,
150160 suggestionCount: suggestionCount
@@ -194,8 +204,17 @@ public final class SuggestionWidgetController {
194204 continue
195205 }
196206 switch suggestion {
197- case let . code( code, startLineIndex, currentSuggestionIndex, suggestionCount) :
198- suggestionPanelViewModel. suggestion = code
207+ case let . code(
208+ code,
209+ language,
210+ startLineIndex,
211+ currentSuggestionIndex,
212+ suggestionCount
213+ ) :
214+ suggestionPanelViewModel. suggestion = highlighted (
215+ code: code,
216+ language: language
217+ )
199218 suggestionPanelViewModel. startLineIndex = startLineIndex
200219 suggestionPanelViewModel. currentSuggestionIndex = currentSuggestionIndex
201220 suggestionPanelViewModel. suggestionCount = suggestionCount
@@ -247,7 +266,10 @@ public final class SuggestionWidgetController {
247266 if foundSize, foundPosition, let screen, let firstScreen {
248267 let proposedAnchorFrameOnTheRightSide = CGRect (
249268 x: frame. maxX - Style. widgetPadding - Style. widgetWidth,
250- y: max ( firstScreen. frame. height - frame. maxY + Style. widgetPadding, 4 + screen. frame. minY) ,
269+ y: max (
270+ firstScreen. frame. height - frame. maxY + Style. widgetPadding,
271+ 4 + screen. frame. minY
272+ ) ,
251273 width: Style . widgetWidth,
252274 height: Style . widgetHeight
253275 )
@@ -312,3 +334,58 @@ public final class SuggestionWidgetController {
312334 hide ( )
313335 }
314336}
337+
338+ func highlighted( code: String , language: String ) -> [ NSAttributedString ] {
339+ switch language {
340+ case " swift " :
341+ let plainTextColor = #colorLiteral( red: 0.6509803922 , green: 0.6980392157 , blue: 0.7529411765 , alpha: 1 )
342+ let highlighter =
343+ SyntaxHighlighter (
344+ format: AttributedStringOutputFormat ( theme: . init(
345+ font: . init( size: 14 ) ,
346+ plainTextColor: plainTextColor,
347+ tokenColors: [
348+ . keyword: #colorLiteral( red: 0.8258609176 , green: 0.5708742738 , blue: 0.8922662139 , alpha: 1 ) ,
349+ . string: #colorLiteral( red: 0.6253595352 , green: 0.7963448763 , blue: 0.5427476764 , alpha: 1 ) ,
350+ . type: #colorLiteral( red: 0.9221783876 , green: 0.7978314757 , blue: 0.5575165749 , alpha: 1 ) ,
351+ . call: #colorLiteral( red: 0.4466812611 , green: 0.742190659 , blue: 0.9515134692 , alpha: 1 ) ,
352+ . number: #colorLiteral( red: 0.8620631099 , green: 0.6468816996 , blue: 0.4395158887 , alpha: 1 ) ,
353+ . comment: #colorLiteral( red: 0.4233166873 , green: 0.4612616301 , blue: 0.5093258619 , alpha: 1 ) ,
354+ . property: #colorLiteral( red: 0.906378448 , green: 0.5044228435 , blue: 0.5263597369 , alpha: 1 ) ,
355+ . dotAccess: #colorLiteral( red: 0.906378448 , green: 0.5044228435 , blue: 0.5263597369 , alpha: 1 ) ,
356+ . preprocessing: #colorLiteral( red: 0.3776347041 , green: 0.8792117238 , blue: 0.4709561467 , alpha: 1 ) ,
357+ ]
358+ ) )
359+ )
360+ let formatted = NSMutableAttributedString ( attributedString: highlighter. highlight ( code) )
361+ formatted. addAttributes (
362+ [ . font: NSFont . monospacedSystemFont ( ofSize: 13 , weight: . regular) ] ,
363+ range: NSRange ( location: 0 , length: formatted. length)
364+ )
365+ return splitAttributedString ( formatted)
366+ default :
367+ guard let highlighter = Highlightr ( ) else {
368+ return splitAttributedString ( NSAttributedString ( string: code) )
369+ }
370+ highlighter. setTheme ( to: " atom-one-dark " )
371+ highlighter. theme. setCodeFont ( . monospacedSystemFont( ofSize: 13 , weight: . regular) )
372+ guard let formatted = highlighter. highlight ( code, as: " swift " ) else {
373+ return splitAttributedString ( NSAttributedString ( string: code) )
374+ }
375+ return splitAttributedString ( formatted)
376+ }
377+ }
378+
379+ func splitAttributedString( _ inputString: NSAttributedString ) -> [ NSAttributedString ] {
380+ let input = inputString. string
381+ let separatedInput = input. components ( separatedBy: " \n " )
382+ var output = [ NSAttributedString] ( )
383+ var start = 0
384+ for sub in separatedInput {
385+ let range = NSMakeRange ( start, sub. utf16. count)
386+ let attributedString = inputString. attributedSubstring ( from: range)
387+ output. append ( attributedString)
388+ start += range. length + 1
389+ }
390+ return output
391+ }
0 commit comments