Specification¶
This document defines how the Python wcwidth and C11 libwcwidth libraries measure the printable
width of characters of a string. This is not meant to be an official standard, but as a terse
description of the lowest level API functions wcwidth.wcwidth() and wcwidth.wcswidth()
and their relation to higher level functions wcwidth.width(), wcwidth.wcstwidth() and
wcwidth.iter_graphemes().
Scope¶
The lowest level functions wcwidth.wcwidth() and wcwidth.wcswidth() return -1 when any
control codes are present. The higher level function wcwidth.width() never returns -1,
accepting default arguments, control_codes='parse' and its behavior and options are described by
its docstring and specifications of related control codes, XTerm Control Sequences and Kitty
Text Sizing Protocol.
Each string yielded by wcwidth.iter_graphemes() may be mapped to wcwidth.wcswidth() to
accurately measure the width of a grapheme. wcwidth.iter_graphemes() implements the Unicode
Standard Annex #29 rules of Unicode 18.0, the version of this library’s tables, while
unicodedata.iter_graphemes(), new in Python 3.15, implements Unicode 17.0. They also differ in
return value: wcwidth.iter_graphemes() yields only strings, while
unicodedata.iter_graphemes() yields unicodedata.Segment class objects.
Tamil, Kannada and Sinhala text is measured differently than it is segmented, so
wcwidth.clip() and wcwidth.wrap() do not measure these scripts correctly. See Virama
Conjunct Formation.
The C11 library libwcwidth implements this specification through parallel entry points:
wcswidth_u32() and wcswidth_u8() for wcwidth.wcswidth(), wcstwidth_u8() for
wcwidth.wcstwidth(), and wcwidth_width_u8() for wcwidth.width(); see the C11 API.
Width of -1¶
The following have a column width of -1 for function wcwidth.wcwidth()
If any character in sequence contains C0 or C1 control characters, the final
return value of wcwidth.wcswidth() is -1, except a control character immediately following
ZWJ (U+200D), which Width of 0 consumes.
Width of 0¶
Any characters with the Default_Ignorable_Code_Point property in DerivedCoreProperties.txt, excluding U+00AD SOFT HYPHEN (width 1) and U+115F HANGUL CHOSEONG FILLER (width 2).
Any characters defined by General Category codes in DerivedGeneralCategory.txt:
‘Me’: Enclosing Mark.
‘Mn’: Nonspacing Mark.
‘Cf’: Format control characters excluding U+00AD SOFT HYPHEN and Prepended_Concatenation_Mark characters.
‘Zl’: U+2028 LINE SEPARATOR only
‘Zp’: U+2029 PARAGRAPH SEPARATOR only
Emoji Modifier Fitzpatrick symbols (U+1F3FB through U+1F3FF) are zero-width only when following an emoji base character in sequence; see Width of 2 for standalone.
The NULL character (U+0000).
ZWJ (U+200D) is zero-width, and in sequence by wcwidth.wcswidth() or
wcwidth.width() the codepoint immediately following it is consumed as zero-width.
For emoji (Extended_Pictographic property) and Regional Indicator sequences this follows the
grapheme cluster boundary rules of Unicode Standard Annex #29. After a virama, the following
consonant continues the conjunct, see Virama Conjunct Formation.
The second Regional Indicator symbol (U+1F1E6 through U+1F1FF) in a
consecutive pair, when measured in sequence by wcwidth.wcswidth() or
wcwidth.width(). The first indicator of the pair is Width of 2.
Hangul Jamo Jungseong and “Extended-B” code blocks, U+1160 through U+11FF and U+D7B0 through U+D7FF.
Any characters of category Mc (Spacing Combining Mark), for the
single-character function wcwidth.wcwidth(). When measured in sequence by
wcwidth.wcswidth(), see Width of 2.
Width of 1¶
String characters are measured width of 1 when they are not measured as Width of 0 or Width of 2.
Any character with U+FE0E (Variation Selector 15) defined as text style
in emoji-variation-sequences.txt, per UTS #51 and Unicode Standard
Section 23.4: VS15 subtracts 1 cell from the wide character it directly
follows, making the pair width 1. Narrow characters are unchanged.
Note
Variation Selector 15 width specification is contested, see https://github.com/jquast/wcwidth/issues/211
Width of 2¶
Any character defined by East Asian (Unicode Standard Annex #11) Fullwidth
(F) or Wide (W) properties in EastAsianWidth.txt, except those that
are defined by the Category codes of Nonspacing Mark (Mn) or Spacing
Combining Mark (Mc).
Regional Indicator symbols (U+1F1E6 through U+1F1FF). Though classified as Neutral in EastAsianWidth.txt, terminals universally render these as double-width. A consecutive pair of Regional Indicators forms a flag emoji and is measured as width 2 total (first indicator is 2, second is 0).
Emoji Modifier Fitzpatrick symbols (U+1F3FB through U+1F3FF) when measured standalone (not following an emoji base character). When following an emoji base, they combine with the base and add 0 to total width.
Any characters of Modifier Symbol category, 'Sk' where 'FULLWIDTH' is
present in comment of UnicodeData.txt.
Any character with U+FE0F (Variation Selector 16) defined as emoji style
in emoji-variation-sequences.txt, per UTS #51 and Unicode Standard
Section 23.4: VS16 adds 1 cell to the narrow character it directly follows,
making the pair width 2. Wide characters are unchanged.
Any character of non-zero width followed by an Mc (Spacing Combining Mark)
character when measured in sequence by wcwidth.wcswidth() or
wcwidth.width(). The Mc character caps the cluster width at 2,
reflecting its positive advance width as defined in the General Category Values
table. Zero-width combining marks (Mn) between the base character and the Mc
do not break the association. For example, a consonant followed
by a Nukta (Mn) and then a vowel sign (Mc) is measured as a cluster of
width 2.
Any grapheme cluster width is limited to 2 cells since 0.8.0, PR #224, which prevents the Mc
rule and the virama conjunct sum from exceeding 2 cells.
Virama Conjunct Formation¶
In Brahmic scripts, IndicSyllabicCategory.txt defines two categories that trigger conjunct formation between consonants: Virama (“may act as a Pure_Killer or Invisible_Stacker depending on context”) and Invisible_Stacker (“not visible by itself; causes conjunct formation or consonant stacking”, the “only as consonant stackers” category described in the Virama section header).
A
Viramacontributes 0 width.Most viramas have category
Mn, but six have categoryMc(Spacing Combining Mark): these are recognised as viramas, so they begin a conjunct.A
Consonantimmediately following aViramaadds its width to the current grapheme cluster.The cluster total is capped at 2 cells since 0.8.0, PR #224.
Mnmarks do not break conjunct context within the same aksara.ZWJ (U+200D) after a virama is consumed without breaking conjunct state, supporting explicit half-form requests (virama + ZWJ + consonant).
See also: L2/23-107 “Proper Complex Script Support in Text Terminals”, the 2023 project proposal that records the missing terminal-width standard, and L2/25-263 for the Text Terminal Working Group’s latest report.