@@ -184,41 +184,88 @@ fn fmt_value(value: &mut Value, config: &Config) {
184
184
match value {
185
185
Value :: Array ( arr) => {
186
186
if arr. to_string ( ) . len ( ) > config. max_array_line_len {
187
+ let old_trailing_comma = arr. trailing_comma ( ) ;
188
+ let new_trailing_comma = config. multiline_trailing_comma ;
189
+
190
+ let trailing = arr. trailing ( ) . as_str ( ) . unwrap_or_default ( ) . to_owned ( ) ;
191
+
187
192
let indent = " " . repeat ( config. indent_count ) ;
193
+ let arr_len = arr. len ( ) ;
188
194
189
- // Move all array elements onto a new line and indent them.
190
- for val in arr. iter_mut ( ) {
191
- // Trim exessive whitespace.
195
+ // Process all elements' prefix and suffix.
196
+ for ( i, val) in arr. iter_mut ( ) . enumerate ( ) {
192
197
let mut prefix = val. prefix ( ) . trim ( ) . to_owned ( ) ;
193
- let suffix = val. suffix ( ) . trim ( ) . to_owned ( ) ;
198
+ let suffix = val. suffix ( ) ;
199
+
200
+ let mut last_suffix = None ;
201
+
202
+ // Handle suffix: Add comma for the last element only.
203
+ let new_suffix = if i == arr_len - 1 {
204
+ if old_trailing_comma != new_trailing_comma {
205
+ // The last line's suffix must be cleared anyway,
206
+ // and append it to the prefix.
207
+ if !suffix. trim ( ) . is_empty ( ) {
208
+ last_suffix = Some ( suffix. trim ( ) ) ;
209
+ }
210
+ if new_trailing_comma {
211
+ "" . to_owned ( )
212
+ } else {
213
+ "" . to_owned ( ) + NEWLINE_PATTERN
214
+ }
215
+ } else {
216
+ suffix. to_owned ( )
217
+ }
218
+ } else {
219
+ suffix. trim_end ( ) . to_owned ( )
220
+ } ;
221
+
222
+ if let Some ( s) = last_suffix {
223
+ prefix. push_str ( & format ! ( "{NEWLINE_PATTERN}{s}" ) ) ;
224
+ prefix = prefix. trim ( ) . to_owned ( ) ;
225
+ }
194
226
195
- // Handle prefix comments. Put them on a dedicated line.
196
- if !prefix. is_empty ( ) {
197
- prefix. push_str ( NEWLINE_PATTERN ) ;
198
- prefix. push_str ( & indent) ;
227
+ if i == arr_len - 1 && !new_trailing_comma {
228
+ prefix. push_str ( & format ! ( "{NEWLINE_PATTERN}{}" , trailing. trim( ) ) ) ;
229
+ prefix = prefix. trim ( ) . to_owned ( ) ;
199
230
}
200
231
201
- val. decor_mut ( )
202
- . set_prefix ( format ! ( "{NEWLINE_PATTERN}{indent}{prefix}" ) ) ;
203
- val. decor_mut ( ) . set_suffix ( suffix) ;
232
+ let n_i = format ! ( "{NEWLINE_PATTERN}{indent}" ) ;
233
+
234
+ // Handle prefix: Add newline and indent, preserve comments.
235
+ let new_prefix = if !prefix. is_empty ( ) {
236
+ prefix
237
+ . lines ( )
238
+ . map ( |line| format ! ( "{n_i}{}" , line. trim( ) ) )
239
+ . collect :: < String > ( )
240
+ + & n_i
241
+ } else {
242
+ n_i
243
+ } ;
244
+
245
+ val. decor_mut ( ) . set_prefix ( new_prefix) ;
246
+ val. decor_mut ( ) . set_suffix ( new_suffix) ;
204
247
}
205
248
206
- // Fix up the last one.
207
- if let Some ( last) = arr. iter_mut ( ) . last ( ) {
208
- let suffix = last. suffix ( ) . to_owned ( ) ;
209
-
210
- let comma = if config. multiline_trailing_comma { "," } else { "" } ;
211
-
212
- last. decor_mut ( )
213
- . set_suffix ( format ! ( "{comma}{suffix}{NEWLINE_PATTERN}" ) ) ;
249
+ if old_trailing_comma != new_trailing_comma {
250
+ if new_trailing_comma {
251
+ let trailing = trailing. trim_end ( ) . to_owned ( ) ;
252
+ arr. set_trailing ( trailing + NEWLINE_PATTERN ) ;
253
+ } else {
254
+ arr. set_trailing ( "" . to_owned ( ) ) ;
255
+ }
214
256
}
257
+ arr. set_trailing_comma ( new_trailing_comma) ;
215
258
} else {
259
+ // Single-line array: Ensure no extra commas.
260
+ // Clear suffixes first to remove input commas.
261
+ for val in arr. iter_mut ( ) {
262
+ val. decor_mut ( ) . set_suffix ( "" ) ;
263
+ }
216
264
arr. fmt ( ) ;
265
+ arr. decor_mut ( ) . set_prefix ( " " ) ;
266
+ // Apply trailing comma to the last element if configured.
267
+ arr. set_trailing_comma ( config. always_trailing_comma ) ;
217
268
}
218
- // TODO: this is most likely after an equal sign but not always...
219
- arr. decor_mut ( ) . set_prefix ( " " ) ;
220
- // TODO: can this be moved into the else of the above if/else
221
- arr. set_trailing_comma ( config. always_trailing_comma ) ;
222
269
}
223
270
Value :: InlineTable ( table) => {
224
271
table. decor_mut ( ) . set_prefix ( " " ) ;
@@ -228,7 +275,11 @@ fn fmt_value(value: &mut Value, config: &Config) {
228
275
// get here from a headed table (`[header] key = val`)
229
276
val => {
230
277
if config. space_around_eq
231
- && val. decor ( ) . prefix ( ) . and_then ( |r| r. as_str ( ) ) . is_none_or ( str:: is_empty)
278
+ && val
279
+ . decor ( )
280
+ . prefix ( )
281
+ . and_then ( RawString :: as_str)
282
+ . is_none_or ( str:: is_empty)
232
283
{
233
284
val. decor_mut ( ) . set_prefix ( " " ) ;
234
285
}
@@ -414,4 +465,72 @@ mod test {
414
465
assert_ne ! ( input, toml. to_string( ) ) ;
415
466
// println!("{}", toml.to_string());
416
467
}
468
+
469
+ #[ test]
470
+ fn array_integration ( ) {
471
+ let input = r#"
472
+ [package]
473
+ authors = [
474
+ "Manish Goregaokar <[email protected] >",
475
+ "Andre Bogus <[email protected] >",
476
+ "Oliver Schneider <[email protected] >" # Here is a comment
477
+ ]
478
+ xyzabc = [
479
+ "foo",
480
+ "bar",
481
+ "baz",
482
+ ]
483
+ integration = [
484
+
485
+ # A feature comment that makes this line very long.
486
+ "git2",
487
+
488
+
489
+ "tempfile", # Here is another comment.
490
+ "abc", # Here is another comment at the end of the array.
491
+ ]
492
+ "# ;
493
+ let expected = r#"
494
+ [package]
495
+ authors = [
496
+ "Manish Goregaokar <[email protected] >",
497
+ "Andre Bogus <[email protected] >",
498
+ # Here is a comment
499
+ "Oliver Schneider <[email protected] >",
500
+ ]
501
+ xyzabc = ["foo", "bar", "baz"]
502
+ integration = [
503
+ # A feature comment that makes this line very long.
504
+ "git2",
505
+ "tempfile",
506
+ # Here is another comment.
507
+ "abc", # Here is another comment at the end of the array.
508
+ ]
509
+ "# ;
510
+ let mut toml = input. parse :: < DocumentMut > ( ) . unwrap ( ) ;
511
+ fmt_toml ( & mut toml, & Config :: new ( ) ) ;
512
+ similar_asserts:: assert_eq!( expected, toml. to_string( ) ) ;
513
+
514
+ let expected2 = r#"
515
+ [package]
516
+ authors = [
517
+ "Manish Goregaokar <[email protected] >",
518
+ "Andre Bogus <[email protected] >",
519
+ "Oliver Schneider <[email protected] >" # Here is a comment
520
+ ]
521
+ xyzabc = ["foo", "bar", "baz"]
522
+ integration = [
523
+ # A feature comment that makes this line very long.
524
+ "git2",
525
+ "tempfile",
526
+ # Here is another comment.
527
+ # Here is another comment at the end of the array.
528
+ "abc"
529
+ ]
530
+ "# ;
531
+ let mut toml = input. parse :: < DocumentMut > ( ) . unwrap ( ) ;
532
+ let cfg = Config { multiline_trailing_comma : false , ..Config :: new ( ) } ;
533
+ fmt_toml ( & mut toml, & cfg) ;
534
+ similar_asserts:: assert_eq!( expected2, toml. to_string( ) ) ;
535
+ }
417
536
}
0 commit comments