Fix wrapping method to support unicode text
Related issues:
@@ -17,6 +17,8 @@ use content_inspector::ContentType;
use encoding::all::{UTF_16BE, UTF_16LE};
use encoding::{DecoderTrap, Encoding};
+use unicode_width::UnicodeWidthChar;
+
use crate::assets::HighlightingAssets;
use crate::decorations::{
Decoration, GridBorderDecoration, LineChangesDecoration, LineNumberDecoration,
@@ -469,35 +471,22 @@ impl<'a> Printer for InteractivePrinter<'a> {
&mut cursor_total,
);
- let mut chars = text.chars();
- let mut remaining = text.chars().count();
+ let max_width = cursor_max - cursor;
- while remaining > 0 {
- let available = cursor_max - cursor;
+ // line buffer (avoid calling write! for every character)
+ let mut line_buf = String::with_capacity(max_width * 4);
- // It fits.
- if remaining <= available {
- let text = chars.by_ref().take(remaining).collect::<String>();
- cursor += remaining;
+ // Displayed width of line_buf
+ let mut current_width = 0;
- write!(
- handle,
- "{}",
- as_terminal_escaped(
- style,
- &*format!(
- "{}{}{}",
- self.ansi_prefix_sgr, ansi_prefix, text
- ),
- self.config.true_color,
- self.config.colored_output,
- self.config.use_italic_text,
- background_color
- )
- )?;
- break;
- }
+ for c in text.chars() {
+ // calculate the displayed width for next character
+ let cw = c.width().unwrap_or(0);
+ current_width += cw;
+ // if next character cannot be printed on this line,
+ // flush the buffer.
+ if current_width > max_width {
// Generate wrap padding if not already generated.
if panel_wrap.is_none() {
panel_wrap = if self.panel_width > 0 {
@@ -516,11 +505,9 @@ impl<'a> Printer for InteractivePrinter<'a> {
}
}
- // It wraps.
- let text = chars.by_ref().take(available).collect::<String>();
cursor = 0;
- remaining -= available;
+ // It wraps.
write!(
handle,
"{}\n{}",
@@ -528,7 +515,7 @@ impl<'a> Printer for InteractivePrinter<'a> {
style,
&*format!(
"{}{}{}",
- self.ansi_prefix_sgr, ansi_prefix, text
+ self.ansi_prefix_sgr, ansi_prefix, line_buf
),
self.config.true_color,
self.config.colored_output,
@@ -537,8 +524,32 @@ impl<'a> Printer for InteractivePrinter<'a> {
),
panel_wrap.clone().unwrap()
)?;
+
+ line_buf.clear();
+ current_width = cw;
+ }
+
+ line_buf.push(c);
}
+ // flush the buffer
+ cursor += current_width;
+ write!(
+ handle,
+ "{}",
+ as_terminal_escaped(
+ style,
+ &*format!(
+ "{}{}{}",
+ self.ansi_prefix_sgr, ansi_prefix, line_buf
+ ),
+ self.config.true_color,
+ self.config.colored_output,
+ self.config.use_italic_text,
+ background_color
+ )
+ )?;
+
// Clear the ANSI prefix buffer.
ansi_prefix.clear();
}
