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 } ;
38
+ use std:: ops:: Range ;
36
39
use std:: { cmp, fmt} ;
37
40
38
41
use crate :: renderer:: { stylesheet:: Stylesheet , Margin , Style } ;
@@ -766,7 +769,7 @@ fn format_slice(
766
769
has_footer : bool ,
767
770
margin : Option < Margin > ,
768
771
) -> 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 ) ;
770
773
let origin = slice. origin ;
771
774
let need_empty_header = origin. is_some ( ) || is_first;
772
775
let mut body = format_body ( slice, need_empty_header, has_footer, margin) ;
@@ -804,13 +807,27 @@ fn format_header<'a>(
804
807
805
808
for item in body {
806
809
if let DisplayLine :: Source {
807
- line : DisplaySourceLine :: Content { range , .. } ,
810
+ line : DisplaySourceLine :: Content { text , range } ,
808
811
lineno,
809
812
..
810
813
} = item
811
814
{
812
815
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 ;
814
831
line_offset = lineno. unwrap_or ( 1 ) ;
815
832
break ;
816
833
}
@@ -932,11 +949,11 @@ fn format_body(
932
949
has_footer : bool ,
933
950
margin : Option < Margin > ,
934
951
) -> Vec < DisplayLine < ' _ > > {
935
- let source_len = slice. source . chars ( ) . count ( ) ;
952
+ let source_len = slice. source . len ( ) ;
936
953
if let Some ( bigger) = slice. annotations . iter ( ) . find_map ( |x| {
937
954
// 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 )
940
957
} else {
941
958
None
942
959
}
@@ -955,18 +972,14 @@ fn format_body(
955
972
struct LineInfo {
956
973
line_start_index : usize ,
957
974
line_end_index : usize ,
958
- // How many spaces each character in the line take up when displayed
959
- char_widths : Vec < usize > ,
960
975
}
961
976
962
977
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
966
979
. chars ( )
967
980
. 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 ) ;
970
983
body. push ( DisplayLine :: Source {
971
984
lineno : Some ( current_line) ,
972
985
inline_marks : vec ! [ ] ,
@@ -978,7 +991,6 @@ fn format_body(
978
991
line_info. push ( LineInfo {
979
992
line_start_index : line_range. 0 ,
980
993
line_end_index : line_range. 1 ,
981
- char_widths,
982
994
} ) ;
983
995
current_line += 1 ;
984
996
current_index += line_length + end_line as usize ;
@@ -991,7 +1003,6 @@ fn format_body(
991
1003
LineInfo {
992
1004
line_start_index,
993
1005
line_end_index,
994
- char_widths,
995
1006
} ,
996
1007
) in line_info. into_iter ( ) . enumerate ( )
997
1008
{
@@ -1007,21 +1018,13 @@ fn format_body(
1007
1018
_ => DisplayAnnotationType :: from ( annotation. annotation_type ) ,
1008
1019
} ;
1009
1020
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 }
1012
1023
if start >= line_start_index && end <= line_end_index
1013
1024
|| start == line_end_index && end - start <= 1 =>
1014
1025
{
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;
1025
1028
let range = ( annotation_start_col, annotation_end_col) ;
1026
1029
body. insert (
1027
1030
body_idx + 1 ,
@@ -1045,7 +1048,7 @@ fn format_body(
1045
1048
annotation_line_count += 1 ;
1046
1049
false
1047
1050
}
1048
- ( start, end)
1051
+ Range { start, end }
1049
1052
if start >= line_start_index
1050
1053
&& start <= line_end_index
1051
1054
&& end > line_end_index =>
@@ -1064,10 +1067,7 @@ fn format_body(
1064
1067
} ) ;
1065
1068
}
1066
1069
} 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;
1071
1071
let range = ( annotation_start_col, annotation_start_col + 1 ) ;
1072
1072
body. insert (
1073
1073
body_idx + 1 ,
@@ -1092,7 +1092,7 @@ fn format_body(
1092
1092
}
1093
1093
true
1094
1094
}
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 => {
1096
1096
if let DisplayLine :: Source {
1097
1097
ref mut inline_marks,
1098
1098
..
@@ -1107,7 +1107,7 @@ fn format_body(
1107
1107
}
1108
1108
true
1109
1109
}
1110
- ( start, end)
1110
+ Range { start, end }
1111
1111
if start < line_start_index
1112
1112
&& end >= line_start_index
1113
1113
&& end <= line_end_index =>
@@ -1125,11 +1125,7 @@ fn format_body(
1125
1125
} ) ;
1126
1126
}
1127
1127
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 ) ;
1133
1129
let range = ( end_mark - margin_left, ( end_mark + 1 ) - margin_left) ;
1134
1130
body. insert (
1135
1131
body_idx + 1 ,
@@ -1380,7 +1376,7 @@ mod tests {
1380
1376
let line_2 = "This is line 2" ;
1381
1377
let source = [ line_1, line_2] . join ( "\n " ) ;
1382
1378
// In line 2
1383
- let range = ( 22 , 24 ) ;
1379
+ let range = 22 .. 24 ;
1384
1380
let input = snippet:: Snippet {
1385
1381
title : None ,
1386
1382
footer : vec ! [ ] ,
@@ -1389,7 +1385,7 @@ mod tests {
1389
1385
line_start: 5402 ,
1390
1386
origin: None ,
1391
1387
annotations: vec![ snippet:: SourceAnnotation {
1392
- range,
1388
+ range: range . clone ( ) ,
1393
1389
label: "Test annotation" ,
1394
1390
annotation_type: snippet:: AnnotationType :: Info ,
1395
1391
} ] ,
@@ -1430,7 +1426,10 @@ mod tests {
1430
1426
style: DisplayTextStyle :: Regular ,
1431
1427
} ] ,
1432
1428
} ,
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
+ ) ,
1434
1433
annotation_type: DisplayAnnotationType :: Info ,
1435
1434
annotation_part: DisplayAnnotationPart :: Standalone ,
1436
1435
} ,
@@ -1480,7 +1479,7 @@ mod tests {
1480
1479
footer : vec ! [ ] ,
1481
1480
slices : vec ! [ snippet:: Slice {
1482
1481
annotations: vec![ snippet:: SourceAnnotation {
1483
- range: ( 0 , source. len( ) + 2 ) ,
1482
+ range: 0 .. source. len( ) + 2 ,
1484
1483
label,
1485
1484
annotation_type: snippet:: AnnotationType :: Error ,
1486
1485
} ] ,
@@ -1507,7 +1506,7 @@ mod tests {
1507
1506
line_start: 1 ,
1508
1507
origin: Some ( "<current file>" ) ,
1509
1508
annotations: vec![ snippet:: SourceAnnotation {
1510
- range: ( 19 , 23 ) ,
1509
+ range: 19 .. 23 ,
1511
1510
label: "oops" ,
1512
1511
annotation_type: snippet:: AnnotationType :: Error ,
1513
1512
} ] ,
0 commit comments