這裏的我很久以前就發現了那個哈它非常有用並且仍然有效(至少在Python 2.7中)。最近我終於完成了大部分最新的Py 2x標準,儘管所有的改變都是我所稱的化妝品。
#!/usr/bin/env python
# File: textformatter.py
# Author: Hamish B Lawson
# Date: 19 Nov 1999
# from http://www.faqts.com/knowledge_base/view.phtml/aid/4517
"""
Here is TextFormatter, a simple module for formatting text into
columns of specified widths. It does multiline wrapping and supports
LEFT, CENTER (or CENTRE), and RIGHT alignment.
SKWM made filling & padding optional, tweaked some edge cases
MRM removed import of deprecated string module, made all classes new style,
capitalized public constants, updated documentation
"""
LEFT, CENTER, RIGHT = range(3)
CENTRE = CENTER
class TextFormatter(object):
"""
Formats text into columns.
Constructor takes a list of dictionaries that each specify the
properties for a column. Dictionary entries can be:
'width' : the width within which the text will be wrapped
'alignment' : LEFT | CENTER | RIGHT
'margin' : number of space characters to prefix in front of column
The compose() method takes a list of strings and returns a formatted
string consisting of each string wrapped within its respective column.
Example:
import textformatter
formatter = textformatter.TextFormatter(
(
{'width': 10},
{'width': 12, 'margin': 4},
{'width': 20, 'margin': 8, 'alignment': textformatter.RIGHT},
)
)
print formatter.compose(
(
"A rather short paragraph",
"Here is a paragraph containing a veryveryverylongwordindeed.",
"And now for something on the right-hand side.",
)
)
gives:
A rather Here is a And now for
short paragraph something on the
paragraph containing a right-hand side.
veryveryvery
longwordinde
ed.
"""
class Column(object):
def __init__(self, width=75, alignment=LEFT, margin=0, fill=1, pad=1):
self.width = width
self.alignment = alignment
self.margin = margin
self.fill = fill
self.pad = pad
self.lines = []
def align(self, line):
if self.alignment == CENTER:
return line.center(self.width)
elif self.alignment == RIGHT:
return line.rjust(self.width)
else:
if self.pad:
return line.ljust(self.width)
else:
return line
def wrap(self, text):
self.lines = []
words = []
if self.fill: # SKWM
for word in text.split():
wordlen = len(word)
if wordlen <= self.width: # fixed MRM
words.append(word)
else:
for i in range(0, wordlen, self.width):
words.append(word[i:i+self.width])
else:
for line in text.split('\n'):
for word in line.split():
for i in range(0, len(word), self.width):
words.append(word[i:i+self.width])
words.append('\n')
if words[-1] == '\n': words.pop() # remove trailing newline - this comment by MRM
if words:
current = words.pop(0)
for word in words:
increment = 1 + len(word)
if word == '\n':
self.lines.append(self.align(current))
current = ''
elif len(current) + increment > self.width:
self.lines.append(self.align(current))
current = word
else:
if current:
current = current + ' ' + word
else:
current = word
if current: self.lines.append(self.align(current))
def getline(self, index):
if index < len(self.lines):
return ' '*self.margin + self.lines[index]
else:
if self.pad:
return ' ' * (self.margin + self.width)
else:
return ''
def numlines(self):
return len(self.lines)
def __init__(self, colspeclist):
self.columns = []
for colspec in colspeclist:
self.columns.append(apply(TextFormatter.Column,(), colspec))
def compose(self, textlist):
numlines = 0
textlist = list(textlist)
if len(textlist) != len(self.columns):
raise IndexError, "Number of text items does not match columns"
for text, column in map(None, textlist, self.columns):
column.wrap(text)
numlines = max(numlines, column.numlines())
complines = [''] * numlines
for ln in range(numlines):
for column in self.columns:
complines[ln] = complines[ln] + column.getline(ln)
return '\n'.join(complines) + '\n'
#return '\n'.join(complines)
def test():
import textformatter
formatter = textformatter.TextFormatter(
(
{'width': 10},
{'width': 12, 'margin': 4, 'fill': 0},
{'width': 20, 'margin': 8, 'alignment': textformatter.RIGHT},
)
)
result = formatter.compose(
(
"A rather short paragraph",
"Here is\na paragraph containing a veryveryverylongwordindeed.",
"And now for something\non the RIGHT-hand side.",
)
)
print result
print
for line in result.split('\n'):
print repr(line+'\n')
__all__ = [TextFormatter, LEFT, CENTER, CENTRE, RIGHT]
if __name__ == '__main__':
test()
通常的慣例是大寫類名,所以'Item'而不是'item' –