term: Fix unicode display width hack

We were skipping certain glyphs due to the width calculation being
wrong. This fixes it, and we're able to display emojis correctly inside
tables now.
This commit is contained in:
cloudhead 2023-11-14 16:11:49 +01:00
parent 06946a2bf4
commit 40303cd8e1
No known key found for this signature in database
6 changed files with 30 additions and 21 deletions

11
Cargo.lock generated
View File

@ -2574,8 +2574,8 @@ dependencies = [
"pretty_assertions",
"tempfile",
"termion 2.0.1",
"unicode-display-width",
"unicode-segmentation",
"unicode-width",
"zeroize",
]
@ -3619,6 +3619,15 @@ version = "0.3.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
[[package]]
name = "unicode-display-width"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a43273b656140aa2bb8e65351fe87c255f0eca706b2538a9bd4a590a3490bf3"
dependencies = [
"unicode-segmentation",
]
[[package]]
name = "unicode-ident"
version = "1.0.11"

View File

@ -18,7 +18,7 @@ inquire = { version = "0.6.2", default-features = false, features = ["termion",
libc = { version = "0.2" }
once_cell = { version = "1.13" }
termion = { version = "2" }
unicode-width = { version = "0.1.10", default-features = false }
unicode-display-width = { version = "0.3.0" }
unicode-segmentation = { version = "1.7.1" }
zeroize = { version = "1.1" }

View File

@ -4,7 +4,6 @@ use std::sync::atomic::AtomicBool;
use std::{fmt, io};
use once_cell::sync::Lazy;
use unicode_width::UnicodeWidthStr;
use super::color::Color;
use super::style::{Property, Style};
@ -232,16 +231,6 @@ impl<T> Paint<T> {
}
}
impl<T: UnicodeWidthStr> UnicodeWidthStr for Paint<T> {
fn width(&self) -> usize {
self.item.width()
}
fn width_cjk(&self) -> usize {
self.item.width_cjk()
}
}
impl<T: fmt::Display> fmt::Display for Paint<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if Paint::is_enabled() && self.style.wrap {

View File

@ -2,8 +2,8 @@ use std::fmt;
use super::{Color, Filled, Line, Paint};
use unicode_display_width as unicode;
use unicode_segmentation::UnicodeSegmentation as _;
use unicode_width::UnicodeWidthStr;
/// Text that can be displayed on the terminal, measured, truncated and padded.
pub trait Cell: fmt::Display {
@ -123,7 +123,9 @@ impl Cell for str {
type Padded = String;
fn width(&self) -> usize {
self.graphemes(true).map(UnicodeWidthStr::width).sum()
self.graphemes(true)
.map(|g| unicode::width(g) as usize)
.sum()
}
fn truncate(&self, width: usize, delim: &str) -> String {
@ -204,3 +206,12 @@ impl<T: Cell + fmt::Display> Cell for Filled<T> {
T::pad(&self.item, width)
}
}
#[cfg(test)]
mod test {
#[test]
fn test_width() {
assert_eq!(unicode_display_width::width("❤️"), 2);
assert_eq!(unicode_display_width::width("🪵"), 2);
}
}

View File

@ -362,9 +362,12 @@ mod test {
#[test]
fn test_width() {
let line = Line::new("Radicle Heartwood Protocol & Stack ❤️ 🪵");
// Nb. This might not display correctly in some editors or terminals.
let line = Line::new("Radicle Heartwood Protocol & Stack ❤️🪵");
assert_eq!(line.width(), 39, "{line}");
let line = Line::new("\u{fe0f}");
assert_eq!(line.width(), 1, "{line}");
assert_eq!(line.width(), 2, "{line}");
let line = Line::new("❤️");
assert_eq!(line.width(), 2, "{line}");
}
}

View File

@ -128,8 +128,5 @@ pub fn label(s: impl Into<Paint<String>>) -> Label {
/// Cleanup the input string for display as a label.
fn cleanup(input: &str) -> String {
input
.chars()
.filter(|c| *c != '\u{fe0f}' && *c != '\n' && *c != '\r')
.collect()
input.chars().filter(|c| *c != '\n' && *c != '\r').collect()
}