aboutsummaryrefslogtreecommitdiff
path: root/QuickLook/QuickLookTextEditor.swift
blob: 0501f6bf89deaff6fb900f6ac8b29e224f0e5ad4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
import SwiftUI
import TreeSitterWmap
import SwiftTreeSitter
import SwiftTreeSitterLayer

struct QuickLookTextEditor: NSViewRepresentable {
  let content: String

  func makeNSView(context: Context) -> NSScrollView {
    let scrollView = NSTextView.scrollableTextView()
    let textView = scrollView.documentView as! NSTextView

    // Configure the scroll view
    scrollView.hasVerticalScroller = true
    scrollView.hasHorizontalScroller = true
    scrollView.autohidesScrollers = false

    // Configure the text view for read-only display
    textView.isEditable = false
    textView.isSelectable = true
    textView.backgroundColor = NSColor.textBackgroundColor
    textView.font = NSFont.monospacedSystemFont(ofSize: 13, weight: .regular)
    textView.string = content
    textView.isVerticallyResizable = true
    textView.isHorizontallyResizable = true
    textView.textContainer?.widthTracksTextView = false
    textView.textContainer?.containerSize = NSSize(
      width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude)

    // Apply syntax highlighting using tree-sitter
    if let textStorage = textView.textStorage {
      applyTreeSitterHighlighting(textStorage: textStorage, content: content)
    }

    return scrollView
  }

  func updateNSView(_ nsView: NSScrollView, context: Context) {
    // No updates needed for read-only view
  }

  private func applyTreeSitterHighlighting(textStorage: NSTextStorage, content: String) {
    // Set up tree-sitter language layer
    guard let wmapConfiguration = try? LanguageConfiguration(tree_sitter_wmap(), name: "wmap")
    else { return }

    let languageConfiguration = LanguageLayer.Configuration(languageProvider: { name in
      switch name {
      case "wmap": return wmapConfiguration
      default: return nil
      }
    })

    guard
      let rootLayer = try? LanguageLayer(
        languageConfig: wmapConfiguration, configuration: languageConfiguration)
    else { return }

    // Update layer with content
    rootLayer.replaceContent(with: content)

    // Set default text color
    let fullRange = NSRange(location: 0, length: textStorage.length)
    textStorage.addAttribute(.foregroundColor, value: NSColor.textColor, range: fullRange)

    // Apply tree-sitter highlighting
    guard
      let highlights = try? rootLayer.highlights(
        in: fullRange, provider: content.predicateTextProvider)
    else { return }

    for highlight in highlights {
      let color = NSColor.Theme.Syntax.colorForSyntax(highlight.name)
      textStorage.addAttribute(.foregroundColor, value: color, range: highlight.range)
    }
  }

}