~ knotless Search/
↑↓ move↵ open⇧↵ all results

johnandersen777.bsky.social/knotless

git that lives in your Atmosphere account

Forked from chadtmiller.com/knotless

0
0
67 lines · 3.0 KB Raw History
import SwiftUI

/// Paints the ranges the server gives: `name:start,length,…;…`, each start
/// counted from the end of the one before, over lines taken as joined by
/// newlines, in UTF-16 units as the pages read them (`web/src/lib/highlight.ts`).
enum Highlight {
    private static let colors: [String: Color] = [
        "comment": Color(themed: { $0.syntax["comment"] ?? 0 }, light: 0x59636e, dark: 0x9198a1),
        "string": Color(themed: { $0.syntax["string"] ?? 0 }, light: 0x0a3069, dark: 0xa5d6ff),
        "keyword": Color(themed: { $0.syntax["keyword"] ?? 0 }, light: 0xcf222e, dark: 0xff7b72),
        "number": Color(themed: { $0.syntax["number"] ?? 0 }, light: 0x0550ae, dark: 0x79c0ff),
        "function": Color(themed: { $0.syntax["function"] ?? 0 }, light: 0x6639ba, dark: 0xd2a8ff),
        "type": Color(themed: { $0.syntax["type"] ?? 0 }, light: 0x953800, dark: 0xffa657),
        "tag": Color(themed: { $0.syntax["tag"] ?? 0 }, light: 0x116329, dark: 0x7ee787),
        "attr": Color(themed: { $0.syntax["attr"] ?? 0 }, light: 0x0550ae, dark: 0x79c0ff),
    ]

    static func paint(lines: [String], ranges: String?) -> [AttributedString] {
        var painted = lines.map { AttributedString($0) }
        guard let ranges, !ranges.isEmpty else { return painted }

        var starts: [Int] = []
        var at = 0
        for line in lines {
            starts.append(at)
            at += line.utf16.count + 1
        }

        for group in ranges.split(separator: ";") {
            let parts = group.split(separator: ":", maxSplits: 1)
            guard parts.count == 2 else { continue }
            let name = String(parts[0])
            let x = parts[1].split(separator: ",").compactMap { Int($0) }
            var offset = 0
            var line = 0
            var i = 0
            while i + 1 < x.count {
                offset += x[i]
                let end = offset + x[i + 1]
                while line < lines.count, starts[line] + lines[line].utf16.count <= offset { line += 1 }
                var k = line
                while k < lines.count, starts[k] < end {
                    apply(name, in: &painted[k], text: lines[k],
                          from: max(offset, starts[k]) - starts[k],
                          to: min(end, starts[k] + lines[k].utf16.count) - starts[k])
                    k += 1
                }
                offset = end
                i += 2
            }
        }
        return painted
    }

    private static func apply(_ name: String, in attributed: inout AttributedString, text: String, from: Int, to: Int) {
        guard from < to,
              let strings = Range(NSRange(location: from, length: to - from), in: text),
              let range = Range(strings, in: attributed)
        else { return }
        switch name {
        case "xins": attributed[range].backgroundColor = Color.success.opacity(0.3)
        case "xdel": attributed[range].backgroundColor = Color.danger.opacity(0.3)
        default:
            if let color = colors[name] { attributed[range].foregroundColor = color }
        }
    }
}