From 709683a2e2f3a2e502e8383f9aa5c725bf7d85e6 Mon Sep 17 00:00:00 2001 From: Matt <85322+mattmassicotte@users.noreply.github.com> Date: Tue, 14 May 2024 14:33:17 -0400 Subject: [PATCH] static highlighting --- README.md | 21 ++++++++++ Sources/Neon/PlatformTextSystem.swift | 2 + Sources/Neon/TreeSitterClient+Neon.swift | 42 +++++++++++++++++++ .../TextViewSystemInterfaceTests.swift | 3 -- 4 files changed, 65 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6bcea6d..1201053 100644 --- a/README.md +++ b/README.md @@ -174,6 +174,27 @@ let highlights = try client.highlights(in: NSRange(0..<24), provider: provider, print("highlights:", highlights) ``` +TreeSitterClient can also perform static highlighting. This can be handy for applying style to a string. + +```swift +let languageConfig = try LanguageConfiguration( + tree_sitter_swift(), + name: "Swift" +) + +let attrProvider: TokenAttributeProvider = { token in + return [.foregroundColor: NSColor.red] +} + +// produce an AttributedString +let highlightedSource = try await TreeSitterClient.highlight( + string: source, + attributeProvider: attrProvider, + rootLanguageConfig: languageConfig, + languageProvider: { _ in nil } +) +``` + ## Contributing and Collaboration I would love to hear from you! Issues or pull requests work great. A [Discord server][discord] is also available for live help, but I have a strong bias towards answering in the form of documentation. diff --git a/Sources/Neon/PlatformTextSystem.swift b/Sources/Neon/PlatformTextSystem.swift index 0962137..48574ed 100644 --- a/Sources/Neon/PlatformTextSystem.swift +++ b/Sources/Neon/PlatformTextSystem.swift @@ -6,10 +6,12 @@ import RangeState import AppKit public typealias TextView = NSTextView +typealias PlatformColor = NSColor #elseif os(iOS) || os(visionOS) import UIKit public typealias TextView = UITextView +typealias PlatformColor = UIColor #endif #if os(macOS) || os(iOS) || os(visionOS) diff --git a/Sources/Neon/TreeSitterClient+Neon.swift b/Sources/Neon/TreeSitterClient+Neon.swift index a0d4931..29829df 100644 --- a/Sources/Neon/TreeSitterClient+Neon.swift +++ b/Sources/Neon/TreeSitterClient+Neon.swift @@ -66,3 +66,45 @@ extension TextViewSystemInterface { } } #endif + +@available(macOS 12, *) +extension TreeSitterClient { + /// Highlight an input string. + public static func highlight( + string: String, + attributeProvider: TokenAttributeProvider, + rootLanguageConfig: LanguageConfiguration, + languageProvider: @escaping LanguageLayer.LanguageProvider + ) async throws -> AttributedString { + let content = LanguageLayer.Content(string: string) + let length = string.utf16.count + + let client = try TreeSitterClient( + rootLanguageConfig: rootLanguageConfig, + configuration: Configuration( + languageProvider: languageProvider, + contentProvider: { _ in content }, + lengthProvider: { length }, + invalidationHandler: { _ in }, + locationTransformer: { _ in nil } + ) + ) + + client.didChangeContent(in: NSRange(0..<0), delta: length) + + let ranges = try await client.highlights(in: NSRange(0..(token.range, in: attributedString) else { continue } + + attributedString[strRange].foregroundColor = attrs[.foregroundColor] as? PlatformColor + } + + return attributedString + } +} + diff --git a/Tests/NeonTests/TextViewSystemInterfaceTests.swift b/Tests/NeonTests/TextViewSystemInterfaceTests.swift index 0160c5c..33bf815 100644 --- a/Tests/NeonTests/TextViewSystemInterfaceTests.swift +++ b/Tests/NeonTests/TextViewSystemInterfaceTests.swift @@ -4,8 +4,6 @@ import XCTest #if os(macOS) import AppKit -typealias PlatformColor = NSColor - extension NSTextView { var text: String { get { return string } @@ -31,7 +29,6 @@ extension NSTextView { #elseif os(iOS) import UIKit -typealias PlatformColor = UIColor #endif //final class TextViewSystemInterfaceTests: XCTestCase {