Skip to content

Commit

Permalink
Merge pull request #79 from liautaud/master
Browse files Browse the repository at this point in the history
Fixed cell width issues when using ANSI color codes.
  • Loading branch information
phsym authored Aug 9, 2018
2 parents f7289e7 + 20cd163 commit 8a40e2a
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 3 deletions.
4 changes: 2 additions & 2 deletions src/cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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;
}
Expand Down
32 changes: 31 additions & 1 deletion src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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::*;
Expand Down

0 comments on commit 8a40e2a

Please sign in to comment.