Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 1 addition & 11 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,18 +90,8 @@ jobs:
shell: bash
run: |
V=${{ matrix.python-version }}

if [[ "$V" = pypy-* ]]; then
V=$(echo $V | tr -d .-)
IS_PYPY=1
else
V=py$(echo $V | tr -d .)
IS_PYPY=0
fi

echo IS_PYPY=$IS_PYPY >>$GITHUB_ENV
V=py$(echo $V | tr -d .)
echo TOX_PYTHON=$V >>$GITHUB_ENV

python -Im pip install tox

- name: Prepare sdist and source-dir
Expand Down
4 changes: 4 additions & 0 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,8 @@ requirements.txt or equivalent. Their signatures will never change.

.. autofunction:: wcwidth.HyperlinkParams

.. autofunction:: wcwidth.TextSizing

.. autofunction:: wcwidth.TextSizingParams

.. _SEMVER: https://semver.org
16 changes: 14 additions & 2 deletions docs/intro.rst
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,12 @@ Use function `width()`_ to measure a string with improved handling of ``control_
>>> # or ignored,
>>> wcwidth.width('hello\x1b[5Dworld', control_codes='ignore')
10
>>> # Measure width of text using kitty text sizing protocol (OSC 66),
>>> width('\x1b]66;w=2;XY\x07')
2
>>> # Scaled text sizing: each grapheme occupies 'scale' cells
>>> width('\x1b]66;s=2;ABC\x07')
6

Use ``control_codes='ignore'`` when the input is known not to contain any control characters or
terminal sequences for slightly improved performance. Note that TAB (``'\t'``) is a control
Expand Down Expand Up @@ -178,7 +184,6 @@ such as clearing the screen, vertical, or absolute cursor movement will raise ``
...
ValueError: Cursor left movement at position 1 would move 5 cells left from column 1, exceeding string start


iter_sequences()
----------------

Expand Down Expand Up @@ -311,6 +316,10 @@ Use `clip()`_ to extract a substring by column positions, preserving terminal se
>>> clip('\x1b]8;;http://example.com\x07Click This link\x1b]8;;\x07', 8, 15)
'\x1b]8;;http://example.com\x07is link\x1b]8;;\x07'

>>> # and OSC 66 kitty text sizing, supporting width and scale, 'Look' -> '...ook'
>>> clip('\x1b]66;w=4:s=4;Look\x07', 1, 16, fillchar='.')
'...\x1b]66;s=4:w=3;ook\x07'

Use ``overtyping=False`` when the input is known not to contain any cursor movement characters
(``\b``, ``\r``, ``CSI C``, ``CSI D``, ``CSI G``) for improved performance. When
``overtyping=None`` (default), a slower "Painter's algorithm" may be used after testing for the
Expand Down Expand Up @@ -526,7 +535,8 @@ History

0.7.0 *2026-04-30*
* **New** `clip()`_ parameter ``control_codes='parse'``, ``'ignore'``, and ``'strict'``. `clip()`_
is now able to clip OSC 8 hyperlinks.
is now able to clip OSC 8 hyperlinks and OSC 66 text sizing sequences.
* **New** support for `kitty text sizing protocol`_ (OSC 66) in `width()`_ and `clip()`_.
* **Improved** `clip()`_ and `width()`_ to support horizontal cursor sequences (``cub``, ``cuf``,
``hpa``). Cursor-left (``cub``) or backspace (``\b``) now overwrites text. ``column_address``
(``hpa``) and carriage return (``\r``) are now parsed, and some values conditionally raise
Expand Down Expand Up @@ -817,6 +827,8 @@ https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c::
.. _`clip()`: https://wcwidth.readthedocs.io/en/latest/api.html#wcwidth.clip
.. _`strip_sequences()`: https://wcwidth.readthedocs.io/en/latest/api.html#wcwidth.strip_sequences
.. _`propagate_sgr()`: https://wcwidth.readthedocs.io/en/latest/api.html#wcwidth.propagate_sgr
.. _`TextSizing`: https://wcwidth.readthedocs.io/en/latest/api.html#wcwidth.TextSizing
.. _`TextSizingParams`: https://wcwidth.readthedocs.io/en/latest/api.html#wcwidth.TextSizingParams
.. _`iter_sequences()`: https://wcwidth.readthedocs.io/en/latest/api.html#wcwidth.iter_sequences
.. _`list_versions()`: https://wcwidth.readthedocs.io/en/latest/api.html#wcwidth.list_versions
.. _`Unicode Standard Annex #29`: https://www.unicode.org/reports/tr29/
Expand Down
2 changes: 1 addition & 1 deletion requirements-tests38.in
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# for python3.8
pytest<7
pytest-cov
coverage[toml]<6
coverage[toml]<=7.6.1
packaging<26
8 changes: 4 additions & 4 deletions requirements-tests38.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#
attrs==25.3.0
# via pytest
coverage==5.5
coverage==7.6.1
# via
# -r requirements-tests38.in
# pytest-cov
Expand All @@ -27,6 +27,6 @@ pytest==6.2.5
pytest-cov==5.0.0
# via -r requirements-tests38.in
toml==0.10.2
# via
# coverage
# pytest
# via pytest
tomli==2.4.1
# via coverage
12 changes: 12 additions & 0 deletions tests/test_benchmarks.py
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,18 @@ def test_clip_osc8_hyperlinks(benchmark):
benchmark(wcwidth.clip, text, 0, 80)


def test_width_osc66(benchmark):
"""Benchmark width() with OSC 66 text sizing sequences."""
text = '\x1b]66;w=2;XY\x07\x1b]66;s=3;ABC\x07'
benchmark(wcwidth.width, text)


def test_clip_osc66(benchmark):
"""Benchmark clip() with OSC 66 text sizing sequences."""
text = '\x1b]66;w=2;XY\x07\x1b]66;s=3;ABC\x07'
benchmark(wcwidth.clip, text, 3, 8)


def test_clip_cursor_cr_overwrite(benchmark):
"""Benchmark clip() with carriage-return overwrite (painter path)."""
text = 'hello\rworld ' * 20
Expand Down
Loading
Loading