wcwidth 0.9.2__tar.gz → 0.9.3__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.2 → wcwidth-0.9.3}/PKG-INFO +1 -1
- {wcwidth-0.9.2 → wcwidth-0.9.3}/docs/history.rst +13 -2
- {wcwidth-0.9.2 → wcwidth-0.9.3}/docs/libwcwidth.rst +8 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/Makefile +2 -2
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/include/wcwidth/utf8.h +17 -5
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/include/wcwidth/wcwidth_config.h +2 -2
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/src/align.c +13 -3
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/src/utf8.c +22 -9
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/tests/test_align.c +36 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/tests/test_utf8.c +90 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/pyproject.toml +1 -1
- {wcwidth-0.9.2 → wcwidth-0.9.3}/requirements-wheels.txt +6 -8
- {wcwidth-0.9.2 → wcwidth-0.9.3}/tests/test_hyperlink.py +6 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/tests/test_textwrap.py +11 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/__init__.py +1 -1
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/hyperlink.py +1 -1
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/textwrap.py +13 -17
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth.egg-info/PKG-INFO +1 -1
- {wcwidth-0.9.2 → wcwidth-0.9.3}/.gitignore +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/.pylintrc +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/LICENSE +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/MANIFEST.in +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/README.rst +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/bin/check-release.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/bin/update-docs.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/bin/update-tables.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/bin/verify-table-integrity.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/bin/wcwidth-browser.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/bin/wcwidth-libc-comparator.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/code_templates/api_c.rst.j2 +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/code_templates/c_gcb_class.c.j2 +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/code_templates/c_table.c.j2 +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/code_templates/c_term_programs.c.j2 +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/code_templates/c_terminal_overrides.c.j2 +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/code_templates/grapheme_override_per_terminal.py.j2 +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/code_templates/grapheme_override_table.py.j2 +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/code_templates/grapheme_registry.py.j2 +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/code_templates/grapheme_table.c.j2 +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/code_templates/grapheme_table.py.j2 +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/code_templates/python_table.py.j2 +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/code_templates/table_overrides.py.j2 +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/code_templates/tables.h.j2 +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/code_templates/term_programs.py.j2 +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/code_templates/unicode_version.rst.j2 +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/code_templates/unicode_versions.py.j2 +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/code_templates/wcwidth_config.h.j2 +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/docs/api.rst +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/docs/conf.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/docs/developing.rst +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/docs/index.rst +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/docs/intro.rst +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/docs/related.rst +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/docs/specs.rst +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/docs/unicode_version.rst +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/.clang-format +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/CMakeLists.txt +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/LICENSE +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/README.rst +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/cmake/libwcwidth-config.cmake.in +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/examples/align.c +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/examples/textwrap.c +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/examples/width.c +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/include/wcwidth/align.h +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/include/wcwidth/clip.h +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/include/wcwidth/escape.h +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/include/wcwidth/grapheme.h +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/include/wcwidth/sgr.h +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/include/wcwidth/table_types.h +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/include/wcwidth/tables.h +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/include/wcwidth/terminal_override.h +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/include/wcwidth/text_sizing.h +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/include/wcwidth/textwrap.h +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/include/wcwidth/unicode.h +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/include/wcwidth/wcwidth.h +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/include/wcwidth/width.h +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/src/bisearch.c +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/src/clip.c +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/src/escape.c +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/src/grapheme.c +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/src/sgr.c +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/src/tables/table_ambiguous.c +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/src/tables/table_gcb_class.c +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/src/tables/table_grapheme.c +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/src/tables/table_mc.c +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/src/tables/table_term_programs.c +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/src/tables/table_terminal_overrides.c +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/src/tables/table_vs15.c +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/src/tables/table_vs16.c +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/src/tables/table_wide.c +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/src/tables/table_zero.c +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/src/terminal_override.c +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/src/text_sizing.c +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/src/textwrap.c +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/src/wcstwidth.c +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/src/wcswidth.c +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/src/wcwidth.c +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/src/width.c +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/tests/test_clip.c +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/tests/test_common.h +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/tests/test_escape.c +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/tests/test_gcb_class.c +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/tests/test_grapheme.c +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/tests/test_sgr.c +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/tests/test_text_sizing.c +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/tests/test_textwrap.c +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/tests/test_wcswidth.c +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/tests/test_wcwidth.c +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/libwcwidth/tests/test_width.c +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/requirements-develop.txt +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/requirements-docs.in +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/requirements-tests39.in +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/requirements-tests39.txt +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/requirements-update.in +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/requirements-update.txt +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/requirements-wheels.in +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/setup.cfg +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/setup.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/tests/__init__.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/tests/conftest.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/tests/test_ambiguous.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/tests/test_benchmarks.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/tests/test_check_release.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/tests/test_clip.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/tests/test_clip_cjk_emoji.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/tests/test_clip_overtyping.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/tests/test_core.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/tests/test_emojis.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/tests/test_fastcall_args.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/tests/test_grapheme.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/tests/test_justify.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/tests/test_setup.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/tests/test_sgr_state.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/tests/test_term_overrides.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/tests/test_text_sizing.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/tests/test_ucslevel.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/tests/test_width.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/tox.ini +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/_clip.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/_constants.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/_wcswidth.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/_wcwidth.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/_wcwidth_c.c +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/_wcwidth_c.pyi +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/_width.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/align.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/bisearch.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/control_codes.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/escape_sequences.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/grapheme.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/py.typed +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/sgr_state.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/table_ambiguous.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/table_grapheme.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/table_grapheme_overrides/__init__.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/table_grapheme_overrides/_known_058c7585.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/table_grapheme_overrides/_known_2148ff29.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/table_grapheme_overrides/_known_244dc88b.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/table_grapheme_overrides/_known_336a71a1.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/table_grapheme_overrides/_known_33ac73f2.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/table_grapheme_overrides/_known_3a1895d5.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/table_grapheme_overrides/_known_59180a0d.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/table_grapheme_overrides/_known_65c6beb5.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/table_grapheme_overrides/_known_78f828e8.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/table_grapheme_overrides/_known_8c2ae14d.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/table_grapheme_overrides/_known_900356bf.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/table_grapheme_overrides/_known_97904ece.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/table_grapheme_overrides/_known_a5880eeb.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/table_grapheme_overrides/_known_b6d33cf4.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/table_grapheme_overrides/_known_c57c295b.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/table_grapheme_overrides/_known_cf02297d.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/table_grapheme_overrides/_known_e18ac6a7.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/table_grapheme_overrides/_known_e2b75ee3.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/table_grapheme_overrides/_known_fb5fd79b.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/table_grapheme_overrides/_known_fdc99132.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/table_grapheme_overrides/_registry.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/table_mc.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/table_overrides.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/table_term_programs.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/table_vs15.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/table_vs16.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/table_wide.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/table_zero.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/text_sizing.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/unicode_versions.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth/wcwidth.py +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth.egg-info/SOURCES.txt +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth.egg-info/dependency_links.txt +0 -0
- {wcwidth-0.9.2 → wcwidth-0.9.3}/wcwidth.egg-info/top_level.txt +0 -0
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
History
|
|
3
3
|
=======
|
|
4
4
|
|
|
5
|
+
0.9.3 *unreleased*
|
|
6
|
+
* **Bugfix** libwcwidth no longer has undefined behavior on NULL or empty input in the UTF-8 and
|
|
7
|
+
alignment functions, `PR #293`_, `PR #294`_.
|
|
8
|
+
* **Changed** `HyperlinkParams.parse()`_ now rejects trailing text, `PR #296`_.
|
|
9
|
+
* **Bugfix** `wrap()`_ should keep a link's own OSC 8 params across a line break, `PR #299`_.
|
|
10
|
+
|
|
5
11
|
0.9.2 *2026-10-04*
|
|
6
12
|
* **Bugfix** `wrap()`_ should omit an empty line as output, like `textwrap.wrap()`_ `PR #291`_.
|
|
7
13
|
* **Bugfix** `clip()`_ when using non-default argument, ``tabsize=0``, `PR #288`_.
|
|
@@ -11,7 +17,7 @@ History
|
|
|
11
17
|
|
|
12
18
|
0.9.1 *2026-09-23*
|
|
13
19
|
* **Bugfix** `width()`_ in Python and libwcwidth mis-measured CSI sequences over 64 bytes, a 0.9.0
|
|
14
|
-
release regression! `PR #
|
|
20
|
+
release regression! `PR #272`_.
|
|
15
21
|
* **Performance** improvement of ~15% for many Python API functions when using default arguments
|
|
16
22
|
like ``ambiguous_width`` and ``term_program``. `PR #273`_
|
|
17
23
|
|
|
@@ -312,12 +318,16 @@ https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c::
|
|
|
312
318
|
.. _`PR #253`: https://github.com/jquast/wcwidth/pull/253
|
|
313
319
|
.. _`PR #259`: https://github.com/jquast/wcwidth/pull/259
|
|
314
320
|
.. _`PR #262`: https://github.com/jquast/wcwidth/pull/262
|
|
315
|
-
.. _`PR #
|
|
321
|
+
.. _`PR #272`: https://github.com/jquast/wcwidth/pull/272
|
|
316
322
|
.. _`PR #273`: https://github.com/jquast/wcwidth/pull/273
|
|
317
323
|
.. _`PR #281`: https://github.com/jquast/wcwidth/pull/281
|
|
318
324
|
.. _`PR #284`: https://github.com/jquast/wcwidth/pull/284
|
|
319
325
|
.. _`PR #288`: https://github.com/jquast/wcwidth/pull/288
|
|
320
326
|
.. _`PR #291`: https://github.com/jquast/wcwidth/pull/291
|
|
327
|
+
.. _`PR #293`: https://github.com/jquast/wcwidth/pull/293
|
|
328
|
+
.. _`PR #294`: https://github.com/jquast/wcwidth/pull/294
|
|
329
|
+
.. _`PR #296`: https://github.com/jquast/wcwidth/pull/296
|
|
330
|
+
.. _`PR #299`: https://github.com/jquast/wcwidth/pull/299
|
|
321
331
|
.. _`Issue #101`: https://github.com/jquast/wcwidth/issues/101
|
|
322
332
|
.. _`Issue #155`: https://github.com/jquast/wcwidth/issues/155
|
|
323
333
|
.. _`Issue #211`: https://github.com/jquast/wcwidth/issues/211
|
|
@@ -343,6 +353,7 @@ https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c::
|
|
|
343
353
|
.. _`iter_sequences()`: https://wcwidth.readthedocs.io/en/latest/api.html#wcwidth.iter_sequences
|
|
344
354
|
.. _`list_versions()`: https://wcwidth.readthedocs.io/en/latest/api.html#wcwidth.list_versions
|
|
345
355
|
.. _`list_term_programs()`: https://wcwidth.readthedocs.io/en/latest/api.html#wcwidth.list_term_programs
|
|
356
|
+
.. _`HyperlinkParams.parse()`: https://wcwidth.readthedocs.io/en/latest/api.html#wcwidth.HyperlinkParams
|
|
346
357
|
.. _`parity padding`: https://jazcap53.github.io/pythons-eccentric-strcenter.html
|
|
347
358
|
.. _`kitty text sizing protocol`: https://sw.kovidgoyal.net/kitty/text-sizing-protocol/
|
|
348
359
|
.. _Corrections: https://wcwidth.readthedocs.io/en/latest/intro.html#corrections
|
|
@@ -147,6 +147,14 @@ Every string function reads exactly the length you pass:
|
|
|
147
147
|
Pass ``strlen(text)`` when the text is a C string. A NUL counts as an ordinary zero-width character
|
|
148
148
|
in any position. Transform functions copy it through and report the full length in ``*out_len``.
|
|
149
149
|
|
|
150
|
+
Pointer contract
|
|
151
|
+
~~~~~~~~~~~~~~~~
|
|
152
|
+
|
|
153
|
+
Input pointers and the ``count`` / ``out_len`` out-length pointers must not be NULL.
|
|
154
|
+
|
|
155
|
+
``stack`` accepts NULL to select the heap path. ``wcwidth_utf8_decode_single()`` accepts
|
|
156
|
+
NULL as ``cp_out``, reporting the length of the next character.
|
|
157
|
+
|
|
150
158
|
Alternate encodings
|
|
151
159
|
~~~~~~~~~~~~~~~~~~~
|
|
152
160
|
|
|
@@ -13,8 +13,8 @@ CFLAGS ?= -std=c11 -Wall -Wextra -O2 -g
|
|
|
13
13
|
INCLUDE = -Iinclude
|
|
14
14
|
BUILD = build
|
|
15
15
|
|
|
16
|
-
ASAN_CFLAGS = -std=c11 -Wall -Wextra -O1 -g -fsanitize=address,undefined -fno-omit-frame-pointer
|
|
17
|
-
UBSAN_CFLAGS = -std=c11 -Wall -Wextra -O2 -g -fsanitize=undefined -fno-omit-frame-pointer
|
|
16
|
+
ASAN_CFLAGS = -std=c11 -Wall -Wextra -O1 -g -fsanitize=address,undefined -fno-sanitize-recover=all -fno-omit-frame-pointer
|
|
17
|
+
UBSAN_CFLAGS = -std=c11 -Wall -Wextra -O2 -g -fsanitize=undefined -fno-sanitize-recover=all -fno-omit-frame-pointer
|
|
18
18
|
|
|
19
19
|
LIB_SRCS = $(wildcard src/*.c) $(wildcard src/tables/*.c)
|
|
20
20
|
LIB_OBJS = $(patsubst %.c,$(BUILD)/%.o,$(LIB_SRCS))
|
|
@@ -17,6 +17,9 @@ extern "C" {
|
|
|
17
17
|
* U+FFFD and the return value is the number of bytes to skip (1 for a bad
|
|
18
18
|
* leading byte, the remaining length for a truncated sequence, or 0 when
|
|
19
19
|
* *len* is 0).
|
|
20
|
+
*
|
|
21
|
+
* *s* must not be NULL. *cp_out* may be NULL to consume the sequence and
|
|
22
|
+
* query the length of the next character.
|
|
20
23
|
*/
|
|
21
24
|
size_t wcwidth_utf8_decode_single(const char *s, size_t len, uint32_t *cp_out);
|
|
22
25
|
|
|
@@ -28,6 +31,11 @@ size_t wcwidth_utf8_decode_single(const char *s, size_t len, uint32_t *cp_out);
|
|
|
28
31
|
* is undefined behavior. Sets *count* and returns NULL on allocation
|
|
29
32
|
* failure.
|
|
30
33
|
*
|
|
34
|
+
* *utf8* and *count* must not be NULL; *count* is required because the
|
|
35
|
+
* returned array carries no terminator. A *stack* of NULL forces the heap
|
|
36
|
+
* path. When *n* is 0 and *stack* is NULL, the result is a freeable array
|
|
37
|
+
* with *count* set to 0.
|
|
38
|
+
*
|
|
31
39
|
* The result type allows a plain free() release, matching wcwidth_encode_u32()
|
|
32
40
|
* below. Treat the contents as read-only.
|
|
33
41
|
*
|
|
@@ -39,7 +47,8 @@ uint32_t *wcwidth_decode_u32(const char *utf8, size_t n, uint32_t *stack, size_t
|
|
|
39
47
|
|
|
40
48
|
/*
|
|
41
49
|
* Decode *utf8* into a malloc'd codepoint array (one free()). Returns the
|
|
42
|
-
* array and sets *count*, or NULL on allocation failure.
|
|
50
|
+
* array and sets *count*, or NULL on allocation failure. An *n* of 0 returns
|
|
51
|
+
* a freeable array with *count* set to 0.
|
|
43
52
|
*
|
|
44
53
|
* Follows the length and NUL semantics of wcwidth_decode_u32().
|
|
45
54
|
*/
|
|
@@ -51,12 +60,15 @@ uint32_t *wcwidth_decode_u32_heap(const char *utf8, size_t n, size_t *count);
|
|
|
51
60
|
* in *stack* (no allocation), otherwise a heap buffer is allocated. The
|
|
52
61
|
* caller must free() the result only when it is not *stack*; freeing *stack*
|
|
53
62
|
* is undefined behavior. Sets *out_len* and returns NULL on allocation
|
|
54
|
-
* failure.
|
|
63
|
+
* failure. An *n* of 0 returns a freeable buffer with *out_len* set to 0.
|
|
64
|
+
*
|
|
65
|
+
* *codepoints* and *out_len* must not be NULL; *out_len* is required because
|
|
66
|
+
* the returned bytes carry no terminator. A *stack* of NULL forces the heap
|
|
67
|
+
* path.
|
|
55
68
|
*
|
|
56
69
|
* Encoding writes exactly *n* codepoints: a U+0000 becomes a NUL byte, so the
|
|
57
|
-
* output can contain embedded NUL bytes.
|
|
58
|
-
*
|
|
59
|
-
* as U+FFFD.
|
|
70
|
+
* output can contain embedded NUL bytes. Invalid codepoints (lone surrogates
|
|
71
|
+
* and values above U+10FFFF) are encoded as U+FFFD.
|
|
60
72
|
*/
|
|
61
73
|
char *wcwidth_encode_u32(const uint32_t *codepoints, size_t n, char *stack, size_t stack_cap,
|
|
62
74
|
size_t *out_len);
|
|
@@ -18,8 +18,8 @@ extern "C" {
|
|
|
18
18
|
|
|
19
19
|
#define WCWIDTH_VERSION_MAJOR 0
|
|
20
20
|
#define WCWIDTH_VERSION_MINOR 9
|
|
21
|
-
#define WCWIDTH_VERSION_PATCH
|
|
22
|
-
#define WCWIDTH_VERSION "0.9.
|
|
21
|
+
#define WCWIDTH_VERSION_PATCH 3
|
|
22
|
+
#define WCWIDTH_VERSION "0.9.3"
|
|
23
23
|
|
|
24
24
|
/* Unicode version the library tables were generated from. */
|
|
25
25
|
#define WCWIDTH_UNICODE_VERSION "18.0.0"
|
|
@@ -87,6 +87,10 @@ fill_repeat(char *dst, const char *fillchar, size_t fillchar_len, size_t count)
|
|
|
87
87
|
{
|
|
88
88
|
size_t i;
|
|
89
89
|
|
|
90
|
+
if (fillchar_len == 0) {
|
|
91
|
+
return dst;
|
|
92
|
+
}
|
|
93
|
+
|
|
90
94
|
for (i = 0; i < count; i++) {
|
|
91
95
|
memcpy(dst, fillchar, fillchar_len);
|
|
92
96
|
dst += fillchar_len;
|
|
@@ -133,7 +137,9 @@ ljust_impl(const char *text, size_t text_len, size_t dest_width, const char *fil
|
|
|
133
137
|
return NULL;
|
|
134
138
|
}
|
|
135
139
|
|
|
136
|
-
|
|
140
|
+
if (text_len > 0) {
|
|
141
|
+
memcpy(result, text, text_len);
|
|
142
|
+
}
|
|
137
143
|
fill_repeat(result + text_len, fillchar, fillchar_len, padding);
|
|
138
144
|
result[total] = '\0';
|
|
139
145
|
|
|
@@ -184,7 +190,9 @@ rjust_impl(const char *text, size_t text_len, size_t dest_width, const char *fil
|
|
|
184
190
|
|
|
185
191
|
fill_repeat(result, fillchar, fillchar_len, padding);
|
|
186
192
|
/* add_fill_bytes() above already proved this product cannot wrap. */
|
|
187
|
-
|
|
193
|
+
if (text_len > 0) {
|
|
194
|
+
memcpy(result + padding * fillchar_len, text, text_len);
|
|
195
|
+
}
|
|
188
196
|
result[total] = '\0';
|
|
189
197
|
|
|
190
198
|
if (out_len != NULL) {
|
|
@@ -246,7 +254,9 @@ center_impl(const char *text, size_t text_len, size_t dest_width, const char *fi
|
|
|
246
254
|
|
|
247
255
|
{
|
|
248
256
|
char *dst = fill_repeat(result, fillchar, fillchar_len, left_pad);
|
|
249
|
-
|
|
257
|
+
if (text_len > 0) {
|
|
258
|
+
memcpy(dst, text, text_len);
|
|
259
|
+
}
|
|
250
260
|
fill_repeat(dst + text_len, fillchar, fillchar_len, right_pad);
|
|
251
261
|
}
|
|
252
262
|
result[total] = '\0';
|
|
@@ -16,6 +16,10 @@ wcwidth_utf8_decode_single(const char *s, size_t len, uint32_t *cp_out)
|
|
|
16
16
|
size_t expected;
|
|
17
17
|
size_t i;
|
|
18
18
|
|
|
19
|
+
if (cp_out == NULL) {
|
|
20
|
+
cp_out = &cp;
|
|
21
|
+
}
|
|
22
|
+
|
|
19
23
|
if (len == 0) {
|
|
20
24
|
*cp_out = 0xFFFD;
|
|
21
25
|
return 0;
|
|
@@ -97,7 +101,7 @@ wcwidth_decode_u32(const char *utf8, size_t n, uint32_t *stack, size_t stack_cap
|
|
|
97
101
|
{
|
|
98
102
|
uint32_t *heap = NULL;
|
|
99
103
|
uint32_t *out = stack;
|
|
100
|
-
size_t cap = stack_cap;
|
|
104
|
+
size_t cap = (stack != NULL) ? stack_cap : 0;
|
|
101
105
|
size_t used = 0;
|
|
102
106
|
size_t pos = 0;
|
|
103
107
|
|
|
@@ -142,17 +146,18 @@ wcwidth_decode_u32(const char *utf8, size_t n, uint32_t *stack, size_t stack_cap
|
|
|
142
146
|
pos += consumed;
|
|
143
147
|
}
|
|
144
148
|
|
|
149
|
+
if (n == 0 && stack == NULL) {
|
|
150
|
+
*count = 0;
|
|
151
|
+
return (uint32_t *) calloc(1, sizeof(uint32_t)); /* freeable empty result */
|
|
152
|
+
}
|
|
153
|
+
|
|
145
154
|
*count = used;
|
|
146
|
-
return
|
|
155
|
+
return out;
|
|
147
156
|
}
|
|
148
157
|
|
|
149
158
|
uint32_t *
|
|
150
159
|
wcwidth_decode_u32_heap(const char *utf8, size_t n, size_t *count)
|
|
151
160
|
{
|
|
152
|
-
if (n == 0) {
|
|
153
|
-
*count = 0;
|
|
154
|
-
return (uint32_t *) malloc(sizeof(uint32_t)); /* freeable empty result */
|
|
155
|
-
}
|
|
156
161
|
return wcwidth_decode_u32(utf8, n, NULL, 0, count);
|
|
157
162
|
}
|
|
158
163
|
|
|
@@ -195,7 +200,7 @@ wcwidth_encode_u32(const uint32_t *codepoints, size_t n, char *stack, size_t sta
|
|
|
195
200
|
{
|
|
196
201
|
char *heap = NULL;
|
|
197
202
|
char *out = stack;
|
|
198
|
-
size_t cap = stack_cap;
|
|
203
|
+
size_t cap = (stack != NULL) ? stack_cap : 0;
|
|
199
204
|
size_t used = 0;
|
|
200
205
|
size_t i;
|
|
201
206
|
|
|
@@ -216,7 +221,10 @@ wcwidth_encode_u32(const uint32_t *codepoints, size_t n, char *stack, size_t sta
|
|
|
216
221
|
*out_len = 0;
|
|
217
222
|
return NULL;
|
|
218
223
|
}
|
|
219
|
-
|
|
224
|
+
if (used > 0) {
|
|
225
|
+
/* stack may be NULL when stack_cap is 0 */
|
|
226
|
+
memcpy(nd, stack, used);
|
|
227
|
+
}
|
|
220
228
|
}
|
|
221
229
|
else {
|
|
222
230
|
nd = (char *) realloc(heap, new_cap);
|
|
@@ -234,6 +242,11 @@ wcwidth_encode_u32(const uint32_t *codepoints, size_t n, char *stack, size_t sta
|
|
|
234
242
|
used += enc_len;
|
|
235
243
|
}
|
|
236
244
|
|
|
245
|
+
if (n == 0 && stack == NULL) {
|
|
246
|
+
*out_len = 0;
|
|
247
|
+
return (char *) calloc(1, 1); /* freeable empty result */
|
|
248
|
+
}
|
|
249
|
+
|
|
237
250
|
*out_len = used;
|
|
238
|
-
return
|
|
251
|
+
return out;
|
|
239
252
|
}
|
|
@@ -262,6 +262,41 @@ TEST(null_opts_defaults)
|
|
|
262
262
|
free(u);
|
|
263
263
|
}
|
|
264
264
|
|
|
265
|
+
TEST(align_null_and_empty_input)
|
|
266
|
+
{
|
|
267
|
+
wcwidth_align_opts_t opts = WCWIDTH_ALIGN_OPTS_DEFAULT;
|
|
268
|
+
size_t len = 1;
|
|
269
|
+
int error = WCWIDTH_ERROR_NONE;
|
|
270
|
+
char *s;
|
|
271
|
+
|
|
272
|
+
s = wcwidth_ljust_u8(NULL, 0, WCWIDTH_PARSE, &opts, &len, &error);
|
|
273
|
+
ASSERT_NOT_NULL(s);
|
|
274
|
+
ASSERT_EQ(0, len);
|
|
275
|
+
ASSERT_STREQ("", s);
|
|
276
|
+
free(s);
|
|
277
|
+
|
|
278
|
+
s = wcwidth_rjust_u8(NULL, 0, WCWIDTH_PARSE, &opts, &len, &error);
|
|
279
|
+
ASSERT_NOT_NULL(s);
|
|
280
|
+
ASSERT_EQ(0, len);
|
|
281
|
+
ASSERT_STREQ("", s);
|
|
282
|
+
free(s);
|
|
283
|
+
|
|
284
|
+
s = wcwidth_center_u8(NULL, 0, WCWIDTH_PARSE, &opts, &len, &error);
|
|
285
|
+
ASSERT_NOT_NULL(s);
|
|
286
|
+
ASSERT_EQ(0, len);
|
|
287
|
+
ASSERT_STREQ("", s);
|
|
288
|
+
free(s);
|
|
289
|
+
|
|
290
|
+
opts.dest_width = 5;
|
|
291
|
+
opts.fillchar = NULL;
|
|
292
|
+
opts.fillchar_len = 0;
|
|
293
|
+
s = wcwidth_ljust_u8("x", 1, WCWIDTH_PARSE, &opts, &len, &error);
|
|
294
|
+
ASSERT_NOT_NULL(s);
|
|
295
|
+
ASSERT_EQ(1, len);
|
|
296
|
+
ASSERT_STREQ("x", s);
|
|
297
|
+
free(s);
|
|
298
|
+
}
|
|
299
|
+
|
|
265
300
|
int
|
|
266
301
|
main(void)
|
|
267
302
|
{
|
|
@@ -276,5 +311,6 @@ main(void)
|
|
|
276
311
|
RUN_TEST(center_huge_dest_width);
|
|
277
312
|
RUN_TEST(align_control_codes_strict);
|
|
278
313
|
RUN_TEST(null_opts_defaults);
|
|
314
|
+
RUN_TEST(align_null_and_empty_input);
|
|
279
315
|
return test_summary();
|
|
280
316
|
}
|
|
@@ -74,6 +74,89 @@ TEST(decode_u32_heap_empty)
|
|
|
74
74
|
|
|
75
75
|
ASSERT_NOT_NULL(out);
|
|
76
76
|
ASSERT_EQ((int64_t) 0, (int64_t) count);
|
|
77
|
+
ASSERT_EQ((int64_t) 0, (int64_t) out[0]);
|
|
78
|
+
free(out);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
TEST(decode_single_null_out)
|
|
82
|
+
{
|
|
83
|
+
ASSERT_EQ((int64_t) 3, (int64_t) wcwidth_utf8_decode_single("\xe4\xb8\xad", 3, NULL));
|
|
84
|
+
ASSERT_EQ((int64_t) 1, (int64_t) wcwidth_utf8_decode_single("abc", 3, NULL));
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
TEST(decode_u32_null_stack)
|
|
88
|
+
{
|
|
89
|
+
uint32_t *out;
|
|
90
|
+
size_t count = 0;
|
|
91
|
+
|
|
92
|
+
out = wcwidth_decode_u32("a", 1, NULL, 8, &count);
|
|
93
|
+
ASSERT_NOT_NULL(out);
|
|
94
|
+
ASSERT_EQ((int64_t) 1, (int64_t) count);
|
|
95
|
+
ASSERT_EQ((int64_t) 'a', (int64_t) out[0]);
|
|
96
|
+
free(out);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
TEST(encode_u32_empty_heap)
|
|
100
|
+
{
|
|
101
|
+
const uint32_t cps[] = {0};
|
|
102
|
+
char *out;
|
|
103
|
+
size_t len = 1;
|
|
104
|
+
|
|
105
|
+
out = wcwidth_encode_u32(cps, 0, NULL, 0, &len);
|
|
106
|
+
ASSERT_NOT_NULL(out);
|
|
107
|
+
ASSERT_EQ((int64_t) 0, (int64_t) len);
|
|
108
|
+
ASSERT_EQ((int64_t) 0, (int64_t) out[0]);
|
|
109
|
+
free(out);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
TEST(encode_u32_null_stack)
|
|
113
|
+
{
|
|
114
|
+
const uint32_t cps[] = {'a', 'b'};
|
|
115
|
+
char *out;
|
|
116
|
+
size_t len = 0;
|
|
117
|
+
|
|
118
|
+
out = wcwidth_encode_u32(cps, 2, NULL, 8, &len);
|
|
119
|
+
ASSERT_NOT_NULL(out);
|
|
120
|
+
ASSERT_EQ((int64_t) 2, (int64_t) len);
|
|
121
|
+
ASSERT_EQ(0, memcmp(out, "ab", 2));
|
|
122
|
+
free(out);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
TEST(decode_u32_empty_stack)
|
|
126
|
+
{
|
|
127
|
+
uint32_t stack[4];
|
|
128
|
+
uint32_t *out;
|
|
129
|
+
size_t count = 1;
|
|
130
|
+
|
|
131
|
+
out = wcwidth_decode_u32("", 0, stack, 4, &count);
|
|
132
|
+
ASSERT_TRUE(out == stack);
|
|
133
|
+
ASSERT_EQ((int64_t) 0, (int64_t) count);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
TEST(encode_u32_empty_stack)
|
|
137
|
+
{
|
|
138
|
+
const uint32_t cps[] = {0};
|
|
139
|
+
char stack[8];
|
|
140
|
+
char *out;
|
|
141
|
+
size_t len = 1;
|
|
142
|
+
|
|
143
|
+
out = wcwidth_encode_u32(cps, 0, stack, 8, &len);
|
|
144
|
+
ASSERT_TRUE(out == stack);
|
|
145
|
+
ASSERT_EQ((int64_t) 0, (int64_t) len);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
TEST(decode_u32_stack_overflow)
|
|
149
|
+
{
|
|
150
|
+
uint32_t stack[2];
|
|
151
|
+
uint32_t *out;
|
|
152
|
+
size_t count = 0;
|
|
153
|
+
|
|
154
|
+
out = wcwidth_decode_u32("abcdef", 6, stack, 2, &count);
|
|
155
|
+
ASSERT_NOT_NULL(out);
|
|
156
|
+
ASSERT_TRUE(out != stack);
|
|
157
|
+
ASSERT_EQ((int64_t) 6, (int64_t) count);
|
|
158
|
+
ASSERT_EQ((int64_t) 'a', (int64_t) out[0]);
|
|
159
|
+
ASSERT_EQ((int64_t) 'f', (int64_t) out[5]);
|
|
77
160
|
free(out);
|
|
78
161
|
}
|
|
79
162
|
|
|
@@ -83,5 +166,12 @@ main(void)
|
|
|
83
166
|
RUN_TEST(encode_roundtrip);
|
|
84
167
|
RUN_TEST(decode_malformed);
|
|
85
168
|
RUN_TEST(decode_u32_heap_empty);
|
|
169
|
+
RUN_TEST(decode_single_null_out);
|
|
170
|
+
RUN_TEST(decode_u32_null_stack);
|
|
171
|
+
RUN_TEST(encode_u32_empty_heap);
|
|
172
|
+
RUN_TEST(encode_u32_null_stack);
|
|
173
|
+
RUN_TEST(decode_u32_empty_stack);
|
|
174
|
+
RUN_TEST(encode_u32_empty_stack);
|
|
175
|
+
RUN_TEST(decode_u32_stack_overflow);
|
|
86
176
|
return test_summary();
|
|
87
177
|
}
|
|
@@ -7,7 +7,7 @@ requires = [ "setuptools>=61" ]
|
|
|
7
7
|
|
|
8
8
|
[project]
|
|
9
9
|
name = "wcwidth"
|
|
10
|
-
version = "0.9.
|
|
10
|
+
version = "0.9.3" # stamped into __init__.py and wcwidth_config.h by bin/update-tables.py
|
|
11
11
|
description = "Measures the displayed width of unicode strings in a terminal"
|
|
12
12
|
readme = "README.rst"
|
|
13
13
|
keywords = [
|
|
@@ -2,23 +2,21 @@
|
|
|
2
2
|
# This file is autogenerated by pip-compile with Python 3.14
|
|
3
3
|
# by the following command:
|
|
4
4
|
#
|
|
5
|
-
# pip-compile --allow-unsafe --no-emit-index-url --
|
|
5
|
+
# pip-compile --allow-unsafe --no-emit-index-url --output-file=requirements-wheels.txt --strip-extras requirements-wheels.in
|
|
6
6
|
#
|
|
7
|
-
--trusted-host localhost
|
|
8
|
-
|
|
9
7
|
bashlex==0.18
|
|
10
8
|
# via cibuildwheel
|
|
11
|
-
bracex==3.
|
|
9
|
+
bracex==3.1
|
|
12
10
|
# via cibuildwheel
|
|
13
11
|
build==1.6.1
|
|
14
12
|
# via cibuildwheel
|
|
15
|
-
certifi==2026.
|
|
13
|
+
certifi==2026.10.19
|
|
16
14
|
# via cibuildwheel
|
|
17
|
-
cibuildwheel==4.
|
|
15
|
+
cibuildwheel==4.3.1
|
|
18
16
|
# via -r requirements-wheels.in
|
|
19
17
|
dependency-groups==1.3.2
|
|
20
18
|
# via cibuildwheel
|
|
21
|
-
filelock==4.
|
|
19
|
+
filelock==4.2.4
|
|
22
20
|
# via cibuildwheel
|
|
23
21
|
humanize==4.16.0
|
|
24
22
|
# via cibuildwheel
|
|
@@ -27,7 +25,7 @@ packaging==26.3
|
|
|
27
25
|
# build
|
|
28
26
|
# cibuildwheel
|
|
29
27
|
# dependency-groups
|
|
30
|
-
platformdirs==4.
|
|
28
|
+
platformdirs==4.13.5
|
|
31
29
|
# via cibuildwheel
|
|
32
30
|
pyproject-hooks==1.3.3
|
|
33
31
|
# via build
|
|
@@ -26,6 +26,12 @@ def test_hyperlinkparams_parse_valid(seq, url, params, term):
|
|
|
26
26
|
'not an escape',
|
|
27
27
|
'\x1b[31m',
|
|
28
28
|
'',
|
|
29
|
+
'\x1b]8;;https://example.com\x07text',
|
|
30
|
+
'\x1b]8;;https://example.com\x07\n',
|
|
31
|
+
'\x1b]8;;https://example.com\x07\x1b[31m',
|
|
32
|
+
'\x1b]8;;https://example.com\x1b\\text',
|
|
33
|
+
'\x1b]8;;https://example.com\x1b\\\n',
|
|
34
|
+
'\x1b]8;;https://example.com\x1b\\\x1b[31m',
|
|
29
35
|
])
|
|
30
36
|
def test_hyperlinkparams_parse_invalid(seq):
|
|
31
37
|
"""Parse an invalid/non-OSC-8 sequence returns None."""
|
|
@@ -486,6 +486,17 @@ OSC_END_BEL = '\x1b]8;;\x07'
|
|
|
486
486
|
'\x1b]8;id=00000002;http://example.com\x07gh\x1b]8;;\x07',
|
|
487
487
|
],
|
|
488
488
|
),
|
|
489
|
+
( # a link opened after a preceding link
|
|
490
|
+
'\x1b]8;id=first;https://a\x07aa bb\x1b]8;;\x07 '
|
|
491
|
+
'\x1b]8;id=second;https://b\x07cc dd ee\x1b]8;;\x07',
|
|
492
|
+
5,
|
|
493
|
+
[
|
|
494
|
+
'\x1b]8;id=first;https://a\x07aa bb\x1b]8;;\x07',
|
|
495
|
+
('\x1b]8;id=first;https://a\x07\x1b]8;;\x07' +
|
|
496
|
+
'\x1b]8;id=second;https://b\x07cc dd\x1b]8;;\x07'),
|
|
497
|
+
'\x1b]8;id=second;https://b\x07ee\x1b]8;;\x07',
|
|
498
|
+
],
|
|
499
|
+
),
|
|
489
500
|
( # long word inside hyperlink forces character-level breaking
|
|
490
501
|
f'{OSC_START_ST}abcdefgh{OSC_END_ST}',
|
|
491
502
|
3,
|
|
@@ -98,4 +98,4 @@ __all__ = ('wcwidth', 'wcswidth', 'wcstwidth', 'width', 'iter_sequences', 'iter_
|
|
|
98
98
|
'Hyperlink', 'HyperlinkParams', 'TextSizing', 'TextSizingParams')
|
|
99
99
|
|
|
100
100
|
# Version is stamped by code generation (bin/update-tables.py) from pyproject.toml.
|
|
101
|
-
__version__ = '0.9.
|
|
101
|
+
__version__ = '0.9.3'
|
|
@@ -44,7 +44,7 @@ class HyperlinkParams(typing.NamedTuple):
|
|
|
44
44
|
>>> HyperlinkParams.parse('\x1b]8;;http://example.com\x07')
|
|
45
45
|
HyperlinkParams(url='http://example.com', params='', terminator='\x07')
|
|
46
46
|
"""
|
|
47
|
-
m = HYPERLINK_OPEN_RE.
|
|
47
|
+
m = HYPERLINK_OPEN_RE.fullmatch(seq)
|
|
48
48
|
if m is None:
|
|
49
49
|
return None
|
|
50
50
|
return cls(url=m.group(2), params=m.group(1), terminator=m.group(3))
|
|
@@ -224,8 +224,6 @@ class SequenceTextWrapper(textwrap.TextWrapper):
|
|
|
224
224
|
is_first_line = True
|
|
225
225
|
|
|
226
226
|
hyperlink_state: Optional[HyperlinkParams] = None
|
|
227
|
-
# Track the id we're using for the current hyperlink continuation
|
|
228
|
-
current_hyperlink_id: Optional[str] = None
|
|
229
227
|
|
|
230
228
|
# Arrange in reverse order so items can be efficiently popped
|
|
231
229
|
chunks = list(reversed(chunks))
|
|
@@ -312,17 +310,16 @@ class SequenceTextWrapper(textwrap.TextWrapper):
|
|
|
312
310
|
|
|
313
311
|
# If we end inside a hyperlink, append close sequence
|
|
314
312
|
if new_state is not None:
|
|
315
|
-
#
|
|
316
|
-
if
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
current_hyperlink_id = f'id={self._next_hyperlink_id()}'
|
|
313
|
+
# Use the active link's params; wrapper state can leak a prior link's id.
|
|
314
|
+
if 'id=' in new_state.params:
|
|
315
|
+
continuation_params = new_state.params
|
|
316
|
+
elif new_state.params:
|
|
317
|
+
# Prepend id to existing params. Per OSC 8 spec, params can have
|
|
318
|
+
# multiple key=value pairs separated by ':'.
|
|
319
|
+
continuation_params = (
|
|
320
|
+
f'id={self._next_hyperlink_id()}:{new_state.params}')
|
|
321
|
+
else:
|
|
322
|
+
continuation_params = f'id={self._next_hyperlink_id()}'
|
|
326
323
|
line_content += HyperlinkParams(
|
|
327
324
|
terminator=new_state.terminator, url='').make_close()
|
|
328
325
|
|
|
@@ -337,17 +334,16 @@ class SequenceTextWrapper(textwrap.TextWrapper):
|
|
|
337
334
|
).make_open()
|
|
338
335
|
new_open = HyperlinkParams(
|
|
339
336
|
url=new_state.url,
|
|
340
|
-
params=
|
|
337
|
+
params=continuation_params,
|
|
341
338
|
terminator=new_state.terminator,
|
|
342
339
|
).make_open()
|
|
343
340
|
line_content = line_content.replace(old_open, new_open, 1)
|
|
344
341
|
|
|
345
|
-
# Update state for next line, using computed
|
|
342
|
+
# Update state for next line, using computed params
|
|
346
343
|
hyperlink_state = HyperlinkParams(
|
|
347
|
-
new_state.url,
|
|
344
|
+
new_state.url, continuation_params, new_state.terminator)
|
|
348
345
|
else:
|
|
349
346
|
hyperlink_state = None
|
|
350
|
-
current_hyperlink_id = None # Reset id when hyperlink closes
|
|
351
347
|
|
|
352
348
|
# Strip trailing whitespace when drop_whitespace is enabled
|
|
353
349
|
# (matches CPython #140627 fix behavior)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|