@@ -954,12 +954,19 @@ impl Renderer {
954
954
let line_offset = buffer. num_lines ( ) ;
955
955
956
956
// Left trim
957
- let left = margin. left ( source_string . len ( ) ) ;
957
+ let left = margin. left ( str_width ( & source_string ) ) ;
958
958
959
959
// FIXME: This looks fishy. See #132860.
960
960
// Account for unicode characters of width !=0 that were removed.
961
- let left = source_string. chars ( ) . take ( left) . map ( char_width) . sum ( ) ;
961
+ let mut taken = 0 ;
962
+ source_string. chars ( ) . for_each ( |ch| {
963
+ let next = char_width ( ch) ;
964
+ if taken + next <= left {
965
+ taken += next;
966
+ }
967
+ } ) ;
962
968
969
+ let left = taken;
963
970
self . draw_line (
964
971
buffer,
965
972
& source_string,
@@ -2018,48 +2025,81 @@ impl Renderer {
2018
2025
) {
2019
2026
// Tabs are assumed to have been replaced by spaces in calling code.
2020
2027
debug_assert ! ( !source_string. contains( '\t' ) ) ;
2021
- let line_len = source_string . len ( ) ;
2028
+ let line_len = str_width ( source_string ) ;
2022
2029
// Create the source line we will highlight.
2023
2030
let left = margin. left ( line_len) ;
2024
2031
let right = margin. right ( line_len) ;
2025
2032
// FIXME: The following code looks fishy. See #132860.
2026
2033
// On long lines, we strip the source line, accounting for unicode.
2027
2034
let mut taken = 0 ;
2035
+ let mut skipped = 0 ;
2028
2036
let code: String = source_string
2029
2037
. chars ( )
2030
- . skip ( left)
2038
+ . skip_while ( |ch| {
2039
+ skipped += char_width ( * ch) ;
2040
+ skipped <= left
2041
+ } )
2031
2042
. take_while ( |ch| {
2032
2043
// Make sure that the trimming on the right will fall within the terminal width.
2033
- let next = char_width ( * ch) ;
2034
- if taken + next > right - left {
2035
- return false ;
2036
- }
2037
- taken += next;
2038
- true
2044
+ taken += char_width ( * ch) ;
2045
+ taken <= ( right - left)
2039
2046
} )
2040
2047
. collect ( ) ;
2041
2048
2042
2049
buffer. puts ( line_offset, code_offset, & code, ElementStyle :: Quotation ) ;
2043
2050
let placeholder = self . margin ( ) ;
2044
- if margin. was_cut_left ( ) {
2051
+ let padding = str_width ( placeholder) ;
2052
+ let ( width_taken, bytes_taken) = if margin. was_cut_left ( ) {
2045
2053
// We have stripped some code/whitespace from the beginning, make it clear.
2054
+ let mut bytes_taken = 0 ;
2055
+ let mut width_taken = 0 ;
2056
+ for ch in code. chars ( ) {
2057
+ width_taken += char_width ( ch) ;
2058
+ bytes_taken += ch. len_utf8 ( ) ;
2059
+
2060
+ if width_taken >= padding {
2061
+ break ;
2062
+ }
2063
+ }
2046
2064
buffer. puts (
2047
2065
line_offset,
2048
2066
code_offset,
2049
- placeholder,
2067
+ & format ! ( "{ placeholder:>width_taken$}" ) ,
2050
2068
ElementStyle :: LineNumber ,
2051
2069
) ;
2052
- }
2070
+ ( width_taken, bytes_taken)
2071
+ } else {
2072
+ ( 0 , 0 )
2073
+ } ;
2074
+
2075
+ buffer. puts (
2076
+ line_offset,
2077
+ code_offset + width_taken,
2078
+ & code[ bytes_taken..] ,
2079
+ ElementStyle :: Quotation ,
2080
+ ) ;
2081
+
2053
2082
if margin. was_cut_right ( line_len) {
2054
- let padding = str_width ( placeholder) ;
2055
- // We have stripped some code after the rightmost span end, make it clear we did so.
2083
+ // We have stripped some code/whitespace from the beginning, make it clear.
2084
+ let mut char_taken = 0 ;
2085
+ let mut width_taken_inner = 0 ;
2086
+ for ch in code. chars ( ) . rev ( ) {
2087
+ width_taken_inner += char_width ( ch) ;
2088
+ char_taken += 1 ;
2089
+
2090
+ if width_taken_inner >= padding {
2091
+ break ;
2092
+ }
2093
+ }
2094
+
2056
2095
buffer. puts (
2057
2096
line_offset,
2058
- code_offset + taken - padding ,
2097
+ code_offset + width_taken + code [ bytes_taken.. ] . chars ( ) . count ( ) - char_taken ,
2059
2098
placeholder,
2060
2099
ElementStyle :: LineNumber ,
2061
2100
) ;
2062
2101
}
2102
+
2063
2103
buffer. puts (
2064
2104
line_offset,
2065
2105
0 ,
0 commit comments