terminal width of Unicode 16.0+Emoji strings in nanoseconds
Project description
Overview
Use uwcwidth
when you want to very quickly find out how many characters a Unicode string takes up in your terminal.
For example, uwcwidth.wcswidth('Hello🥹')
returns 7
because your terminal will use 5 places for "Hello" and then 2 places for the "🥹" emoji.
uwcwidth
is designed to run as fast as standard built-in Python string operations and use a tiny amount of memory.
Installation
pip install uwcwidth
Isn't this easy?
Let's take a look at "👩🦯➡️":
While len('\U0001F469\u200d\U0001F9AF\u200d\u27a1\ufe0f')
returns 6
because this string has 6 unicode codepoints, we are looking at a single emoji "👩🦯➡️". This emoji occupies 2 characters in your terminal. Here I am assuming your terminal knows how to deal with the special Zero-Width Joiner (U+200D) and the Variation Selector-16 Emoji (U+FE0F). Things get worse as there are special modifiers for skin tone, which can be either invisible or standalone characters, etc. Also, you have to deal with other languages and their scripts, etc.
Correctness
uwcwidth
should work fine on various scripts such as Cyrillic, Katakana, and also Emojis in Unicode v16.0. This includes Emojis that use Variation Selector 15 and 16, Zero Width Joiner, Emoji Modifiers for skin type, etc. Overall, uwcwidth
is probably more accurate than whatever is currently shipping with your OS and whatever your terminal is using in 2024.
Some edge cases that break other wc(s)width
libraries and a lot of terminals:
from uwcwidth import wcswidth
# Should be 8 terminal chars: 🏃🏾♂️=🏃️🏾♂
assert wcswidth('\U0001F3C3\U0001F3FE\u200d\u2642\ufe0f'
'=\U0001F3C3\ufe0f\U0001F3FE\u2642') == 8
# Should be 5 terminal chars: ⛹🏼🏴!
assert wcswidth('\u26f9\U0001F3FC'
'\U0001F3F4\U000E0067\U000E0062\U000E0073'
'\U000E0063\U000E0074\U000E007F!') == 5
See the tests
folder for more.
Tiny footprint and code
uwcwidth
reserves around 4 KB of memory for its lookup tables. Parts of the storage scheme are derived from an older wcwidth
implementation in musl libc. Generally sparse or dense bitmaps are used to look things up.
The uwcwidth.pyx
file is under 100 lines of code, with comments and whitespace.
Performance: 30x faster than wcwidth
uwcwidth
is about 30 times faster than the popular, well-documented and highly tested wcwidth library, while maintaining similar accuracy. It's also 5 times faster than cwcwidth
, which does not work on new Emojis and breaks on some other edge cases.
In [1]: import wcwidth, cwcwidth, uwcwidth
In [2]: %%timeit
...: wcwidth.wcswidth("コンニチハ, セカイ!")
1.28 μs ± 6.22 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
In [3]: %%timeit
...: cwcwidth.wcswidth("コンニチハ, セカイ!")
205 ns ± 0.408 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
In [4]: %%timeit
...: uwcwidth.wcswidth("コンニチハ, セカイ!")
38.5 ns ± 0.29 ns per loop (mean ± std. dev. of 7 runs, 10,000,000 loops each)
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file uwcwidth-0.9.tar.gz
.
File metadata
- Download URL: uwcwidth-0.9.tar.gz
- Upload date:
- Size: 11.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.12.5
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | ce037fc75af62c94d29db454ec0af96a4d6a13d441e9a494222b3cb4243d1fa3 |
|
MD5 | 59d77dcaada69e55add726eb3774bcab |
|
BLAKE2b-256 | a360108a19a99885bddac4e629ee5ca44a0d90045bcafac902045ba8df087911 |
File details
Details for the file uwcwidth-0.9-cp312-cp312-macosx_14_0_arm64.whl
.
File metadata
- Download URL: uwcwidth-0.9-cp312-cp312-macosx_14_0_arm64.whl
- Upload date:
- Size: 30.3 kB
- Tags: CPython 3.12, macOS 14.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.12.5
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 281bf1982c100aabaa9d8987e607ce64286c57058bca80e978495d73725d0366 |
|
MD5 | cd7f97f46bed9a1c0841410b91418dde |
|
BLAKE2b-256 | 38ecd9549889b7cbe7581091def18c8d319ea907bee72683d0e64c5781ad6b17 |