Skip to content

Commit a67bb60

Browse files
Fix invalid cell width calculation with modern unicode-width versions
Fixes phsym#165
1 parent 225f6d4 commit a67bb60

File tree

2 files changed

+5
-51
lines changed

2 files changed

+5
-51
lines changed

Cargo.toml

+3-2
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,10 @@ path = "src/main.rs"
3636
name = "prettytable"
3737

3838
[dependencies]
39-
unicode-width = "0.1"
39+
unicode-width = "0.2"
4040
term = "0.7"
4141
lazy_static = "1.4"
4242
is-terminal = "0.4"
4343
encode_unicode = "1.0"
44-
csv = { version = "1.1", optional = true }
44+
strip-ansi-escapes = "0.2.0"
45+
csv = { version = "1.1", optional = true }

src/utils.rs

+2-49
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::fmt;
33
use std::io::{Error, ErrorKind, Write};
44
use std::str;
55

6-
use unicode_width::{UnicodeWidthChar, UnicodeWidthStr};
6+
use unicode_width::UnicodeWidthStr;
77

88
use super::format::Alignment;
99

@@ -84,54 +84,7 @@ pub fn print_align<T: Write + ?Sized>(
8484
/// Return the display width of a unicode string.
8585
/// This functions takes ANSI-escaped color codes into account.
8686
pub fn display_width(text: &str) -> usize {
87-
#[derive(PartialEq, Eq, Clone, Copy)]
88-
enum State {
89-
/// We are not inside any terminal escape.
90-
Normal,
91-
/// We have just seen a \u{1b}
92-
EscapeChar,
93-
/// We have just seen a [
94-
OpenBracket,
95-
/// We just ended the escape by seeing an m
96-
AfterEscape,
97-
}
98-
99-
let width = UnicodeWidthStr::width(text);
100-
let mut state = State::Normal;
101-
let mut hidden = 0;
102-
103-
for c in text.chars() {
104-
state = match (state, c) {
105-
(State::Normal, '\u{1b}') => State::EscapeChar,
106-
(State::EscapeChar, '[') => State::OpenBracket,
107-
(State::EscapeChar, _) => State::Normal,
108-
(State::OpenBracket, 'm') => State::AfterEscape,
109-
_ => state,
110-
};
111-
112-
// We don't count escape characters as hidden as
113-
// UnicodeWidthStr::width already considers them.
114-
if matches!(state, State::OpenBracket | State::AfterEscape) {
115-
// but if we see an escape char *inside* the ANSI escape, we should ignore it.
116-
if UnicodeWidthChar::width(c).unwrap_or(0) > 0 {
117-
hidden += 1;
118-
}
119-
}
120-
121-
if state == State::AfterEscape {
122-
state = State::Normal;
123-
}
124-
}
125-
126-
assert!(
127-
width >= hidden,
128-
"internal error: width {} less than hidden {} on string {:?}",
129-
width,
130-
hidden,
131-
text
132-
);
133-
134-
width - hidden
87+
UnicodeWidthStr::width(strip_ansi_escapes::strip_str(text).as_str())
13588
}
13689

13790
/// Wrapper struct which will emit the HTML-escaped version of the contained

0 commit comments

Comments
 (0)