2 个不稳定版本
0.3.0 | 2023年11月15日 |
---|---|
0.2.0 | 2023年10月23日 |
#428 in 文本处理
890 每月下载量
在 11 个 Crates 中使用 (5 直接使用)
16KB
205 行
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