diff options
Diffstat (limited to 'pym/gentoolkit/textwrap_.py')
-rw-r--r-- | pym/gentoolkit/textwrap_.py | 180 |
1 files changed, 91 insertions, 89 deletions
diff --git a/pym/gentoolkit/textwrap_.py b/pym/gentoolkit/textwrap_.py index 07c0831..fd28c6a 100644 --- a/pym/gentoolkit/textwrap_.py +++ b/pym/gentoolkit/textwrap_.py @@ -5,95 +5,97 @@ prevent the splitting of ANSI colors as well as package names and versions.""" import re import textwrap + class TextWrapper(textwrap.TextWrapper): - """Ignore ANSI escape codes while wrapping text""" - - def _split(self, text): - """_split(text : string) -> [string] - - Split the text to wrap into indivisible chunks. - """ - # Only split on whitespace to avoid mangling ANSI escape codes or - # package names. - wordsep_re = re.compile(r'(\s+)') - chunks = wordsep_re.split(text) - chunks = [x for x in chunks if x is not None] - return chunks - - def _wrap_chunks(self, chunks): - """_wrap_chunks(chunks : [string]) -> [string] - - Wrap a sequence of text chunks and return a list of lines of - length 'self.width' or less. (If 'break_long_words' is false, - some lines may be longer than this.) Chunks correspond roughly - to words and the whitespace between them: each chunk is - indivisible (modulo 'break_long_words'), but a line break can - come between any two chunks. Chunks should not have internal - whitespace; ie. a chunk is either all whitespace or a "word". - Whitespace chunks will be removed from the beginning and end of - lines, but apart from that whitespace is preserved. - """ - lines = [] - if self.width <= 0: - raise ValueError("invalid width %r (must be > 0)" % self.width) - - # Arrange in reverse order so items can be efficiently popped - # from a stack of chunks. - chunks.reverse() - - # Regex to strip ANSI escape codes. It's only used for the - # length calculations of indent and each chuck. - ansi_re = re.compile(r'\x1b\[[0-9;]*m') - - while chunks: - - # Start the list of chunks that will make up the current line. - # cur_len is just the length of all the chunks in cur_line. - cur_line = [] - cur_len = 0 - - # Figure out which static string will prefix this line. - if lines: - indent = self.subsequent_indent - else: - indent = self.initial_indent - - # Maximum width for this line. Ingore ANSI escape codes. - width = self.width - len(re.sub(ansi_re, '', indent)) - - # First chunk on line is whitespace -- drop it, unless this - # is the very beginning of the text (ie. no lines started yet). - if chunks[-1].strip() == '' and lines: - del chunks[-1] - - while chunks: - # Ignore ANSI escape codes. - chunk_len = len(re.sub(ansi_re, '', chunks[-1])) - - # Can at least squeeze this chunk onto the current line. - if cur_len + chunk_len <= width: - cur_line.append(chunks.pop()) - cur_len += chunk_len - - # Nope, this line is full. - else: - break - - # The current line is full, and the next chunk is too big to - # fit on *any* line (not just this one). - # Ignore ANSI escape codes. - if chunks and len(re.sub(ansi_re, '', chunks[-1])) > width: - self._handle_long_word(chunks, cur_line, cur_len, width) - - # If the last chunk on this line is all whitespace, drop it. - if cur_line and cur_line[-1].strip() == '': - del cur_line[-1] - - # Convert current line back to a string and store it in list - # of all lines (return value). - if cur_line: - lines.append(indent + ''.join(cur_line)) - - return lines + """Ignore ANSI escape codes while wrapping text""" + + def _split(self, text): + """_split(text : string) -> [string] + + Split the text to wrap into indivisible chunks. + """ + # Only split on whitespace to avoid mangling ANSI escape codes or + # package names. + wordsep_re = re.compile(r"(\s+)") + chunks = wordsep_re.split(text) + chunks = [x for x in chunks if x is not None] + return chunks + + def _wrap_chunks(self, chunks): + """_wrap_chunks(chunks : [string]) -> [string] + + Wrap a sequence of text chunks and return a list of lines of + length 'self.width' or less. (If 'break_long_words' is false, + some lines may be longer than this.) Chunks correspond roughly + to words and the whitespace between them: each chunk is + indivisible (modulo 'break_long_words'), but a line break can + come between any two chunks. Chunks should not have internal + whitespace; ie. a chunk is either all whitespace or a "word". + Whitespace chunks will be removed from the beginning and end of + lines, but apart from that whitespace is preserved. + """ + lines = [] + if self.width <= 0: + raise ValueError("invalid width %r (must be > 0)" % self.width) + + # Arrange in reverse order so items can be efficiently popped + # from a stack of chunks. + chunks.reverse() + + # Regex to strip ANSI escape codes. It's only used for the + # length calculations of indent and each chuck. + ansi_re = re.compile(r"\x1b\[[0-9;]*m") + + while chunks: + + # Start the list of chunks that will make up the current line. + # cur_len is just the length of all the chunks in cur_line. + cur_line = [] + cur_len = 0 + + # Figure out which static string will prefix this line. + if lines: + indent = self.subsequent_indent + else: + indent = self.initial_indent + + # Maximum width for this line. Ingore ANSI escape codes. + width = self.width - len(re.sub(ansi_re, "", indent)) + + # First chunk on line is whitespace -- drop it, unless this + # is the very beginning of the text (ie. no lines started yet). + if chunks[-1].strip() == "" and lines: + del chunks[-1] + + while chunks: + # Ignore ANSI escape codes. + chunk_len = len(re.sub(ansi_re, "", chunks[-1])) + + # Can at least squeeze this chunk onto the current line. + if cur_len + chunk_len <= width: + cur_line.append(chunks.pop()) + cur_len += chunk_len + + # Nope, this line is full. + else: + break + + # The current line is full, and the next chunk is too big to + # fit on *any* line (not just this one). + # Ignore ANSI escape codes. + if chunks and len(re.sub(ansi_re, "", chunks[-1])) > width: + self._handle_long_word(chunks, cur_line, cur_len, width) + + # If the last chunk on this line is all whitespace, drop it. + if cur_line and cur_line[-1].strip() == "": + del cur_line[-1] + + # Convert current line back to a string and store it in list + # of all lines (return value). + if cur_line: + lines.append(indent + "".join(cur_line)) + + return lines + # vim: set ts=4 sw=4 tw=79: |