diff --git a/src/utils/ansi.py b/src/utils/ansi.py index 85ecd8776..be79a7c60 100644 --- a/src/utils/ansi.py +++ b/src/utils/ansi.py @@ -358,7 +358,7 @@ def _on_raw(func_name): args = list(args) try: string = args.pop(0) - if hasattr(string, 'raw_string'): + if hasattr(string, '_raw_string'): args.insert(0, string.raw()) else: args.insert(0, string) @@ -381,9 +381,9 @@ def _transform(func_name): def wrapped(self, *args, **kwargs): replacement_string = _query_super(func_name)(self, *args, **kwargs) to_string = [] - for index in range(0, len(self.raw_string)): + for index in range(0, len(self._raw_string)): if index in self._code_indexes: - to_string.append(self.raw_string[index]) + to_string.append(self._raw_string[index]) elif index in self._char_indexes: to_string.append(replacement_string[index]) return ANSIString(''.join(to_string), decoded=True) @@ -470,7 +470,7 @@ class ANSIString(unicode): string = str(string) parser = kwargs.get('parser', ANSI_PARSER) regexable = kwargs.get('regexable', False) - decoded = kwargs.get('decoded', False) or hasattr(string, 'raw_string') + decoded = kwargs.get('decoded', False) or hasattr(string, '_raw_string') if not decoded: string = parser.parse_ansi(string) if isinstance(string, unicode): @@ -533,7 +533,7 @@ class ANSIString(unicode): if not isinstance(other, basestring): return NotImplemented return ANSIString(self._raw_string + getattr( - other, 'raw_string', other), decoded=True) + other, '_raw_string', other), decoded=True) def __radd__(self, other): """ @@ -542,7 +542,7 @@ class ANSIString(unicode): if not isinstance(other, basestring): return NotImplemented return ANSIString(getattr( - other, 'raw_string', other) + self._raw_string, decoded=True) + other, '_raw_string', other) + self._raw_string, decoded=True) def __getslice__(self, i, j): """ @@ -705,32 +705,8 @@ class ANSIString(unicode): if not code_indexes: # Plain string, no ANSI codes. return code_indexes, range(0, len(self._raw_string)) - flat_ranges = [] - # We need to get the ones between them, but the code might start at - # the beginning, and there might be codes at the end. - for tup in matches: - flat_ranges.extend(tup) - # Is the beginning of the string a code character? - if flat_ranges[0] == 0: - flat_ranges.pop(0) - else: - flat_ranges.insert(0, 0) - # How about the end? - end_index = (len(self._raw_string) - 1) - if flat_ranges[-1] == end_index: - flat_ranges.pop() - else: - flat_ranges.append(end_index) - char_indexes = [] - for start, end in list(group(flat_ranges, 2)): - 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) - # And in some instances, this may also end up in the code indexes - if end_index in code_indexes: - code_indexes.pop() + # all indexes not occupied by ansi codes are normal characters + char_indexes = [i for i in range(len(self._raw_string)) if i not in code_indexes] return code_indexes, char_indexes def _get_interleving(self, index): diff --git a/src/utils/evtable.py b/src/utils/evtable.py index 6ddb9b686..73b8d07be 100644 --- a/src/utils/evtable.py +++ b/src/utils/evtable.py @@ -7,8 +7,8 @@ This is an advanced ASCII table creator. It was inspired by prettytable but shares no code. WARNING: UNDER DEVELOPMENT. Evtable does currently NOT support -colour ANSI markers in the table. Non-colour tables should -work fully (so make issues if they don't). +colour ANSI markers in the table. Non-colour tables should +work fully (so make issues if they don't). Example usage: @@ -74,13 +74,19 @@ ANSI-coloured string types. """ from textwrap import wrap from copy import deepcopy, copy - -#from src.utils.ansi import ANSIString +from src.utils.ansi import ANSIString def make_iter(obj): "Makes sure that the object is always iterable." return not hasattr(obj, '__iter__') and [obj] or obj +def _to_ansi(obj, regexable=False): + "convert to ANSIString" + if hasattr(obj, "__iter__"): + return [_to_ansi(o) for o in obj] + else: + return ANSIString(unicode(obj), regexable=regexable) + # Cell class (see further down for the EvTable itself) @@ -196,8 +202,8 @@ class Cell(object): self.align = kwargs.get("align", "c") self.valign = kwargs.get("valign", "c") - self.data = self._split_lines(unicode(data)) - #self.data = self._split_lines(ANSIString(unicode(data))) + #self.data = self._split_lines(unicode(data)) + self.data = self._split_lines(_to_ansi(data)) self.raw_width = max(len(line) for line in self.data) self.raw_height = len(self.data) @@ -226,6 +232,7 @@ class Cell(object): def _split_lines(self, text): "Simply split by linebreak" + print "split:", text, text.split("\n") return text.split("\n") def _fit_width(self, data): @@ -237,7 +244,8 @@ class Cell(object): adjusted_data = [] for line in data: if 0 < width < len(line): - adjusted_data.extend(wrap(line, width=width, drop_whitespace=False)) + adjusted_data.extend(_to_ansi(wrap(line, width=width, drop_whitespace=False, + replace_whitespace=False, expand_tabs=False))) # fix for ANSIString not supporting expand_tabs/translate else: adjusted_data.append(line) if self.enforce_size: @@ -368,8 +376,8 @@ class Cell(object): kwargs - like when creating the cell anew. """ - self.data = self._split_lines(unicode(data)) - #self.data = self._split_lines(ANSIString(unicode(data))) + #self.data = self._split_lines(unicode(data)) + self.data = self._split_lines(_to_ansi(data)) self.raw_width = max(len(line) for line in self.data) self.raw_height = len(self.data) self.reformat(**kwargs) @@ -460,6 +468,7 @@ class EvTable(object): all cell boundaries lining up. """ + def __init__(self, *args, **kwargs): """ Args: @@ -523,7 +532,7 @@ class EvTable(object): self.table.extend([] for i in range(excess)) elif excess < 0: # too short header - header.extend(["" for i in range(abs(excess))]) + header.extend(_to_ansi(["" for i in range(abs(excess))])) for ix, heading in enumerate(header): self.table[ix].insert(0, heading) else: