Repository: gleam-lang/gleam (rust)

Issue:
No newline inserted between records inside a const list if the first record spans multiple lines
```gleam
type Command {
  Command(name: String, description: String)
}

const commands = [
  Command(
    name: "dev",
    description: "Start a file watcher that automatically re-compiles your app on all file changes.",
  ), Command(name: "help", description: "Show this help text."),
]
```

when writing the same literal inside a function, the second command will be on its own line ~ :purple_heart: 

Pull request description:
Fix formatting of lists of constant records
This PR closes #3720 

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7da9b447a..8e4531ada 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -203,6 +203,7 @@
     Some(1)
   }
   ```
+
   ([Jiangda Wang](https://github.com/Frank-III))
 
 ### Bug Fixes
@@ -234,6 +235,10 @@
   would generate invalid TypeScript definitions.
   ([Richard Viney](https://github.com/richard-viney))
 
+- When splitting a constant list made of records, the formatter will keep each
+  item on its own line to make things easier to read.
+  ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
+
 ## v1.5.1 - 2024-09-26
 
 ### Bug Fixes
diff --git a/compiler-core/src/format.rs b/compiler-core/src/format.rs
index 998b05e14..80dbd3e70 100644
--- a/compiler-core/src/format.rs
+++ b/compiler-core/src/format.rs
@@ -545,7 +545,29 @@ impl<'comments> Formatter<'comments> {
             };
         }
 
-        let comma = flex_break(",", ", ");
+        let comma = match elements.first() {
+            // If the list is made of records and it gets too long we want to
+            // have each record on its own line instead of trying to fit as much
+            // as possible in each line. For example:
+            //
+            //    [
+            //       Some("wibble wobble"),
+            //       None,
+            //       Some("wobble wibble"),
+            //    ]
+            //
+            Some(Constant::Record { .. }) => break_(",", ", "),
+            // For all other items, if we have to break the list we still try to
+            // fit as much as possible into a single line instead of putting
+            // each item on its own separate line. For example:
+            //
+            //   [
+            //     1, 2, 3, 4,
+            //     5, 6, 7,
+            //   ]
+            //
+            Some(_) | None => flex_break(",", ", "),
+        };
         let elements = join(elements.iter().map(|e| self.const_expr(e)), comma);
 
         let doc = break_("[", "[").append(elements).nest(INDENT);


Test patch:
diff --git a/compiler-core/src/format/tests.rs b/compiler-core/src/format/tests.rs
index 063ae63c7..e9c1f876b 100644
--- a/compiler-core/src/format/tests.rs
+++ b/compiler-core/src/format/tests.rs
@@ -6435,3 +6435,25 @@ fn big_grapheme_cluster() {
 "#
     );
 }
+
+// https://github.com/gleam-lang/gleam/issues/3720
+#[test]
+fn record_inside_const_list() {
+    assert_format_rewrite!(
+        r#"const commands = [
+  Command(
+    "dev",
+    "Start a file watcher that automatically re-compiles your app on all file changes.",
+  ), Command("help", "Show this help text."),
+]
+"#,
+        r#"const commands = [
+  Command(
+    "dev",
+    "Start a file watcher that automatically re-compiles your app on all file changes.",
+  ),
+  Command("help", "Show this help text."),
+]
+"#
+    );
+}