summaryrefslogtreecommitdiff
path: root/Hutch/Views/Repositories/FileTreeView.swift
diff options
context:
space:
mode:
authorChristian Cleberg <[email protected]>2026-08-07 02:52:03 -0500
committerGitHub <[email protected]>2026-08-07 02:52:03 -0500
commit044c33f7f43db1f38d6c44dd8f483298d9efcc06 (patch)
tree649488b2e5d3d901db8c792c0dc215c835fa9d38 /Hutch/Views/Repositories/FileTreeView.swift
parent0a3e55c15cfb9ce1bd3df0c7b352760bc2ee33c3 (diff)
parentb410fd16b76146f4116538c5b82330818dd47da9 (diff)
downloadhutch-044c33f7f43db1f38d6c44dd8f483298d9efcc06.tar.gz
hutch-044c33f7f43db1f38d6c44dd8f483298d9efcc06.tar.bz2
hutch-044c33f7f43db1f38d6c44dd8f483298d9efcc06.zip
Merge pull request #30 from krazywarez/syntax-highlighting
Add multi-language syntax highlighting (#16)
Diffstat (limited to 'Hutch/Views/Repositories/FileTreeView.swift')
-rw-r--r--Hutch/Views/Repositories/FileTreeView.swift49
1 files changed, 32 insertions, 17 deletions
diff --git a/Hutch/Views/Repositories/FileTreeView.swift b/Hutch/Views/Repositories/FileTreeView.swift
index 7bfce17..13f72b8 100644
--- a/Hutch/Views/Repositories/FileTreeView.swift
+++ b/Hutch/Views/Repositories/FileTreeView.swift
@@ -456,12 +456,19 @@ final class CodeFileUIView: UIView {
private var wrapLines: Bool
private var needsLineLayoutUpdate = true
private var lastMeasuredCodeWidth: CGFloat = 0
+ private var syntaxHighlighter: SyntaxHighlighter?
+ private var syntaxHighlighterTheme: SyntaxHighlightTheme?
init(text: String, fileName: String, font: UIFont, wrapLines: Bool) {
self.currentFont = font
self.wrapLines = wrapLines
super.init(frame: .zero)
setupViews()
+ registerForTraitChanges([UITraitUserInterfaceStyle.self]) { (view: CodeFileUIView, _: UITraitCollection) in
+ view.rebuildRows()
+ view.needsLineLayoutUpdate = true
+ view.setNeedsLayout()
+ }
updateContent(text: text, fileName: fileName, font: font, wrapLines: wrapLines)
}
@@ -583,11 +590,7 @@ final class CodeFileUIView: UIView {
}
rows.removeAll()
- let attributedText = CodeSyntaxHighlighter.attributedText(
- for: currentText,
- fileName: currentFileName,
- font: currentFont
- )
+ let attributedText = highlightedAttributedText()
let lines = makeLines(from: attributedText, font: currentFont)
gutterWidthConstraint?.constant = Self.gutterWidth(lineCount: lines.count, font: currentFont)
@@ -600,6 +603,30 @@ final class CodeFileUIView: UIView {
}
}
+ /// Highlighting cap: above this size, skip tokenizing to keep the main
+ /// thread responsive and render plain, label-colored text instead.
+ private static let maxHighlightableLength = 100_000
+
+ private func highlightedAttributedText() -> NSAttributedString {
+ let plain = NSAttributedString(
+ string: currentText,
+ attributes: [.font: currentFont, .foregroundColor: UIColor.label]
+ )
+
+ guard currentText.count <= Self.maxHighlightableLength,
+ let language = SyntaxHighlighter.language(forFileName: currentFileName) else {
+ return plain
+ }
+
+ let theme = SyntaxHighlightTheme(userInterfaceStyle: traitCollection.userInterfaceStyle)
+ if syntaxHighlighterTheme != theme || syntaxHighlighter == nil {
+ syntaxHighlighter = SyntaxHighlighter(theme: theme)
+ syntaxHighlighterTheme = theme
+ }
+
+ return syntaxHighlighter?.attributedText(for: currentText, language: language, font: currentFont) ?? plain
+ }
+
private func makeRow(for line: CodeFileLineData) -> LineRow {
let row = LineRow()
@@ -737,18 +764,6 @@ private struct CodeFileLineData {
let text: NSAttributedString
}
-private enum CodeSyntaxHighlighter {
- static func attributedText(for text: String, fileName _: String, font: UIFont) -> NSAttributedString {
- NSAttributedString(
- string: text,
- attributes: [
- .font: font,
- .foregroundColor: UIColor.label
- ]
- )
- }
-}
-
// MARK: - Tree Entry Row
private struct TreeEntryRow: View {