// TerminalTheme.swift // Defines color themes for the terminal view. // // SwiftTerm API notes (discovered during T-2.3): // • SwiftTerm.Color uses UInt16 components (0...65535). // Conversion from 8-bit: multiply by 257 (= 0x101), which maps 0→0 and 255→65535. // • installColors([SwiftTerm.Color]) installs the 16-color ANSI palette. // • nativeForegroundColor / nativeBackgroundColor accept UIColor. import Foundation import SwiftTerm // MARK: - ThemeColor /// A simple 8-bit RGB color that is Codable and Sendable. public struct ThemeColor: Codable, Sendable, Equatable { public let r: UInt8 public let g: UInt8 public let b: UInt8 public init(r: UInt8, g: UInt8, b: UInt8) { self.r = r; self.g = g; self.b = b } } // MARK: - TerminalTheme /// A complete color theme for the terminal view. /// /// `ansiColors` must contain exactly 16 entries (indices 0–15) representing /// the standard ANSI palette: 0–7 normal, 8–15 bright. public struct TerminalTheme: Codable, Identifiable, Sendable, Equatable { public let id: String public let name: String public let foreground: ThemeColor public let background: ThemeColor public let cursor: ThemeColor /// 16 ANSI colors: indices 0–7 are the standard colors, 8–15 are the bright variants. public let ansiColors: [ThemeColor] public init( id: String, name: String, foreground: ThemeColor, background: ThemeColor, cursor: ThemeColor, ansiColors: [ThemeColor] ) { precondition(ansiColors.count == 16, "ansiColors must contain exactly 16 entries") self.id = id self.name = name self.foreground = foreground self.background = background self.cursor = cursor self.ansiColors = ansiColors } // MARK: SwiftTerm conversion /// Converts a `ThemeColor` to a `SwiftTerm.Color`. /// /// SwiftTerm.Color uses UInt16 components (0–65535). Multiplying each 8-bit /// component by 257 (0x101) gives an exact linear mapping: 0→0, 255→65535. public func toSwiftTermColor(_ c: ThemeColor) -> SwiftTerm.Color { SwiftTerm.Color( red: UInt16(c.r) * 257, green: UInt16(c.g) * 257, blue: UInt16(c.b) * 257 ) } /// Returns all 16 ANSI entries as `SwiftTerm.Color` values. public var swiftTermAnsiColors: [SwiftTerm.Color] { ansiColors.map { toSwiftTermColor($0) } } } // MARK: - Built-in themes public extension TerminalTheme { // MARK: dark — hacker/Matrix style: black bg, green fg static let dark = TerminalTheme( id: "dark", name: "Dark (Hacker)", foreground: ThemeColor(r: 0x33, g: 0xFF, b: 0x33), // bright green background: ThemeColor(r: 0x00, g: 0x00, b: 0x00), // pure black cursor: ThemeColor(r: 0x33, g: 0xFF, b: 0x33), ansiColors: [ // 0 – black (normal) ThemeColor(r: 0x00, g: 0x00, b: 0x00), // 1 – red ThemeColor(r: 0xCC, g: 0x00, b: 0x00), // 2 – green ThemeColor(r: 0x00, g: 0xCC, b: 0x00), // 3 – yellow ThemeColor(r: 0xCC, g: 0xCC, b: 0x00), // 4 – blue ThemeColor(r: 0x00, g: 0x00, b: 0xCC), // 5 – magenta ThemeColor(r: 0xCC, g: 0x00, b: 0xCC), // 6 – cyan ThemeColor(r: 0x00, g: 0xCC, b: 0xCC), // 7 – white (normal) ThemeColor(r: 0xCC, g: 0xCC, b: 0xCC), // 8 – bright black (dark gray) ThemeColor(r: 0x33, g: 0x33, b: 0x33), // 9 – bright red ThemeColor(r: 0xFF, g: 0x33, b: 0x33), // 10 – bright green ThemeColor(r: 0x33, g: 0xFF, b: 0x33), // 11 – bright yellow ThemeColor(r: 0xFF, g: 0xFF, b: 0x33), // 12 – bright blue ThemeColor(r: 0x33, g: 0x33, b: 0xFF), // 13 – bright magenta ThemeColor(r: 0xFF, g: 0x33, b: 0xFF), // 14 – bright cyan ThemeColor(r: 0x33, g: 0xFF, b: 0xFF), // 15 – bright white ThemeColor(r: 0xFF, g: 0xFF, b: 0xFF), ] ) // MARK: github — GitHub Dark theme static let github = TerminalTheme( id: "github", name: "GitHub Dark", foreground: ThemeColor(r: 0xE6, g: 0xED, b: 0xF3), // #e6edf3 background: ThemeColor(r: 0x0D, g: 0x11, b: 0x17), // #0d1117 cursor: ThemeColor(r: 0xE6, g: 0xED, b: 0xF3), ansiColors: [ // 0 – black ThemeColor(r: 0x48, g: 0x4F, b: 0x58), // 1 – red ThemeColor(r: 0xFF, g: 0x77, b: 0x77), // 2 – green ThemeColor(r: 0x56, g: 0xD3, b: 0x64), // 3 – yellow ThemeColor(r: 0xE3, g: 0xB3, b: 0x41), // 4 – blue ThemeColor(r: 0x6C, g: 0xA4, b: 0xF8), // 5 – magenta ThemeColor(r: 0xBC, g: 0x8C, b: 0xFF), // 6 – cyan ThemeColor(r: 0x2B, g: 0x73, b: 0x89), // #2b7389 // 7 – white ThemeColor(r: 0xE6, g: 0xED, b: 0xF3), // 8 – bright black ThemeColor(r: 0x6E, g: 0x76, b: 0x81), // 9 – bright red ThemeColor(r: 0xFF, g: 0xA1, b: 0x98), // 10 – bright green ThemeColor(r: 0x3F, g: 0xB9, b: 0x50), // 11 – bright yellow ThemeColor(r: 0xD2, g: 0x9C, b: 0x22), // 12 – bright blue ThemeColor(r: 0x79, g: 0xC0, b: 0xFF), // 13 – bright magenta ThemeColor(r: 0xD2, g: 0xA8, b: 0xFF), // 14 – bright cyan ThemeColor(r: 0x39, g: 0xC5, b: 0xCF), // 15 – bright white ThemeColor(r: 0xFF, g: 0xFF, b: 0xFF), ] ) }