summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/cell.rs4
-rw-r--r--src/utils.rs32
2 files changed, 33 insertions, 3 deletions
diff --git a/src/cell.rs b/src/cell.rs
index 255c3fd..cca22d4 100644
--- a/src/cell.rs
+++ b/src/cell.rs
@@ -2,9 +2,9 @@
use std::io::{Write, Error};
use std::string::ToString;
-use unicode_width::UnicodeWidthStr;
use super::{Attr, Terminal, color};
use super::format::Alignment;
+use super::utils::display_width;
use super::utils::print_align;
/// Represent a table cell containing a string.
@@ -26,7 +26,7 @@ impl Cell {
let content: Vec<String> = string.lines().map(|x| x.to_string()).collect();
let mut width = 0;
for cont in &content {
- let l = UnicodeWidthStr::width(&cont[..]);
+ let l = display_width(&cont[..]);
if l > width {
width = l;
}
diff --git a/src/utils.rs b/src/utils.rs
index b96828e..79e3be8 100644
--- a/src/utils.rs
+++ b/src/utils.rs
@@ -57,7 +57,7 @@ pub fn print_align<T: Write + ?Sized>(out: &mut T,
size: usize,
skip_right_fill: bool)
-> Result<(), Error> {
- let text_len = UnicodeWidthStr::width(text);
+ let text_len = display_width(text);
let mut nfill = if text_len < size { size - text_len } else { 0 };
let n = match align {
Alignment::LEFT => 0,
@@ -75,6 +75,36 @@ pub fn print_align<T: Write + ?Sized>(out: &mut T,
Ok(())
}
+/// Return the display width of a unicode string.
+/// This functions takes ANSI-escaped color codes into account.
+pub fn display_width(text: &str) -> usize {
+ let width = UnicodeWidthStr::width(text);
+ let mut state = 0;
+ let mut hidden = 0;
+
+ for c in text.chars() {
+ state = match (state, c) {
+ (0, '\u{1b}') => 1,
+ (1, '[') => 2,
+ (1, _) => 0,
+ (2, 'm') => 3,
+ _ => state,
+ };
+
+ // We don't count escape characters as hidden as
+ // UnicodeWidthStr::width already considers them.
+ if state > 1 {
+ hidden += 1;
+ }
+
+ if state == 3 {
+ state = 0;
+ }
+ }
+
+ width - hidden
+}
+
#[cfg(test)]
mod tests {
use super::*;