Skip to content

Commit 9890da9

Browse files
authored
Merge pull request astanin#58 from chrd5273/multiline_full_width
wide character support in multi-line item fix astanin#28 (?)
2 parents 2effb3d + 94e6757 commit 9890da9

File tree

1 file changed

+39
-6
lines changed

1 file changed

+39
-6
lines changed

tabulate.py

100755100644
Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -821,6 +821,36 @@ def _align_column_choose_padfn(strings, alignment, has_invisible):
821821
return strings, padfn
822822

823823

824+
def _align_column_choose_width_fn(has_invisible, enable_widechars, is_multiline):
825+
if has_invisible:
826+
line_width_fn = _visible_width
827+
elif enable_widechars: # optional wide-character support if available
828+
line_width_fn = wcwidth.wcswidth
829+
else:
830+
line_width_fn = len
831+
if is_multiline:
832+
width_fn = lambda s: _align_column_multiline_width(s, line_width_fn) # noqa
833+
else:
834+
width_fn = line_width_fn
835+
return width_fn
836+
837+
838+
def _align_column_multiline_width(multiline_s, line_width_fn=len):
839+
"""Visible width of a potentially multiline content."""
840+
return list(map(line_width_fn, re.split("[\r\n]", multiline_s)))
841+
842+
843+
def _flat_list(nested_list):
844+
ret = []
845+
for item in nested_list:
846+
if isinstance(item, list):
847+
for subitem in item:
848+
ret.append(subitem)
849+
else:
850+
ret.append(item)
851+
return ret
852+
853+
824854
def _align_column(
825855
strings,
826856
alignment,
@@ -831,10 +861,10 @@ def _align_column(
831861
):
832862
"""[string] -> [padded_string]"""
833863
strings, padfn = _align_column_choose_padfn(strings, alignment, has_invisible)
834-
width_fn = _choose_width_fn(has_invisible, enable_widechars, is_multiline)
864+
width_fn = _align_column_choose_width_fn(has_invisible, enable_widechars, is_multiline)
835865

836866
s_widths = list(map(width_fn, strings))
837-
maxwidth = max(max(s_widths), minwidth)
867+
maxwidth = max(max(_flat_list(s_widths)), minwidth)
838868
# TODO: refactor column alignment in single-line and multiline modes
839869
if is_multiline:
840870
if not enable_widechars and not has_invisible:
@@ -844,13 +874,16 @@ def _align_column(
844874
]
845875
else:
846876
# enable wide-character width corrections
847-
s_lens = [max((len(s) for s in re.split("[\r\n]", ms))) for ms in strings]
848-
visible_widths = [maxwidth - (w - l) for w, l in zip(s_widths, s_lens)]
877+
s_lens = [[len(s) for s in re.split("[\r\n]", ms)] for ms in strings]
878+
visible_widths = [
879+
[maxwidth - (w - l) for w, l in zip(mw, ml)]
880+
for mw, ml in zip(s_widths, s_lens)
881+
]
849882
# wcswidth and _visible_width don't count invisible characters;
850883
# padfn doesn't need to apply another correction
851884
padded_strings = [
852-
"\n".join([padfn(w, s) for s in (ms.splitlines() or ms)])
853-
for ms, w in zip(strings, visible_widths)
885+
"\n".join([padfn(w, s) for s, w in zip((ms.splitlines() or ms), mw)])
886+
for ms, mw in zip(strings, visible_widths)
854887
]
855888
else: # single-line cell values
856889
if not enable_widechars and not has_invisible:

0 commit comments

Comments
 (0)