wcwidth 0.9.0__tar.gz → 0.9.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {wcwidth-0.9.0 → wcwidth-0.9.2}/.gitignore +4 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/PKG-INFO +6 -5
- {wcwidth-0.9.0 → wcwidth-0.9.2}/README.rst +5 -4
- {wcwidth-0.9.0 → wcwidth-0.9.2}/bin/update-docs.py +38 -15
- {wcwidth-0.9.0 → wcwidth-0.9.2}/docs/developing.rst +6 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/docs/history.rst +21 -2
- {wcwidth-0.9.0 → wcwidth-0.9.2}/docs/intro.rst +5 -4
- {wcwidth-0.9.0 → wcwidth-0.9.2}/docs/libwcwidth.rst +36 -12
- {wcwidth-0.9.0 → wcwidth-0.9.2}/docs/specs.rst +60 -45
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/include/wcwidth/align.h +5 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/include/wcwidth/utf8.h +9 -2
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/include/wcwidth/wcwidth_config.h +2 -2
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/src/textwrap.c +10 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/src/utf8.c +8 -18
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/src/wcstwidth.c +1 -1
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/src/width.c +47 -20
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/tests/test_align.c +29 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/tests/test_clip.c +51 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/tests/test_sgr.c +50 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/tests/test_text_sizing.c +13 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/tests/test_textwrap.c +71 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/tests/test_utf8.c +29 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/tests/test_wcswidth.c +7 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/tests/test_width.c +69 -1
- {wcwidth-0.9.0 → wcwidth-0.9.2}/pyproject.toml +4 -5
- {wcwidth-0.9.0 → wcwidth-0.9.2}/requirements-update.txt +1 -1
- wcwidth-0.9.2/requirements-wheels.in +4 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/requirements-wheels.txt +4 -11
- {wcwidth-0.9.0 → wcwidth-0.9.2}/tests/test_benchmarks.py +10 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/tests/test_check_release.py +1 -1
- {wcwidth-0.9.0 → wcwidth-0.9.2}/tests/test_clip.py +28 -0
- wcwidth-0.9.2/tests/test_fastcall_args.py +118 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/tests/test_term_overrides.py +32 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/tests/test_textwrap.py +21 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/tests/test_width.py +10 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/tox.ini +58 -9
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/__init__.py +1 -1
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/_clip.py +9 -2
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/_wcswidth.py +1 -1
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/_wcwidth_c.c +724 -107
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/_width.py +1 -1
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/align.py +61 -3
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/textwrap.py +9 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth.egg-info/PKG-INFO +6 -5
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth.egg-info/SOURCES.txt +1 -1
- wcwidth-0.9.0/docs/api_c.rst +0 -1042
- wcwidth-0.9.0/requirements-wheels.in +0 -3
- {wcwidth-0.9.0 → wcwidth-0.9.2}/.pylintrc +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/LICENSE +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/MANIFEST.in +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/bin/check-release.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/bin/update-tables.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/bin/verify-table-integrity.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/bin/wcwidth-browser.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/bin/wcwidth-libc-comparator.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/code_templates/api_c.rst.j2 +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/code_templates/c_gcb_class.c.j2 +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/code_templates/c_table.c.j2 +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/code_templates/c_term_programs.c.j2 +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/code_templates/c_terminal_overrides.c.j2 +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/code_templates/grapheme_override_per_terminal.py.j2 +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/code_templates/grapheme_override_table.py.j2 +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/code_templates/grapheme_registry.py.j2 +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/code_templates/grapheme_table.c.j2 +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/code_templates/grapheme_table.py.j2 +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/code_templates/python_table.py.j2 +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/code_templates/table_overrides.py.j2 +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/code_templates/tables.h.j2 +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/code_templates/term_programs.py.j2 +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/code_templates/unicode_version.rst.j2 +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/code_templates/unicode_versions.py.j2 +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/code_templates/wcwidth_config.h.j2 +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/docs/api.rst +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/docs/conf.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/docs/index.rst +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/docs/related.rst +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/docs/unicode_version.rst +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/.clang-format +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/CMakeLists.txt +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/LICENSE +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/Makefile +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/README.rst +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/cmake/libwcwidth-config.cmake.in +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/examples/align.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/examples/textwrap.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/examples/width.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/include/wcwidth/clip.h +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/include/wcwidth/escape.h +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/include/wcwidth/grapheme.h +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/include/wcwidth/sgr.h +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/include/wcwidth/table_types.h +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/include/wcwidth/tables.h +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/include/wcwidth/terminal_override.h +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/include/wcwidth/text_sizing.h +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/include/wcwidth/textwrap.h +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/include/wcwidth/unicode.h +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/include/wcwidth/wcwidth.h +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/include/wcwidth/width.h +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/src/align.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/src/bisearch.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/src/clip.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/src/escape.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/src/grapheme.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/src/sgr.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/src/tables/table_ambiguous.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/src/tables/table_gcb_class.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/src/tables/table_grapheme.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/src/tables/table_mc.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/src/tables/table_term_programs.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/src/tables/table_terminal_overrides.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/src/tables/table_vs15.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/src/tables/table_vs16.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/src/tables/table_wide.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/src/tables/table_zero.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/src/terminal_override.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/src/text_sizing.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/src/wcswidth.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/src/wcwidth.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/tests/test_common.h +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/tests/test_escape.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/tests/test_gcb_class.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/tests/test_grapheme.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/libwcwidth/tests/test_wcwidth.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/requirements-develop.txt +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/requirements-docs.in +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/requirements-tests39.in +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/requirements-tests39.txt +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/requirements-update.in +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/setup.cfg +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/setup.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/tests/__init__.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/tests/conftest.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/tests/test_ambiguous.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/tests/test_clip_cjk_emoji.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/tests/test_clip_overtyping.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/tests/test_core.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/tests/test_emojis.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/tests/test_grapheme.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/tests/test_hyperlink.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/tests/test_justify.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/tests/test_setup.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/tests/test_sgr_state.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/tests/test_text_sizing.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/tests/test_ucslevel.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/_constants.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/_wcwidth.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/_wcwidth_c.pyi +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/bisearch.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/control_codes.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/escape_sequences.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/grapheme.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/hyperlink.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/py.typed +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/sgr_state.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/table_ambiguous.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/table_grapheme.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/table_grapheme_overrides/__init__.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/table_grapheme_overrides/_known_058c7585.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/table_grapheme_overrides/_known_2148ff29.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/table_grapheme_overrides/_known_244dc88b.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/table_grapheme_overrides/_known_336a71a1.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/table_grapheme_overrides/_known_33ac73f2.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/table_grapheme_overrides/_known_3a1895d5.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/table_grapheme_overrides/_known_59180a0d.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/table_grapheme_overrides/_known_65c6beb5.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/table_grapheme_overrides/_known_78f828e8.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/table_grapheme_overrides/_known_8c2ae14d.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/table_grapheme_overrides/_known_900356bf.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/table_grapheme_overrides/_known_97904ece.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/table_grapheme_overrides/_known_a5880eeb.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/table_grapheme_overrides/_known_b6d33cf4.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/table_grapheme_overrides/_known_c57c295b.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/table_grapheme_overrides/_known_cf02297d.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/table_grapheme_overrides/_known_e18ac6a7.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/table_grapheme_overrides/_known_e2b75ee3.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/table_grapheme_overrides/_known_fb5fd79b.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/table_grapheme_overrides/_known_fdc99132.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/table_grapheme_overrides/_registry.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/table_mc.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/table_overrides.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/table_term_programs.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/table_vs15.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/table_vs16.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/table_wide.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/table_zero.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/text_sizing.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/unicode_versions.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth/wcwidth.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth.egg-info/dependency_links.txt +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.2}/wcwidth.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: wcwidth
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.2
|
|
4
4
|
Summary: Measures the displayed width of unicode strings in a terminal
|
|
5
5
|
Author-email: Jeff Quast <contact@jeffquast.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/jquast/wcwidth
|
|
@@ -97,8 +97,9 @@ This library may be considered to presume the terminal is enabled for DEC Privat
|
|
|
97
97
|
("Grapheme Clustering") by default, which may require to be enabled by a TUI application but
|
|
98
98
|
is often the default mode for those terminals that support it.
|
|
99
99
|
|
|
100
|
-
This library does support any specific "legacy width" measurement by API, but it does provide
|
|
101
|
-
Corrections_ for
|
|
100
|
+
This library does not support any specific "legacy width" measurement by API, but it does provide
|
|
101
|
+
Corrections_ for terminals using "legacy width" measurements or are without basic emoji or grapheme
|
|
102
|
+
support.
|
|
102
103
|
|
|
103
104
|
See also:
|
|
104
105
|
|
|
@@ -154,7 +155,7 @@ anywhere in the string.
|
|
|
154
155
|
wcstwidth()
|
|
155
156
|
-----------
|
|
156
157
|
|
|
157
|
-
|
|
158
|
+
`wcstwidth()`_ is a variant of `wcswidth()`_ that provides terminal-specific Corrections_, reading
|
|
158
159
|
``TERM_PROGRAM`` or ``TERM`` when ``True`` (default), or caller can provide terminal query
|
|
159
160
|
XTVERSION_ or ENQ_ response:
|
|
160
161
|
|
|
@@ -550,7 +551,7 @@ https://wcwidth.readthedocs.io/en/latest/related.html
|
|
|
550
551
|
.. _`str.rjust()`: https://docs.python.org/3/library/stdtypes.html#str.rjust
|
|
551
552
|
.. _`str.center()`: https://docs.python.org/3/library/stdtypes.html#str.center
|
|
552
553
|
.. _`str.expandtabs()`: https://docs.python.org/3/library/stdtypes.html#str.expandtabs
|
|
553
|
-
.. _`General Tabulated Summary`: https://ucs-detect.readthedocs.io/results.html#tabulated-
|
|
554
|
+
.. _`General Tabulated Summary`: https://ucs-detect.readthedocs.io/results.html#general-tabulated-summary
|
|
554
555
|
.. _`wcwidth()`: https://wcwidth.readthedocs.io/en/latest/api.html#wcwidth.wcwidth
|
|
555
556
|
.. _`wcswidth()`: https://wcwidth.readthedocs.io/en/latest/api.html#wcwidth.wcswidth
|
|
556
557
|
.. _`wcstwidth()`: https://wcwidth.readthedocs.io/en/latest/api.html#wcwidth.wcstwidth
|
|
@@ -66,8 +66,9 @@ This library may be considered to presume the terminal is enabled for DEC Privat
|
|
|
66
66
|
("Grapheme Clustering") by default, which may require to be enabled by a TUI application but
|
|
67
67
|
is often the default mode for those terminals that support it.
|
|
68
68
|
|
|
69
|
-
This library does support any specific "legacy width" measurement by API, but it does provide
|
|
70
|
-
Corrections_ for
|
|
69
|
+
This library does not support any specific "legacy width" measurement by API, but it does provide
|
|
70
|
+
Corrections_ for terminals using "legacy width" measurements or are without basic emoji or grapheme
|
|
71
|
+
support.
|
|
71
72
|
|
|
72
73
|
See also:
|
|
73
74
|
|
|
@@ -123,7 +124,7 @@ anywhere in the string.
|
|
|
123
124
|
wcstwidth()
|
|
124
125
|
-----------
|
|
125
126
|
|
|
126
|
-
|
|
127
|
+
`wcstwidth()`_ is a variant of `wcswidth()`_ that provides terminal-specific Corrections_, reading
|
|
127
128
|
``TERM_PROGRAM`` or ``TERM`` when ``True`` (default), or caller can provide terminal query
|
|
128
129
|
XTVERSION_ or ENQ_ response:
|
|
129
130
|
|
|
@@ -519,7 +520,7 @@ https://wcwidth.readthedocs.io/en/latest/related.html
|
|
|
519
520
|
.. _`str.rjust()`: https://docs.python.org/3/library/stdtypes.html#str.rjust
|
|
520
521
|
.. _`str.center()`: https://docs.python.org/3/library/stdtypes.html#str.center
|
|
521
522
|
.. _`str.expandtabs()`: https://docs.python.org/3/library/stdtypes.html#str.expandtabs
|
|
522
|
-
.. _`General Tabulated Summary`: https://ucs-detect.readthedocs.io/results.html#tabulated-
|
|
523
|
+
.. _`General Tabulated Summary`: https://ucs-detect.readthedocs.io/results.html#general-tabulated-summary
|
|
523
524
|
.. _`wcwidth()`: https://wcwidth.readthedocs.io/en/latest/api.html#wcwidth.wcwidth
|
|
524
525
|
.. _`wcswidth()`: https://wcwidth.readthedocs.io/en/latest/api.html#wcwidth.wcswidth
|
|
525
526
|
.. _`wcstwidth()`: https://wcwidth.readthedocs.io/en/latest/api.html#wcwidth.wcstwidth
|
|
@@ -6,7 +6,9 @@ from __future__ import annotations
|
|
|
6
6
|
# std imports
|
|
7
7
|
import os
|
|
8
8
|
import re
|
|
9
|
+
import sys
|
|
9
10
|
import glob
|
|
11
|
+
import argparse
|
|
10
12
|
import textwrap
|
|
11
13
|
import importlib.util
|
|
12
14
|
|
|
@@ -21,7 +23,7 @@ import jinja2
|
|
|
21
23
|
# docs/unicode_version.rst, docs/libwcwidth.rst, and the list_term_programs()
|
|
22
24
|
# example in README.rst.
|
|
23
25
|
|
|
24
|
-
PATH_UP = os.path.
|
|
26
|
+
PATH_UP = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
25
27
|
JINJA_ENV = jinja2.Environment(
|
|
26
28
|
loader=jinja2.FileSystemLoader(os.path.join(PATH_UP, 'code_templates')),
|
|
27
29
|
keep_trailing_newline=True,
|
|
@@ -458,21 +460,29 @@ def report(label: str, changed: bool) -> None:
|
|
|
458
460
|
print(f'{label}: {"updated" if changed else "up-to-date"}')
|
|
459
461
|
|
|
460
462
|
|
|
461
|
-
def write_if_changed(path: str, content: str, label: str) ->
|
|
462
|
-
"""
|
|
463
|
+
def write_if_changed(path: str, content: str, label: str, check: bool = False) -> bool:
|
|
464
|
+
"""
|
|
465
|
+
Write *content* to *path* only if it differs, reporting and returning whether it did.
|
|
466
|
+
|
|
467
|
+
With *check*, report the difference without writing, so a stale file fails the run.
|
|
468
|
+
"""
|
|
463
469
|
try:
|
|
464
470
|
with open(path, encoding='utf-8') as fin:
|
|
465
471
|
original = fin.read()
|
|
466
472
|
except FileNotFoundError:
|
|
467
473
|
original = ''
|
|
468
|
-
if content
|
|
469
|
-
new_path = path + '.new'
|
|
470
|
-
with open(new_path, 'w', encoding='utf-8', newline='\n') as fout:
|
|
471
|
-
fout.write(content)
|
|
472
|
-
os.replace(new_path, path)
|
|
473
|
-
print(f'{label}: updated')
|
|
474
|
-
else:
|
|
474
|
+
if content == original:
|
|
475
475
|
print(f'{label}: up-to-date')
|
|
476
|
+
return False
|
|
477
|
+
if check:
|
|
478
|
+
print(f'{label}: out of date, run bin/update-docs.py')
|
|
479
|
+
return True
|
|
480
|
+
new_path = path + '.new'
|
|
481
|
+
with open(new_path, 'w', encoding='utf-8', newline='\n') as fout:
|
|
482
|
+
fout.write(content)
|
|
483
|
+
os.replace(new_path, path)
|
|
484
|
+
print(f'{label}: updated')
|
|
485
|
+
return True
|
|
476
486
|
|
|
477
487
|
|
|
478
488
|
def update_libwcwidth_term_programs() -> bool:
|
|
@@ -545,18 +555,31 @@ def unicode_version_page() -> str:
|
|
|
545
555
|
source_headers=unicode_source_headers())
|
|
546
556
|
|
|
547
557
|
|
|
548
|
-
def main() ->
|
|
549
|
-
"""Regenerate all generated documentation files."""
|
|
550
|
-
write_if_changed(API_C_OUTPUT, render_api_doc(), 'docs/api_c.rst')
|
|
558
|
+
def main(api_only: bool = False, check: bool = False) -> int:
|
|
559
|
+
"""Regenerate all generated documentation files, or only docs/api_c.rst."""
|
|
560
|
+
stale = write_if_changed(API_C_OUTPUT, render_api_doc(), 'docs/api_c.rst', check)
|
|
561
|
+
if api_only:
|
|
562
|
+
# api_c.rst is parsed from the C headers, but everything below reads the
|
|
563
|
+
# Unicode sources under data/, which only `tox -e fetch` downloads.
|
|
564
|
+
return int(check and stale)
|
|
551
565
|
write_if_changed(os.path.join(PATH_DOCS, 'unicode_version.rst'),
|
|
552
|
-
unicode_version_page(), 'docs/unicode_version.rst')
|
|
566
|
+
unicode_version_page(), 'docs/unicode_version.rst', check)
|
|
553
567
|
report('docs/libwcwidth.rst: canonical terminal names',
|
|
554
568
|
update_libwcwidth_term_programs())
|
|
555
569
|
report('docs/libwcwidth.rst: Unicode version',
|
|
556
570
|
update_libwcwidth_unicode_version())
|
|
557
571
|
report('README.rst: list_term_programs() example',
|
|
558
572
|
update_readme_term_programs())
|
|
573
|
+
return int(check and stale)
|
|
559
574
|
|
|
560
575
|
|
|
561
576
|
if __name__ == '__main__':
|
|
562
|
-
|
|
577
|
+
parser = argparse.ArgumentParser(description=__doc__)
|
|
578
|
+
parser.add_argument('--api-only', action='store_true',
|
|
579
|
+
help='regenerate docs/api_c.rst only, which needs no Unicode data')
|
|
580
|
+
parser.add_argument('--check', action='store_true',
|
|
581
|
+
help='report stale output instead of writing it, for CI')
|
|
582
|
+
args = parser.parse_args()
|
|
583
|
+
if args.check and not args.api_only:
|
|
584
|
+
parser.error('--check needs --api-only: the other outputs read the fetched Unicode data')
|
|
585
|
+
sys.exit(main(api_only=args.api_only, check=args.check))
|
|
@@ -18,6 +18,12 @@ To run tests with detailed coverage reporting showing missing lines::
|
|
|
18
18
|
|
|
19
19
|
tox -epy314 -- --cov-report=term-missing
|
|
20
20
|
|
|
21
|
+
The C11 library's coverage is measured separately, since coverage.py cannot see compiled
|
|
22
|
+
code. This merges two instrumented runs, the C11 test suite and the Python suite driving
|
|
23
|
+
the C extension, and writes ``coverage-c.lcov`` and ``htmlcov-c/index.html``::
|
|
24
|
+
|
|
25
|
+
tox -e c_coverage
|
|
26
|
+
|
|
21
27
|
Updating Unicode Version
|
|
22
28
|
------------------------
|
|
23
29
|
|
|
@@ -2,7 +2,20 @@
|
|
|
2
2
|
History
|
|
3
3
|
=======
|
|
4
4
|
|
|
5
|
-
0.9.
|
|
5
|
+
0.9.2 *2026-10-04*
|
|
6
|
+
* **Bugfix** `wrap()`_ should omit an empty line as output, like `textwrap.wrap()`_ `PR #291`_.
|
|
7
|
+
* **Bugfix** `clip()`_ when using non-default argument, ``tabsize=0``, `PR #288`_.
|
|
8
|
+
* **Bugfix** regional-indicator pairs (flags) when corrected for terminals that show lone regional
|
|
9
|
+
indicators as narrow (xterm, wezterm, VTE, and others) in `wcstwidth()`_ and `width()`_, `PR
|
|
10
|
+
#284`.
|
|
11
|
+
|
|
12
|
+
0.9.1 *2026-09-23*
|
|
13
|
+
* **Bugfix** `width()`_ in Python and libwcwidth mis-measured CSI sequences over 64 bytes, a 0.9.0
|
|
14
|
+
release regression! `PR #271`_.
|
|
15
|
+
* **Performance** improvement of ~15% for many Python API functions when using default arguments
|
|
16
|
+
like ``ambiguous_width`` and ``term_program``. `PR #273`_
|
|
17
|
+
|
|
18
|
+
0.9.0 *2026-09-23*
|
|
6
19
|
* **New** Optional CPython extension using libwcwidth_, improving performance 10-58x `PR #248`_.
|
|
7
20
|
* **Drop Support** for Python 3.8, `PR #248`_.
|
|
8
21
|
|
|
@@ -233,7 +246,7 @@ https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c::
|
|
|
233
246
|
* for any purpose and without fee is hereby granted. The author
|
|
234
247
|
* disclaims all warranties with regard to this software.
|
|
235
248
|
|
|
236
|
-
.. _`Spacing Combining Mark`: https://www.unicode.org/versions/latest/
|
|
249
|
+
.. _`Spacing Combining Mark`: https://www.unicode.org/versions/latest/core-spec/chapter-4/#G134153
|
|
237
250
|
.. _`specification`: https://wcwidth.readthedocs.io/en/latest/specs.html
|
|
238
251
|
.. _`prospector`: https://github.com/landscapeio/prospector
|
|
239
252
|
.. _`combining`: https://en.wikipedia.org/wiki/Combining_character
|
|
@@ -299,6 +312,12 @@ https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c::
|
|
|
299
312
|
.. _`PR #253`: https://github.com/jquast/wcwidth/pull/253
|
|
300
313
|
.. _`PR #259`: https://github.com/jquast/wcwidth/pull/259
|
|
301
314
|
.. _`PR #262`: https://github.com/jquast/wcwidth/pull/262
|
|
315
|
+
.. _`PR #271`: https://github.com/jquast/wcwidth/pull/271
|
|
316
|
+
.. _`PR #273`: https://github.com/jquast/wcwidth/pull/273
|
|
317
|
+
.. _`PR #281`: https://github.com/jquast/wcwidth/pull/281
|
|
318
|
+
.. _`PR #284`: https://github.com/jquast/wcwidth/pull/284
|
|
319
|
+
.. _`PR #288`: https://github.com/jquast/wcwidth/pull/288
|
|
320
|
+
.. _`PR #291`: https://github.com/jquast/wcwidth/pull/291
|
|
302
321
|
.. _`Issue #101`: https://github.com/jquast/wcwidth/issues/101
|
|
303
322
|
.. _`Issue #155`: https://github.com/jquast/wcwidth/issues/155
|
|
304
323
|
.. _`Issue #211`: https://github.com/jquast/wcwidth/issues/211
|
|
@@ -66,8 +66,9 @@ This library may be considered to presume the terminal is enabled for DEC Privat
|
|
|
66
66
|
("Grapheme Clustering") by default, which may require to be enabled by a TUI application but
|
|
67
67
|
is often the default mode for those terminals that support it.
|
|
68
68
|
|
|
69
|
-
This library does support any specific "legacy width" measurement by API, but it does provide
|
|
70
|
-
Corrections_ for
|
|
69
|
+
This library does not support any specific "legacy width" measurement by API, but it does provide
|
|
70
|
+
Corrections_ for terminals using "legacy width" measurements or are without basic emoji or grapheme
|
|
71
|
+
support.
|
|
71
72
|
|
|
72
73
|
See also:
|
|
73
74
|
|
|
@@ -123,7 +124,7 @@ anywhere in the string.
|
|
|
123
124
|
wcstwidth()
|
|
124
125
|
-----------
|
|
125
126
|
|
|
126
|
-
|
|
127
|
+
`wcstwidth()`_ is a variant of `wcswidth()`_ that provides terminal-specific Corrections_, reading
|
|
127
128
|
``TERM_PROGRAM`` or ``TERM`` when ``True`` (default), or caller can provide terminal query
|
|
128
129
|
XTVERSION_ or ENQ_ response:
|
|
129
130
|
|
|
@@ -519,7 +520,7 @@ https://wcwidth.readthedocs.io/en/latest/related.html
|
|
|
519
520
|
.. _`str.rjust()`: https://docs.python.org/3/library/stdtypes.html#str.rjust
|
|
520
521
|
.. _`str.center()`: https://docs.python.org/3/library/stdtypes.html#str.center
|
|
521
522
|
.. _`str.expandtabs()`: https://docs.python.org/3/library/stdtypes.html#str.expandtabs
|
|
522
|
-
.. _`General Tabulated Summary`: https://ucs-detect.readthedocs.io/results.html#tabulated-
|
|
523
|
+
.. _`General Tabulated Summary`: https://ucs-detect.readthedocs.io/results.html#general-tabulated-summary
|
|
523
524
|
.. _`wcwidth()`: https://wcwidth.readthedocs.io/en/latest/api.html#wcwidth.wcwidth
|
|
524
525
|
.. _`wcswidth()`: https://wcwidth.readthedocs.io/en/latest/api.html#wcwidth.wcswidth
|
|
525
526
|
.. _`wcstwidth()`: https://wcwidth.readthedocs.io/en/latest/api.html#wcwidth.wcstwidth
|
|
@@ -10,16 +10,20 @@ The Python documentation_ closely matches this C library. The C API adds UTF-8
|
|
|
10
10
|
array interfaces.
|
|
11
11
|
|
|
12
12
|
The lowest-level functions are derived from POSIX.1-2001 and POSIX.1-2008 `wcwidth(3)`_ and
|
|
13
|
-
`wcswidth(3)`_, which this library implements as
|
|
14
|
-
functions return -1 when C0 and C1 control
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
`wcswidth(3)`_, which this library implements as :ref:`wcwidth_u32() <libwcwidth-wcwidth>` and
|
|
14
|
+
:ref:`wcswidth_u32() <libwcwidth-wcswidth>`. These functions return -1 when C0 and C1 control
|
|
15
|
+
codes other than NUL are present; NUL measures as zero-width.
|
|
16
|
+
:ref:`wcstwidth_u8() <libwcwidth-wcstwidth>` applies corrections for a specific terminal program,
|
|
17
|
+
as described in the Python Corrections_ documentation.
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
:ref:`wcwidth_width_u8() <libwcwidth-width>` is a higher-level wrapper of
|
|
20
|
+
:ref:`wcswidth_u8() <libwcwidth-wcswidth>` that also measures terminal control sequences, like
|
|
21
|
+
colors, bold, tabstops, and horizontal cursor movement.
|
|
20
22
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
+
The text transforms have their own sections:
|
|
24
|
+
:ref:`wcwidth_ljust_u8() <libwcwidth-align>` with ``rjust`` and ``center``,
|
|
25
|
+
:ref:`wcwidth_clip_u8() <libwcwidth-clip>`, :ref:`wcwidth_wrap_u8() <libwcwidth-wrap>`, and
|
|
26
|
+
:ref:`wcwidth_escape_strip() <libwcwidth-escape-strip>`.
|
|
23
27
|
|
|
24
28
|
Quick Start
|
|
25
29
|
-----------
|
|
@@ -133,16 +137,15 @@ address:
|
|
|
133
137
|
String length conventions
|
|
134
138
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
135
139
|
|
|
136
|
-
Every string function
|
|
140
|
+
Every string function reads exactly the length you pass:
|
|
137
141
|
|
|
138
142
|
``_u32`` functions
|
|
139
143
|
count codepoints in the array,
|
|
140
144
|
``_u8`` functions
|
|
141
145
|
count bytes.
|
|
142
146
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
it survives into transform output, whose ``*out_len`` is the true length.
|
|
147
|
+
Pass ``strlen(text)`` when the text is a C string. A NUL counts as an ordinary zero-width character
|
|
148
|
+
in any position. Transform functions copy it through and report the full length in ``*out_len``.
|
|
146
149
|
|
|
147
150
|
Alternate encodings
|
|
148
151
|
~~~~~~~~~~~~~~~~~~~
|
|
@@ -187,6 +190,8 @@ throughout, or use the ``_u32`` forms and re-encode the result. `wcwidth_encode
|
|
|
187
190
|
Re-encoding to a legacy charset is the caller's iconv(3) or ICU (``ucnv_*``) call; a byte cast
|
|
188
191
|
works when every codepoint fits the target, and iconv reports ``EILSEQ`` when one does not.
|
|
189
192
|
|
|
193
|
+
.. _libwcwidth-wcwidth:
|
|
194
|
+
|
|
190
195
|
wcwidth_u32()
|
|
191
196
|
~~~~~~~~~~~~~
|
|
192
197
|
|
|
@@ -206,6 +211,8 @@ U+2640 above is Ambiguous, so it answers to the second argument, while U+2630 is
|
|
|
206
211
|
2 under either setting. A single codepoint needs no ``_u8`` variant; use `wcswidth_u8()`_ to
|
|
207
212
|
measure text.
|
|
208
213
|
|
|
214
|
+
.. _libwcwidth-wcswidth:
|
|
215
|
+
|
|
209
216
|
wcswidth_u32() and wcswidth_u8()
|
|
210
217
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
211
218
|
|
|
@@ -219,6 +226,8 @@ when any control code other than NUL is present:
|
|
|
219
226
|
wcswidth_u32(family, 5, 1) /* man ZWJ woman ZWJ girl */ 2
|
|
220
227
|
wcswidth_u8("café", 5, 1) 4
|
|
221
228
|
|
|
229
|
+
.. _libwcwidth-wcstwidth:
|
|
230
|
+
|
|
222
231
|
wcstwidth_u32() and wcstwidth_u8()
|
|
223
232
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
224
233
|
|
|
@@ -230,6 +239,8 @@ argument applies terminal-specific corrections:
|
|
|
230
239
|
wcswidth_u8("☰", 3, 1) /* U+2630, wide */ 2
|
|
231
240
|
wcstwidth_u8("☰", 3, 1, "vte") 1
|
|
232
241
|
|
|
242
|
+
.. _libwcwidth-width:
|
|
243
|
+
|
|
233
244
|
wcwidth_width_u32() and wcwidth_width_u8()
|
|
234
245
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
235
246
|
|
|
@@ -261,6 +272,8 @@ codes:
|
|
|
261
272
|
/* err is WCWIDTH_ERROR_VERTICAL_CTRL */
|
|
262
273
|
}
|
|
263
274
|
|
|
275
|
+
.. _libwcwidth-align:
|
|
276
|
+
|
|
264
277
|
wcwidth_ljust_u8(), wcwidth_rjust_u8(), and wcwidth_center_u8()
|
|
265
278
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
266
279
|
|
|
@@ -288,6 +301,13 @@ returns a ``malloc``\ 'd NUL-terminated string the caller must ``free``:
|
|
|
288
301
|
/* "*café*" */
|
|
289
302
|
free(out);
|
|
290
303
|
|
|
304
|
+
Tabs are measured as though text begins at column 0. ``wcwidth_rjust_u8()`` and
|
|
305
|
+
``wcwidth_center_u8()`` insert padding to the left of the ``text`` which move tabstops and return
|
|
306
|
+
an incorrect result, always expand tabs or call `wcwidth_clip_u8()`_ to ``opts->dest_width`` first,
|
|
307
|
+
which expands tabs before using these alignment functions.
|
|
308
|
+
|
|
309
|
+
.. _libwcwidth-clip:
|
|
310
|
+
|
|
291
311
|
wcwidth_clip_u8()
|
|
292
312
|
~~~~~~~~~~~~~~~~~
|
|
293
313
|
|
|
@@ -344,6 +364,8 @@ Movement is reported wherever it appears; the OSC sequences only where the clip
|
|
|
344
364
|
`wcwidth_clip_u32()`_ is the codepoint-array form, returning a ``malloc``\ 'd array of ``*out_len``
|
|
345
365
|
codepoints.
|
|
346
366
|
|
|
367
|
+
.. _libwcwidth-wrap:
|
|
368
|
+
|
|
347
369
|
wcwidth_wrap_u8() and wcwidth_wrap_u8_text()
|
|
348
370
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
349
371
|
|
|
@@ -383,6 +405,8 @@ unbreakable unit, so a line is never broken inside one, even at a space or hyphe
|
|
|
383
405
|
text. Python's `wrap()`_ behaves the same way. `wcwidth_wrap_u32()`_ and `wcwidth_wrap_u32_text()`_ are the
|
|
384
406
|
codepoint-array forms.
|
|
385
407
|
|
|
408
|
+
.. _libwcwidth-escape-strip:
|
|
409
|
+
|
|
386
410
|
wcwidth_escape_strip()
|
|
387
411
|
~~~~~~~~~~~~~~~~~~~~~~
|
|
388
412
|
|
|
@@ -4,10 +4,11 @@
|
|
|
4
4
|
Specification
|
|
5
5
|
=============
|
|
6
6
|
|
|
7
|
-
This document defines how
|
|
8
|
-
a string. This is not meant to an official standard, but as a terse
|
|
9
|
-
API functions :func:`wcwidth.wcwidth` and
|
|
10
|
-
functions :func:`wcwidth.width
|
|
7
|
+
This document defines how the Python wcwidth and C11 libwcwidth_ libraries measure the printable
|
|
8
|
+
width of characters of a string. This is not meant to be an official standard, but as a terse
|
|
9
|
+
description of the lowest level API functions :func:`wcwidth.wcwidth` and :func:`wcwidth.wcswidth`
|
|
10
|
+
and their relation to higher level functions :func:`wcwidth.width`, :func:`wcwidth.wcstwidth` and
|
|
11
|
+
:func:`wcwidth.iter_graphemes`.
|
|
11
12
|
|
|
12
13
|
Scope
|
|
13
14
|
-----
|
|
@@ -19,10 +20,19 @@ its docstring and specifications of related control codes, `XTerm Control Sequen
|
|
|
19
20
|
Text Sizing Protocol`_.
|
|
20
21
|
|
|
21
22
|
Each string yielded by :func:`wcwidth.iter_graphemes` may be mapped to :func:`wcwidth.wcswidth` to
|
|
22
|
-
accurately measure the width of a grapheme.
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
accurately measure the width of a grapheme. :func:`wcwidth.iter_graphemes` implements the `Unicode
|
|
24
|
+
Standard Annex #29`_ rules of Unicode 18.0, the version of this library's tables, while
|
|
25
|
+
`unicodedata.iter_graphemes()`_, new in Python 3.15, implements Unicode 17.0. They also differ in
|
|
26
|
+
return value: :func:`wcwidth.iter_graphemes` yields only strings, while
|
|
27
|
+
:func:`unicodedata.iter_graphemes` yields ``unicodedata.Segment`` class objects.
|
|
28
|
+
|
|
29
|
+
Tamil, Kannada and Sinhala text is measured differently than it is segmented, so
|
|
30
|
+
:func:`wcwidth.clip` and :func:`wcwidth.wrap` do not measure these scripts correctly. See `Virama
|
|
31
|
+
Conjunct Formation`_.
|
|
32
|
+
|
|
33
|
+
The C11 library libwcwidth_ implements this specification through parallel entry points:
|
|
34
|
+
``wcswidth_u32()`` and ``wcswidth_u8()`` for :func:`wcwidth.wcswidth`, ``wcstwidth_u8()`` for
|
|
35
|
+
:func:`wcwidth.wcstwidth`, and ``wcwidth_width_u8()`` for :func:`wcwidth.width`; see the `C11 API`_.
|
|
26
36
|
|
|
27
37
|
Width of -1
|
|
28
38
|
-----------
|
|
@@ -30,39 +40,38 @@ Width of -1
|
|
|
30
40
|
The following have a column width of -1 for function :func:`wcwidth.wcwidth`
|
|
31
41
|
|
|
32
42
|
- ``C0`` control characters (`U+0001`_ through `U+001F`_).
|
|
33
|
-
- ``C1`` control characters and ``DEL`` (`U+007F`_ through `U+
|
|
43
|
+
- ``C1`` control characters and ``DEL`` (`U+007F`_ through `U+009F`_).
|
|
34
44
|
|
|
35
45
|
If any character in sequence contains ``C0`` or ``C1`` control characters, the final
|
|
36
|
-
return value of :func:`wcwidth.wcswidth` is -1
|
|
46
|
+
return value of :func:`wcwidth.wcswidth` is -1, except a control character immediately following
|
|
47
|
+
ZWJ (`U+200D`_), which `Width of 0`_ consumes.
|
|
37
48
|
|
|
38
49
|
Width of 0
|
|
39
50
|
----------
|
|
40
51
|
|
|
41
52
|
Any characters with the `Default_Ignorable_Code_Point`_ property in
|
|
42
|
-
`DerivedCoreProperties.txt`_
|
|
43
|
-
|
|
53
|
+
`DerivedCoreProperties.txt`_, excluding `U+00AD`_ SOFT HYPHEN (width 1) and
|
|
54
|
+
`U+115F`_ HANGUL CHOSEONG FILLER (width 2).
|
|
44
55
|
|
|
45
|
-
Any characters defined by `General Category`_ codes in `DerivedGeneralCategory.txt`_
|
|
56
|
+
Any characters defined by `General Category`_ codes in `DerivedGeneralCategory.txt`_:
|
|
46
57
|
|
|
47
|
-
- 'Me': `Enclosing Mark`_
|
|
48
|
-
- 'Mn': `Nonspacing Mark`_
|
|
58
|
+
- 'Me': `Enclosing Mark`_.
|
|
59
|
+
- 'Mn': `Nonspacing Mark`_.
|
|
49
60
|
- 'Cf': `Format`_ control characters excluding `U+00AD`_ SOFT HYPHEN and
|
|
50
|
-
`Prepended_Concatenation_Mark`_ characters
|
|
61
|
+
`Prepended_Concatenation_Mark`_ characters.
|
|
51
62
|
- 'Zl': `U+2028`_ LINE SEPARATOR only
|
|
52
63
|
- 'Zp': `U+2029`_ PARAGRAPH SEPARATOR only
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
an emoji base character in sequence; see `Width of 2`_ for standalone.
|
|
64
|
+
|
|
65
|
+
`Emoji Modifier`_ Fitzpatrick symbols (`U+1F3FB`_ through `U+1F3FF`_) are zero-width
|
|
66
|
+
only when following an emoji base character in sequence; see `Width of 2`_ for standalone.
|
|
57
67
|
|
|
58
68
|
The NULL character (`U+0000`_).
|
|
59
69
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
of `Unicode Standard Annex #29`_.
|
|
64
|
-
|
|
65
|
-
is measured normally.
|
|
70
|
+
ZWJ (`U+200D`_) is zero-width, and in sequence by :func:`wcwidth.wcswidth` or
|
|
71
|
+
:func:`wcwidth.width` the codepoint immediately following it is consumed as zero-width.
|
|
72
|
+
For emoji (`Extended_Pictographic`_ property) and `Regional Indicator`_ sequences this follows the
|
|
73
|
+
grapheme cluster boundary rules of `Unicode Standard Annex #29`_. After a virama, the following
|
|
74
|
+
consonant continues the conjunct, see `Virama Conjunct Formation`_.
|
|
66
75
|
|
|
67
76
|
The second `Regional Indicator`_ symbol (`U+1F1E6`_ through `U+1F1FF`_) in a
|
|
68
77
|
consecutive pair, when measured in sequence by :func:`wcwidth.wcswidth` or
|
|
@@ -71,9 +80,9 @@ consecutive pair, when measured in sequence by :func:`wcwidth.wcswidth` or
|
|
|
71
80
|
`Hangul Jamo`_ Jungseong and "Extended-B" code blocks, `U+1160`_ through
|
|
72
81
|
`U+11FF`_ and `U+D7B0`_ through `U+D7FF`_.
|
|
73
82
|
|
|
74
|
-
Any characters of category ``Mc`` (`Spacing Combining Mark`_),
|
|
75
|
-
|
|
76
|
-
|
|
83
|
+
Any characters of category ``Mc`` (`Spacing Combining Mark`_), for the
|
|
84
|
+
single-character function :func:`wcwidth.wcwidth`. When measured in sequence by
|
|
85
|
+
:func:`wcwidth.wcswidth`, see `Width of 2`_.
|
|
77
86
|
|
|
78
87
|
Width of 1
|
|
79
88
|
----------
|
|
@@ -93,8 +102,9 @@ Width of 2
|
|
|
93
102
|
----------
|
|
94
103
|
|
|
95
104
|
Any character defined by `East Asian`_ (`Unicode Standard Annex #11`_) Fullwidth
|
|
96
|
-
(``F``) or Wide (``W``) properties in `EastAsianWidth.txt`_
|
|
97
|
-
|
|
105
|
+
(``F``) or Wide (``W``) properties in `EastAsianWidth.txt`_, except those that
|
|
106
|
+
are defined by the Category codes of `Nonspacing Mark`_ (``Mn``) or `Spacing
|
|
107
|
+
Combining Mark`_ (``Mc``).
|
|
98
108
|
|
|
99
109
|
`Regional Indicator`_ symbols (`U+1F1E6`_ through `U+1F1FF`_). Though
|
|
100
110
|
classified as Neutral in `EastAsianWidth.txt`_, terminals universally render
|
|
@@ -106,7 +116,7 @@ measured standalone (not following an emoji base character). When following
|
|
|
106
116
|
an emoji base, they combine with the base and add 0 to total width.
|
|
107
117
|
|
|
108
118
|
Any characters of `Modifier Symbol`_ category, ``'Sk'`` where ``'FULLWIDTH'`` is
|
|
109
|
-
present in comment of `UnicodeData.txt`_
|
|
119
|
+
present in comment of `UnicodeData.txt`_.
|
|
110
120
|
|
|
111
121
|
Any character with `U+FE0F`_ (Variation Selector 16) defined as ``emoji style``
|
|
112
122
|
in `emoji-variation-sequences.txt`_, per `UTS #51`_ and `Unicode Standard
|
|
@@ -116,13 +126,14 @@ making the pair width 2. Wide characters are unchanged.
|
|
|
116
126
|
Any character of non-zero width followed by an ``Mc`` (`Spacing Combining Mark`_)
|
|
117
127
|
character when measured in sequence by :func:`wcwidth.wcswidth` or
|
|
118
128
|
:func:`wcwidth.width`. The ``Mc`` character caps the cluster width at 2,
|
|
119
|
-
reflecting its *positive advance width* as defined in `General Category`_
|
|
120
|
-
|
|
121
|
-
|
|
129
|
+
reflecting its *positive advance width* as defined in the `General Category Values`_
|
|
130
|
+
table. Zero-width combining marks (``Mn``) between the base character and the ``Mc``
|
|
131
|
+
do not break the association. For example, a consonant followed
|
|
122
132
|
by a Nukta (``Mn``) and then a vowel sign (``Mc``) is measured as a cluster of
|
|
123
133
|
width 2.
|
|
124
134
|
|
|
125
|
-
Any grapheme cluster width is limited to 2 cells since 0.8.0, `PR #224`_
|
|
135
|
+
Any grapheme cluster width is limited to 2 cells since 0.8.0, `PR #224`_, which prevents the ``Mc``
|
|
136
|
+
rule and the virama conjunct sum from exceeding 2 cells.
|
|
126
137
|
|
|
127
138
|
Virama Conjunct Formation
|
|
128
139
|
-------------------------
|
|
@@ -145,16 +156,19 @@ described in the Virama section header).
|
|
|
145
156
|
- ZWJ (`U+200D`_) after a virama is consumed without breaking conjunct state,
|
|
146
157
|
supporting explicit half-form requests (virama + ZWJ + consonant).
|
|
147
158
|
|
|
148
|
-
See also: `L2/
|
|
159
|
+
See also: `L2/23-107`_ "Proper Complex Script Support in Text Terminals", the 2023 project
|
|
160
|
+
proposal that records the missing terminal-width standard, and `L2/25-263`_ for the Text Terminal
|
|
161
|
+
Working Group's latest report.
|
|
149
162
|
|
|
150
|
-
.. _`Hyperlinks in Terminal Emulators`: https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda
|
|
151
163
|
.. _`Kitty Text Sizing Protocol`: https://sw.kovidgoyal.net/kitty/text-sizing-protocol/
|
|
152
164
|
.. _`XTerm Control Sequences`: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html
|
|
165
|
+
.. _`C11 API`: https://wcwidth.readthedocs.io/en/latest/api_c.html
|
|
166
|
+
.. _libwcwidth: https://wcwidth.readthedocs.io/en/latest/libwcwidth.html
|
|
153
167
|
.. _`U+0000`: https://codepoints.net/U+0000
|
|
154
168
|
.. _`U+0001`: https://codepoints.net/U+0001
|
|
155
169
|
.. _`U+001F`: https://codepoints.net/U+001F
|
|
156
170
|
.. _`U+007F`: https://codepoints.net/U+007F
|
|
157
|
-
.. _`U+
|
|
171
|
+
.. _`U+009F`: https://codepoints.net/U+009F
|
|
158
172
|
.. _`U+00AD`: https://codepoints.net/U+00AD
|
|
159
173
|
.. _`U+1160`: https://codepoints.net/U+1160
|
|
160
174
|
.. _`U+11FF`: https://codepoints.net/U+11FF
|
|
@@ -172,12 +186,13 @@ See also: `L2/2023/23107`_ "Proper Complex Script Support in Text Terminals".
|
|
|
172
186
|
.. _`Prepended_Concatenation_Mark`: https://www.unicode.org/reports/tr44/#Prepended_Concatenation_Mark
|
|
173
187
|
.. _`Default_Ignorable_Code_Point`: https://www.unicode.org/reports/tr44/#Default_Ignorable_Code_Point
|
|
174
188
|
.. _`General Category`: https://www.unicode.org/reports/tr44/#General_Category
|
|
189
|
+
.. _`General Category Values`: https://www.unicode.org/reports/tr44/#GC_Values_Table
|
|
175
190
|
.. _`Spacing Combining Mark`: https://www.unicode.org/versions/latest/core-spec/chapter-4/#G134153
|
|
176
191
|
.. _`Enclosing Mark`: https://www.unicode.org/versions/latest/core-spec/chapter-4/#G134153
|
|
177
192
|
.. _`Format`: https://www.unicode.org/versions/latest/core-spec/chapter-4/#G134153
|
|
178
193
|
.. _`Modifier Symbol`: https://www.unicode.org/versions/latest/core-spec/chapter-4/#G134153
|
|
179
194
|
.. _`Hangul Jamo`: https://www.unicode.org/charts/PDF/U1100.pdf
|
|
180
|
-
.. _`U+D7FF`: https://
|
|
195
|
+
.. _`U+D7FF`: https://www.unicode.org/charts/PDF/UD7B0.pdf
|
|
181
196
|
.. _`UnicodeData.txt`: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
|
|
182
197
|
.. _`East Asian`: https://www.unicode.org/reports/tr11/
|
|
183
198
|
.. _`Unicode Standard Annex #11`: https://www.unicode.org/reports/tr11/
|
|
@@ -187,18 +202,18 @@ See also: `L2/2023/23107`_ "Proper Complex Script Support in Text Terminals".
|
|
|
187
202
|
.. _`U+1F3FF`: https://codepoints.net/U+1F3FF
|
|
188
203
|
.. _`Regional Indicator`: https://www.unicode.org/charts/PDF/U1F100.pdf
|
|
189
204
|
.. _`Emoji Modifier`: https://unicode.org/reports/tr51/#Emoji_Modifiers
|
|
190
|
-
.. _`Extended_Pictographic`: https://www.unicode.org/
|
|
205
|
+
.. _`Extended_Pictographic`: https://www.unicode.org/Public/UCD/latest/ucd/emoji/emoji-data.txt
|
|
191
206
|
.. _`UTS #51`: https://www.unicode.org/reports/tr51/
|
|
192
207
|
.. _`Nonspacing Mark`: https://www.unicode.org/versions/latest/core-spec/chapter-4/#G134153
|
|
193
208
|
.. _`IndicSyllabicCategory.txt`: https://www.unicode.org/Public/UCD/latest/ucd/IndicSyllabicCategory.txt
|
|
194
|
-
.. _`Indic_Syllabic_Category`: https://www.unicode.org/reports/tr44/#Indic_Syllabic_Category
|
|
195
209
|
.. _`Invisible_Stacker`: https://www.unicode.org/Public/UCD/latest/ucd/IndicSyllabicCategory.txt
|
|
196
210
|
.. _`Brahmic scripts`: https://en.wikipedia.org/wiki/Brahmic_scripts
|
|
197
211
|
.. _`Virama`: https://www.unicode.org/glossary/#virama
|
|
198
212
|
.. _`conjunct`: https://www.unicode.org/glossary/#consonant_conjunct
|
|
199
213
|
.. _`aksara`: https://www.unicode.org/glossary/#aksara
|
|
200
|
-
.. _`L2/
|
|
214
|
+
.. _`L2/23-107`: https://www.unicode.org/L2/L2023/23107-terminal-suppt.pdf
|
|
215
|
+
.. _`L2/25-263`: https://www.unicode.org/L2/L2025/25263-ttwg-report-utc185.pdf
|
|
201
216
|
.. _`Unicode Standard Annex #29`: https://www.unicode.org/reports/tr29/
|
|
202
|
-
.. _`Unicode Standard Section 23.4`: https://www.unicode.org/versions/
|
|
203
|
-
.. _`
|
|
217
|
+
.. _`Unicode Standard Section 23.4`: https://www.unicode.org/versions/latest/core-spec/chapter-23/#G19053
|
|
218
|
+
.. _`unicodedata.iter_graphemes()`: https://docs.python.org/3.15/library/unicodedata.html#unicodedata.iter_graphemes
|
|
204
219
|
.. _`PR #224`: https://github.com/jquast/wcwidth/pull/224
|
|
@@ -48,6 +48,11 @@ extern const wcwidth_align_opts_t WCWIDTH_ALIGN_OPTS_DEFAULT;
|
|
|
48
48
|
* opts: alignment options, or NULL for defaults.
|
|
49
49
|
* out_len: output: byte length of result (excluding NUL); may be NULL.
|
|
50
50
|
* error: output: wcwidth_error_t, WCWIDTH_ERROR_NONE on success.
|
|
51
|
+
*
|
|
52
|
+
* Tabs are measured as though text begins at column 0. 'rjust' and 'center' operations insert
|
|
53
|
+
* padding to the left of the ``text`` which move tabstops and return an incorrect result, always
|
|
54
|
+
* expand tabs or clip to ``opts->dest_width``, which expands tabs before using those alignment
|
|
55
|
+
* functions.
|
|
51
56
|
*/
|
|
52
57
|
char *wcwidth_ljust_u8(const char *text, size_t text_len, wcwidth_control_mode_t mode,
|
|
53
58
|
const wcwidth_align_opts_t *opts, size_t *out_len, int *error);
|