From 0239ef25b39fa865ac941756093069f1dc167c2d Mon Sep 17 00:00:00 2001 From: gwenn <45554+gwenn@users.noreply.github.com> Date: Wed, 15 Jan 2025 08:08:18 +0100 Subject: [PATCH] Grapheme clusters See #826 --- src/layout.rs | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/layout.rs b/src/layout.rs index ba8d603f7..9c4b27b40 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -13,6 +13,23 @@ pub(crate) fn swidth(s: &str) -> Unit { Unit::try_from(s.width()).unwrap() } +fn wcwidth(s: &str) -> Unit { + let mut width = 0; + for c in s.chars() { + width += cwidh(c); + } + width +} + +const ZWJ: char = '\u{200D}'; +fn no_zwj(s: &str) -> Unit { + let mut width = 0; + for x in s.split(ZWJ) { + width += swidth(x); + } + width +} + #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] pub struct Position { pub col: Unit, // The leftmost column is number 0. @@ -44,3 +61,34 @@ pub struct Layout { /// Number of rows used so far (from start of prompt to end of input) pub end: Position, } + +#[cfg(test)] +mod test { + #[test] + fn unicode_width() { + assert_eq!(1, super::swidth("a")); + assert_eq!(2, super::swidth("๐Ÿ‘ฉโ€๐Ÿš€")); + assert_eq!(2, super::swidth("๐Ÿ‘‹๐Ÿฟ")); + assert_eq!(2, super::swidth("๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ")); + assert_eq!(2, super::swidth("๐Ÿ‘ฉ๐Ÿผโ€๐Ÿ‘จ๐Ÿผโ€๐Ÿ‘ฆ๐Ÿผโ€๐Ÿ‘ฆ๐Ÿผ")); + assert_eq!(2, super::swidth("โค๏ธ")); + } + #[test] + fn test_wcwidth() { + assert_eq!(1, super::wcwidth("a")); + assert_eq!(4, super::wcwidth("๐Ÿ‘ฉโ€๐Ÿš€")); + assert_eq!(4, super::wcwidth("๐Ÿ‘‹๐Ÿฟ")); + assert_eq!(8, super::wcwidth("๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ")); + assert_eq!(16, super::wcwidth("๐Ÿ‘ฉ๐Ÿผโ€๐Ÿ‘จ๐Ÿผโ€๐Ÿ‘ฆ๐Ÿผโ€๐Ÿ‘ฆ๐Ÿผ")); + assert_eq!(1, super::wcwidth("โค๏ธ")); + } + #[test] + fn test_no_zwj() { + assert_eq!(1, super::no_zwj("a")); + assert_eq!(4, super::no_zwj("๐Ÿ‘ฉโ€๐Ÿš€")); + assert_eq!(2, super::no_zwj("๐Ÿ‘‹๐Ÿฟ")); + assert_eq!(8, super::no_zwj("๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ")); + assert_eq!(8, super::no_zwj("๐Ÿ‘ฉ๐Ÿผโ€๐Ÿ‘จ๐Ÿผโ€๐Ÿ‘ฆ๐Ÿผโ€๐Ÿ‘ฆ๐Ÿผ")); + assert_eq!(2, super::no_zwj("โค๏ธ")); + } +}