format-aware highlighting: code files get code mode, others fall back to Cordial/markdown

This commit is contained in:
jess 2026-04-06 13:25:31 -07:00
parent 3d20668edc
commit 977874cd22
1 changed files with 28 additions and 6 deletions

View File

@ -908,6 +908,7 @@ struct EditorView: View {
EditorTextView( EditorTextView(
text: bodyBinding, text: bodyBinding,
evalResults: offsetEvalResults(state.evalResults), evalResults: offsetEvalResults(state.evalResults),
fileFormat: state.currentFileFormat,
onEvaluate: { state.evaluate() }, onEvaluate: { state.evaluate() },
onBackspaceAtStart: { onBackspaceAtStart: {
NotificationCenter.default.post(name: .focusTitle, object: nil) NotificationCenter.default.post(name: .focusTitle, object: nil)
@ -928,6 +929,7 @@ struct EditorView: View {
struct EditorTextView: NSViewRepresentable { struct EditorTextView: NSViewRepresentable {
@Binding var text: String @Binding var text: String
var evalResults: [Int: String] var evalResults: [Int: String]
var fileFormat: FileFormat = .markdown
var onEvaluate: () -> Void var onEvaluate: () -> Void
var onBackspaceAtStart: (() -> Void)? = nil var onBackspaceAtStart: (() -> Void)? = nil
@ -983,7 +985,7 @@ struct EditorTextView: NSViewRepresentable {
if let ts = textView.textStorage { if let ts = textView.textStorage {
ts.beginEditing() ts.beginEditing()
applySyntaxHighlighting(to: ts) applySyntaxHighlighting(to: ts, format: fileFormat)
ts.endEditing() ts.endEditing()
} }
textView.typingAttributes = [ textView.typingAttributes = [
@ -1007,7 +1009,7 @@ struct EditorTextView: NSViewRepresentable {
textView.string = text textView.string = text
if let ts = textView.textStorage { if let ts = textView.textStorage {
ts.beginEditing() ts.beginEditing()
applySyntaxHighlighting(to: ts) applySyntaxHighlighting(to: ts, format: fileFormat)
ts.endEditing() ts.endEditing()
} }
textView.selectedRanges = selectedRanges textView.selectedRanges = selectedRanges
@ -1056,7 +1058,7 @@ struct EditorTextView: NSViewRepresentable {
.foregroundColor: palette.text .foregroundColor: palette.text
] ]
ts.beginEditing() ts.beginEditing()
applySyntaxHighlighting(to: ts) applySyntaxHighlighting(to: ts, format: parent.fileFormat)
ts.endEditing() ts.endEditing()
tv.needsDisplay = true tv.needsDisplay = true
} }
@ -1077,7 +1079,7 @@ struct EditorTextView: NSViewRepresentable {
parent.text = tv.string parent.text = tv.string
let sel = tv.selectedRanges let sel = tv.selectedRanges
ts.beginEditing() ts.beginEditing()
applySyntaxHighlighting(to: ts) applySyntaxHighlighting(to: ts, format: parent.fileFormat)
ts.endEditing() ts.endEditing()
tv.typingAttributes = [ tv.typingAttributes = [
.font: Theme.editorFont, .font: Theme.editorFont,
@ -1175,7 +1177,7 @@ struct EditorTextView: NSViewRepresentable {
let sel = tv.selectedRanges let sel = tv.selectedRanges
ts.beginEditing() ts.beginEditing()
ts.replaceCharacters(in: range, with: newMarkdown) ts.replaceCharacters(in: range, with: newMarkdown)
applySyntaxHighlighting(to: ts) applySyntaxHighlighting(to: ts, format: parent.fileFormat)
ts.endEditing() ts.endEditing()
tv.selectedRanges = sel tv.selectedRanges = sel
parent.text = tv.string parent.text = tv.string
@ -1396,7 +1398,7 @@ private let syntaxBooleans: Set<String> = ["true", "false"]
private let syntaxOperatorChars = CharacterSet(charactersIn: "+-*/=^<>!(){}[]:,.&|%") private let syntaxOperatorChars = CharacterSet(charactersIn: "+-*/=^<>!(){}[]:,.&|%")
func applySyntaxHighlighting(to textStorage: NSTextStorage) { func applySyntaxHighlighting(to textStorage: NSTextStorage, format: FileFormat = .markdown) {
let text = textStorage.string let text = textStorage.string
let fullRange = NSRange(location: 0, length: (text as NSString).length) let fullRange = NSRange(location: 0, length: (text as NSString).length)
let palette = Theme.current let palette = Theme.current
@ -1409,6 +1411,11 @@ func applySyntaxHighlighting(to textStorage: NSTextStorage) {
] ]
textStorage.setAttributes(baseAttrs, range: fullRange) textStorage.setAttributes(baseAttrs, range: fullRange)
if format.isCode {
applyCodeFileHighlighting(to: textStorage, syn: syn, baseFont: baseFont)
return
}
let fencedRanges = highlightFencedCodeBlocks(textStorage: textStorage, palette: palette, baseFont: baseFont) let fencedRanges = highlightFencedCodeBlocks(textStorage: textStorage, palette: palette, baseFont: baseFont)
let tableHeaderLines = findTableHeaderLines(textStorage: textStorage, fencedRanges: fencedRanges) let tableHeaderLines = findTableHeaderLines(textStorage: textStorage, fencedRanges: fencedRanges)
@ -1457,6 +1464,21 @@ func applySyntaxHighlighting(to textStorage: NSTextStorage) {
highlightAutolinks(textStorage: textStorage, palette: palette, fencedRanges: fencedRanges) highlightAutolinks(textStorage: textStorage, palette: palette, fencedRanges: fencedRanges)
} }
private func applyCodeFileHighlighting(to textStorage: NSTextStorage, syn: Theme.SyntaxColors, baseFont: NSFont) {
let text = textStorage.string
let nsText = text as NSString
var lineStart = 0
while lineStart < nsText.length {
let lineRange = nsText.lineRange(for: NSRange(location: lineStart, length: 0))
let line = nsText.substring(with: lineRange)
highlightCodeLine(line, lineRange: lineRange, textStorage: textStorage, syn: syn)
lineStart = NSMaxRange(lineRange)
}
highlightBlockComments(textStorage: textStorage, syn: syn, baseFont: baseFont)
}
private func highlightMarkdownLine(_ trimmed: String, line: String, lineRange: NSRange, textStorage: NSTextStorage, baseFont: NSFont, palette: CatppuccinPalette, isTableHeader: Bool = false) -> Bool { private func highlightMarkdownLine(_ trimmed: String, line: String, lineRange: NSRange, textStorage: NSTextStorage, baseFont: NSFont, palette: CatppuccinPalette, isTableHeader: Bool = false) -> Bool {
if trimmed.hasPrefix("### ") { if trimmed.hasPrefix("### ") {
let hashRange = (textStorage.string as NSString).range(of: "###", range: lineRange) let hashRange = (textStorage.string as NSString).range(of: "###", range: lineRange)