Adjustments for getting interleving ANSI codes in splits, slices, and indexes.
This commit is contained in:
parent
8c1b81a06c
commit
67f53564cb
1 changed files with 35 additions and 43 deletions
|
|
@ -567,6 +567,11 @@ class ANSIString(unicode):
|
||||||
replayed.
|
replayed.
|
||||||
"""
|
"""
|
||||||
slice_indexes = self._char_indexes[slc]
|
slice_indexes = self._char_indexes[slc]
|
||||||
|
# If it's the end of the string, we need to append final color codes.
|
||||||
|
if self._char_indexes and self._char_indexes[-1] in slice_indexes:
|
||||||
|
append_tail = self._get_interleving(len(self))
|
||||||
|
else:
|
||||||
|
append_tail = ''
|
||||||
if not slice_indexes:
|
if not slice_indexes:
|
||||||
return ANSIString('')
|
return ANSIString('')
|
||||||
try:
|
try:
|
||||||
|
|
@ -584,7 +589,7 @@ class ANSIString(unicode):
|
||||||
string += self._raw_string[i]
|
string += self._raw_string[i]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
pass
|
pass
|
||||||
return ANSIString(string, decoded=True)
|
return ANSIString(string + append_tail, decoded=True)
|
||||||
|
|
||||||
def __getitem__(self, item):
|
def __getitem__(self, item):
|
||||||
"""
|
"""
|
||||||
|
|
@ -599,9 +604,12 @@ class ANSIString(unicode):
|
||||||
# Slices must be handled specially.
|
# Slices must be handled specially.
|
||||||
return self._slice(item)
|
return self._slice(item)
|
||||||
try:
|
try:
|
||||||
item = self._char_indexes[item]
|
self._char_indexes[item]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
raise IndexError("ANSIString index out of range.")
|
raise IndexError("ANSIString Index out of range")
|
||||||
|
# Get character codes after the index as well.
|
||||||
|
append_tail = self._get_interleving(item + 1)
|
||||||
|
item = self._char_indexes[item]
|
||||||
|
|
||||||
clean = self._raw_string[item]
|
clean = self._raw_string[item]
|
||||||
result = ''
|
result = ''
|
||||||
|
|
@ -610,38 +618,7 @@ class ANSIString(unicode):
|
||||||
for index in range(0, item + 1):
|
for index in range(0, item + 1):
|
||||||
if index in self._code_indexes:
|
if index in self._code_indexes:
|
||||||
result += self._raw_string[index]
|
result += self._raw_string[index]
|
||||||
return ANSIString(result + clean, decoded=True)
|
return ANSIString(result + clean + append_tail, decoded=True)
|
||||||
|
|
||||||
def rsplit(self, sep=None, maxsplit=None):
|
|
||||||
"""
|
|
||||||
Like split, but from the end of the string, rather than the beginning.
|
|
||||||
"""
|
|
||||||
return self.split(sep, maxsplit, reverse=True)
|
|
||||||
|
|
||||||
def split(self, sep=None, maxsplit=None, reverse=False):
|
|
||||||
"""
|
|
||||||
Splits in a manner similar to the standard string split method. First,
|
|
||||||
we split the clean string. Then we measure each section of the result
|
|
||||||
to figure out where they start and end, and replay any escapes that
|
|
||||||
would have occured before that.
|
|
||||||
"""
|
|
||||||
if hasattr(sep, 'clean_string'):
|
|
||||||
sep = sep.clean_string
|
|
||||||
args = [sep]
|
|
||||||
if maxsplit is not None:
|
|
||||||
args.append(maxsplit)
|
|
||||||
if reverse:
|
|
||||||
parent_result = self._clean_string.rsplit(*args)
|
|
||||||
else:
|
|
||||||
parent_result = self._clean_string.split(*args)
|
|
||||||
# Might be None.
|
|
||||||
sep = sep or ''
|
|
||||||
current_index = 0
|
|
||||||
result = []
|
|
||||||
for section in parent_result:
|
|
||||||
result.append(self[current_index:current_index + len(section)])
|
|
||||||
current_index += (len(section)) + len(sep)
|
|
||||||
return result
|
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
"""
|
"""
|
||||||
|
|
@ -744,12 +721,25 @@ class ANSIString(unicode):
|
||||||
char_indexes = []
|
char_indexes = []
|
||||||
for start, end in list(group(flat_ranges, 2)):
|
for start, end in list(group(flat_ranges, 2)):
|
||||||
char_indexes.extend(range(start, end))
|
char_indexes.extend(range(start, end))
|
||||||
# The end character will be left off if it's a normal character. Fix
|
|
||||||
# that here.
|
|
||||||
if end_index in flat_ranges:
|
|
||||||
char_indexes.append(end_index)
|
|
||||||
return code_indexes, char_indexes
|
return code_indexes, char_indexes
|
||||||
|
|
||||||
|
def _get_interleving(self, index):
|
||||||
|
"""
|
||||||
|
Get the code characters from the given slice end to the next
|
||||||
|
character.
|
||||||
|
"""
|
||||||
|
index = self._char_indexes[index - 1]
|
||||||
|
s = ''
|
||||||
|
while True:
|
||||||
|
index += 1
|
||||||
|
if index in self._char_indexes:
|
||||||
|
break
|
||||||
|
elif index in self._code_indexes:
|
||||||
|
s += self._raw_string[index]
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
return s
|
||||||
|
|
||||||
def split(self, by, maxsplit=-1):
|
def split(self, by, maxsplit=-1):
|
||||||
"""
|
"""
|
||||||
Stolen from PyPy's pure Python string implementation, tweaked for
|
Stolen from PyPy's pure Python string implementation, tweaked for
|
||||||
|
|
@ -768,11 +758,12 @@ class ANSIString(unicode):
|
||||||
next = self._clean_string.find(by, start)
|
next = self._clean_string.find(by, start)
|
||||||
if next < 0:
|
if next < 0:
|
||||||
break
|
break
|
||||||
res.append(self[start:next])
|
# Get character codes after the index as well.
|
||||||
|
res.append(self[start:next] + self._get_interleving(next))
|
||||||
start = next + bylen
|
start = next + bylen
|
||||||
maxsplit -= 1 # NB. if it's already < 0, it stays < 0
|
maxsplit -= 1 # NB. if it's already < 0, it stays < 0
|
||||||
|
|
||||||
res.append(self[start:len(self)])
|
res.append(self[start:len(self)] + self._get_interleving(len(self)))
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def rsplit(self, by, maxsplit=-1):
|
def rsplit(self, by, maxsplit=-1):
|
||||||
|
|
@ -793,11 +784,12 @@ class ANSIString(unicode):
|
||||||
next = self._clean_string.rfind(by, 0, end)
|
next = self._clean_string.rfind(by, 0, end)
|
||||||
if next < 0:
|
if next < 0:
|
||||||
break
|
break
|
||||||
res.append(self[next+bylen:end])
|
# Get character codes after the index as well.
|
||||||
|
res.append(self[next+bylen:end] + self._get_interleving(end))
|
||||||
end = next
|
end = next
|
||||||
maxsplit -= 1 # NB. if it's already < 0, it stays < 0
|
maxsplit -= 1 # NB. if it's already < 0, it stays < 0
|
||||||
|
|
||||||
res.append(self[:end])
|
res.append(self[:end] + self._get_interleving(end))
|
||||||
res.reverse()
|
res.reverse()
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue