Implement ANSIString.strip() .lstrip() and .rstrip() as tag-aware methods. This handles the last prblem with #1117.

This commit is contained in:
Griatch 2016-11-17 00:21:05 +01:00
parent 596bfff35a
commit f00fbb9d88
3 changed files with 118 additions and 24 deletions

View file

@ -977,6 +977,29 @@ class ANSIString(with_metaclass(ANSIMeta, unicode)):
break
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):
"""
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 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):
"""
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 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):
"""
Joins together strings in an iterable.