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