Implement ANSIString.strip() .lstrip() and .rstrip() as tag-aware methods. This handles the last prblem with #1117.
This commit is contained in:
parent
596bfff35a
commit
f00fbb9d88
3 changed files with 118 additions and 24 deletions
|
|
@ -977,6 +977,29 @@ class ANSIString(with_metaclass(ANSIMeta, unicode)):
|
||||||
break
|
break
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
def __mul__(self, other):
|
||||||
|
"""
|
||||||
|
Multiplication method. Implemented for performance reasons.
|
||||||
|
|
||||||
|
"""
|
||||||
|
if not isinstance(other, int):
|
||||||
|
return NotImplemented
|
||||||
|
raw_string = self._raw_string * other
|
||||||
|
clean_string = self._clean_string * other
|
||||||
|
code_indexes = self._code_indexes[:]
|
||||||
|
char_indexes = self._char_indexes[:]
|
||||||
|
for i in range(1, other + 1):
|
||||||
|
code_indexes.extend(
|
||||||
|
self._shifter(self._code_indexes, i * len(self._raw_string)))
|
||||||
|
char_indexes.extend(
|
||||||
|
self._shifter(self._char_indexes, i * len(self._raw_string)))
|
||||||
|
return ANSIString(
|
||||||
|
raw_string, code_indexes=code_indexes, char_indexes=char_indexes,
|
||||||
|
clean_string=clean_string)
|
||||||
|
|
||||||
|
def __rmul__(self, other):
|
||||||
|
return self.__mul__(other)
|
||||||
|
|
||||||
def split(self, by=None, maxsplit=-1):
|
def split(self, by=None, maxsplit=-1):
|
||||||
"""
|
"""
|
||||||
Stolen from PyPy's pure Python string implementation, tweaked for
|
Stolen from PyPy's pure Python string implementation, tweaked for
|
||||||
|
|
@ -1010,29 +1033,6 @@ class ANSIString(with_metaclass(ANSIMeta, unicode)):
|
||||||
return [part for part in res if part != ""]
|
return [part for part in res if part != ""]
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def __mul__(self, other):
|
|
||||||
"""
|
|
||||||
Multiplication method. Implemented for performance reasons.
|
|
||||||
|
|
||||||
"""
|
|
||||||
if not isinstance(other, int):
|
|
||||||
return NotImplemented
|
|
||||||
raw_string = self._raw_string * other
|
|
||||||
clean_string = self._clean_string * other
|
|
||||||
code_indexes = self._code_indexes[:]
|
|
||||||
char_indexes = self._char_indexes[:]
|
|
||||||
for i in range(1, other + 1):
|
|
||||||
code_indexes.extend(
|
|
||||||
self._shifter(self._code_indexes, i * len(self._raw_string)))
|
|
||||||
char_indexes.extend(
|
|
||||||
self._shifter(self._char_indexes, i * len(self._raw_string)))
|
|
||||||
return ANSIString(
|
|
||||||
raw_string, code_indexes=code_indexes, char_indexes=char_indexes,
|
|
||||||
clean_string=clean_string)
|
|
||||||
|
|
||||||
def __rmul__(self, other):
|
|
||||||
return self.__mul__(other)
|
|
||||||
|
|
||||||
def rsplit(self, by=None, maxsplit=-1):
|
def rsplit(self, by=None, maxsplit=-1):
|
||||||
"""
|
"""
|
||||||
Stolen from PyPy's pure Python string implementation, tweaked for
|
Stolen from PyPy's pure Python string implementation, tweaked for
|
||||||
|
|
@ -1066,6 +1066,88 @@ class ANSIString(with_metaclass(ANSIMeta, unicode)):
|
||||||
return [part for part in res if part != ""]
|
return [part for part in res if part != ""]
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
def strip(self, chars=None):
|
||||||
|
"""
|
||||||
|
Strip from both ends, taking ANSI markers into account.
|
||||||
|
"""
|
||||||
|
clean = self._clean_string
|
||||||
|
raw = self._raw_string
|
||||||
|
|
||||||
|
# count continuous sequence of chars from left and right
|
||||||
|
nlen = len(clean)
|
||||||
|
nlstripped = nlen - len(clean.lstrip(chars))
|
||||||
|
nrstripped = nlen - len(clean.rstrip(chars))
|
||||||
|
|
||||||
|
# within the stripped regions, only retain parts of the raw
|
||||||
|
# string *not* matching the clean string (these are ansi/mxp tags)
|
||||||
|
lstripped = ""
|
||||||
|
ic, ir1 = 0, 0
|
||||||
|
while nlstripped:
|
||||||
|
if ic >= nlstripped:
|
||||||
|
break
|
||||||
|
elif raw[ir1] != clean[ic]:
|
||||||
|
lstripped += raw[ir1]
|
||||||
|
else:
|
||||||
|
ic += 1
|
||||||
|
ir1 += 1
|
||||||
|
rstripped = ""
|
||||||
|
ic, ir2 = nlen-1, len(raw)-1
|
||||||
|
while nrstripped:
|
||||||
|
if nlen - ic > nrstripped:
|
||||||
|
break
|
||||||
|
elif raw[ir2] != clean[ic]:
|
||||||
|
rstripped += raw[ir2]
|
||||||
|
else:
|
||||||
|
ic -= 1
|
||||||
|
ir2 -= 1
|
||||||
|
rstripped = rstripped[::-1]
|
||||||
|
return ANSIString(lstripped + raw[ir1:ir2+1] + rstripped)
|
||||||
|
|
||||||
|
|
||||||
|
def lstrip(self, chars=None):
|
||||||
|
"""
|
||||||
|
Strip from the left, taking ANSI markers into account.
|
||||||
|
"""
|
||||||
|
clean = self._clean_string
|
||||||
|
raw = self._raw_string
|
||||||
|
|
||||||
|
# count continuous sequence of chars from left and right
|
||||||
|
nlen = len(clean)
|
||||||
|
nlstripped = nlen - len(clean.lstrip(chars))
|
||||||
|
# within the stripped regions, only retain parts of the raw
|
||||||
|
# string *not* matching the clean string (these are ansi/mxp tags)
|
||||||
|
lstripped = ""
|
||||||
|
ic, ir1 = 0, 0
|
||||||
|
while nlstripped:
|
||||||
|
if ic >= nlstripped:
|
||||||
|
break
|
||||||
|
elif raw[ir1] != clean[ic]:
|
||||||
|
lstripped += raw[ir1]
|
||||||
|
else:
|
||||||
|
ic += 1
|
||||||
|
ir1 += 1
|
||||||
|
return ANSIString(lstripped + raw[ir1:])
|
||||||
|
|
||||||
|
def rstrip(self, chars=None):
|
||||||
|
"""
|
||||||
|
Strip from the right, taking ANSI markers into account.
|
||||||
|
"""
|
||||||
|
clean = self._clean_string
|
||||||
|
raw = self._raw_string
|
||||||
|
nlen = len(clean)
|
||||||
|
nrstripped = nlen - len(clean.rstrip(chars))
|
||||||
|
rstripped = ""
|
||||||
|
ic, ir2 = nlen-1, len(raw)-1
|
||||||
|
while nrstripped:
|
||||||
|
if nlen - ic > nrstripped:
|
||||||
|
break
|
||||||
|
elif raw[ir2] != clean[ic]:
|
||||||
|
rstripped += raw[ir2]
|
||||||
|
else:
|
||||||
|
ic -= 1
|
||||||
|
ir2 -= 1
|
||||||
|
return ANSIString(raw[:ir2+1] + rstripped)
|
||||||
|
|
||||||
def join(self, iterable):
|
def join(self, iterable):
|
||||||
"""
|
"""
|
||||||
Joins together strings in an iterable.
|
Joins together strings in an iterable.
|
||||||
|
|
|
||||||
|
|
@ -576,7 +576,8 @@ class EvCell(object):
|
||||||
hfill_char = self.hfill_char
|
hfill_char = self.hfill_char
|
||||||
width = self.width
|
width = self.width
|
||||||
if align == "l":
|
if align == "l":
|
||||||
return [(line.lstrip(" ") + " " if line.startswith(" ") and not line.startswith(" ") else line) + hfill_char * (width - m_len(line)) for line in data]
|
lines= [(line.lstrip(" ") + " " if line.startswith(" ") and not line.startswith(" ") else line) + hfill_char * (width - m_len(line)) for line in data]
|
||||||
|
return lines
|
||||||
elif align == "r":
|
elif align == "r":
|
||||||
return [hfill_char * (width - m_len(line)) + (" " + line.rstrip(" ") if line.endswith(" ") and not line.endswith(" ") else line) for line in data]
|
return [hfill_char * (width - m_len(line)) + (" " + line.rstrip(" ") if line.endswith(" ") and not line.endswith(" ") else line) for line in data]
|
||||||
else: # center, 'c'
|
else: # center, 'c'
|
||||||
|
|
|
||||||
|
|
@ -152,6 +152,17 @@ class ANSIStringTestCase(TestCase):
|
||||||
]
|
]
|
||||||
self.table_check(c, char_table, code_table)
|
self.table_check(c, char_table, code_table)
|
||||||
|
|
||||||
|
def test_strip(self):
|
||||||
|
"""
|
||||||
|
Test the ansi-aware .strip() methods
|
||||||
|
"""
|
||||||
|
a = ANSIString(" |r Test of stuff |b with spaces |n ")
|
||||||
|
b = ANSIString("|r|b")
|
||||||
|
self.assertEqual(a.strip(), ANSIString("|rTest of stuff |b with spaces|n"))
|
||||||
|
self.assertEqual(a.lstrip(), ANSIString("|rTest of stuff |b with spaces |n "))
|
||||||
|
self.assertEqual(a.rstrip(), ANSIString(" |r Test of stuff |b with spaces|n"))
|
||||||
|
self.assertEqual(b.strip(), b)
|
||||||
|
|
||||||
|
|
||||||
class TestIsIter(TestCase):
|
class TestIsIter(TestCase):
|
||||||
def test_is_iter(self):
|
def test_is_iter(self):
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue