blob: 60e60f116015b35203757a5429d8909dcdd2106c [file] [log] [blame]
Guido van Rossum4b8c6ea2000-02-04 15:39:30 +00001"""Generic output formatting.
2
3Formatter objects transform an abstract flow of formatting events into
4specific output events on writer objects. Formatters manage several stack
5structures to allow various properties of a writer object to be changed and
6restored; writers need not be able to handle relative changes nor any sort
7of ``change back'' operation. Specific writer properties which may be
8controlled via formatter objects are horizontal alignment, font, and left
9margin indentations. A mechanism is provided which supports providing
10arbitrary, non-exclusive style settings to a writer as well. Additional
11interfaces facilitate formatting events which are not reversible, such as
Tim Peters88869f92001-01-14 23:36:06 +000012paragraph separation.
Guido van Rossum4b8c6ea2000-02-04 15:39:30 +000013
14Writer objects encapsulate device interfaces. Abstract devices, such as
15file formats, are supported as well as physical devices. The provided
16implementations all work with abstract devices. The interface makes
17available mechanisms for setting the properties which formatter objects
Tim Peters88869f92001-01-14 23:36:06 +000018manage and inserting data into the output.
Guido van Rossum4b8c6ea2000-02-04 15:39:30 +000019"""
20
Guido van Rossuma0eab1d1995-08-07 20:07:36 +000021import sys
22
23
24AS_IS = None
25
Guido van Rossuma0eab1d1995-08-07 20:07:36 +000026
Guido van Rossum909507d1995-10-06 15:31:30 +000027class NullFormatter:
Raymond Hettingeraef22fb2002-05-29 16:18:42 +000028 """A formatter which does nothing.
29
30 If the writer parameter is omitted, a NullWriter instance is created.
31 No methods of the writer are called by NullFormatter instances.
32
33 Implementations should inherit from this class if implementing a writer
34 interface but don't need to inherit any implementation.
35
36 """
Guido van Rossum909507d1995-10-06 15:31:30 +000037
Guido van Rossumccd8b191996-10-07 21:29:49 +000038 def __init__(self, writer=None):
Raymond Hettinger094662a2002-06-01 01:29:16 +000039 if writer is None:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000040 writer = NullWriter()
41 self.writer = writer
Guido van Rossum909507d1995-10-06 15:31:30 +000042 def end_paragraph(self, blankline): pass
43 def add_line_break(self): pass
Fred Drakeca8cdc61996-10-08 21:57:47 +000044 def add_hor_rule(self, *args, **kw): pass
45 def add_label_data(self, format, counter, blankline=None): pass
Guido van Rossum909507d1995-10-06 15:31:30 +000046 def add_flowing_data(self, data): pass
47 def add_literal_data(self, data): pass
48 def flush_softspace(self): pass
Guido van Rossum9787bdaf1996-05-28 23:50:49 +000049 def push_alignment(self, align): pass
50 def pop_alignment(self): pass
Guido van Rossum909507d1995-10-06 15:31:30 +000051 def push_font(self, x): pass
52 def pop_font(self): pass
53 def push_margin(self, margin): pass
54 def pop_margin(self): pass
55 def set_spacing(self, spacing): pass
Guido van Rossum9787bdaf1996-05-28 23:50:49 +000056 def push_style(self, *styles): pass
57 def pop_style(self, n=1): pass
58 def assert_line_data(self, flag=1): pass
Guido van Rossum909507d1995-10-06 15:31:30 +000059
60
Guido van Rossuma0eab1d1995-08-07 20:07:36 +000061class AbstractFormatter:
Raymond Hettingeraef22fb2002-05-29 16:18:42 +000062 """The standard formatter.
63
64 This implementation has demonstrated wide applicability to many writers,
65 and may be used directly in most circumstances. It has been used to
66 implement a full-featured World Wide Web browser.
67
68 """
Guido van Rossuma0eab1d1995-08-07 20:07:36 +000069
Guido van Rossum8e449911996-08-26 16:19:23 +000070 # Space handling policy: blank spaces at the boundary between elements
71 # are handled by the outermost context. "Literal" data is not checked
72 # to determine context, so spaces in literal data are handled directly
73 # in all circumstances.
74
Guido van Rossuma0eab1d1995-08-07 20:07:36 +000075 def __init__(self, writer):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000076 self.writer = writer # Output device
77 self.align = None # Current alignment
78 self.align_stack = [] # Alignment stack
79 self.font_stack = [] # Font state
80 self.margin_stack = [] # Margin state
81 self.spacing = None # Vertical spacing state
82 self.style_stack = [] # Other state, e.g. color
83 self.nospace = 1 # Should leading space be suppressed
84 self.softspace = 0 # Should a space be inserted
85 self.para_end = 1 # Just ended a paragraph
86 self.parskip = 0 # Skipped space between paragraphs?
87 self.hard_break = 1 # Have a hard break
88 self.have_label = 0
Guido van Rossuma0eab1d1995-08-07 20:07:36 +000089
90 def end_paragraph(self, blankline):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000091 if not self.hard_break:
92 self.writer.send_line_break()
93 self.have_label = 0
94 if self.parskip < blankline and not self.have_label:
95 self.writer.send_paragraph(blankline - self.parskip)
96 self.parskip = blankline
97 self.have_label = 0
98 self.hard_break = self.nospace = self.para_end = 1
99 self.softspace = 0
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000100
101 def add_line_break(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000102 if not (self.hard_break or self.para_end):
103 self.writer.send_line_break()
104 self.have_label = self.parskip = 0
105 self.hard_break = self.nospace = 1
106 self.softspace = 0
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000107
Guido van Rossum9787bdaf1996-05-28 23:50:49 +0000108 def add_hor_rule(self, *args, **kw):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000109 if not self.hard_break:
110 self.writer.send_line_break()
Guido van Rossum68468eb2003-02-27 20:14:51 +0000111 self.writer.send_hor_rule(*args, **kw)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000112 self.hard_break = self.nospace = 1
113 self.have_label = self.para_end = self.softspace = self.parskip = 0
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000114
Guido van Rossum9787bdaf1996-05-28 23:50:49 +0000115 def add_label_data(self, format, counter, blankline = None):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000116 if self.have_label or not self.hard_break:
117 self.writer.send_line_break()
118 if not self.para_end:
119 self.writer.send_paragraph((blankline and 1) or 0)
Walter Dörwald65230a22002-06-03 15:58:32 +0000120 if isinstance(format, str):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000121 self.writer.send_label_data(self.format_counter(format, counter))
122 else:
123 self.writer.send_label_data(format)
124 self.nospace = self.have_label = self.hard_break = self.para_end = 1
125 self.softspace = self.parskip = 0
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000126
127 def format_counter(self, format, counter):
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000128 label = ''
129 for c in format:
Fred Drake6f6a14f2001-05-11 19:25:08 +0000130 if c == '1':
131 label = label + ('%d' % counter)
132 elif c in 'aA':
133 if counter > 0:
134 label = label + self.format_letter(c, counter)
135 elif c in 'iI':
136 if counter > 0:
137 label = label + self.format_roman(c, counter)
138 else:
Guido van Rossum9787bdaf1996-05-28 23:50:49 +0000139 label = label + c
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000140 return label
141
142 def format_letter(self, case, counter):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000143 label = ''
144 while counter > 0:
145 counter, x = divmod(counter-1, 26)
Fred Drake6f6a14f2001-05-11 19:25:08 +0000146 # This makes a strong assumption that lowercase letters
147 # and uppercase letters form two contiguous blocks, with
148 # letters in order!
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000149 s = chr(ord(case) + x)
150 label = s + label
151 return label
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000152
153 def format_roman(self, case, counter):
154 ones = ['i', 'x', 'c', 'm']
155 fives = ['v', 'l', 'd']
Guido van Rossum9787bdaf1996-05-28 23:50:49 +0000156 label, index = '', 0
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000157 # This will die of IndexError when counter is too big
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000158 while counter > 0:
159 counter, x = divmod(counter, 10)
160 if x == 9:
Guido van Rossum9787bdaf1996-05-28 23:50:49 +0000161 label = ones[index] + ones[index+1] + label
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000162 elif x == 4:
Guido van Rossum9787bdaf1996-05-28 23:50:49 +0000163 label = ones[index] + fives[index] + label
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000164 else:
165 if x >= 5:
166 s = fives[index]
167 x = x-5
168 else:
169 s = ''
170 s = s + ones[index]*x
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000171 label = s + label
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000172 index = index + 1
Guido van Rossum9787bdaf1996-05-28 23:50:49 +0000173 if case == 'I':
Eric S. Raymondb08b2d32001-02-09 11:10:16 +0000174 return label.upper()
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000175 return label
176
Walter Dörwald65230a22002-06-03 15:58:32 +0000177 def add_flowing_data(self, data):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000178 if not data: return
Walter Dörwald65230a22002-06-03 15:58:32 +0000179 prespace = data[:1].isspace()
180 postspace = data[-1:].isspace()
181 data = " ".join(data.split())
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000182 if self.nospace and not data:
183 return
184 elif prespace or self.softspace:
185 if not data:
186 if not self.nospace:
187 self.softspace = 1
188 self.parskip = 0
189 return
190 if not self.nospace:
191 data = ' ' + data
192 self.hard_break = self.nospace = self.para_end = \
193 self.parskip = self.have_label = 0
194 self.softspace = postspace
195 self.writer.send_flowing_data(data)
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000196
197 def add_literal_data(self, data):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000198 if not data: return
199 if self.softspace:
200 self.writer.send_flowing_data(" ")
201 self.hard_break = data[-1:] == '\n'
202 self.nospace = self.para_end = self.softspace = \
203 self.parskip = self.have_label = 0
204 self.writer.send_literal_data(data)
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000205
Guido van Rossumc7ae9201995-09-30 16:49:58 +0000206 def flush_softspace(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000207 if self.softspace:
208 self.hard_break = self.para_end = self.parskip = \
209 self.have_label = self.softspace = 0
210 self.nospace = 1
211 self.writer.send_flowing_data(' ')
Guido van Rossumc7ae9201995-09-30 16:49:58 +0000212
Guido van Rossum9787bdaf1996-05-28 23:50:49 +0000213 def push_alignment(self, align):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000214 if align and align != self.align:
215 self.writer.new_alignment(align)
216 self.align = align
217 self.align_stack.append(align)
218 else:
219 self.align_stack.append(self.align)
Guido van Rossum9787bdaf1996-05-28 23:50:49 +0000220
221 def pop_alignment(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000222 if self.align_stack:
223 del self.align_stack[-1]
224 if self.align_stack:
225 self.align = align = self.align_stack[-1]
226 self.writer.new_alignment(align)
227 else:
228 self.align = None
229 self.writer.new_alignment(None)
Guido van Rossum9787bdaf1996-05-28 23:50:49 +0000230
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000231 def push_font(self, font):
232 size, i, b, tt = font
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000233 if self.softspace:
234 self.hard_break = self.para_end = self.softspace = 0
235 self.nospace = 1
236 self.writer.send_flowing_data(' ')
237 if self.font_stack:
238 csize, ci, cb, ctt = self.font_stack[-1]
239 if size is AS_IS: size = csize
240 if i is AS_IS: i = ci
241 if b is AS_IS: b = cb
242 if tt is AS_IS: tt = ctt
243 font = (size, i, b, tt)
244 self.font_stack.append(font)
245 self.writer.new_font(font)
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000246
247 def pop_font(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000248 if self.font_stack:
249 del self.font_stack[-1]
250 if self.font_stack:
251 font = self.font_stack[-1]
252 else:
253 font = None
254 self.writer.new_font(font)
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000255
256 def push_margin(self, margin):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000257 self.margin_stack.append(margin)
Georg Brandl7cd67cc2008-09-09 19:31:25 +0000258 fstack = [m for m in self.margin_stack if m]
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000259 if not margin and fstack:
260 margin = fstack[-1]
261 self.writer.new_margin(margin, len(fstack))
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000262
263 def pop_margin(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000264 if self.margin_stack:
265 del self.margin_stack[-1]
Georg Brandl7cd67cc2008-09-09 19:31:25 +0000266 fstack = [m for m in self.margin_stack if m]
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000267 if fstack:
268 margin = fstack[-1]
269 else:
270 margin = None
271 self.writer.new_margin(margin, len(fstack))
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000272
273 def set_spacing(self, spacing):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000274 self.spacing = spacing
275 self.writer.new_spacing(spacing)
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000276
Guido van Rossum9787bdaf1996-05-28 23:50:49 +0000277 def push_style(self, *styles):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000278 if self.softspace:
279 self.hard_break = self.para_end = self.softspace = 0
280 self.nospace = 1
281 self.writer.send_flowing_data(' ')
282 for style in styles:
283 self.style_stack.append(style)
284 self.writer.new_styles(tuple(self.style_stack))
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000285
Guido van Rossum9787bdaf1996-05-28 23:50:49 +0000286 def pop_style(self, n=1):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000287 del self.style_stack[-n:]
288 self.writer.new_styles(tuple(self.style_stack))
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000289
Guido van Rossum9787bdaf1996-05-28 23:50:49 +0000290 def assert_line_data(self, flag=1):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000291 self.nospace = self.hard_break = not flag
292 self.para_end = self.parskip = self.have_label = 0
Guido van Rossum9787bdaf1996-05-28 23:50:49 +0000293
294
295class NullWriter:
Raymond Hettingeraef22fb2002-05-29 16:18:42 +0000296 """Minimal writer interface to use in testing & inheritance.
297
298 A writer which only provides the interface definition; no actions are
299 taken on any methods. This should be the base class for all writers
300 which do not need to inherit any implementation methods.
301
302 """
Guido van Rossum3672aa21996-05-29 00:02:30 +0000303 def __init__(self): pass
Fred Drake28231681996-12-31 20:50:51 +0000304 def flush(self): pass
Guido van Rossum9787bdaf1996-05-28 23:50:49 +0000305 def new_alignment(self, align): pass
306 def new_font(self, font): pass
307 def new_margin(self, margin, level): pass
308 def new_spacing(self, spacing): pass
309 def new_styles(self, styles): pass
310 def send_paragraph(self, blankline): pass
311 def send_line_break(self): pass
312 def send_hor_rule(self, *args, **kw): pass
313 def send_label_data(self, data): pass
314 def send_flowing_data(self, data): pass
315 def send_literal_data(self, data): pass
316
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000317
Guido van Rossum3672aa21996-05-29 00:02:30 +0000318class AbstractWriter(NullWriter):
Raymond Hettingeraef22fb2002-05-29 16:18:42 +0000319 """A writer which can be used in debugging formatters, but not much else.
320
321 Each method simply announces itself by printing its name and
322 arguments on standard output.
323
324 """
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000325
Guido van Rossum9787bdaf1996-05-28 23:50:49 +0000326 def new_alignment(self, align):
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000327 print("new_alignment(%r)" % (align,))
Guido van Rossum9787bdaf1996-05-28 23:50:49 +0000328
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000329 def new_font(self, font):
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000330 print("new_font(%r)" % (font,))
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000331
332 def new_margin(self, margin, level):
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000333 print("new_margin(%r, %d)" % (margin, level))
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000334
335 def new_spacing(self, spacing):
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000336 print("new_spacing(%r)" % (spacing,))
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000337
338 def new_styles(self, styles):
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000339 print("new_styles(%r)" % (styles,))
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000340
341 def send_paragraph(self, blankline):
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000342 print("send_paragraph(%r)" % (blankline,))
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000343
344 def send_line_break(self):
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000345 print("send_line_break()")
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000346
Guido van Rossum9787bdaf1996-05-28 23:50:49 +0000347 def send_hor_rule(self, *args, **kw):
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000348 print("send_hor_rule()")
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000349
350 def send_label_data(self, data):
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000351 print("send_label_data(%r)" % (data,))
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000352
353 def send_flowing_data(self, data):
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000354 print("send_flowing_data(%r)" % (data,))
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000355
356 def send_literal_data(self, data):
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000357 print("send_literal_data(%r)" % (data,))
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000358
359
Guido van Rossum3672aa21996-05-29 00:02:30 +0000360class DumbWriter(NullWriter):
Raymond Hettingeraef22fb2002-05-29 16:18:42 +0000361 """Simple writer class which writes output on the file object passed in
362 as the file parameter or, if file is omitted, on standard output. The
363 output is simply word-wrapped to the number of columns specified by
364 the maxcol parameter. This class is suitable for reflowing a sequence
365 of paragraphs.
366
367 """
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000368
369 def __init__(self, file=None, maxcol=72):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000370 self.file = file or sys.stdout
371 self.maxcol = maxcol
372 NullWriter.__init__(self)
373 self.reset()
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000374
375 def reset(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000376 self.col = 0
377 self.atbreak = 0
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000378
379 def send_paragraph(self, blankline):
Fred Drakef4bb6561999-01-12 18:13:27 +0000380 self.file.write('\n'*blankline)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000381 self.col = 0
382 self.atbreak = 0
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000383
384 def send_line_break(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000385 self.file.write('\n')
386 self.col = 0
387 self.atbreak = 0
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000388
Guido van Rossum9787bdaf1996-05-28 23:50:49 +0000389 def send_hor_rule(self, *args, **kw):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000390 self.file.write('\n')
391 self.file.write('-'*self.maxcol)
392 self.file.write('\n')
393 self.col = 0
394 self.atbreak = 0
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000395
396 def send_literal_data(self, data):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000397 self.file.write(data)
Eric S. Raymondb08b2d32001-02-09 11:10:16 +0000398 i = data.rfind('\n')
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000399 if i >= 0:
400 self.col = 0
401 data = data[i+1:]
Eric S. Raymondb08b2d32001-02-09 11:10:16 +0000402 data = data.expandtabs()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000403 self.col = self.col + len(data)
404 self.atbreak = 0
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000405
406 def send_flowing_data(self, data):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000407 if not data: return
Walter Dörwald65230a22002-06-03 15:58:32 +0000408 atbreak = self.atbreak or data[0].isspace()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000409 col = self.col
410 maxcol = self.maxcol
411 write = self.file.write
Eric S. Raymondb08b2d32001-02-09 11:10:16 +0000412 for word in data.split():
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000413 if atbreak:
414 if col + len(word) >= maxcol:
415 write('\n')
416 col = 0
417 else:
418 write(' ')
419 col = col + 1
420 write(word)
421 col = col + len(word)
422 atbreak = 1
423 self.col = col
Walter Dörwald65230a22002-06-03 15:58:32 +0000424 self.atbreak = data[-1].isspace()
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000425
426
427def test(file = None):
428 w = DumbWriter()
429 f = AbstractFormatter(w)
Raymond Hettinger094662a2002-06-01 01:29:16 +0000430 if file is not None:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000431 fp = open(file)
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000432 elif sys.argv[1:]:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000433 fp = open(sys.argv[1])
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000434 else:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000435 fp = sys.stdin
Georg Brandl86def6c2008-01-21 20:36:10 +0000436 for line in fp:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000437 if line == '\n':
438 f.end_paragraph(1)
439 else:
440 f.add_flowing_data(line)
Guido van Rossuma0eab1d1995-08-07 20:07:36 +0000441 f.end_paragraph(0)
442
443
444if __name__ == '__main__':
445 test()