A simple library for measuring the width of unicode characters and strings.
Dependencies
> moon add moonbit-community/unicodewidth///|
test {
// ASCII characters have width 1
assert_eq(@unicodewidth.char_width('a'), Some(1))
assert_eq(@unicodewidth.char_width('Z'), Some(1))
// Fullwidth characters have width 2
assert_eq(@unicodewidth.char_width('h'), Some(2)) // Fullwidth 'h'
// Control characters return None
assert_eq(@unicodewidth.char_width('\u{0}'), None) // Null character
// But str_width handles them as width 1
assert_eq(@unicodewidth.str_width("\u{0}"), 1)
}///|
test {
// Mixed-width strings
assert_eq(@unicodewidth.str_width("Hello"), 5) // ASCII only
assert_eq(@unicodewidth.str_width("hello"), 10) // Fullwidth only
assert_eq(@unicodewidth.str_width("Hello世界"), 9) // Mixed ASCII + CJK (5 + 2 + 2)
// Emoji handling
assert_eq(@unicodewidth.str_width("👩"), 2) // Woman emoji
assert_eq(@unicodewidth.str_width("👩🔬"), 2) // Woman scientist (ZWJ sequence)
}///|
test {
// Ambiguous width characters behave differently in CJK vs non-CJK contexts
let ambiguous_char = '\u{B7}' // Middle dot
// In non-CJK context (cjk=false)
assert_eq(@unicodewidth.char_width(ambiguous_char, cjk=false), Some(1))
// In CJK context (cjk=true) - treated as wide
assert_eq(@unicodewidth.char_width(ambiguous_char, cjk=true), Some(2))
// This affects string width calculations
let text = "Hello\u{B7}World"
assert_eq(@unicodewidth.str_width(text, cjk=false), 11) // 5 + 1 + 5
assert_eq(@unicodewidth.str_width(text, cjk=true), 12) // 5 + 2 + 5
}///|
test {
// Regional indicator sequences (flag emojis)
assert_eq(@unicodewidth.str_width("🇺🇸"), 2) // US flag
// Emoji with modifiers
assert_eq(@unicodewidth.str_width("👶🏽"), 2) // Baby with skin tone modifier
// Zero-width sequences
assert_eq(@unicodewidth.str_width("👨👩👧👦"), 2) // Family emoji (multiple ZWJ)
// Combining marks
assert_eq(@unicodewidth.str_width("é"), 1) // 'e' + acute accent
}///|
test {
// Text alignment in terminal
fn align_text(text : String, width : Int, align : String) -> String {
let text_width = @unicodewidth.str_width(text)
match align {
"left" => text + " ".repeat(width - text_width)
"right" => " ".repeat(width - text_width) + text
"center" => {
let left_pad = (width - text_width) / 2
let right_pad = width - text_width - left_pad
" ".repeat(left_pad) + text + " ".repeat(right_pad)
}
_ => text
}
}
// Example usage
let sample_text = "Hello世界"
assert_eq(@unicodewidth.str_width(sample_text), 9) // 5 + 2 + 2
let centered = align_text(sample_text, 10, "center")
assert_eq(@unicodewidth.str_width(centered), 10)
}> moon testfn char_width(c : Char, cjk? : Bool) -> Int?fn str_width(s : StringView, cjk? : Bool) -> IntA simple library for measuring the width of unicode characters and strings.
Dependencies