#unicode-width #width #unicode #unicode-text #east-asian-width #wcswidth #wcwidth

unicode-display-width

符合 Unicode 15.1.0 的实用工具,用于确定显示任意字符串所需的列数

2 个不稳定版本

0.3.0 2023年11月15日
0.2.0 2023年10月23日

#428 in 文本处理

Download history 122/week @ 2024-03-13 101/week @ 2024-03-20 115/week @ 2024-03-27 222/week @ 2024-04-03 184/week @ 2024-04-10 179/week @ 2024-04-17 81/week @ 2024-04-24 99/week @ 2024-05-01 86/week @ 2024-05-08 147/week @ 2024-05-15 94/week @ 2024-05-22 188/week @ 2024-05-29 240/week @ 2024-06-05 159/week @ 2024-06-12 237/week @ 2024-06-19 184/week @ 2024-06-26

890 每月下载量
11 个 Crates 中使用 (5 直接使用)

MIT 许可证

16KB
205

Rust Latest Version License: MIT Contributor Covenant

Unicode 显示宽度

一个安全、高效的 Rust 库,用于确定显示任意字符串所需的列数。它符合 Unicode 15.1.0 并正确处理图形群。

use unicode_display_width::width;

assert_eq!(width("🔥🗡🍩👩🏻‍🚀⏰💃🏼🔦👍🏻"), 15);
assert_eq!(width("🦀"), 2);
assert_eq!(width("👨‍👩‍👧‍👧"), 2);
assert_eq!(width("👩‍🔬"), 2);
assert_eq!(width("sane text"), 9);
assert_eq!(width("Ẓ̌á̲l͔̝̞̄̑͌g̖̘̘̔̔͢͞͝o̪̔T̢̙̫̈̍͞e̬͈͕͌̏͑x̺̍ṭ̓̓ͅ"), 9);
assert_eq!(width("슬라바 우크라이나"), 17);

此库永远不会崩溃。即使是私有使用和未分配的代码点也完全支持。

use unicode_display_width::width;

// unassigned code points are assumed to have width 1
assert_eq!(width("\u{00378}"), 1);

// private use code points are also assumed to have width 1
assert_eq!(width("\u{0E000}"), 1);

注意: GitHub 的 Markdown 渲染 并非真正等宽

动机

表情符号、表意文字中文、日文、韩文字符以及许多其他 Unicode 图形都是用常规字符宽度的一倍来渲染的。

确定图形的正确宽度是一个至关重要的操作,因为它可以确定按下箭头键、删除键或在文本文档中添加字符时,光标应该移动多远。例如,在 VS Code 中的 ݓ΅ɓԶѥƘҕ࠹ɇঐԢظ 或 macOS 终端中的 🛡 中,光标的行为并不直观。

宽度函数的使用范围比最初想象的更广。例如,确定文本换行位置(当启用单词换行时)。要看到 VS Code 简单宽度函数的效果,请多次粘贴 "Ẓ̌á̲l͔̝̞̄̑͌g̖̘̘̔̔͢͞͝o̪̔T̢̙̫̈̍͞e̬͈͕͌̏͑x̺̍ṭ̓̓ͅ" 到一行上。

工作原理

Unicode 显示宽度将字符串参数分割成一系列图形(用户可见的字符)。例如,"🔥🗡👩🏻‍🚀" 被分割成 "🔥", "🗡", "👩🏻‍🚀"

对于每个字符集群,它会检查构成该字符集群的任何代码点(Unicode文本的原子部分)是否具有表示双宽或Emoji_Presentation的emoji字符属性的Unicode东亚宽度属性值。

  • 如果至少有一个代码点具有双宽,则整个字符集群的宽度为2,无论构成字符集群的代码点有多少。
  • 如果没有这样的代码点,字符集群的宽度为1。

例如,"👩🏻‍🚀"有三个代码点:"👩🏻","\u{200D}"和"🚀"。第一个和第三个具有双宽的东亚宽度属性。因此,"👩🏻‍🚀"的宽度为2。

最后,将所有字符集群的宽度相加并返回。这种方法确保了每个用户可见字符可能宽度值的集合为{1, 2}

有关字符集群、代码点、Unicode等周围细微之处的更全面讨论,请参阅背景

局限性

Unicode Display Width不决定任何特定编辑器或特定字体的渲染宽度,而是根据Unicode 15.1.0标准返回理论宽度。

旧版文本渲染引擎不支持所有现代Unicode功能,因此某些文本的渲染宽度可能与Unicode Display Width返回的理论结果相差很大。这包括vim、emacs、大多数终端模拟器和大多数shell。

即使是基于浏览器的现代文本渲染解决方案(例如,使用Electron通过Chromium的VS Code)也与理论Unicode宽度不完全一致。例如,"슬라바 우크라이나"在GitHub上的水平像素比"🔥🗡🍩👩🏻‍🚀⏰💃🏼🔦👍🏻"少,但理论宽度更大。有关更深入的讨论,请参阅字体

包括天城文在内的印度语脚本似乎没有等宽表示。在这些脚本中,零宽度连接符具有不同的语义。Unicode Display Width在这些代码点上不会产生有用的结果。

宽度是以列为单位测量的,因此它不适用于非等宽的编辑器。这包括Microsoft Word或Google Docs等所见即所得编辑器。

有关渲染引擎和文本编辑器的更深入讨论,请参阅编辑器选择历史替代方案

致谢

我想向Joe Lanska表示衷心的感谢,感谢他坚定不移的支持以及他为我改进文档所付出的所有时间。

支持

如果您想进一步支持开发,请考虑为我买杯咖啡

依赖项

~555KB