Display wide characters correctly.
- Made termstr's length match the on-screen width.
- Achieved by adding a zero width character after each wide
character.
- This fixes ljust and rjust, so that there is correct padding,
otherwise Portal appearances aren't the correct width.
- When getting a sub-string containing half a wide character,
the half character is a space.
- Some wide characters are still broken. e.g. country flags
This commit is contained in:
parent
c4fb3fdfe3
commit
c91beda9b4
3 changed files with 34 additions and 7 deletions
|
|
@ -8,6 +8,7 @@ import os
|
|||
import weakref
|
||||
|
||||
import pygments.formatters.terminal256
|
||||
import cwcwidth
|
||||
|
||||
import eris.ColorMap
|
||||
import eris.terminal as terminal
|
||||
|
|
@ -130,15 +131,26 @@ def _join_lists(lists):
|
|||
return list(itertools.chain.from_iterable(lists))
|
||||
|
||||
|
||||
_ZERO_WIDTH_SPACE = chr(0x00ad)
|
||||
|
||||
|
||||
def _pad_wide_chars(str_):
|
||||
return "".join(f"{char}{_ZERO_WIDTH_SPACE}"
|
||||
if cwcwidth.wcwidth(char) == 2 else char for char in str_)
|
||||
|
||||
|
||||
class TermStr(collections.UserString):
|
||||
|
||||
def __init__(self, data, style=CharStyle()):
|
||||
try:
|
||||
self.data, self.style = data.data, data.style
|
||||
except AttributeError:
|
||||
if isinstance(style, tuple):
|
||||
self.data = data
|
||||
self.style = (style if isinstance(style, tuple)
|
||||
else (style,) * len(data))
|
||||
self.style = style
|
||||
else:
|
||||
try:
|
||||
self.data, self.style = data.data, data.style
|
||||
except AttributeError:
|
||||
self.data = _pad_wide_chars(data)
|
||||
self.style = (style,) * len(self.data)
|
||||
|
||||
@classmethod
|
||||
def from_term(cls, data):
|
||||
|
|
@ -249,7 +261,17 @@ class TermStr(collections.UserString):
|
|||
__rmul__ = __mul__
|
||||
|
||||
def __getitem__(self, index):
|
||||
return self.__class__(self.data[index], self.style[index])
|
||||
data = self.data[index]
|
||||
if len(data) == 0:
|
||||
result = ""
|
||||
else:
|
||||
first_char = " " if data[0] == _ZERO_WIDTH_SPACE else data[0]
|
||||
if len(data) == 1:
|
||||
result = first_char
|
||||
else:
|
||||
end_char = " " if cwcwidth.wcwidth(data[-1]) == 2 else data[-1]
|
||||
result = first_char + data[1:-1] + end_char
|
||||
return self.__class__(result, self.style[index])
|
||||
|
||||
def join(self, parts):
|
||||
parts = [TermStr(part) if isinstance(part, str) else part
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue