32
32
//!
33
33
//! The above snippet has been built out of the following structure:
34
34
use crate::snippet;
35
+ use itertools::FoldWhile::{Continue, Done};
36
+ use itertools::Itertools;
35
37
use std::fmt::{Display, Write};
36
38
use std::{cmp, fmt};
37
39
@@ -804,13 +806,27 @@ fn format_header<'a>(
804
806
805
807
for item in body {
806
808
if let DisplayLine::Source {
807
- line: DisplaySourceLine::Content { range, .. },
809
+ line: DisplaySourceLine::Content { text, range },
808
810
lineno,
809
811
..
810
812
} = item
811
813
{
812
814
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;
814
830
line_offset = lineno.unwrap_or(1);
815
831
break;
816
832
}
@@ -932,7 +948,7 @@ fn format_body(
932
948
has_footer: bool,
933
949
margin: Option<Margin>,
934
950
) -> Vec<DisplayLine<'_>> {
935
- let source_len = slice.source.chars ().count();
951
+ let source_len = slice.source.as_bytes().iter ().count();
936
952
if let Some(bigger) = slice.annotations.iter().find_map(|x| {
937
953
// Allow highlighting one past the last character in the source.
938
954
if source_len + 1 < x.range.1 {
@@ -955,18 +971,14 @@ fn format_body(
955
971
struct LineInfo {
956
972
line_start_index: usize,
957
973
line_end_index: usize,
958
- // How many spaces each character in the line take up when displayed
959
- char_widths: Vec<usize>,
960
974
}
961
975
962
976
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
966
978
.chars()
967
979
.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 );
970
982
body.push(DisplayLine::Source {
971
983
lineno: Some(current_line),
972
984
inline_marks: vec![],
@@ -978,7 +990,6 @@ fn format_body(
978
990
line_info.push(LineInfo {
979
991
line_start_index: line_range.0,
980
992
line_end_index: line_range.1,
981
- char_widths,
982
993
});
983
994
current_line += 1;
984
995
current_index += line_length + end_line as usize;
@@ -991,7 +1002,6 @@ fn format_body(
991
1002
LineInfo {
992
1003
line_start_index,
993
1004
line_end_index,
994
- char_widths,
995
1005
},
996
1006
) in line_info.into_iter().enumerate()
997
1007
{
@@ -1012,16 +1022,8 @@ fn format_body(
1012
1022
if start >= line_start_index && end <= line_end_index
1013
1023
|| start == line_end_index && end - start <= 1 =>
1014
1024
{
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;
1025
1027
let range = (annotation_start_col, annotation_end_col);
1026
1028
body.insert(
1027
1029
body_idx + 1,
@@ -1064,10 +1066,7 @@ fn format_body(
1064
1066
});
1065
1067
}
1066
1068
} 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;
1071
1070
let range = (annotation_start_col, annotation_start_col + 1);
1072
1071
body.insert(
1073
1072
body_idx + 1,
@@ -1125,11 +1124,7 @@ fn format_body(
1125
1124
});
1126
1125
}
1127
1126
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);
1133
1128
let range = (end_mark - margin_left, (end_mark + 1) - margin_left);
1134
1129
body.insert(
1135
1130
body_idx + 1,
0 commit comments