Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
e47252f
Text Sizing Protocol (WIP/DRAFT!)
jquast Apr 8, 2026
f1249fc
Mass rename 'OSC 66' -> 'Text Sizing'
jquast Apr 10, 2026
7d08ea6
don't do all that
jquast Apr 11, 2026
a33b401
readme example
jquast Apr 11, 2026
8db11b2
Briefly mention kitty sizing
jquast Apr 14, 2026
f09e950
Merge remote-tracking branch 'origin/master' into jq/text-sizing-prot…
jquast Apr 18, 2026
39f3b33
broken! not complete!
jquast Apr 19, 2026
43c298e
still pecking away at this ..
jquast Apr 24, 2026
bea1c34
passing tests, now we lint ..
jquast Apr 27, 2026
a2cde09
finish gross refactor, preventing circular imports
jquast Apr 27, 2026
309deb2
big bucks, no whammies
jquast Apr 27, 2026
d459320
try ..
jquast Apr 27, 2026
9f061ea
go ahead, have it all
jquast Apr 27, 2026
8b41747
small changes
jquast Apr 28, 2026
af4cab8
tempted to dump pypy testing ..
jquast Apr 28, 2026
8e7dade
That's it. Disable pypy. Fuck Microsoft.
jquast Apr 28, 2026
fe98de8
small refactor and remove local import in textwrap
jquast Apr 28, 2026
20f1bf6
re-order text sizing after SGR (less common/faster match)
jquast Apr 28, 2026
1bc7a43
don't redefine width from outer scope
jquast Apr 28, 2026
ba6741e
checkpoint
jquast Apr 28, 2026
0edd663
finish clip() of text sizing and left/right
jquast Apr 28, 2026
5aa4265
checkpoint
jquast Apr 28, 2026
7193ac7
much better clip(), also comes with a refactor ..
jquast Apr 29, 2026
90e90f8
annoying copilot linting
jquast Apr 29, 2026
59c25ae
lint/docformatter
jquast Apr 29, 2026
3a16702
Refactor -- no API or behavior changes
jquast Apr 29, 2026
131faeb
stupid simplification/refactor
jquast Apr 30, 2026
84d46a8
use NamedTuple ..
jquast Apr 30, 2026
fab8771
checkpoint
jquast Apr 30, 2026
a01f045
allow clip() to better translate CURSOR_LEFT, +text_size
jquast Apr 30, 2026
29e9548
narf, go ahead commit text sizing here, too
jquast Apr 30, 2026
6b6e4d8
Merge branch 'jq/refactor' into jq/text-sizing-protocol
jquast Apr 30, 2026
f980a1e
use python 3.13 docformatter
jquast Apr 30, 2026
45ebfb5
Merge branch 'jq/refactor' into jq/text-sizing-protocol
jquast Apr 30, 2026
24f1cdc
refactor
jquast Apr 30, 2026
554d828
Merge branch 'jq/refactor' into jq/text-sizing-protocol
jquast Apr 30, 2026
08a1c63
lint and turn if/else inward
jquast Apr 30, 2026
34b6db7
checkpoint
jquast Apr 30, 2026
195a81d
more refactor/moving of files
jquast Apr 30, 2026
d983907
use py38-friendly types
jquast Apr 30, 2026
9c20f00
py38 friendly types
jquast Apr 30, 2026
2e46823
Merge branch 'jq/refactor' into jq/text-sizing-protocol
jquast Apr 30, 2026
addf077
more refactor, remove text sizing for PR!
jquast Apr 30, 2026
7cc2845
format
jquast Apr 30, 2026
c5fa80f
rename files to prevent conflict
jquast Apr 30, 2026
abc6772
Merge remote-tracking branch 'origin/master' into jq/refactor
jquast Apr 30, 2026
bf1676a
bugger fixer
jquast Apr 30, 2026
e0da554
Add legacy import helper
jquast Apr 30, 2026
d214ef8
unused reference
jquast Apr 30, 2026
0e232a7
nit
jquast Apr 30, 2026
36d654b
make painter's algorithm optional by cursor sequence movement
jquast Apr 30, 2026
b4fbb7a
use \x08 as suggested by co-pilot, i guess
jquast Apr 30, 2026
9d8419e
basic support for \r and hpa
jquast Apr 30, 2026
c38dddf
checkpoint, 100% coverage but hyperlinks todo
jquast Apr 30, 2026
1c60bd3
clip() is getting a bit long in the tooth!
jquast Apr 30, 2026
4ede819
last rewrite?
jquast Apr 30, 2026
dbb742f
link to more wcwidth's
jquast Apr 30, 2026
535959b
experiment with simpler VS16 and GraphemeMeasurer() class
jquast May 1, 2026
da498b7
big update, no whammies, let's check the performance ..
jquast May 1, 2026
1746d13
linting is out of control
jquast May 1, 2026
92c2f41
add missing files :o
jquast May 1, 2026
4809924
docfix
jquast May 1, 2026
e0e310e
doc refactor
jquast May 1, 2026
1e8b3c8
return to inline/duplicated wcswidth/width
jquast May 1, 2026
5e79b04
inline performance refactor and variable names for readaibility
jquast May 1, 2026
6490d47
refactor, no _ClipContext
jquast May 1, 2026
fd7dc44
refactor test_clip_cursors -> test_clip_overtyping
jquast May 1, 2026
2b89964
add many cc=ignore and two overtyping=True benchmarks
jquast May 1, 2026
d2b12ea
add missing coverage, don't ignore old wcwidth.wcwidth import path,
jquast May 1, 2026
251a319
pylint
jquast May 1, 2026
ea8fffc
now i'm 100% certain of no possible ill-effects of refactor
jquast May 1, 2026
91eae65
fix import order
jquast May 1, 2026
1e5f195
alright, fixadoodle
jquast May 1, 2026
a3155a9
skip pedantic tests without cospeed installed
jquast May 1, 2026
a2dbb94
bugfix version
jquast May 1, 2026
495f1fa
nit
jquast May 1, 2026
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
4 changes: 0 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,6 @@ jobs:
- "3.12"
- "3.13"
- "3.14"
- "pypy-3.8"
- "pypy-3.9"
- "pypy-3.10"
- "pypy-3.11"

runs-on: ${{ matrix.os }}
container: ${{ matrix.container }}
Expand Down
48 changes: 0 additions & 48 deletions bin/new-wide-by-version.py

This file was deleted.

17 changes: 11 additions & 6 deletions bin/update-tables.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
#!/usr/bin/env python
"""
Update the Unicode code tables for wcwidth. This is code generation using jinja2.
Update the Unicode code tables for wcwidth.

This is typically executed through tox,
This is code generation using jinja2. This is typically executed through tox,

$ tox -e update

https://github.com/jquast/wcwidth
"""

from __future__ import annotations

# std imports
Expand All @@ -24,7 +25,7 @@
from pathlib import Path
from dataclasses import field, fields, dataclass

from typing import Any, Mapping, Iterable, Iterator, Sequence, Collection
from typing import Any, Mapping, Iterable, Iterator, Optional, Sequence, Collection

try:
from typing import Self
Expand Down Expand Up @@ -108,9 +109,10 @@ def _bisearch(ucs, table):
@dataclass(order=True, frozen=True)
class UnicodeVersion:
"""A class for comparable unicode version."""

major: int
minor: int
micro: int | None
micro: Optional[int]

@classmethod
def parse(cls, version_str: str) -> UnicodeVersion:
Expand Down Expand Up @@ -138,7 +140,8 @@ def __str__(self) -> str:
@dataclass(frozen=True)
class TableEntry:
"""An entry of a unicode table."""
code_range: tuple[int, int] | None

code_range: Optional[tuple[int, int]]
properties: tuple[str, ...]
comment: str

Expand Down Expand Up @@ -255,6 +258,7 @@ class UnicodeTableRenderCtx(RenderContext):
@dataclass
class RenderDefinition:
"""Base class, do not instantiate it directly."""

jinja_filename: str
output_filename: str
render_context: RenderContext
Expand Down Expand Up @@ -330,6 +334,7 @@ def new(cls, filename: str, context: UnicodeTableRenderCtx) -> Self:
@dataclass(frozen=True)
class GraphemeTableRenderCtx(RenderContext):
"""Render context for grapheme tables (latest version only)."""

unicode_version: str
tables: Mapping[str, TableDef]

Expand Down Expand Up @@ -880,7 +885,6 @@ def fetch_table_grapheme_data() -> GraphemeTableRenderCtx:
tables.update(parse_indic_syllabic_category(
UnicodeDataFile.IndicSyllabicCategory(latest_version)
))

return GraphemeTableRenderCtx(str(latest_version), tables)


Expand All @@ -895,6 +899,7 @@ class UnicodeDataFile:
TestEmojiVariationSequences, these files should be forcefully re-fetched CLI argument '--no-
check-last-modified'.
"""

URL_DERIVED_AGE = 'https://www.unicode.org/Public/UCD/latest/ucd/DerivedAge.txt'
URL_EASTASIAN_WIDTH = 'https://www.unicode.org/Public/{version}/ucd/EastAsianWidth.txt'
URL_DERIVED_CATEGORY = 'https://www.unicode.org/Public/{version}/ucd/extracted/DerivedGeneralCategory.txt'
Expand Down
1 change: 1 addition & 0 deletions bin/verify-table-integrity.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
+DerivedGeneralCategory-8.0.0.txt:19B0..19C9 ; Lo # [26] NEW TAI LUE VOWEL SIGN VOWEL SHORTENER..NEW TAI LUE TONE MARK-2

"""

# std imports
import logging

Expand Down
18 changes: 9 additions & 9 deletions bin/wcwidth-browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,7 @@ def page_size(self):

class Pager:
"""A less(1)-like browser for browsing unicode characters."""

# pylint: disable=too-many-instance-attributes

#: screen state for next draw method(s).
Expand Down Expand Up @@ -520,14 +521,13 @@ def run(self, writer, reader):
"""
Pager entry point.

In interactive mode (terminal is a tty), run until
``process_keystroke()`` detects quit keystroke ('q'). In
non-interactive mode, exit after displaying all unicode points.
In interactive mode (terminal is a tty), run until ``process_keystroke()`` detects quit
keystroke ('q'). In non-interactive mode, exit after displaying all unicode points.

:param writer: callable writes to output stream, receiving unicode.
:type writer: callable
:param reader: callable reads keystrokes from input stream, sending
instance of blessed.keyboard.Keystroke.
:param reader: callable reads keystrokes from input stream, sending instance of
blessed.keyboard.Keystroke.
:type reader: callable
"""
self.initialize_page_data()
Expand Down Expand Up @@ -720,8 +720,8 @@ def draw_heading(self, writer):
"""
Conditionally redraw screen when ``dirty`` attribute is valued REFRESH.

When Pager attribute ``dirty`` is ``STATE_REFRESH``, cursor is moved
to (0,0), screen is cleared, and heading is displayed.
When Pager attribute ``dirty`` is ``STATE_REFRESH``, cursor is moved to (0,0), screen is
cleared, and heading is displayed.

:param callable writer: callable writes to output stream, receiving unicode.
:return: True if class attribute ``dirty`` is ``STATE_REFRESH``.
Expand Down Expand Up @@ -787,8 +787,8 @@ def page_view(self, data):
"""
Generator yields text to be displayed for the current unicode pageview.

:param list[(unicode, unicode)] data: The current page's data as tuple
of ``(ucs, name)``.
:param list[(unicode, unicode)] data: The current page's data as tuple of ``(ucs,
name)``.
:returns: generator for full-page text for display
"""
if self.term.is_a_tty:
Expand Down
1 change: 1 addition & 0 deletions bin/wcwidth-libc-comparator.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
This program accepts one optional command-line argument, the unicode version
level for our library to use when comparing to libc.
"""

# pylint: disable=C0103
# Invalid module name "wcwidth-libc-comparator"

Expand Down
2 changes: 1 addition & 1 deletion code_templates/grapheme_table.py.j2
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Exports grapheme cluster break property tables for Unicode version {{ unicode_ve
This module provides lookup tables for Unicode grapheme cluster break properties as defined in UAX
#29: Unicode Text Segmentation.

This code generated by {{this_filepath}} on {{utc_now}}.
This code generated by python wcwidth project.
"""
# pylint: disable=duplicate-code
{%- for var_name, table_def in tables.items() %}
Expand Down
2 changes: 1 addition & 1 deletion code_templates/python_table.py.j2
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""
Exports {{ variable_name }} table keyed by supporting unicode version level.

This code generated by {{this_filepath}} on {{utc_now}}.
This code generated by python wcwidth project.
"""
# pylint: disable=duplicate-code
{{ variable_name }} = {
Expand Down
2 changes: 1 addition & 1 deletion code_templates/unicode_versions.py.j2
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""
Exports function list_versions() for unicode version level support.

This code generated by {{this_filepath}} on {{utc_now}}.
This code generated by python wcwidth project.
"""

from __future__ import annotations
Expand Down
4 changes: 4 additions & 0 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,8 @@ requirements.txt or equivalent. Their signatures will never change.

.. autofunction:: wcwidth.list_versions

.. autofunction:: wcwidth.Hyperlink

.. autofunction:: wcwidth.HyperlinkParams

.. _SEMVER: https://semver.org
Loading
Loading