Fix formatting of nested inner evtables. Resolve #3193

This commit is contained in:
Griatch 2026-02-15 13:32:23 +01:00
parent 6fea92196d
commit 172d5162f0
3 changed files with 57 additions and 20 deletions

View file

@ -43,6 +43,7 @@
- [Fix][issue2774]: Properly support `\n` in `evennia connections` long descriptions (Griatch)
- [Fix][issue3312]: Handle all edge cases breaking `monitor/monitored` `input_funcs` (Griatch)
- [Fix][issue3154]: Persistent EvMenu caused multiple cmdsets on reload (Griatch)
- [Fix][issue3193]: Formatting of inner nested evtable would break (Griatch)
- [Doc][pull3801]: Move Evennia doc build system to latest Sphinx/myST
(PowershellNinja, also honorary mention to electroglyph)
- [Doc][pull3800]: Describe support for Telnet SSH in HAProxy documentation (holl0wstar)
@ -79,6 +80,7 @@
[issue2774]: https://github.com/evennia/evennia/issues/2774
[issue3312]: https://github.com/evennia/evennia/issues/3312
[issue3154]: https://github.com/evennia/evennia/issues/3154
[issue3193]: https://github.com/evennia/evennia/issues/3193
## Evennia 5.0.1

View file

@ -184,19 +184,17 @@ class ANSITextWrapper(TextWrapper):
'use', ' ', 'the', ' ', '-b', ' ', option!'
otherwise.
"""
# NOTE-PYTHON3: The following code only roughly approximates what this
# function used to do. Regex splitting on ANSIStrings is
# dropping ANSI codes, so we're using ANSIString.split
# for the time being.
#
# A less hackier solution would be appreciated.
chunks = _to_ansi(text).split()
chunks = [chunk + " " for chunk in chunks if chunk] # remove empty chunks
if len(chunks) > 1:
chunks[-1] = chunks[-1][0:-1]
# ANSIString.split(None) collapses repeated whitespace, which breaks
# pre-formatted content (such as nested EvTables). Split on explicit
# spaces instead and keep separators as separate chunks.
text = _to_ansi(text)
parts = text.split(" ")
chunks = []
for idx, part in enumerate(parts):
if part:
chunks.append(part)
if idx < len(parts) - 1:
chunks.append(" ")
return chunks
def _wrap_chunks(self, chunks):
@ -557,7 +555,26 @@ class EvCell:
align = self.align
hfill_char = self.hfill_char
width = self.width
return [justify(line, width, align=align, fillchar=hfill_char) for line in data]
aligned = []
for line in data:
# Preserve manually spaced/pre-formatted lines (like nested tables).
if " " in line or (line and (line[0].isspace() or line[-1].isspace())):
line_width = d_len(line)
if line_width >= width:
aligned.append(justify(line, width, align="a", fillchar=hfill_char))
continue
pad = width - line_width
if align == "r":
aligned.append(hfill_char * pad + line)
elif align == "c":
left = pad // 2
right = pad - left
aligned.append(hfill_char * left + line + hfill_char * right)
else:
aligned.append(line + hfill_char * pad)
else:
aligned.append(justify(line, width, align=align, fillchar=hfill_char))
return aligned
def _valign(self, data):
"""

View file

@ -272,18 +272,13 @@ class TestEvTable(EvenniaTestCase):
self._validate(expected, str(table))
# add by passing a column to constructor directly
colB = evtable.EvColumn("another", width=8)
table = evtable.EvTable(table=[colB], fill_char=".", pad_char="#")
self._validate(expected, str(table))
# more complex table
colA = evtable.EvColumn("this", "is", "a", "column") # no width
colB = evtable.EvColumn("and", "another", "one", "here", width=8)
table = evtable.EvTable(table=[colA, colB], fill_char=".", pad_char="#")
expected = """
@ -295,9 +290,32 @@ class TestEvTable(EvenniaTestCase):
|#column#|#here.#|
+--------+-------+
"""
self._validate(expected, str(table))
def test_nested_table_preserves_inner_spacing(self):
"""
Testing https://github.com/evennia/evennia/issues/3193
Nested EvTables should preserve spacing in inner table rows.
"""
content = [evtable.EvColumn(align="r"), evtable.EvColumn(align="l")]
content[0].add_rows("Item 1")
content[0].add_rows("Item 2")
content[1].add_rows("Item 3")
content[1].add_rows("Item 4")
left_table = evtable.EvTable(table=content, border="cells", header=False, width=24, align="l")
right_table = evtable.EvTable(
table=content, border="cells", header=False, width=24, align="r"
)
nested_table = evtable.EvTable(
table=[[left_table], [right_table]], border="incols", width=55, align="c"
)
rendered = ansi.strip_ansi(str(nested_table))
self.assertIn("| Item 1 | Item 3 |", rendered)
self.assertIn("| Item 2 | Item 4 |", rendered)
def test_width_enforcement(self):
"""
Testing https://github.com/evennia/evennia/issues/2761