//
// File.swift
// rapid2026
//
// Created by David Sisemore on 10/12/25.
//
import AppKit
import Foundation
// lite
fileprivate let liteNumbers : NSColor = NSColor(rgb:0x1C00CF)
fileprivate let liteKeywords : NSColor = NSColor(rgb:0x0F68A0)
fileprivate let liteStrings : NSColor = NSColor(rgb:0xC41A16)
fileprivate let litePreprocessor : NSColor = NSColor(rgb:0xFD8008)
fileprivate let liteComments : NSColor = NSColor(rgb:0x007f00)
fileprivate let liteMarks : NSColor = NSColor(rgb:0xFF0000)
fileprivate let liteTypes : NSColor = NSColor(rgb:0x3900A0)
fileprivate let liteClass : NSColor = NSColor(rgb:0x3900A0)
// Dark
fileprivate let darkNumbers : NSColor = NSColor(rgb:0xD0BF69)
fileprivate let darkKeywords : NSColor = NSColor(rgb:0xFC5FA3)
fileprivate let darkStrings : NSColor = NSColor(rgb:0xFC6A5D)
fileprivate let darkPreprocessor : NSColor = NSColor(rgb:0xFD8F3F)
fileprivate let darkComments : NSColor = NSColor(rgb:0x6C7986)
fileprivate let darkMarks : NSColor = NSColor(rgb:0x92A1B1)
fileprivate let darkTypes : NSColor = NSColor(rgb:0xD0A8FF)
fileprivate let darkClass : NSColor = NSColor(rgb:0xD0A8FF)
public enum TheHighlighter : CaseIterable {
// MARK: Rules must be in proper order
case plain_text
case numbers
case keywords
case otherClass
case otherTypes
case string
case preprocessor
case lineComment
case marks
case blockComments
// Visual Attributes
var fontName : String { return "Menlo" } // should be a mono-space font
var fontsize : CGFloat { return 24 }
var selectColor : NSColor { return NSColor(rgb:0x8aCaff) }
var gutterWidth : CGFloat { return 60 }
var gutterBG : NSColor { return NSColor.windowBackgroundColor }
var gutterFG : NSColor { return .labelColor }
//
var regEX : NSRegularExpression?{ // This keyword list is for Swift 5
var rule : String
switch self {
case .plain_text :
rule = "(.*$)"
case .numbers :
let dec = #"([-+]?(?:[0-9]+(?:\.[0-9]+)?|\.[0-9]+))"#
let hex = #"(0[xX][0-9a-fA-F]+)"#
rule = #"(\#(hex)|\#(dec))"#
case .keywords :
let keywordList = "if|for|func|var|let|else|return|switch|case|while|as|repeat|inout|class|struct|enum|import|guard|break|continue|in|is|try|throws|throw|catch|do|default|protocol|extension|public|private|internal|fileprivate|open|static|init|self|super|true|false|nil|Anyasync|await|actor|associatedtype|defer|final|convenience|mutating|nonmutating|required|override|weak|unowned|lazy|optional|some|any|get|set|willSet|didSet|dynamic|distributed|prefix|postfix|infix|precedencegroup|precedence|associativity|operator|indirect|consuming|consume|borrowing|rethrows|typealias|subscript|where|fallingthrough|fileprivateType|deinit|left|none|right"
rule = "(?-i)(?<!\\B)("+keywordList+")\\b"
case .otherClass :
let otherList = "NSColor|NSFont|NSAlert|NSApplication|NSBezierPath|NSBox|NSButton|NSClipView|NSCollectionView|NSComboBox|NSDrawer|NSEvent|NSDateFormatter|NSNumberFormatter|NSFormatter|NSImage|NSLayoutManager|NSLocale|NSMenu|NSMenuItem|NSNotificationCenter|NSOpenPanel|NSOutlineView|NSPageController|NSPopUpButton|NSResponder|NSRunLoop|NSSavePanel|NSScrollView|NSSlider|NSStatusBar|NSTableView|NSTextField|NSTextStorage|NSTextView|NSToolbar|NSUUID|NSView|NSWindow|NSWorkspace|CGColor|CGColorSpace|CGContext|CGPath|CGAffineTransform|CGPoint|CGSize|CGRect|CGGradient|CGImage|CGFont|CGMutablePath|CGDataProvider|CGPattern|CGPDFDocument|CGPDFPage|CGShading"
rule = "(?-i)(?<!\\B)("+otherList+")\\b"
case .otherTypes :
let typeList = "String|Int8|Int16|Int32|UInt8|UInt16|UInt32|UInt64|Int|Float|Double|Bool|Character|Set|Range|CGSize|CGPoint|CGRect|CGVector|CGAffineTransform|AttributedString|CBool|CChar16|CChar32|CChar8|CChar|CDouble|CFloat16|CFloat|CInt|CLongDouble|CLongLong|CLong|CShort|CSignedChar|CUnsignedChar|CUnsignedInt|CUnsignedLong|CUnsignedLongLong|CUnsignedShort|CVaListPointer|CWideChar|OpaquePointer|Stride"
rule = "(?-i)(?<!\\B)("+typeList+")\\b"
case .string :
rule = "(\"(\"\"|.)+\")"
case .preprocessor :
let pp = #"if\s|#elseif\s|#else\s|#endif|#available|#colorLiteral|#column|#file|#fileID|#fileLiteral|#filePath|#function|#imageLiteral|#line|#selector\(|#sourceLocation\(|#error\(|#warning\(|"#
rule = #"(?-i)^\s*("#+pp+#").*$"#
case .lineComment :
rule = "(//.*$)"
case .marks :
rule = #"(?-i)//\s*((MARK|TODO|FIXME): ).*$"#
case .blockComments :
rule = "(/\\*[\\s\\S]*?\\*/)"
}
return try? NSRegularExpression(pattern: rule, options: [NSRegularExpression.Options.anchorsMatchLines,NSRegularExpression.Options.caseInsensitive])
}
var color : NSColor {
let isDark = UserDefaults.standard.string(forKey: "AppleInterfaceStyle") == "Dark"
if isDark==false {
switch self {
case .plain_text : return NSColor.labelColor
case .numbers : return liteNumbers
case .keywords : return liteKeywords
case .otherClass : return liteClass
case .otherTypes : return liteTypes
case .string : return liteStrings
case .preprocessor : return litePreprocessor
case .lineComment : return liteComments
case .marks : return liteMarks
case .blockComments : return liteComments
}
} else {
switch self {
case .plain_text : return NSColor.labelColor
case .numbers : return darkNumbers
case .keywords : return darkKeywords
case .otherClass : return darkClass
case .otherTypes : return darkTypes
case .string : return darkStrings
case .preprocessor : return darkPreprocessor
case .lineComment : return darkComments
case .marks : return darkMarks
case .blockComments : return darkComments
}
}
}
}
I do not trust any Version Control software… I got burned by one big time many years ago, and ended up losing almost an entire years worth of work… So, I’m sorry if the manner in which I give away code isn’t up to community standards…
its harder for people to contribute any fixes, changes, updates (that you still get to approve or reject)
Millions, probably tens or hundreds of millions, of people use things like Git every day
They get reviewed & updated & patched by millions
So the free software movements promise of lots of eyes looking things over to make sure there are not bugs & glitches actually works
that all may be true (and I have no doubt that it is)…. but I really have no incentive to learn how those work anymore. If people do not wish to take advantage of what I do offer, that is 100% up to them
But as I said, I got burned REALLY bad by that kind of process in the past, and perhaps if I had a “team” and large projects, it might be different… but I don’t
Understand. I forget the name of the source host we were using but they got caught in a ransomware attack and they lost everything. They folded up shop the next day as their backups were deleted as well. I lost a couple of projects that I didn’t have backed up locally. Thankfully nothing super important.
I don’t remember what the software was, but it was all on company servers as it was highly sensitive healthcare data and proprietary code. But something happened between server and client and all it delivered was gibberish
I have an updated version of this code if anyone is interested
added highlight of current line
added bookmarks complete with navigation
added contextual menu
various refactoring
I will NOT be posting the code here based on previous comments, so if you are interested, private me you email address and I’ll send a server link (as soon as I zip it up)
Hey people calm down. Dave is doing all of this as hobby work. He don’t like Git? That’s his choice. He will provide a ZIP archive for everybody which is interested in. That’s engough. If you want a GIT: ask him for the ZIP and store the project on your private GIT. Then you have your Git