Skip to content

Commit d858aa9

Browse files
committed
fix!: Take in byte spans
BREAKING CHANGE: This switches from char spans to byte spans
1 parent 027c95b commit d858aa9

File tree

4 files changed

+44
-38
lines changed

4 files changed

+44
-38
lines changed

Diff for: Cargo.lock

+12-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ maintenance = { status = "actively-developed" }
2525

2626
[dependencies]
2727
anstyle = "1.0.4"
28+
itertools = "0.12.1"
2829
unicode-width = "0.1.11"
2930

3031
[dev-dependencies]

Diff for: src/renderer/display_list.rs

+26-31
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
//!
3333
//! The above snippet has been built out of the following structure:
3434
use crate::snippet;
35+
use itertools::FoldWhile::{Continue, Done};
36+
use itertools::Itertools;
3537
use std::fmt::{Display, Write};
3638
use std::{cmp, fmt};
3739

@@ -804,13 +806,27 @@ fn format_header<'a>(
804806

805807
for item in body {
806808
if let DisplayLine::Source {
807-
line: DisplaySourceLine::Content { range, .. },
809+
line: DisplaySourceLine::Content { text, range },
808810
lineno,
809811
..
810812
} = item
811813
{
812814
if main_range >= range.0 && main_range <= range.1 {
813-
col = main_range - range.0 + 1;
815+
let char_column = text
816+
.chars()
817+
.map(|c| unicode_width::UnicodeWidthChar::width(c).unwrap_or(0))
818+
.chain(std::iter::once(1)) // treat the end of line as single-width
819+
.enumerate()
820+
.fold_while((0, 0), |(count, acc), (i, width)| {
821+
if acc <= main_range - range.0 {
822+
Continue((i, acc + width))
823+
} else {
824+
Done((count, acc))
825+
}
826+
})
827+
.into_inner()
828+
.0;
829+
col = char_column + 1;
814830
line_offset = lineno.unwrap_or(1);
815831
break;
816832
}
@@ -932,7 +948,7 @@ fn format_body(
932948
has_footer: bool,
933949
margin: Option<Margin>,
934950
) -> Vec<DisplayLine<'_>> {
935-
let source_len = slice.source.chars().count();
951+
let source_len = slice.source.as_bytes().iter().count();
936952
if let Some(bigger) = slice.annotations.iter().find_map(|x| {
937953
// Allow highlighting one past the last character in the source.
938954
if source_len + 1 < x.range.1 {
@@ -955,18 +971,14 @@ fn format_body(
955971
struct LineInfo {
956972
line_start_index: usize,
957973
line_end_index: usize,
958-
// How many spaces each character in the line take up when displayed
959-
char_widths: Vec<usize>,
960974
}
961975

962976
for (line, end_line) in CursorLines::new(slice.source) {
963-
let line_length = line.chars().count();
964-
let line_range = (current_index, current_index + line_length);
965-
let char_widths = line
977+
let line_length: usize = line
966978
.chars()
967979
.map(|c| unicode_width::UnicodeWidthChar::width(c).unwrap_or(0))
968-
.chain(std::iter::once(1)) // treat the end of line as single-width
969-
.collect::<Vec<_>>();
980+
.sum();
981+
let line_range = (current_index, current_index + line_length);
970982
body.push(DisplayLine::Source {
971983
lineno: Some(current_line),
972984
inline_marks: vec![],
@@ -978,7 +990,6 @@ fn format_body(
978990
line_info.push(LineInfo {
979991
line_start_index: line_range.0,
980992
line_end_index: line_range.1,
981-
char_widths,
982993
});
983994
current_line += 1;
984995
current_index += line_length + end_line as usize;
@@ -991,7 +1002,6 @@ fn format_body(
9911002
LineInfo {
9921003
line_start_index,
9931004
line_end_index,
994-
char_widths,
9951005
},
9961006
) in line_info.into_iter().enumerate()
9971007
{
@@ -1012,16 +1022,8 @@ fn format_body(
10121022
if start >= line_start_index && end <= line_end_index
10131023
|| start == line_end_index && end - start <= 1 =>
10141024
{
1015-
let annotation_start_col = char_widths
1016-
.iter()
1017-
.take(start - line_start_index)
1018-
.sum::<usize>()
1019-
- margin_left;
1020-
let annotation_end_col = char_widths
1021-
.iter()
1022-
.take(end - line_start_index)
1023-
.sum::<usize>()
1024-
- margin_left;
1025+
let annotation_start_col = start - line_start_index - margin_left;
1026+
let annotation_end_col = end - line_start_index - margin_left;
10251027
let range = (annotation_start_col, annotation_end_col);
10261028
body.insert(
10271029
body_idx + 1,
@@ -1064,10 +1066,7 @@ fn format_body(
10641066
});
10651067
}
10661068
} else {
1067-
let annotation_start_col = char_widths
1068-
.iter()
1069-
.take(start - line_start_index)
1070-
.sum::<usize>();
1069+
let annotation_start_col = start - line_start_index;
10711070
let range = (annotation_start_col, annotation_start_col + 1);
10721071
body.insert(
10731072
body_idx + 1,
@@ -1125,11 +1124,7 @@ fn format_body(
11251124
});
11261125
}
11271126

1128-
let end_mark = char_widths
1129-
.iter()
1130-
.take(end - line_start_index)
1131-
.sum::<usize>()
1132-
.saturating_sub(1);
1127+
let end_mark = (end - line_start_index).saturating_sub(1);
11331128
let range = (end_mark - margin_left, (end_mark + 1) - margin_left);
11341129
body.insert(
11351130
body_idx + 1,

Diff for: tests/formatter.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ fn test_point_to_double_width_characters() {
4141
line_start: 1,
4242
origin: Some("<current file>"),
4343
annotations: vec![SourceAnnotation {
44-
range: (6, 8),
44+
range: (12, 16),
4545
label: "world",
4646
annotation_type: AnnotationType::Error,
4747
}],
@@ -69,7 +69,7 @@ fn test_point_to_double_width_characters_across_lines() {
6969
line_start: 1,
7070
origin: Some("<current file>"),
7171
annotations: vec![SourceAnnotation {
72-
range: (2, 8),
72+
range: (4, 15),
7373
label: "Good morning",
7474
annotation_type: AnnotationType::Error,
7575
}],
@@ -100,12 +100,12 @@ fn test_point_to_double_width_characters_multiple() {
100100
origin: Some("<current file>"),
101101
annotations: vec![
102102
SourceAnnotation {
103-
range: (0, 3),
103+
range: (0, 6),
104104
label: "Sushi1",
105105
annotation_type: AnnotationType::Error,
106106
},
107107
SourceAnnotation {
108-
range: (6, 8),
108+
range: (11, 15),
109109
label: "Sushi2",
110110
annotation_type: AnnotationType::Note,
111111
},
@@ -136,7 +136,7 @@ fn test_point_to_double_width_characters_mixed() {
136136
line_start: 1,
137137
origin: Some("<current file>"),
138138
annotations: vec![SourceAnnotation {
139-
range: (6, 14),
139+
range: (12, 23),
140140
label: "New world",
141141
annotation_type: AnnotationType::Error,
142142
}],

0 commit comments

Comments
 (0)