-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathimp-highlight.mts
More file actions
145 lines (129 loc) · 4.13 KB
/
imp-highlight.mts
File metadata and controls
145 lines (129 loc) · 4.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// ANSI color codes for terminal syntax highlighting
const colors = {
reset: '\x1b[0m',
number: '\x1b[38;5;110m', // blue (like #6897bb)
string: '\x1b[38;5;108m', // green (like #6a8759)
operator: '\x1b[38;5;221m', // yellow (like #ffc66d)
keyword: '\x1b[38;5;173m', // orange (like #cc7832)
identifier: '\x1b[38;5;145m', // gray (like #a9b7c6)
comment: '\x1b[38;5;244m', // dark gray (like #808080)
brace: '\x1b[38;5;210m', // red (like #f97c7c)
symbol: '\x1b[38;5;139m', // purple for special symbols
backtick: '\x1b[38;5;179m', // tan/gold for backtick symbols
file: '\x1b[38;5;114m', // light green for file paths
}
const KEYWORDS = new Set([
'rev', 'drop', 'take', 'each', 'map', 'sum', 'prod', 'min', 'max',
'abs', 'floor', 'ceil', 'not', 'and', 'or', 'if', 'then', 'else'
])
/**
* Highlights implish code with ANSI color codes for terminal display
*/
export function highlightCode(code: string): string {
let result = ''
let i = 0
while (i < code.length) {
const rest = code.slice(i)
const char = rest[0]
// Handle whitespace
if (char === '\t' || char === ' ') {
result += char
i++
continue
}
// Handle comments: .: ... :.
// If unclosed, highlight to end of line
if (char === '.' && rest[1] === ':') {
const end = rest.indexOf(':.', 2)
if (end !== -1) {
const comment = rest.slice(0, end + 2)
result += colors.comment + comment + colors.reset
i += comment.length
continue
} else {
// Unclosed comment - highlight to end of line
const comment = rest
result += colors.comment + comment + colors.reset
i += comment.length
continue
}
}
// Handle file paths: %/path/to/file
if (char === '%') {
const fileMatch = rest.match(/^%[^\s\[\]\{\}\(\)]+/)
if (fileMatch) {
result += colors.file + fileMatch[0] + colors.reset
i += fileMatch[0].length
continue
}
}
// Handle backtick symbols: `sym
if (char === '`') {
const symMatch = rest.match(/^`[^\s\[\]\{\}\(\)]*/)
if (symMatch) {
result += colors.backtick + symMatch[0] + colors.reset
i += symMatch[0].length
continue
}
}
// Handle single-quote symbols: 'sym
if (char === "'") {
const symMatch = rest.match(/^'[^\s\[\]\{\}\(\)]*/)
if (symMatch) {
result += colors.symbol + symMatch[0] + colors.reset
i += symMatch[0].length
continue
}
}
// Handle get-words: :word
if (char === ':' && rest.length > 1 && rest[1].match(/[A-Za-z_]/)) {
const getMatch = rest.match(/^:[A-Za-z_][\w-]*/)
if (getMatch) {
result += colors.symbol + getMatch[0] + colors.reset
i += getMatch[0].length
continue
}
}
// Handle strings: "..."
const stringMatch = rest.match(/^"(?:\\.|[^"\\])*"?/)
if (stringMatch && stringMatch[0].length > 1) {
result += colors.string + stringMatch[0] + colors.reset
i += stringMatch[0].length
continue
}
// Handle numbers: 123 or 123.456
const numberMatch = rest.match(/^\d+(?:\.\d+)?/)
if (numberMatch) {
result += colors.number + numberMatch[0] + colors.reset
i += numberMatch[0].length
continue
}
// Handle words/identifiers
const wordMatch = rest.match(/^[A-Za-z_][\w-]*/)
if (wordMatch) {
const token = wordMatch[0]
const color = KEYWORDS.has(token) ? colors.keyword : colors.identifier
result += color + token + colors.reset
i += token.length
continue
}
// Handle operators
const operatorMatch = rest.match(/^[+\-*/^=<>!?,]+/)
if (operatorMatch) {
result += colors.operator + operatorMatch[0] + colors.reset
i += operatorMatch[0].length
continue
}
// Handle braces/brackets/parens
const braceMatch = rest.match(/^[\[\]\{\}\(\)]/)
if (braceMatch) {
result += colors.brace + braceMatch[0] + colors.reset
i += braceMatch[0].length
continue
}
// Default: just add the character as-is
result += char
i++
}
return result
}