-
Notifications
You must be signed in to change notification settings - Fork 62
Description
Problem
As for the need for "width" function, just about every downstream library has some issue with the POSIX wcwidth() and wcswidth() functions, either in C or in this python library.
This is mainly because both functions may return -1, and the return value must be checked, but it often is not.
Although using wcswidth() on a string is the most popular use case, it has the possibility to return -1 by POSIX definition, and Markus Kuhn's 2007 implementation returns -1 for control characters.
The return value is often unchecked where it is used with sum(), slice() or screen positioning functions with surprising results.
Solution
Provide new function signature, width that always returns a "best effort" of measured distance. It may ignore or measure control codes, instead. If "catching unexpected control codes" is a desired function, we can continue to provide it as an optional keyword argument, and, rather than return -1, raise an exception.
Maybe new keyword argument control_codes with default argument 'ignore', in similar spirit to 'errors' for https://docs.python.org/3/library/stdtypes.html#bytes.decode,
- 'ignore': measure all individual control codes and terminal sequences as 0 width.
- 'strict': raise ValueError on any control codes.
- 'replace': make best effort to account for horizontal width movement in terminal sequences.
Workaround
As a workaround, I have suggested to use wcwidth() directly on each individual character and clip the possible -1 return value to 0, example: https://github.com/jquast/blessed/blob/a34c6b1869b4dd467c6d1ab6895872bb72db7e0f/blessed/sequences.py#L364
This provides the same function as wcswidth but provides a "best guess", however, this method cannot handle coming changes to wcswidth to handle zero width joiner (ZWJ) sequences.