From 62080bee145c3ba97e239821b0f484629cc203b8 Mon Sep 17 00:00:00 2001 From: Greg Ward Date: Mon, 10 Jun 2002 21:37:12 +0000 Subject: [PATCH] Took initial_tab and subsequent_tab away from the fill() method and transformed them into the initial_indent and subsequent_indent instance attributes. Now they actually work as advertised, ie. they are accounted for in the width of each output line. Plus you can use them with wrap() as well as fill(), and fill() went from simple-and-broken to trivial-and-working. --- Lib/textwrap.py | 56 ++++++++++++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/Lib/textwrap.py b/Lib/textwrap.py index af7a48aec57..3230566076f 100644 --- a/Lib/textwrap.py +++ b/Lib/textwrap.py @@ -22,6 +22,12 @@ class TextWrapper: width (default: 70) the maximum width of wrapped lines (unless break_long_words is false) + initial_indent (default: "") + string that will be prepended to the first line of wrapped + output. Counts towards the line's width. + subsequent_indent (default: "") + string that will be prepended to all lines save the first + of wrapped output; also counts towards each line's width. expand_tabs (default: true) Expand tabs in input text to spaces before further processing. Each tab will become 1 .. 8 spaces, depending on its position in @@ -63,11 +69,15 @@ class TextWrapper: def __init__ (self, width=70, + initial_indent="", + subsequent_indent="", expand_tabs=True, replace_whitespace=True, fix_sentence_endings=False, break_long_words=True): self.width = width + self.initial_indent = initial_indent + self.subsequent_indent = subsequent_indent self.expand_tabs = expand_tabs self.replace_whitespace = replace_whitespace self.fix_sentence_endings = fix_sentence_endings @@ -124,15 +134,15 @@ def _fix_sentence_endings(self, chunks): else: i += 1 - def _handle_long_word(self, chunks, cur_line, cur_len): + def _handle_long_word(self, chunks, cur_line, cur_len, width): """_handle_long_word(chunks : [string], cur_line : [string], - cur_len : int) + cur_len : int, width : int) Handle a chunk of text (most likely a word, not whitespace) that is too long to fit in any line. """ - space_left = self.width - cur_len + space_left = width - cur_len # If we're allowed to break long words, then do so: put as much # of the next chunk onto the current line as will fit. @@ -166,12 +176,22 @@ def _wrap_chunks(self, chunks): lines, but apart from that whitespace is preserved. """ lines = [] - width = self.width while chunks: - cur_line = [] # list of chunks (to-be-joined) - cur_len = 0 # length of current line + # 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. + width = self.width - len(indent) # First chunk on line is whitespace -- drop it. if chunks[0].strip() == '': @@ -192,7 +212,7 @@ def _wrap_chunks(self, chunks): # The current line is full, and the next chunk is too big to # fit on *any* line (not just this one). if chunks and len(chunks[0]) > width: - self._handle_long_word(chunks, cur_line, cur_len) + 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() == '': @@ -201,7 +221,7 @@ def _wrap_chunks(self, chunks): # Convert current line back to a string and store it in list # of all lines (return value). if cur_line: - lines.append(''.join(cur_line)) + lines.append(indent + ''.join(cur_line)) return lines @@ -225,21 +245,13 @@ def wrap(self, text): self._fix_sentence_endings(chunks) return self._wrap_chunks(chunks) - def fill(self, text, initial_tab="", subsequent_tab=""): - """fill(text : string, - initial_tab : string = "", - subsequent_tab : string = "") - -> string + def fill(self, text): + """fill(text : string) -> string Reformat the paragraph in 'text' to fit in lines of no more than - 'width' columns. The first line is prefixed with 'initial_tab', - and subsequent lines are prefixed with 'subsequent_tab'; the - lengths of the tab strings are accounted for when wrapping lines - to fit in 'width' columns. + 'width' columns. """ - lines = self.wrap(text) - sep = "\n" + subsequent_tab - return initial_tab + sep.join(lines) + return "\n".join(self.wrap(text)) # Convenience interface @@ -248,6 +260,6 @@ def wrap(text, width=70, **kwargs): w = TextWrapper(width=width, **kwargs) return w.wrap(text) -def fill(text, width=70, initial_tab="", subsequent_tab="", **kwargs): +def fill(text, width=70, **kwargs): w = TextWrapper(width=width, **kwargs) - return w.fill(text, initial_tab, subsequent_tab) + return w.fill(text)