Fix wrapping method to support unicode text

Related issues:
- #787
- #811
pull/847/head
Kogia-sima 5 years ago committed by David Peter
parent 22ded00824
commit 944866affd

@ -17,6 +17,8 @@ use content_inspector::ContentType;
use encoding::all::{UTF_16BE, UTF_16LE}; use encoding::all::{UTF_16BE, UTF_16LE};
use encoding::{DecoderTrap, Encoding}; use encoding::{DecoderTrap, Encoding};
use unicode_width::UnicodeWidthChar;
use crate::assets::HighlightingAssets; use crate::assets::HighlightingAssets;
use crate::decorations::{ use crate::decorations::{
Decoration, GridBorderDecoration, LineChangesDecoration, LineNumberDecoration, Decoration, GridBorderDecoration, LineChangesDecoration, LineNumberDecoration,
@ -469,76 +471,85 @@ impl<'a> Printer for InteractivePrinter<'a> {
&mut cursor_total, &mut cursor_total,
); );
let mut chars = text.chars(); let max_width = cursor_max - cursor;
let mut remaining = text.chars().count();
// line buffer (avoid calling write! for every character)
while remaining > 0 { let mut line_buf = String::with_capacity(max_width * 4);
let available = cursor_max - cursor;
// Displayed width of line_buf
let mut current_width = 0;
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 {
Some(format!(
"{} ",
self.decorations
.iter()
.map(|ref d| d
.generate(line_number, true, self)
.text)
.collect::<Vec<String>>()
.join(" ")
))
} else {
Some("".to_string())
}
}
// It fits. cursor = 0;
if remaining <= available {
let text = chars.by_ref().take(remaining).collect::<String>();
cursor += remaining;
// It wraps.
write!( write!(
handle, handle,
"{}", "{}\n{}",
as_terminal_escaped( as_terminal_escaped(
style, style,
&*format!( &*format!(
"{}{}{}", "{}{}{}",
self.ansi_prefix_sgr, ansi_prefix, text self.ansi_prefix_sgr, ansi_prefix, line_buf
), ),
self.config.true_color, self.config.true_color,
self.config.colored_output, self.config.colored_output,
self.config.use_italic_text, self.config.use_italic_text,
background_color background_color
) ),
panel_wrap.clone().unwrap()
)?; )?;
break;
}
// Generate wrap padding if not already generated. line_buf.clear();
if panel_wrap.is_none() { current_width = cw;
panel_wrap = if self.panel_width > 0 {
Some(format!(
"{} ",
self.decorations
.iter()
.map(|ref d| d
.generate(line_number, true, self)
.text)
.collect::<Vec<String>>()
.join(" ")
))
} else {
Some("".to_string())
}
} }
// It wraps. line_buf.push(c);
let text = chars.by_ref().take(available).collect::<String>();
cursor = 0;
remaining -= available;
write!(
handle,
"{}\n{}",
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
),
panel_wrap.clone().unwrap()
)?;
} }
// 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. // Clear the ANSI prefix buffer.
ansi_prefix.clear(); ansi_prefix.clear();
} }

Loading…
Cancel
Save