The module in Example 15-7 implements general tools for wrapping long lines, at either a fixed column or the first delimiter at or before a fixed column. PyMailGUI uses this file’s wrapText1 function for text in view, reply, and forward windows, but this code is potentially useful in other programs. Run the file as a script to watch its self-test code at work, and study its functions to see its text-processing logic.
Example 15-7.PP3E\Internet\Email\PyMailGui\wraplines.py
################################################################ # split lines on fixed columns or at delimiters before a column # see also: related but different textwrap standard library module (2.3+) ###############################################################
defaultsize = 80
def wrapLinesSimple(lineslist, size=defaultsize): "split at fixed position size" wraplines = [] for line in lineslist: while True: wraplines.append(line[:size]) # OK if len < size line = line[size:] # split without analysis if not line: break return wraplines
def wrapLinesSmart(lineslist, size=defaultsize, delimiters='.,:\t '): "wrap at first delimiter left of size" wraplines = [] for line in lineslist: while True: if len(line) <= size: wraplines += [line] break else: for look in range(size-1, size/2, -1): if line[look] in delimiters: front, line = line[:look+1], line[look+1:] break else: front, line = line[:size], line[size:] wraplines += [front] return wraplines
################################################################ # common use case utilities ###############################################################
def wrapText1(text, size=defaultsize): # better for line-based txt: mail "when text read all at once" # keeps original line brks struct lines = text.split('\n') # split on newlines
lines = wrapLinesSmart(lines, size)
# wrap lines on delimiters
return '\n'.join(lines)
# put back together
def wrapText2(text, size=defaultsize):
# more uniform across lines
"same, but treat as one long line"
# but loses original line struct
text = text.replace('\n', ' ')
# drop newlines if any
lines = wrapLinesSmart([text], size)
# wrap single line on delimiters
return lines
# caller puts back together
def wrapText3(text, size=defaultsize):
"same, but put back together"
lines = wrapText2(text, size)
# wrap as single long line
return '\n'.join(lines) + '\n'
# make one string with newlines
def wrapLines1(lines, size=defaultsize):
"when newline included at end"
lines = [line[:-1] for line in lines]
# strip off newlines (or .rstrip)
lines = wrapLinesSmart(lines, size)
# wrap on delimiters
return [(line + '\n') for line in lines]
# put them back
def wrapLines2(lines, size=defaultsize):
# more uniform across lines
"same, but concat as one long line"
# but loses original structure
text = ''.join(lines)
# put together as 1 line
lines = wrapText2(text)
# wrap on delimiters
return [(line + '\n') for line in lines]
# put newlines on ends
################################################################ a self-test ###############################################################
if __name__ == '__main__': lines = ['spam ham ' * 20 + 'spam,ni' * 20, 'spam ham ' * 20, 'spam,ni' * 20, 'spam ham.ni' * 20, '', 'spam'*80, ' ', 'spam ham eggs'] print 'all', '-'*30 for line in lines: print repr(line) print 'simple', '-'*30 for line in wrapLinesSimple(lines): print repr(line) print 'smart', '-'*30 for line in wrapLinesSmart(lines): print repr(line)
print 'single1', '-'*30 for line in wrapLinesSimple([lines[0]], 60): print repr(line) print 'single2', '-'*30 for line in wrapLinesSmart([lines[0]], 60): print repr(line) print 'combined text', '-'*30 for line in wrapLines2(lines): print repr(line) print 'combined lines', '-'*30 print wrapText1('\n'.join(lines))