diff --git a/evennia/objects/objects.py b/evennia/objects/objects.py index 7e742b1cbc..cf3b6279de 100644 --- a/evennia/objects/objects.py +++ b/evennia/objects/objects.py @@ -30,6 +30,7 @@ from evennia.utils.utils import ( iter_to_str, lazy_property, make_iter, + strip_extra_whitespace, to_str, variable_from_module, ) @@ -220,7 +221,9 @@ class DefaultObject(ObjectDB, metaclass=TypeclassBase): {header} |c{name}|n {desc} -{exits}{characters}{things} +{exits} +{characters} +{things} {footer} """ # on-object properties @@ -1385,7 +1388,7 @@ class DefaultObject(ObjectDB, metaclass=TypeclassBase): char.get_display_name(looker, **kwargs) for char in characters ) - return f"\n|wCharacters:|n {character_names}" if character_names else "" + return f"|wCharacters:|n {character_names}" if character_names else "" def get_display_things(self, looker, **kwargs): """ @@ -1416,7 +1419,7 @@ class DefaultObject(ObjectDB, metaclass=TypeclassBase): singular, plural = thing.get_numbered_name(nthings, looker, key=thingname) thing_names.append(singular if nthings == 1 else plural) thing_names = iter_to_str(thing_names) - return f"\n|wYou see:|n {thing_names}" if thing_names else "" + return f"|wYou see:|n {thing_names}" if thing_names else "" def get_display_footer(self, looker, **kwargs): """ @@ -1443,7 +1446,7 @@ class DefaultObject(ObjectDB, metaclass=TypeclassBase): str: The final formatted output. """ - return appearance.strip() + return strip_extra_whitespace(appearance) def return_appearance(self, looker, **kwargs): """ diff --git a/evennia/utils/utils.py b/evennia/utils/utils.py index 03d1e98a55..5ababa62d1 100644 --- a/evennia/utils/utils.py +++ b/evennia/utils/utils.py @@ -472,6 +472,31 @@ def iter_to_str(iterable, sep=",", endsep=", and", addquote=False): list_to_string = iter_to_str iter_to_string = iter_to_str +re_empty = re.compile("\n\s*\n") + +def strip_extra_whitespace(text, max_linebreaks=1, max_spacing=2): + """ + Removes extra sequential whitespace in a block of text. This will also remove any trailing + whitespace at the end. + + Args: + text (str): A string which may contain excess internal whitespace. + + Keyword args: + max_linebreaks (int): How many linebreak characters are allowed to occur in a row. + max_spacing (int): How many spaces are allowed to occur in a row. + + """ + text = text.rstrip() + # replaces any non-visible lines that are just whitespace characters with actual empty lines + # this allows the blank-line compression to eliminate them if needed + text = re_empty.sub("\n\n", text) + # replace groups of extra spaces with the maximum number of spaces + text = re.sub(f" {{{max_spacing},}}", " "*max_spacing, text) + # replace groups of extra newlines with the maximum number of newlines + text = re.sub(f"\n{{{max_linebreaks},}}", "\n"*max_linebreaks, text) + return text + def wildcard_to_regexp(instring): """