mirror of
https://github.com/evennia/evennia.git
synced 2026-04-07 00:45:22 +02:00
Fix bugs in format_grid, include verbatim elements
This commit is contained in:
parent
a863ff77db
commit
458df00272
4 changed files with 67 additions and 61 deletions
|
|
@ -14,6 +14,7 @@ from evennia.utils.utils import fill, dedent
|
|||
from evennia.commands.command import Command
|
||||
from evennia.help.models import HelpEntry
|
||||
from evennia.utils import create, evmore
|
||||
from evennia.utils.ansi import ANSIString
|
||||
from evennia.utils.eveditor import EvEditor
|
||||
from evennia.utils.utils import string_suggestions, class_from_module, inherits_from, format_grid
|
||||
|
||||
|
|
@ -40,6 +41,7 @@ class HelpCategory:
|
|||
"tags": "",
|
||||
"text": ""
|
||||
}
|
||||
|
||||
def __str__(self):
|
||||
return f"Category: {self.key}"
|
||||
|
||||
|
|
@ -178,39 +180,27 @@ class CmdHelp(Command):
|
|||
string += "\n" + _SEP
|
||||
return string
|
||||
|
||||
@staticmethod
|
||||
def format_help_list(hdict_cmds, hdict_db):
|
||||
def format_help_list(self, hdict_cmds, hdict_db):
|
||||
"""
|
||||
Output a category-ordered list. The input are the
|
||||
pre-loaded help files for commands and database-helpfiles
|
||||
respectively. You can override this method to return a
|
||||
custom display of the list of commands and topics.
|
||||
"""
|
||||
output = []
|
||||
width = self.client_width()
|
||||
grid = []
|
||||
verbatim_elements = []
|
||||
for category in sorted(set(list(hdict_cmds.keys()) + list(hdict_db.keys()))):
|
||||
output.append(f"|w{category.title()}|G")
|
||||
|
||||
category_str = f"-- {category.title()} "
|
||||
grid.append(ANSIString("|w" + category_str + "-" * (width - len(category_str)) + "|G"))
|
||||
verbatim_elements.append(len(grid) - 1)
|
||||
|
||||
entries = sorted(set(hdict_cmds.get(category, []) + hdict_db.get(category, [])))
|
||||
output.append(format_grid(entries, width=78)) # self.client_width()))
|
||||
return "\n".join(output)
|
||||
grid.extend(entries)
|
||||
|
||||
string = ""
|
||||
if hdict_cmds and any(hdict_cmds.values()):
|
||||
string += "\n" + _SEP + "\n |CCommand help entries|n\n" + _SEP
|
||||
for category in sorted(hdict_cmds.keys()):
|
||||
string += "\n |w%s|n:\n" % (str(category).title())
|
||||
string += "|G" + fill("|C, |G".join(sorted(hdict_cmds[category]))) + "|n"
|
||||
|
||||
if hdict_db and any(hdict_db.values()):
|
||||
string += "\n\n" + _SEP + "\n\r |COther help entries|n\n" + _SEP
|
||||
for category in sorted(hdict_db.keys()):
|
||||
string += "\n\r |w%s|n:\n" % (str(category).title())
|
||||
string += (
|
||||
"|G"
|
||||
+ fill(", ".join(sorted([str(topic) for topic in hdict_db[category]])))
|
||||
+ "|n"
|
||||
)
|
||||
|
||||
return string
|
||||
gridrows = format_grid(grid, width, sep=" ", verbatim_elements=verbatim_elements)
|
||||
return "\n".join(gridrows)
|
||||
|
||||
def check_show_help(self, cmd, caller):
|
||||
"""
|
||||
|
|
@ -320,9 +310,9 @@ class CmdHelp(Command):
|
|||
if isinstance(match, HelpCategory):
|
||||
formatted = self.format_help_list(
|
||||
{match.key: [cmd.key for cmd in all_cmds
|
||||
if match.key.lower() == cmd.help_category]},
|
||||
if match.key.lower() == cmd.help_category]},
|
||||
{match.key: [topic.key for topic in all_topics
|
||||
if match.key.lower() == topic.help_category]}
|
||||
if match.key.lower() == topic.help_category]}
|
||||
)
|
||||
elif inherits_from(match, "evennia.commands.command.Command"):
|
||||
formatted = self.format_help_entry(
|
||||
|
|
|
|||
|
|
@ -298,7 +298,7 @@ class EvMore(object):
|
|||
nsize = len(inp)
|
||||
self._npages = nsize // self.height + (0 if nsize % self.height == 0 else 1)
|
||||
self._data = inp
|
||||
self._paginator_slice
|
||||
self._paginator = self.paginator_slice
|
||||
|
||||
def init_f_str(self, text):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -289,8 +289,6 @@ class TestFormatGrid(TestCase):
|
|||
elements = self._generate_elements(3, 1, 30)
|
||||
result = utils.format_grid(elements, width=78)
|
||||
rows = result.split("\n")
|
||||
for row in rows:
|
||||
print(f"'{row}'")
|
||||
self.assertEqual(len(rows), 3)
|
||||
self.assertTrue(all(len(row) == 78 for row in rows))
|
||||
|
||||
|
|
@ -299,20 +297,14 @@ class TestFormatGrid(TestCase):
|
|||
elements = self._generate_elements(3, 15, 30)
|
||||
result = utils.format_grid(elements, width=82, sep=" ")
|
||||
rows = result.split("\n")
|
||||
for row in rows:
|
||||
print(f"'{row}'")
|
||||
self.assertEqual(len(rows), 8)
|
||||
self.assertTrue(all(len(row) == 82 for row in rows))
|
||||
|
||||
def test_huge_grid(self):
|
||||
"""Grid with very long strings"""
|
||||
# from pudb import debugger
|
||||
# debugger.Debugger().set_trace()
|
||||
elements = self._generate_elements(70, 20, 30)
|
||||
result = utils.format_grid(elements, width=78)
|
||||
rows = result.split("\n")
|
||||
for row in rows:
|
||||
print(f"'{row}'")
|
||||
self.assertEqual(len(rows), 30)
|
||||
self.assertTrue(all(len(row) == 78 for row in rows))
|
||||
|
||||
|
|
@ -324,7 +316,18 @@ class TestFormatGrid(TestCase):
|
|||
result = utils.format_grid(elements, width=78)
|
||||
rows = result.split("\n")
|
||||
self.assertEqual(len(rows), 2)
|
||||
for row in rows:
|
||||
print(f"'{row}'")
|
||||
for element in elements:
|
||||
self.assertTrue(element in result, f"element {element} is missing.")
|
||||
|
||||
def test_breakline(self):
|
||||
"""Grid with line-long elements in middle"""
|
||||
elements = self._generate_elements(6, 4, 30)
|
||||
elements[10] = elements[20] = "-" * 78
|
||||
# from pudb import debugger
|
||||
# debugger.Debugger().set_trace()
|
||||
result = utils.format_grid(elements, width=78)
|
||||
rows = result.split("\n")
|
||||
self.assertEqual(len(rows), 8)
|
||||
for element in elements:
|
||||
self.assertTrue(element in result, f"element {element} is missing.")
|
||||
|
||||
|
|
|
|||
|
|
@ -153,6 +153,7 @@ def crop(text, width=None, suffix="[...]"):
|
|||
if ltext <= width:
|
||||
return text
|
||||
else:
|
||||
from evennia import set_trace;set_trace()
|
||||
lsuffix = len(suffix)
|
||||
text = text[:width] if lsuffix >= width else "%s%s" % (text[: width - lsuffix], suffix)
|
||||
return to_str(text)
|
||||
|
|
@ -1713,7 +1714,7 @@ def percentile(iterable, percent, key=lambda x: x):
|
|||
return d0 + d1
|
||||
|
||||
|
||||
def format_grid(elements, width=78, sep=" "):
|
||||
def format_grid(elements, width=78, sep=" ", verbatim_elements=None):
|
||||
"""
|
||||
This helper function makes a 'grid' output, where it distributes the given
|
||||
string-elements as evenly as possible to fill out the given width.
|
||||
|
|
@ -1723,52 +1724,63 @@ def format_grid(elements, width=78, sep=" "):
|
|||
elements (iterable): A 1D list of string elements to put in the grid.
|
||||
width (int, optional): The width of the grid area to fill.
|
||||
sep (str, optional): The extra separator to put between words. If
|
||||
set to the empty string, words may run into each other
|
||||
set to the empty string, words may run into each other.
|
||||
verbatim_elements (list, optional): This is a list of indices pointing to
|
||||
specific items in the `elements` list. An element at this index will
|
||||
not be included in the calculation of the slot sizes. It will still
|
||||
be inserted into the grid at the correct position and may be surrounded
|
||||
by padding unless filling the entire line. This is useful for embedding
|
||||
decorations in the grid, such as horizontal bars.
|
||||
|
||||
Returns:
|
||||
gridstr (str): The grid as a finished renderede multi-line string.
|
||||
|
||||
gridstr (list): The grid as a list of ready-formatted rows. We return it
|
||||
like this to make it easier to insert decorations between rows, such
|
||||
as horizontal bars.
|
||||
"""
|
||||
nelements = len(elements)
|
||||
elements = [elements[ie] + sep for ie in range(nelements - 1)] + [elements[-1]]
|
||||
if not verbatim_elements:
|
||||
verbatim_elements = []
|
||||
|
||||
nelements = len(elements)
|
||||
# add sep to all but the very last element
|
||||
elements = [elements[ie] + sep for ie in range(nelements - 1)] + [elements[-1]]
|
||||
wls = [len(elem) for elem in elements]
|
||||
wls_percentile = [wl for iw, wl in enumerate(wls) if iw not in verbatim_elements]
|
||||
|
||||
# get the nth percentile as a good representation of average width
|
||||
averlen = int(percentile(sorted(wls), 0.9)) + 2 # include extra space
|
||||
averlen = int(percentile(sorted(wls_percentile), 0.9)) + 2 # include extra space
|
||||
aver_per_row = width // averlen + 1
|
||||
|
||||
if aver_per_row == 1:
|
||||
# one line per row, output directly since this is trivial
|
||||
# we use rstrip here to remove extra spaces added by sep
|
||||
return "\n".join(
|
||||
crop(element.rstrip(), width) + " " * max(0, width - len(element.rstrip()))
|
||||
for iel, element in enumerate(elements)
|
||||
)
|
||||
|
||||
indices = [averlen * ind for ind in range(aver_per_row - 1)]
|
||||
|
||||
rows = []
|
||||
ic = 0
|
||||
row = ""
|
||||
for ie, element in enumerate(elements):
|
||||
|
||||
wl = wls[ie]
|
||||
lrow = len(row)
|
||||
debug = row.replace(" ", ".")
|
||||
|
||||
if lrow + wl > width:
|
||||
# last slot extends outside grid, move to next line
|
||||
# this slot extends outside grid, move to next line
|
||||
row += " " * (width - lrow)
|
||||
rows.append(row)
|
||||
if wl >= width:
|
||||
# remove sep if this fills the entire line
|
||||
element = element.rstrip()
|
||||
row = crop(element, width)
|
||||
ic = 0
|
||||
elif ic >= aver_per_row - 1:
|
||||
# last slot on the line
|
||||
if ic == 0:
|
||||
# one slot per line
|
||||
row = crop(element, width)
|
||||
row += " " * max(0, (width - len(row)))
|
||||
rows.append(row)
|
||||
else:
|
||||
# finish line, put slot on next line
|
||||
row += " " * max(0, (width - lrow))
|
||||
rows.append(row)
|
||||
row = crop(element, width)
|
||||
ic = 0
|
||||
elif lrow + wl > width:
|
||||
# last slot extends outside grid, move to next line
|
||||
row += " " * (width - lrow)
|
||||
# no more slots available on this line
|
||||
row += " " * max(0, (width - lrow))
|
||||
rows.append(row)
|
||||
row = crop(element, width)
|
||||
ic = 0
|
||||
|
|
@ -1793,9 +1805,10 @@ def format_grid(elements, width=78, sep=" "):
|
|||
|
||||
if ie >= nelements - 1:
|
||||
# last element, make sure to store
|
||||
row += " " * max(0, width - len(row))
|
||||
rows.append(row)
|
||||
|
||||
return "\n".join(rows)
|
||||
return rows
|
||||
|
||||
|
||||
def get_evennia_pids():
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue