Skip to content

Commit d27d366

Browse files
committed
Fix breaking up of long words so it doesn't mess up ANSI escape codes.
1 parent d19c2fb commit d27d366

File tree

2 files changed

+10
-7
lines changed

2 files changed

+10
-7
lines changed

tabulate/__init__.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2540,16 +2540,19 @@ def _handle_long_word(self, reversed_chunks, cur_line, cur_len, width):
25402540
# take each charcter's width into account
25412541
chunk = reversed_chunks[-1]
25422542
i = 1
2543+
# Only count printable characters, so strip_ansi first, index later.
25432544
while len(_strip_ansi(chunk)[:i]) <= space_left:
25442545
i = i + 1
25452546
# Consider escape codes when breaking words up
25462547
total_escape_len = 0
2548+
last_group = 0
25472549
if _ansi_codes.search(chunk) is not None:
25482550
for group, _, _, _ in _ansi_codes.findall(chunk):
25492551
escape_len = len(group)
2550-
# FIXME: Needs to keep track of found groups and search from there
2551-
if group in chunk[: i + total_escape_len + escape_len - 1]:
2552+
if group in chunk[last_group: i + total_escape_len + escape_len - 1]:
25522553
total_escape_len += escape_len
2554+
found = _ansi_codes.search(chunk[last_group:])
2555+
last_group += found.end()
25532556
cur_line.append(chunk[: i + total_escape_len - 1])
25542557
reversed_chunks[-1] = chunk[i + total_escape_len - 1 :]
25552558

test/test_textwrapper.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -177,23 +177,23 @@ def test_wrap_color_line_longword():
177177

178178

179179
def test_wrap_color_line_multiple_escapes():
180-
data = '012345(\x1b[32ma\x1b[0mbc\x1b[32mdefghij\x1b[0m)'
180+
data = "012345(\x1b[32ma\x1b[0mbc\x1b[32mdefghij\x1b[0m)"
181181
expected = [
182-
"012345(\x1b[32ma\x1b[0mbc\x1b[32mdefg\x1b[0m",
183-
"\x1b[32mhij\x1b[0m)",
182+
"012345(\x1b[32ma\x1b[0mbc\x1b[32m\x1b[0m",
183+
"\x1b[32mdefghij\x1b[0m)",
184184
]
185185
wrapper = CTW(width=10)
186186
result = wrapper.wrap(data)
187187
assert_equal(expected, result)
188+
188189
clean_data = _strip_ansi(data)
189190
for width in range(2, len(clean_data)):
190-
# Currently fails with 14, 15 and 16, because a escape code gets split at the end
191191
wrapper = CTW(width=width)
192192
result = wrapper.wrap(data)
193-
# print(width, result)
194193
# Comparing after stripping ANSI should be enough to catch broken escape codes
195194
assert_equal(clean_data, _strip_ansi("".join(result)))
196195

196+
197197
def test_wrap_datetime():
198198
"""TextWrapper: Show that datetimes can be wrapped without crashing"""
199199
data = [

0 commit comments

Comments
 (0)