Skip to content

Commit 8f89737

Browse files
committed
Improvements to fontification
1. correctly fontify escape sequences and regex strings; 2. correctly fontify tuple assigments; 3. make function definition name fontification significantly simpler and more robust, fontify more obscure variants correctly; 4. fontify variable assignments in a few more scenarios: typed assignments and slurps;
1 parent d693c6b commit 8f89737

File tree

4 files changed

+95
-95
lines changed

4 files changed

+95
-95
lines changed

julia-ts-mode.el

Lines changed: 64 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -144,23 +144,24 @@ Otherwise, the indentation is:
144144
(treesit-font-lock-rules
145145
:language 'julia
146146
:feature 'assignment
147-
`((assignment :anchor [(identifier) (operator)] @font-lock-variable-name-face)
148-
(assignment
149-
:anchor
150-
(field_expression
151-
value: (identifier) "." (identifier) @font-lock-variable-name-face))
152-
(assignment (open_tuple (identifier) @font-lock-variable-name-face))
153-
(assignment
154-
:anchor
155-
(open_tuple
156-
(field_expression
157-
value: (identifier) "." (identifier) @font-lock-variable-name-face)))
158-
(local_statement (identifier) @font-lock-variable-name-face)
147+
`(;; plain assignments
148+
([(identifier) (operator)] @font-lock-variable-name-face @lhs
149+
(:pred julia-ts--assignment-left-side-p @lhs))
150+
;; qualified name assignments
151+
((field_expression "." (identifier) @font-lock-variable-name-face) @lhs
152+
(:pred julia-ts--assignment-left-side-p @lhs))
153+
;; typed assignments
154+
((typed_expression (identifier) @font-lock-variable-name-face "::") @lhs
155+
(:pred julia-ts--assignment-left-side-p @lhs))
156+
;; let blocks
159157
(let_statement :anchor (identifier) @font-lock-variable-name-face)
160158
((let_statement _ @comma :anchor (identifier) @font-lock-variable-name-face)
161159
(:equal "," @comma))
162160
(let_binding :anchor (identifier) @font-lock-variable-name-face)
161+
;; local and global statements
162+
(local_statement (identifier) @font-lock-variable-name-face)
163163
(global_statement (identifier) @font-lock-variable-name-face)
164+
;; named (keyword) argument names with assigned values
164165
(named_argument (identifier) @julia-ts-keyword-argument-face (operator)))
165166

166167
:language 'julia
@@ -177,81 +178,27 @@ Otherwise, the indentation is:
177178

178179
:language 'julia
179180
:feature 'definition
180-
`((function_definition
181-
(signature (identifier) @font-lock-function-name-face))
181+
`(;; function declaration
182182
(function_definition
183-
(signature
184-
(call_expression [(identifier) (operator)] @font-lock-function-name-face)))
185-
(function_definition
186-
(signature
187-
(typed_expression
188-
(call_expression [(identifier) (operator)] @font-lock-function-name-face))))
189-
(function_definition
190-
(signature
191-
(where_expression
192-
(call_expression [(identifier) (operator)] @font-lock-function-name-face))))
193-
(function_definition
194-
(signature
195-
(where_expression
196-
(typed_expression
197-
(call_expression [(identifier) (operator)] @font-lock-function-name-face)))))
198-
(function_definition
199-
(signature
200-
(call_expression
201-
(field_expression
202-
value: (identifier) "." (identifier) @font-lock-function-name-face))))
203-
(function_definition
204-
(signature
205-
(typed_expression
206-
(call_expression
207-
(field_expression
208-
value: (identifier) "." (identifier) @font-lock-function-name-face)))))
209-
(macro_definition
210-
(signature
211-
(call_expression (identifier) @font-lock-function-name-face)))
212-
(macro_definition
213-
(signature
214-
(call_expression
215-
(field_expression
216-
value: (identifier) "." (identifier) @font-lock-function-name-face))))
217-
(abstract_definition
218-
(type_head (identifier) @font-lock-type-face))
219-
(abstract_definition
220-
(type_head (binary_expression (identifier) @font-lock-type-face)))
221-
(primitive_definition
222-
(type_head (identifier) @font-lock-type-face))
223-
(primitive_definition
224-
(type_head (binary_expression (identifier) @font-lock-type-face)))
225-
(struct_definition
226-
(type_head (identifier) @font-lock-type-face))
227-
(struct_definition
228-
(type_head (binary_expression (identifier) @font-lock-type-face)))
229-
(assignment
230-
:anchor
231-
(call_expression [(identifier) (operator)] @font-lock-function-name-face))
232-
(assignment
233-
:anchor
234-
(call_expression
235-
(parenthesized_expression
236-
[(identifier) (operator)] @font-lock-function-name-face)))
237-
(assignment
238-
:anchor
239-
(call_expression
240-
(field_expression
241-
value: (identifier) "." (identifier) @font-lock-function-name-face)))
242-
(assignment
243-
:anchor
244-
(where_expression
245-
(call_expression (identifier) @font-lock-function-name-face)))
246-
(assignment
247-
:anchor
248-
(where_expression
249-
(call_expression
250-
(field_expression
251-
value: (identifier) "." (identifier) @font-lock-function-name-face))))
183+
(signature (identifier) @font-lock-function-name-face))
184+
;; function definitions (long and short syntax)
185+
(call_expression
186+
[(identifier) (operator)] @font-lock-function-name-face
187+
(:pred julia-ts--fundef-name-p @font-lock-function-name-face))
188+
(call_expression
189+
(parenthesized_expression
190+
[(identifier) (operator)] @font-lock-function-name-face)
191+
(:pred julia-ts--fundef-name-p @font-lock-function-name-face))
192+
(call_expression
193+
(field_expression "." [(identifier) (operator)] @font-lock-function-name-face)
194+
(:pred julia-ts--fundef-name-p @font-lock-function-name-face))
195+
;; binary operator definition as assignment
252196
(assignment
253197
:anchor
254-
(binary_expression _ (operator) @font-lock-function-name-face)))
198+
(binary_expression _ (operator) @font-lock-function-name-face))
199+
;; struct/abstract type/primitive type definitions
200+
(type_head (identifier) @font-lock-type-face)
201+
(type_head (binary_expression (identifier) @font-lock-type-face)))
255202

256203
:language 'julia
257204
:feature 'error
@@ -315,6 +262,12 @@ Otherwise, the indentation is:
315262
:override 'keep
316263
`((quote_expression) @julia-ts-quoted-symbol-face)
317264

265+
:language 'julia
266+
:feature 'string
267+
'(((escape_sequence) @font-lock-escape-face)
268+
((prefixed_string_literal prefix: _ @prefix) @font-lock-regexp-face
269+
(:equal "r" @prefix)))
270+
318271
:language 'julia
319272
:feature 'string
320273
:override 'keep
@@ -432,6 +385,33 @@ Return nil if there is no name or if NODE is not a defun node."
432385
(lambda (child)
433386
(equal (treesit-node-type child) type)))))
434387

388+
(defun julia-ts--assignment-left-side-p (node)
389+
"Return non-nil if NODE is the left hand side of an `assignment'.
390+
It may be wrapped (within the `'assignment') in an `open_tuple'
391+
or a `tuple_expression' (but only one of those two), and/or a
392+
`splat_expression' as well."
393+
(let* ((p1 (treesit-node-parent node))
394+
(p2 (if (equal (treesit-node-type p1) "splat_expression")
395+
(treesit-node-parent p1) p1))
396+
(p3 (if (member (treesit-node-type p2) '("open_tuple" "tuple_expression"))
397+
(treesit-node-parent p2) p2)))
398+
(and (equal (treesit-node-type p3) "assignment")
399+
(member (treesit-node-child p3 0) (list p2 p1 node)))))
400+
401+
(defun julia-ts--fundef-name-p (node)
402+
"Return non-nil if NODE is the name of a function definition.
403+
NODE is recognized as such if it has an ancestor that is either a
404+
`signature' (long syntax) or an `assignment' (short syntax), via
405+
the ancestor's first child."
406+
(let ((prev node))
407+
(treesit-parent-until
408+
node
409+
(lambda (ancestor)
410+
(prog1
411+
(and (member (treesit-node-type ancestor) '("signature" "assignment"))
412+
(equal (treesit-node-child ancestor 0) prev))
413+
(setq prev ancestor))))))
414+
435415
;;;###autoload
436416
(add-to-list 'auto-mode-alist '("\\.jl\\'" . julia-ts-mode))
437417

test/Downloads.jl.faceup

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ in which case both the inner and outer code and message may be of interest.
149149
«v:errstr» = err.message
150150
«v:status» = err.response.status
151151
«v:message» = err.response.message
152-
«v:status_re» = Regex(status == «c:0» ? «s:""» : «s:"\\b»«:julia-ts-string-interpolation-face:$»«D:status»«s:\\b"»)
152+
«v:status_re» = Regex(status == «c:0» ? «s:""» : «s:"»«:font-lock-escape-face:\\»«s:b»«:julia-ts-string-interpolation-face:$»«D:status»«:font-lock-escape-face:\\»«s:b"»)
153153

154154
err.code == Curl.CURLE_OK &&
155155
«k:return» isempty(message) ? «s:"Error status »«:julia-ts-string-interpolation-face:$»«D:status»«s:"» :

test/tree-sitter-corpus.jl

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,6 @@ echo "\033[31mred\033[m"
492492
# non-standard string literals
493493
# ==============================
494494

495-
# FIXME: \s shouldn't be an escape_sequence here
496495
trailing_ws = r"\s+$"
497496
version = v"1.0"
498497
K"\\"
@@ -522,6 +521,17 @@ tup = 1, 2, 3
522521
car, cdr... = list
523522
c &= d ÷= e
524523

524+
# open tuple
525+
a, b = 1, 2
526+
# regular tuple
527+
(a, b) = (1, 2)
528+
# typed assignment
529+
a::Int = 1
530+
# FQN
531+
Main.a = 12
532+
# combination
533+
a::Int, b::Int... = 1, 2, 3
534+
525535
# ==============================
526536
# binary arithmetic operators
527537
# ==============================

test/tree-sitter-corpus.jl.faceup

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ Base.«f:foo»(x) = x
227227
n
228228
«k:end»
229229

230-
f(n::«t:N», m::«t:M») «k:where» {«t:N» <: «t:Number»} «k:where» {«t:M» <: «t:Integer»} = n^m
230+
«f:f»(n::«t:N», m::«t:M») «k:where» {«t:N» <: «t:Number»} «k:where» {«t:M» <: «t:Integer»} = n^m
231231

232232
«t:Foo»{«t:T»}(x::«t:T») «k:where» {«t:T»} = x
233233

@@ -466,10 +466,10 @@ a -> «v:a» = «c:2», «c:3»
466466
«x:# ==============================»
467467

468468
«s:""»
469-
«s:"\"
469+
«s:"»«:font-lock-escape-face:\"»«s:
470470
«s:"foo
471471
bar"»
472-
«s:"this is a \"string\"."»
472+
«s:"this is a »«:font-lock-escape-face:\"»«s:string»«:font-lock-escape-face:\"»«s:."»
473473
«s:"""this is also a "string"."""»
474474
«v:band» = «s:"Interpol"»
475475
«s:"»«:julia-ts-string-interpolation-face:$»«D:band»«s: is a cool band"»
@@ -483,19 +483,18 @@ a -> «v:a» = «c:2», «c:3»
483483
«s:`pwd`»
484484
«s:m`pwd`»
485485
«s:`cd »«:julia-ts-string-interpolation-face:$»«D:dir»«s:`»
486-
«s:`echo \`cmd\`
486+
«s:`echo »«:font-lock-escape-face:\`»«s:cmd»«:font-lock-escape-face:\`»«s:
487487
«s:```
488-
echo "\033[31mred\033[m"
488+
echo "»«:font-lock-escape-face:\033»«s:[31mred»«:font-lock-escape-face:\033»«s:[m"
489489
```»
490490

491491
«x:# ==============================»
492492
«x:# non-standard string literals»
493493
«x:# ==============================»
494494

495-
«x:# FIXME: \s shouldn't be an escape_sequence here»
496-
«v:trailing_ws» = «s:r"\s+$"»
495+
«v:trailing_ws» = «:font-lock-regexp-face:r"\s+$"»
497496
«v:version» = «s:v"1.0"»
498-
«s:K"\\
497+
«s:K"»«:font-lock-escape-face:\\»«s:
499498

500499
«x:# ==============================»
501500
«x:# comments»
@@ -519,9 +518,20 @@ nested #= comments =# =#»
519518
«v:a» = b
520519
a «f:..» b = a * b
521520
«v:tup» = «c:1», «c:2», «c:3»
522-
«v:car», cdr... = list
521+
«v:car», «v:cdr»... = list
523522
c &= d ÷= e
524523

524+
«x:# open tuple»
525+
«v:a», «v:b» = «c:1», «c:2»
526+
«x:# regular tuple»
527+
(«v:a», «v:b») = («c:1», «c:2»)
528+
«x:# typed assignment»
529+
«v:a»::«t:Int» = «c:1»
530+
«x:# FQN»
531+
Main.«v:a» = «c:12»
532+
«x:# combination»
533+
«v:a»::«t:Int», «v:b»::«t:Int»... = «c:1», «c:2», «c:3»
534+
525535
«x:# ==============================»
526536
«x:# binary arithmetic operators»
527537
«x:# ==============================»

0 commit comments

Comments
 (0)