Skip to content

Commit c79ab5d

Browse files
committed
fix: Use correct offset when trimming unicode char
1 parent 22d0f7a commit c79ab5d

File tree

2 files changed

+36
-29
lines changed

2 files changed

+36
-29
lines changed

src/renderer/render.rs

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -664,12 +664,12 @@ fn render_snippet_annotations(
664664
let mut label_right_margin = 0;
665665
let mut max_line_len = 0;
666666
for line_info in annotated_lines {
667-
max_line_len = max(max_line_len, line_info.line.len());
667+
max_line_len = max(max_line_len, str_width(line_info.line));
668668
for ann in &line_info.annotations {
669669
span_right_margin = max(span_right_margin, ann.start.display);
670670
span_right_margin = max(span_right_margin, ann.end.display);
671671
// FIXME: account for labels not in the same line
672-
let label_right = ann.label.as_ref().map_or(0, |l| l.len() + 1);
672+
let label_right = ann.label.as_ref().map_or(0, |l| str_width(l) + 1);
673673
label_right_margin = max(label_right_margin, ann.end.display + label_right);
674674
}
675675
}
@@ -1995,23 +1995,34 @@ fn draw_line(
19951995
// Create the source line we will highlight.
19961996
let mut left = margin.left(line_len);
19971997
let right = margin.right(line_len);
1998-
// FIXME: The following code looks fishy. See #132860.
1999-
// On long lines, we strip the source line, accounting for unicode.
1998+
20001999
let mut taken = 0;
20012000
let mut skipped = 0;
20022001
let code: String = source_string
20032002
.chars()
20042003
.skip_while(|ch| {
2005-
skipped += char_width(*ch);
2006-
skipped <= left
2004+
let w = char_width(*ch);
2005+
// If `skipped` is less than `left`, always skip the next `ch`,
2006+
// even if `ch` is a multi-width char that would make `skipped`
2007+
// exceed `left`. This ensures that we do not exceed term width on
2008+
// source lines.
2009+
if skipped < left {
2010+
skipped += w;
2011+
true
2012+
} else {
2013+
false
2014+
}
20072015
})
20082016
.take_while(|ch| {
20092017
// Make sure that the trimming on the right will fall within the terminal width.
20102018
taken += char_width(*ch);
20112019
taken <= (right - left)
20122020
})
20132021
.collect();
2014-
2022+
// If we skipped more than `left`, adjust `left` to account for it.
2023+
if skipped > left {
2024+
left += skipped - left;
2025+
}
20152026
let placeholder = renderer.decor_style.margin();
20162027
let padding = str_width(placeholder);
20172028
let (width_taken, bytes_taken) = if margin.was_cut_left() {
@@ -2027,10 +2038,6 @@ fn draw_line(
20272038
}
20282039
}
20292040

2030-
if width_taken > padding {
2031-
left -= width_taken - padding;
2032-
}
2033-
20342041
buffer.puts(
20352042
line_offset,
20362043
code_offset,

tests/formatter.rs

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2965,7 +2965,7 @@ fn trim_unicode_annotate_ascii_end_with_label() {
29652965
let expected_ascii = str![[r#"
29662966
|
29672967
1 | ... 的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。*/?
2968-
| ^ expected item
2968+
| ^ expected item
29692969
"#]];
29702970

29712971
let renderer = Renderer::plain();
@@ -2974,7 +2974,7 @@ fn trim_unicode_annotate_ascii_end_with_label() {
29742974
let expected_unicode = str![[r#"
29752975
╭▸
29762976
1 │ … 宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。*/?
2977-
╰╴ ━ expected item
2977+
╰╴ ━ expected item
29782978
"#]];
29792979
let renderer = renderer.decor_style(DecorStyle::Unicode);
29802980
assert_data_eq!(renderer.render(input), expected_unicode);
@@ -2988,17 +2988,17 @@ fn trim_unicode_annotate_ascii_end_no_label() {
29882988

29892989
let expected_ascii = str![[r#"
29902990
|
2991-
1 | ... 这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。*/
2992-
| ^
2991+
1 | ... 这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。*/?
2992+
| ^
29932993
"#]];
29942994

29952995
let renderer = Renderer::plain();
29962996
assert_data_eq!(renderer.render(input), expected_ascii);
29972997

29982998
let expected_unicode = str![[r#"
29992999
╭▸
3000-
1 │ … 。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。*/
3001-
╰╴
3000+
1 │ … 。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。*/?
3001+
╰╴ ━
30023002
"#]];
30033003
let renderer = renderer.decor_style(DecorStyle::Unicode);
30043004
assert_data_eq!(renderer.render(input), expected_unicode);
@@ -3018,7 +3018,7 @@ fn trim_unicode_annotate_unicode_end_with_label() {
30183018
let expected_ascii = str![[r#"
30193019
|
30203020
1 | ... 的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。*/好
3021-
| ^^ expected item
3021+
| ^^ expected item
30223022
"#]];
30233023

30243024
let renderer = Renderer::plain();
@@ -3027,7 +3027,7 @@ fn trim_unicode_annotate_unicode_end_with_label() {
30273027
let expected_unicode = str![[r#"
30283028
╭▸
30293029
1 │ … 宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。*/好
3030-
╰╴ ━━ expected item
3030+
╰╴ ━━ expected item
30313031
"#]];
30323032
let renderer = renderer.decor_style(DecorStyle::Unicode);
30333033
assert_data_eq!(renderer.render(input), expected_unicode);
@@ -3041,17 +3041,17 @@ fn trim_unicode_annotate_unicode_end_no_label() {
30413041

30423042
let expected_ascii = str![[r#"
30433043
|
3044-
1 | ... 这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。*/
3045-
| ^^
3044+
1 | ... 这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。*/
3045+
| ^^
30463046
"#]];
30473047

30483048
let renderer = Renderer::plain();
30493049
assert_data_eq!(renderer.render(input), expected_ascii);
30503050

30513051
let expected_unicode = str![[r#"
30523052
╭▸
3053-
1 │ … 。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。*/
3054-
╰╴ ━━
3053+
1 │ … 。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。*/
3054+
╰╴ ━━
30553055
"#]];
30563056
let renderer = renderer.decor_style(DecorStyle::Unicode);
30573057
assert_data_eq!(renderer.render(input), expected_unicode);
@@ -3070,17 +3070,17 @@ fn trim_unicode_annotate_unicode_middle_with_label() {
30703070

30713071
let expected_ascii = str![[r#"
30723072
|
3073-
1 | ... 这是宽的。这是宽的。这是宽的...
3074-
| ^^ expected item
3073+
1 | ... 这是宽的。这是宽的。这是宽的...
3074+
| ^^ expected item
30753075
"#]];
30763076

30773077
let renderer = Renderer::plain().term_width(43);
30783078
assert_data_eq!(renderer.render(input), expected_ascii);
30793079

30803080
let expected_unicode = str![[r#"
30813081
╭▸
3082-
1 │ … 。这是宽的。这是宽的。这是宽的。…
3083-
╰╴ ━━ expected item
3082+
1 │ … 。这是宽的。这是宽的。这是宽的。
3083+
╰╴ ━━ expected item
30843084
"#]];
30853085
let renderer = renderer.decor_style(DecorStyle::Unicode);
30863086
assert_data_eq!(renderer.render(input), expected_unicode);
@@ -3095,7 +3095,7 @@ fn trim_unicode_annotate_unicode_middle_no_label() {
30953095
let expected_ascii = str![[r#"
30963096
|
30973097
1 | ... 是宽的。这是宽的。这是宽的。这...
3098-
| ^^
3098+
| ^^
30993099
"#]];
31003100

31013101
let renderer = Renderer::plain().term_width(43);
@@ -3104,7 +3104,7 @@ fn trim_unicode_annotate_unicode_middle_no_label() {
31043104
let expected_unicode = str![[r#"
31053105
╭▸
31063106
1 │ … 这是宽的。这是宽的。这是宽的。这是…
3107-
╰╴ ━━
3107+
╰╴ ━━
31083108
"#]];
31093109
let renderer = renderer.decor_style(DecorStyle::Unicode);
31103110
assert_data_eq!(renderer.render(input), expected_unicode);

0 commit comments

Comments
 (0)