wcwidth 0.9.0__tar.gz → 0.9.1__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.1}/.gitignore +4 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/PKG-INFO +1 -1
- {wcwidth-0.9.0 → wcwidth-0.9.1}/bin/update-docs.py +38 -15
- {wcwidth-0.9.0 → wcwidth-0.9.1}/docs/developing.rst +6 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/docs/history.rst +9 -1
- {wcwidth-0.9.0 → wcwidth-0.9.1}/docs/libwcwidth.rst +28 -8
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/include/wcwidth/wcwidth_config.h +2 -2
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/src/width.c +42 -16
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/tests/test_align.c +29 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/tests/test_clip.c +38 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/tests/test_sgr.c +50 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/tests/test_text_sizing.c +13 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/tests/test_textwrap.c +50 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/tests/test_utf8.c +18 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/tests/test_wcswidth.c +7 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/tests/test_width.c +69 -1
- {wcwidth-0.9.0 → wcwidth-0.9.1}/pyproject.toml +1 -1
- {wcwidth-0.9.0 → wcwidth-0.9.1}/tests/test_benchmarks.py +10 -0
- wcwidth-0.9.1/tests/test_fastcall_args.py +118 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/tests/test_term_overrides.py +6 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/tests/test_width.py +5 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/tox.ini +50 -2
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/__init__.py +1 -1
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/_wcwidth_c.c +724 -107
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth.egg-info/PKG-INFO +1 -1
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth.egg-info/SOURCES.txt +1 -1
- wcwidth-0.9.0/docs/api_c.rst +0 -1042
- {wcwidth-0.9.0 → wcwidth-0.9.1}/.pylintrc +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/LICENSE +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/MANIFEST.in +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/README.rst +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/bin/check-release.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/bin/update-tables.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/bin/verify-table-integrity.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/bin/wcwidth-browser.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/bin/wcwidth-libc-comparator.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/code_templates/api_c.rst.j2 +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/code_templates/c_gcb_class.c.j2 +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/code_templates/c_table.c.j2 +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/code_templates/c_term_programs.c.j2 +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/code_templates/c_terminal_overrides.c.j2 +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/code_templates/grapheme_override_per_terminal.py.j2 +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/code_templates/grapheme_override_table.py.j2 +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/code_templates/grapheme_registry.py.j2 +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/code_templates/grapheme_table.c.j2 +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/code_templates/grapheme_table.py.j2 +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/code_templates/python_table.py.j2 +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/code_templates/table_overrides.py.j2 +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/code_templates/tables.h.j2 +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/code_templates/term_programs.py.j2 +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/code_templates/unicode_version.rst.j2 +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/code_templates/unicode_versions.py.j2 +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/code_templates/wcwidth_config.h.j2 +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/docs/api.rst +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/docs/conf.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/docs/index.rst +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/docs/intro.rst +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/docs/related.rst +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/docs/specs.rst +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/docs/unicode_version.rst +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/.clang-format +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/CMakeLists.txt +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/LICENSE +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/Makefile +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/README.rst +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/cmake/libwcwidth-config.cmake.in +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/examples/align.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/examples/textwrap.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/examples/width.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/include/wcwidth/align.h +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/include/wcwidth/clip.h +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/include/wcwidth/escape.h +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/include/wcwidth/grapheme.h +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/include/wcwidth/sgr.h +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/include/wcwidth/table_types.h +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/include/wcwidth/tables.h +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/include/wcwidth/terminal_override.h +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/include/wcwidth/text_sizing.h +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/include/wcwidth/textwrap.h +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/include/wcwidth/unicode.h +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/include/wcwidth/utf8.h +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/include/wcwidth/wcwidth.h +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/include/wcwidth/width.h +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/src/align.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/src/bisearch.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/src/clip.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/src/escape.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/src/grapheme.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/src/sgr.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/src/tables/table_ambiguous.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/src/tables/table_gcb_class.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/src/tables/table_grapheme.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/src/tables/table_mc.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/src/tables/table_term_programs.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/src/tables/table_terminal_overrides.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/src/tables/table_vs15.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/src/tables/table_vs16.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/src/tables/table_wide.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/src/tables/table_zero.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/src/terminal_override.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/src/text_sizing.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/src/textwrap.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/src/utf8.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/src/wcstwidth.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/src/wcswidth.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/src/wcwidth.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/tests/test_common.h +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/tests/test_escape.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/tests/test_gcb_class.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/tests/test_grapheme.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/libwcwidth/tests/test_wcwidth.c +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/requirements-develop.txt +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/requirements-docs.in +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/requirements-tests39.in +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/requirements-tests39.txt +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/requirements-update.in +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/requirements-update.txt +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/requirements-wheels.in +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/requirements-wheels.txt +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/setup.cfg +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/setup.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/tests/__init__.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/tests/conftest.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/tests/test_ambiguous.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/tests/test_check_release.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/tests/test_clip.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/tests/test_clip_cjk_emoji.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/tests/test_clip_overtyping.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/tests/test_core.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/tests/test_emojis.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/tests/test_grapheme.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/tests/test_hyperlink.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/tests/test_justify.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/tests/test_setup.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/tests/test_sgr_state.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/tests/test_text_sizing.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/tests/test_textwrap.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/tests/test_ucslevel.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/_clip.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/_constants.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/_wcswidth.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/_wcwidth.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/_wcwidth_c.pyi +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/_width.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/align.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/bisearch.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/control_codes.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/escape_sequences.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/grapheme.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/hyperlink.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/py.typed +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/sgr_state.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/table_ambiguous.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/table_grapheme.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/table_grapheme_overrides/__init__.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/table_grapheme_overrides/_known_058c7585.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/table_grapheme_overrides/_known_2148ff29.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/table_grapheme_overrides/_known_244dc88b.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/table_grapheme_overrides/_known_336a71a1.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/table_grapheme_overrides/_known_33ac73f2.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/table_grapheme_overrides/_known_3a1895d5.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/table_grapheme_overrides/_known_59180a0d.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/table_grapheme_overrides/_known_65c6beb5.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/table_grapheme_overrides/_known_78f828e8.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/table_grapheme_overrides/_known_8c2ae14d.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/table_grapheme_overrides/_known_900356bf.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/table_grapheme_overrides/_known_97904ece.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/table_grapheme_overrides/_known_a5880eeb.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/table_grapheme_overrides/_known_b6d33cf4.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/table_grapheme_overrides/_known_c57c295b.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/table_grapheme_overrides/_known_cf02297d.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/table_grapheme_overrides/_known_e18ac6a7.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/table_grapheme_overrides/_known_e2b75ee3.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/table_grapheme_overrides/_known_fb5fd79b.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/table_grapheme_overrides/_known_fdc99132.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/table_grapheme_overrides/_registry.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/table_mc.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/table_overrides.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/table_term_programs.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/table_vs15.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/table_vs16.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/table_wide.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/table_zero.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/text_sizing.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/textwrap.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/unicode_versions.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth/wcwidth.py +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth.egg-info/dependency_links.txt +0 -0
- {wcwidth-0.9.0 → wcwidth-0.9.1}/wcwidth.egg-info/top_level.txt +0 -0
|
@@ -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,13 @@
|
|
|
2
2
|
History
|
|
3
3
|
=======
|
|
4
4
|
|
|
5
|
-
0.9.
|
|
5
|
+
0.9.1 *2026-09-23*
|
|
6
|
+
* **Bugfix** a regression in 0.9.0 Python and libwcwidth_ `width()`_ mis-measured CSI sequences
|
|
7
|
+
over 64 bytes, `PR #271`_.
|
|
8
|
+
* **Performance** improvement of ~15% for 11 many Python API functions when using
|
|
9
|
+
default ``ambiguous_width`` and ``term_program`` arguments. `PR #273`_
|
|
10
|
+
|
|
11
|
+
0.9.0 *2026-09-23*
|
|
6
12
|
* **New** Optional CPython extension using libwcwidth_, improving performance 10-58x `PR #248`_.
|
|
7
13
|
* **Drop Support** for Python 3.8, `PR #248`_.
|
|
8
14
|
|
|
@@ -299,6 +305,8 @@ https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c::
|
|
|
299
305
|
.. _`PR #253`: https://github.com/jquast/wcwidth/pull/253
|
|
300
306
|
.. _`PR #259`: https://github.com/jquast/wcwidth/pull/259
|
|
301
307
|
.. _`PR #262`: https://github.com/jquast/wcwidth/pull/262
|
|
308
|
+
.. _`PR #271`: https://github.com/jquast/wcwidth/pull/271
|
|
309
|
+
.. _`PR #273`: https://github.com/jquast/wcwidth/pull/273
|
|
302
310
|
.. _`Issue #101`: https://github.com/jquast/wcwidth/issues/101
|
|
303
311
|
.. _`Issue #155`: https://github.com/jquast/wcwidth/issues/155
|
|
304
312
|
.. _`Issue #211`: https://github.com/jquast/wcwidth/issues/211
|
|
@@ -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
|
-----------
|
|
@@ -187,6 +191,8 @@ throughout, or use the ``_u32`` forms and re-encode the result. `wcwidth_encode
|
|
|
187
191
|
Re-encoding to a legacy charset is the caller's iconv(3) or ICU (``ucnv_*``) call; a byte cast
|
|
188
192
|
works when every codepoint fits the target, and iconv reports ``EILSEQ`` when one does not.
|
|
189
193
|
|
|
194
|
+
.. _libwcwidth-wcwidth:
|
|
195
|
+
|
|
190
196
|
wcwidth_u32()
|
|
191
197
|
~~~~~~~~~~~~~
|
|
192
198
|
|
|
@@ -206,6 +212,8 @@ U+2640 above is Ambiguous, so it answers to the second argument, while U+2630 is
|
|
|
206
212
|
2 under either setting. A single codepoint needs no ``_u8`` variant; use `wcswidth_u8()`_ to
|
|
207
213
|
measure text.
|
|
208
214
|
|
|
215
|
+
.. _libwcwidth-wcswidth:
|
|
216
|
+
|
|
209
217
|
wcswidth_u32() and wcswidth_u8()
|
|
210
218
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
211
219
|
|
|
@@ -219,6 +227,8 @@ when any control code other than NUL is present:
|
|
|
219
227
|
wcswidth_u32(family, 5, 1) /* man ZWJ woman ZWJ girl */ 2
|
|
220
228
|
wcswidth_u8("café", 5, 1) 4
|
|
221
229
|
|
|
230
|
+
.. _libwcwidth-wcstwidth:
|
|
231
|
+
|
|
222
232
|
wcstwidth_u32() and wcstwidth_u8()
|
|
223
233
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
224
234
|
|
|
@@ -230,6 +240,8 @@ argument applies terminal-specific corrections:
|
|
|
230
240
|
wcswidth_u8("☰", 3, 1) /* U+2630, wide */ 2
|
|
231
241
|
wcstwidth_u8("☰", 3, 1, "vte") 1
|
|
232
242
|
|
|
243
|
+
.. _libwcwidth-width:
|
|
244
|
+
|
|
233
245
|
wcwidth_width_u32() and wcwidth_width_u8()
|
|
234
246
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
235
247
|
|
|
@@ -261,6 +273,8 @@ codes:
|
|
|
261
273
|
/* err is WCWIDTH_ERROR_VERTICAL_CTRL */
|
|
262
274
|
}
|
|
263
275
|
|
|
276
|
+
.. _libwcwidth-align:
|
|
277
|
+
|
|
264
278
|
wcwidth_ljust_u8(), wcwidth_rjust_u8(), and wcwidth_center_u8()
|
|
265
279
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
266
280
|
|
|
@@ -288,6 +302,8 @@ returns a ``malloc``\ 'd NUL-terminated string the caller must ``free``:
|
|
|
288
302
|
/* "*café*" */
|
|
289
303
|
free(out);
|
|
290
304
|
|
|
305
|
+
.. _libwcwidth-clip:
|
|
306
|
+
|
|
291
307
|
wcwidth_clip_u8()
|
|
292
308
|
~~~~~~~~~~~~~~~~~
|
|
293
309
|
|
|
@@ -344,6 +360,8 @@ Movement is reported wherever it appears; the OSC sequences only where the clip
|
|
|
344
360
|
`wcwidth_clip_u32()`_ is the codepoint-array form, returning a ``malloc``\ 'd array of ``*out_len``
|
|
345
361
|
codepoints.
|
|
346
362
|
|
|
363
|
+
.. _libwcwidth-wrap:
|
|
364
|
+
|
|
347
365
|
wcwidth_wrap_u8() and wcwidth_wrap_u8_text()
|
|
348
366
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
349
367
|
|
|
@@ -383,6 +401,8 @@ unbreakable unit, so a line is never broken inside one, even at a space or hyphe
|
|
|
383
401
|
text. Python's `wrap()`_ behaves the same way. `wcwidth_wrap_u32()`_ and `wcwidth_wrap_u32_text()`_ are the
|
|
384
402
|
codepoint-array forms.
|
|
385
403
|
|
|
404
|
+
.. _libwcwidth-escape-strip:
|
|
405
|
+
|
|
386
406
|
wcwidth_escape_strip()
|
|
387
407
|
~~~~~~~~~~~~~~~~~~~~~~
|
|
388
408
|
|
|
@@ -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 1
|
|
22
|
+
#define WCWIDTH_VERSION "0.9.1"
|
|
23
23
|
|
|
24
24
|
/* Unicode version the library tables were generated from. */
|
|
25
25
|
#define WCWIDTH_UNICODE_VERSION "18.0.0"
|
|
@@ -90,12 +90,6 @@ is_illegal_ctrl(uint32_t ucs)
|
|
|
90
90
|
if (ucs >= 28 && ucs <= 31) {
|
|
91
91
|
return true; /* FS, GS, RS, US */
|
|
92
92
|
}
|
|
93
|
-
if (ucs == 0x7F) {
|
|
94
|
-
return true; /* DEL */
|
|
95
|
-
}
|
|
96
|
-
if (ucs >= 0x80 && ucs <= 0x9F) {
|
|
97
|
-
return true; /* C1 control characters */
|
|
98
|
-
}
|
|
99
93
|
return false;
|
|
100
94
|
}
|
|
101
95
|
|
|
@@ -417,7 +411,9 @@ static size_t
|
|
|
417
411
|
escape_span_u32(const uint32_t *cp, size_t n, size_t idx)
|
|
418
412
|
{
|
|
419
413
|
char buf[64];
|
|
414
|
+
char *heap = NULL;
|
|
420
415
|
size_t cap = 16;
|
|
416
|
+
size_t span = 1;
|
|
421
417
|
wcwidth_esc_result_t result;
|
|
422
418
|
|
|
423
419
|
if (idx + 1 < n && (cp[idx + 1] == '(' || cp[idx + 1] == ')')) {
|
|
@@ -428,26 +424,56 @@ escape_span_u32(const uint32_t *cp, size_t n, size_t idx)
|
|
|
428
424
|
}
|
|
429
425
|
|
|
430
426
|
/*
|
|
431
|
-
*
|
|
432
|
-
*
|
|
433
|
-
* run
|
|
427
|
+
* Widen before classifying: the classifier reads a truncated run as
|
|
428
|
+
* unterminated. Stop once a byte has ended the sequence, or the copy would
|
|
429
|
+
* run on into the text that follows, and only a CSI with no final byte
|
|
430
|
+
* takes a heap copy.
|
|
434
431
|
*/
|
|
435
432
|
for (;;) {
|
|
433
|
+
char *out = (heap != NULL) ? heap : buf;
|
|
434
|
+
bool open = true; /* the sequence has no final byte yet */
|
|
436
435
|
size_t j = 0;
|
|
437
436
|
|
|
438
437
|
while (j < cap && idx + j < n && cp[idx + j] < 0x80) {
|
|
439
|
-
|
|
438
|
+
uint32_t b = cp[idx + j];
|
|
439
|
+
|
|
440
|
+
if (j > 1 && (b < 0x20 || b > 0x3F)) {
|
|
441
|
+
open = false;
|
|
442
|
+
}
|
|
443
|
+
out[j] = (char) b;
|
|
440
444
|
j++;
|
|
441
445
|
}
|
|
442
|
-
if (j == cap && idx + j < n && cp[idx + j] < 0x80
|
|
443
|
-
cap
|
|
444
|
-
|
|
446
|
+
if (open && j == cap && idx + j < n && cp[idx + j] < 0x80) {
|
|
447
|
+
if (cap < sizeof(buf)) {
|
|
448
|
+
cap = sizeof(buf);
|
|
449
|
+
continue;
|
|
450
|
+
}
|
|
451
|
+
if (heap == NULL && cp[idx + 1] == '[') {
|
|
452
|
+
size_t run = cap;
|
|
453
|
+
|
|
454
|
+
while (idx + run < n && cp[idx + run] < 0x80) {
|
|
455
|
+
run++;
|
|
456
|
+
}
|
|
457
|
+
heap = (char *) malloc(run);
|
|
458
|
+
if (heap == NULL) {
|
|
459
|
+
return 1;
|
|
460
|
+
}
|
|
461
|
+
cap = run;
|
|
462
|
+
continue;
|
|
463
|
+
}
|
|
445
464
|
}
|
|
446
|
-
if (j == 0 || !wcwidth_escape_classify(
|
|
447
|
-
|
|
465
|
+
if (j == 0 || !wcwidth_escape_classify(out, j, 0, &result) || result.length == 0) {
|
|
466
|
+
span = 1;
|
|
448
467
|
}
|
|
449
|
-
|
|
468
|
+
else {
|
|
469
|
+
span = result.length;
|
|
470
|
+
}
|
|
471
|
+
break;
|
|
472
|
+
}
|
|
473
|
+
if (heap != NULL) {
|
|
474
|
+
free(heap);
|
|
450
475
|
}
|
|
476
|
+
return span;
|
|
451
477
|
}
|
|
452
478
|
|
|
453
479
|
/*
|
|
@@ -234,6 +234,34 @@ TEST(align_control_codes_strict)
|
|
|
234
234
|
ASSERT_EQ(WCWIDTH_ERROR_ILLEGAL_CTRL, error);
|
|
235
235
|
}
|
|
236
236
|
|
|
237
|
+
TEST(null_opts_defaults)
|
|
238
|
+
{
|
|
239
|
+
uint32_t cps[] = {'h', 'i'};
|
|
240
|
+
size_t len = 0;
|
|
241
|
+
int error = WCWIDTH_ERROR_NONE;
|
|
242
|
+
char *s;
|
|
243
|
+
uint32_t *u;
|
|
244
|
+
|
|
245
|
+
s = wcwidth_ljust_u8("hi", 2, WCWIDTH_PARSE, NULL, &len, &error);
|
|
246
|
+
ASSERT_EQ(2, len);
|
|
247
|
+
free(s);
|
|
248
|
+
s = wcwidth_rjust_u8("hi", 2, WCWIDTH_PARSE, NULL, &len, &error);
|
|
249
|
+
ASSERT_EQ(2, len);
|
|
250
|
+
free(s);
|
|
251
|
+
s = wcwidth_center_u8("hi", 2, WCWIDTH_PARSE, NULL, &len, &error);
|
|
252
|
+
ASSERT_EQ(2, len);
|
|
253
|
+
free(s);
|
|
254
|
+
u = wcwidth_ljust_u32(cps, 2, WCWIDTH_PARSE, NULL, &len, &error);
|
|
255
|
+
ASSERT_EQ(2, len);
|
|
256
|
+
free(u);
|
|
257
|
+
u = wcwidth_rjust_u32(cps, 2, WCWIDTH_PARSE, NULL, &len, &error);
|
|
258
|
+
ASSERT_EQ(2, len);
|
|
259
|
+
free(u);
|
|
260
|
+
u = wcwidth_center_u32(cps, 2, WCWIDTH_PARSE, NULL, &len, &error);
|
|
261
|
+
ASSERT_EQ(2, len);
|
|
262
|
+
free(u);
|
|
263
|
+
}
|
|
264
|
+
|
|
237
265
|
int
|
|
238
266
|
main(void)
|
|
239
267
|
{
|
|
@@ -247,5 +275,6 @@ main(void)
|
|
|
247
275
|
RUN_TEST(rjust_huge_dest_width_multibyte_fill);
|
|
248
276
|
RUN_TEST(center_huge_dest_width);
|
|
249
277
|
RUN_TEST(align_control_codes_strict);
|
|
278
|
+
RUN_TEST(null_opts_defaults);
|
|
250
279
|
return test_summary();
|
|
251
280
|
}
|
|
@@ -143,6 +143,42 @@ TEST(unsupported_osc)
|
|
|
143
143
|
cs_assert("ab\x1b]0;t\x07xy", 0, 3, "ab\x1b]0;t\x07x");
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
+
TEST(null_opts_and_tabsize_zero)
|
|
147
|
+
{
|
|
148
|
+
size_t len = 0;
|
|
149
|
+
int error = WCWIDTH_ERROR_NONE;
|
|
150
|
+
wcwidth_clip_opts_t opts = WCWIDTH_CLIP_OPTS_DEFAULT;
|
|
151
|
+
char *s;
|
|
152
|
+
|
|
153
|
+
s = wcwidth_clip_u8("a\tb", 3, WCWIDTH_PARSE, NULL, &len, &error);
|
|
154
|
+
ASSERT_NOT_NULL(s);
|
|
155
|
+
free(s);
|
|
156
|
+
|
|
157
|
+
opts.tabsize = 0;
|
|
158
|
+
s = wcwidth_clip_u8("a\tb", 3, WCWIDTH_PARSE, &opts, &len, &error);
|
|
159
|
+
ASSERT_STREQ("a\tb", s);
|
|
160
|
+
free(s);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
TEST(u32_null_opts_and_past_end)
|
|
164
|
+
{
|
|
165
|
+
uint32_t cps[] = {'h', 'i'};
|
|
166
|
+
size_t len = 0;
|
|
167
|
+
int error = WCWIDTH_ERROR_NONE;
|
|
168
|
+
wcwidth_clip_opts_t opts = WCWIDTH_CLIP_OPTS_DEFAULT;
|
|
169
|
+
uint32_t *u;
|
|
170
|
+
|
|
171
|
+
u = wcwidth_clip_u32(cps, 2, WCWIDTH_PARSE, NULL, &len, &error);
|
|
172
|
+
ASSERT_NOT_NULL(u);
|
|
173
|
+
free(u);
|
|
174
|
+
|
|
175
|
+
opts.v_start = 5;
|
|
176
|
+
opts.v_end = 9;
|
|
177
|
+
u = wcwidth_clip_u32(cps, 2, WCWIDTH_PARSE, &opts, &len, &error);
|
|
178
|
+
ASSERT_NOT_NULL(u);
|
|
179
|
+
free(u);
|
|
180
|
+
}
|
|
181
|
+
|
|
146
182
|
int
|
|
147
183
|
main(void)
|
|
148
184
|
{
|
|
@@ -154,5 +190,7 @@ main(void)
|
|
|
154
190
|
RUN_TEST(tab_captures_style);
|
|
155
191
|
RUN_TEST(unsupported_cursor_movement);
|
|
156
192
|
RUN_TEST(unsupported_osc);
|
|
193
|
+
RUN_TEST(null_opts_and_tabsize_zero);
|
|
194
|
+
RUN_TEST(u32_null_opts_and_past_end);
|
|
157
195
|
return test_summary();
|
|
158
196
|
}
|
|
@@ -162,6 +162,55 @@ TEST(to_escape_colon_form)
|
|
|
162
162
|
ASSERT_STREQ("\x1b[38;2;10;20;30m", buf);
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
+
TEST(attribute_and_color_codes)
|
|
166
|
+
{
|
|
167
|
+
static const char *const active[] = {"2", "3", "5", "6", "7", "8", "9",
|
|
168
|
+
"21", "30", "37", "40", "47", "48;5;9", "48;2;1;2;3"};
|
|
169
|
+
size_t i;
|
|
170
|
+
wcwidth_sgr_state_t s;
|
|
171
|
+
|
|
172
|
+
for (i = 0; i < sizeof(active) / sizeof(active[0]); i++) {
|
|
173
|
+
s = WCWIDTH_SGR_STATE_DEFAULT;
|
|
174
|
+
wcwidth_sgr_update(&s, active[i], strlen(active[i]));
|
|
175
|
+
ASSERT_TRUE(wcwidth_sgr_is_active(&s));
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
s = WCWIDTH_SGR_STATE_DEFAULT;
|
|
179
|
+
wcwidth_sgr_update(&s, "31;41", 5);
|
|
180
|
+
ASSERT_TRUE(wcwidth_sgr_is_active(&s));
|
|
181
|
+
wcwidth_sgr_update(&s, "39", 2);
|
|
182
|
+
ASSERT_TRUE(wcwidth_sgr_is_active(&s));
|
|
183
|
+
wcwidth_sgr_update(&s, "49", 2);
|
|
184
|
+
ASSERT_FALSE(wcwidth_sgr_is_active(&s));
|
|
185
|
+
|
|
186
|
+
s = WCWIDTH_SGR_STATE_DEFAULT;
|
|
187
|
+
wcwidth_sgr_update(&s, "1;2;3;4;5;6;7;8;9;21", 20);
|
|
188
|
+
ASSERT_TRUE(wcwidth_sgr_is_active(&s));
|
|
189
|
+
wcwidth_sgr_update(&s, "22;23;24;25;27;28;29", 20);
|
|
190
|
+
ASSERT_FALSE(wcwidth_sgr_is_active(&s));
|
|
191
|
+
|
|
192
|
+
s = WCWIDTH_SGR_STATE_DEFAULT;
|
|
193
|
+
wcwidth_sgr_update(&s, "38;5;99999999999999", 19);
|
|
194
|
+
ASSERT_TRUE(wcwidth_sgr_is_active(&s));
|
|
195
|
+
|
|
196
|
+
{
|
|
197
|
+
char many[512];
|
|
198
|
+
size_t p;
|
|
199
|
+
|
|
200
|
+
for (p = 0; p < sizeof(many) - 1; p++) {
|
|
201
|
+
many[p] = (p % 2 == 0) ? '1' : ';';
|
|
202
|
+
}
|
|
203
|
+
many[p] = '\0';
|
|
204
|
+
s = WCWIDTH_SGR_STATE_DEFAULT;
|
|
205
|
+
wcwidth_sgr_update(&s, many, p);
|
|
206
|
+
ASSERT_TRUE(s.bold);
|
|
207
|
+
|
|
208
|
+
s = WCWIDTH_SGR_STATE_DEFAULT;
|
|
209
|
+
wcwidth_sgr_update(&s, ";;1", 3);
|
|
210
|
+
ASSERT_TRUE(s.bold);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
165
214
|
int
|
|
166
215
|
main(void)
|
|
167
216
|
{
|
|
@@ -171,5 +220,6 @@ main(void)
|
|
|
171
220
|
RUN_TEST(to_escape_bounded);
|
|
172
221
|
RUN_TEST(to_escape_colon_form);
|
|
173
222
|
RUN_TEST(propagate_basic);
|
|
223
|
+
RUN_TEST(attribute_and_color_codes);
|
|
174
224
|
return test_summary();
|
|
175
225
|
}
|
|
@@ -40,10 +40,23 @@ TEST(display_width_basic)
|
|
|
40
40
|
ASSERT_EQ(3, wcwidth_ts_display_width(&ts, 1));
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
TEST(parse_invalid_and_clamped)
|
|
44
|
+
{
|
|
45
|
+
wcwidth_ts_params_t params;
|
|
46
|
+
|
|
47
|
+
ASSERT_TRUE(wcwidth_ts_parse_params("z=1", 3, ¶ms)); /* unknown key */
|
|
48
|
+
ASSERT_TRUE(wcwidth_ts_parse_params("s=-5", 4, ¶ms)); /* clamped low */
|
|
49
|
+
ASSERT_TRUE(wcwidth_ts_parse_params("s=", 2, ¶ms)); /* no digits */
|
|
50
|
+
ASSERT_TRUE(wcwidth_ts_parse_params("s=2x", 4, ¶ms)); /* trailing junk */
|
|
51
|
+
ASSERT_TRUE(wcwidth_ts_parse_params("s=99999999999999999999", 22, ¶ms));
|
|
52
|
+
ASSERT_TRUE(params.scale >= 1); /* saturated, then clamped high */
|
|
53
|
+
}
|
|
54
|
+
|
|
43
55
|
int
|
|
44
56
|
main(void)
|
|
45
57
|
{
|
|
46
58
|
RUN_TEST(parse_basic);
|
|
47
59
|
RUN_TEST(display_width_basic);
|
|
60
|
+
RUN_TEST(parse_invalid_and_clamped);
|
|
48
61
|
return test_summary();
|
|
49
62
|
}
|
|
@@ -240,6 +240,55 @@ TEST(wrap_lone_continuation_bytes)
|
|
|
240
240
|
}
|
|
241
241
|
}
|
|
242
242
|
|
|
243
|
+
TEST(wrap_max_lines_placeholder)
|
|
244
|
+
{
|
|
245
|
+
char *out;
|
|
246
|
+
size_t len;
|
|
247
|
+
wcwidth_wrap_opts_t o = WCWIDTH_WRAP_OPTS_DEFAULT;
|
|
248
|
+
const char *exp[] = {"aa bb [...]"};
|
|
249
|
+
|
|
250
|
+
o.width = 11;
|
|
251
|
+
o.max_lines = 1;
|
|
252
|
+
ASSERT_EQ(0, wcwidth_wrap_u8("aa bb cccccccc", 14, &o, &out, &len));
|
|
253
|
+
check_lines(out, len, exp, 1);
|
|
254
|
+
free(out);
|
|
255
|
+
|
|
256
|
+
o = WCWIDTH_WRAP_OPTS_DEFAULT;
|
|
257
|
+
o.width = 4;
|
|
258
|
+
o.max_lines = 1;
|
|
259
|
+
ASSERT_EQ(-2, wcwidth_wrap_u8("aaaa bbbb", 9, &o, &out, &len));
|
|
260
|
+
|
|
261
|
+
o = WCWIDTH_WRAP_OPTS_DEFAULT;
|
|
262
|
+
o.width = 6;
|
|
263
|
+
o.max_lines = 1;
|
|
264
|
+
ASSERT_EQ(0, wcwidth_wrap_u8("aa bbbb", 7, &o, &out, &len));
|
|
265
|
+
free(out);
|
|
266
|
+
|
|
267
|
+
o = WCWIDTH_WRAP_OPTS_DEFAULT;
|
|
268
|
+
o.width = 6;
|
|
269
|
+
o.max_lines = 2;
|
|
270
|
+
ASSERT_EQ(0, wcwidth_wrap_u8("aa bb cc dd ee", 14, &o, &out, &len));
|
|
271
|
+
free(out);
|
|
272
|
+
|
|
273
|
+
o = WCWIDTH_WRAP_OPTS_DEFAULT;
|
|
274
|
+
o.width = 11;
|
|
275
|
+
o.max_lines = 2;
|
|
276
|
+
ASSERT_EQ(0, wcwidth_wrap_u8("aa bb ccccccccc dd", 18, &o, &out, &len));
|
|
277
|
+
free(out);
|
|
278
|
+
|
|
279
|
+
o = WCWIDTH_WRAP_OPTS_DEFAULT;
|
|
280
|
+
o.width = 3;
|
|
281
|
+
o.expand_tabs = false;
|
|
282
|
+
ASSERT_EQ(0, wcwidth_wrap_u8("a\tb", 3, &o, &out, &len));
|
|
283
|
+
free(out);
|
|
284
|
+
|
|
285
|
+
o = WCWIDTH_WRAP_OPTS_DEFAULT;
|
|
286
|
+
o.width = 2;
|
|
287
|
+
o.break_long_words = false;
|
|
288
|
+
ASSERT_EQ(0, wcwidth_wrap_u8("abcdef", 6, &o, &out, &len));
|
|
289
|
+
free(out);
|
|
290
|
+
}
|
|
291
|
+
|
|
243
292
|
int
|
|
244
293
|
main(void)
|
|
245
294
|
{
|
|
@@ -251,5 +300,6 @@ main(void)
|
|
|
251
300
|
RUN_TEST(wrap_lines_u8);
|
|
252
301
|
RUN_TEST(wrap_tabsize_zero);
|
|
253
302
|
RUN_TEST(wrap_lone_continuation_bytes);
|
|
303
|
+
RUN_TEST(wrap_max_lines_placeholder);
|
|
254
304
|
return test_summary();
|
|
255
305
|
}
|
|
@@ -50,9 +50,27 @@ TEST(encode_roundtrip)
|
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
TEST(decode_malformed)
|
|
54
|
+
{
|
|
55
|
+
static const char *const bad[] = {
|
|
56
|
+
"\xf8", "\xff", "\xe2\x82", "\xe2\x28\xa1",
|
|
57
|
+
"\xc0\xaf", "\xe0\x80\xaf", "\xed\xa0\x80", "\xf4\x90\x80\x80"};
|
|
58
|
+
size_t i;
|
|
59
|
+
uint32_t cp = 0;
|
|
60
|
+
|
|
61
|
+
ASSERT_EQ(0, wcwidth_utf8_decode_single("", 0, &cp));
|
|
62
|
+
for (i = 0; i < sizeof(bad) / sizeof(bad[0]); i++) {
|
|
63
|
+
size_t used = wcwidth_utf8_decode_single(bad[i], strlen(bad[i]), &cp);
|
|
64
|
+
|
|
65
|
+
ASSERT_EQ(0xFFFD, cp);
|
|
66
|
+
ASSERT_TRUE(used >= 1 && used <= strlen(bad[i]));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
53
70
|
int
|
|
54
71
|
main(void)
|
|
55
72
|
{
|
|
56
73
|
RUN_TEST(encode_roundtrip);
|
|
74
|
+
RUN_TEST(decode_malformed);
|
|
57
75
|
return test_summary();
|
|
58
76
|
}
|
|
@@ -88,6 +88,12 @@ TEST(wcstwidth_terminal_overrides)
|
|
|
88
88
|
ASSERT_EQ(2, wcstwidth_u32(family, 5, 1, "kitty"));
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
+
TEST(null_input)
|
|
92
|
+
{
|
|
93
|
+
ASSERT_EQ(0, wcswidth_u8(NULL, 0, 1));
|
|
94
|
+
ASSERT_EQ(0, wcstwidth_u8(NULL, 0, 1, "kitty"));
|
|
95
|
+
}
|
|
96
|
+
|
|
91
97
|
int
|
|
92
98
|
main(void)
|
|
93
99
|
{
|
|
@@ -97,5 +103,6 @@ main(void)
|
|
|
97
103
|
RUN_TEST(wcstwidth_u8_basic);
|
|
98
104
|
RUN_TEST(wcstwidth_u8_long);
|
|
99
105
|
RUN_TEST(wcstwidth_terminal_overrides);
|
|
106
|
+
RUN_TEST(null_input);
|
|
100
107
|
return test_summary();
|
|
101
108
|
}
|