Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 8b3788d

Browse files
committed
rewrite_string: allow to break on a boundary character that is on edge
1 parent bb74428 commit 8b3788d

File tree

5 files changed

+78
-27
lines changed

5 files changed

+78
-27
lines changed

src/string.rs

Lines changed: 70 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,12 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option<String>
118118
}
119119

120120
// The input starting at cur_start needs to be broken
121-
match break_string(cur_max_chars, fmt.trim_end, &graphemes[cur_start..]) {
121+
match break_string(
122+
cur_max_chars,
123+
fmt.trim_end,
124+
fmt.line_end,
125+
&graphemes[cur_start..],
126+
) {
122127
SnippetState::LineEnd(line, len) => {
123128
result.push_str(&line);
124129
result.push_str(fmt.line_end);
@@ -190,7 +195,7 @@ enum SnippetState {
190195

191196
/// Break the input string at a boundary character around the offset `max_chars`. A boundary
192197
/// character is either a punctuation or a whitespace.
193-
fn break_string(max_chars: usize, trim_end: bool, input: &[&str]) -> SnippetState {
198+
fn break_string(max_chars: usize, trim_end: bool, line_end: &str, input: &[&str]) -> SnippetState {
194199
let break_at = |index /* grapheme at index is included */| {
195200
// Take in any whitespaces to the left/right of `input[index]` while
196201
// preserving line feeds
@@ -242,6 +247,17 @@ fn break_string(max_chars: usize, trim_end: bool, input: &[&str]) -> SnippetStat
242247
};
243248

244249
// Find the position in input for breaking the string
250+
if line_end.is_empty()
251+
&& trim_end
252+
&& !is_whitespace(input[max_chars - 1])
253+
&& is_whitespace(input[max_chars])
254+
{
255+
// At a breaking point already
256+
// The line won't invalidate the rewriting because:
257+
// - no extra space needed for the line_end character
258+
// - extra whitespaces to the right can be trimmed
259+
return break_at(max_chars - 1);
260+
}
245261
match input[0..max_chars]
246262
.iter()
247263
.rposition(|grapheme| is_whitespace(grapheme))
@@ -304,11 +320,11 @@ mod test {
304320
let string = "Placerat felis. Mauris porta ante sagittis purus.";
305321
let graphemes = UnicodeSegmentation::graphemes(&*string, false).collect::<Vec<&str>>();
306322
assert_eq!(
307-
break_string(20, false, &graphemes[..]),
323+
break_string(20, false, "", &graphemes[..]),
308324
SnippetState::LineEnd("Placerat felis. ".to_string(), 16)
309325
);
310326
assert_eq!(
311-
break_string(20, true, &graphemes[..]),
327+
break_string(20, true, "", &graphemes[..]),
312328
SnippetState::LineEnd("Placerat felis.".to_string(), 16)
313329
);
314330
}
@@ -318,7 +334,7 @@ mod test {
318334
let string = "Placerat_felis._Mauris_porta_ante_sagittis_purus.";
319335
let graphemes = UnicodeSegmentation::graphemes(&*string, false).collect::<Vec<&str>>();
320336
assert_eq!(
321-
break_string(20, false, &graphemes[..]),
337+
break_string(20, false, "", &graphemes[..]),
322338
SnippetState::LineEnd("Placerat_felis.".to_string(), 15)
323339
);
324340
}
@@ -328,11 +344,11 @@ mod test {
328344
let string = "Venenatis_tellus_vel_tellus. Aliquam aliquam dolor at justo.";
329345
let graphemes = UnicodeSegmentation::graphemes(&*string, false).collect::<Vec<&str>>();
330346
assert_eq!(
331-
break_string(20, false, &graphemes[..]),
347+
break_string(20, false, "", &graphemes[..]),
332348
SnippetState::LineEnd("Venenatis_tellus_vel_tellus. ".to_string(), 29)
333349
);
334350
assert_eq!(
335-
break_string(20, true, &graphemes[..]),
351+
break_string(20, true, "", &graphemes[..]),
336352
SnippetState::LineEnd("Venenatis_tellus_vel_tellus.".to_string(), 29)
337353
);
338354
}
@@ -342,7 +358,7 @@ mod test {
342358
let string = "Venenatis_tellus_vel_tellus";
343359
let graphemes = UnicodeSegmentation::graphemes(&*string, false).collect::<Vec<&str>>();
344360
assert_eq!(
345-
break_string(20, false, &graphemes[..]),
361+
break_string(20, false, "", &graphemes[..]),
346362
SnippetState::EndOfInput("Venenatis_tellus_vel_tellus".to_string())
347363
);
348364
}
@@ -352,21 +368,21 @@ mod test {
352368
let string = "Neque in sem. \n Pellentesque tellus augue.";
353369
let graphemes = UnicodeSegmentation::graphemes(&*string, false).collect::<Vec<&str>>();
354370
assert_eq!(
355-
break_string(15, false, &graphemes[..]),
371+
break_string(15, false, "", &graphemes[..]),
356372
SnippetState::EndWithLineFeed("Neque in sem. \n".to_string(), 20)
357373
);
358374
assert_eq!(
359-
break_string(25, false, &graphemes[..]),
375+
break_string(25, false, "", &graphemes[..]),
360376
SnippetState::EndWithLineFeed("Neque in sem. \n".to_string(), 20)
361377
);
362-
// if `StringFormat::line_end` is true, then the line feed does not matter anymore
378+
363379
assert_eq!(
364-
break_string(15, true, &graphemes[..]),
365-
SnippetState::LineEnd("Neque in sem.".to_string(), 26)
380+
break_string(15, true, "", &graphemes[..]),
381+
SnippetState::LineEnd("Neque in sem.".to_string(), 19)
366382
);
367383
assert_eq!(
368-
break_string(25, true, &graphemes[..]),
369-
SnippetState::LineEnd("Neque in sem.".to_string(), 26)
384+
break_string(25, true, "", &graphemes[..]),
385+
SnippetState::EndWithLineFeed("Neque in sem.\n".to_string(), 20)
370386
);
371387
}
372388

@@ -375,11 +391,11 @@ mod test {
375391
let string = "Neque in sem. Pellentesque tellus augue.";
376392
let graphemes = UnicodeSegmentation::graphemes(&*string, false).collect::<Vec<&str>>();
377393
assert_eq!(
378-
break_string(20, false, &graphemes[..]),
394+
break_string(20, false, "", &graphemes[..]),
379395
SnippetState::LineEnd("Neque in sem. ".to_string(), 25)
380396
);
381397
assert_eq!(
382-
break_string(20, true, &graphemes[..]),
398+
break_string(20, true, "", &graphemes[..]),
383399
SnippetState::LineEnd("Neque in sem.".to_string(), 25)
384400
);
385401
}
@@ -390,11 +406,11 @@ mod test {
390406

391407
let graphemes = UnicodeSegmentation::graphemes(&*string, false).collect::<Vec<&str>>();
392408
assert_eq!(
393-
break_string(25, false, &graphemes[..]),
409+
break_string(25, false, "", &graphemes[..]),
394410
SnippetState::EndWithLineFeed("Nulla\n".to_string(), 6)
395411
);
396412
assert_eq!(
397-
break_string(25, true, &graphemes[..]),
413+
break_string(25, true, "", &graphemes[..]),
398414
SnippetState::EndWithLineFeed("Nulla\n".to_string(), 6)
399415
);
400416

@@ -559,4 +575,39 @@ mod test {
559575
Some("Aenean\n //\n // metus. Vestibulum ac\n // lacus.".to_string())
560576
);
561577
}
578+
579+
#[test]
580+
fn boundary_on_edge() {
581+
let config: Config = Default::default();
582+
let mut fmt = StringFormat {
583+
opener: "",
584+
closer: "",
585+
line_start: "// ",
586+
line_end: "",
587+
shape: Shape::legacy(13, Indent::from_width(&config, 4)),
588+
trim_end: true,
589+
config: &config,
590+
};
591+
592+
let comment = "Aenean metus. Vestibulum ac lacus.";
593+
assert_eq!(
594+
rewrite_string(comment, &fmt),
595+
Some("Aenean metus.\n // Vestibulum ac\n // lacus.".to_string())
596+
);
597+
598+
fmt.trim_end = false;
599+
let comment = "Vestibulum ac lacus.";
600+
assert_eq!(
601+
rewrite_string(comment, &fmt),
602+
Some("Vestibulum \n // ac lacus.".to_string())
603+
);
604+
605+
fmt.trim_end = true;
606+
fmt.line_end = "\\";
607+
let comment = "Vestibulum ac lacus.";
608+
assert_eq!(
609+
rewrite_string(comment, &fmt),
610+
Some("Vestibulum\\\n // ac lacus.".to_string())
611+
);
612+
}
562613
}

tests/target/comment5.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
// rustfmt-wrap_comments: true
33

44
//@ special comment
5-
//@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec adiam
6-
//@ lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam
5+
//@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec adiam lectus.
6+
//@ Sed sit amet ipsum mauris. Maecenas congue ligula ac quam
77
//@
88
//@ foo
99
fn test() {}

tests/target/enum.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,8 @@ pub enum Bencoding<'i> {
145145
Int(i64),
146146
List(Vec<Bencoding<'i>>),
147147
/// A bencoded dict value. The first element the slice of bytes in the
148-
/// source that the dict is composed of. The second is the dict,
149-
/// decoded into an ordered map.
148+
/// source that the dict is composed of. The second is the dict, decoded
149+
/// into an ordered map.
150150
// TODO make Dict "structlike" AKA name the two values.
151151
Dict(&'i [u8], BTreeMap<&'i [u8], Bencoding<'i>>),
152152
}

tests/target/struct_lits.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ fn main() {
4040

4141
A {
4242
// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit
43-
// amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante
44-
// hendrerit. Donec et mollis dolor.
43+
// amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit.
44+
// Donec et mollis dolor.
4545
first: item(),
4646
// Praesent et diam eget libero egestas mattis sit amet vitae augue.
4747
// Nam tincidunt congue enim, ut porta lorem lacinia consectetur.

tests/target/struct_lits_multiline.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ fn main() {
5050

5151
A {
5252
// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit
53-
// amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante
54-
// hendrerit. Donec et mollis dolor.
53+
// amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit.
54+
// Donec et mollis dolor.
5555
first: item(),
5656
// Praesent et diam eget libero egestas mattis sit amet vitae augue.
5757
// Nam tincidunt congue enim, ut porta lorem lacinia consectetur.

0 commit comments

Comments
 (0)