mirror of
https://github.com/evennia/evennia.git
synced 2026-03-25 01:06:32 +01:00
Make utils.justify handle ANSIString properly. Resolve #2986
This commit is contained in:
parent
20520d99d5
commit
da03b22e1c
4 changed files with 52 additions and 12 deletions
|
|
@ -118,7 +118,6 @@ from copy import copy, deepcopy
|
|||
from textwrap import TextWrapper
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
from evennia.utils.ansi import ANSIString
|
||||
from evennia.utils.utils import display_len as d_len
|
||||
from evennia.utils.utils import is_iter, justify
|
||||
|
|
|
|||
|
|
@ -330,3 +330,20 @@ class TestEvTable(EvenniaTestCase):
|
|||
"""
|
||||
|
||||
self._validate(expected, str(table))
|
||||
|
||||
def test_color_transfer(self):
|
||||
"""
|
||||
Testing https://github.com/evennia/evennia/issues/2986
|
||||
|
||||
EvTable swallowing color tags.
|
||||
|
||||
"""
|
||||
from evennia.utils.ansi import ANSI_CYAN, ANSI_RED
|
||||
|
||||
row1 = "|cAn entire colored row|n"
|
||||
row2 = "A single |rred|n word"
|
||||
|
||||
table = evtable.EvTable(table=[[row1, row2]])
|
||||
|
||||
self.assertIn(ANSI_RED, str(table))
|
||||
self.assertIn(ANSI_CYAN, str(table))
|
||||
|
|
|
|||
|
|
@ -11,12 +11,11 @@ from datetime import datetime, timedelta
|
|||
|
||||
import mock
|
||||
from django.test import TestCase
|
||||
from parameterized import parameterized
|
||||
from twisted.internet import task
|
||||
|
||||
from evennia.utils import utils
|
||||
from evennia.utils.ansi import ANSIString
|
||||
from evennia.utils.test_resources import BaseEvenniaTest
|
||||
from parameterized import parameterized
|
||||
from twisted.internet import task
|
||||
|
||||
|
||||
class TestIsIter(TestCase):
|
||||
|
|
@ -759,3 +758,17 @@ class TestJustify(TestCase):
|
|||
def test_center_justify_small(self, width, expected):
|
||||
result = utils.justify("Task ID", width, align="c", indent=0, fillchar=" ")
|
||||
self.assertEqual(expected, result)
|
||||
|
||||
def test_justify_ansi(self):
|
||||
"""
|
||||
Justify ansistring
|
||||
|
||||
"""
|
||||
|
||||
from evennia.utils.ansi import ANSI_RED
|
||||
|
||||
line = ANSIString("This is a |rred|n word")
|
||||
|
||||
result = utils.justify(line, align="c", width=30)
|
||||
|
||||
self.assertIn(ANSI_RED, str(result))
|
||||
|
|
|
|||
|
|
@ -34,13 +34,12 @@ from django.core.validators import validate_email as django_validate_email
|
|||
from django.utils import timezone
|
||||
from django.utils.html import strip_tags
|
||||
from django.utils.translation import gettext as _
|
||||
from evennia.utils import logger
|
||||
from simpleeval import simple_eval
|
||||
from twisted.internet import reactor, threads
|
||||
from twisted.internet.defer import returnValue # noqa - used as import target
|
||||
from twisted.internet.task import deferLater
|
||||
|
||||
from evennia.utils import logger
|
||||
|
||||
_MULTIMATCH_TEMPLATE = settings.SEARCH_MULTIMATCH_TEMPLATE
|
||||
_EVENNIA_DIR = settings.EVENNIA_DIR
|
||||
_GAME_DIR = settings.GAME_DIR
|
||||
|
|
@ -51,6 +50,7 @@ ENCODINGS = settings.ENCODINGS
|
|||
_TASK_HANDLER = None
|
||||
_TICKER_HANDLER = None
|
||||
_STRIP_UNSAFE_TOKENS = None
|
||||
_ANSISTRING = None
|
||||
|
||||
_GA = object.__getattribute__
|
||||
_SA = object.__setattr__
|
||||
|
|
@ -236,6 +236,13 @@ def justify(text, width=None, align="l", indent=0, fillchar=" "):
|
|||
justified (str): The justified and indented block of text.
|
||||
|
||||
"""
|
||||
# we need to retain ansitrings
|
||||
global _ANSISTRING
|
||||
if not _ANSISTRING:
|
||||
from evennia.utils.ansi import ANSIString as _ANSISTRING
|
||||
|
||||
is_ansi = isinstance(text, _ANSISTRING)
|
||||
lb = _ANSISTRING("\n") if is_ansi else "\n"
|
||||
|
||||
def _process_line(line):
|
||||
"""
|
||||
|
|
@ -244,7 +251,9 @@ def justify(text, width=None, align="l", indent=0, fillchar=" "):
|
|||
distribute odd spaces to one of the gaps.
|
||||
"""
|
||||
line_rest = width - (wlen + ngaps)
|
||||
gap = " " # minimum gap between words
|
||||
|
||||
gap = _ANSISTRING(" ") if is_ansi else " "
|
||||
|
||||
if line_rest > 0:
|
||||
if align == "l":
|
||||
if line[-1] == "\n\n":
|
||||
|
|
@ -284,23 +293,25 @@ def justify(text, width=None, align="l", indent=0, fillchar=" "):
|
|||
else:
|
||||
line = crop(line, width=width, suffix="")
|
||||
abs_lines.append(line)
|
||||
return "\n".join(abs_lines)
|
||||
return lb.join(abs_lines)
|
||||
|
||||
# all other aligns requires splitting into paragraphs and words
|
||||
|
||||
# split into paragraphs and words
|
||||
paragraphs = re.split("\n\s*?\n", text, re.MULTILINE)
|
||||
paragraphs = [text] # re.split("\n\s*?\n", text, re.MULTILINE)
|
||||
words = []
|
||||
for ip, paragraph in enumerate(paragraphs):
|
||||
if ip > 0:
|
||||
words.append(("\n", 0))
|
||||
words.extend((word, len(word)) for word in paragraph.split())
|
||||
ngaps, wlen, line = 0, 0, []
|
||||
|
||||
if not words:
|
||||
# Just whitespace!
|
||||
return sp * width
|
||||
|
||||
ngaps = 0
|
||||
wlen = 0
|
||||
line = []
|
||||
lines = []
|
||||
|
||||
while words:
|
||||
|
|
@ -328,8 +339,8 @@ def justify(text, width=None, align="l", indent=0, fillchar=" "):
|
|||
if line: # catch any line left behind
|
||||
lines.append(_process_line(line))
|
||||
indentstring = sp * indent
|
||||
out = "\n".join([indentstring + line for line in lines])
|
||||
return "\n".join([indentstring + line for line in lines])
|
||||
out = lb.join([indentstring + line for line in lines])
|
||||
return lb.join([indentstring + line for line in lines])
|
||||
|
||||
|
||||
def columnize(string, columns=2, spacing=4, align="l", width=None):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue