Skip to content

Instantly share code, notes, and snippets.

@martinpi
Created October 13, 2018 14:27
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save martinpi/3fe7e73363d8076f3ded1d90a55d8fba to your computer and use it in GitHub Desktop.
Save martinpi/3fe7e73363d8076f3ded1d90a55d8fba to your computer and use it in GitHub Desktop.
A simple Swift 4.0 class for syntax highlighting in an NSTextView
//
// SyntaxHighlighter.swift
// CardsCardsCards
//
// Created by Martin Pichlmair on 12/10/2018.
//
// Based on https://raw.githubusercontent.com/kuyawa/Macaw/master/Macaw/Macaw.swift
import Cocoa
import Foundation
class SyntaxHighlighter {
struct color {
static let normal = [NSAttributedString.Key.foregroundColor: NSColor(red: 0.95, green: 0.95, blue: 0.95, alpha: 1.0)] // light grey
static let ruleName = [NSAttributedString.Key.foregroundColor: NSColor(red: 0.40, green: 0.60, blue: 0.90, alpha: 1.0)] // cyan
static let number = [NSAttributedString.Key.foregroundColor: NSColor(red: 0.60, green: 0.60, blue: 0.90, alpha: 1.0)] // blue
static let keyword = [NSAttributedString.Key.foregroundColor: NSColor(red: 0.75, green: 0.20, blue: 0.75, alpha: 1.0)] // magenta
static let expression = [NSAttributedString.Key.foregroundColor: NSColor(red: 0.95, green: 0.75, blue: 0.10, alpha: 1.0)] // yellow
static let modifier = [NSAttributedString.Key.foregroundColor: NSColor(red: 0.95, green: 0.50, blue: 0.20, alpha: 1.0)] // orange
static let comment = [NSAttributedString.Key.foregroundColor: NSColor(red: 0.20, green: 0.60, blue: 0.20, alpha: 1.0)] // green
}
struct regex {
static let keywords = "\\b(origin)\\b"
static let ruleName = "(\\[.*\\])"
static let expression = "(\\#[a-zA-Z][a-zA-Z0-9,\\.\\(\\)]*\\#)"
static let modifier = "\\#.*\\.([a-zA-Z][a-zA-Z0-9,]*\\(.*\\))\\#"
static let numberLiteral = "\\b([0-9]*(\\.[0-9]*)?)\\b"
static let symbols = "(\\+|-|\\*|/|=|\\{|\\}|\\[|\\]|\\(|\\))"
static let commentLine = "(^\\\\.*)"
}
let patterns = [
regex.commentLine : color.comment,
regex.ruleName : color.keyword,
regex.numberLiteral : color.number,
regex.keywords : color.keyword,
regex.expression : color.expression,
regex.modifier : color.modifier
]
init() {
}
// Colorize all
func colorize(_ textView: NSTextView) {
let all = textView.string
let range = NSString(string: textView.string).range(of: all)
colorize(textView, range: range)
}
// Colorize range
func colorize(_ textView: NSTextView, range: NSRange) {
var extended = NSUnionRange(range, NSString(string: textView.string).lineRange(for: NSMakeRange(range.location, 0)))
extended = NSUnionRange(range, NSString(string: textView.string).lineRange(for: NSMakeRange(NSMaxRange(range), 0)))
for (pattern, attribute) in patterns {
applyStyles(textView, range: extended, pattern: pattern, attribute: attribute)
}
}
func applyStyles(_ textView: NSTextView, range: NSRange, pattern: String, attribute: [NSAttributedString.Key: Any]) {
let regex = try? NSRegularExpression(pattern: pattern, options: [NSRegularExpression.Options.anchorsMatchLines])
regex?.enumerateMatches(in: textView.string, options: [], range: range) {
match, flags, stop in
let matchRange = match?.range(at: 1)
textView.textStorage?.addAttributes(attribute, range: matchRange!)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment