kopia lustrzana https://github.com/ihabunek/toot
Consolidate wcwidth-related utils in one module
rodzic
769ff9e406
commit
8a3ff94e47
|
@ -1,5 +1,4 @@
|
||||||
from toot import utils
|
from toot.wcstring import wc_wrap, trunc, pad, fit_text
|
||||||
from toot.wcstring import wc_wrap
|
|
||||||
|
|
||||||
|
|
||||||
def test_pad():
|
def test_pad():
|
||||||
|
@ -8,72 +7,72 @@ def test_pad():
|
||||||
text = 'Frank Zappa 🎸'
|
text = 'Frank Zappa 🎸'
|
||||||
|
|
||||||
# Negative values are basically ignored
|
# Negative values are basically ignored
|
||||||
assert utils.pad(text, -100) is text
|
assert pad(text, -100) is text
|
||||||
|
|
||||||
# Padding to length smaller than text length does nothing
|
# Padding to length smaller than text length does nothing
|
||||||
assert utils.pad(text, 11) is text
|
assert pad(text, 11) is text
|
||||||
assert utils.pad(text, 12) is text
|
assert pad(text, 12) is text
|
||||||
assert utils.pad(text, 13) is text
|
assert pad(text, 13) is text
|
||||||
assert utils.pad(text, 14) is text
|
assert pad(text, 14) is text
|
||||||
|
|
||||||
assert utils.pad(text, 15) == 'Frank Zappa 🎸 '
|
assert pad(text, 15) == 'Frank Zappa 🎸 '
|
||||||
assert utils.pad(text, 16) == 'Frank Zappa 🎸 '
|
assert pad(text, 16) == 'Frank Zappa 🎸 '
|
||||||
assert utils.pad(text, 17) == 'Frank Zappa 🎸 '
|
assert pad(text, 17) == 'Frank Zappa 🎸 '
|
||||||
assert utils.pad(text, 18) == 'Frank Zappa 🎸 '
|
assert pad(text, 18) == 'Frank Zappa 🎸 '
|
||||||
assert utils.pad(text, 19) == 'Frank Zappa 🎸 '
|
assert pad(text, 19) == 'Frank Zappa 🎸 '
|
||||||
assert utils.pad(text, 20) == 'Frank Zappa 🎸 '
|
assert pad(text, 20) == 'Frank Zappa 🎸 '
|
||||||
|
|
||||||
|
|
||||||
def test_trunc():
|
def test_trunc():
|
||||||
text = 'Frank Zappa 🎸'
|
text = 'Frank Zappa 🎸'
|
||||||
|
|
||||||
assert utils.trunc(text, 1) == '…'
|
assert trunc(text, 1) == '…'
|
||||||
assert utils.trunc(text, 2) == 'F…'
|
assert trunc(text, 2) == 'F…'
|
||||||
assert utils.trunc(text, 3) == 'Fr…'
|
assert trunc(text, 3) == 'Fr…'
|
||||||
assert utils.trunc(text, 4) == 'Fra…'
|
assert trunc(text, 4) == 'Fra…'
|
||||||
assert utils.trunc(text, 5) == 'Fran…'
|
assert trunc(text, 5) == 'Fran…'
|
||||||
assert utils.trunc(text, 6) == 'Frank…'
|
assert trunc(text, 6) == 'Frank…'
|
||||||
assert utils.trunc(text, 7) == 'Frank…'
|
assert trunc(text, 7) == 'Frank…'
|
||||||
assert utils.trunc(text, 8) == 'Frank Z…'
|
assert trunc(text, 8) == 'Frank Z…'
|
||||||
assert utils.trunc(text, 9) == 'Frank Za…'
|
assert trunc(text, 9) == 'Frank Za…'
|
||||||
assert utils.trunc(text, 10) == 'Frank Zap…'
|
assert trunc(text, 10) == 'Frank Zap…'
|
||||||
assert utils.trunc(text, 11) == 'Frank Zapp…'
|
assert trunc(text, 11) == 'Frank Zapp…'
|
||||||
assert utils.trunc(text, 12) == 'Frank Zappa…'
|
assert trunc(text, 12) == 'Frank Zappa…'
|
||||||
assert utils.trunc(text, 13) == 'Frank Zappa…'
|
assert trunc(text, 13) == 'Frank Zappa…'
|
||||||
|
|
||||||
# Truncating to length larger than text length does nothing
|
# Truncating to length larger than text length does nothing
|
||||||
assert utils.trunc(text, 14) is text
|
assert trunc(text, 14) is text
|
||||||
assert utils.trunc(text, 15) is text
|
assert trunc(text, 15) is text
|
||||||
assert utils.trunc(text, 16) is text
|
assert trunc(text, 16) is text
|
||||||
assert utils.trunc(text, 17) is text
|
assert trunc(text, 17) is text
|
||||||
assert utils.trunc(text, 18) is text
|
assert trunc(text, 18) is text
|
||||||
assert utils.trunc(text, 19) is text
|
assert trunc(text, 19) is text
|
||||||
assert utils.trunc(text, 20) is text
|
assert trunc(text, 20) is text
|
||||||
|
|
||||||
|
|
||||||
def test_fit_text():
|
def test_fit_text():
|
||||||
text = 'Frank Zappa 🎸'
|
text = 'Frank Zappa 🎸'
|
||||||
|
|
||||||
assert utils.fit_text(text, 1) == '…'
|
assert fit_text(text, 1) == '…'
|
||||||
assert utils.fit_text(text, 2) == 'F…'
|
assert fit_text(text, 2) == 'F…'
|
||||||
assert utils.fit_text(text, 3) == 'Fr…'
|
assert fit_text(text, 3) == 'Fr…'
|
||||||
assert utils.fit_text(text, 4) == 'Fra…'
|
assert fit_text(text, 4) == 'Fra…'
|
||||||
assert utils.fit_text(text, 5) == 'Fran…'
|
assert fit_text(text, 5) == 'Fran…'
|
||||||
assert utils.fit_text(text, 6) == 'Frank…'
|
assert fit_text(text, 6) == 'Frank…'
|
||||||
assert utils.fit_text(text, 7) == 'Frank…'
|
assert fit_text(text, 7) == 'Frank…'
|
||||||
assert utils.fit_text(text, 8) == 'Frank Z…'
|
assert fit_text(text, 8) == 'Frank Z…'
|
||||||
assert utils.fit_text(text, 9) == 'Frank Za…'
|
assert fit_text(text, 9) == 'Frank Za…'
|
||||||
assert utils.fit_text(text, 10) == 'Frank Zap…'
|
assert fit_text(text, 10) == 'Frank Zap…'
|
||||||
assert utils.fit_text(text, 11) == 'Frank Zapp…'
|
assert fit_text(text, 11) == 'Frank Zapp…'
|
||||||
assert utils.fit_text(text, 12) == 'Frank Zappa…'
|
assert fit_text(text, 12) == 'Frank Zappa…'
|
||||||
assert utils.fit_text(text, 13) == 'Frank Zappa…'
|
assert fit_text(text, 13) == 'Frank Zappa…'
|
||||||
assert utils.fit_text(text, 14) == 'Frank Zappa 🎸'
|
assert fit_text(text, 14) == 'Frank Zappa 🎸'
|
||||||
assert utils.fit_text(text, 15) == 'Frank Zappa 🎸 '
|
assert fit_text(text, 15) == 'Frank Zappa 🎸 '
|
||||||
assert utils.fit_text(text, 16) == 'Frank Zappa 🎸 '
|
assert fit_text(text, 16) == 'Frank Zappa 🎸 '
|
||||||
assert utils.fit_text(text, 17) == 'Frank Zappa 🎸 '
|
assert fit_text(text, 17) == 'Frank Zappa 🎸 '
|
||||||
assert utils.fit_text(text, 18) == 'Frank Zappa 🎸 '
|
assert fit_text(text, 18) == 'Frank Zappa 🎸 '
|
||||||
assert utils.fit_text(text, 19) == 'Frank Zappa 🎸 '
|
assert fit_text(text, 19) == 'Frank Zappa 🎸 '
|
||||||
assert utils.fit_text(text, 20) == 'Frank Zappa 🎸 '
|
assert fit_text(text, 20) == 'Frank Zappa 🎸 '
|
||||||
|
|
||||||
|
|
||||||
def test_wc_wrap_plain_text():
|
def test_wc_wrap_plain_text():
|
||||||
|
|
|
@ -7,7 +7,6 @@ import unicodedata
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
from wcwidth import wcwidth, wcswidth
|
|
||||||
|
|
||||||
from toot.exceptions import ConsoleError
|
from toot.exceptions import ConsoleError
|
||||||
|
|
||||||
|
@ -76,61 +75,6 @@ def assert_domain_exists(domain):
|
||||||
raise ConsoleError("Domain {} not found".format(domain))
|
raise ConsoleError("Domain {} not found".format(domain))
|
||||||
|
|
||||||
|
|
||||||
def trunc(text, length):
|
|
||||||
"""
|
|
||||||
Truncates text to given length, taking into account wide characters.
|
|
||||||
|
|
||||||
If truncated, the last char is replaced by an elipsis.
|
|
||||||
"""
|
|
||||||
if length < 1:
|
|
||||||
raise ValueError("length should be 1 or larger")
|
|
||||||
|
|
||||||
# Remove whitespace first so no unneccesary truncation is done.
|
|
||||||
text = text.strip()
|
|
||||||
text_length = wcswidth(text)
|
|
||||||
|
|
||||||
if text_length <= length:
|
|
||||||
return text
|
|
||||||
|
|
||||||
# We cannot just remove n characters from the end since we don't know how
|
|
||||||
# wide these characters are and how it will affect text length.
|
|
||||||
# Use wcwidth to determine how many characters need to be truncated.
|
|
||||||
chars_to_truncate = 0
|
|
||||||
trunc_length = 0
|
|
||||||
for char in reversed(text):
|
|
||||||
chars_to_truncate += 1
|
|
||||||
trunc_length += wcwidth(char)
|
|
||||||
if text_length - trunc_length <= length:
|
|
||||||
break
|
|
||||||
|
|
||||||
# Additional char to make room for elipsis
|
|
||||||
n = chars_to_truncate + 1
|
|
||||||
return text[:-n].strip() + '…'
|
|
||||||
|
|
||||||
|
|
||||||
def pad(text, length):
|
|
||||||
"""Pads text to given length, taking into account wide characters."""
|
|
||||||
text_length = wcswidth(text)
|
|
||||||
|
|
||||||
if text_length < length:
|
|
||||||
return text + ' ' * (length - text_length)
|
|
||||||
|
|
||||||
return text
|
|
||||||
|
|
||||||
|
|
||||||
def fit_text(text, length):
|
|
||||||
"""Makes text fit the given length by padding or truncating it."""
|
|
||||||
text_length = wcswidth(text)
|
|
||||||
|
|
||||||
if text_length > length:
|
|
||||||
return trunc(text, length)
|
|
||||||
|
|
||||||
if text_length < length:
|
|
||||||
return pad(text, length)
|
|
||||||
|
|
||||||
return text
|
|
||||||
|
|
||||||
|
|
||||||
EOF_KEY = "Ctrl-Z" if os.name == 'nt' else "Ctrl-D"
|
EOF_KEY = "Ctrl-Z" if os.name == 'nt' else "Ctrl-D"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -64,3 +64,58 @@ def wc_wrap(text, length):
|
||||||
yield line
|
yield line
|
||||||
else:
|
else:
|
||||||
yield from _wc_hard_wrap(line, length)
|
yield from _wc_hard_wrap(line, length)
|
||||||
|
|
||||||
|
|
||||||
|
def trunc(text, length):
|
||||||
|
"""
|
||||||
|
Truncates text to given length, taking into account wide characters.
|
||||||
|
|
||||||
|
If truncated, the last char is replaced by an elipsis.
|
||||||
|
"""
|
||||||
|
if length < 1:
|
||||||
|
raise ValueError("length should be 1 or larger")
|
||||||
|
|
||||||
|
# Remove whitespace first so no unneccesary truncation is done.
|
||||||
|
text = text.strip()
|
||||||
|
text_length = wcswidth(text)
|
||||||
|
|
||||||
|
if text_length <= length:
|
||||||
|
return text
|
||||||
|
|
||||||
|
# We cannot just remove n characters from the end since we don't know how
|
||||||
|
# wide these characters are and how it will affect text length.
|
||||||
|
# Use wcwidth to determine how many characters need to be truncated.
|
||||||
|
chars_to_truncate = 0
|
||||||
|
trunc_length = 0
|
||||||
|
for char in reversed(text):
|
||||||
|
chars_to_truncate += 1
|
||||||
|
trunc_length += wcwidth(char)
|
||||||
|
if text_length - trunc_length <= length:
|
||||||
|
break
|
||||||
|
|
||||||
|
# Additional char to make room for elipsis
|
||||||
|
n = chars_to_truncate + 1
|
||||||
|
return text[:-n].strip() + '…'
|
||||||
|
|
||||||
|
|
||||||
|
def pad(text, length):
|
||||||
|
"""Pads text to given length, taking into account wide characters."""
|
||||||
|
text_length = wcswidth(text)
|
||||||
|
|
||||||
|
if text_length < length:
|
||||||
|
return text + ' ' * (length - text_length)
|
||||||
|
|
||||||
|
return text
|
||||||
|
|
||||||
|
|
||||||
|
def fit_text(text, length):
|
||||||
|
"""Makes text fit the given length by padding or truncating it."""
|
||||||
|
text_length = wcswidth(text)
|
||||||
|
|
||||||
|
if text_length > length:
|
||||||
|
return trunc(text, length)
|
||||||
|
|
||||||
|
if text_length < length:
|
||||||
|
return pad(text, length)
|
||||||
|
|
||||||
|
return text
|
||||||
|
|
Ładowanie…
Reference in New Issue