Skip to content

Commit

Permalink
RangeState and new TreeSitterClient
Browse files Browse the repository at this point in the history
  • Loading branch information
mattmassicotte committed Jan 17, 2024
1 parent 7df7d08 commit d9fa43e
Show file tree
Hide file tree
Showing 36 changed files with 2,341 additions and 1,781 deletions.
3 changes: 1 addition & 2 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/ChimeHQ/SwiftTreeSitter",
"state" : {
"revision" : "2599e95310b3159641469d8a21baf2d3d200e61f",
"version" : "0.8.0"
"revision" : "87ed52a71d4ad6b5e6a11185b42f6f74eb5b47da"
}
}
],
Expand Down
50 changes: 39 additions & 11 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,55 @@ import PackageDescription

let package = Package(
name: "Neon",
platforms: [.macOS(.v10_13), .iOS(.v11), .tvOS(.v11), .watchOS(.v5)],
platforms: [.macOS(.v10_15), .iOS(.v13), .tvOS(.v13), .watchOS(.v6)],
products: [
.library(name: "Neon", targets: ["Neon"]),
],
dependencies: [
.package(url: "https://github.com/ChimeHQ/SwiftTreeSitter", from: "0.8.0"),
.package(url: "https://github.com/ChimeHQ/SwiftTreeSitter", revision: "87ed52a71d4ad6b5e6a11185b42f6f74eb5b47da"),
.package(url: "https://github.com/ChimeHQ/Rearrange", from: "1.6.0"),
],
targets: [
.target(name: "ConcurrencyCompatibility"),
.target(name: "RangeState", dependencies: ["ConcurrencyCompatibility", "Rearrange"]),
.target(
name: "Neon",
dependencies: ["SwiftTreeSitter", "Rearrange", "TreeSitterClient"],
swiftSettings: [.enableExperimentalFeature("StrictConcurrency")]
dependencies: [
"ConcurrencyCompatibility",
"RangeState",
"Rearrange",
"TreeSitterClient",
.product(name: "SwiftTreeSitterLayer", package: "SwiftTreeSitter"),
]
),
.target(
name: "TreeSitterClient",
dependencies: [
"ConcurrencyCompatibility",
"RangeState",
"Rearrange",
"SwiftTreeSitter",
.product(name: "SwiftTreeSitterLayer", package: "SwiftTreeSitter"),
]
),
.target(
name: "NeonTestsTreeSitterSwift",
path: "tree-sitter-swift",
sources: ["src/parser.c", "src/scanner.c"],
publicHeadersPath: "bindings/swift",
cSettings: [.headerSearchPath("src")]
),
.target(name: "TreeSitterClient", dependencies: ["Rearrange", "SwiftTreeSitter"]),
.target(name: "TestTreeSitterSwift",
path: "tree-sitter-swift",
sources: ["src/parser.c", "src/scanner.c"],
publicHeadersPath: "bindings/swift",
cSettings: [.headerSearchPath("src")]),
.testTarget(name: "NeonTests", dependencies: ["Neon"]),
.testTarget(name: "TreeSitterClientTests", dependencies: ["TreeSitterClient", "TestTreeSitterSwift"])
.testTarget(name: "TreeSitterClientTests", dependencies: ["TreeSitterClient", "NeonTestsTreeSitterSwift"])
]
)

let swiftSettings: [SwiftSetting] = [
.enableExperimentalFeature("StrictConcurrency")
]

for target in package.targets {
var settings = target.swiftSettings ?? []
settings.append(contentsOf: swiftSettings)
target.swiftSettings = settings
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,16 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/ChimeHQ/Rearrange",
"state" : {
"revision" : "8f97f721d8a08c6e01ab9f7460e53819bef72dfa",
"version" : "1.5.3"
"revision" : "0fb658e721c68495f6340c211cc6d4719e6b52d8",
"version" : "1.6.0"
}
},
{
"identity" : "swifttreesitter",
"kind" : "remoteSourceControl",
"location" : "https://github.com/ChimeHQ/SwiftTreeSitter",
"state" : {
"revision" : "df25a52f72ebc5b50ae20d26d1363793408bb28b",
"version" : "0.7.1"
"revision" : "87ed52a71d4ad6b5e6a11185b42f6f74eb5b47da"
}
},
{
Expand Down
80 changes: 63 additions & 17 deletions Projects/NeonExample/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Cocoa
import Neon
import SwiftTreeSitter
import TreeSitterSwift
import TreeSitterClient

final class ViewController: NSViewController {
let textView: NSTextView
Expand All @@ -12,6 +13,12 @@ final class ViewController: NSViewController {
self.textView = NSTextView()
textView.isRichText = false // Discards any attributes when pasting.

textView.string = """
// Example Code!
let value = "hello world"
print(value)
"""

scrollView.documentView = textView

let regularFont = NSFont.monospacedSystemFont(ofSize: 16, weight: .regular)
Expand All @@ -35,19 +42,18 @@ final class ViewController: NSViewController {
}
}

let language = Language(language: tree_sitter_swift())
let languageConfig = try! LanguageConfiguration(
tree_sitter_swift(),
name: "Swift"
)

let url = Bundle.main
.resourceURL?
.appendingPathComponent("TreeSitterSwift_TreeSitterSwift.bundle")
.appendingPathComponent("Contents/Resources/queries/highlights.scm")
let query = try! language.query(contentsOf: url!)
let highlighterConfig = TextViewHighlighter.Configuration(
languageConfiguration: languageConfig,
attributeProvider: provider,
locationTransformer: { _ in nil }
)

let interface = TextStorageSystemInterface(textView: textView, attributeProvider: provider)
self.highlighter = try! TextViewHighlighter(textView: textView,
language: language,
highlightQuery: query,
interface: interface)
self.highlighter = try! TextViewHighlighter(textView: textView, configuration: highlighterConfig)

super.init(nibName: nil, bundle: nil)
}
Expand All @@ -68,11 +74,51 @@ final class ViewController: NSViewController {
self.view = scrollView
}

override func viewWillAppear() {
textView.string = """
// Example Code!
let value = "hello world"
print(value)
"""
func setUpTreeSitter() throws {
let languageConfig = try LanguageConfiguration(
tree_sitter_swift(),
name: "Swift"
)

let clientConfig = TreeSitterClient.Configuration(
languageProvider: { identifier in
// look up nested languages by identifier here. If done
// asynchronously, inform the client they are ready with
// `languageConfigurationChanged(for:)`
return nil
},
contentProvider: { [textView] length in
// given a maximum needed length, produce a Content structure
// that will be used to access the text data

return .init(string: textView.string)
},
lengthProvider: { [textView] in
textView.string.utf16.count

},
invalidationHandler: { set in
// take action on invalidated regions of the text
},
locationTransformer: { location in
// optionally, use the UTF-16 location to produce a line-relative Point structure.
return nil
}
)

let client = try TreeSitterClient(
rootLanguageConfig: languageConfig,
configuration: clientConfig
)

let source = textView.string

let provider = source.predicateTextProvider

// this uses the synchronous query API, but with the `.required` mode, which will force the client
// to do all processing necessary to satsify the request.
let highlights = try client.highlights(in: NSRange(0..<24), provider: provider, mode: .required)!

print("highlights:", highlights)
}
}
Loading

0 comments on commit d9fa43e

Please sign in to comment.