Python 2.3 module textwrap can justify text in three modes: left/right/center. Sometimes 'align' mode become more useful.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | ## {{{ Recipe 414870 (r3): Align text string using spaces between words to fit specified width
#!/usr/bin/env python
'''
align_string.py
Align string with spaces between words to fit specified width
Author: Denis Barmenkov <denis.barmenkov@gmail.com>
Copyright: this code is free, but if you want to use it,
please keep this multiline comment along with function source.
Thank you.
2005-05-22 13:27 - first revision
2010-03-09 17:01 - added align_paragraph()
2010-03-09 17:56 - added check for paragraph's last line
2010-03-09 18:16 - fork for pipe align sample script
'''
import re
import sys
import textwrap
__author__ = 'Denis Barmenkov <denis.barmenkov@gmail.com>'
#__source__ = 'http://code.activestate.com/recipes/414870/'
__source__ = 'http://code.activestate.com/recipes/577093/'
def items_len(l):
return sum([ len(x) for x in l] )
lead_re = re.compile(r'(^\s+)(.*)$')
def align_string(s, width, last_paragraph_line=0):
'''
align string to specified width
'''
# detect and save leading whitespace
m = lead_re.match(s)
if m is None:
left, right, w = '', s, width
else:
left, right, w = m.group(1), m.group(2), width - len(m.group(1))
items = right.split()
# add required space to each words, exclude last item
for i in range(len(items) - 1):
items[i] += ' '
if not last_paragraph_line:
# number of spaces to add
left_count = w - items_len(items)
while left_count > 0 and len(items) > 1:
for i in range(len(items) - 1):
items[i] += ' '
left_count -= 1
if left_count < 1:
break
res = left + ''.join(items)
return res
def align_paragraph(paragraph, width, debug=0):
'''
align paragraph to specified width,
returns list of paragraph lines
'''
lines = list()
if type(paragraph) == type(lines):
lines.extend(paragraph)
elif type(paragraph) == type(''):
lines.append(paragraph)
elif type(paragraph) == type(tuple()):
lines.extend(list(paragraph))
else:
raise TypeError, 'Unsopported paragraph type: %r' % type(paragraph)
flatten_para = ' '.join(lines)
splitted = textwrap.wrap(flatten_para, width)
if debug:
print 'textwrap:\n%s\n' % '\n'.join(splitted)
wrapped = list()
while len(splitted) > 0:
line = splitted.pop(0)
if len(splitted) == 0:
last_paragraph_line = 1
else:
last_paragraph_line = 0
aligned = align_string(line, width, last_paragraph_line)
wrapped.append(aligned)
if debug:
print 'textwrap & align_string:\n%s\n' % '\n'.join(wrapped)
return wrapped
def align_pipe(width, inpipe=None, outpipe=None):
'''
read paragraphs from one pipe,
align them and puts to second pipe
'''
if inpipe is None:
inpipe = sys.stdin
if outpipe is None:
outpipe = sys.stdout
paragraph_lines = list()
def flush_paragraph(paragraph_lines):
'''
align paragraph, put to output,
reset state
'''
if len(paragraph_lines) > 0:
aligned_paragraph = align_paragraph(paragraph_lines, width)
for line in aligned_paragraph:
outpipe.write(line + '\n')
paragraph_lines = list()
return paragraph_lines
for rawline in inpipe:
line = rawline.splitlines()[0]
# paragraph closed by empty line
if line.strip() == '':
paragraph_lines = flush_paragraph(paragraph_lines)
outpipe.write('\n')
continue
# paragraph started with space
if line[0].isspace():
paragraph_lines = flush_paragraph(paragraph_lines)
paragraph_lines.append(line)
paragraph_lines = flush_paragraph(paragraph_lines)
if __name__ == '__main__':
width = 75
# or
# width = int(sys.argv[1])
align_pipe(width)
|
Call this script on *nixes:
chmod +x align_pipe.py
cat text_file | align_pipe.py
or on Windows:
type text_file | python align_pipe.py
See also: http://docs.python.org/using/index.html
Thank you very much!
Your script will help me a lot. I am too impressed that fast way you code.
Thanks a lot from Brazil!