plum

#treesitter#compiler#wasm

git clone https://git.pyrossh.dev/plum

A statically typed, imperative programming language inspired by rust, python


2ba2a03 — Peter John 2026-11-04T15:36:02+05:30
format: blank line after the module line
plum-core/src/formatter.rs CHANGED
@@ -74,7 +74,24 @@ pub fn formatSourceWithOpts(
74
74
  tolerate_parsing_errors: false,
75
75
  },
76
76
  )?;
77
- Ok(String::from_utf8(output).expect("Topiary output is valid UTF-8"))
77
+ let formatted = String::from_utf8(output).expect("Topiary output is valid UTF-8");
78
+ Ok(blankLineAfterModule(&formatted))
79
+ }
80
+
81
+ /// Ensures exactly one blank line after the leading `module` line (when anything
82
+ /// follows it). Topiary has no capture that inserts a blank line, so this is a text
83
+ /// pass on its output; Topiary keeps at most one blank line between top-level items,
84
+ /// so the result formats to itself.
85
+ pub fn blankLineAfterModule(source: &str) -> String {
86
+ let Some(end) = source.find('\n') else { return source.to_string() };
87
+ if !source.starts_with("module ") {
88
+ return source.to_string();
89
+ }
90
+ let rest = &source[end + 1..];
91
+ if rest.is_empty() || rest.starts_with('\n') {
92
+ return source.to_string();
93
+ }
94
+ format!("{}\n{}", &source[..=end], rest)
78
95
  }
79
96
 
80
97
  /// Collapses a `match` case (or `guard_case`) whose body is an indented block
plum-core/tests/formatter_test.rs CHANGED
@@ -494,3 +494,13 @@ fn format_multiline_record_fields_one_per_line() {
494
494
  fn format_mut_and_export_keywords() {
495
495
  assertFormatsUnchanged("record World(mut s: Int, t: Int)\n\nexport fun f() -> Int =\n 1\n");
496
496
  }
497
+
498
+ /// A blank line always follows the `module` line, and formatting again keeps it.
499
+ #[test]
500
+ fn format_blank_line_after_module() {
501
+ let input = "module app\nimport std/Int\n\nfun f() -> Int =\n 1\n";
502
+ let expected = "module app\n\nimport std/Int\n\nfun f() -> Int =\n 1\n";
503
+ assert_eq!(formatSource(input).unwrap(), expected);
504
+ assertFormatsUnchanged(expected);
505
+ assertFormatsUnchanged("module app\n");
506
+ }
plum-game/tests/fixtures/assets_fixture.plum CHANGED
@@ -1,4 +1,5 @@
1
1
  module assets_fixture
2
+
2
3
  import std/Int
3
4
  import std/Float
4
5
  import std/Str
plum-game/tests/fixtures/host_fixture.plum CHANGED
@@ -1,4 +1,5 @@
1
1
  module host_fixture
2
+
2
3
  import std/Int
3
4
  import std/Float
4
5
  import std/Str
plum-game/tests/fixtures/target_fixture.plum CHANGED
@@ -1,4 +1,5 @@
1
1
  module target_fixture
2
+
2
3
  import std/Int
3
4
  import std/Float
4
5
  import std/Str
plum-std/Array.plum CHANGED
@@ -1,4 +1,5 @@
1
1
  module std
2
+
2
3
  import std/Int
3
4
  import std/Float
4
5
  import std/Str
plum-std/Base64.plum CHANGED
@@ -1,4 +1,5 @@
1
1
  module std
2
+
2
3
  import std/Str
3
4
  import std/Buffer
4
5
  import std/Int
plum-std/Bool.plum CHANGED
@@ -1,4 +1,5 @@
1
1
  module std
2
+
2
3
  import std/Str
3
4
 
4
5
  # The API of the built-in `Bool` type: `Bool.parse` and `toStr` (also used by
plum-std/Buffer.plum CHANGED
@@ -1,4 +1,5 @@
1
1
  module std
2
+
2
3
  import std/Array
3
4
  import std/Str
4
5
  import std/Int
plum-std/Byte.plum CHANGED
@@ -1,4 +1,5 @@
1
1
  module std
2
+
2
3
  import std/Int
3
4
  import std/Float
4
5
  import std/Str
plum-std/Deque.plum CHANGED
@@ -1,4 +1,5 @@
1
1
  module std
2
+
2
3
  import std/Array
3
4
  import std/Slice
4
5
  import std/Int
plum-std/Float.plum CHANGED
@@ -1,4 +1,5 @@
1
1
  module std
2
+
2
3
  import std/Str
3
4
  import std/Int
4
5
  import std/Math
plum-std/Grid.plum CHANGED
@@ -1,4 +1,5 @@
1
1
  module std
2
+
2
3
  import std/Array
3
4
  import std/Int
4
5
  import std/Float
plum-std/Heap.plum CHANGED
@@ -1,4 +1,5 @@
1
1
  module std
2
+
2
3
  import std/Array
3
4
  import std/Slice
4
5
  import std/Int
plum-std/Int.plum CHANGED
@@ -1,4 +1,5 @@
1
1
  module std
2
+
2
3
  import std/Str
3
4
  import std/Float
4
5
  import std/Math
plum-std/Io.plum CHANGED
@@ -1,4 +1,5 @@
1
1
  module std
2
+
2
3
  import std/Int
3
4
  import std/Float
4
5
  import std/Str
plum-std/Map.plum CHANGED
@@ -1,4 +1,5 @@
1
1
  module std
2
+
2
3
  import std/Slice
3
4
  import std/Array
4
5
  import std/Int
plum-std/Math.plum CHANGED
@@ -1,4 +1,5 @@
1
1
  module std
2
+
2
3
  import std/Int
3
4
  import std/Float
4
5
 
plum-std/Mem.plum CHANGED
@@ -1,4 +1,5 @@
1
1
  module std
2
+
2
3
  import std/Int
3
4
  import std/Float
4
5
 
plum-std/Os.plum CHANGED
@@ -1,4 +1,5 @@
1
1
  module std
2
+
2
3
  import std/Slice
3
4
  import std/Str
4
5
  import std/Uuid
plum-std/Random.plum CHANGED
@@ -1,4 +1,5 @@
1
1
  module std
2
+
2
3
  import std/Int
3
4
  import std/Float
4
5
 
plum-std/Set.plum CHANGED
@@ -1,4 +1,5 @@
1
1
  module std
2
+
2
3
  import std/Map
3
4
  import std/Slice
4
5
  import std/Int
plum-std/Time.plum CHANGED
@@ -1,4 +1,5 @@
1
1
  module std
2
+
2
3
  import std/Int
3
4
  import std/Float
4
5
  import std/Str
plum-std/Uuid.plum CHANGED
@@ -1,4 +1,5 @@
1
1
  module std
2
+
2
3
  import std/Int
3
4
  import std/Float
4
5
  import std/Str
plum-std/game/Affine.plum CHANGED
@@ -1,4 +1,5 @@
1
1
  module std
2
+
2
3
  import std/Float
3
4
  import std/Math
4
5
  import std/game/Vec2
plum-std/game/Color.plum CHANGED
@@ -1,4 +1,5 @@
1
1
  module std
2
+
2
3
  import std/Float
3
4
 
4
5
  # An RGBA colour with each channel in 0..1.
plum-std/game/Game.plum CHANGED
@@ -1,4 +1,5 @@
1
1
  module std
2
+
2
3
  import std/Int
3
4
  import std/Float
4
5
  import std/Str
plum-std/game/Input.plum CHANGED
@@ -1,4 +1,5 @@
1
1
  module std
2
+
2
3
  import std/Int
3
4
  import std/Float
4
5
  import std/Slice
plum-std/game/Vec2.plum CHANGED
@@ -1,4 +1,5 @@
1
1
  module std
2
+
2
3
  import std/Float
3
4
  import std/Math
4
5
 
plum-std/game/functional/Anim.plum CHANGED
@@ -1,4 +1,5 @@
1
1
  module std
2
+
2
3
  import std/Int
3
4
  import std/Float
4
5
  import std/List
plum-std/game/functional/FunctionalScene.plum CHANGED
@@ -1,4 +1,5 @@
1
1
  module std
2
+
2
3
  import std/Int
3
4
  import std/Float
4
5
  import std/Str
plum-std/game/functional/Ui.plum CHANGED
@@ -1,4 +1,5 @@
1
1
  module std
2
+
2
3
  import std/Int
3
4
  import std/Float
4
5
  import std/Str
plum-std/game/imperative/Scene.plum CHANGED
@@ -1,4 +1,5 @@
1
1
  module std
2
+
2
3
  import std/Int
3
4
  import std/Float
4
5
  import std/Str
plum-std/game/pure/Actions.plum CHANGED
@@ -1,4 +1,5 @@
1
1
  module std
2
+
2
3
  import std/Slice
3
4
  import std/Int
4
5
  import std/Float
plum-std/game/pure/PureScene.plum CHANGED
@@ -1,4 +1,5 @@
1
1
  module std
2
+
2
3
  import std/Int
3
4
  import std/Float
4
5
  import std/Str
plum-std/game/pure/SceneInput.plum CHANGED
@@ -1,4 +1,5 @@
1
1
  module std
2
+
2
3
  import std/Int
3
4
  import std/Float
4
5
  import std/Str