@@ -36,6 +36,29 @@ currently just `Nothing` and `Missing`.
3636"""
3737const SINGLETON_IDENTIFIERS = (:nothing , :missing )
3838
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+
3962"""
4063 BUILTIN_FUNCTIONS
4164
@@ -72,6 +95,7 @@ const HIGHLIGHT_FACES = [
7295 :julia_broadcast => Face (inherit= :julia_operator ),
7396 :julia_builtin => Face (),
7497 :julia_operator => Face (),
98+ :julia_opassignment => Face (inherit= :julia_assignment ),
7599 :julia_comparator => Face (inherit= :julia_operator ),
76100 :julia_assignment => Face (),
77101 :julia_keyword => Face (foreground= :red ),
@@ -181,16 +205,28 @@ function _hl_annotations!(highlights::Vector{@NamedTuple{region::UnitRange{Int},
181205 pkind = if ! isnothing (parent) kind (parent. node) end
182206 ppkind = if ! isnothing (parent) && ! isnothing (parent. parent)
183207 kind (parent. parent. node) end
184- isplainoperator (node) =
208+ isplainoperator (node, pnode ) =
185209 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)) &&
187213 ! JuliaSyntax. is_prec_assignment (node) &&
188214 ! JuliaSyntax. is_word_operator (node) &&
189215 nkind != K " ." && nkind != K " ..." &&
190216 (JuliaSyntax. is_trivia (node) || JuliaSyntax. is_leaf (node))
191217 face = if nkind == K " Identifier"
192218 if pkind == K " curly"
193219 :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
194230 else
195231 name = Symbol (regionstr)
196232 if name in SINGLETON_IDENTIFIERS
@@ -226,15 +262,12 @@ function _hl_annotations!(highlights::Vector{@NamedTuple{region::UnitRange{Int},
226262 elseif JuliaSyntax. is_string_delim (node); :julia_string_delim
227263 elseif nkind == K " CmdString" ; :julia_cmd
228264 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
234267 elseif nkind == K " Bool" ; :julia_bool
235268 elseif JuliaSyntax. is_number (nkind); :julia_number
236269 elseif JuliaSyntax. is_prec_assignment (nkind) && JuliaSyntax. is_trivia (node);
237- if nkind == K " = "
270+ if JuliaSyntax . is_syntactic_assignment ( nkind)
238271 ifelse (ppkind == K " for" , :julia_keyword , :julia_assignment )
239272 else # updating for <op>=
240273 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},
258291 :julia_type
259292 end
260293 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
263295 elseif nkind == K " isa" ; :julia_builtin
264296 elseif nkind in (K " &&" , K " ||" , K " <:" , K " ===" ) && JuliaSyntax. is_trivia (node)
265297 :julia_builtin
266298 elseif JuliaSyntax. is_prec_comparison (nkind) && JuliaSyntax. is_trivia (node);
267299 :julia_comparator
268- elseif isplainoperator (node); :julia_operator
300+ elseif isplainoperator (node, pnode ); :julia_operator
269301 elseif nkind == K " ..." && JuliaSyntax. is_trivia (node); :julia_operator
270302 elseif nkind == K " ." && JuliaSyntax. is_trivia (node) && kind (pnode) == K " dotcall" ;
271303 :julia_broadcast
@@ -281,14 +313,11 @@ function _hl_annotations!(highlights::Vector{@NamedTuple{region::UnitRange{Int},
281313 if isnothing (arg1)
282314 elseif kind (arg1) == K " Identifier"
283315 region = first (region): first (region)+ argoffset- 1
284- name = Symbol (regionstr)
316+ name = Symbol (view ( regionstr, 1 : argoffset) )
285317 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))
292321 ifelse (name in BUILTIN_FUNCTIONS, :julia_builtin , :julia_funcall )
293322 end
294323 elseif syntax_errors && JuliaSyntax. is_error (nkind); :julia_error
@@ -360,10 +389,11 @@ julia> JuliaSyntaxHighlighting.highlight("sum(1:8)")
360389"sum(1:8)"
361390
362391julia> 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}}:
364393 @NamedTuple{region::UnitRange{Int64}, label::Symbol, value}((1:3, :face, :julia_funcall))
365394 @NamedTuple{region::UnitRange{Int64}, label::Symbol, value}((4:4, :face, :julia_rainbow_paren_1))
366395 @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))
367397 @NamedTuple{region::UnitRange{Int64}, label::Symbol, value}((7:7, :face, :julia_number))
368398 @NamedTuple{region::UnitRange{Int64}, label::Symbol, value}((8:8, :face, :julia_rainbow_paren_1))
369399```
@@ -409,10 +439,11 @@ julia> JuliaSyntaxHighlighting.highlight!(str)
409439"sum(1:8)"
410440
411441julia> 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}}:
413443 @NamedTuple{region::UnitRange{Int64}, label::Symbol, value}((1:3, :face, :julia_funcall))
414444 @NamedTuple{region::UnitRange{Int64}, label::Symbol, value}((4:4, :face, :julia_rainbow_paren_1))
415445 @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))
416447 @NamedTuple{region::UnitRange{Int64}, label::Symbol, value}((7:7, :face, :julia_number))
417448 @NamedTuple{region::UnitRange{Int64}, label::Symbol, value}((8:8, :face, :julia_rainbow_paren_1))
418449```
0 commit comments