plum
git clone https://git.pyrossh.dev/plum
A statically typed, imperative programming language inspired by rust, python
5bb1d4c
— Peter John
2026-11-02T19:37:19+05:30
T3: formatter and highlighting
plum-core/tests/formatter_test.rs
CHANGED
|
@@ -322,3 +322,31 @@ fn formatAnnotatedDeclaration() {
|
|
|
322
322
|
assert!(first.contains(" o: Int? := null\n"), "got: {first:?}");
|
|
323
323
|
assert_eq!(first, formatSource(&first).expect("second"));
|
|
324
324
|
}
|
|
325
|
+
|
|
326
|
+
#[test]
|
|
327
|
+
fn format_trait_idempotent() {
|
|
328
|
+
let input = "\
|
|
329
|
+
trait Ent(pos: Int,z: Int) =
|
|
330
|
+
fun update(self,dt: Float)
|
|
331
|
+
# moves it
|
|
332
|
+
fun moveBy(self,d: Int) =
|
|
333
|
+
self.pos = self.pos + d
|
|
334
|
+
self.z = 0
|
|
335
|
+
fun draw(self) -> Int = self.z
|
|
336
|
+
|
|
337
|
+
record House(Ent,k: Int) =
|
|
338
|
+
fun update(self,dt: Float) = 1
|
|
339
|
+
";
|
|
340
|
+
let once = formatSource(input).expect("first pass");
|
|
341
|
+
assert!(once.contains("trait Ent(pos: Int, z: Int) ="), "got: {once}");
|
|
342
|
+
assert!(once.contains(" fun update(self, dt: Float)\n"), "got: {once}");
|
|
343
|
+
assert!(once.contains(" # moves it\n"), "got: {once}");
|
|
344
|
+
let twice = formatSource(&once).expect("second pass");
|
|
345
|
+
assert_eq!(once, twice, "not idempotent:\n{once}");
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
#[test]
|
|
349
|
+
fn format_record_embeds() {
|
|
350
|
+
let out = formatSource("record House(Ent,Cl,k:Int)\n").expect("format");
|
|
351
|
+
assert!(out.contains("record House(Ent, Cl, k: Int)"), "got: {out}");
|
|
352
|
+
}
|
plum-tooling/tree-sitter-plum/queries/plum/format.scm
CHANGED
|
@@ -18,6 +18,9 @@
|
|
|
18
18
|
(source
|
|
19
19
|
(record) @allow_blank_line_before)
|
|
20
20
|
|
|
21
|
+
(source
|
|
22
|
+
(trait) @allow_blank_line_before)
|
|
23
|
+
|
|
21
24
|
(source
|
|
22
25
|
(primitive) @allow_blank_line_before)
|
|
23
26
|
|
|
@@ -103,6 +106,8 @@
|
|
|
103
106
|
|
|
104
107
|
(record "record" @append_space)
|
|
105
108
|
|
|
109
|
+
(trait "trait" @append_space)
|
|
110
|
+
|
|
106
111
|
(primitive "primitive" @append_space)
|
|
107
112
|
|
|
108
113
|
(primitive
|
|
@@ -296,6 +301,21 @@
|
|
|
296
301
|
(_) @append_indent_end
|
|
297
302
|
.)
|
|
298
303
|
|
|
304
|
+
; `trait` bodies: methods indent under the `=`; the body is optional.
|
|
305
|
+
(trait
|
|
306
|
+
(fn) @prepend_hardline)
|
|
307
|
+
|
|
308
|
+
(trait
|
|
309
|
+
(fn) @allow_blank_line_before)
|
|
310
|
+
|
|
311
|
+
(trait
|
|
312
|
+
"=" @append_indent_start)
|
|
313
|
+
|
|
314
|
+
(trait
|
|
315
|
+
"="
|
|
316
|
+
(_) @append_indent_end
|
|
317
|
+
.)
|
|
318
|
+
|
|
299
319
|
; `enum_field` (a variant like `| Circle(r: Float)`) is ALIASED to the visible
|
|
300
320
|
; node kind "field"; only it has a literal "|" — safe to target unscoped by
|
|
301
321
|
; parent.
|
plum-tooling/tree-sitter-plum/queries/plum/highlights.scm
CHANGED
|
@@ -120,6 +120,7 @@
|
|
|
120
120
|
"primitive"
|
|
121
121
|
"struct"
|
|
122
122
|
"record"
|
|
123
|
+
"trait"
|
|
123
124
|
"fun"
|
|
124
125
|
"fun*"
|
|
125
126
|
"extern"
|
|
@@ -155,3 +156,6 @@
|
|
|
155
156
|
"crash" @keyword.control.exception
|
|
156
157
|
|
|
157
158
|
"match" @keyword
|
|
159
|
+
|
|
160
|
+
(trait
|
|
161
|
+
name: (type_identifier) @type.definition)
|
plum-tooling/tree-sitter-plum/queries/plum/tags.scm
CHANGED
|
@@ -7,6 +7,9 @@
|
|
|
7
7
|
(record
|
|
8
8
|
name: (type_identifier) @name) @definition.class
|
|
9
9
|
|
|
10
|
+
(trait
|
|
11
|
+
name: (type_identifier) @name) @definition.interface
|
|
12
|
+
|
|
10
13
|
(fn
|
|
11
14
|
name: (fn_identifier) @name) @definition.function
|
|
12
15
|
|