@@ -36,6 +36,29 @@ currently just `Nothing` and `Missing`.
36
36
"""
37
37
const SINGLETON_IDENTIFIERS = (:nothing , :missing )
38
38
39
+ """
40
+ OPERATOR_KINDS
41
+
42
+ A set of known operator kind strings.
43
+
44
+ This is a workaround for operators that are classified as `K"Identifier"`.
45
+ """
46
+ const OPERATOR_KINDS = if isdefined (JuliaSyntax, :_kind_str_to_int ) && isdefined (JuliaSyntax, :_kind_int_to_str )
47
+ let (str2int, int2str) = (getglobal (JuliaSyntax, :_kind_str_to_int ), getglobal (JuliaSyntax, :_kind_int_to_str ))
48
+ op_start = get (str2int, " BEGIN_OPS" , typemax (UInt16))
49
+ op_end = get (str2int, " END_OPS" , typemin (UInt16))
50
+ ops = Set {String} ()
51
+ for int in op_start: op_end
52
+ op = get (int2str, int, " " )
53
+ ! isempty (op) && ! startswith (op, " Error" )
54
+ push! (ops, op)
55
+ end
56
+ ops
57
+ end
58
+ else
59
+ Set {String} ()
60
+ end
61
+
39
62
"""
40
63
BUILTIN_FUNCTIONS
41
64
@@ -72,6 +95,7 @@ const HIGHLIGHT_FACES = [
72
95
:julia_broadcast => Face (inherit= :julia_operator ),
73
96
:julia_builtin => Face (),
74
97
:julia_operator => Face (),
98
+ :julia_opassignment => Face (inherit= :julia_assignment ),
75
99
:julia_comparator => Face (inherit= :julia_operator ),
76
100
:julia_assignment => Face (),
77
101
:julia_keyword => Face (foreground= :red ),
@@ -181,16 +205,28 @@ function _hl_annotations!(highlights::Vector{@NamedTuple{region::UnitRange{Int},
181
205
pkind = if ! isnothing (parent) kind (parent. node) end
182
206
ppkind = if ! isnothing (parent) && ! isnothing (parent. parent)
183
207
kind (parent. parent. node) end
184
- isplainoperator (node) =
208
+ isplainoperator (node, pnode ) =
185
209
JuliaSyntax. is_operator (node) &&
186
- ! JuliaSyntax. is_trivia (node) &&
210
+ (! JuliaSyntax. is_trivia (node) ||
211
+ # HACK: This handles a case where an operator is misleadingly labelled as trivia
212
+ ! isnothing (pnode) && JuliaSyntax. is_infix_op_call (pnode)) &&
187
213
! JuliaSyntax. is_prec_assignment (node) &&
188
214
! JuliaSyntax. is_word_operator (node) &&
189
215
nkind != K " ." && nkind != K " ..." &&
190
216
(JuliaSyntax. is_trivia (node) || JuliaSyntax. is_leaf (node))
191
217
face = if nkind == K " Identifier"
192
218
if pkind == K " curly"
193
219
:julia_type
220
+ elseif pkind == K " op=" && kind (lnode) != K " op=" &&
221
+ regionstr in OPERATOR_KINDS
222
+ :julia_opassignment
223
+ elseif pkind ∈ (K " call" , K " dotcall" ) && regionstr in OPERATOR_KINDS
224
+ # HACK: The first operator isn't a `K"<op>"` for /some/ reason in
225
+ # JuliaSyntax 1.0.
226
+ :julia_operator
227
+ elseif pkind == K " comparison" && regionstr in OPERATOR_KINDS
228
+ # HACK: The same as above.
229
+ :julia_comparator
194
230
else
195
231
name = Symbol (regionstr)
196
232
if name in SINGLETON_IDENTIFIERS
@@ -226,15 +262,12 @@ function _hl_annotations!(highlights::Vector{@NamedTuple{region::UnitRange{Int},
226
262
elseif JuliaSyntax. is_string_delim (node); :julia_string_delim
227
263
elseif nkind == K " CmdString" ; :julia_cmd
228
264
elseif nkind == K " `" || nkind == K " ```" ; :julia_cmd_delim
229
- elseif nkind == K " Char"
230
- kind (lnode) == K " '" && ! isempty (highlights) &&
231
- (highlights[end ] = (highlights[end ][1 ], :face , :julia_char_delim ))
232
- :julia_char
233
- elseif nkind == K " '" && kind (lnode) == K " Char" ; :julia_char_delim
265
+ elseif nkind == K " Char" ; :julia_char
266
+ elseif nkind == K " '" && pkind == K " char" ; :julia_char_delim
234
267
elseif nkind == K " Bool" ; :julia_bool
235
268
elseif JuliaSyntax. is_number (nkind); :julia_number
236
269
elseif JuliaSyntax. is_prec_assignment (nkind) && JuliaSyntax. is_trivia (node);
237
- if nkind == K " = "
270
+ if JuliaSyntax . is_syntactic_assignment ( nkind)
238
271
ifelse (ppkind == K " for" , :julia_keyword , :julia_assignment )
239
272
else # updating for <op>=
240
273
push! (highlights, (firstindex (content)+ offset: span (node)+ offset- 1 , :face , :julia_operator ))
@@ -258,14 +291,13 @@ function _hl_annotations!(highlights::Vector{@NamedTuple{region::UnitRange{Int},
258
291
:julia_type
259
292
end
260
293
end
261
- elseif nkind == K " in"
262
- ifelse (ppkind == K " for" , :julia_keyword , :julia_comparator )
294
+ elseif nkind == K " in" && pkind == K " in" ; :julia_keyword
263
295
elseif nkind == K " isa" ; :julia_builtin
264
296
elseif nkind in (K " &&" , K " ||" , K " <:" , K " ===" ) && JuliaSyntax. is_trivia (node)
265
297
:julia_builtin
266
298
elseif JuliaSyntax. is_prec_comparison (nkind) && JuliaSyntax. is_trivia (node);
267
299
:julia_comparator
268
- elseif isplainoperator (node); :julia_operator
300
+ elseif isplainoperator (node, pnode ); :julia_operator
269
301
elseif nkind == K " ..." && JuliaSyntax. is_trivia (node); :julia_operator
270
302
elseif nkind == K " ." && JuliaSyntax. is_trivia (node) && kind (pnode) == K " dotcall" ;
271
303
:julia_broadcast
@@ -281,14 +313,11 @@ function _hl_annotations!(highlights::Vector{@NamedTuple{region::UnitRange{Int},
281
313
if isnothing (arg1)
282
314
elseif kind (arg1) == K " Identifier"
283
315
region = first (region): first (region)+ argoffset- 1
284
- name = Symbol (regionstr)
316
+ name = Symbol (view ( regionstr, 1 : argoffset) )
285
317
ifelse (name in BUILTIN_FUNCTIONS, :julia_builtin , :julia_funcall )
286
- elseif kind (arg1) == K " ." && numchildren (arg1) == 3 &&
287
- kind (arg1[end ]) == K " quote" &&
288
- numchildren (arg1[end ]) == 1 &&
289
- kind (arg1[end ][1 ]) == K " Identifier"
290
- region = first (region)+ argoffset- span (arg1[end ][1 ]): first (region)+ argoffset- 1
291
- name = Symbol (regionstr)
318
+ elseif kind (arg1) == K " ." && numchildren (arg1) == 3 && kind (arg1[end ]) == K " Identifier"
319
+ region = first (region)+ argoffset- span (arg1[end ]): first (region)+ argoffset- 1
320
+ name = Symbol (view (regionstr, 1 : argoffset))
292
321
ifelse (name in BUILTIN_FUNCTIONS, :julia_builtin , :julia_funcall )
293
322
end
294
323
elseif syntax_errors && JuliaSyntax. is_error (nkind); :julia_error
@@ -360,10 +389,11 @@ julia> JuliaSyntaxHighlighting.highlight("sum(1:8)")
360
389
"sum(1:8)"
361
390
362
391
julia> JuliaSyntaxHighlighting.highlight("sum(1:8)") |> Base.annotations
363
- 5 -element Vector{@NamedTuple{region::UnitRange{Int64}, label::Symbol, value}}:
392
+ 6 -element Vector{@NamedTuple{region::UnitRange{Int64}, label::Symbol, value}}:
364
393
@NamedTuple{region::UnitRange{Int64}, label::Symbol, value}((1:3, :face, :julia_funcall))
365
394
@NamedTuple{region::UnitRange{Int64}, label::Symbol, value}((4:4, :face, :julia_rainbow_paren_1))
366
395
@NamedTuple{region::UnitRange{Int64}, label::Symbol, value}((5:5, :face, :julia_number))
396
+ @NamedTuple{region::UnitRange{Int64}, label::Symbol, value}((6:6, :face, :julia_operator))
367
397
@NamedTuple{region::UnitRange{Int64}, label::Symbol, value}((7:7, :face, :julia_number))
368
398
@NamedTuple{region::UnitRange{Int64}, label::Symbol, value}((8:8, :face, :julia_rainbow_paren_1))
369
399
```
@@ -409,10 +439,11 @@ julia> JuliaSyntaxHighlighting.highlight!(str)
409
439
"sum(1:8)"
410
440
411
441
julia> Base.annotations(str)
412
- 5 -element Vector{@NamedTuple{region::UnitRange{Int64}, label::Symbol, value}}:
442
+ 6 -element Vector{@NamedTuple{region::UnitRange{Int64}, label::Symbol, value}}:
413
443
@NamedTuple{region::UnitRange{Int64}, label::Symbol, value}((1:3, :face, :julia_funcall))
414
444
@NamedTuple{region::UnitRange{Int64}, label::Symbol, value}((4:4, :face, :julia_rainbow_paren_1))
415
445
@NamedTuple{region::UnitRange{Int64}, label::Symbol, value}((5:5, :face, :julia_number))
446
+ @NamedTuple{region::UnitRange{Int64}, label::Symbol, value}((6:6, :face, :julia_operator))
416
447
@NamedTuple{region::UnitRange{Int64}, label::Symbol, value}((7:7, :face, :julia_number))
417
448
@NamedTuple{region::UnitRange{Int64}, label::Symbol, value}((8:8, :face, :julia_rainbow_paren_1))
418
449
```
0 commit comments