Skip to content

Commit 86f2be9

Browse files
authored
Merge pull request #90 from Muscraft/use-bytes
fix!: Take in byte spans
2 parents 027c95b + c3bd0c3 commit 86f2be9

File tree

10 files changed

+75
-61
lines changed

10 files changed

+75
-61
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: benches/simple.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,12 @@ fn create_snippet(renderer: Renderer) {
3838
SourceAnnotation {
3939
label: "expected `Option<String>` because of return type",
4040
annotation_type: AnnotationType::Warning,
41-
range: (5, 19),
41+
range: 5..19,
4242
},
4343
SourceAnnotation {
4444
label: "expected enum `std::option::Option`",
4545
annotation_type: AnnotationType::Error,
46-
range: (26, 724),
46+
range: 26..724,
4747
},
4848
],
4949
}],

Diff for: examples/expected_type.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@ fn main() {
2020
SourceAnnotation {
2121
label: "",
2222
annotation_type: AnnotationType::Error,
23-
range: (193, 195),
23+
range: 193..195,
2424
},
2525
SourceAnnotation {
2626
label: "while parsing this struct",
2727
annotation_type: AnnotationType::Info,
28-
range: (34, 50),
28+
range: 34..50,
2929
},
3030
],
3131
}],

Diff for: examples/footer.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ fn main() {
2121
fold: false,
2222
annotations: vec![SourceAnnotation {
2323
label: "expected struct `annotate_snippets::snippet::Slice`, found reference",
24-
range: (21, 24),
24+
range: 21..24,
2525
annotation_type: AnnotationType::Error,
2626
}],
2727
}],

Diff for: examples/format.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,12 @@ fn main() {
3232
SourceAnnotation {
3333
label: "expected `Option<String>` because of return type",
3434
annotation_type: AnnotationType::Warning,
35-
range: (5, 19),
35+
range: 5..19,
3636
},
3737
SourceAnnotation {
3838
label: "expected enum `std::option::Option`",
3939
annotation_type: AnnotationType::Error,
40-
range: (26, 724),
40+
range: 26..724,
4141
},
4242
],
4343
}],

Diff for: src/renderer/display_list.rs

+43-44
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,10 @@
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};
38+
use std::ops::Range;
3639
use std::{cmp, fmt};
3740

3841
use crate::renderer::{stylesheet::Stylesheet, Margin, Style};
@@ -766,7 +769,7 @@ fn format_slice(
766769
has_footer: bool,
767770
margin: Option<Margin>,
768771
) -> Vec<DisplayLine<'_>> {
769-
let main_range = slice.annotations.first().map(|x| x.range.0);
772+
let main_range = slice.annotations.first().map(|x| x.range.start);
770773
let origin = slice.origin;
771774
let need_empty_header = origin.is_some() || is_first;
772775
let mut body = format_body(slice, need_empty_header, has_footer, margin);
@@ -804,13 +807,27 @@ fn format_header<'a>(
804807

805808
for item in body {
806809
if let DisplayLine::Source {
807-
line: DisplaySourceLine::Content { range, .. },
810+
line: DisplaySourceLine::Content { text, range },
808811
lineno,
809812
..
810813
} = item
811814
{
812815
if main_range >= range.0 && main_range <= range.1 {
813-
col = main_range - range.0 + 1;
816+
let char_column = text
817+
.chars()
818+
.map(|c| unicode_width::UnicodeWidthChar::width(c).unwrap_or(0))
819+
.chain(std::iter::once(1)) // treat the end of line as single-width
820+
.enumerate()
821+
.fold_while((0, 0), |(count, acc), (i, width)| {
822+
if acc <= main_range - range.0 {
823+
Continue((i, acc + width))
824+
} else {
825+
Done((count, acc))
826+
}
827+
})
828+
.into_inner()
829+
.0;
830+
col = char_column + 1;
814831
line_offset = lineno.unwrap_or(1);
815832
break;
816833
}
@@ -932,11 +949,11 @@ fn format_body(
932949
has_footer: bool,
933950
margin: Option<Margin>,
934951
) -> Vec<DisplayLine<'_>> {
935-
let source_len = slice.source.chars().count();
952+
let source_len = slice.source.len();
936953
if let Some(bigger) = slice.annotations.iter().find_map(|x| {
937954
// Allow highlighting one past the last character in the source.
938-
if source_len + 1 < x.range.1 {
939-
Some(x.range)
955+
if source_len + 1 < x.range.end {
956+
Some(&x.range)
940957
} else {
941958
None
942959
}
@@ -955,18 +972,14 @@ fn format_body(
955972
struct LineInfo {
956973
line_start_index: usize,
957974
line_end_index: usize,
958-
// How many spaces each character in the line take up when displayed
959-
char_widths: Vec<usize>,
960975
}
961976

962977
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
978+
let line_length: usize = line
966979
.chars()
967980
.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<_>>();
981+
.sum();
982+
let line_range = (current_index, current_index + line_length);
970983
body.push(DisplayLine::Source {
971984
lineno: Some(current_line),
972985
inline_marks: vec![],
@@ -978,7 +991,6 @@ fn format_body(
978991
line_info.push(LineInfo {
979992
line_start_index: line_range.0,
980993
line_end_index: line_range.1,
981-
char_widths,
982994
});
983995
current_line += 1;
984996
current_index += line_length + end_line as usize;
@@ -991,7 +1003,6 @@ fn format_body(
9911003
LineInfo {
9921004
line_start_index,
9931005
line_end_index,
994-
char_widths,
9951006
},
9961007
) in line_info.into_iter().enumerate()
9971008
{
@@ -1007,21 +1018,13 @@ fn format_body(
10071018
_ => DisplayAnnotationType::from(annotation.annotation_type),
10081019
};
10091020
match annotation.range {
1010-
(start, _) if start > line_end_index => true,
1011-
(start, end)
1021+
Range { start, .. } if start > line_end_index => true,
1022+
Range { start, end }
10121023
if start >= line_start_index && end <= line_end_index
10131024
|| start == line_end_index && end - start <= 1 =>
10141025
{
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;
1026+
let annotation_start_col = start - line_start_index - margin_left;
1027+
let annotation_end_col = end - line_start_index - margin_left;
10251028
let range = (annotation_start_col, annotation_end_col);
10261029
body.insert(
10271030
body_idx + 1,
@@ -1045,7 +1048,7 @@ fn format_body(
10451048
annotation_line_count += 1;
10461049
false
10471050
}
1048-
(start, end)
1051+
Range { start, end }
10491052
if start >= line_start_index
10501053
&& start <= line_end_index
10511054
&& end > line_end_index =>
@@ -1064,10 +1067,7 @@ fn format_body(
10641067
});
10651068
}
10661069
} else {
1067-
let annotation_start_col = char_widths
1068-
.iter()
1069-
.take(start - line_start_index)
1070-
.sum::<usize>();
1070+
let annotation_start_col = start - line_start_index;
10711071
let range = (annotation_start_col, annotation_start_col + 1);
10721072
body.insert(
10731073
body_idx + 1,
@@ -1092,7 +1092,7 @@ fn format_body(
10921092
}
10931093
true
10941094
}
1095-
(start, end) if start < line_start_index && end > line_end_index => {
1095+
Range { start, end } if start < line_start_index && end > line_end_index => {
10961096
if let DisplayLine::Source {
10971097
ref mut inline_marks,
10981098
..
@@ -1107,7 +1107,7 @@ fn format_body(
11071107
}
11081108
true
11091109
}
1110-
(start, end)
1110+
Range { start, end }
11111111
if start < line_start_index
11121112
&& end >= line_start_index
11131113
&& end <= line_end_index =>
@@ -1125,11 +1125,7 @@ fn format_body(
11251125
});
11261126
}
11271127

1128-
let end_mark = char_widths
1129-
.iter()
1130-
.take(end - line_start_index)
1131-
.sum::<usize>()
1132-
.saturating_sub(1);
1128+
let end_mark = (end - line_start_index).saturating_sub(1);
11331129
let range = (end_mark - margin_left, (end_mark + 1) - margin_left);
11341130
body.insert(
11351131
body_idx + 1,
@@ -1380,7 +1376,7 @@ mod tests {
13801376
let line_2 = "This is line 2";
13811377
let source = [line_1, line_2].join("\n");
13821378
// In line 2
1383-
let range = (22, 24);
1379+
let range = 22..24;
13841380
let input = snippet::Snippet {
13851381
title: None,
13861382
footer: vec![],
@@ -1389,7 +1385,7 @@ mod tests {
13891385
line_start: 5402,
13901386
origin: None,
13911387
annotations: vec![snippet::SourceAnnotation {
1392-
range,
1388+
range: range.clone(),
13931389
label: "Test annotation",
13941390
annotation_type: snippet::AnnotationType::Info,
13951391
}],
@@ -1430,7 +1426,10 @@ mod tests {
14301426
style: DisplayTextStyle::Regular,
14311427
}],
14321428
},
1433-
range: (range.0 - (line_1.len() + 1), range.1 - (line_1.len() + 1)),
1429+
range: (
1430+
range.start - (line_1.len() + 1),
1431+
range.end - (line_1.len() + 1),
1432+
),
14341433
annotation_type: DisplayAnnotationType::Info,
14351434
annotation_part: DisplayAnnotationPart::Standalone,
14361435
},
@@ -1480,7 +1479,7 @@ mod tests {
14801479
footer: vec![],
14811480
slices: vec![snippet::Slice {
14821481
annotations: vec![snippet::SourceAnnotation {
1483-
range: (0, source.len() + 2),
1482+
range: 0..source.len() + 2,
14841483
label,
14851484
annotation_type: snippet::AnnotationType::Error,
14861485
}],
@@ -1507,7 +1506,7 @@ mod tests {
15071506
line_start: 1,
15081507
origin: Some("<current file>"),
15091508
annotations: vec![snippet::SourceAnnotation {
1510-
range: (19, 23),
1509+
range: 19..23,
15111510
label: "oops",
15121511
annotation_type: snippet::AnnotationType::Error,
15131512
}],

Diff for: src/snippet.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
//! };
3232
//! ```
3333
34+
use std::ops::Range;
35+
3436
/// Primary structure provided for formatting
3537
#[derive(Debug, Default)]
3638
pub struct Snippet<'a> {
@@ -70,7 +72,8 @@ pub enum AnnotationType {
7072
/// An annotation for a `Slice`.
7173
#[derive(Debug)]
7274
pub struct SourceAnnotation<'a> {
73-
pub range: (usize, usize),
75+
/// The byte range of the annotation in the `source` string
76+
pub range: Range<usize>,
7477
pub label: &'a str,
7578
pub annotation_type: AnnotationType,
7679
}

Diff for: tests/fixtures/deserialize.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use serde::{Deserialize, Deserializer, Serialize};
2+
use std::ops::Range;
23

34
use annotate_snippets::{
45
renderer::Margin, Annotation, AnnotationType, Renderer, Slice, Snippet, SourceAnnotation,
@@ -122,7 +123,7 @@ where
122123
#[derive(Serialize, Deserialize)]
123124
#[serde(remote = "SourceAnnotation")]
124125
pub struct SourceAnnotationDef<'a> {
125-
pub range: (usize, usize),
126+
pub range: Range<usize>,
126127
#[serde(borrow)]
127128
pub label: &'a str,
128129
#[serde(with = "AnnotationTypeDef")]

0 commit comments

Comments
 (0)