3232//!
3333//! The above snippet has been built out of the following structure:
3434use crate :: snippet;
35+ use itertools:: FoldWhile :: { Continue , Done } ;
36+ use itertools:: Itertools ;
3537use std:: fmt:: { Display , Write } ;
3638use 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 . len ( ) ;
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 ,
0 commit comments